vfs: Fix CID 1035384 Unchecked return value from library
[Samba.git] / source3 / modules / vfs_default.c
blob1c29cb4c79df40a9161fc5bddb186671e2900042
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 int ret;
694 int fd;
696 if (conn->asys_ctx != NULL) {
697 return true;
699 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
700 if (ret != 0) {
701 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
702 return false;
705 fd = asys_signalfd(conn->asys_ctx);
707 ret = set_blocking(fd, false);
708 if (ret != 0) {
709 DBG_WARNING("set_blocking failed: %s\n", strerror(ret));
710 asys_context_destroy(conn->asys_ctx);
711 conn->asys_ctx = NULL;
712 return false;
715 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
716 TEVENT_FD_READ,
717 vfswrap_asys_finished,
718 conn->asys_ctx);
719 if (conn->asys_fde == NULL) {
720 DEBUG(1, ("tevent_add_fd failed\n"));
721 asys_context_destroy(conn->asys_ctx);
722 conn->asys_ctx = NULL;
723 return false;
725 return true;
728 struct vfswrap_asys_state {
729 struct asys_context *asys_ctx;
730 struct tevent_req *req;
731 ssize_t ret;
732 int err;
733 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
734 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
737 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
739 asys_cancel(s->asys_ctx, s->req);
740 return 0;
743 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
744 TALLOC_CTX *mem_ctx,
745 struct tevent_context *ev,
746 struct files_struct *fsp,
747 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_pread, profile_p,
766 state->profile_bytes, n);
767 ret = asys_pread(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_pwrite_send(struct vfs_handle_struct *handle,
778 TALLOC_CTX *mem_ctx,
779 struct tevent_context *ev,
780 struct files_struct *fsp,
781 const void *data,
782 size_t n, off_t offset)
784 struct tevent_req *req;
785 struct vfswrap_asys_state *state;
786 int ret;
788 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
789 if (req == NULL) {
790 return NULL;
792 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
793 tevent_req_oom(req);
794 return tevent_req_post(req, ev);
796 state->asys_ctx = handle->conn->sconn->asys_ctx;
797 state->req = req;
799 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
800 state->profile_bytes, n);
801 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
802 if (ret != 0) {
803 tevent_req_error(req, ret);
804 return tevent_req_post(req, ev);
806 talloc_set_destructor(state, vfswrap_asys_state_destructor);
808 return req;
811 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
812 TALLOC_CTX *mem_ctx,
813 struct tevent_context *ev,
814 struct files_struct *fsp)
816 struct tevent_req *req;
817 struct vfswrap_asys_state *state;
818 int ret;
820 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
821 if (req == NULL) {
822 return NULL;
824 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
825 tevent_req_oom(req);
826 return tevent_req_post(req, ev);
828 state->asys_ctx = handle->conn->sconn->asys_ctx;
829 state->req = req;
831 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
832 state->profile_basic);
833 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
834 if (ret != 0) {
835 tevent_req_error(req, ret);
836 return tevent_req_post(req, ev);
838 talloc_set_destructor(state, vfswrap_asys_state_destructor);
840 return req;
843 static void vfswrap_asys_finished(struct tevent_context *ev,
844 struct tevent_fd *fde,
845 uint16_t flags, void *p)
847 struct asys_context *asys_ctx = (struct asys_context *)p;
848 struct asys_result results[outstanding_aio_calls];
849 int i, ret;
851 if ((flags & TEVENT_FD_READ) == 0) {
852 return;
855 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
856 if (ret < 0) {
857 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
858 return;
861 for (i=0; i<ret; i++) {
862 struct asys_result *result = &results[i];
863 struct tevent_req *req;
864 struct vfswrap_asys_state *state;
866 if ((result->ret == -1) && (result->err == ECANCELED)) {
867 continue;
870 req = talloc_get_type_abort(result->private_data,
871 struct tevent_req);
872 state = tevent_req_data(req, struct vfswrap_asys_state);
874 talloc_set_destructor(state, NULL);
876 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
877 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
878 state->ret = result->ret;
879 state->err = result->err;
880 tevent_req_defer_callback(req, ev);
881 tevent_req_done(req);
885 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
887 struct vfswrap_asys_state *state = tevent_req_data(
888 req, struct vfswrap_asys_state);
890 if (tevent_req_is_unix_error(req, err)) {
891 return -1;
893 *err = state->err;
894 return state->ret;
897 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
899 struct vfswrap_asys_state *state = tevent_req_data(
900 req, struct vfswrap_asys_state);
902 if (tevent_req_is_unix_error(req, err)) {
903 return -1;
905 *err = state->err;
906 return state->ret;
909 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
911 off_t result = 0;
913 START_PROFILE(syscall_lseek);
915 /* Cope with 'stat' file opens. */
916 if (fsp->fh->fd != -1)
917 result = lseek(fsp->fh->fd, offset, whence);
920 * We want to maintain the fiction that we can seek
921 * on a fifo for file system purposes. This allows
922 * people to set up UNIX fifo's that feed data to Windows
923 * applications. JRA.
926 if((result == -1) && (errno == ESPIPE)) {
927 result = 0;
928 errno = 0;
931 END_PROFILE(syscall_lseek);
932 return result;
935 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
936 off_t offset, size_t n)
938 ssize_t result;
940 START_PROFILE_BYTES(syscall_sendfile, n);
941 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
942 END_PROFILE_BYTES(syscall_sendfile);
943 return result;
946 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
947 int fromfd,
948 files_struct *tofsp,
949 off_t offset,
950 size_t n)
952 ssize_t result;
954 START_PROFILE_BYTES(syscall_recvfile, n);
955 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
956 END_PROFILE_BYTES(syscall_recvfile);
957 return result;
960 static int vfswrap_rename(vfs_handle_struct *handle,
961 const struct smb_filename *smb_fname_src,
962 const struct smb_filename *smb_fname_dst)
964 int result = -1;
966 START_PROFILE(syscall_rename);
968 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
969 errno = ENOENT;
970 goto out;
973 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
975 out:
976 END_PROFILE(syscall_rename);
977 return result;
980 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
982 #ifdef HAVE_FSYNC
983 int result;
985 START_PROFILE(syscall_fsync);
986 result = fsync(fsp->fh->fd);
987 END_PROFILE(syscall_fsync);
988 return result;
989 #else
990 return 0;
991 #endif
994 static int vfswrap_stat(vfs_handle_struct *handle,
995 struct smb_filename *smb_fname)
997 int result = -1;
999 START_PROFILE(syscall_stat);
1001 if (smb_fname->stream_name) {
1002 errno = ENOENT;
1003 goto out;
1006 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1007 lp_fake_directory_create_times(SNUM(handle->conn)));
1008 out:
1009 END_PROFILE(syscall_stat);
1010 return result;
1013 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1015 int result;
1017 START_PROFILE(syscall_fstat);
1018 result = sys_fstat(fsp->fh->fd,
1019 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1020 END_PROFILE(syscall_fstat);
1021 return result;
1024 static int vfswrap_lstat(vfs_handle_struct *handle,
1025 struct smb_filename *smb_fname)
1027 int result = -1;
1029 START_PROFILE(syscall_lstat);
1031 if (smb_fname->stream_name) {
1032 errno = ENOENT;
1033 goto out;
1036 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1037 lp_fake_directory_create_times(SNUM(handle->conn)));
1038 out:
1039 END_PROFILE(syscall_lstat);
1040 return result;
1043 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1044 const char *name,
1045 enum vfs_translate_direction direction,
1046 TALLOC_CTX *mem_ctx,
1047 char **mapped_name)
1049 return NT_STATUS_NONE_MAPPED;
1053 * Implement the default fsctl operation.
1055 static bool vfswrap_logged_ioctl_message = false;
1057 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1058 struct files_struct *fsp,
1059 TALLOC_CTX *ctx,
1060 uint32_t function,
1061 uint16_t req_flags, /* Needed for UNICODE ... */
1062 const uint8_t *_in_data,
1063 uint32_t in_len,
1064 uint8_t **_out_data,
1065 uint32_t max_out_len,
1066 uint32_t *out_len)
1068 const char *in_data = (const char *)_in_data;
1069 char **out_data = (char **)_out_data;
1070 NTSTATUS status;
1072 switch (function) {
1073 case FSCTL_SET_SPARSE:
1075 bool set_sparse = true;
1077 if (in_len >= 1 && in_data[0] == 0) {
1078 set_sparse = false;
1081 status = file_set_sparse(handle->conn, fsp, set_sparse);
1083 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1084 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1085 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1086 nt_errstr(status)));
1088 return status;
1091 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1093 unsigned char objid[16];
1094 char *return_data = NULL;
1096 /* This should return the object-id on this file.
1097 * I think I'll make this be the inode+dev. JRA.
1100 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1101 fsp_fnum_dbg(fsp)));
1103 *out_len = MIN(max_out_len, 64);
1105 /* Hmmm, will this cause problems if less data asked for? */
1106 return_data = talloc_array(ctx, char, 64);
1107 if (return_data == NULL) {
1108 return NT_STATUS_NO_MEMORY;
1111 /* For backwards compatibility only store the dev/inode. */
1112 push_file_id_16(return_data, &fsp->file_id);
1113 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1114 push_file_id_16(return_data+32, &fsp->file_id);
1115 memset(return_data+48, 0, 16);
1116 *out_data = return_data;
1117 return NT_STATUS_OK;
1120 case FSCTL_GET_REPARSE_POINT:
1122 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1123 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1124 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1125 return NT_STATUS_NOT_A_REPARSE_POINT;
1128 case FSCTL_SET_REPARSE_POINT:
1130 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1131 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1132 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1133 return NT_STATUS_NOT_A_REPARSE_POINT;
1136 case FSCTL_GET_SHADOW_COPY_DATA:
1139 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1140 * and return their volume names. If max_data_count is 16, then it is just
1141 * asking for the number of volumes and length of the combined names.
1143 * pdata is the data allocated by our caller, but that uses
1144 * total_data_count (which is 0 in our case) rather than max_data_count.
1145 * Allocate the correct amount and return the pointer to let
1146 * it be deallocated when we return.
1148 struct shadow_copy_data *shadow_data = NULL;
1149 bool labels = False;
1150 uint32_t labels_data_count = 0;
1151 uint32_t i;
1152 char *cur_pdata = NULL;
1154 if (max_out_len < 16) {
1155 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1156 max_out_len));
1157 return NT_STATUS_INVALID_PARAMETER;
1160 if (max_out_len > 16) {
1161 labels = True;
1164 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1165 if (shadow_data == NULL) {
1166 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1167 return NT_STATUS_NO_MEMORY;
1171 * Call the VFS routine to actually do the work.
1173 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1174 int log_lev = 0;
1175 if (errno == 0) {
1176 /* broken module didn't set errno on error */
1177 status = NT_STATUS_UNSUCCESSFUL;
1178 } else {
1179 status = map_nt_error_from_unix(errno);
1180 if (NT_STATUS_EQUAL(status,
1181 NT_STATUS_NOT_SUPPORTED)) {
1182 log_lev = 5;
1185 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1186 "connectpath %s, failed - %s.\n",
1187 fsp->conn->connectpath,
1188 nt_errstr(status)));
1189 TALLOC_FREE(shadow_data);
1190 return status;
1193 labels_data_count = (shadow_data->num_volumes * 2 *
1194 sizeof(SHADOW_COPY_LABEL)) + 2;
1196 if (!labels) {
1197 *out_len = 16;
1198 } else {
1199 *out_len = 12 + labels_data_count;
1202 if (max_out_len < *out_len) {
1203 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1204 max_out_len, *out_len));
1205 TALLOC_FREE(shadow_data);
1206 return NT_STATUS_BUFFER_TOO_SMALL;
1209 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1210 if (cur_pdata == NULL) {
1211 TALLOC_FREE(shadow_data);
1212 return NT_STATUS_NO_MEMORY;
1215 *out_data = cur_pdata;
1217 /* num_volumes 4 bytes */
1218 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1220 if (labels) {
1221 /* num_labels 4 bytes */
1222 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1225 /* needed_data_count 4 bytes */
1226 SIVAL(cur_pdata, 8, labels_data_count);
1228 cur_pdata += 12;
1230 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1231 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1232 if (labels && shadow_data->labels) {
1233 for (i=0; i<shadow_data->num_volumes; i++) {
1234 size_t len = 0;
1235 status = srvstr_push(cur_pdata, req_flags,
1236 cur_pdata, shadow_data->labels[i],
1237 2 * sizeof(SHADOW_COPY_LABEL),
1238 STR_UNICODE|STR_TERMINATE, &len);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 TALLOC_FREE(*out_data);
1241 TALLOC_FREE(shadow_data);
1242 return status;
1244 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1245 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1249 TALLOC_FREE(shadow_data);
1251 return NT_STATUS_OK;
1254 case FSCTL_FIND_FILES_BY_SID:
1256 /* pretend this succeeded -
1258 * we have to send back a list with all files owned by this SID
1260 * but I have to check that --metze
1262 struct dom_sid sid;
1263 uid_t uid;
1264 size_t sid_len;
1266 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1267 fsp_fnum_dbg(fsp)));
1269 if (in_len < 8) {
1270 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1271 return NT_STATUS_INVALID_PARAMETER;
1274 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1276 /* unknown 4 bytes: this is not the length of the sid :-( */
1277 /*unknown = IVAL(pdata,0);*/
1279 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1280 return NT_STATUS_INVALID_PARAMETER;
1282 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1284 if (!sid_to_uid(&sid, &uid)) {
1285 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1286 sid_string_dbg(&sid),
1287 (unsigned long)sid_len));
1288 uid = (-1);
1291 /* we can take a look at the find source :-)
1293 * find ./ -uid $uid -name '*' is what we need here
1296 * and send 4bytes len and then NULL terminated unicode strings
1297 * for each file
1299 * but I don't know how to deal with the paged results
1300 * (maybe we can hang the result anywhere in the fsp struct)
1302 * but I don't know how to deal with the paged results
1303 * (maybe we can hang the result anywhere in the fsp struct)
1305 * we don't send all files at once
1306 * and at the next we should *not* start from the beginning,
1307 * so we have to cache the result
1309 * --metze
1312 /* this works for now... */
1313 return NT_STATUS_OK;
1316 case FSCTL_QUERY_ALLOCATED_RANGES:
1318 /* FIXME: This is just a dummy reply, telling that all of the
1319 * file is allocated. MKS cp needs that.
1320 * Adding the real allocated ranges via FIEMAP on Linux
1321 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1322 * this FSCTL correct for sparse files.
1324 uint64_t offset, length;
1325 char *out_data_tmp = NULL;
1327 if (in_len != 16) {
1328 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1329 in_len));
1330 return NT_STATUS_INVALID_PARAMETER;
1333 if (max_out_len < 16) {
1334 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1335 max_out_len));
1336 return NT_STATUS_INVALID_PARAMETER;
1339 offset = BVAL(in_data,0);
1340 length = BVAL(in_data,8);
1342 if (offset + length < offset) {
1343 /* No 64-bit integer wrap. */
1344 return NT_STATUS_INVALID_PARAMETER;
1347 /* Shouldn't this be SMB_VFS_STAT ... ? */
1348 status = vfs_stat_fsp(fsp);
1349 if (!NT_STATUS_IS_OK(status)) {
1350 return status;
1353 *out_len = 16;
1354 out_data_tmp = talloc_array(ctx, char, *out_len);
1355 if (out_data_tmp == NULL) {
1356 DEBUG(10, ("unable to allocate memory for response\n"));
1357 return NT_STATUS_NO_MEMORY;
1360 if (offset > fsp->fsp_name->st.st_ex_size ||
1361 fsp->fsp_name->st.st_ex_size == 0 ||
1362 length == 0) {
1363 memset(out_data_tmp, 0, *out_len);
1364 } else {
1365 uint64_t end = offset + length;
1366 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1367 SBVAL(out_data_tmp, 0, 0);
1368 SBVAL(out_data_tmp, 8, end);
1371 *out_data = out_data_tmp;
1373 return NT_STATUS_OK;
1376 case FSCTL_IS_VOLUME_DIRTY:
1378 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1379 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1381 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1382 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1384 return NT_STATUS_INVALID_PARAMETER;
1387 default:
1389 * Only print once ... unfortunately there could be lots of
1390 * different FSCTLs that are called.
1392 if (!vfswrap_logged_ioctl_message) {
1393 vfswrap_logged_ioctl_message = true;
1394 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1395 __func__, function));
1399 return NT_STATUS_NOT_SUPPORTED;
1402 struct vfs_cc_state {
1403 off_t copied;
1404 uint8_t *buf;
1407 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1408 TALLOC_CTX *mem_ctx,
1409 struct tevent_context *ev,
1410 struct files_struct *src_fsp,
1411 off_t src_off,
1412 struct files_struct *dest_fsp,
1413 off_t dest_off,
1414 off_t num)
1416 struct tevent_req *req;
1417 struct vfs_cc_state *vfs_cc_state;
1418 NTSTATUS status;
1420 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1421 (unsigned long)num));
1423 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1424 if (req == NULL) {
1425 return NULL;
1428 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1429 MIN(num, 8*1024*1024));
1430 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1431 return tevent_req_post(req, ev);
1434 status = vfs_stat_fsp(src_fsp);
1435 if (tevent_req_nterror(req, status)) {
1436 return tevent_req_post(req, ev);
1439 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1441 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1442 * If the SourceOffset or SourceOffset + Length extends beyond
1443 * the end of file, the server SHOULD<240> treat this as a
1444 * STATUS_END_OF_FILE error.
1445 * ...
1446 * <240> Section 3.3.5.15.6: Windows servers will return
1447 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1449 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1450 return tevent_req_post(req, ev);
1453 /* could use 2.6.33+ sendfile here to do this in kernel */
1454 while (vfs_cc_state->copied < num) {
1455 ssize_t ret;
1456 struct lock_struct lck;
1457 int saved_errno;
1459 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1460 num - vfs_cc_state->copied);
1462 if (src_fsp->op == NULL) {
1463 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1464 return tevent_req_post(req, ev);
1466 init_strict_lock_struct(src_fsp,
1467 src_fsp->op->global->open_persistent_id,
1468 src_off,
1469 this_num,
1470 READ_LOCK,
1471 &lck);
1473 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1474 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1475 return tevent_req_post(req, ev);
1478 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1479 this_num, src_off);
1480 if (ret == -1) {
1481 saved_errno = errno;
1484 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1486 if (ret == -1) {
1487 errno = saved_errno;
1488 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1489 return tevent_req_post(req, ev);
1491 if (ret != this_num) {
1492 /* zero tolerance for short reads */
1493 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1494 return tevent_req_post(req, ev);
1497 src_off += ret;
1499 if (dest_fsp->op == NULL) {
1500 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1501 return tevent_req_post(req, ev);
1504 init_strict_lock_struct(dest_fsp,
1505 dest_fsp->op->global->open_persistent_id,
1506 dest_off,
1507 this_num,
1508 WRITE_LOCK,
1509 &lck);
1511 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1512 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1513 return tevent_req_post(req, ev);
1516 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1517 this_num, dest_off);
1518 if (ret == -1) {
1519 saved_errno = errno;
1522 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1524 if (ret == -1) {
1525 errno = saved_errno;
1526 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1527 return tevent_req_post(req, ev);
1529 if (ret != this_num) {
1530 /* zero tolerance for short writes */
1531 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1532 return tevent_req_post(req, ev);
1534 dest_off += ret;
1536 vfs_cc_state->copied += this_num;
1539 tevent_req_done(req);
1540 return tevent_req_post(req, ev);
1543 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1544 struct tevent_req *req,
1545 off_t *copied)
1547 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1548 struct vfs_cc_state);
1549 NTSTATUS status;
1551 if (tevent_req_is_nterror(req, &status)) {
1552 DEBUG(2, ("server side copy chunk failed: %s\n",
1553 nt_errstr(status)));
1554 *copied = 0;
1555 tevent_req_received(req);
1556 return status;
1559 *copied = vfs_cc_state->copied;
1560 DEBUG(10, ("server side copy chunk copied %lu\n",
1561 (unsigned long)*copied));
1562 tevent_req_received(req);
1564 return NT_STATUS_OK;
1567 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1568 TALLOC_CTX *mem_ctx,
1569 struct files_struct *fsp,
1570 struct smb_filename *smb_fname,
1571 uint16_t *_compression_fmt)
1573 return NT_STATUS_INVALID_DEVICE_REQUEST;
1576 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1577 TALLOC_CTX *mem_ctx,
1578 struct files_struct *fsp,
1579 uint16_t compression_fmt)
1581 return NT_STATUS_INVALID_DEVICE_REQUEST;
1584 /********************************************************************
1585 Given a stat buffer return the allocated size on disk, taking into
1586 account sparse files.
1587 ********************************************************************/
1588 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1589 struct files_struct *fsp,
1590 const SMB_STRUCT_STAT *sbuf)
1592 uint64_t result;
1594 START_PROFILE(syscall_get_alloc_size);
1596 if(S_ISDIR(sbuf->st_ex_mode)) {
1597 result = 0;
1598 goto out;
1601 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1602 /* The type of st_blocksize is blkcnt_t which *MUST* be
1603 signed (according to POSIX) and can be less than 64-bits.
1604 Ensure when we're converting to 64 bits wide we don't
1605 sign extend. */
1606 #if defined(SIZEOF_BLKCNT_T_8)
1607 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1608 #elif defined(SIZEOF_BLKCNT_T_4)
1610 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1611 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1613 #else
1614 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1615 #endif
1616 if (result == 0) {
1618 * Some file systems do not allocate a block for very
1619 * small files. But for non-empty file should report a
1620 * positive size.
1623 uint64_t filesize = get_file_size_stat(sbuf);
1624 if (filesize > 0) {
1625 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1628 #else
1629 result = get_file_size_stat(sbuf);
1630 #endif
1632 if (fsp && fsp->initial_allocation_size)
1633 result = MAX(result,fsp->initial_allocation_size);
1635 result = smb_roundup(handle->conn, result);
1637 out:
1638 END_PROFILE(syscall_get_alloc_size);
1639 return result;
1642 static int vfswrap_unlink(vfs_handle_struct *handle,
1643 const struct smb_filename *smb_fname)
1645 int result = -1;
1647 START_PROFILE(syscall_unlink);
1649 if (smb_fname->stream_name) {
1650 errno = ENOENT;
1651 goto out;
1653 result = unlink(smb_fname->base_name);
1655 out:
1656 END_PROFILE(syscall_unlink);
1657 return result;
1660 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1662 int result;
1664 START_PROFILE(syscall_chmod);
1667 * We need to do this due to the fact that the default POSIX ACL
1668 * chmod modifies the ACL *mask* for the group owner, not the
1669 * group owner bits directly. JRA.
1674 int saved_errno = errno; /* We might get ENOSYS */
1675 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1676 END_PROFILE(syscall_chmod);
1677 return result;
1679 /* Error - return the old errno. */
1680 errno = saved_errno;
1683 result = chmod(path, mode);
1684 END_PROFILE(syscall_chmod);
1685 return result;
1688 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1690 int result;
1692 START_PROFILE(syscall_fchmod);
1695 * We need to do this due to the fact that the default POSIX ACL
1696 * chmod modifies the ACL *mask* for the group owner, not the
1697 * group owner bits directly. JRA.
1701 int saved_errno = errno; /* We might get ENOSYS */
1702 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1703 END_PROFILE(syscall_fchmod);
1704 return result;
1706 /* Error - return the old errno. */
1707 errno = saved_errno;
1710 #if defined(HAVE_FCHMOD)
1711 result = fchmod(fsp->fh->fd, mode);
1712 #else
1713 result = -1;
1714 errno = ENOSYS;
1715 #endif
1717 END_PROFILE(syscall_fchmod);
1718 return result;
1721 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1723 int result;
1725 START_PROFILE(syscall_chown);
1726 result = chown(path, uid, gid);
1727 END_PROFILE(syscall_chown);
1728 return result;
1731 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1733 #ifdef HAVE_FCHOWN
1734 int result;
1736 START_PROFILE(syscall_fchown);
1737 result = fchown(fsp->fh->fd, uid, gid);
1738 END_PROFILE(syscall_fchown);
1739 return result;
1740 #else
1741 errno = ENOSYS;
1742 return -1;
1743 #endif
1746 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1748 int result;
1750 START_PROFILE(syscall_lchown);
1751 result = lchown(path, uid, gid);
1752 END_PROFILE(syscall_lchown);
1753 return result;
1756 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1758 int result;
1760 START_PROFILE(syscall_chdir);
1761 result = chdir(path);
1762 END_PROFILE(syscall_chdir);
1763 return result;
1766 static char *vfswrap_getwd(vfs_handle_struct *handle)
1768 char *result;
1770 START_PROFILE(syscall_getwd);
1771 result = sys_getwd();
1772 END_PROFILE(syscall_getwd);
1773 return result;
1776 /*********************************************************************
1777 nsec timestamp resolution call. Convert down to whatever the underlying
1778 system will support.
1779 **********************************************************************/
1781 static int vfswrap_ntimes(vfs_handle_struct *handle,
1782 const struct smb_filename *smb_fname,
1783 struct smb_file_time *ft)
1785 int result = -1;
1787 START_PROFILE(syscall_ntimes);
1789 if (smb_fname->stream_name) {
1790 errno = ENOENT;
1791 goto out;
1794 if (ft != NULL) {
1795 if (null_timespec(ft->atime)) {
1796 ft->atime= smb_fname->st.st_ex_atime;
1799 if (null_timespec(ft->mtime)) {
1800 ft->mtime = smb_fname->st.st_ex_mtime;
1803 if (!null_timespec(ft->create_time)) {
1804 set_create_timespec_ea(handle->conn,
1805 smb_fname,
1806 ft->create_time);
1809 if ((timespec_compare(&ft->atime,
1810 &smb_fname->st.st_ex_atime) == 0) &&
1811 (timespec_compare(&ft->mtime,
1812 &smb_fname->st.st_ex_mtime) == 0)) {
1813 return 0;
1817 #if defined(HAVE_UTIMENSAT)
1818 if (ft != NULL) {
1819 struct timespec ts[2];
1820 ts[0] = ft->atime;
1821 ts[1] = ft->mtime;
1822 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1823 } else {
1824 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1826 if (!((result == -1) && (errno == ENOSYS))) {
1827 goto out;
1829 #endif
1830 #if defined(HAVE_UTIMES)
1831 if (ft != NULL) {
1832 struct timeval tv[2];
1833 tv[0] = convert_timespec_to_timeval(ft->atime);
1834 tv[1] = convert_timespec_to_timeval(ft->mtime);
1835 result = utimes(smb_fname->base_name, tv);
1836 } else {
1837 result = utimes(smb_fname->base_name, NULL);
1839 if (!((result == -1) && (errno == ENOSYS))) {
1840 goto out;
1842 #endif
1843 #if defined(HAVE_UTIME)
1844 if (ft != NULL) {
1845 struct utimbuf times;
1846 times.actime = convert_timespec_to_time_t(ft->atime);
1847 times.modtime = convert_timespec_to_time_t(ft->mtime);
1848 result = utime(smb_fname->base_name, &times);
1849 } else {
1850 result = utime(smb_fname->base_name, NULL);
1852 if (!((result == -1) && (errno == ENOSYS))) {
1853 goto out;
1855 #endif
1856 errno = ENOSYS;
1857 result = -1;
1859 out:
1860 END_PROFILE(syscall_ntimes);
1861 return result;
1864 /*********************************************************************
1865 A version of ftruncate that will write the space on disk if strict
1866 allocate is set.
1867 **********************************************************************/
1869 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1871 off_t space_to_write;
1872 uint64_t space_avail;
1873 uint64_t bsize,dfree,dsize;
1874 int ret;
1875 NTSTATUS status;
1876 SMB_STRUCT_STAT *pst;
1878 status = vfs_stat_fsp(fsp);
1879 if (!NT_STATUS_IS_OK(status)) {
1880 return -1;
1882 pst = &fsp->fsp_name->st;
1884 #ifdef S_ISFIFO
1885 if (S_ISFIFO(pst->st_ex_mode))
1886 return 0;
1887 #endif
1889 if (pst->st_ex_size == len)
1890 return 0;
1892 /* Shrink - just ftruncate. */
1893 if (pst->st_ex_size > len)
1894 return ftruncate(fsp->fh->fd, len);
1896 space_to_write = len - pst->st_ex_size;
1898 /* for allocation try fallocate first. This can fail on some
1899 platforms e.g. when the filesystem doesn't support it and no
1900 emulation is being done by the libc (like on AIX with JFS1). In that
1901 case we do our own emulation. fallocate implementations can
1902 return ENOTSUP or EINVAL in cases like that. */
1903 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1904 if (ret == -1 && errno == ENOSPC) {
1905 return -1;
1907 if (ret == 0) {
1908 return 0;
1910 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1911 "error %d. Falling back to slow manual allocation\n", errno));
1913 /* available disk space is enough or not? */
1914 space_avail = get_dfree_info(fsp->conn,
1915 fsp->fsp_name->base_name,
1916 &bsize, &dfree, &dsize);
1917 /* space_avail is 1k blocks */
1918 if (space_avail == (uint64_t)-1 ||
1919 ((uint64_t)space_to_write/1024 > space_avail) ) {
1920 errno = ENOSPC;
1921 return -1;
1924 /* Write out the real space on disk. */
1925 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1926 if (ret != 0) {
1927 return -1;
1930 return 0;
1933 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1935 int result = -1;
1936 SMB_STRUCT_STAT *pst;
1937 NTSTATUS status;
1938 char c = 0;
1940 START_PROFILE(syscall_ftruncate);
1942 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1943 result = strict_allocate_ftruncate(handle, fsp, len);
1944 END_PROFILE(syscall_ftruncate);
1945 return result;
1948 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1949 ftruncate if the system supports it. Then I discovered that
1950 you can have some filesystems that support ftruncate
1951 expansion and some that don't! On Linux fat can't do
1952 ftruncate extend but ext2 can. */
1954 result = ftruncate(fsp->fh->fd, len);
1956 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1957 extend a file with ftruncate. Provide alternate implementation
1958 for this */
1960 /* Do an fstat to see if the file is longer than the requested
1961 size in which case the ftruncate above should have
1962 succeeded or shorter, in which case seek to len - 1 and
1963 write 1 byte of zero */
1964 status = vfs_stat_fsp(fsp);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 goto done;
1969 /* We need to update the files_struct after successful ftruncate */
1970 if (result == 0) {
1971 goto done;
1974 pst = &fsp->fsp_name->st;
1976 #ifdef S_ISFIFO
1977 if (S_ISFIFO(pst->st_ex_mode)) {
1978 result = 0;
1979 goto done;
1981 #endif
1983 if (pst->st_ex_size == len) {
1984 result = 0;
1985 goto done;
1988 if (pst->st_ex_size > len) {
1989 /* the ftruncate should have worked */
1990 goto done;
1993 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1994 goto done;
1997 result = 0;
1999 done:
2001 END_PROFILE(syscall_ftruncate);
2002 return result;
2005 static int vfswrap_fallocate(vfs_handle_struct *handle,
2006 files_struct *fsp,
2007 uint32_t mode,
2008 off_t offset,
2009 off_t len)
2011 int result;
2013 START_PROFILE(syscall_fallocate);
2014 if (mode == 0) {
2015 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2017 * posix_fallocate returns 0 on success, errno on error
2018 * and doesn't set errno. Make it behave like fallocate()
2019 * which returns -1, and sets errno on failure.
2021 if (result != 0) {
2022 errno = result;
2023 result = -1;
2025 } else {
2026 /* sys_fallocate handles filtering of unsupported mode flags */
2027 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2029 END_PROFILE(syscall_fallocate);
2030 return result;
2033 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2035 bool result;
2037 START_PROFILE(syscall_fcntl_lock);
2038 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2039 END_PROFILE(syscall_fcntl_lock);
2040 return result;
2043 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2044 uint32_t share_mode, uint32_t access_mask)
2046 START_PROFILE(syscall_kernel_flock);
2047 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2048 END_PROFILE(syscall_kernel_flock);
2049 return 0;
2052 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2054 bool result;
2056 START_PROFILE(syscall_fcntl_getlock);
2057 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2058 END_PROFILE(syscall_fcntl_getlock);
2059 return result;
2062 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2063 int leasetype)
2065 int result = -1;
2067 START_PROFILE(syscall_linux_setlease);
2069 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2070 result = linux_setlease(fsp->fh->fd, leasetype);
2071 #else
2072 errno = ENOSYS;
2073 #endif
2074 END_PROFILE(syscall_linux_setlease);
2075 return result;
2078 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2080 int result;
2082 START_PROFILE(syscall_symlink);
2083 result = symlink(oldpath, newpath);
2084 END_PROFILE(syscall_symlink);
2085 return result;
2088 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2090 int result;
2092 START_PROFILE(syscall_readlink);
2093 result = readlink(path, buf, bufsiz);
2094 END_PROFILE(syscall_readlink);
2095 return result;
2098 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2100 int result;
2102 START_PROFILE(syscall_link);
2103 result = link(oldpath, newpath);
2104 END_PROFILE(syscall_link);
2105 return result;
2108 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2110 int result;
2112 START_PROFILE(syscall_mknod);
2113 result = sys_mknod(pathname, mode, dev);
2114 END_PROFILE(syscall_mknod);
2115 return result;
2118 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2120 char *result;
2122 START_PROFILE(syscall_realpath);
2123 #ifdef REALPATH_TAKES_NULL
2124 result = realpath(path, NULL);
2125 #else
2126 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2127 if (result) {
2128 char *resolved_path = realpath(path, result);
2129 if (!resolved_path) {
2130 SAFE_FREE(result);
2131 } else {
2132 /* SMB_ASSERT(result == resolved_path) ? */
2133 result = resolved_path;
2136 #endif
2137 END_PROFILE(syscall_realpath);
2138 return result;
2141 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2142 unsigned int flags)
2144 #ifdef HAVE_CHFLAGS
2145 return chflags(path, flags);
2146 #else
2147 errno = ENOSYS;
2148 return -1;
2149 #endif
2152 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2153 const SMB_STRUCT_STAT *sbuf)
2155 struct file_id key;
2157 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2158 * blob */
2159 ZERO_STRUCT(key);
2161 key.devid = sbuf->st_ex_dev;
2162 key.inode = sbuf->st_ex_ino;
2163 /* key.extid is unused by default. */
2165 return key;
2168 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2169 struct files_struct *fsp,
2170 const char *fname,
2171 TALLOC_CTX *mem_ctx,
2172 unsigned int *pnum_streams,
2173 struct stream_struct **pstreams)
2175 SMB_STRUCT_STAT sbuf;
2176 struct stream_struct *tmp_streams = NULL;
2177 int ret;
2179 if ((fsp != NULL) && (fsp->is_directory)) {
2181 * No default streams on directories
2183 goto done;
2186 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2187 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2189 else {
2190 struct smb_filename smb_fname;
2192 ZERO_STRUCT(smb_fname);
2193 smb_fname.base_name = discard_const_p(char, fname);
2195 if (lp_posix_pathnames()) {
2196 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2197 } else {
2198 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2200 sbuf = smb_fname.st;
2203 if (ret == -1) {
2204 return map_nt_error_from_unix(errno);
2207 if (S_ISDIR(sbuf.st_ex_mode)) {
2208 goto done;
2211 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2212 (*pnum_streams) + 1);
2213 if (tmp_streams == NULL) {
2214 return NT_STATUS_NO_MEMORY;
2216 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2217 if (tmp_streams[*pnum_streams].name == NULL) {
2218 return NT_STATUS_NO_MEMORY;
2220 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2221 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2223 *pnum_streams += 1;
2224 *pstreams = tmp_streams;
2225 done:
2226 return NT_STATUS_OK;
2229 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2230 const char *path,
2231 const char *name,
2232 TALLOC_CTX *mem_ctx,
2233 char **found_name)
2236 * Don't fall back to get_real_filename so callers can differentiate
2237 * between a full directory scan and an actual case-insensitive stat.
2239 errno = EOPNOTSUPP;
2240 return -1;
2243 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2244 const char *fname)
2246 return handle->conn->connectpath;
2249 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2250 struct byte_range_lock *br_lck,
2251 struct lock_struct *plock,
2252 bool blocking_lock)
2254 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2256 /* Note: blr is not used in the default implementation. */
2257 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2260 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2261 struct messaging_context *msg_ctx,
2262 struct byte_range_lock *br_lck,
2263 const struct lock_struct *plock)
2265 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2267 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2270 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2271 struct byte_range_lock *br_lck,
2272 struct lock_struct *plock)
2274 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2276 /* Note: blr is not used in the default implementation. */
2277 return brl_lock_cancel_default(br_lck, plock);
2280 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2281 files_struct *fsp,
2282 struct lock_struct *plock)
2284 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2285 plock->lock_type == WRITE_LOCK);
2287 return strict_lock_default(fsp, plock);
2290 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2291 files_struct *fsp,
2292 struct lock_struct *plock)
2294 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2295 plock->lock_type == WRITE_LOCK);
2297 strict_unlock_default(fsp, plock);
2300 /* NT ACL operations. */
2302 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2303 files_struct *fsp,
2304 uint32_t security_info,
2305 TALLOC_CTX *mem_ctx,
2306 struct security_descriptor **ppdesc)
2308 NTSTATUS result;
2310 START_PROFILE(fget_nt_acl);
2311 result = posix_fget_nt_acl(fsp, security_info,
2312 mem_ctx, ppdesc);
2313 END_PROFILE(fget_nt_acl);
2314 return result;
2317 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2318 const char *name,
2319 uint32_t security_info,
2320 TALLOC_CTX *mem_ctx,
2321 struct security_descriptor **ppdesc)
2323 NTSTATUS result;
2325 START_PROFILE(get_nt_acl);
2326 result = posix_get_nt_acl(handle->conn, name, security_info,
2327 mem_ctx, ppdesc);
2328 END_PROFILE(get_nt_acl);
2329 return result;
2332 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2334 NTSTATUS result;
2336 START_PROFILE(fset_nt_acl);
2337 result = set_nt_acl(fsp, security_info_sent, psd);
2338 END_PROFILE(fset_nt_acl);
2339 return result;
2342 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2343 struct smb_filename *file,
2344 struct security_acl *sacl,
2345 uint32_t access_requested,
2346 uint32_t access_denied)
2348 return NT_STATUS_OK; /* Nothing to do here ... */
2351 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2353 #ifdef HAVE_NO_ACL
2354 errno = ENOSYS;
2355 return -1;
2356 #else
2357 int result;
2359 START_PROFILE(chmod_acl);
2360 result = chmod_acl(handle->conn, name, mode);
2361 END_PROFILE(chmod_acl);
2362 return result;
2363 #endif
2366 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2368 #ifdef HAVE_NO_ACL
2369 errno = ENOSYS;
2370 return -1;
2371 #else
2372 int result;
2374 START_PROFILE(fchmod_acl);
2375 result = fchmod_acl(fsp, mode);
2376 END_PROFILE(fchmod_acl);
2377 return result;
2378 #endif
2381 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2382 const char *path_p,
2383 SMB_ACL_TYPE_T type,
2384 TALLOC_CTX *mem_ctx)
2386 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2389 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2390 files_struct *fsp,
2391 TALLOC_CTX *mem_ctx)
2393 return sys_acl_get_fd(handle, fsp, mem_ctx);
2396 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2398 return sys_acl_set_file(handle, name, acltype, theacl);
2401 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2403 return sys_acl_set_fd(handle, fsp, theacl);
2406 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2408 return sys_acl_delete_def_file(handle, path);
2411 /****************************************************************
2412 Extended attribute operations.
2413 *****************************************************************/
2415 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2417 return getxattr(path, name, value, size);
2420 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2422 return fgetxattr(fsp->fh->fd, name, value, size);
2425 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2427 return listxattr(path, list, size);
2430 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2432 return flistxattr(fsp->fh->fd, list, size);
2435 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2437 return removexattr(path, name);
2440 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2442 return fremovexattr(fsp->fh->fd, name);
2445 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2447 return setxattr(path, name, value, size, flags);
2450 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2452 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2455 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2457 return false;
2460 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2461 const struct smb_filename *fname,
2462 SMB_STRUCT_STAT *sbuf)
2464 NTSTATUS status;
2465 char *path;
2466 bool offline = false;
2468 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2469 return false;
2472 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2473 #if defined(ENOTSUP)
2474 errno = ENOTSUP;
2475 #endif
2476 return false;
2479 status = get_full_smb_filename(talloc_tos(), fname, &path);
2480 if (!NT_STATUS_IS_OK(status)) {
2481 errno = map_errno_from_nt_status(status);
2482 return false;
2485 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2487 TALLOC_FREE(path);
2489 return offline;
2492 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2493 const struct smb_filename *fname)
2495 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2496 #if defined(ENOTSUP)
2497 errno = ENOTSUP;
2498 #endif
2499 return -1;
2502 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2503 struct files_struct *fsp,
2504 TALLOC_CTX *mem_ctx,
2505 DATA_BLOB *cookie)
2507 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2510 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2511 struct files_struct *fsp,
2512 const DATA_BLOB old_cookie,
2513 TALLOC_CTX *mem_ctx,
2514 DATA_BLOB *new_cookie)
2516 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2517 new_cookie);
2520 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2521 struct smb_request *smb1req,
2522 struct smbXsrv_open *op,
2523 const DATA_BLOB old_cookie,
2524 TALLOC_CTX *mem_ctx,
2525 struct files_struct **fsp,
2526 DATA_BLOB *new_cookie)
2528 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2529 old_cookie, mem_ctx,
2530 fsp, new_cookie);
2533 static struct vfs_fn_pointers vfs_default_fns = {
2534 /* Disk operations */
2536 .connect_fn = vfswrap_connect,
2537 .disconnect_fn = vfswrap_disconnect,
2538 .disk_free_fn = vfswrap_disk_free,
2539 .get_quota_fn = vfswrap_get_quota,
2540 .set_quota_fn = vfswrap_set_quota,
2541 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2542 .statvfs_fn = vfswrap_statvfs,
2543 .fs_capabilities_fn = vfswrap_fs_capabilities,
2544 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2545 .snap_check_path_fn = vfswrap_snap_check_path,
2546 .snap_create_fn = vfswrap_snap_create,
2547 .snap_delete_fn = vfswrap_snap_delete,
2549 /* Directory operations */
2551 .opendir_fn = vfswrap_opendir,
2552 .fdopendir_fn = vfswrap_fdopendir,
2553 .readdir_fn = vfswrap_readdir,
2554 .readdir_attr_fn = vfswrap_readdir_attr,
2555 .seekdir_fn = vfswrap_seekdir,
2556 .telldir_fn = vfswrap_telldir,
2557 .rewind_dir_fn = vfswrap_rewinddir,
2558 .mkdir_fn = vfswrap_mkdir,
2559 .rmdir_fn = vfswrap_rmdir,
2560 .closedir_fn = vfswrap_closedir,
2561 .init_search_op_fn = vfswrap_init_search_op,
2563 /* File operations */
2565 .open_fn = vfswrap_open,
2566 .create_file_fn = vfswrap_create_file,
2567 .close_fn = vfswrap_close,
2568 .read_fn = vfswrap_read,
2569 .pread_fn = vfswrap_pread,
2570 .pread_send_fn = vfswrap_pread_send,
2571 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2572 .write_fn = vfswrap_write,
2573 .pwrite_fn = vfswrap_pwrite,
2574 .pwrite_send_fn = vfswrap_pwrite_send,
2575 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2576 .lseek_fn = vfswrap_lseek,
2577 .sendfile_fn = vfswrap_sendfile,
2578 .recvfile_fn = vfswrap_recvfile,
2579 .rename_fn = vfswrap_rename,
2580 .fsync_fn = vfswrap_fsync,
2581 .fsync_send_fn = vfswrap_fsync_send,
2582 .fsync_recv_fn = vfswrap_asys_int_recv,
2583 .stat_fn = vfswrap_stat,
2584 .fstat_fn = vfswrap_fstat,
2585 .lstat_fn = vfswrap_lstat,
2586 .get_alloc_size_fn = vfswrap_get_alloc_size,
2587 .unlink_fn = vfswrap_unlink,
2588 .chmod_fn = vfswrap_chmod,
2589 .fchmod_fn = vfswrap_fchmod,
2590 .chown_fn = vfswrap_chown,
2591 .fchown_fn = vfswrap_fchown,
2592 .lchown_fn = vfswrap_lchown,
2593 .chdir_fn = vfswrap_chdir,
2594 .getwd_fn = vfswrap_getwd,
2595 .ntimes_fn = vfswrap_ntimes,
2596 .ftruncate_fn = vfswrap_ftruncate,
2597 .fallocate_fn = vfswrap_fallocate,
2598 .lock_fn = vfswrap_lock,
2599 .kernel_flock_fn = vfswrap_kernel_flock,
2600 .linux_setlease_fn = vfswrap_linux_setlease,
2601 .getlock_fn = vfswrap_getlock,
2602 .symlink_fn = vfswrap_symlink,
2603 .readlink_fn = vfswrap_readlink,
2604 .link_fn = vfswrap_link,
2605 .mknod_fn = vfswrap_mknod,
2606 .realpath_fn = vfswrap_realpath,
2607 .chflags_fn = vfswrap_chflags,
2608 .file_id_create_fn = vfswrap_file_id_create,
2609 .streaminfo_fn = vfswrap_streaminfo,
2610 .get_real_filename_fn = vfswrap_get_real_filename,
2611 .connectpath_fn = vfswrap_connectpath,
2612 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2613 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2614 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2615 .strict_lock_fn = vfswrap_strict_lock,
2616 .strict_unlock_fn = vfswrap_strict_unlock,
2617 .translate_name_fn = vfswrap_translate_name,
2618 .fsctl_fn = vfswrap_fsctl,
2619 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2620 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2621 .get_compression_fn = vfswrap_get_compression,
2622 .set_compression_fn = vfswrap_set_compression,
2624 /* NT ACL operations. */
2626 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2627 .get_nt_acl_fn = vfswrap_get_nt_acl,
2628 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2629 .audit_file_fn = vfswrap_audit_file,
2631 /* POSIX ACL operations. */
2633 .chmod_acl_fn = vfswrap_chmod_acl,
2634 .fchmod_acl_fn = vfswrap_fchmod_acl,
2636 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2637 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2638 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2639 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2640 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2641 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2642 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2644 /* EA operations. */
2645 .getxattr_fn = vfswrap_getxattr,
2646 .fgetxattr_fn = vfswrap_fgetxattr,
2647 .listxattr_fn = vfswrap_listxattr,
2648 .flistxattr_fn = vfswrap_flistxattr,
2649 .removexattr_fn = vfswrap_removexattr,
2650 .fremovexattr_fn = vfswrap_fremovexattr,
2651 .setxattr_fn = vfswrap_setxattr,
2652 .fsetxattr_fn = vfswrap_fsetxattr,
2654 /* aio operations */
2655 .aio_force_fn = vfswrap_aio_force,
2657 /* offline operations */
2658 .is_offline_fn = vfswrap_is_offline,
2659 .set_offline_fn = vfswrap_set_offline,
2661 /* durable handle operations */
2662 .durable_cookie_fn = vfswrap_durable_cookie,
2663 .durable_disconnect_fn = vfswrap_durable_disconnect,
2664 .durable_reconnect_fn = vfswrap_durable_reconnect,
2667 NTSTATUS vfs_default_init(void);
2668 NTSTATUS vfs_default_init(void)
2670 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2671 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);