s4-dsdb: Add documentation link for Tombstone Reanimation
[Samba.git] / source3 / modules / vfs_default.c
blob5a4a187e59997d4120e814244de68bd0adf0f74c
1 /*
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/>.
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.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/sys_rw.h"
37 #undef DBGC_CLASS
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
44 this possibility. */
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)
55 /* Disk operations */
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
58 uint64_t *dfree, uint64_t *dsize)
60 uint64_t result;
62 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
63 return result;
66 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
68 #ifdef HAVE_SYS_QUOTAS
69 int result;
71 START_PROFILE(syscall_get_quota);
72 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
73 END_PROFILE(syscall_get_quota);
74 return result;
75 #else
76 errno = ENOSYS;
77 return -1;
78 #endif
81 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
83 #ifdef HAVE_SYS_QUOTAS
84 int result;
86 START_PROFILE(syscall_set_quota);
87 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
88 END_PROFILE(syscall_set_quota);
89 return result;
90 #else
91 errno = ENOSYS;
92 return -1;
93 #endif
96 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
97 struct files_struct *fsp,
98 struct shadow_copy_data *shadow_copy_data,
99 bool labels)
101 errno = ENOSYS;
102 return -1; /* Not implemented. */
105 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
107 return sys_statvfs(path, statbuf);
110 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
111 enum timestamp_set_resolution *p_ts_res)
113 connection_struct *conn = handle->conn;
114 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
115 struct smb_filename *smb_fname_cpath = NULL;
116 struct vfs_statvfs_struct statbuf;
117 int ret;
119 ZERO_STRUCT(statbuf);
120 ret = sys_statvfs(conn->connectpath, &statbuf);
121 if (ret == 0) {
122 caps = statbuf.FsCapabilities;
125 *p_ts_res = TIMESTAMP_SET_SECONDS;
127 /* Work out what timestamp resolution we can
128 * use when setting a timestamp. */
130 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
131 NULL, NULL);
132 if (smb_fname_cpath == NULL) {
133 return caps;
136 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
137 if (ret == -1) {
138 TALLOC_FREE(smb_fname_cpath);
139 return caps;
142 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
145 /* If any of the normal UNIX directory timestamps
146 * have a non-zero tv_nsec component assume
147 * we might be able to set sub-second timestamps.
148 * See what filetime set primitives we have.
150 #if defined(HAVE_UTIMENSAT)
151 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
152 #elif defined(HAVE_UTIMES)
153 /* utimes allows msec timestamps to be set. */
154 *p_ts_res = TIMESTAMP_SET_MSEC;
155 #elif defined(HAVE_UTIME)
156 /* utime only allows sec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_SECONDS;
158 #endif
160 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
161 "resolution of %s "
162 "available on share %s, directory %s\n",
163 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
164 lp_servicename(talloc_tos(), conn->params->service),
165 conn->connectpath ));
167 TALLOC_FREE(smb_fname_cpath);
168 return caps;
171 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
172 struct dfs_GetDFSReferral *r)
174 struct junction_map *junction = NULL;
175 int consumedcnt = 0;
176 bool self_referral = false;
177 char *pathnamep = NULL;
178 char *local_dfs_path = NULL;
179 NTSTATUS status;
180 int i;
181 uint16_t max_referral_level = r->in.req.max_referral_level;
183 if (DEBUGLVL(10)) {
184 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
187 /* get the junction entry */
188 if (r->in.req.servername == NULL) {
189 return NT_STATUS_NOT_FOUND;
193 * Trim pathname sent by client so it begins with only one backslash.
194 * Two backslashes confuse some dfs clients
197 local_dfs_path = talloc_strdup(r, r->in.req.servername);
198 if (local_dfs_path == NULL) {
199 return NT_STATUS_NO_MEMORY;
201 pathnamep = local_dfs_path;
202 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
203 IS_DIRECTORY_SEP(pathnamep[1])) {
204 pathnamep++;
207 junction = talloc_zero(r, struct junction_map);
208 if (junction == NULL) {
209 return NT_STATUS_NO_MEMORY;
212 /* The following call can change cwd. */
213 status = get_referred_path(r, pathnamep,
214 !handle->conn->sconn->using_smb2,
215 junction, &consumedcnt, &self_referral);
216 if (!NT_STATUS_IS_OK(status)) {
217 vfs_ChDir(handle->conn, handle->conn->connectpath);
218 return status;
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
222 if (!self_referral) {
223 pathnamep[consumedcnt] = '\0';
225 if (DEBUGLVL(3)) {
226 dbgtext("Path %s to alternate path(s):",
227 pathnamep);
228 for (i=0; i < junction->referral_count; i++) {
229 dbgtext(" %s",
230 junction->referral_list[i].alternate_path);
232 dbgtext(".\n");
236 if (r->in.req.max_referral_level <= 2) {
237 max_referral_level = 2;
239 if (r->in.req.max_referral_level >= 3) {
240 max_referral_level = 3;
243 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
244 if (r->out.resp == NULL) {
245 return NT_STATUS_NO_MEMORY;
248 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
249 r->out.resp->nb_referrals = junction->referral_count;
251 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
252 if (self_referral) {
253 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
256 r->out.resp->referral_entries = talloc_zero_array(r,
257 struct dfs_referral_type,
258 r->out.resp->nb_referrals);
259 if (r->out.resp->referral_entries == NULL) {
260 return NT_STATUS_NO_MEMORY;
263 switch (max_referral_level) {
264 case 2:
265 for(i=0; i < junction->referral_count; i++) {
266 struct referral *ref = &junction->referral_list[i];
267 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
268 struct dfs_referral_type *t =
269 &r->out.resp->referral_entries[i];
270 struct dfs_referral_v2 *v2 = &t->referral.v2;
272 t->version = 2;
273 v2->size = VERSION2_REFERRAL_SIZE;
274 if (self_referral) {
275 v2->server_type = DFS_SERVER_ROOT;
276 } else {
277 v2->server_type = DFS_SERVER_NON_ROOT;
279 v2->entry_flags = 0;
280 v2->proximity = ref->proximity;
281 v2->ttl = ref->ttl;
282 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
283 if (v2->DFS_path == NULL) {
284 return NT_STATUS_NO_MEMORY;
286 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
287 if (v2->DFS_alt_path == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 v2->netw_address = talloc_strdup(mem_ctx,
291 ref->alternate_path);
292 if (v2->netw_address == NULL) {
293 return NT_STATUS_NO_MEMORY;
297 break;
298 case 3:
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v3 *v3 = &t->referral.v3;
305 struct dfs_normal_referral *r1 = &v3->referrals.r1;
307 t->version = 3;
308 v3->size = VERSION3_REFERRAL_SIZE;
309 if (self_referral) {
310 v3->server_type = DFS_SERVER_ROOT;
311 } else {
312 v3->server_type = DFS_SERVER_NON_ROOT;
314 v3->entry_flags = 0;
315 v3->ttl = ref->ttl;
316 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (r1->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (r1->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 r1->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (r1->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
330 break;
331 default:
332 DEBUG(0,("Invalid dfs referral version: %d\n",
333 max_referral_level));
334 return NT_STATUS_INVALID_LEVEL;
337 if (DEBUGLVL(10)) {
338 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
341 return NT_STATUS_OK;
344 /* Directory operations */
346 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
348 DIR *result;
350 START_PROFILE(syscall_opendir);
351 result = opendir(fname);
352 END_PROFILE(syscall_opendir);
353 return result;
356 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
357 files_struct *fsp,
358 const char *mask,
359 uint32 attr)
361 DIR *result;
363 START_PROFILE(syscall_fdopendir);
364 result = sys_fdopendir(fsp->fh->fd);
365 END_PROFILE(syscall_fdopendir);
366 return result;
370 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
371 DIR *dirp,
372 SMB_STRUCT_STAT *sbuf)
374 struct dirent *result;
376 START_PROFILE(syscall_readdir);
377 result = readdir(dirp);
378 END_PROFILE(syscall_readdir);
379 if (sbuf) {
380 /* Default Posix readdir() does not give us stat info.
381 * Set to invalid to indicate we didn't return this info. */
382 SET_STAT_INVALID(*sbuf);
383 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
384 if (result != NULL) {
385 /* See if we can efficiently return this. */
386 struct stat st;
387 int flags = (lp_posix_pathnames() ?
388 AT_SYMLINK_NOFOLLOW : 0);
389 int ret = fstatat(dirfd(dirp),
390 result->d_name,
391 &st,
392 flags);
393 if (ret == 0) {
394 init_stat_ex_from_stat(sbuf,
395 &st,
396 lp_fake_directory_create_times(
397 SNUM(handle->conn)));
400 #endif
402 return result;
405 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
406 const struct smb_filename *fname,
407 TALLOC_CTX *mem_ctx,
408 struct readdir_attr_data **attr_data)
410 return NT_STATUS_NOT_SUPPORTED;
413 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
415 START_PROFILE(syscall_seekdir);
416 seekdir(dirp, offset);
417 END_PROFILE(syscall_seekdir);
420 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
422 long result;
423 START_PROFILE(syscall_telldir);
424 result = telldir(dirp);
425 END_PROFILE(syscall_telldir);
426 return result;
429 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
431 START_PROFILE(syscall_rewinddir);
432 rewinddir(dirp);
433 END_PROFILE(syscall_rewinddir);
436 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
438 int result;
439 bool has_dacl = False;
440 char *parent = NULL;
442 START_PROFILE(syscall_mkdir);
444 if (lp_inherit_acls(SNUM(handle->conn))
445 && parent_dirname(talloc_tos(), path, &parent, NULL)
446 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
447 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
449 TALLOC_FREE(parent);
451 result = mkdir(path, mode);
453 if (result == 0 && !has_dacl) {
455 * We need to do this as the default behavior of POSIX ACLs
456 * is to set the mask to be the requested group permission
457 * bits, not the group permission bits to be the requested
458 * group permission bits. This is not what we want, as it will
459 * mess up any inherited ACL bits that were set. JRA.
461 int saved_errno = errno; /* We may get ENOSYS */
462 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
463 errno = saved_errno;
466 END_PROFILE(syscall_mkdir);
467 return result;
470 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
472 int result;
474 START_PROFILE(syscall_rmdir);
475 result = rmdir(path);
476 END_PROFILE(syscall_rmdir);
477 return result;
480 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
482 int result;
484 START_PROFILE(syscall_closedir);
485 result = closedir(dirp);
486 END_PROFILE(syscall_closedir);
487 return result;
490 static void vfswrap_init_search_op(vfs_handle_struct *handle,
491 DIR *dirp)
493 /* Default behavior is a NOOP */
496 /* File operations */
498 static int vfswrap_open(vfs_handle_struct *handle,
499 struct smb_filename *smb_fname,
500 files_struct *fsp, int flags, mode_t mode)
502 int result = -1;
504 START_PROFILE(syscall_open);
506 if (smb_fname->stream_name) {
507 errno = ENOENT;
508 goto out;
511 result = open(smb_fname->base_name, flags, mode);
512 out:
513 END_PROFILE(syscall_open);
514 return result;
517 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
518 struct smb_request *req,
519 uint16_t root_dir_fid,
520 struct smb_filename *smb_fname,
521 uint32_t access_mask,
522 uint32_t share_access,
523 uint32_t create_disposition,
524 uint32_t create_options,
525 uint32_t file_attributes,
526 uint32_t oplock_request,
527 struct smb2_lease *lease,
528 uint64_t allocation_size,
529 uint32_t private_flags,
530 struct security_descriptor *sd,
531 struct ea_list *ea_list,
532 files_struct **result,
533 int *pinfo,
534 const struct smb2_create_blobs *in_context_blobs,
535 struct smb2_create_blobs *out_context_blobs)
537 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
538 access_mask, share_access,
539 create_disposition, create_options,
540 file_attributes, oplock_request, lease,
541 allocation_size, private_flags,
542 sd, ea_list, result,
543 pinfo, in_context_blobs, out_context_blobs);
546 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
548 int result;
550 START_PROFILE(syscall_close);
551 result = fd_close_posix(fsp);
552 END_PROFILE(syscall_close);
553 return result;
556 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
558 ssize_t result;
560 START_PROFILE_BYTES(syscall_read, n);
561 result = sys_read(fsp->fh->fd, data, n);
562 END_PROFILE_BYTES(syscall_read);
563 return result;
566 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
567 size_t n, off_t offset)
569 ssize_t result;
571 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
572 START_PROFILE_BYTES(syscall_pread, n);
573 result = sys_pread(fsp->fh->fd, data, n, offset);
574 END_PROFILE_BYTES(syscall_pread);
576 if (result == -1 && errno == ESPIPE) {
577 /* Maintain the fiction that pipes can be seeked (sought?) on. */
578 result = SMB_VFS_READ(fsp, data, n);
579 fsp->fh->pos = 0;
582 #else /* HAVE_PREAD */
583 off_t curr;
584 int lerrno;
586 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
587 if (curr == -1 && errno == ESPIPE) {
588 /* Maintain the fiction that pipes can be seeked (sought?) on. */
589 result = SMB_VFS_READ(fsp, data, n);
590 fsp->fh->pos = 0;
591 return result;
594 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
595 return -1;
598 errno = 0;
599 result = SMB_VFS_READ(fsp, data, n);
600 lerrno = errno;
602 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
603 errno = lerrno;
605 #endif /* HAVE_PREAD */
607 return result;
610 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
612 ssize_t result;
614 START_PROFILE_BYTES(syscall_write, n);
615 result = sys_write(fsp->fh->fd, data, n);
616 END_PROFILE_BYTES(syscall_write);
617 return result;
620 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
621 size_t n, off_t offset)
623 ssize_t result;
625 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
626 START_PROFILE_BYTES(syscall_pwrite, n);
627 result = sys_pwrite(fsp->fh->fd, data, n, offset);
628 END_PROFILE_BYTES(syscall_pwrite);
630 if (result == -1 && errno == ESPIPE) {
631 /* Maintain the fiction that pipes can be sought on. */
632 result = SMB_VFS_WRITE(fsp, data, n);
635 #else /* HAVE_PWRITE */
636 off_t curr;
637 int lerrno;
639 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
640 if (curr == -1) {
641 return -1;
644 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
645 return -1;
648 result = SMB_VFS_WRITE(fsp, data, n);
649 lerrno = errno;
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
652 errno = lerrno;
654 #endif /* HAVE_PWRITE */
656 return result;
659 static void vfswrap_asys_finished(struct tevent_context *ev,
660 struct tevent_fd *fde,
661 uint16_t flags, void *p);
663 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
665 int ret;
666 int fd;
668 if (conn->asys_ctx != NULL) {
669 return true;
671 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
672 if (ret != 0) {
673 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
674 return false;
677 fd = asys_signalfd(conn->asys_ctx);
679 set_blocking(fd, false);
681 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
682 TEVENT_FD_READ,
683 vfswrap_asys_finished,
684 conn->asys_ctx);
685 if (conn->asys_fde == NULL) {
686 DEBUG(1, ("tevent_add_fd failed\n"));
687 asys_context_destroy(conn->asys_ctx);
688 conn->asys_ctx = NULL;
689 return false;
691 return true;
694 struct vfswrap_asys_state {
695 struct asys_context *asys_ctx;
696 struct tevent_req *req;
697 ssize_t ret;
698 int err;
699 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
700 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
703 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
705 asys_cancel(s->asys_ctx, s->req);
706 return 0;
709 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
710 TALLOC_CTX *mem_ctx,
711 struct tevent_context *ev,
712 struct files_struct *fsp,
713 void *data,
714 size_t n, off_t offset)
716 struct tevent_req *req;
717 struct vfswrap_asys_state *state;
718 int ret;
720 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
721 if (req == NULL) {
722 return NULL;
724 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
725 tevent_req_oom(req);
726 return tevent_req_post(req, ev);
728 state->asys_ctx = handle->conn->sconn->asys_ctx;
729 state->req = req;
731 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
732 state->profile_bytes, n);
733 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
734 if (ret != 0) {
735 tevent_req_error(req, ret);
736 return tevent_req_post(req, ev);
738 talloc_set_destructor(state, vfswrap_asys_state_destructor);
740 return req;
743 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
744 TALLOC_CTX *mem_ctx,
745 struct tevent_context *ev,
746 struct files_struct *fsp,
747 const void *data,
748 size_t n, off_t offset)
750 struct tevent_req *req;
751 struct vfswrap_asys_state *state;
752 int ret;
754 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
755 if (req == NULL) {
756 return NULL;
758 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
759 tevent_req_oom(req);
760 return tevent_req_post(req, ev);
762 state->asys_ctx = handle->conn->sconn->asys_ctx;
763 state->req = req;
765 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
766 state->profile_bytes, n);
767 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
768 if (ret != 0) {
769 tevent_req_error(req, ret);
770 return tevent_req_post(req, ev);
772 talloc_set_destructor(state, vfswrap_asys_state_destructor);
774 return req;
777 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
778 TALLOC_CTX *mem_ctx,
779 struct tevent_context *ev,
780 struct files_struct *fsp)
782 struct tevent_req *req;
783 struct vfswrap_asys_state *state;
784 int ret;
786 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
787 if (req == NULL) {
788 return NULL;
790 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
791 tevent_req_oom(req);
792 return tevent_req_post(req, ev);
794 state->asys_ctx = handle->conn->sconn->asys_ctx;
795 state->req = req;
797 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
798 state->profile_basic);
799 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
800 if (ret != 0) {
801 tevent_req_error(req, ret);
802 return tevent_req_post(req, ev);
804 talloc_set_destructor(state, vfswrap_asys_state_destructor);
806 return req;
809 static void vfswrap_asys_finished(struct tevent_context *ev,
810 struct tevent_fd *fde,
811 uint16_t flags, void *p)
813 struct asys_context *asys_ctx = (struct asys_context *)p;
814 struct asys_result results[outstanding_aio_calls];
815 int i, ret;
817 if ((flags & TEVENT_FD_READ) == 0) {
818 return;
821 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
822 if (ret < 0) {
823 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
824 return;
827 for (i=0; i<ret; i++) {
828 struct asys_result *result = &results[i];
829 struct tevent_req *req;
830 struct vfswrap_asys_state *state;
832 if ((result->ret == -1) && (result->err == ECANCELED)) {
833 continue;
836 req = talloc_get_type_abort(result->private_data,
837 struct tevent_req);
838 state = tevent_req_data(req, struct vfswrap_asys_state);
840 talloc_set_destructor(state, NULL);
842 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
843 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
844 state->ret = result->ret;
845 state->err = result->err;
846 tevent_req_defer_callback(req, ev);
847 tevent_req_done(req);
851 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
853 struct vfswrap_asys_state *state = tevent_req_data(
854 req, struct vfswrap_asys_state);
856 if (tevent_req_is_unix_error(req, err)) {
857 return -1;
859 *err = state->err;
860 return state->ret;
863 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
865 struct vfswrap_asys_state *state = tevent_req_data(
866 req, struct vfswrap_asys_state);
868 if (tevent_req_is_unix_error(req, err)) {
869 return -1;
871 *err = state->err;
872 return state->ret;
875 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
877 off_t result = 0;
879 START_PROFILE(syscall_lseek);
881 /* Cope with 'stat' file opens. */
882 if (fsp->fh->fd != -1)
883 result = lseek(fsp->fh->fd, offset, whence);
886 * We want to maintain the fiction that we can seek
887 * on a fifo for file system purposes. This allows
888 * people to set up UNIX fifo's that feed data to Windows
889 * applications. JRA.
892 if((result == -1) && (errno == ESPIPE)) {
893 result = 0;
894 errno = 0;
897 END_PROFILE(syscall_lseek);
898 return result;
901 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
902 off_t offset, size_t n)
904 ssize_t result;
906 START_PROFILE_BYTES(syscall_sendfile, n);
907 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
908 END_PROFILE_BYTES(syscall_sendfile);
909 return result;
912 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
913 int fromfd,
914 files_struct *tofsp,
915 off_t offset,
916 size_t n)
918 ssize_t result;
920 START_PROFILE_BYTES(syscall_recvfile, n);
921 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
922 END_PROFILE_BYTES(syscall_recvfile);
923 return result;
926 static int vfswrap_rename(vfs_handle_struct *handle,
927 const struct smb_filename *smb_fname_src,
928 const struct smb_filename *smb_fname_dst)
930 int result = -1;
932 START_PROFILE(syscall_rename);
934 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
935 errno = ENOENT;
936 goto out;
939 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
941 out:
942 END_PROFILE(syscall_rename);
943 return result;
946 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
948 #ifdef HAVE_FSYNC
949 int result;
951 START_PROFILE(syscall_fsync);
952 result = fsync(fsp->fh->fd);
953 END_PROFILE(syscall_fsync);
954 return result;
955 #else
956 return 0;
957 #endif
960 static int vfswrap_stat(vfs_handle_struct *handle,
961 struct smb_filename *smb_fname)
963 int result = -1;
965 START_PROFILE(syscall_stat);
967 if (smb_fname->stream_name) {
968 errno = ENOENT;
969 goto out;
972 result = sys_stat(smb_fname->base_name, &smb_fname->st,
973 lp_fake_directory_create_times(SNUM(handle->conn)));
974 out:
975 END_PROFILE(syscall_stat);
976 return result;
979 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
981 int result;
983 START_PROFILE(syscall_fstat);
984 result = sys_fstat(fsp->fh->fd,
985 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
986 END_PROFILE(syscall_fstat);
987 return result;
990 static int vfswrap_lstat(vfs_handle_struct *handle,
991 struct smb_filename *smb_fname)
993 int result = -1;
995 START_PROFILE(syscall_lstat);
997 if (smb_fname->stream_name) {
998 errno = ENOENT;
999 goto out;
1002 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1003 lp_fake_directory_create_times(SNUM(handle->conn)));
1004 out:
1005 END_PROFILE(syscall_lstat);
1006 return result;
1009 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1010 const char *name,
1011 enum vfs_translate_direction direction,
1012 TALLOC_CTX *mem_ctx,
1013 char **mapped_name)
1015 return NT_STATUS_NONE_MAPPED;
1019 * Implement the default fsctl operation.
1021 static bool vfswrap_logged_ioctl_message = false;
1023 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1024 struct files_struct *fsp,
1025 TALLOC_CTX *ctx,
1026 uint32_t function,
1027 uint16_t req_flags, /* Needed for UNICODE ... */
1028 const uint8_t *_in_data,
1029 uint32_t in_len,
1030 uint8_t **_out_data,
1031 uint32_t max_out_len,
1032 uint32_t *out_len)
1034 const char *in_data = (const char *)_in_data;
1035 char **out_data = (char **)_out_data;
1036 NTSTATUS status;
1038 switch (function) {
1039 case FSCTL_SET_SPARSE:
1041 bool set_sparse = true;
1043 if (in_len >= 1 && in_data[0] == 0) {
1044 set_sparse = false;
1047 status = file_set_sparse(handle->conn, fsp, set_sparse);
1049 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1050 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1051 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1052 nt_errstr(status)));
1054 return status;
1057 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1059 unsigned char objid[16];
1060 char *return_data = NULL;
1062 /* This should return the object-id on this file.
1063 * I think I'll make this be the inode+dev. JRA.
1066 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1067 fsp_fnum_dbg(fsp)));
1069 *out_len = MIN(max_out_len, 64);
1071 /* Hmmm, will this cause problems if less data asked for? */
1072 return_data = talloc_array(ctx, char, 64);
1073 if (return_data == NULL) {
1074 return NT_STATUS_NO_MEMORY;
1077 /* For backwards compatibility only store the dev/inode. */
1078 push_file_id_16(return_data, &fsp->file_id);
1079 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1080 push_file_id_16(return_data+32, &fsp->file_id);
1081 memset(return_data+48, 0, 16);
1082 *out_data = return_data;
1083 return NT_STATUS_OK;
1086 case FSCTL_GET_REPARSE_POINT:
1088 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1089 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1090 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1091 return NT_STATUS_NOT_A_REPARSE_POINT;
1094 case FSCTL_SET_REPARSE_POINT:
1096 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1097 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1098 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1099 return NT_STATUS_NOT_A_REPARSE_POINT;
1102 case FSCTL_GET_SHADOW_COPY_DATA:
1105 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1106 * and return their volume names. If max_data_count is 16, then it is just
1107 * asking for the number of volumes and length of the combined names.
1109 * pdata is the data allocated by our caller, but that uses
1110 * total_data_count (which is 0 in our case) rather than max_data_count.
1111 * Allocate the correct amount and return the pointer to let
1112 * it be deallocated when we return.
1114 struct shadow_copy_data *shadow_data = NULL;
1115 bool labels = False;
1116 uint32 labels_data_count = 0;
1117 uint32 i;
1118 char *cur_pdata = NULL;
1120 if (max_out_len < 16) {
1121 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1122 max_out_len));
1123 return NT_STATUS_INVALID_PARAMETER;
1126 if (max_out_len > 16) {
1127 labels = True;
1130 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1131 if (shadow_data == NULL) {
1132 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1133 return NT_STATUS_NO_MEMORY;
1137 * Call the VFS routine to actually do the work.
1139 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1140 int log_lev = 0;
1141 if (errno == 0) {
1142 /* broken module didn't set errno on error */
1143 status = NT_STATUS_UNSUCCESSFUL;
1144 } else {
1145 status = map_nt_error_from_unix(errno);
1146 if (NT_STATUS_EQUAL(status,
1147 NT_STATUS_NOT_SUPPORTED)) {
1148 log_lev = 5;
1151 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1152 "connectpath %s, failed - %s.\n",
1153 fsp->conn->connectpath,
1154 nt_errstr(status)));
1155 TALLOC_FREE(shadow_data);
1156 return status;
1159 labels_data_count = (shadow_data->num_volumes * 2 *
1160 sizeof(SHADOW_COPY_LABEL)) + 2;
1162 if (!labels) {
1163 *out_len = 16;
1164 } else {
1165 *out_len = 12 + labels_data_count;
1168 if (max_out_len < *out_len) {
1169 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1170 max_out_len, *out_len));
1171 TALLOC_FREE(shadow_data);
1172 return NT_STATUS_BUFFER_TOO_SMALL;
1175 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1176 if (cur_pdata == NULL) {
1177 TALLOC_FREE(shadow_data);
1178 return NT_STATUS_NO_MEMORY;
1181 *out_data = cur_pdata;
1183 /* num_volumes 4 bytes */
1184 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1186 if (labels) {
1187 /* num_labels 4 bytes */
1188 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1191 /* needed_data_count 4 bytes */
1192 SIVAL(cur_pdata, 8, labels_data_count);
1194 cur_pdata += 12;
1196 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1197 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1198 if (labels && shadow_data->labels) {
1199 for (i=0; i<shadow_data->num_volumes; i++) {
1200 size_t len = 0;
1201 status = srvstr_push(cur_pdata, req_flags,
1202 cur_pdata, shadow_data->labels[i],
1203 2 * sizeof(SHADOW_COPY_LABEL),
1204 STR_UNICODE|STR_TERMINATE, &len);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 TALLOC_FREE(*out_data);
1207 TALLOC_FREE(shadow_data);
1208 return status;
1210 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1211 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1215 TALLOC_FREE(shadow_data);
1217 return NT_STATUS_OK;
1220 case FSCTL_FIND_FILES_BY_SID:
1222 /* pretend this succeeded -
1224 * we have to send back a list with all files owned by this SID
1226 * but I have to check that --metze
1228 struct dom_sid sid;
1229 uid_t uid;
1230 size_t sid_len;
1232 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1233 fsp_fnum_dbg(fsp)));
1235 if (in_len < 8) {
1236 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1237 return NT_STATUS_INVALID_PARAMETER;
1240 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1242 /* unknown 4 bytes: this is not the length of the sid :-( */
1243 /*unknown = IVAL(pdata,0);*/
1245 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1246 return NT_STATUS_INVALID_PARAMETER;
1248 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1250 if (!sid_to_uid(&sid, &uid)) {
1251 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1252 sid_string_dbg(&sid),
1253 (unsigned long)sid_len));
1254 uid = (-1);
1257 /* we can take a look at the find source :-)
1259 * find ./ -uid $uid -name '*' is what we need here
1262 * and send 4bytes len and then NULL terminated unicode strings
1263 * for each file
1265 * but I don't know how to deal with the paged results
1266 * (maybe we can hang the result anywhere in the fsp struct)
1268 * but I don't know how to deal with the paged results
1269 * (maybe we can hang the result anywhere in the fsp struct)
1271 * we don't send all files at once
1272 * and at the next we should *not* start from the beginning,
1273 * so we have to cache the result
1275 * --metze
1278 /* this works for now... */
1279 return NT_STATUS_OK;
1282 case FSCTL_QUERY_ALLOCATED_RANGES:
1284 /* FIXME: This is just a dummy reply, telling that all of the
1285 * file is allocated. MKS cp needs that.
1286 * Adding the real allocated ranges via FIEMAP on Linux
1287 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1288 * this FSCTL correct for sparse files.
1290 uint64_t offset, length;
1291 char *out_data_tmp = NULL;
1293 if (in_len != 16) {
1294 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1295 in_len));
1296 return NT_STATUS_INVALID_PARAMETER;
1299 if (max_out_len < 16) {
1300 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1301 max_out_len));
1302 return NT_STATUS_INVALID_PARAMETER;
1305 offset = BVAL(in_data,0);
1306 length = BVAL(in_data,8);
1308 if (offset + length < offset) {
1309 /* No 64-bit integer wrap. */
1310 return NT_STATUS_INVALID_PARAMETER;
1313 /* Shouldn't this be SMB_VFS_STAT ... ? */
1314 status = vfs_stat_fsp(fsp);
1315 if (!NT_STATUS_IS_OK(status)) {
1316 return status;
1319 *out_len = 16;
1320 out_data_tmp = talloc_array(ctx, char, *out_len);
1321 if (out_data_tmp == NULL) {
1322 DEBUG(10, ("unable to allocate memory for response\n"));
1323 return NT_STATUS_NO_MEMORY;
1326 if (offset > fsp->fsp_name->st.st_ex_size ||
1327 fsp->fsp_name->st.st_ex_size == 0 ||
1328 length == 0) {
1329 memset(out_data_tmp, 0, *out_len);
1330 } else {
1331 uint64_t end = offset + length;
1332 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1333 SBVAL(out_data_tmp, 0, 0);
1334 SBVAL(out_data_tmp, 8, end);
1337 *out_data = out_data_tmp;
1339 return NT_STATUS_OK;
1342 case FSCTL_IS_VOLUME_DIRTY:
1344 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1345 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1347 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1348 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1350 return NT_STATUS_INVALID_PARAMETER;
1353 default:
1355 * Only print once ... unfortunately there could be lots of
1356 * different FSCTLs that are called.
1358 if (!vfswrap_logged_ioctl_message) {
1359 vfswrap_logged_ioctl_message = true;
1360 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1361 __func__, function));
1365 return NT_STATUS_NOT_SUPPORTED;
1368 struct vfs_cc_state {
1369 off_t copied;
1370 uint8_t buf[65536];
1373 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1374 TALLOC_CTX *mem_ctx,
1375 struct tevent_context *ev,
1376 struct files_struct *src_fsp,
1377 off_t src_off,
1378 struct files_struct *dest_fsp,
1379 off_t dest_off,
1380 off_t num)
1382 struct tevent_req *req;
1383 struct vfs_cc_state *vfs_cc_state;
1384 NTSTATUS status;
1386 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1387 (unsigned long)num));
1389 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1390 if (req == NULL) {
1391 return NULL;
1394 status = vfs_stat_fsp(src_fsp);
1395 if (tevent_req_nterror(req, status)) {
1396 return tevent_req_post(req, ev);
1399 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1401 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1402 * If the SourceOffset or SourceOffset + Length extends beyond
1403 * the end of file, the server SHOULD<240> treat this as a
1404 * STATUS_END_OF_FILE error.
1405 * ...
1406 * <240> Section 3.3.5.15.6: Windows servers will return
1407 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1409 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1410 return tevent_req_post(req, ev);
1413 /* could use 2.6.33+ sendfile here to do this in kernel */
1414 while (vfs_cc_state->copied < num) {
1415 ssize_t ret;
1416 struct lock_struct lck;
1417 int saved_errno;
1419 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1420 num - vfs_cc_state->copied);
1422 if (src_fsp->op == NULL) {
1423 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1424 return tevent_req_post(req, ev);
1426 init_strict_lock_struct(src_fsp,
1427 src_fsp->op->global->open_persistent_id,
1428 src_off,
1429 this_num,
1430 READ_LOCK,
1431 &lck);
1433 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1434 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1435 return tevent_req_post(req, ev);
1438 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1439 this_num, src_off);
1440 if (ret == -1) {
1441 saved_errno = errno;
1444 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1446 if (ret == -1) {
1447 errno = saved_errno;
1448 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1449 return tevent_req_post(req, ev);
1451 if (ret != this_num) {
1452 /* zero tolerance for short reads */
1453 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1454 return tevent_req_post(req, ev);
1457 src_off += ret;
1459 if (dest_fsp->op == NULL) {
1460 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1461 return tevent_req_post(req, ev);
1464 init_strict_lock_struct(dest_fsp,
1465 dest_fsp->op->global->open_persistent_id,
1466 dest_off,
1467 this_num,
1468 WRITE_LOCK,
1469 &lck);
1471 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1472 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1473 return tevent_req_post(req, ev);
1476 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1477 this_num, dest_off);
1478 if (ret == -1) {
1479 saved_errno = errno;
1482 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1484 if (ret == -1) {
1485 errno = saved_errno;
1486 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1487 return tevent_req_post(req, ev);
1489 if (ret != this_num) {
1490 /* zero tolerance for short writes */
1491 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1492 return tevent_req_post(req, ev);
1494 dest_off += ret;
1496 vfs_cc_state->copied += this_num;
1499 tevent_req_done(req);
1500 return tevent_req_post(req, ev);
1503 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1504 struct tevent_req *req,
1505 off_t *copied)
1507 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1508 struct vfs_cc_state);
1509 NTSTATUS status;
1511 if (tevent_req_is_nterror(req, &status)) {
1512 DEBUG(2, ("server side copy chunk failed: %s\n",
1513 nt_errstr(status)));
1514 *copied = 0;
1515 tevent_req_received(req);
1516 return status;
1519 *copied = vfs_cc_state->copied;
1520 DEBUG(10, ("server side copy chunk copied %lu\n",
1521 (unsigned long)*copied));
1522 tevent_req_received(req);
1524 return NT_STATUS_OK;
1527 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1528 TALLOC_CTX *mem_ctx,
1529 struct files_struct *fsp,
1530 struct smb_filename *smb_fname,
1531 uint16_t *_compression_fmt)
1533 return NT_STATUS_INVALID_DEVICE_REQUEST;
1536 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1537 TALLOC_CTX *mem_ctx,
1538 struct files_struct *fsp,
1539 uint16_t compression_fmt)
1541 return NT_STATUS_INVALID_DEVICE_REQUEST;
1544 /********************************************************************
1545 Given a stat buffer return the allocated size on disk, taking into
1546 account sparse files.
1547 ********************************************************************/
1548 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1549 struct files_struct *fsp,
1550 const SMB_STRUCT_STAT *sbuf)
1552 uint64_t result;
1554 START_PROFILE(syscall_get_alloc_size);
1556 if(S_ISDIR(sbuf->st_ex_mode)) {
1557 result = 0;
1558 goto out;
1561 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1562 /* The type of st_blocksize is blkcnt_t which *MUST* be
1563 signed (according to POSIX) and can be less than 64-bits.
1564 Ensure when we're converting to 64 bits wide we don't
1565 sign extend. */
1566 #if defined(SIZEOF_BLKCNT_T_8)
1567 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1568 #elif defined(SIZEOF_BLKCNT_T_4)
1570 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1571 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1573 #else
1574 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1575 #endif
1576 if (result == 0) {
1578 * Some file systems do not allocate a block for very
1579 * small files. But for non-empty file should report a
1580 * positive size.
1583 uint64_t filesize = get_file_size_stat(sbuf);
1584 if (filesize > 0) {
1585 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1588 #else
1589 result = get_file_size_stat(sbuf);
1590 #endif
1592 if (fsp && fsp->initial_allocation_size)
1593 result = MAX(result,fsp->initial_allocation_size);
1595 result = smb_roundup(handle->conn, result);
1597 out:
1598 END_PROFILE(syscall_get_alloc_size);
1599 return result;
1602 static int vfswrap_unlink(vfs_handle_struct *handle,
1603 const struct smb_filename *smb_fname)
1605 int result = -1;
1607 START_PROFILE(syscall_unlink);
1609 if (smb_fname->stream_name) {
1610 errno = ENOENT;
1611 goto out;
1613 result = unlink(smb_fname->base_name);
1615 out:
1616 END_PROFILE(syscall_unlink);
1617 return result;
1620 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1622 int result;
1624 START_PROFILE(syscall_chmod);
1627 * We need to do this due to the fact that the default POSIX ACL
1628 * chmod modifies the ACL *mask* for the group owner, not the
1629 * group owner bits directly. JRA.
1634 int saved_errno = errno; /* We might get ENOSYS */
1635 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1636 END_PROFILE(syscall_chmod);
1637 return result;
1639 /* Error - return the old errno. */
1640 errno = saved_errno;
1643 result = chmod(path, mode);
1644 END_PROFILE(syscall_chmod);
1645 return result;
1648 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1650 int result;
1652 START_PROFILE(syscall_fchmod);
1655 * We need to do this due to the fact that the default POSIX ACL
1656 * chmod modifies the ACL *mask* for the group owner, not the
1657 * group owner bits directly. JRA.
1661 int saved_errno = errno; /* We might get ENOSYS */
1662 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1663 END_PROFILE(syscall_fchmod);
1664 return result;
1666 /* Error - return the old errno. */
1667 errno = saved_errno;
1670 #if defined(HAVE_FCHMOD)
1671 result = fchmod(fsp->fh->fd, mode);
1672 #else
1673 result = -1;
1674 errno = ENOSYS;
1675 #endif
1677 END_PROFILE(syscall_fchmod);
1678 return result;
1681 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1683 int result;
1685 START_PROFILE(syscall_chown);
1686 result = chown(path, uid, gid);
1687 END_PROFILE(syscall_chown);
1688 return result;
1691 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1693 #ifdef HAVE_FCHOWN
1694 int result;
1696 START_PROFILE(syscall_fchown);
1697 result = fchown(fsp->fh->fd, uid, gid);
1698 END_PROFILE(syscall_fchown);
1699 return result;
1700 #else
1701 errno = ENOSYS;
1702 return -1;
1703 #endif
1706 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1708 int result;
1710 START_PROFILE(syscall_lchown);
1711 result = lchown(path, uid, gid);
1712 END_PROFILE(syscall_lchown);
1713 return result;
1716 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1718 int result;
1720 START_PROFILE(syscall_chdir);
1721 result = chdir(path);
1722 END_PROFILE(syscall_chdir);
1723 return result;
1726 static char *vfswrap_getwd(vfs_handle_struct *handle)
1728 char *result;
1730 START_PROFILE(syscall_getwd);
1731 result = sys_getwd();
1732 END_PROFILE(syscall_getwd);
1733 return result;
1736 /*********************************************************************
1737 nsec timestamp resolution call. Convert down to whatever the underlying
1738 system will support.
1739 **********************************************************************/
1741 static int vfswrap_ntimes(vfs_handle_struct *handle,
1742 const struct smb_filename *smb_fname,
1743 struct smb_file_time *ft)
1745 int result = -1;
1747 START_PROFILE(syscall_ntimes);
1749 if (smb_fname->stream_name) {
1750 errno = ENOENT;
1751 goto out;
1754 if (ft != NULL) {
1755 if (null_timespec(ft->atime)) {
1756 ft->atime= smb_fname->st.st_ex_atime;
1759 if (null_timespec(ft->mtime)) {
1760 ft->mtime = smb_fname->st.st_ex_mtime;
1763 if (!null_timespec(ft->create_time)) {
1764 set_create_timespec_ea(handle->conn,
1765 smb_fname,
1766 ft->create_time);
1769 if ((timespec_compare(&ft->atime,
1770 &smb_fname->st.st_ex_atime) == 0) &&
1771 (timespec_compare(&ft->mtime,
1772 &smb_fname->st.st_ex_mtime) == 0)) {
1773 return 0;
1777 #if defined(HAVE_UTIMENSAT)
1778 if (ft != NULL) {
1779 struct timespec ts[2];
1780 ts[0] = ft->atime;
1781 ts[1] = ft->mtime;
1782 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1783 } else {
1784 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1786 if (!((result == -1) && (errno == ENOSYS))) {
1787 goto out;
1789 #endif
1790 #if defined(HAVE_UTIMES)
1791 if (ft != NULL) {
1792 struct timeval tv[2];
1793 tv[0] = convert_timespec_to_timeval(ft->atime);
1794 tv[1] = convert_timespec_to_timeval(ft->mtime);
1795 result = utimes(smb_fname->base_name, tv);
1796 } else {
1797 result = utimes(smb_fname->base_name, NULL);
1799 if (!((result == -1) && (errno == ENOSYS))) {
1800 goto out;
1802 #endif
1803 #if defined(HAVE_UTIME)
1804 if (ft != NULL) {
1805 struct utimbuf times;
1806 times.actime = convert_timespec_to_time_t(ft->atime);
1807 times.modtime = convert_timespec_to_time_t(ft->mtime);
1808 result = utime(smb_fname->base_name, &times);
1809 } else {
1810 result = utime(smb_fname->base_name, NULL);
1812 if (!((result == -1) && (errno == ENOSYS))) {
1813 goto out;
1815 #endif
1816 errno = ENOSYS;
1817 result = -1;
1819 out:
1820 END_PROFILE(syscall_ntimes);
1821 return result;
1824 /*********************************************************************
1825 A version of ftruncate that will write the space on disk if strict
1826 allocate is set.
1827 **********************************************************************/
1829 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1831 off_t space_to_write;
1832 uint64_t space_avail;
1833 uint64_t bsize,dfree,dsize;
1834 int ret;
1835 NTSTATUS status;
1836 SMB_STRUCT_STAT *pst;
1838 status = vfs_stat_fsp(fsp);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 return -1;
1842 pst = &fsp->fsp_name->st;
1844 #ifdef S_ISFIFO
1845 if (S_ISFIFO(pst->st_ex_mode))
1846 return 0;
1847 #endif
1849 if (pst->st_ex_size == len)
1850 return 0;
1852 /* Shrink - just ftruncate. */
1853 if (pst->st_ex_size > len)
1854 return ftruncate(fsp->fh->fd, len);
1856 space_to_write = len - pst->st_ex_size;
1858 /* for allocation try fallocate first. This can fail on some
1859 platforms e.g. when the filesystem doesn't support it and no
1860 emulation is being done by the libc (like on AIX with JFS1). In that
1861 case we do our own emulation. fallocate implementations can
1862 return ENOTSUP or EINVAL in cases like that. */
1863 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1864 pst->st_ex_size, space_to_write);
1865 if (ret == -1 && errno == ENOSPC) {
1866 return -1;
1868 if (ret == 0) {
1869 return 0;
1871 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1872 "error %d. Falling back to slow manual allocation\n", errno));
1874 /* available disk space is enough or not? */
1875 space_avail = get_dfree_info(fsp->conn,
1876 fsp->fsp_name->base_name, false,
1877 &bsize,&dfree,&dsize);
1878 /* space_avail is 1k blocks */
1879 if (space_avail == (uint64_t)-1 ||
1880 ((uint64_t)space_to_write/1024 > space_avail) ) {
1881 errno = ENOSPC;
1882 return -1;
1885 /* Write out the real space on disk. */
1886 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1887 if (ret != 0) {
1888 return -1;
1891 return 0;
1894 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1896 int result = -1;
1897 SMB_STRUCT_STAT *pst;
1898 NTSTATUS status;
1899 char c = 0;
1901 START_PROFILE(syscall_ftruncate);
1903 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1904 result = strict_allocate_ftruncate(handle, fsp, len);
1905 END_PROFILE(syscall_ftruncate);
1906 return result;
1909 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1910 ftruncate if the system supports it. Then I discovered that
1911 you can have some filesystems that support ftruncate
1912 expansion and some that don't! On Linux fat can't do
1913 ftruncate extend but ext2 can. */
1915 result = ftruncate(fsp->fh->fd, len);
1916 if (result == 0)
1917 goto done;
1919 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1920 extend a file with ftruncate. Provide alternate implementation
1921 for this */
1923 /* Do an fstat to see if the file is longer than the requested
1924 size in which case the ftruncate above should have
1925 succeeded or shorter, in which case seek to len - 1 and
1926 write 1 byte of zero */
1927 status = vfs_stat_fsp(fsp);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 goto done;
1931 pst = &fsp->fsp_name->st;
1933 #ifdef S_ISFIFO
1934 if (S_ISFIFO(pst->st_ex_mode)) {
1935 result = 0;
1936 goto done;
1938 #endif
1940 if (pst->st_ex_size == len) {
1941 result = 0;
1942 goto done;
1945 if (pst->st_ex_size > len) {
1946 /* the ftruncate should have worked */
1947 goto done;
1950 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1951 goto done;
1954 result = 0;
1956 done:
1958 END_PROFILE(syscall_ftruncate);
1959 return result;
1962 static int vfswrap_fallocate(vfs_handle_struct *handle,
1963 files_struct *fsp,
1964 enum vfs_fallocate_mode mode,
1965 off_t offset,
1966 off_t len)
1968 int result;
1970 START_PROFILE(syscall_fallocate);
1971 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1972 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1974 * posix_fallocate returns 0 on success, errno on error
1975 * and doesn't set errno. Make it behave like fallocate()
1976 * which returns -1, and sets errno on failure.
1978 if (result != 0) {
1979 errno = result;
1980 result = -1;
1982 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1983 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1984 } else {
1985 errno = EINVAL;
1986 result = -1;
1988 END_PROFILE(syscall_fallocate);
1989 return result;
1992 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1994 bool result;
1996 START_PROFILE(syscall_fcntl_lock);
1997 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1998 END_PROFILE(syscall_fcntl_lock);
1999 return result;
2002 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2003 uint32 share_mode, uint32 access_mask)
2005 START_PROFILE(syscall_kernel_flock);
2006 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2007 END_PROFILE(syscall_kernel_flock);
2008 return 0;
2011 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2013 bool result;
2015 START_PROFILE(syscall_fcntl_getlock);
2016 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2017 END_PROFILE(syscall_fcntl_getlock);
2018 return result;
2021 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2022 int leasetype)
2024 int result = -1;
2026 START_PROFILE(syscall_linux_setlease);
2028 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2029 result = linux_setlease(fsp->fh->fd, leasetype);
2030 #else
2031 errno = ENOSYS;
2032 #endif
2033 END_PROFILE(syscall_linux_setlease);
2034 return result;
2037 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2039 int result;
2041 START_PROFILE(syscall_symlink);
2042 result = symlink(oldpath, newpath);
2043 END_PROFILE(syscall_symlink);
2044 return result;
2047 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2049 int result;
2051 START_PROFILE(syscall_readlink);
2052 result = readlink(path, buf, bufsiz);
2053 END_PROFILE(syscall_readlink);
2054 return result;
2057 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2059 int result;
2061 START_PROFILE(syscall_link);
2062 result = link(oldpath, newpath);
2063 END_PROFILE(syscall_link);
2064 return result;
2067 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2069 int result;
2071 START_PROFILE(syscall_mknod);
2072 result = sys_mknod(pathname, mode, dev);
2073 END_PROFILE(syscall_mknod);
2074 return result;
2077 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2079 char *result;
2081 START_PROFILE(syscall_realpath);
2082 #ifdef REALPATH_TAKES_NULL
2083 result = realpath(path, NULL);
2084 #else
2085 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2086 if (result) {
2087 char *resolved_path = realpath(path, result);
2088 if (!resolved_path) {
2089 SAFE_FREE(result);
2090 } else {
2091 /* SMB_ASSERT(result == resolved_path) ? */
2092 result = resolved_path;
2095 #endif
2096 END_PROFILE(syscall_realpath);
2097 return result;
2100 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2101 struct sys_notify_context *ctx,
2102 const char *path,
2103 uint32_t *filter,
2104 uint32_t *subdir_filter,
2105 void (*callback)(struct sys_notify_context *ctx,
2106 void *private_data,
2107 struct notify_event *ev),
2108 void *private_data, void *handle)
2111 * So far inotify is the only supported default notify mechanism. If
2112 * another platform like the the BSD's or a proprietary Unix comes
2113 * along and wants another default, we can play the same trick we
2114 * played with Posix ACLs.
2116 * Until that is the case, hard-code inotify here.
2118 #ifdef HAVE_INOTIFY
2119 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2120 int ret;
2121 if (!lp_parm_bool(-1, "notify", "inotify", True)) {
2122 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2125 * "ctx->private_data" is not obvious as a talloc context
2126 * here. Without modifying the VFS we don't have a mem_ctx
2127 * available here, and ctx->private_data was used by
2128 * inotify_watch before it got a real talloc parent.
2130 ret = inotify_watch(ctx->private_data, ctx,
2131 path, filter, subdir_filter,
2132 callback, private_data, handle);
2133 if (ret != 0) {
2134 return map_nt_error_from_unix(ret);
2136 return NT_STATUS_OK;
2138 #endif
2140 * Do nothing, leave everything to notify_internal.c
2142 return NT_STATUS_OK;
2145 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2146 unsigned int flags)
2148 #ifdef HAVE_CHFLAGS
2149 return chflags(path, flags);
2150 #else
2151 errno = ENOSYS;
2152 return -1;
2153 #endif
2156 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2157 const SMB_STRUCT_STAT *sbuf)
2159 struct file_id key;
2161 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2162 * blob */
2163 ZERO_STRUCT(key);
2165 key.devid = sbuf->st_ex_dev;
2166 key.inode = sbuf->st_ex_ino;
2167 /* key.extid is unused by default. */
2169 return key;
2172 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2173 struct files_struct *fsp,
2174 const char *fname,
2175 TALLOC_CTX *mem_ctx,
2176 unsigned int *pnum_streams,
2177 struct stream_struct **pstreams)
2179 SMB_STRUCT_STAT sbuf;
2180 struct stream_struct *tmp_streams = NULL;
2181 int ret;
2183 if ((fsp != NULL) && (fsp->is_directory)) {
2185 * No default streams on directories
2187 goto done;
2190 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2191 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2193 else {
2194 struct smb_filename smb_fname;
2196 ZERO_STRUCT(smb_fname);
2197 smb_fname.base_name = discard_const_p(char, fname);
2199 if (lp_posix_pathnames()) {
2200 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2201 } else {
2202 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2204 sbuf = smb_fname.st;
2207 if (ret == -1) {
2208 return map_nt_error_from_unix(errno);
2211 if (S_ISDIR(sbuf.st_ex_mode)) {
2212 goto done;
2215 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2216 (*pnum_streams) + 1);
2217 if (tmp_streams == NULL) {
2218 return NT_STATUS_NO_MEMORY;
2220 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2221 if (tmp_streams[*pnum_streams].name == NULL) {
2222 return NT_STATUS_NO_MEMORY;
2224 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2225 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2227 *pnum_streams += 1;
2228 *pstreams = tmp_streams;
2229 done:
2230 return NT_STATUS_OK;
2233 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2234 const char *path,
2235 const char *name,
2236 TALLOC_CTX *mem_ctx,
2237 char **found_name)
2240 * Don't fall back to get_real_filename so callers can differentiate
2241 * between a full directory scan and an actual case-insensitive stat.
2243 errno = EOPNOTSUPP;
2244 return -1;
2247 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2248 const char *fname)
2250 return handle->conn->connectpath;
2253 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2254 struct byte_range_lock *br_lck,
2255 struct lock_struct *plock,
2256 bool blocking_lock)
2258 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2260 /* Note: blr is not used in the default implementation. */
2261 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2264 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2265 struct messaging_context *msg_ctx,
2266 struct byte_range_lock *br_lck,
2267 const struct lock_struct *plock)
2269 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2271 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2274 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2275 struct byte_range_lock *br_lck,
2276 struct lock_struct *plock)
2278 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2280 /* Note: blr is not used in the default implementation. */
2281 return brl_lock_cancel_default(br_lck, plock);
2284 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2285 files_struct *fsp,
2286 struct lock_struct *plock)
2288 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2289 plock->lock_type == WRITE_LOCK);
2291 return strict_lock_default(fsp, plock);
2294 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2295 files_struct *fsp,
2296 struct lock_struct *plock)
2298 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2299 plock->lock_type == WRITE_LOCK);
2301 strict_unlock_default(fsp, plock);
2304 /* NT ACL operations. */
2306 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2307 files_struct *fsp,
2308 uint32 security_info,
2309 TALLOC_CTX *mem_ctx,
2310 struct security_descriptor **ppdesc)
2312 NTSTATUS result;
2314 START_PROFILE(fget_nt_acl);
2315 result = posix_fget_nt_acl(fsp, security_info,
2316 mem_ctx, ppdesc);
2317 END_PROFILE(fget_nt_acl);
2318 return result;
2321 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2322 const char *name,
2323 uint32 security_info,
2324 TALLOC_CTX *mem_ctx,
2325 struct security_descriptor **ppdesc)
2327 NTSTATUS result;
2329 START_PROFILE(get_nt_acl);
2330 result = posix_get_nt_acl(handle->conn, name, security_info,
2331 mem_ctx, ppdesc);
2332 END_PROFILE(get_nt_acl);
2333 return result;
2336 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2338 NTSTATUS result;
2340 START_PROFILE(fset_nt_acl);
2341 result = set_nt_acl(fsp, security_info_sent, psd);
2342 END_PROFILE(fset_nt_acl);
2343 return result;
2346 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2347 struct smb_filename *file,
2348 struct security_acl *sacl,
2349 uint32_t access_requested,
2350 uint32_t access_denied)
2352 return NT_STATUS_OK; /* Nothing to do here ... */
2355 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2357 #ifdef HAVE_NO_ACL
2358 errno = ENOSYS;
2359 return -1;
2360 #else
2361 int result;
2363 START_PROFILE(chmod_acl);
2364 result = chmod_acl(handle->conn, name, mode);
2365 END_PROFILE(chmod_acl);
2366 return result;
2367 #endif
2370 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2372 #ifdef HAVE_NO_ACL
2373 errno = ENOSYS;
2374 return -1;
2375 #else
2376 int result;
2378 START_PROFILE(fchmod_acl);
2379 result = fchmod_acl(fsp, mode);
2380 END_PROFILE(fchmod_acl);
2381 return result;
2382 #endif
2385 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2386 const char *path_p,
2387 SMB_ACL_TYPE_T type,
2388 TALLOC_CTX *mem_ctx)
2390 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2393 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2394 files_struct *fsp,
2395 TALLOC_CTX *mem_ctx)
2397 return sys_acl_get_fd(handle, fsp, mem_ctx);
2400 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2402 return sys_acl_set_file(handle, name, acltype, theacl);
2405 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2407 return sys_acl_set_fd(handle, fsp, theacl);
2410 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2412 return sys_acl_delete_def_file(handle, path);
2415 /****************************************************************
2416 Extended attribute operations.
2417 *****************************************************************/
2419 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2421 return getxattr(path, name, value, size);
2424 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2426 return fgetxattr(fsp->fh->fd, name, value, size);
2429 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2431 return listxattr(path, list, size);
2434 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2436 return flistxattr(fsp->fh->fd, list, size);
2439 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2441 return removexattr(path, name);
2444 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2446 return fremovexattr(fsp->fh->fd, name);
2449 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2451 return setxattr(path, name, value, size, flags);
2454 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2456 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2459 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2461 return false;
2464 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2465 const struct smb_filename *fname,
2466 SMB_STRUCT_STAT *sbuf)
2468 NTSTATUS status;
2469 char *path;
2470 bool offline = false;
2472 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2473 return false;
2476 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2477 #if defined(ENOTSUP)
2478 errno = ENOTSUP;
2479 #endif
2480 return false;
2483 status = get_full_smb_filename(talloc_tos(), fname, &path);
2484 if (!NT_STATUS_IS_OK(status)) {
2485 errno = map_errno_from_nt_status(status);
2486 return false;
2489 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2491 TALLOC_FREE(path);
2493 return offline;
2496 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2497 const struct smb_filename *fname)
2499 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2500 #if defined(ENOTSUP)
2501 errno = ENOTSUP;
2502 #endif
2503 return -1;
2506 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2507 struct files_struct *fsp,
2508 TALLOC_CTX *mem_ctx,
2509 DATA_BLOB *cookie)
2511 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2514 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2515 struct files_struct *fsp,
2516 const DATA_BLOB old_cookie,
2517 TALLOC_CTX *mem_ctx,
2518 DATA_BLOB *new_cookie)
2520 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2521 new_cookie);
2524 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2525 struct smb_request *smb1req,
2526 struct smbXsrv_open *op,
2527 const DATA_BLOB old_cookie,
2528 TALLOC_CTX *mem_ctx,
2529 struct files_struct **fsp,
2530 DATA_BLOB *new_cookie)
2532 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2533 old_cookie, mem_ctx,
2534 fsp, new_cookie);
2537 static struct vfs_fn_pointers vfs_default_fns = {
2538 /* Disk operations */
2540 .connect_fn = vfswrap_connect,
2541 .disconnect_fn = vfswrap_disconnect,
2542 .disk_free_fn = vfswrap_disk_free,
2543 .get_quota_fn = vfswrap_get_quota,
2544 .set_quota_fn = vfswrap_set_quota,
2545 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2546 .statvfs_fn = vfswrap_statvfs,
2547 .fs_capabilities_fn = vfswrap_fs_capabilities,
2548 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2550 /* Directory operations */
2552 .opendir_fn = vfswrap_opendir,
2553 .fdopendir_fn = vfswrap_fdopendir,
2554 .readdir_fn = vfswrap_readdir,
2555 .readdir_attr_fn = vfswrap_readdir_attr,
2556 .seekdir_fn = vfswrap_seekdir,
2557 .telldir_fn = vfswrap_telldir,
2558 .rewind_dir_fn = vfswrap_rewinddir,
2559 .mkdir_fn = vfswrap_mkdir,
2560 .rmdir_fn = vfswrap_rmdir,
2561 .closedir_fn = vfswrap_closedir,
2562 .init_search_op_fn = vfswrap_init_search_op,
2564 /* File operations */
2566 .open_fn = vfswrap_open,
2567 .create_file_fn = vfswrap_create_file,
2568 .close_fn = vfswrap_close,
2569 .read_fn = vfswrap_read,
2570 .pread_fn = vfswrap_pread,
2571 .pread_send_fn = vfswrap_pread_send,
2572 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2573 .write_fn = vfswrap_write,
2574 .pwrite_fn = vfswrap_pwrite,
2575 .pwrite_send_fn = vfswrap_pwrite_send,
2576 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2577 .lseek_fn = vfswrap_lseek,
2578 .sendfile_fn = vfswrap_sendfile,
2579 .recvfile_fn = vfswrap_recvfile,
2580 .rename_fn = vfswrap_rename,
2581 .fsync_fn = vfswrap_fsync,
2582 .fsync_send_fn = vfswrap_fsync_send,
2583 .fsync_recv_fn = vfswrap_asys_int_recv,
2584 .stat_fn = vfswrap_stat,
2585 .fstat_fn = vfswrap_fstat,
2586 .lstat_fn = vfswrap_lstat,
2587 .get_alloc_size_fn = vfswrap_get_alloc_size,
2588 .unlink_fn = vfswrap_unlink,
2589 .chmod_fn = vfswrap_chmod,
2590 .fchmod_fn = vfswrap_fchmod,
2591 .chown_fn = vfswrap_chown,
2592 .fchown_fn = vfswrap_fchown,
2593 .lchown_fn = vfswrap_lchown,
2594 .chdir_fn = vfswrap_chdir,
2595 .getwd_fn = vfswrap_getwd,
2596 .ntimes_fn = vfswrap_ntimes,
2597 .ftruncate_fn = vfswrap_ftruncate,
2598 .fallocate_fn = vfswrap_fallocate,
2599 .lock_fn = vfswrap_lock,
2600 .kernel_flock_fn = vfswrap_kernel_flock,
2601 .linux_setlease_fn = vfswrap_linux_setlease,
2602 .getlock_fn = vfswrap_getlock,
2603 .symlink_fn = vfswrap_symlink,
2604 .readlink_fn = vfswrap_readlink,
2605 .link_fn = vfswrap_link,
2606 .mknod_fn = vfswrap_mknod,
2607 .realpath_fn = vfswrap_realpath,
2608 .notify_watch_fn = vfswrap_notify_watch,
2609 .chflags_fn = vfswrap_chflags,
2610 .file_id_create_fn = vfswrap_file_id_create,
2611 .streaminfo_fn = vfswrap_streaminfo,
2612 .get_real_filename_fn = vfswrap_get_real_filename,
2613 .connectpath_fn = vfswrap_connectpath,
2614 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2615 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2616 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2617 .strict_lock_fn = vfswrap_strict_lock,
2618 .strict_unlock_fn = vfswrap_strict_unlock,
2619 .translate_name_fn = vfswrap_translate_name,
2620 .fsctl_fn = vfswrap_fsctl,
2621 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2622 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2623 .get_compression_fn = vfswrap_get_compression,
2624 .set_compression_fn = vfswrap_set_compression,
2626 /* NT ACL operations. */
2628 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2629 .get_nt_acl_fn = vfswrap_get_nt_acl,
2630 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2631 .audit_file_fn = vfswrap_audit_file,
2633 /* POSIX ACL operations. */
2635 .chmod_acl_fn = vfswrap_chmod_acl,
2636 .fchmod_acl_fn = vfswrap_fchmod_acl,
2638 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2639 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2640 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2641 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2642 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2643 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2644 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2646 /* EA operations. */
2647 .getxattr_fn = vfswrap_getxattr,
2648 .fgetxattr_fn = vfswrap_fgetxattr,
2649 .listxattr_fn = vfswrap_listxattr,
2650 .flistxattr_fn = vfswrap_flistxattr,
2651 .removexattr_fn = vfswrap_removexattr,
2652 .fremovexattr_fn = vfswrap_fremovexattr,
2653 .setxattr_fn = vfswrap_setxattr,
2654 .fsetxattr_fn = vfswrap_fsetxattr,
2656 /* aio operations */
2657 .aio_force_fn = vfswrap_aio_force,
2659 /* offline operations */
2660 .is_offline_fn = vfswrap_is_offline,
2661 .set_offline_fn = vfswrap_set_offline,
2663 /* durable handle operations */
2664 .durable_cookie_fn = vfswrap_durable_cookie,
2665 .durable_disconnect_fn = vfswrap_durable_disconnect,
2666 .durable_reconnect_fn = vfswrap_durable_reconnect,
2669 NTSTATUS vfs_default_init(void);
2670 NTSTATUS vfs_default_init(void)
2672 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2673 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);