smbd: Use asys_results
[Samba.git] / source3 / modules / vfs_default.c
blob673ebfe35bf99cefc17257b8d33ea12d069dac7d
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"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_VFS
39 /* Check for NULL pointer parameters in vfswrap_* functions */
41 /* We don't want to have NULL function pointers lying around. Someone
42 is sure to try and execute them. These stubs are used to prevent
43 this possibility. */
45 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
47 return 0; /* Return >= 0 for success */
50 static void vfswrap_disconnect(vfs_handle_struct *handle)
54 /* Disk operations */
56 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
57 uint64_t *dfree, uint64_t *dsize)
59 uint64_t result;
61 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
62 return result;
65 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
67 #ifdef HAVE_SYS_QUOTAS
68 int result;
70 START_PROFILE(syscall_get_quota);
71 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
72 END_PROFILE(syscall_get_quota);
73 return result;
74 #else
75 errno = ENOSYS;
76 return -1;
77 #endif
80 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
82 #ifdef HAVE_SYS_QUOTAS
83 int result;
85 START_PROFILE(syscall_set_quota);
86 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
87 END_PROFILE(syscall_set_quota);
88 return result;
89 #else
90 errno = ENOSYS;
91 return -1;
92 #endif
95 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
96 struct files_struct *fsp,
97 struct shadow_copy_data *shadow_copy_data,
98 bool labels)
100 errno = ENOSYS;
101 return -1; /* Not implemented. */
104 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
106 return sys_statvfs(path, statbuf);
109 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
110 enum timestamp_set_resolution *p_ts_res)
112 connection_struct *conn = handle->conn;
113 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
114 struct smb_filename *smb_fname_cpath = NULL;
115 struct vfs_statvfs_struct statbuf;
116 int ret;
118 ZERO_STRUCT(statbuf);
119 ret = sys_statvfs(conn->connectpath, &statbuf);
120 if (ret == 0) {
121 caps = statbuf.FsCapabilities;
124 *p_ts_res = TIMESTAMP_SET_SECONDS;
126 /* Work out what timestamp resolution we can
127 * use when setting a timestamp. */
129 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
130 NULL, NULL);
131 if (smb_fname_cpath == NULL) {
132 return caps;
135 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
136 if (ret == -1) {
137 TALLOC_FREE(smb_fname_cpath);
138 return caps;
141 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
142 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
144 /* If any of the normal UNIX directory timestamps
145 * have a non-zero tv_nsec component assume
146 * we might be able to set sub-second timestamps.
147 * See what filetime set primitives we have.
149 #if defined(HAVE_UTIMENSAT)
150 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
151 #elif defined(HAVE_UTIMES)
152 /* utimes allows msec timestamps to be set. */
153 *p_ts_res = TIMESTAMP_SET_MSEC;
154 #elif defined(HAVE_UTIME)
155 /* utime only allows sec timestamps to be set. */
156 *p_ts_res = TIMESTAMP_SET_SECONDS;
157 #endif
159 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
160 "resolution of %s "
161 "available on share %s, directory %s\n",
162 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
163 lp_servicename(talloc_tos(), conn->params->service),
164 conn->connectpath ));
166 TALLOC_FREE(smb_fname_cpath);
167 return caps;
170 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
171 struct dfs_GetDFSReferral *r)
173 struct junction_map *junction = NULL;
174 int consumedcnt = 0;
175 bool self_referral = false;
176 char *pathnamep = NULL;
177 char *local_dfs_path = NULL;
178 NTSTATUS status;
179 int i;
180 uint16_t max_referral_level = r->in.req.max_referral_level;
182 if (DEBUGLVL(10)) {
183 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
186 /* get the junction entry */
187 if (r->in.req.servername == NULL) {
188 return NT_STATUS_NOT_FOUND;
192 * Trim pathname sent by client so it begins with only one backslash.
193 * Two backslashes confuse some dfs clients
196 local_dfs_path = talloc_strdup(r, r->in.req.servername);
197 if (local_dfs_path == NULL) {
198 return NT_STATUS_NO_MEMORY;
200 pathnamep = local_dfs_path;
201 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
202 IS_DIRECTORY_SEP(pathnamep[1])) {
203 pathnamep++;
206 junction = talloc_zero(r, struct junction_map);
207 if (junction == NULL) {
208 return NT_STATUS_NO_MEMORY;
211 /* The following call can change cwd. */
212 status = get_referred_path(r, pathnamep,
213 !handle->conn->sconn->using_smb2,
214 junction, &consumedcnt, &self_referral);
215 if (!NT_STATUS_IS_OK(status)) {
216 vfs_ChDir(handle->conn, handle->conn->connectpath);
217 return status;
219 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 if (!self_referral) {
222 pathnamep[consumedcnt] = '\0';
224 if (DEBUGLVL(3)) {
225 dbgtext("setup_dfs_referral: Path %s to "
226 "alternate path(s):",
227 pathnamep);
228 for (i=0; i < junction->referral_count; i++) {
229 dbgtext(" %s",
230 junction->referral_list[i].alternate_path);
232 dbgtext(".\n");
236 if (r->in.req.max_referral_level <= 2) {
237 max_referral_level = 2;
239 if (r->in.req.max_referral_level >= 3) {
240 max_referral_level = 3;
243 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
244 if (r->out.resp == NULL) {
245 return NT_STATUS_NO_MEMORY;
248 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
249 r->out.resp->nb_referrals = junction->referral_count;
251 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
252 if (self_referral) {
253 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
256 r->out.resp->referral_entries = talloc_zero_array(r,
257 struct dfs_referral_type,
258 r->out.resp->nb_referrals);
259 if (r->out.resp->referral_entries == NULL) {
260 return NT_STATUS_NO_MEMORY;
263 switch (max_referral_level) {
264 case 2:
265 for(i=0; i < junction->referral_count; i++) {
266 struct referral *ref = &junction->referral_list[i];
267 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
268 struct dfs_referral_type *t =
269 &r->out.resp->referral_entries[i];
270 struct dfs_referral_v2 *v2 = &t->referral.v2;
272 t->version = 2;
273 v2->size = VERSION2_REFERRAL_SIZE;
274 if (self_referral) {
275 v2->server_type = DFS_SERVER_ROOT;
276 } else {
277 v2->server_type = DFS_SERVER_NON_ROOT;
279 v2->entry_flags = 0;
280 v2->proximity = ref->proximity;
281 v2->ttl = ref->ttl;
282 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
283 if (v2->DFS_path == NULL) {
284 return NT_STATUS_NO_MEMORY;
286 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
287 if (v2->DFS_alt_path == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 v2->netw_address = talloc_strdup(mem_ctx,
291 ref->alternate_path);
292 if (v2->netw_address == NULL) {
293 return NT_STATUS_NO_MEMORY;
297 break;
298 case 3:
299 for(i=0; i < junction->referral_count; i++) {
300 struct referral *ref = &junction->referral_list[i];
301 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302 struct dfs_referral_type *t =
303 &r->out.resp->referral_entries[i];
304 struct dfs_referral_v3 *v3 = &t->referral.v3;
305 struct dfs_normal_referral *r1 = &v3->referrals.r1;
307 t->version = 3;
308 v3->size = VERSION3_REFERRAL_SIZE;
309 if (self_referral) {
310 v3->server_type = DFS_SERVER_ROOT;
311 } else {
312 v3->server_type = DFS_SERVER_NON_ROOT;
314 v3->entry_flags = 0;
315 v3->ttl = ref->ttl;
316 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317 if (r1->DFS_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321 if (r1->DFS_alt_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 r1->netw_address = talloc_strdup(mem_ctx,
325 ref->alternate_path);
326 if (r1->netw_address == NULL) {
327 return NT_STATUS_NO_MEMORY;
330 break;
331 default:
332 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
333 "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 /* Directory operations */
347 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
349 DIR *result;
351 START_PROFILE(syscall_opendir);
352 result = opendir(fname);
353 END_PROFILE(syscall_opendir);
354 return result;
357 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
358 files_struct *fsp,
359 const char *mask,
360 uint32 attr)
362 DIR *result;
364 START_PROFILE(syscall_fdopendir);
365 result = sys_fdopendir(fsp->fh->fd);
366 END_PROFILE(syscall_fdopendir);
367 return result;
371 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
372 DIR *dirp,
373 SMB_STRUCT_STAT *sbuf)
375 struct dirent *result;
377 START_PROFILE(syscall_readdir);
378 result = readdir(dirp);
379 END_PROFILE(syscall_readdir);
380 if (sbuf) {
381 /* Default Posix readdir() does not give us stat info.
382 * Set to invalid to indicate we didn't return this info. */
383 SET_STAT_INVALID(*sbuf);
384 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
385 if (result != NULL) {
386 /* See if we can efficiently return this. */
387 struct stat st;
388 int flags = (lp_posix_pathnames() ?
389 AT_SYMLINK_NOFOLLOW : 0);
390 int ret = fstatat(dirfd(dirp),
391 result->d_name,
392 &st,
393 flags);
394 if (ret == 0) {
395 init_stat_ex_from_stat(sbuf,
396 &st,
397 lp_fake_directory_create_times(
398 SNUM(handle->conn)));
401 #endif
403 return result;
406 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
408 START_PROFILE(syscall_seekdir);
409 seekdir(dirp, offset);
410 END_PROFILE(syscall_seekdir);
413 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
415 long result;
416 START_PROFILE(syscall_telldir);
417 result = telldir(dirp);
418 END_PROFILE(syscall_telldir);
419 return result;
422 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
424 START_PROFILE(syscall_rewinddir);
425 rewinddir(dirp);
426 END_PROFILE(syscall_rewinddir);
429 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
431 int result;
432 bool has_dacl = False;
433 char *parent = NULL;
435 START_PROFILE(syscall_mkdir);
437 if (lp_inherit_acls(SNUM(handle->conn))
438 && parent_dirname(talloc_tos(), path, &parent, NULL)
439 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
440 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
442 TALLOC_FREE(parent);
444 result = mkdir(path, mode);
446 if (result == 0 && !has_dacl) {
448 * We need to do this as the default behavior of POSIX ACLs
449 * is to set the mask to be the requested group permission
450 * bits, not the group permission bits to be the requested
451 * group permission bits. This is not what we want, as it will
452 * mess up any inherited ACL bits that were set. JRA.
454 int saved_errno = errno; /* We may get ENOSYS */
455 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
456 errno = saved_errno;
459 END_PROFILE(syscall_mkdir);
460 return result;
463 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
465 int result;
467 START_PROFILE(syscall_rmdir);
468 result = rmdir(path);
469 END_PROFILE(syscall_rmdir);
470 return result;
473 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
475 int result;
477 START_PROFILE(syscall_closedir);
478 result = closedir(dirp);
479 END_PROFILE(syscall_closedir);
480 return result;
483 static void vfswrap_init_search_op(vfs_handle_struct *handle,
484 DIR *dirp)
486 /* Default behavior is a NOOP */
489 /* File operations */
491 static int vfswrap_open(vfs_handle_struct *handle,
492 struct smb_filename *smb_fname,
493 files_struct *fsp, int flags, mode_t mode)
495 int result = -1;
497 START_PROFILE(syscall_open);
499 if (smb_fname->stream_name) {
500 errno = ENOENT;
501 goto out;
504 result = open(smb_fname->base_name, flags, mode);
505 out:
506 END_PROFILE(syscall_open);
507 return result;
510 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
511 struct smb_request *req,
512 uint16_t root_dir_fid,
513 struct smb_filename *smb_fname,
514 uint32_t access_mask,
515 uint32_t share_access,
516 uint32_t create_disposition,
517 uint32_t create_options,
518 uint32_t file_attributes,
519 uint32_t oplock_request,
520 uint64_t allocation_size,
521 uint32_t private_flags,
522 struct security_descriptor *sd,
523 struct ea_list *ea_list,
524 files_struct **result,
525 int *pinfo)
527 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
528 access_mask, share_access,
529 create_disposition, create_options,
530 file_attributes, oplock_request,
531 allocation_size, private_flags,
532 sd, ea_list, result,
533 pinfo);
536 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
538 int result;
540 START_PROFILE(syscall_close);
541 result = fd_close_posix(fsp);
542 END_PROFILE(syscall_close);
543 return result;
546 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
548 ssize_t result;
550 START_PROFILE_BYTES(syscall_read, n);
551 result = sys_read(fsp->fh->fd, data, n);
552 END_PROFILE(syscall_read);
553 return result;
556 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
557 size_t n, off_t offset)
559 ssize_t result;
561 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
562 START_PROFILE_BYTES(syscall_pread, n);
563 result = sys_pread(fsp->fh->fd, data, n, offset);
564 END_PROFILE(syscall_pread);
566 if (result == -1 && errno == ESPIPE) {
567 /* Maintain the fiction that pipes can be seeked (sought?) on. */
568 result = SMB_VFS_READ(fsp, data, n);
569 fsp->fh->pos = 0;
572 #else /* HAVE_PREAD */
573 off_t curr;
574 int lerrno;
576 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
577 if (curr == -1 && errno == ESPIPE) {
578 /* Maintain the fiction that pipes can be seeked (sought?) on. */
579 result = SMB_VFS_READ(fsp, data, n);
580 fsp->fh->pos = 0;
581 return result;
584 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
585 return -1;
588 errno = 0;
589 result = SMB_VFS_READ(fsp, data, n);
590 lerrno = errno;
592 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
593 errno = lerrno;
595 #endif /* HAVE_PREAD */
597 return result;
600 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
602 ssize_t result;
604 START_PROFILE_BYTES(syscall_write, n);
605 result = sys_write(fsp->fh->fd, data, n);
606 END_PROFILE(syscall_write);
607 return result;
610 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
611 size_t n, off_t offset)
613 ssize_t result;
615 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
616 START_PROFILE_BYTES(syscall_pwrite, n);
617 result = sys_pwrite(fsp->fh->fd, data, n, offset);
618 END_PROFILE(syscall_pwrite);
620 if (result == -1 && errno == ESPIPE) {
621 /* Maintain the fiction that pipes can be sought on. */
622 result = SMB_VFS_WRITE(fsp, data, n);
625 #else /* HAVE_PWRITE */
626 off_t curr;
627 int lerrno;
629 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
630 if (curr == -1) {
631 return -1;
634 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
635 return -1;
638 result = SMB_VFS_WRITE(fsp, data, n);
639 lerrno = errno;
641 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
642 errno = lerrno;
644 #endif /* HAVE_PWRITE */
646 return result;
649 static void vfswrap_asys_finished(struct tevent_context *ev,
650 struct tevent_fd *fde,
651 uint16_t flags, void *p);
653 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
655 int ret;
656 int fd;
658 if (conn->asys_ctx != NULL) {
659 return true;
661 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
662 if (ret != 0) {
663 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
664 return false;
667 fd = asys_signalfd(conn->asys_ctx);
669 set_blocking(fd, false);
671 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
672 TEVENT_FD_READ,
673 vfswrap_asys_finished,
674 conn->asys_ctx);
675 if (conn->asys_fde == NULL) {
676 DEBUG(1, ("tevent_add_fd failed\n"));
677 asys_context_destroy(conn->asys_ctx);
678 conn->asys_ctx = NULL;
679 return false;
681 return true;
684 struct vfswrap_asys_state {
685 struct asys_context *asys_ctx;
686 struct tevent_req *req;
687 ssize_t ret;
688 int err;
691 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
693 asys_cancel(s->asys_ctx, s->req);
694 return 0;
697 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
698 TALLOC_CTX *mem_ctx,
699 struct tevent_context *ev,
700 struct files_struct *fsp,
701 void *data,
702 size_t n, off_t offset)
704 struct tevent_req *req;
705 struct vfswrap_asys_state *state;
706 int ret;
708 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
709 if (req == NULL) {
710 return NULL;
712 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
713 tevent_req_oom(req);
714 return tevent_req_post(req, ev);
716 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
717 state->req = req;
719 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
720 if (ret != 0) {
721 tevent_req_error(req, ret);
722 return tevent_req_post(req, ev);
724 talloc_set_destructor(state, vfswrap_asys_state_destructor);
726 return req;
729 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
730 TALLOC_CTX *mem_ctx,
731 struct tevent_context *ev,
732 struct files_struct *fsp,
733 const void *data,
734 size_t n, off_t offset)
736 struct tevent_req *req;
737 struct vfswrap_asys_state *state;
738 int ret;
740 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
741 if (req == NULL) {
742 return NULL;
744 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
745 tevent_req_oom(req);
746 return tevent_req_post(req, ev);
748 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
749 state->req = req;
751 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
752 if (ret != 0) {
753 tevent_req_error(req, ret);
754 return tevent_req_post(req, ev);
756 talloc_set_destructor(state, vfswrap_asys_state_destructor);
758 return req;
761 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
762 TALLOC_CTX *mem_ctx,
763 struct tevent_context *ev,
764 struct files_struct *fsp)
766 struct tevent_req *req;
767 struct vfswrap_asys_state *state;
768 int ret;
770 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
771 if (req == NULL) {
772 return NULL;
774 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
775 tevent_req_oom(req);
776 return tevent_req_post(req, ev);
778 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
779 state->req = req;
781 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
782 if (ret != 0) {
783 tevent_req_error(req, ret);
784 return tevent_req_post(req, ev);
786 talloc_set_destructor(state, vfswrap_asys_state_destructor);
788 return req;
791 static void vfswrap_asys_finished(struct tevent_context *ev,
792 struct tevent_fd *fde,
793 uint16_t flags, void *p)
795 struct asys_context *asys_ctx = (struct asys_context *)p;
796 struct asys_result results[outstanding_aio_calls];
797 int i, ret;
799 if ((flags & TEVENT_FD_READ) == 0) {
800 return;
803 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
804 if (ret < 0) {
805 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
806 return;
809 for (i=0; i<ret; i++) {
810 struct asys_result *result = &results[i];
811 struct tevent_req *req;
812 struct vfswrap_asys_state *state;
814 if ((result->ret == -1) && (result->err == ECANCELED)) {
815 continue;
818 req = talloc_get_type_abort(result->private_data,
819 struct tevent_req);
820 state = tevent_req_data(req, struct vfswrap_asys_state);
822 talloc_set_destructor(state, NULL);
824 state->ret = result->ret;
825 state->err = result->err;
826 tevent_req_defer_callback(req, ev);
827 tevent_req_done(req);
831 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
833 struct vfswrap_asys_state *state = tevent_req_data(
834 req, struct vfswrap_asys_state);
836 if (tevent_req_is_unix_error(req, err)) {
837 return -1;
839 *err = state->err;
840 return state->ret;
843 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
845 struct vfswrap_asys_state *state = tevent_req_data(
846 req, struct vfswrap_asys_state);
848 if (tevent_req_is_unix_error(req, err)) {
849 return -1;
851 *err = state->err;
852 return state->ret;
855 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
857 off_t result = 0;
859 START_PROFILE(syscall_lseek);
861 /* Cope with 'stat' file opens. */
862 if (fsp->fh->fd != -1)
863 result = lseek(fsp->fh->fd, offset, whence);
866 * We want to maintain the fiction that we can seek
867 * on a fifo for file system purposes. This allows
868 * people to set up UNIX fifo's that feed data to Windows
869 * applications. JRA.
872 if((result == -1) && (errno == ESPIPE)) {
873 result = 0;
874 errno = 0;
877 END_PROFILE(syscall_lseek);
878 return result;
881 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
882 off_t offset, size_t n)
884 ssize_t result;
886 START_PROFILE_BYTES(syscall_sendfile, n);
887 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
888 END_PROFILE(syscall_sendfile);
889 return result;
892 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
893 int fromfd,
894 files_struct *tofsp,
895 off_t offset,
896 size_t n)
898 ssize_t result;
900 START_PROFILE_BYTES(syscall_recvfile, n);
901 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
902 END_PROFILE(syscall_recvfile);
903 return result;
906 static int vfswrap_rename(vfs_handle_struct *handle,
907 const struct smb_filename *smb_fname_src,
908 const struct smb_filename *smb_fname_dst)
910 int result = -1;
912 START_PROFILE(syscall_rename);
914 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
915 errno = ENOENT;
916 goto out;
919 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
921 out:
922 END_PROFILE(syscall_rename);
923 return result;
926 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
928 #ifdef HAVE_FSYNC
929 int result;
931 START_PROFILE(syscall_fsync);
932 result = fsync(fsp->fh->fd);
933 END_PROFILE(syscall_fsync);
934 return result;
935 #else
936 return 0;
937 #endif
940 static int vfswrap_stat(vfs_handle_struct *handle,
941 struct smb_filename *smb_fname)
943 int result = -1;
945 START_PROFILE(syscall_stat);
947 if (smb_fname->stream_name) {
948 errno = ENOENT;
949 goto out;
952 result = sys_stat(smb_fname->base_name, &smb_fname->st,
953 lp_fake_directory_create_times(SNUM(handle->conn)));
954 out:
955 END_PROFILE(syscall_stat);
956 return result;
959 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
961 int result;
963 START_PROFILE(syscall_fstat);
964 result = sys_fstat(fsp->fh->fd,
965 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
966 END_PROFILE(syscall_fstat);
967 return result;
970 static int vfswrap_lstat(vfs_handle_struct *handle,
971 struct smb_filename *smb_fname)
973 int result = -1;
975 START_PROFILE(syscall_lstat);
977 if (smb_fname->stream_name) {
978 errno = ENOENT;
979 goto out;
982 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
983 lp_fake_directory_create_times(SNUM(handle->conn)));
984 out:
985 END_PROFILE(syscall_lstat);
986 return result;
989 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
990 const char *name,
991 enum vfs_translate_direction direction,
992 TALLOC_CTX *mem_ctx,
993 char **mapped_name)
995 return NT_STATUS_NONE_MAPPED;
999 * Implement the default fsctl operation.
1001 static bool vfswrap_logged_ioctl_message = false;
1003 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1004 struct files_struct *fsp,
1005 TALLOC_CTX *ctx,
1006 uint32_t function,
1007 uint16_t req_flags, /* Needed for UNICODE ... */
1008 const uint8_t *_in_data,
1009 uint32_t in_len,
1010 uint8_t **_out_data,
1011 uint32_t max_out_len,
1012 uint32_t *out_len)
1014 const char *in_data = (const char *)_in_data;
1015 char **out_data = (char **)_out_data;
1016 NTSTATUS status;
1018 switch (function) {
1019 case FSCTL_SET_SPARSE:
1021 bool set_sparse = true;
1023 if (in_len >= 1 && in_data[0] == 0) {
1024 set_sparse = false;
1027 status = file_set_sparse(handle->conn, fsp, set_sparse);
1029 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1030 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1031 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1032 nt_errstr(status)));
1034 return status;
1037 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1039 unsigned char objid[16];
1040 char *return_data = NULL;
1042 /* This should return the object-id on this file.
1043 * I think I'll make this be the inode+dev. JRA.
1046 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1047 fsp_fnum_dbg(fsp)));
1049 *out_len = MIN(max_out_len, 64);
1051 /* Hmmm, will this cause problems if less data asked for? */
1052 return_data = talloc_array(ctx, char, 64);
1053 if (return_data == NULL) {
1054 return NT_STATUS_NO_MEMORY;
1057 /* For backwards compatibility only store the dev/inode. */
1058 push_file_id_16(return_data, &fsp->file_id);
1059 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1060 push_file_id_16(return_data+32, &fsp->file_id);
1061 memset(return_data+48, 0, 16);
1062 *out_data = return_data;
1063 return NT_STATUS_OK;
1066 case FSCTL_GET_REPARSE_POINT:
1068 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1069 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1070 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1071 return NT_STATUS_NOT_A_REPARSE_POINT;
1074 case FSCTL_SET_REPARSE_POINT:
1076 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1077 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1078 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1079 return NT_STATUS_NOT_A_REPARSE_POINT;
1082 case FSCTL_GET_SHADOW_COPY_DATA:
1085 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1086 * and return their volume names. If max_data_count is 16, then it is just
1087 * asking for the number of volumes and length of the combined names.
1089 * pdata is the data allocated by our caller, but that uses
1090 * total_data_count (which is 0 in our case) rather than max_data_count.
1091 * Allocate the correct amount and return the pointer to let
1092 * it be deallocated when we return.
1094 struct shadow_copy_data *shadow_data = NULL;
1095 bool labels = False;
1096 uint32 labels_data_count = 0;
1097 uint32 i;
1098 char *cur_pdata = NULL;
1100 if (max_out_len < 16) {
1101 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1102 max_out_len));
1103 return NT_STATUS_INVALID_PARAMETER;
1106 if (max_out_len > 16) {
1107 labels = True;
1110 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1111 if (shadow_data == NULL) {
1112 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1113 return NT_STATUS_NO_MEMORY;
1117 * Call the VFS routine to actually do the work.
1119 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1120 int log_lev = 0;
1121 if (errno == 0) {
1122 /* broken module didn't set errno on error */
1123 status = NT_STATUS_UNSUCCESSFUL;
1124 } else {
1125 status = map_nt_error_from_unix(errno);
1126 if (NT_STATUS_EQUAL(status,
1127 NT_STATUS_NOT_SUPPORTED)) {
1128 log_lev = 5;
1131 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1132 "connectpath %s, failed - %s.\n",
1133 fsp->conn->connectpath,
1134 nt_errstr(status)));
1135 TALLOC_FREE(shadow_data);
1136 return status;
1139 labels_data_count = (shadow_data->num_volumes * 2 *
1140 sizeof(SHADOW_COPY_LABEL)) + 2;
1142 if (!labels) {
1143 *out_len = 16;
1144 } else {
1145 *out_len = 12 + labels_data_count;
1148 if (max_out_len < *out_len) {
1149 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1150 max_out_len, *out_len));
1151 TALLOC_FREE(shadow_data);
1152 return NT_STATUS_BUFFER_TOO_SMALL;
1155 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1156 if (cur_pdata == NULL) {
1157 TALLOC_FREE(shadow_data);
1158 return NT_STATUS_NO_MEMORY;
1161 *out_data = cur_pdata;
1163 /* num_volumes 4 bytes */
1164 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1166 if (labels) {
1167 /* num_labels 4 bytes */
1168 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1171 /* needed_data_count 4 bytes */
1172 SIVAL(cur_pdata, 8, labels_data_count);
1174 cur_pdata += 12;
1176 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1177 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1178 if (labels && shadow_data->labels) {
1179 for (i=0; i<shadow_data->num_volumes; i++) {
1180 srvstr_push(cur_pdata, req_flags,
1181 cur_pdata, shadow_data->labels[i],
1182 2 * sizeof(SHADOW_COPY_LABEL),
1183 STR_UNICODE|STR_TERMINATE);
1184 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1185 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1189 TALLOC_FREE(shadow_data);
1191 return NT_STATUS_OK;
1194 case FSCTL_FIND_FILES_BY_SID:
1196 /* pretend this succeeded -
1198 * we have to send back a list with all files owned by this SID
1200 * but I have to check that --metze
1202 struct dom_sid sid;
1203 uid_t uid;
1204 size_t sid_len;
1206 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1207 fsp_fnum_dbg(fsp)));
1209 if (in_len < 8) {
1210 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1211 return NT_STATUS_INVALID_PARAMETER;
1214 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1216 /* unknown 4 bytes: this is not the length of the sid :-( */
1217 /*unknown = IVAL(pdata,0);*/
1219 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1220 return NT_STATUS_INVALID_PARAMETER;
1222 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1224 if (!sid_to_uid(&sid, &uid)) {
1225 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1226 sid_string_dbg(&sid),
1227 (unsigned long)sid_len));
1228 uid = (-1);
1231 /* we can take a look at the find source :-)
1233 * find ./ -uid $uid -name '*' is what we need here
1236 * and send 4bytes len and then NULL terminated unicode strings
1237 * for each file
1239 * but I don't know how to deal with the paged results
1240 * (maybe we can hang the result anywhere in the fsp struct)
1242 * but I don't know how to deal with the paged results
1243 * (maybe we can hang the result anywhere in the fsp struct)
1245 * we don't send all files at once
1246 * and at the next we should *not* start from the beginning,
1247 * so we have to cache the result
1249 * --metze
1252 /* this works for now... */
1253 return NT_STATUS_OK;
1256 case FSCTL_QUERY_ALLOCATED_RANGES:
1258 /* FIXME: This is just a dummy reply, telling that all of the
1259 * file is allocated. MKS cp needs that.
1260 * Adding the real allocated ranges via FIEMAP on Linux
1261 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1262 * this FSCTL correct for sparse files.
1264 uint64_t offset, length;
1265 char *out_data_tmp = NULL;
1267 if (in_len != 16) {
1268 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1269 in_len));
1270 return NT_STATUS_INVALID_PARAMETER;
1273 if (max_out_len < 16) {
1274 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1275 max_out_len));
1276 return NT_STATUS_INVALID_PARAMETER;
1279 offset = BVAL(in_data,0);
1280 length = BVAL(in_data,8);
1282 if (offset + length < offset) {
1283 /* No 64-bit integer wrap. */
1284 return NT_STATUS_INVALID_PARAMETER;
1287 /* Shouldn't this be SMB_VFS_STAT ... ? */
1288 status = vfs_stat_fsp(fsp);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 return status;
1293 *out_len = 16;
1294 out_data_tmp = talloc_array(ctx, char, *out_len);
1295 if (out_data_tmp == NULL) {
1296 DEBUG(10, ("unable to allocate memory for response\n"));
1297 return NT_STATUS_NO_MEMORY;
1300 if (offset > fsp->fsp_name->st.st_ex_size ||
1301 fsp->fsp_name->st.st_ex_size == 0 ||
1302 length == 0) {
1303 memset(out_data_tmp, 0, *out_len);
1304 } else {
1305 uint64_t end = offset + length;
1306 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1307 SBVAL(out_data_tmp, 0, 0);
1308 SBVAL(out_data_tmp, 8, end);
1311 *out_data = out_data_tmp;
1313 return NT_STATUS_OK;
1316 case FSCTL_IS_VOLUME_DIRTY:
1318 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1319 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1321 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1322 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1324 return NT_STATUS_INVALID_PARAMETER;
1327 default:
1329 * Only print once ... unfortunately there could be lots of
1330 * different FSCTLs that are called.
1332 if (!vfswrap_logged_ioctl_message) {
1333 vfswrap_logged_ioctl_message = true;
1334 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1335 __func__, function));
1339 return NT_STATUS_NOT_SUPPORTED;
1342 struct vfs_cc_state {
1343 off_t copied;
1344 uint8_t buf[65536];
1347 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1348 TALLOC_CTX *mem_ctx,
1349 struct tevent_context *ev,
1350 struct files_struct *src_fsp,
1351 off_t src_off,
1352 struct files_struct *dest_fsp,
1353 off_t dest_off,
1354 off_t num)
1356 struct tevent_req *req;
1357 struct vfs_cc_state *vfs_cc_state;
1358 NTSTATUS status;
1360 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1361 (unsigned long)num));
1363 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1364 if (req == NULL) {
1365 return NULL;
1368 status = vfs_stat_fsp(src_fsp);
1369 if (tevent_req_nterror(req, status)) {
1370 return tevent_req_post(req, ev);
1373 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1375 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1376 * If the SourceOffset or SourceOffset + Length extends beyond
1377 * the end of file, the server SHOULD<240> treat this as a
1378 * STATUS_END_OF_FILE error.
1379 * ...
1380 * <240> Section 3.3.5.15.6: Windows servers will return
1381 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1383 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1384 return tevent_req_post(req, ev);
1387 /* could use 2.6.33+ sendfile here to do this in kernel */
1388 while (vfs_cc_state->copied < num) {
1389 ssize_t ret;
1390 struct lock_struct lck;
1391 int saved_errno;
1393 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1394 num - vfs_cc_state->copied);
1396 init_strict_lock_struct(src_fsp,
1397 src_fsp->op->global->open_persistent_id,
1398 src_off,
1399 this_num,
1400 READ_LOCK,
1401 &lck);
1403 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1404 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1405 return tevent_req_post(req, ev);
1408 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1409 this_num, src_off);
1410 if (ret == -1) {
1411 saved_errno = errno;
1414 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1416 if (ret == -1) {
1417 errno = saved_errno;
1418 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1419 return tevent_req_post(req, ev);
1421 if (ret != this_num) {
1422 /* zero tolerance for short reads */
1423 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1424 return tevent_req_post(req, ev);
1427 src_off += ret;
1429 init_strict_lock_struct(dest_fsp,
1430 dest_fsp->op->global->open_persistent_id,
1431 dest_off,
1432 this_num,
1433 WRITE_LOCK,
1434 &lck);
1436 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1437 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1438 return tevent_req_post(req, ev);
1441 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1442 this_num, dest_off);
1443 if (ret == -1) {
1444 saved_errno = errno;
1447 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1449 if (ret == -1) {
1450 errno = saved_errno;
1451 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1452 return tevent_req_post(req, ev);
1454 if (ret != this_num) {
1455 /* zero tolerance for short writes */
1456 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1457 return tevent_req_post(req, ev);
1459 dest_off += ret;
1461 vfs_cc_state->copied += this_num;
1464 tevent_req_done(req);
1465 return tevent_req_post(req, ev);
1468 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1469 struct tevent_req *req,
1470 off_t *copied)
1472 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1473 struct vfs_cc_state);
1474 NTSTATUS status;
1476 if (tevent_req_is_nterror(req, &status)) {
1477 DEBUG(2, ("server side copy chunk failed: %s\n",
1478 nt_errstr(status)));
1479 *copied = 0;
1480 tevent_req_received(req);
1481 return status;
1484 *copied = vfs_cc_state->copied;
1485 DEBUG(10, ("server side copy chunk copied %lu\n",
1486 (unsigned long)*copied));
1487 tevent_req_received(req);
1489 return NT_STATUS_OK;
1492 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1493 TALLOC_CTX *mem_ctx,
1494 struct files_struct *fsp,
1495 struct smb_filename *smb_fname,
1496 uint16_t *_compression_fmt)
1498 return NT_STATUS_INVALID_DEVICE_REQUEST;
1501 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1502 TALLOC_CTX *mem_ctx,
1503 struct files_struct *fsp,
1504 uint16_t compression_fmt)
1506 return NT_STATUS_INVALID_DEVICE_REQUEST;
1509 /********************************************************************
1510 Given a stat buffer return the allocated size on disk, taking into
1511 account sparse files.
1512 ********************************************************************/
1513 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1514 struct files_struct *fsp,
1515 const SMB_STRUCT_STAT *sbuf)
1517 uint64_t result;
1519 START_PROFILE(syscall_get_alloc_size);
1521 if(S_ISDIR(sbuf->st_ex_mode)) {
1522 result = 0;
1523 goto out;
1526 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1527 /* The type of st_blocksize is blkcnt_t which *MUST* be
1528 signed (according to POSIX) and can be less than 64-bits.
1529 Ensure when we're converting to 64 bits wide we don't
1530 sign extend. */
1531 #if defined(SIZEOF_BLKCNT_T_8)
1532 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1533 #elif defined(SIZEOF_BLKCNT_T_4)
1535 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1536 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1538 #else
1539 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1540 #endif
1541 #else
1542 result = get_file_size_stat(sbuf);
1543 #endif
1545 if (fsp && fsp->initial_allocation_size)
1546 result = MAX(result,fsp->initial_allocation_size);
1548 result = smb_roundup(handle->conn, result);
1550 out:
1551 END_PROFILE(syscall_get_alloc_size);
1552 return result;
1555 static int vfswrap_unlink(vfs_handle_struct *handle,
1556 const struct smb_filename *smb_fname)
1558 int result = -1;
1560 START_PROFILE(syscall_unlink);
1562 if (smb_fname->stream_name) {
1563 errno = ENOENT;
1564 goto out;
1566 result = unlink(smb_fname->base_name);
1568 out:
1569 END_PROFILE(syscall_unlink);
1570 return result;
1573 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1575 int result;
1577 START_PROFILE(syscall_chmod);
1580 * We need to do this due to the fact that the default POSIX ACL
1581 * chmod modifies the ACL *mask* for the group owner, not the
1582 * group owner bits directly. JRA.
1587 int saved_errno = errno; /* We might get ENOSYS */
1588 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1589 END_PROFILE(syscall_chmod);
1590 return result;
1592 /* Error - return the old errno. */
1593 errno = saved_errno;
1596 result = chmod(path, mode);
1597 END_PROFILE(syscall_chmod);
1598 return result;
1601 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1603 int result;
1605 START_PROFILE(syscall_fchmod);
1608 * We need to do this due to the fact that the default POSIX ACL
1609 * chmod modifies the ACL *mask* for the group owner, not the
1610 * group owner bits directly. JRA.
1614 int saved_errno = errno; /* We might get ENOSYS */
1615 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1616 END_PROFILE(syscall_fchmod);
1617 return result;
1619 /* Error - return the old errno. */
1620 errno = saved_errno;
1623 #if defined(HAVE_FCHMOD)
1624 result = fchmod(fsp->fh->fd, mode);
1625 #else
1626 result = -1;
1627 errno = ENOSYS;
1628 #endif
1630 END_PROFILE(syscall_fchmod);
1631 return result;
1634 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1636 int result;
1638 START_PROFILE(syscall_chown);
1639 result = chown(path, uid, gid);
1640 END_PROFILE(syscall_chown);
1641 return result;
1644 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1646 #ifdef HAVE_FCHOWN
1647 int result;
1649 START_PROFILE(syscall_fchown);
1650 result = fchown(fsp->fh->fd, uid, gid);
1651 END_PROFILE(syscall_fchown);
1652 return result;
1653 #else
1654 errno = ENOSYS;
1655 return -1;
1656 #endif
1659 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1661 int result;
1663 START_PROFILE(syscall_lchown);
1664 result = lchown(path, uid, gid);
1665 END_PROFILE(syscall_lchown);
1666 return result;
1669 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1671 int result;
1673 START_PROFILE(syscall_chdir);
1674 result = chdir(path);
1675 END_PROFILE(syscall_chdir);
1676 return result;
1679 static char *vfswrap_getwd(vfs_handle_struct *handle)
1681 char *result;
1683 START_PROFILE(syscall_getwd);
1684 result = sys_getwd();
1685 END_PROFILE(syscall_getwd);
1686 return result;
1689 /*********************************************************************
1690 nsec timestamp resolution call. Convert down to whatever the underlying
1691 system will support.
1692 **********************************************************************/
1694 static int vfswrap_ntimes(vfs_handle_struct *handle,
1695 const struct smb_filename *smb_fname,
1696 struct smb_file_time *ft)
1698 int result = -1;
1700 START_PROFILE(syscall_ntimes);
1702 if (smb_fname->stream_name) {
1703 errno = ENOENT;
1704 goto out;
1707 if (ft != NULL) {
1708 if (null_timespec(ft->atime)) {
1709 ft->atime= smb_fname->st.st_ex_atime;
1712 if (null_timespec(ft->mtime)) {
1713 ft->mtime = smb_fname->st.st_ex_mtime;
1716 if (!null_timespec(ft->create_time)) {
1717 set_create_timespec_ea(handle->conn,
1718 smb_fname,
1719 ft->create_time);
1722 if ((timespec_compare(&ft->atime,
1723 &smb_fname->st.st_ex_atime) == 0) &&
1724 (timespec_compare(&ft->mtime,
1725 &smb_fname->st.st_ex_mtime) == 0)) {
1726 return 0;
1730 #if defined(HAVE_UTIMENSAT)
1731 if (ft != NULL) {
1732 struct timespec ts[2];
1733 ts[0] = ft->atime;
1734 ts[1] = ft->mtime;
1735 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1736 } else {
1737 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1739 if (!((result == -1) && (errno == ENOSYS))) {
1740 goto out;
1742 #endif
1743 #if defined(HAVE_UTIMES)
1744 if (ft != NULL) {
1745 struct timeval tv[2];
1746 tv[0] = convert_timespec_to_timeval(ft->atime);
1747 tv[1] = convert_timespec_to_timeval(ft->mtime);
1748 result = utimes(smb_fname->base_name, tv);
1749 } else {
1750 result = utimes(smb_fname->base_name, NULL);
1752 if (!((result == -1) && (errno == ENOSYS))) {
1753 goto out;
1755 #endif
1756 #if defined(HAVE_UTIME)
1757 if (ft != NULL) {
1758 struct utimbuf times;
1759 times.actime = convert_timespec_to_time_t(ft->atime);
1760 times.modtime = convert_timespec_to_time_t(ft->mtime);
1761 result = utime(smb_fname->base_name, &times);
1762 } else {
1763 result = utime(smb_fname->base_name, NULL);
1765 if (!((result == -1) && (errno == ENOSYS))) {
1766 goto out;
1768 #endif
1769 errno = ENOSYS;
1770 result = -1;
1772 out:
1773 END_PROFILE(syscall_ntimes);
1774 return result;
1777 /*********************************************************************
1778 A version of ftruncate that will write the space on disk if strict
1779 allocate is set.
1780 **********************************************************************/
1782 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1784 off_t space_to_write;
1785 uint64_t space_avail;
1786 uint64_t bsize,dfree,dsize;
1787 int ret;
1788 NTSTATUS status;
1789 SMB_STRUCT_STAT *pst;
1791 status = vfs_stat_fsp(fsp);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 return -1;
1795 pst = &fsp->fsp_name->st;
1797 #ifdef S_ISFIFO
1798 if (S_ISFIFO(pst->st_ex_mode))
1799 return 0;
1800 #endif
1802 if (pst->st_ex_size == len)
1803 return 0;
1805 /* Shrink - just ftruncate. */
1806 if (pst->st_ex_size > len)
1807 return ftruncate(fsp->fh->fd, len);
1809 space_to_write = len - pst->st_ex_size;
1811 /* for allocation try fallocate first. This can fail on some
1812 platforms e.g. when the filesystem doesn't support it and no
1813 emulation is being done by the libc (like on AIX with JFS1). In that
1814 case we do our own emulation. fallocate implementations can
1815 return ENOTSUP or EINVAL in cases like that. */
1816 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1817 pst->st_ex_size, space_to_write);
1818 if (ret == ENOSPC) {
1819 errno = ENOSPC;
1820 return -1;
1822 if (ret == 0) {
1823 return 0;
1825 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1826 "error %d. Falling back to slow manual allocation\n", ret));
1828 /* available disk space is enough or not? */
1829 space_avail = get_dfree_info(fsp->conn,
1830 fsp->fsp_name->base_name, false,
1831 &bsize,&dfree,&dsize);
1832 /* space_avail is 1k blocks */
1833 if (space_avail == (uint64_t)-1 ||
1834 ((uint64_t)space_to_write/1024 > space_avail) ) {
1835 errno = ENOSPC;
1836 return -1;
1839 /* Write out the real space on disk. */
1840 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1841 if (ret != 0) {
1842 errno = ret;
1843 ret = -1;
1846 return 0;
1849 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1851 int result = -1;
1852 SMB_STRUCT_STAT *pst;
1853 NTSTATUS status;
1854 char c = 0;
1856 START_PROFILE(syscall_ftruncate);
1858 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1859 result = strict_allocate_ftruncate(handle, fsp, len);
1860 END_PROFILE(syscall_ftruncate);
1861 return result;
1864 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1865 ftruncate if the system supports it. Then I discovered that
1866 you can have some filesystems that support ftruncate
1867 expansion and some that don't! On Linux fat can't do
1868 ftruncate extend but ext2 can. */
1870 result = ftruncate(fsp->fh->fd, len);
1871 if (result == 0)
1872 goto done;
1874 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1875 extend a file with ftruncate. Provide alternate implementation
1876 for this */
1878 /* Do an fstat to see if the file is longer than the requested
1879 size in which case the ftruncate above should have
1880 succeeded or shorter, in which case seek to len - 1 and
1881 write 1 byte of zero */
1882 status = vfs_stat_fsp(fsp);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 goto done;
1886 pst = &fsp->fsp_name->st;
1888 #ifdef S_ISFIFO
1889 if (S_ISFIFO(pst->st_ex_mode)) {
1890 result = 0;
1891 goto done;
1893 #endif
1895 if (pst->st_ex_size == len) {
1896 result = 0;
1897 goto done;
1900 if (pst->st_ex_size > len) {
1901 /* the ftruncate should have worked */
1902 goto done;
1905 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1906 goto done;
1909 result = 0;
1911 done:
1913 END_PROFILE(syscall_ftruncate);
1914 return result;
1917 static int vfswrap_fallocate(vfs_handle_struct *handle,
1918 files_struct *fsp,
1919 enum vfs_fallocate_mode mode,
1920 off_t offset,
1921 off_t len)
1923 int result;
1925 START_PROFILE(syscall_fallocate);
1926 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1927 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1928 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1929 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1930 } else {
1931 errno = EINVAL;
1932 result = -1;
1934 END_PROFILE(syscall_fallocate);
1935 return result;
1938 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1940 bool result;
1942 START_PROFILE(syscall_fcntl_lock);
1943 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1944 END_PROFILE(syscall_fcntl_lock);
1945 return result;
1948 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1949 uint32 share_mode, uint32 access_mask)
1951 START_PROFILE(syscall_kernel_flock);
1952 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1953 END_PROFILE(syscall_kernel_flock);
1954 return 0;
1957 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1959 bool result;
1961 START_PROFILE(syscall_fcntl_getlock);
1962 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1963 END_PROFILE(syscall_fcntl_getlock);
1964 return result;
1967 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1968 int leasetype)
1970 int result = -1;
1972 START_PROFILE(syscall_linux_setlease);
1974 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1975 result = linux_setlease(fsp->fh->fd, leasetype);
1976 #else
1977 errno = ENOSYS;
1978 #endif
1979 END_PROFILE(syscall_linux_setlease);
1980 return result;
1983 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1985 int result;
1987 START_PROFILE(syscall_symlink);
1988 result = symlink(oldpath, newpath);
1989 END_PROFILE(syscall_symlink);
1990 return result;
1993 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
1995 int result;
1997 START_PROFILE(syscall_readlink);
1998 result = readlink(path, buf, bufsiz);
1999 END_PROFILE(syscall_readlink);
2000 return result;
2003 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2005 int result;
2007 START_PROFILE(syscall_link);
2008 result = link(oldpath, newpath);
2009 END_PROFILE(syscall_link);
2010 return result;
2013 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2015 int result;
2017 START_PROFILE(syscall_mknod);
2018 result = sys_mknod(pathname, mode, dev);
2019 END_PROFILE(syscall_mknod);
2020 return result;
2023 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2025 char *result;
2027 START_PROFILE(syscall_realpath);
2028 #ifdef REALPATH_TAKES_NULL
2029 result = realpath(path, NULL);
2030 #else
2031 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2032 if (result) {
2033 char *resolved_path = realpath(path, result);
2034 if (!resolved_path) {
2035 SAFE_FREE(result);
2036 } else {
2037 /* SMB_ASSERT(result == resolved_path) ? */
2038 result = resolved_path;
2041 #endif
2042 END_PROFILE(syscall_realpath);
2043 return result;
2046 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2047 struct sys_notify_context *ctx,
2048 const char *path,
2049 uint32_t *filter,
2050 uint32_t *subdir_filter,
2051 void (*callback)(struct sys_notify_context *ctx,
2052 void *private_data,
2053 struct notify_event *ev),
2054 void *private_data, void *handle)
2057 * So far inotify is the only supported default notify mechanism. If
2058 * another platform like the the BSD's or a proprietary Unix comes
2059 * along and wants another default, we can play the same trick we
2060 * played with Posix ACLs.
2062 * Until that is the case, hard-code inotify here.
2064 #ifdef HAVE_INOTIFY
2065 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2066 return inotify_watch(ctx, path, filter, subdir_filter,
2067 callback, private_data, handle);
2069 #endif
2071 * Do nothing, leave everything to notify_internal.c
2073 return NT_STATUS_OK;
2076 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2077 unsigned int flags)
2079 #ifdef HAVE_CHFLAGS
2080 return chflags(path, flags);
2081 #else
2082 errno = ENOSYS;
2083 return -1;
2084 #endif
2087 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2088 const SMB_STRUCT_STAT *sbuf)
2090 struct file_id key;
2092 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2093 * blob */
2094 ZERO_STRUCT(key);
2096 key.devid = sbuf->st_ex_dev;
2097 key.inode = sbuf->st_ex_ino;
2098 /* key.extid is unused by default. */
2100 return key;
2103 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2104 struct files_struct *fsp,
2105 const char *fname,
2106 TALLOC_CTX *mem_ctx,
2107 unsigned int *pnum_streams,
2108 struct stream_struct **pstreams)
2110 SMB_STRUCT_STAT sbuf;
2111 struct stream_struct *tmp_streams = NULL;
2112 int ret;
2114 if ((fsp != NULL) && (fsp->is_directory)) {
2116 * No default streams on directories
2118 goto done;
2121 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2122 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2124 else {
2125 struct smb_filename smb_fname;
2127 ZERO_STRUCT(smb_fname);
2128 smb_fname.base_name = discard_const_p(char, fname);
2130 if (lp_posix_pathnames()) {
2131 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2132 } else {
2133 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2135 sbuf = smb_fname.st;
2138 if (ret == -1) {
2139 return map_nt_error_from_unix(errno);
2142 if (S_ISDIR(sbuf.st_ex_mode)) {
2143 goto done;
2146 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2147 (*pnum_streams) + 1);
2148 if (tmp_streams == NULL) {
2149 return NT_STATUS_NO_MEMORY;
2151 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2152 if (tmp_streams[*pnum_streams].name == NULL) {
2153 return NT_STATUS_NO_MEMORY;
2155 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2156 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2158 *pnum_streams += 1;
2159 *pstreams = tmp_streams;
2160 done:
2161 return NT_STATUS_OK;
2164 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2165 const char *path,
2166 const char *name,
2167 TALLOC_CTX *mem_ctx,
2168 char **found_name)
2171 * Don't fall back to get_real_filename so callers can differentiate
2172 * between a full directory scan and an actual case-insensitive stat.
2174 errno = EOPNOTSUPP;
2175 return -1;
2178 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2179 const char *fname)
2181 return handle->conn->connectpath;
2184 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2185 struct byte_range_lock *br_lck,
2186 struct lock_struct *plock,
2187 bool blocking_lock,
2188 struct blocking_lock_record *blr)
2190 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2192 /* Note: blr is not used in the default implementation. */
2193 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2196 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2197 struct messaging_context *msg_ctx,
2198 struct byte_range_lock *br_lck,
2199 const struct lock_struct *plock)
2201 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2203 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2206 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2207 struct byte_range_lock *br_lck,
2208 struct lock_struct *plock,
2209 struct blocking_lock_record *blr)
2211 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2213 /* Note: blr is not used in the default implementation. */
2214 return brl_lock_cancel_default(br_lck, plock);
2217 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2218 files_struct *fsp,
2219 struct lock_struct *plock)
2221 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2222 plock->lock_type == WRITE_LOCK);
2224 return strict_lock_default(fsp, plock);
2227 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2228 files_struct *fsp,
2229 struct lock_struct *plock)
2231 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2232 plock->lock_type == WRITE_LOCK);
2234 strict_unlock_default(fsp, plock);
2237 /* NT ACL operations. */
2239 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2240 files_struct *fsp,
2241 uint32 security_info,
2242 TALLOC_CTX *mem_ctx,
2243 struct security_descriptor **ppdesc)
2245 NTSTATUS result;
2247 START_PROFILE(fget_nt_acl);
2248 result = posix_fget_nt_acl(fsp, security_info,
2249 mem_ctx, ppdesc);
2250 END_PROFILE(fget_nt_acl);
2251 return result;
2254 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2255 const char *name,
2256 uint32 security_info,
2257 TALLOC_CTX *mem_ctx,
2258 struct security_descriptor **ppdesc)
2260 NTSTATUS result;
2262 START_PROFILE(get_nt_acl);
2263 result = posix_get_nt_acl(handle->conn, name, security_info,
2264 mem_ctx, ppdesc);
2265 END_PROFILE(get_nt_acl);
2266 return result;
2269 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2271 NTSTATUS result;
2273 START_PROFILE(fset_nt_acl);
2274 result = set_nt_acl(fsp, security_info_sent, psd);
2275 END_PROFILE(fset_nt_acl);
2276 return result;
2279 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2280 struct smb_filename *file,
2281 struct security_acl *sacl,
2282 uint32_t access_requested,
2283 uint32_t access_denied)
2285 return NT_STATUS_OK; /* Nothing to do here ... */
2288 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2290 #ifdef HAVE_NO_ACL
2291 errno = ENOSYS;
2292 return -1;
2293 #else
2294 int result;
2296 START_PROFILE(chmod_acl);
2297 result = chmod_acl(handle->conn, name, mode);
2298 END_PROFILE(chmod_acl);
2299 return result;
2300 #endif
2303 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2305 #ifdef HAVE_NO_ACL
2306 errno = ENOSYS;
2307 return -1;
2308 #else
2309 int result;
2311 START_PROFILE(fchmod_acl);
2312 result = fchmod_acl(fsp, mode);
2313 END_PROFILE(fchmod_acl);
2314 return result;
2315 #endif
2318 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2319 const char *path_p,
2320 SMB_ACL_TYPE_T type,
2321 TALLOC_CTX *mem_ctx)
2323 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2326 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2327 files_struct *fsp,
2328 TALLOC_CTX *mem_ctx)
2330 return sys_acl_get_fd(handle, fsp, mem_ctx);
2333 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2335 return sys_acl_set_file(handle, name, acltype, theacl);
2338 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2340 return sys_acl_set_fd(handle, fsp, theacl);
2343 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2345 return sys_acl_delete_def_file(handle, path);
2348 /****************************************************************
2349 Extended attribute operations.
2350 *****************************************************************/
2352 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2354 return getxattr(path, name, value, size);
2357 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2359 return fgetxattr(fsp->fh->fd, name, value, size);
2362 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2364 return listxattr(path, list, size);
2367 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2369 return flistxattr(fsp->fh->fd, list, size);
2372 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2374 return removexattr(path, name);
2377 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2379 return fremovexattr(fsp->fh->fd, name);
2382 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2384 return setxattr(path, name, value, size, flags);
2387 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2389 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2392 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2394 return false;
2397 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2398 const struct smb_filename *fname,
2399 SMB_STRUCT_STAT *sbuf)
2401 NTSTATUS status;
2402 char *path;
2403 bool offline = false;
2405 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2406 return false;
2409 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2410 #if defined(ENOTSUP)
2411 errno = ENOTSUP;
2412 #endif
2413 return false;
2416 status = get_full_smb_filename(talloc_tos(), fname, &path);
2417 if (!NT_STATUS_IS_OK(status)) {
2418 errno = map_errno_from_nt_status(status);
2419 return false;
2422 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2424 TALLOC_FREE(path);
2426 return offline;
2429 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2430 const struct smb_filename *fname)
2432 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2433 #if defined(ENOTSUP)
2434 errno = ENOTSUP;
2435 #endif
2436 return -1;
2439 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2440 struct files_struct *fsp,
2441 TALLOC_CTX *mem_ctx,
2442 DATA_BLOB *cookie)
2444 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2447 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2448 struct files_struct *fsp,
2449 const DATA_BLOB old_cookie,
2450 TALLOC_CTX *mem_ctx,
2451 DATA_BLOB *new_cookie)
2453 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2454 new_cookie);
2457 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2458 struct smb_request *smb1req,
2459 struct smbXsrv_open *op,
2460 const DATA_BLOB old_cookie,
2461 TALLOC_CTX *mem_ctx,
2462 struct files_struct **fsp,
2463 DATA_BLOB *new_cookie)
2465 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2466 old_cookie, mem_ctx,
2467 fsp, new_cookie);
2470 static struct vfs_fn_pointers vfs_default_fns = {
2471 /* Disk operations */
2473 .connect_fn = vfswrap_connect,
2474 .disconnect_fn = vfswrap_disconnect,
2475 .disk_free_fn = vfswrap_disk_free,
2476 .get_quota_fn = vfswrap_get_quota,
2477 .set_quota_fn = vfswrap_set_quota,
2478 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2479 .statvfs_fn = vfswrap_statvfs,
2480 .fs_capabilities_fn = vfswrap_fs_capabilities,
2481 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2483 /* Directory operations */
2485 .opendir_fn = vfswrap_opendir,
2486 .fdopendir_fn = vfswrap_fdopendir,
2487 .readdir_fn = vfswrap_readdir,
2488 .seekdir_fn = vfswrap_seekdir,
2489 .telldir_fn = vfswrap_telldir,
2490 .rewind_dir_fn = vfswrap_rewinddir,
2491 .mkdir_fn = vfswrap_mkdir,
2492 .rmdir_fn = vfswrap_rmdir,
2493 .closedir_fn = vfswrap_closedir,
2494 .init_search_op_fn = vfswrap_init_search_op,
2496 /* File operations */
2498 .open_fn = vfswrap_open,
2499 .create_file_fn = vfswrap_create_file,
2500 .close_fn = vfswrap_close,
2501 .read_fn = vfswrap_read,
2502 .pread_fn = vfswrap_pread,
2503 .pread_send_fn = vfswrap_pread_send,
2504 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2505 .write_fn = vfswrap_write,
2506 .pwrite_fn = vfswrap_pwrite,
2507 .pwrite_send_fn = vfswrap_pwrite_send,
2508 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2509 .lseek_fn = vfswrap_lseek,
2510 .sendfile_fn = vfswrap_sendfile,
2511 .recvfile_fn = vfswrap_recvfile,
2512 .rename_fn = vfswrap_rename,
2513 .fsync_fn = vfswrap_fsync,
2514 .fsync_send_fn = vfswrap_fsync_send,
2515 .fsync_recv_fn = vfswrap_asys_int_recv,
2516 .stat_fn = vfswrap_stat,
2517 .fstat_fn = vfswrap_fstat,
2518 .lstat_fn = vfswrap_lstat,
2519 .get_alloc_size_fn = vfswrap_get_alloc_size,
2520 .unlink_fn = vfswrap_unlink,
2521 .chmod_fn = vfswrap_chmod,
2522 .fchmod_fn = vfswrap_fchmod,
2523 .chown_fn = vfswrap_chown,
2524 .fchown_fn = vfswrap_fchown,
2525 .lchown_fn = vfswrap_lchown,
2526 .chdir_fn = vfswrap_chdir,
2527 .getwd_fn = vfswrap_getwd,
2528 .ntimes_fn = vfswrap_ntimes,
2529 .ftruncate_fn = vfswrap_ftruncate,
2530 .fallocate_fn = vfswrap_fallocate,
2531 .lock_fn = vfswrap_lock,
2532 .kernel_flock_fn = vfswrap_kernel_flock,
2533 .linux_setlease_fn = vfswrap_linux_setlease,
2534 .getlock_fn = vfswrap_getlock,
2535 .symlink_fn = vfswrap_symlink,
2536 .readlink_fn = vfswrap_readlink,
2537 .link_fn = vfswrap_link,
2538 .mknod_fn = vfswrap_mknod,
2539 .realpath_fn = vfswrap_realpath,
2540 .notify_watch_fn = vfswrap_notify_watch,
2541 .chflags_fn = vfswrap_chflags,
2542 .file_id_create_fn = vfswrap_file_id_create,
2543 .streaminfo_fn = vfswrap_streaminfo,
2544 .get_real_filename_fn = vfswrap_get_real_filename,
2545 .connectpath_fn = vfswrap_connectpath,
2546 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2547 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2548 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2549 .strict_lock_fn = vfswrap_strict_lock,
2550 .strict_unlock_fn = vfswrap_strict_unlock,
2551 .translate_name_fn = vfswrap_translate_name,
2552 .fsctl_fn = vfswrap_fsctl,
2553 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2554 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2555 .get_compression_fn = vfswrap_get_compression,
2556 .set_compression_fn = vfswrap_set_compression,
2558 /* NT ACL operations. */
2560 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2561 .get_nt_acl_fn = vfswrap_get_nt_acl,
2562 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2563 .audit_file_fn = vfswrap_audit_file,
2565 /* POSIX ACL operations. */
2567 .chmod_acl_fn = vfswrap_chmod_acl,
2568 .fchmod_acl_fn = vfswrap_fchmod_acl,
2570 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2571 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2572 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2573 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2574 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2575 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2576 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2578 /* EA operations. */
2579 .getxattr_fn = vfswrap_getxattr,
2580 .fgetxattr_fn = vfswrap_fgetxattr,
2581 .listxattr_fn = vfswrap_listxattr,
2582 .flistxattr_fn = vfswrap_flistxattr,
2583 .removexattr_fn = vfswrap_removexattr,
2584 .fremovexattr_fn = vfswrap_fremovexattr,
2585 .setxattr_fn = vfswrap_setxattr,
2586 .fsetxattr_fn = vfswrap_fsetxattr,
2588 /* aio operations */
2589 .aio_force_fn = vfswrap_aio_force,
2591 /* offline operations */
2592 .is_offline_fn = vfswrap_is_offline,
2593 .set_offline_fn = vfswrap_set_offline,
2595 /* durable handle operations */
2596 .durable_cookie_fn = vfswrap_durable_cookie,
2597 .durable_disconnect_fn = vfswrap_durable_disconnect,
2598 .durable_reconnect_fn = vfswrap_durable_reconnect,
2601 NTSTATUS vfs_default_init(void);
2602 NTSTATUS vfs_default_init(void)
2604 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2605 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);