nfs4acls: Introduce a helper variable
[Samba.git] / source3 / modules / vfs_default.c
blob10d0f3b62c822eca03aeb7cfc6073f3e9e7ed7d6
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,
58 uint64_t *bsize, uint64_t *dfree,
59 uint64_t *dsize)
61 uint64_t result;
63 result = sys_disk_free(handle->conn, path, bsize, dfree, dsize);
64 return result;
67 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
69 #ifdef HAVE_SYS_QUOTAS
70 int result;
72 START_PROFILE(syscall_get_quota);
73 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
74 END_PROFILE(syscall_get_quota);
75 return result;
76 #else
77 errno = ENOSYS;
78 return -1;
79 #endif
82 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
84 #ifdef HAVE_SYS_QUOTAS
85 int result;
87 START_PROFILE(syscall_set_quota);
88 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
89 END_PROFILE(syscall_set_quota);
90 return result;
91 #else
92 errno = ENOSYS;
93 return -1;
94 #endif
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
98 struct files_struct *fsp,
99 struct shadow_copy_data *shadow_copy_data,
100 bool labels)
102 errno = ENOSYS;
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
108 return sys_statvfs(path, statbuf);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
112 enum timestamp_set_resolution *p_ts_res)
114 connection_struct *conn = handle->conn;
115 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
116 struct smb_filename *smb_fname_cpath = NULL;
117 struct vfs_statvfs_struct statbuf;
118 int ret;
120 ZERO_STRUCT(statbuf);
121 ret = sys_statvfs(conn->connectpath, &statbuf);
122 if (ret == 0) {
123 caps = statbuf.FsCapabilities;
126 *p_ts_res = TIMESTAMP_SET_SECONDS;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
132 NULL, NULL);
133 if (smb_fname_cpath == NULL) {
134 return caps;
137 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
138 if (ret == -1) {
139 TALLOC_FREE(smb_fname_cpath);
140 return caps;
143 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
145 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res = TIMESTAMP_SET_MSEC;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res = TIMESTAMP_SET_SECONDS;
159 #endif
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
162 "resolution of %s "
163 "available on share %s, directory %s\n",
164 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn->params->service),
166 conn->connectpath ));
168 TALLOC_FREE(smb_fname_cpath);
169 return caps;
172 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
173 struct dfs_GetDFSReferral *r)
175 struct junction_map *junction = NULL;
176 int consumedcnt = 0;
177 bool self_referral = false;
178 char *pathnamep = NULL;
179 char *local_dfs_path = NULL;
180 NTSTATUS status;
181 int i;
182 uint16_t max_referral_level = r->in.req.max_referral_level;
184 if (DEBUGLVL(10)) {
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
188 /* get the junction entry */
189 if (r->in.req.servername == NULL) {
190 return NT_STATUS_NOT_FOUND;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path = talloc_strdup(r, r->in.req.servername);
199 if (local_dfs_path == NULL) {
200 return NT_STATUS_NO_MEMORY;
202 pathnamep = local_dfs_path;
203 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
204 IS_DIRECTORY_SEP(pathnamep[1])) {
205 pathnamep++;
208 junction = talloc_zero(r, struct junction_map);
209 if (junction == NULL) {
210 return NT_STATUS_NO_MEMORY;
213 /* The following call can change cwd. */
214 status = get_referred_path(r, pathnamep,
215 !handle->conn->sconn->using_smb2,
216 junction, &consumedcnt, &self_referral);
217 if (!NT_STATUS_IS_OK(status)) {
218 vfs_ChDir(handle->conn, handle->conn->connectpath);
219 return status;
221 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 if (!self_referral) {
224 pathnamep[consumedcnt] = '\0';
226 if (DEBUGLVL(3)) {
227 dbgtext("Path %s to alternate path(s):",
228 pathnamep);
229 for (i=0; i < junction->referral_count; i++) {
230 dbgtext(" %s",
231 junction->referral_list[i].alternate_path);
233 dbgtext(".\n");
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
253 if (self_referral) {
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
265 case 2:
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
273 t->version = 2;
274 v2->size = VERSION2_REFERRAL_SIZE;
275 if (self_referral) {
276 v2->server_type = DFS_SERVER_ROOT;
277 } else {
278 v2->server_type = DFS_SERVER_NON_ROOT;
280 v2->entry_flags = 0;
281 v2->proximity = ref->proximity;
282 v2->ttl = ref->ttl;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
298 break;
299 case 3:
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
308 t->version = 3;
309 v3->size = VERSION3_REFERRAL_SIZE;
310 if (self_referral) {
311 v3->server_type = DFS_SERVER_ROOT;
312 } else {
313 v3->server_type = DFS_SERVER_NON_ROOT;
315 v3->entry_flags = 0;
316 v3->ttl = ref->ttl;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
331 break;
332 default:
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
338 if (DEBUGLVL(10)) {
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
342 return NT_STATUS_OK;
345 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
346 TALLOC_CTX *mem_ctx,
347 const char *service_path,
348 char **base_volume)
350 return NT_STATUS_NOT_SUPPORTED;
353 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
354 TALLOC_CTX *mem_ctx,
355 const char *base_volume,
356 time_t *tstamp,
357 bool rw,
358 char **base_path,
359 char **snap_path)
361 return NT_STATUS_NOT_SUPPORTED;
364 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
365 TALLOC_CTX *mem_ctx,
366 char *base_path,
367 char *snap_path)
369 return NT_STATUS_NOT_SUPPORTED;
372 /* Directory operations */
374 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
376 DIR *result;
378 START_PROFILE(syscall_opendir);
379 result = opendir(fname);
380 END_PROFILE(syscall_opendir);
381 return result;
384 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
385 files_struct *fsp,
386 const char *mask,
387 uint32_t attr)
389 DIR *result;
391 START_PROFILE(syscall_fdopendir);
392 result = sys_fdopendir(fsp->fh->fd);
393 END_PROFILE(syscall_fdopendir);
394 return result;
398 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
399 DIR *dirp,
400 SMB_STRUCT_STAT *sbuf)
402 struct dirent *result;
404 START_PROFILE(syscall_readdir);
405 result = readdir(dirp);
406 END_PROFILE(syscall_readdir);
407 if (sbuf) {
408 /* Default Posix readdir() does not give us stat info.
409 * Set to invalid to indicate we didn't return this info. */
410 SET_STAT_INVALID(*sbuf);
411 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
412 if (result != NULL) {
413 /* See if we can efficiently return this. */
414 struct stat st;
415 int flags = (lp_posix_pathnames() ?
416 AT_SYMLINK_NOFOLLOW : 0);
417 int ret = fstatat(dirfd(dirp),
418 result->d_name,
419 &st,
420 flags);
421 if (ret == 0) {
422 init_stat_ex_from_stat(sbuf,
423 &st,
424 lp_fake_directory_create_times(
425 SNUM(handle->conn)));
428 #endif
430 return result;
433 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
434 const struct smb_filename *fname,
435 TALLOC_CTX *mem_ctx,
436 struct readdir_attr_data **attr_data)
438 return NT_STATUS_NOT_SUPPORTED;
441 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
443 START_PROFILE(syscall_seekdir);
444 seekdir(dirp, offset);
445 END_PROFILE(syscall_seekdir);
448 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
450 long result;
451 START_PROFILE(syscall_telldir);
452 result = telldir(dirp);
453 END_PROFILE(syscall_telldir);
454 return result;
457 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
459 START_PROFILE(syscall_rewinddir);
460 rewinddir(dirp);
461 END_PROFILE(syscall_rewinddir);
464 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
466 int result;
467 bool has_dacl = False;
468 char *parent = NULL;
470 START_PROFILE(syscall_mkdir);
472 if (lp_inherit_acls(SNUM(handle->conn))
473 && parent_dirname(talloc_tos(), path, &parent, NULL)
474 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
475 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
477 TALLOC_FREE(parent);
479 result = mkdir(path, mode);
481 if (result == 0 && !has_dacl) {
483 * We need to do this as the default behavior of POSIX ACLs
484 * is to set the mask to be the requested group permission
485 * bits, not the group permission bits to be the requested
486 * group permission bits. This is not what we want, as it will
487 * mess up any inherited ACL bits that were set. JRA.
489 int saved_errno = errno; /* We may get ENOSYS */
490 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
491 errno = saved_errno;
494 END_PROFILE(syscall_mkdir);
495 return result;
498 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
500 int result;
502 START_PROFILE(syscall_rmdir);
503 result = rmdir(path);
504 END_PROFILE(syscall_rmdir);
505 return result;
508 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
510 int result;
512 START_PROFILE(syscall_closedir);
513 result = closedir(dirp);
514 END_PROFILE(syscall_closedir);
515 return result;
518 static void vfswrap_init_search_op(vfs_handle_struct *handle,
519 DIR *dirp)
521 /* Default behavior is a NOOP */
524 /* File operations */
526 static int vfswrap_open(vfs_handle_struct *handle,
527 struct smb_filename *smb_fname,
528 files_struct *fsp, int flags, mode_t mode)
530 int result = -1;
532 START_PROFILE(syscall_open);
534 if (smb_fname->stream_name) {
535 errno = ENOENT;
536 goto out;
539 result = open(smb_fname->base_name, flags, mode);
540 out:
541 END_PROFILE(syscall_open);
542 return result;
545 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
546 struct smb_request *req,
547 uint16_t root_dir_fid,
548 struct smb_filename *smb_fname,
549 uint32_t access_mask,
550 uint32_t share_access,
551 uint32_t create_disposition,
552 uint32_t create_options,
553 uint32_t file_attributes,
554 uint32_t oplock_request,
555 struct smb2_lease *lease,
556 uint64_t allocation_size,
557 uint32_t private_flags,
558 struct security_descriptor *sd,
559 struct ea_list *ea_list,
560 files_struct **result,
561 int *pinfo,
562 const struct smb2_create_blobs *in_context_blobs,
563 struct smb2_create_blobs *out_context_blobs)
565 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
566 access_mask, share_access,
567 create_disposition, create_options,
568 file_attributes, oplock_request, lease,
569 allocation_size, private_flags,
570 sd, ea_list, result,
571 pinfo, in_context_blobs, out_context_blobs);
574 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
576 int result;
578 START_PROFILE(syscall_close);
579 result = fd_close_posix(fsp);
580 END_PROFILE(syscall_close);
581 return result;
584 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
586 ssize_t result;
588 START_PROFILE_BYTES(syscall_read, n);
589 result = sys_read(fsp->fh->fd, data, n);
590 END_PROFILE_BYTES(syscall_read);
591 return result;
594 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
595 size_t n, off_t offset)
597 ssize_t result;
599 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
600 START_PROFILE_BYTES(syscall_pread, n);
601 result = sys_pread(fsp->fh->fd, data, n, offset);
602 END_PROFILE_BYTES(syscall_pread);
604 if (result == -1 && errno == ESPIPE) {
605 /* Maintain the fiction that pipes can be seeked (sought?) on. */
606 result = SMB_VFS_READ(fsp, data, n);
607 fsp->fh->pos = 0;
610 #else /* HAVE_PREAD */
611 off_t curr;
612 int lerrno;
614 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
615 if (curr == -1 && errno == ESPIPE) {
616 /* Maintain the fiction that pipes can be seeked (sought?) on. */
617 result = SMB_VFS_READ(fsp, data, n);
618 fsp->fh->pos = 0;
619 return result;
622 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
623 return -1;
626 errno = 0;
627 result = SMB_VFS_READ(fsp, data, n);
628 lerrno = errno;
630 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
631 errno = lerrno;
633 #endif /* HAVE_PREAD */
635 return result;
638 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
640 ssize_t result;
642 START_PROFILE_BYTES(syscall_write, n);
643 result = sys_write(fsp->fh->fd, data, n);
644 END_PROFILE_BYTES(syscall_write);
645 return result;
648 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
649 size_t n, off_t offset)
651 ssize_t result;
653 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
654 START_PROFILE_BYTES(syscall_pwrite, n);
655 result = sys_pwrite(fsp->fh->fd, data, n, offset);
656 END_PROFILE_BYTES(syscall_pwrite);
658 if (result == -1 && errno == ESPIPE) {
659 /* Maintain the fiction that pipes can be sought on. */
660 result = SMB_VFS_WRITE(fsp, data, n);
663 #else /* HAVE_PWRITE */
664 off_t curr;
665 int lerrno;
667 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
668 if (curr == -1) {
669 return -1;
672 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
673 return -1;
676 result = SMB_VFS_WRITE(fsp, data, n);
677 lerrno = errno;
679 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
680 errno = lerrno;
682 #endif /* HAVE_PWRITE */
684 return result;
687 static void vfswrap_asys_finished(struct tevent_context *ev,
688 struct tevent_fd *fde,
689 uint16_t flags, void *p);
691 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
693 struct asys_context *ctx;
694 struct tevent_fd *fde;
695 int ret;
696 int fd;
698 if (conn->asys_ctx != NULL) {
699 return true;
702 ret = asys_context_init(&ctx, aio_pending_size);
703 if (ret != 0) {
704 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
705 return false;
708 fd = asys_signalfd(ctx);
710 ret = set_blocking(fd, false);
711 if (ret != 0) {
712 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
713 goto fail;
716 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
717 vfswrap_asys_finished, ctx);
718 if (fde == NULL) {
719 DEBUG(1, ("tevent_add_fd failed\n"));
720 goto fail;
723 conn->asys_ctx = ctx;
724 conn->asys_fde = fde;
725 return true;
727 fail:
728 asys_context_destroy(ctx);
729 return false;
732 struct vfswrap_asys_state {
733 struct asys_context *asys_ctx;
734 struct tevent_req *req;
735 ssize_t ret;
736 int err;
737 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
738 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
741 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
743 asys_cancel(s->asys_ctx, s->req);
744 return 0;
747 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
748 TALLOC_CTX *mem_ctx,
749 struct tevent_context *ev,
750 struct files_struct *fsp,
751 void *data,
752 size_t n, off_t offset)
754 struct tevent_req *req;
755 struct vfswrap_asys_state *state;
756 int ret;
758 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
759 if (req == NULL) {
760 return NULL;
762 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
763 tevent_req_oom(req);
764 return tevent_req_post(req, ev);
766 state->asys_ctx = handle->conn->sconn->asys_ctx;
767 state->req = req;
769 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
770 state->profile_bytes, n);
771 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
772 if (ret != 0) {
773 tevent_req_error(req, ret);
774 return tevent_req_post(req, ev);
776 talloc_set_destructor(state, vfswrap_asys_state_destructor);
778 return req;
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
782 TALLOC_CTX *mem_ctx,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
785 const void *data,
786 size_t n, off_t offset)
788 struct tevent_req *req;
789 struct vfswrap_asys_state *state;
790 int ret;
792 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
793 if (req == NULL) {
794 return NULL;
796 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
797 tevent_req_oom(req);
798 return tevent_req_post(req, ev);
800 state->asys_ctx = handle->conn->sconn->asys_ctx;
801 state->req = req;
803 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
804 state->profile_bytes, n);
805 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
806 if (ret != 0) {
807 tevent_req_error(req, ret);
808 return tevent_req_post(req, ev);
810 talloc_set_destructor(state, vfswrap_asys_state_destructor);
812 return req;
815 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
816 TALLOC_CTX *mem_ctx,
817 struct tevent_context *ev,
818 struct files_struct *fsp)
820 struct tevent_req *req;
821 struct vfswrap_asys_state *state;
822 int ret;
824 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
825 if (req == NULL) {
826 return NULL;
828 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
829 tevent_req_oom(req);
830 return tevent_req_post(req, ev);
832 state->asys_ctx = handle->conn->sconn->asys_ctx;
833 state->req = req;
835 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
836 state->profile_basic);
837 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
838 if (ret != 0) {
839 tevent_req_error(req, ret);
840 return tevent_req_post(req, ev);
842 talloc_set_destructor(state, vfswrap_asys_state_destructor);
844 return req;
847 static void vfswrap_asys_finished(struct tevent_context *ev,
848 struct tevent_fd *fde,
849 uint16_t flags, void *p)
851 struct asys_context *asys_ctx = (struct asys_context *)p;
852 struct asys_result results[outstanding_aio_calls];
853 int i, ret;
855 if ((flags & TEVENT_FD_READ) == 0) {
856 return;
859 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
860 if (ret < 0) {
861 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
862 return;
865 for (i=0; i<ret; i++) {
866 struct asys_result *result = &results[i];
867 struct tevent_req *req;
868 struct vfswrap_asys_state *state;
870 if ((result->ret == -1) && (result->err == ECANCELED)) {
871 continue;
874 req = talloc_get_type_abort(result->private_data,
875 struct tevent_req);
876 state = tevent_req_data(req, struct vfswrap_asys_state);
878 talloc_set_destructor(state, NULL);
880 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
881 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
882 state->ret = result->ret;
883 state->err = result->err;
884 tevent_req_defer_callback(req, ev);
885 tevent_req_done(req);
889 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
891 struct vfswrap_asys_state *state = tevent_req_data(
892 req, struct vfswrap_asys_state);
894 if (tevent_req_is_unix_error(req, err)) {
895 return -1;
897 *err = state->err;
898 return state->ret;
901 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
903 struct vfswrap_asys_state *state = tevent_req_data(
904 req, struct vfswrap_asys_state);
906 if (tevent_req_is_unix_error(req, err)) {
907 return -1;
909 *err = state->err;
910 return state->ret;
913 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
915 off_t result = 0;
917 START_PROFILE(syscall_lseek);
919 /* Cope with 'stat' file opens. */
920 if (fsp->fh->fd != -1)
921 result = lseek(fsp->fh->fd, offset, whence);
924 * We want to maintain the fiction that we can seek
925 * on a fifo for file system purposes. This allows
926 * people to set up UNIX fifo's that feed data to Windows
927 * applications. JRA.
930 if((result == -1) && (errno == ESPIPE)) {
931 result = 0;
932 errno = 0;
935 END_PROFILE(syscall_lseek);
936 return result;
939 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
940 off_t offset, size_t n)
942 ssize_t result;
944 START_PROFILE_BYTES(syscall_sendfile, n);
945 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
946 END_PROFILE_BYTES(syscall_sendfile);
947 return result;
950 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
951 int fromfd,
952 files_struct *tofsp,
953 off_t offset,
954 size_t n)
956 ssize_t result;
958 START_PROFILE_BYTES(syscall_recvfile, n);
959 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
960 END_PROFILE_BYTES(syscall_recvfile);
961 return result;
964 static int vfswrap_rename(vfs_handle_struct *handle,
965 const struct smb_filename *smb_fname_src,
966 const struct smb_filename *smb_fname_dst)
968 int result = -1;
970 START_PROFILE(syscall_rename);
972 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
973 errno = ENOENT;
974 goto out;
977 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
979 out:
980 END_PROFILE(syscall_rename);
981 return result;
984 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
986 #ifdef HAVE_FSYNC
987 int result;
989 START_PROFILE(syscall_fsync);
990 result = fsync(fsp->fh->fd);
991 END_PROFILE(syscall_fsync);
992 return result;
993 #else
994 return 0;
995 #endif
998 static int vfswrap_stat(vfs_handle_struct *handle,
999 struct smb_filename *smb_fname)
1001 int result = -1;
1003 START_PROFILE(syscall_stat);
1005 if (smb_fname->stream_name) {
1006 errno = ENOENT;
1007 goto out;
1010 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1011 lp_fake_directory_create_times(SNUM(handle->conn)));
1012 out:
1013 END_PROFILE(syscall_stat);
1014 return result;
1017 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1019 int result;
1021 START_PROFILE(syscall_fstat);
1022 result = sys_fstat(fsp->fh->fd,
1023 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1024 END_PROFILE(syscall_fstat);
1025 return result;
1028 static int vfswrap_lstat(vfs_handle_struct *handle,
1029 struct smb_filename *smb_fname)
1031 int result = -1;
1033 START_PROFILE(syscall_lstat);
1035 if (smb_fname->stream_name) {
1036 errno = ENOENT;
1037 goto out;
1040 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1041 lp_fake_directory_create_times(SNUM(handle->conn)));
1042 out:
1043 END_PROFILE(syscall_lstat);
1044 return result;
1047 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1048 const char *name,
1049 enum vfs_translate_direction direction,
1050 TALLOC_CTX *mem_ctx,
1051 char **mapped_name)
1053 return NT_STATUS_NONE_MAPPED;
1057 * Implement the default fsctl operation.
1059 static bool vfswrap_logged_ioctl_message = false;
1061 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1062 struct files_struct *fsp,
1063 TALLOC_CTX *ctx,
1064 uint32_t function,
1065 uint16_t req_flags, /* Needed for UNICODE ... */
1066 const uint8_t *_in_data,
1067 uint32_t in_len,
1068 uint8_t **_out_data,
1069 uint32_t max_out_len,
1070 uint32_t *out_len)
1072 const char *in_data = (const char *)_in_data;
1073 char **out_data = (char **)_out_data;
1074 NTSTATUS status;
1076 switch (function) {
1077 case FSCTL_SET_SPARSE:
1079 bool set_sparse = true;
1081 if (in_len >= 1 && in_data[0] == 0) {
1082 set_sparse = false;
1085 status = file_set_sparse(handle->conn, fsp, set_sparse);
1087 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1088 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1089 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1090 nt_errstr(status)));
1092 return status;
1095 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1097 unsigned char objid[16];
1098 char *return_data = NULL;
1100 /* This should return the object-id on this file.
1101 * I think I'll make this be the inode+dev. JRA.
1104 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1105 fsp_fnum_dbg(fsp)));
1107 *out_len = MIN(max_out_len, 64);
1109 /* Hmmm, will this cause problems if less data asked for? */
1110 return_data = talloc_array(ctx, char, 64);
1111 if (return_data == NULL) {
1112 return NT_STATUS_NO_MEMORY;
1115 /* For backwards compatibility only store the dev/inode. */
1116 push_file_id_16(return_data, &fsp->file_id);
1117 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1118 push_file_id_16(return_data+32, &fsp->file_id);
1119 memset(return_data+48, 0, 16);
1120 *out_data = return_data;
1121 return NT_STATUS_OK;
1124 case FSCTL_GET_REPARSE_POINT:
1126 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1127 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1128 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1129 return NT_STATUS_NOT_A_REPARSE_POINT;
1132 case FSCTL_SET_REPARSE_POINT:
1134 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1135 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1136 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1137 return NT_STATUS_NOT_A_REPARSE_POINT;
1140 case FSCTL_GET_SHADOW_COPY_DATA:
1143 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1144 * and return their volume names. If max_data_count is 16, then it is just
1145 * asking for the number of volumes and length of the combined names.
1147 * pdata is the data allocated by our caller, but that uses
1148 * total_data_count (which is 0 in our case) rather than max_data_count.
1149 * Allocate the correct amount and return the pointer to let
1150 * it be deallocated when we return.
1152 struct shadow_copy_data *shadow_data = NULL;
1153 bool labels = False;
1154 uint32_t labels_data_count = 0;
1155 uint32_t i;
1156 char *cur_pdata = NULL;
1158 if (max_out_len < 16) {
1159 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1160 max_out_len));
1161 return NT_STATUS_INVALID_PARAMETER;
1164 if (max_out_len > 16) {
1165 labels = True;
1168 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1169 if (shadow_data == NULL) {
1170 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1171 return NT_STATUS_NO_MEMORY;
1175 * Call the VFS routine to actually do the work.
1177 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1178 int log_lev = 0;
1179 if (errno == 0) {
1180 /* broken module didn't set errno on error */
1181 status = NT_STATUS_UNSUCCESSFUL;
1182 } else {
1183 status = map_nt_error_from_unix(errno);
1184 if (NT_STATUS_EQUAL(status,
1185 NT_STATUS_NOT_SUPPORTED)) {
1186 log_lev = 5;
1189 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1190 "connectpath %s, failed - %s.\n",
1191 fsp->conn->connectpath,
1192 nt_errstr(status)));
1193 TALLOC_FREE(shadow_data);
1194 return status;
1197 labels_data_count = (shadow_data->num_volumes * 2 *
1198 sizeof(SHADOW_COPY_LABEL)) + 2;
1200 if (!labels) {
1201 *out_len = 16;
1202 } else {
1203 *out_len = 12 + labels_data_count;
1206 if (max_out_len < *out_len) {
1207 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1208 max_out_len, *out_len));
1209 TALLOC_FREE(shadow_data);
1210 return NT_STATUS_BUFFER_TOO_SMALL;
1213 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1214 if (cur_pdata == NULL) {
1215 TALLOC_FREE(shadow_data);
1216 return NT_STATUS_NO_MEMORY;
1219 *out_data = cur_pdata;
1221 /* num_volumes 4 bytes */
1222 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1224 if (labels) {
1225 /* num_labels 4 bytes */
1226 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1229 /* needed_data_count 4 bytes */
1230 SIVAL(cur_pdata, 8, labels_data_count);
1232 cur_pdata += 12;
1234 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1235 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1236 if (labels && shadow_data->labels) {
1237 for (i=0; i<shadow_data->num_volumes; i++) {
1238 size_t len = 0;
1239 status = srvstr_push(cur_pdata, req_flags,
1240 cur_pdata, shadow_data->labels[i],
1241 2 * sizeof(SHADOW_COPY_LABEL),
1242 STR_UNICODE|STR_TERMINATE, &len);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 TALLOC_FREE(*out_data);
1245 TALLOC_FREE(shadow_data);
1246 return status;
1248 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1249 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1253 TALLOC_FREE(shadow_data);
1255 return NT_STATUS_OK;
1258 case FSCTL_FIND_FILES_BY_SID:
1260 /* pretend this succeeded -
1262 * we have to send back a list with all files owned by this SID
1264 * but I have to check that --metze
1266 struct dom_sid sid;
1267 uid_t uid;
1268 size_t sid_len;
1270 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1271 fsp_fnum_dbg(fsp)));
1273 if (in_len < 8) {
1274 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1275 return NT_STATUS_INVALID_PARAMETER;
1278 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1280 /* unknown 4 bytes: this is not the length of the sid :-( */
1281 /*unknown = IVAL(pdata,0);*/
1283 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1284 return NT_STATUS_INVALID_PARAMETER;
1286 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1288 if (!sid_to_uid(&sid, &uid)) {
1289 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1290 sid_string_dbg(&sid),
1291 (unsigned long)sid_len));
1292 uid = (-1);
1295 /* we can take a look at the find source :-)
1297 * find ./ -uid $uid -name '*' is what we need here
1300 * and send 4bytes len and then NULL terminated unicode strings
1301 * for each file
1303 * but I don't know how to deal with the paged results
1304 * (maybe we can hang the result anywhere in the fsp struct)
1306 * but I don't know how to deal with the paged results
1307 * (maybe we can hang the result anywhere in the fsp struct)
1309 * we don't send all files at once
1310 * and at the next we should *not* start from the beginning,
1311 * so we have to cache the result
1313 * --metze
1316 /* this works for now... */
1317 return NT_STATUS_OK;
1320 case FSCTL_QUERY_ALLOCATED_RANGES:
1322 /* FIXME: This is just a dummy reply, telling that all of the
1323 * file is allocated. MKS cp needs that.
1324 * Adding the real allocated ranges via FIEMAP on Linux
1325 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1326 * this FSCTL correct for sparse files.
1328 uint64_t offset, length;
1329 char *out_data_tmp = NULL;
1331 if (in_len != 16) {
1332 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1333 in_len));
1334 return NT_STATUS_INVALID_PARAMETER;
1337 if (max_out_len < 16) {
1338 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1339 max_out_len));
1340 return NT_STATUS_INVALID_PARAMETER;
1343 offset = BVAL(in_data,0);
1344 length = BVAL(in_data,8);
1346 if (offset + length < offset) {
1347 /* No 64-bit integer wrap. */
1348 return NT_STATUS_INVALID_PARAMETER;
1351 /* Shouldn't this be SMB_VFS_STAT ... ? */
1352 status = vfs_stat_fsp(fsp);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 return status;
1357 *out_len = 16;
1358 out_data_tmp = talloc_array(ctx, char, *out_len);
1359 if (out_data_tmp == NULL) {
1360 DEBUG(10, ("unable to allocate memory for response\n"));
1361 return NT_STATUS_NO_MEMORY;
1364 if (offset > fsp->fsp_name->st.st_ex_size ||
1365 fsp->fsp_name->st.st_ex_size == 0 ||
1366 length == 0) {
1367 memset(out_data_tmp, 0, *out_len);
1368 } else {
1369 uint64_t end = offset + length;
1370 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1371 SBVAL(out_data_tmp, 0, 0);
1372 SBVAL(out_data_tmp, 8, end);
1375 *out_data = out_data_tmp;
1377 return NT_STATUS_OK;
1380 case FSCTL_IS_VOLUME_DIRTY:
1382 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1383 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1385 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1386 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1388 return NT_STATUS_INVALID_PARAMETER;
1391 default:
1393 * Only print once ... unfortunately there could be lots of
1394 * different FSCTLs that are called.
1396 if (!vfswrap_logged_ioctl_message) {
1397 vfswrap_logged_ioctl_message = true;
1398 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1399 __func__, function));
1403 return NT_STATUS_NOT_SUPPORTED;
1406 struct vfs_cc_state {
1407 off_t copied;
1408 uint8_t *buf;
1411 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1412 TALLOC_CTX *mem_ctx,
1413 struct tevent_context *ev,
1414 struct files_struct *src_fsp,
1415 off_t src_off,
1416 struct files_struct *dest_fsp,
1417 off_t dest_off,
1418 off_t num)
1420 struct tevent_req *req;
1421 struct vfs_cc_state *vfs_cc_state;
1422 NTSTATUS status;
1424 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1425 (unsigned long)num));
1427 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1428 if (req == NULL) {
1429 return NULL;
1432 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1433 MIN(num, 8*1024*1024));
1434 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1435 return tevent_req_post(req, ev);
1438 status = vfs_stat_fsp(src_fsp);
1439 if (tevent_req_nterror(req, status)) {
1440 return tevent_req_post(req, ev);
1443 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1445 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1446 * If the SourceOffset or SourceOffset + Length extends beyond
1447 * the end of file, the server SHOULD<240> treat this as a
1448 * STATUS_END_OF_FILE error.
1449 * ...
1450 * <240> Section 3.3.5.15.6: Windows servers will return
1451 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1453 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1454 return tevent_req_post(req, ev);
1457 /* could use 2.6.33+ sendfile here to do this in kernel */
1458 while (vfs_cc_state->copied < num) {
1459 ssize_t ret;
1460 struct lock_struct lck;
1461 int saved_errno;
1463 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1464 num - vfs_cc_state->copied);
1466 if (src_fsp->op == NULL) {
1467 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1468 return tevent_req_post(req, ev);
1470 init_strict_lock_struct(src_fsp,
1471 src_fsp->op->global->open_persistent_id,
1472 src_off,
1473 this_num,
1474 READ_LOCK,
1475 &lck);
1477 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1478 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1479 return tevent_req_post(req, ev);
1482 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1483 this_num, src_off);
1484 if (ret == -1) {
1485 saved_errno = errno;
1488 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1490 if (ret == -1) {
1491 errno = saved_errno;
1492 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1493 return tevent_req_post(req, ev);
1495 if (ret != this_num) {
1496 /* zero tolerance for short reads */
1497 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1498 return tevent_req_post(req, ev);
1501 src_off += ret;
1503 if (dest_fsp->op == NULL) {
1504 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1505 return tevent_req_post(req, ev);
1508 init_strict_lock_struct(dest_fsp,
1509 dest_fsp->op->global->open_persistent_id,
1510 dest_off,
1511 this_num,
1512 WRITE_LOCK,
1513 &lck);
1515 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1516 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1517 return tevent_req_post(req, ev);
1520 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1521 this_num, dest_off);
1522 if (ret == -1) {
1523 saved_errno = errno;
1526 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1528 if (ret == -1) {
1529 errno = saved_errno;
1530 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1531 return tevent_req_post(req, ev);
1533 if (ret != this_num) {
1534 /* zero tolerance for short writes */
1535 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1536 return tevent_req_post(req, ev);
1538 dest_off += ret;
1540 vfs_cc_state->copied += this_num;
1543 tevent_req_done(req);
1544 return tevent_req_post(req, ev);
1547 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1548 struct tevent_req *req,
1549 off_t *copied)
1551 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1552 struct vfs_cc_state);
1553 NTSTATUS status;
1555 if (tevent_req_is_nterror(req, &status)) {
1556 DEBUG(2, ("server side copy chunk failed: %s\n",
1557 nt_errstr(status)));
1558 *copied = 0;
1559 tevent_req_received(req);
1560 return status;
1563 *copied = vfs_cc_state->copied;
1564 DEBUG(10, ("server side copy chunk copied %lu\n",
1565 (unsigned long)*copied));
1566 tevent_req_received(req);
1568 return NT_STATUS_OK;
1571 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1572 TALLOC_CTX *mem_ctx,
1573 struct files_struct *fsp,
1574 struct smb_filename *smb_fname,
1575 uint16_t *_compression_fmt)
1577 return NT_STATUS_INVALID_DEVICE_REQUEST;
1580 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1581 TALLOC_CTX *mem_ctx,
1582 struct files_struct *fsp,
1583 uint16_t compression_fmt)
1585 return NT_STATUS_INVALID_DEVICE_REQUEST;
1588 /********************************************************************
1589 Given a stat buffer return the allocated size on disk, taking into
1590 account sparse files.
1591 ********************************************************************/
1592 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1593 struct files_struct *fsp,
1594 const SMB_STRUCT_STAT *sbuf)
1596 uint64_t result;
1598 START_PROFILE(syscall_get_alloc_size);
1600 if(S_ISDIR(sbuf->st_ex_mode)) {
1601 result = 0;
1602 goto out;
1605 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1606 /* The type of st_blocksize is blkcnt_t which *MUST* be
1607 signed (according to POSIX) and can be less than 64-bits.
1608 Ensure when we're converting to 64 bits wide we don't
1609 sign extend. */
1610 #if defined(SIZEOF_BLKCNT_T_8)
1611 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1612 #elif defined(SIZEOF_BLKCNT_T_4)
1614 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1615 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1617 #else
1618 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1619 #endif
1620 if (result == 0) {
1622 * Some file systems do not allocate a block for very
1623 * small files. But for non-empty file should report a
1624 * positive size.
1627 uint64_t filesize = get_file_size_stat(sbuf);
1628 if (filesize > 0) {
1629 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1632 #else
1633 result = get_file_size_stat(sbuf);
1634 #endif
1636 if (fsp && fsp->initial_allocation_size)
1637 result = MAX(result,fsp->initial_allocation_size);
1639 result = smb_roundup(handle->conn, result);
1641 out:
1642 END_PROFILE(syscall_get_alloc_size);
1643 return result;
1646 static int vfswrap_unlink(vfs_handle_struct *handle,
1647 const struct smb_filename *smb_fname)
1649 int result = -1;
1651 START_PROFILE(syscall_unlink);
1653 if (smb_fname->stream_name) {
1654 errno = ENOENT;
1655 goto out;
1657 result = unlink(smb_fname->base_name);
1659 out:
1660 END_PROFILE(syscall_unlink);
1661 return result;
1664 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1666 int result;
1668 START_PROFILE(syscall_chmod);
1671 * We need to do this due to the fact that the default POSIX ACL
1672 * chmod modifies the ACL *mask* for the group owner, not the
1673 * group owner bits directly. JRA.
1678 int saved_errno = errno; /* We might get ENOSYS */
1679 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1680 END_PROFILE(syscall_chmod);
1681 return result;
1683 /* Error - return the old errno. */
1684 errno = saved_errno;
1687 result = chmod(path, mode);
1688 END_PROFILE(syscall_chmod);
1689 return result;
1692 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1694 int result;
1696 START_PROFILE(syscall_fchmod);
1699 * We need to do this due to the fact that the default POSIX ACL
1700 * chmod modifies the ACL *mask* for the group owner, not the
1701 * group owner bits directly. JRA.
1705 int saved_errno = errno; /* We might get ENOSYS */
1706 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1707 END_PROFILE(syscall_fchmod);
1708 return result;
1710 /* Error - return the old errno. */
1711 errno = saved_errno;
1714 #if defined(HAVE_FCHMOD)
1715 result = fchmod(fsp->fh->fd, mode);
1716 #else
1717 result = -1;
1718 errno = ENOSYS;
1719 #endif
1721 END_PROFILE(syscall_fchmod);
1722 return result;
1725 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1727 int result;
1729 START_PROFILE(syscall_chown);
1730 result = chown(path, uid, gid);
1731 END_PROFILE(syscall_chown);
1732 return result;
1735 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1737 #ifdef HAVE_FCHOWN
1738 int result;
1740 START_PROFILE(syscall_fchown);
1741 result = fchown(fsp->fh->fd, uid, gid);
1742 END_PROFILE(syscall_fchown);
1743 return result;
1744 #else
1745 errno = ENOSYS;
1746 return -1;
1747 #endif
1750 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1752 int result;
1754 START_PROFILE(syscall_lchown);
1755 result = lchown(path, uid, gid);
1756 END_PROFILE(syscall_lchown);
1757 return result;
1760 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1762 int result;
1764 START_PROFILE(syscall_chdir);
1765 result = chdir(path);
1766 END_PROFILE(syscall_chdir);
1767 return result;
1770 static char *vfswrap_getwd(vfs_handle_struct *handle)
1772 char *result;
1774 START_PROFILE(syscall_getwd);
1775 result = sys_getwd();
1776 END_PROFILE(syscall_getwd);
1777 return result;
1780 /*********************************************************************
1781 nsec timestamp resolution call. Convert down to whatever the underlying
1782 system will support.
1783 **********************************************************************/
1785 static int vfswrap_ntimes(vfs_handle_struct *handle,
1786 const struct smb_filename *smb_fname,
1787 struct smb_file_time *ft)
1789 int result = -1;
1791 START_PROFILE(syscall_ntimes);
1793 if (smb_fname->stream_name) {
1794 errno = ENOENT;
1795 goto out;
1798 if (ft != NULL) {
1799 if (null_timespec(ft->atime)) {
1800 ft->atime= smb_fname->st.st_ex_atime;
1803 if (null_timespec(ft->mtime)) {
1804 ft->mtime = smb_fname->st.st_ex_mtime;
1807 if (!null_timespec(ft->create_time)) {
1808 set_create_timespec_ea(handle->conn,
1809 smb_fname,
1810 ft->create_time);
1813 if ((timespec_compare(&ft->atime,
1814 &smb_fname->st.st_ex_atime) == 0) &&
1815 (timespec_compare(&ft->mtime,
1816 &smb_fname->st.st_ex_mtime) == 0)) {
1817 return 0;
1821 #if defined(HAVE_UTIMENSAT)
1822 if (ft != NULL) {
1823 struct timespec ts[2];
1824 ts[0] = ft->atime;
1825 ts[1] = ft->mtime;
1826 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1827 } else {
1828 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1830 if (!((result == -1) && (errno == ENOSYS))) {
1831 goto out;
1833 #endif
1834 #if defined(HAVE_UTIMES)
1835 if (ft != NULL) {
1836 struct timeval tv[2];
1837 tv[0] = convert_timespec_to_timeval(ft->atime);
1838 tv[1] = convert_timespec_to_timeval(ft->mtime);
1839 result = utimes(smb_fname->base_name, tv);
1840 } else {
1841 result = utimes(smb_fname->base_name, NULL);
1843 if (!((result == -1) && (errno == ENOSYS))) {
1844 goto out;
1846 #endif
1847 #if defined(HAVE_UTIME)
1848 if (ft != NULL) {
1849 struct utimbuf times;
1850 times.actime = convert_timespec_to_time_t(ft->atime);
1851 times.modtime = convert_timespec_to_time_t(ft->mtime);
1852 result = utime(smb_fname->base_name, &times);
1853 } else {
1854 result = utime(smb_fname->base_name, NULL);
1856 if (!((result == -1) && (errno == ENOSYS))) {
1857 goto out;
1859 #endif
1860 errno = ENOSYS;
1861 result = -1;
1863 out:
1864 END_PROFILE(syscall_ntimes);
1865 return result;
1868 /*********************************************************************
1869 A version of ftruncate that will write the space on disk if strict
1870 allocate is set.
1871 **********************************************************************/
1873 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1875 off_t space_to_write;
1876 uint64_t space_avail;
1877 uint64_t bsize,dfree,dsize;
1878 int ret;
1879 NTSTATUS status;
1880 SMB_STRUCT_STAT *pst;
1882 status = vfs_stat_fsp(fsp);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 return -1;
1886 pst = &fsp->fsp_name->st;
1888 #ifdef S_ISFIFO
1889 if (S_ISFIFO(pst->st_ex_mode))
1890 return 0;
1891 #endif
1893 if (pst->st_ex_size == len)
1894 return 0;
1896 /* Shrink - just ftruncate. */
1897 if (pst->st_ex_size > len)
1898 return ftruncate(fsp->fh->fd, len);
1900 space_to_write = len - pst->st_ex_size;
1902 /* for allocation try fallocate first. This can fail on some
1903 platforms e.g. when the filesystem doesn't support it and no
1904 emulation is being done by the libc (like on AIX with JFS1). In that
1905 case we do our own emulation. fallocate implementations can
1906 return ENOTSUP or EINVAL in cases like that. */
1907 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1908 if (ret == -1 && errno == ENOSPC) {
1909 return -1;
1911 if (ret == 0) {
1912 return 0;
1914 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1915 "error %d. Falling back to slow manual allocation\n", errno));
1917 /* available disk space is enough or not? */
1918 space_avail = get_dfree_info(fsp->conn,
1919 fsp->fsp_name->base_name,
1920 &bsize, &dfree, &dsize);
1921 /* space_avail is 1k blocks */
1922 if (space_avail == (uint64_t)-1 ||
1923 ((uint64_t)space_to_write/1024 > space_avail) ) {
1924 errno = ENOSPC;
1925 return -1;
1928 /* Write out the real space on disk. */
1929 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1930 if (ret != 0) {
1931 return -1;
1934 return 0;
1937 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1939 int result = -1;
1940 SMB_STRUCT_STAT *pst;
1941 NTSTATUS status;
1942 char c = 0;
1944 START_PROFILE(syscall_ftruncate);
1946 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1947 result = strict_allocate_ftruncate(handle, fsp, len);
1948 END_PROFILE(syscall_ftruncate);
1949 return result;
1952 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1953 ftruncate if the system supports it. Then I discovered that
1954 you can have some filesystems that support ftruncate
1955 expansion and some that don't! On Linux fat can't do
1956 ftruncate extend but ext2 can. */
1958 result = ftruncate(fsp->fh->fd, len);
1960 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1961 extend a file with ftruncate. Provide alternate implementation
1962 for this */
1964 /* Do an fstat to see if the file is longer than the requested
1965 size in which case the ftruncate above should have
1966 succeeded or shorter, in which case seek to len - 1 and
1967 write 1 byte of zero */
1968 status = vfs_stat_fsp(fsp);
1969 if (!NT_STATUS_IS_OK(status)) {
1970 goto done;
1973 /* We need to update the files_struct after successful ftruncate */
1974 if (result == 0) {
1975 goto done;
1978 pst = &fsp->fsp_name->st;
1980 #ifdef S_ISFIFO
1981 if (S_ISFIFO(pst->st_ex_mode)) {
1982 result = 0;
1983 goto done;
1985 #endif
1987 if (pst->st_ex_size == len) {
1988 result = 0;
1989 goto done;
1992 if (pst->st_ex_size > len) {
1993 /* the ftruncate should have worked */
1994 goto done;
1997 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1998 goto done;
2001 result = 0;
2003 done:
2005 END_PROFILE(syscall_ftruncate);
2006 return result;
2009 static int vfswrap_fallocate(vfs_handle_struct *handle,
2010 files_struct *fsp,
2011 uint32_t mode,
2012 off_t offset,
2013 off_t len)
2015 int result;
2017 START_PROFILE(syscall_fallocate);
2018 if (mode == 0) {
2019 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2021 * posix_fallocate returns 0 on success, errno on error
2022 * and doesn't set errno. Make it behave like fallocate()
2023 * which returns -1, and sets errno on failure.
2025 if (result != 0) {
2026 errno = result;
2027 result = -1;
2029 } else {
2030 /* sys_fallocate handles filtering of unsupported mode flags */
2031 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2033 END_PROFILE(syscall_fallocate);
2034 return result;
2037 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2039 bool result;
2041 START_PROFILE(syscall_fcntl_lock);
2042 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2043 END_PROFILE(syscall_fcntl_lock);
2044 return result;
2047 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2048 uint32_t share_mode, uint32_t access_mask)
2050 START_PROFILE(syscall_kernel_flock);
2051 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2052 END_PROFILE(syscall_kernel_flock);
2053 return 0;
2056 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2058 bool result;
2060 START_PROFILE(syscall_fcntl_getlock);
2061 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2062 END_PROFILE(syscall_fcntl_getlock);
2063 return result;
2066 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2067 int leasetype)
2069 int result = -1;
2071 START_PROFILE(syscall_linux_setlease);
2073 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2074 result = linux_setlease(fsp->fh->fd, leasetype);
2075 #else
2076 errno = ENOSYS;
2077 #endif
2078 END_PROFILE(syscall_linux_setlease);
2079 return result;
2082 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2084 int result;
2086 START_PROFILE(syscall_symlink);
2087 result = symlink(oldpath, newpath);
2088 END_PROFILE(syscall_symlink);
2089 return result;
2092 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2094 int result;
2096 START_PROFILE(syscall_readlink);
2097 result = readlink(path, buf, bufsiz);
2098 END_PROFILE(syscall_readlink);
2099 return result;
2102 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2104 int result;
2106 START_PROFILE(syscall_link);
2107 result = link(oldpath, newpath);
2108 END_PROFILE(syscall_link);
2109 return result;
2112 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2114 int result;
2116 START_PROFILE(syscall_mknod);
2117 result = sys_mknod(pathname, mode, dev);
2118 END_PROFILE(syscall_mknod);
2119 return result;
2122 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2124 char *result;
2126 START_PROFILE(syscall_realpath);
2127 #ifdef REALPATH_TAKES_NULL
2128 result = realpath(path, NULL);
2129 #else
2130 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2131 if (result) {
2132 char *resolved_path = realpath(path, result);
2133 if (!resolved_path) {
2134 SAFE_FREE(result);
2135 } else {
2136 /* SMB_ASSERT(result == resolved_path) ? */
2137 result = resolved_path;
2140 #endif
2141 END_PROFILE(syscall_realpath);
2142 return result;
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_t 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_t 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_t 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,
2549 .snap_check_path_fn = vfswrap_snap_check_path,
2550 .snap_create_fn = vfswrap_snap_create,
2551 .snap_delete_fn = vfswrap_snap_delete,
2553 /* Directory operations */
2555 .opendir_fn = vfswrap_opendir,
2556 .fdopendir_fn = vfswrap_fdopendir,
2557 .readdir_fn = vfswrap_readdir,
2558 .readdir_attr_fn = vfswrap_readdir_attr,
2559 .seekdir_fn = vfswrap_seekdir,
2560 .telldir_fn = vfswrap_telldir,
2561 .rewind_dir_fn = vfswrap_rewinddir,
2562 .mkdir_fn = vfswrap_mkdir,
2563 .rmdir_fn = vfswrap_rmdir,
2564 .closedir_fn = vfswrap_closedir,
2565 .init_search_op_fn = vfswrap_init_search_op,
2567 /* File operations */
2569 .open_fn = vfswrap_open,
2570 .create_file_fn = vfswrap_create_file,
2571 .close_fn = vfswrap_close,
2572 .read_fn = vfswrap_read,
2573 .pread_fn = vfswrap_pread,
2574 .pread_send_fn = vfswrap_pread_send,
2575 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2576 .write_fn = vfswrap_write,
2577 .pwrite_fn = vfswrap_pwrite,
2578 .pwrite_send_fn = vfswrap_pwrite_send,
2579 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2580 .lseek_fn = vfswrap_lseek,
2581 .sendfile_fn = vfswrap_sendfile,
2582 .recvfile_fn = vfswrap_recvfile,
2583 .rename_fn = vfswrap_rename,
2584 .fsync_fn = vfswrap_fsync,
2585 .fsync_send_fn = vfswrap_fsync_send,
2586 .fsync_recv_fn = vfswrap_asys_int_recv,
2587 .stat_fn = vfswrap_stat,
2588 .fstat_fn = vfswrap_fstat,
2589 .lstat_fn = vfswrap_lstat,
2590 .get_alloc_size_fn = vfswrap_get_alloc_size,
2591 .unlink_fn = vfswrap_unlink,
2592 .chmod_fn = vfswrap_chmod,
2593 .fchmod_fn = vfswrap_fchmod,
2594 .chown_fn = vfswrap_chown,
2595 .fchown_fn = vfswrap_fchown,
2596 .lchown_fn = vfswrap_lchown,
2597 .chdir_fn = vfswrap_chdir,
2598 .getwd_fn = vfswrap_getwd,
2599 .ntimes_fn = vfswrap_ntimes,
2600 .ftruncate_fn = vfswrap_ftruncate,
2601 .fallocate_fn = vfswrap_fallocate,
2602 .lock_fn = vfswrap_lock,
2603 .kernel_flock_fn = vfswrap_kernel_flock,
2604 .linux_setlease_fn = vfswrap_linux_setlease,
2605 .getlock_fn = vfswrap_getlock,
2606 .symlink_fn = vfswrap_symlink,
2607 .readlink_fn = vfswrap_readlink,
2608 .link_fn = vfswrap_link,
2609 .mknod_fn = vfswrap_mknod,
2610 .realpath_fn = vfswrap_realpath,
2611 .chflags_fn = vfswrap_chflags,
2612 .file_id_create_fn = vfswrap_file_id_create,
2613 .streaminfo_fn = vfswrap_streaminfo,
2614 .get_real_filename_fn = vfswrap_get_real_filename,
2615 .connectpath_fn = vfswrap_connectpath,
2616 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2617 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2618 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2619 .strict_lock_fn = vfswrap_strict_lock,
2620 .strict_unlock_fn = vfswrap_strict_unlock,
2621 .translate_name_fn = vfswrap_translate_name,
2622 .fsctl_fn = vfswrap_fsctl,
2623 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2624 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2625 .get_compression_fn = vfswrap_get_compression,
2626 .set_compression_fn = vfswrap_set_compression,
2628 /* NT ACL operations. */
2630 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2631 .get_nt_acl_fn = vfswrap_get_nt_acl,
2632 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2633 .audit_file_fn = vfswrap_audit_file,
2635 /* POSIX ACL operations. */
2637 .chmod_acl_fn = vfswrap_chmod_acl,
2638 .fchmod_acl_fn = vfswrap_fchmod_acl,
2640 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2641 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2642 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2643 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2644 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2645 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2646 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2648 /* EA operations. */
2649 .getxattr_fn = vfswrap_getxattr,
2650 .fgetxattr_fn = vfswrap_fgetxattr,
2651 .listxattr_fn = vfswrap_listxattr,
2652 .flistxattr_fn = vfswrap_flistxattr,
2653 .removexattr_fn = vfswrap_removexattr,
2654 .fremovexattr_fn = vfswrap_fremovexattr,
2655 .setxattr_fn = vfswrap_setxattr,
2656 .fsetxattr_fn = vfswrap_fsetxattr,
2658 /* aio operations */
2659 .aio_force_fn = vfswrap_aio_force,
2661 /* offline operations */
2662 .is_offline_fn = vfswrap_is_offline,
2663 .set_offline_fn = vfswrap_set_offline,
2665 /* durable handle operations */
2666 .durable_cookie_fn = vfswrap_durable_cookie,
2667 .durable_disconnect_fn = vfswrap_durable_disconnect,
2668 .durable_reconnect_fn = vfswrap_durable_reconnect,
2671 NTSTATUS vfs_default_init(void);
2672 NTSTATUS vfs_default_init(void)
2674 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2675 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);