s3: smbd: VFS: For all EA and ACL calls use synthetic_smb_fname(), not synthetic_smb_...
[Samba.git] / source3 / modules / vfs_default.c
blob618e460491236d40bc6dcfce5bd5eb6c03ed6050
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_dir_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_dir_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 tevent_req *req;
797 struct vfswrap_asys_state *state;
798 int res;
799 ssize_t ret;
800 int err;
801 void *private_data;
803 if ((flags & TEVENT_FD_READ) == 0) {
804 return;
807 while (true) {
808 res = asys_result(asys_ctx, &ret, &err, &private_data);
809 if (res == EINTR || res == EAGAIN) {
810 return;
812 #ifdef EWOULDBLOCK
813 if (res == EWOULDBLOCK) {
814 return;
816 #endif
818 if (res == ECANCELED) {
819 return;
822 if (res != 0) {
823 DEBUG(1, ("asys_result returned %s\n", strerror(res)));
824 return;
827 req = talloc_get_type_abort(private_data, struct tevent_req);
828 state = tevent_req_data(req, struct vfswrap_asys_state);
830 talloc_set_destructor(state, NULL);
832 state->ret = ret;
833 state->err = err;
834 tevent_req_defer_callback(req, ev);
835 tevent_req_done(req);
839 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
841 struct vfswrap_asys_state *state = tevent_req_data(
842 req, struct vfswrap_asys_state);
844 if (tevent_req_is_unix_error(req, err)) {
845 return -1;
847 *err = state->err;
848 return state->ret;
851 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
853 struct vfswrap_asys_state *state = tevent_req_data(
854 req, struct vfswrap_asys_state);
856 if (tevent_req_is_unix_error(req, err)) {
857 return -1;
859 *err = state->err;
860 return state->ret;
863 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
865 off_t result = 0;
867 START_PROFILE(syscall_lseek);
869 /* Cope with 'stat' file opens. */
870 if (fsp->fh->fd != -1)
871 result = lseek(fsp->fh->fd, offset, whence);
874 * We want to maintain the fiction that we can seek
875 * on a fifo for file system purposes. This allows
876 * people to set up UNIX fifo's that feed data to Windows
877 * applications. JRA.
880 if((result == -1) && (errno == ESPIPE)) {
881 result = 0;
882 errno = 0;
885 END_PROFILE(syscall_lseek);
886 return result;
889 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
890 off_t offset, size_t n)
892 ssize_t result;
894 START_PROFILE_BYTES(syscall_sendfile, n);
895 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
896 END_PROFILE(syscall_sendfile);
897 return result;
900 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
901 int fromfd,
902 files_struct *tofsp,
903 off_t offset,
904 size_t n)
906 ssize_t result;
908 START_PROFILE_BYTES(syscall_recvfile, n);
909 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
910 END_PROFILE(syscall_recvfile);
911 return result;
914 static int vfswrap_rename(vfs_handle_struct *handle,
915 const struct smb_filename *smb_fname_src,
916 const struct smb_filename *smb_fname_dst)
918 int result = -1;
920 START_PROFILE(syscall_rename);
922 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
923 errno = ENOENT;
924 goto out;
927 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
929 out:
930 END_PROFILE(syscall_rename);
931 return result;
934 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
936 #ifdef HAVE_FSYNC
937 int result;
939 START_PROFILE(syscall_fsync);
940 result = fsync(fsp->fh->fd);
941 END_PROFILE(syscall_fsync);
942 return result;
943 #else
944 return 0;
945 #endif
948 static int vfswrap_stat(vfs_handle_struct *handle,
949 struct smb_filename *smb_fname)
951 int result = -1;
953 START_PROFILE(syscall_stat);
955 if (smb_fname->stream_name) {
956 errno = ENOENT;
957 goto out;
960 result = sys_stat(smb_fname->base_name, &smb_fname->st,
961 lp_fake_dir_create_times(SNUM(handle->conn)));
962 out:
963 END_PROFILE(syscall_stat);
964 return result;
967 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
969 int result;
971 START_PROFILE(syscall_fstat);
972 result = sys_fstat(fsp->fh->fd,
973 sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
974 END_PROFILE(syscall_fstat);
975 return result;
978 static int vfswrap_lstat(vfs_handle_struct *handle,
979 struct smb_filename *smb_fname)
981 int result = -1;
983 START_PROFILE(syscall_lstat);
985 if (smb_fname->stream_name) {
986 errno = ENOENT;
987 goto out;
990 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
991 lp_fake_dir_create_times(SNUM(handle->conn)));
992 out:
993 END_PROFILE(syscall_lstat);
994 return result;
997 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
998 const char *name,
999 enum vfs_translate_direction direction,
1000 TALLOC_CTX *mem_ctx,
1001 char **mapped_name)
1003 return NT_STATUS_NONE_MAPPED;
1007 * Implement the default fsctl operation.
1009 static bool vfswrap_logged_ioctl_message = false;
1011 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1012 struct files_struct *fsp,
1013 TALLOC_CTX *ctx,
1014 uint32_t function,
1015 uint16_t req_flags, /* Needed for UNICODE ... */
1016 const uint8_t *_in_data,
1017 uint32_t in_len,
1018 uint8_t **_out_data,
1019 uint32_t max_out_len,
1020 uint32_t *out_len)
1022 const char *in_data = (const char *)_in_data;
1023 char **out_data = (char **)_out_data;
1025 switch (function) {
1026 case FSCTL_SET_SPARSE:
1028 bool set_sparse = true;
1029 NTSTATUS status;
1031 if (in_len >= 1 && in_data[0] == 0) {
1032 set_sparse = false;
1035 status = file_set_sparse(handle->conn, fsp, set_sparse);
1037 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1038 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1039 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1040 nt_errstr(status)));
1042 return status;
1045 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1047 unsigned char objid[16];
1048 char *return_data = NULL;
1050 /* This should return the object-id on this file.
1051 * I think I'll make this be the inode+dev. JRA.
1054 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1055 fsp_fnum_dbg(fsp)));
1057 *out_len = (max_out_len >= 64) ? 64 : max_out_len;
1058 /* Hmmm, will this cause problems if less data asked for? */
1059 return_data = talloc_array(ctx, char, 64);
1060 if (return_data == NULL) {
1061 return NT_STATUS_NO_MEMORY;
1064 /* For backwards compatibility only store the dev/inode. */
1065 push_file_id_16(return_data, &fsp->file_id);
1066 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1067 push_file_id_16(return_data+32, &fsp->file_id);
1068 *out_data = return_data;
1069 return NT_STATUS_OK;
1072 case FSCTL_GET_REPARSE_POINT:
1074 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1075 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1076 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1077 return NT_STATUS_NOT_A_REPARSE_POINT;
1080 case FSCTL_SET_REPARSE_POINT:
1082 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1083 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1084 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1085 return NT_STATUS_NOT_A_REPARSE_POINT;
1088 case FSCTL_GET_SHADOW_COPY_DATA:
1091 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1092 * and return their volume names. If max_data_count is 16, then it is just
1093 * asking for the number of volumes and length of the combined names.
1095 * pdata is the data allocated by our caller, but that uses
1096 * total_data_count (which is 0 in our case) rather than max_data_count.
1097 * Allocate the correct amount and return the pointer to let
1098 * it be deallocated when we return.
1100 struct shadow_copy_data *shadow_data = NULL;
1101 bool labels = False;
1102 uint32 labels_data_count = 0;
1103 uint32 i;
1104 char *cur_pdata = NULL;
1106 if (max_out_len < 16) {
1107 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1108 max_out_len));
1109 return NT_STATUS_INVALID_PARAMETER;
1112 if (max_out_len > 16) {
1113 labels = True;
1116 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1117 if (shadow_data == NULL) {
1118 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1119 return NT_STATUS_NO_MEMORY;
1123 * Call the VFS routine to actually do the work.
1125 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1126 TALLOC_FREE(shadow_data);
1127 if (errno == ENOSYS) {
1128 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
1129 fsp->conn->connectpath));
1130 return NT_STATUS_NOT_SUPPORTED;
1131 } else {
1132 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
1133 fsp->conn->connectpath));
1134 return NT_STATUS_UNSUCCESSFUL;
1138 labels_data_count = (shadow_data->num_volumes * 2 *
1139 sizeof(SHADOW_COPY_LABEL)) + 2;
1141 if (!labels) {
1142 *out_len = 16;
1143 } else {
1144 *out_len = 12 + labels_data_count;
1147 if (max_out_len < *out_len) {
1148 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1149 max_out_len, *out_len));
1150 TALLOC_FREE(shadow_data);
1151 return NT_STATUS_BUFFER_TOO_SMALL;
1154 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1155 if (cur_pdata == NULL) {
1156 TALLOC_FREE(shadow_data);
1157 return NT_STATUS_NO_MEMORY;
1160 *out_data = cur_pdata;
1162 /* num_volumes 4 bytes */
1163 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1165 if (labels) {
1166 /* num_labels 4 bytes */
1167 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1170 /* needed_data_count 4 bytes */
1171 SIVAL(cur_pdata, 8, labels_data_count);
1173 cur_pdata += 12;
1175 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1176 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1177 if (labels && shadow_data->labels) {
1178 for (i=0; i<shadow_data->num_volumes; i++) {
1179 srvstr_push(cur_pdata, req_flags,
1180 cur_pdata, shadow_data->labels[i],
1181 2 * sizeof(SHADOW_COPY_LABEL),
1182 STR_UNICODE|STR_TERMINATE);
1183 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1184 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1188 TALLOC_FREE(shadow_data);
1190 return NT_STATUS_OK;
1193 case FSCTL_FIND_FILES_BY_SID:
1195 /* pretend this succeeded -
1197 * we have to send back a list with all files owned by this SID
1199 * but I have to check that --metze
1201 struct dom_sid sid;
1202 uid_t uid;
1203 size_t sid_len;
1205 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1206 fsp_fnum_dbg(fsp)));
1208 if (in_len < 8) {
1209 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1210 return NT_STATUS_INVALID_PARAMETER;
1213 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1215 /* unknown 4 bytes: this is not the length of the sid :-( */
1216 /*unknown = IVAL(pdata,0);*/
1218 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1219 return NT_STATUS_INVALID_PARAMETER;
1221 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1223 if (!sid_to_uid(&sid, &uid)) {
1224 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1225 sid_string_dbg(&sid),
1226 (unsigned long)sid_len));
1227 uid = (-1);
1230 /* we can take a look at the find source :-)
1232 * find ./ -uid $uid -name '*' is what we need here
1235 * and send 4bytes len and then NULL terminated unicode strings
1236 * for each file
1238 * but I don't know how to deal with the paged results
1239 * (maybe we can hang the result anywhere in the fsp struct)
1241 * but I don't know how to deal with the paged results
1242 * (maybe we can hang the result anywhere in the fsp struct)
1244 * we don't send all files at once
1245 * and at the next we should *not* start from the beginning,
1246 * so we have to cache the result
1248 * --metze
1251 /* this works for now... */
1252 return NT_STATUS_OK;
1255 case FSCTL_QUERY_ALLOCATED_RANGES:
1257 /* FIXME: This is just a dummy reply, telling that all of the
1258 * file is allocated. MKS cp needs that.
1259 * Adding the real allocated ranges via FIEMAP on Linux
1260 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1261 * this FSCTL correct for sparse files.
1263 NTSTATUS status;
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 if (src_fsp->op == NULL) {
1397 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1398 return tevent_req_post(req, ev);
1400 init_strict_lock_struct(src_fsp,
1401 src_fsp->op->global->open_persistent_id,
1402 src_off,
1403 this_num,
1404 READ_LOCK,
1405 &lck);
1407 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1408 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1409 return tevent_req_post(req, ev);
1412 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1413 this_num, src_off);
1414 if (ret == -1) {
1415 saved_errno = errno;
1418 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1420 if (ret == -1) {
1421 errno = saved_errno;
1422 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1423 return tevent_req_post(req, ev);
1425 if (ret != this_num) {
1426 /* zero tolerance for short reads */
1427 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1428 return tevent_req_post(req, ev);
1431 src_off += ret;
1433 if (dest_fsp->op == NULL) {
1434 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1435 return tevent_req_post(req, ev);
1438 init_strict_lock_struct(dest_fsp,
1439 dest_fsp->op->global->open_persistent_id,
1440 dest_off,
1441 this_num,
1442 WRITE_LOCK,
1443 &lck);
1445 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1446 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1447 return tevent_req_post(req, ev);
1450 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1451 this_num, dest_off);
1452 if (ret == -1) {
1453 saved_errno = errno;
1456 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1458 if (ret == -1) {
1459 errno = saved_errno;
1460 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1461 return tevent_req_post(req, ev);
1463 if (ret != this_num) {
1464 /* zero tolerance for short writes */
1465 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1466 return tevent_req_post(req, ev);
1468 dest_off += ret;
1470 vfs_cc_state->copied += this_num;
1473 tevent_req_done(req);
1474 return tevent_req_post(req, ev);
1477 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1478 struct tevent_req *req,
1479 off_t *copied)
1481 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1482 struct vfs_cc_state);
1483 NTSTATUS status;
1485 if (tevent_req_is_nterror(req, &status)) {
1486 DEBUG(2, ("server side copy chunk failed: %s\n",
1487 nt_errstr(status)));
1488 *copied = 0;
1489 tevent_req_received(req);
1490 return status;
1493 *copied = vfs_cc_state->copied;
1494 DEBUG(10, ("server side copy chunk copied %lu\n",
1495 (unsigned long)*copied));
1496 tevent_req_received(req);
1498 return NT_STATUS_OK;
1501 /********************************************************************
1502 Given a stat buffer return the allocated size on disk, taking into
1503 account sparse files.
1504 ********************************************************************/
1505 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1506 struct files_struct *fsp,
1507 const SMB_STRUCT_STAT *sbuf)
1509 uint64_t result;
1511 START_PROFILE(syscall_get_alloc_size);
1513 if(S_ISDIR(sbuf->st_ex_mode)) {
1514 result = 0;
1515 goto out;
1518 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1519 /* The type of st_blocksize is blkcnt_t which *MUST* be
1520 signed (according to POSIX) and can be less than 64-bits.
1521 Ensure when we're converting to 64 bits wide we don't
1522 sign extend. */
1523 #if defined(SIZEOF_BLKCNT_T_8)
1524 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1525 #elif defined(SIZEOF_BLKCNT_T_4)
1527 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1528 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1530 #else
1531 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1532 #endif
1533 if (result == 0) {
1535 * Some file systems do not allocate a block for very
1536 * small files. But for non-empty file should report a
1537 * positive size.
1540 uint64_t filesize = get_file_size_stat(sbuf);
1541 if (filesize > 0) {
1542 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1545 #else
1546 result = get_file_size_stat(sbuf);
1547 #endif
1549 if (fsp && fsp->initial_allocation_size)
1550 result = MAX(result,fsp->initial_allocation_size);
1552 result = smb_roundup(handle->conn, result);
1554 out:
1555 END_PROFILE(syscall_get_alloc_size);
1556 return result;
1559 static int vfswrap_unlink(vfs_handle_struct *handle,
1560 const struct smb_filename *smb_fname)
1562 int result = -1;
1564 START_PROFILE(syscall_unlink);
1566 if (smb_fname->stream_name) {
1567 errno = ENOENT;
1568 goto out;
1570 result = unlink(smb_fname->base_name);
1572 out:
1573 END_PROFILE(syscall_unlink);
1574 return result;
1577 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1579 int result;
1581 START_PROFILE(syscall_chmod);
1584 * We need to do this due to the fact that the default POSIX ACL
1585 * chmod modifies the ACL *mask* for the group owner, not the
1586 * group owner bits directly. JRA.
1591 int saved_errno = errno; /* We might get ENOSYS */
1592 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1593 END_PROFILE(syscall_chmod);
1594 return result;
1596 /* Error - return the old errno. */
1597 errno = saved_errno;
1600 result = chmod(path, mode);
1601 END_PROFILE(syscall_chmod);
1602 return result;
1605 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1607 int result;
1609 START_PROFILE(syscall_fchmod);
1612 * We need to do this due to the fact that the default POSIX ACL
1613 * chmod modifies the ACL *mask* for the group owner, not the
1614 * group owner bits directly. JRA.
1618 int saved_errno = errno; /* We might get ENOSYS */
1619 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1620 END_PROFILE(syscall_fchmod);
1621 return result;
1623 /* Error - return the old errno. */
1624 errno = saved_errno;
1627 #if defined(HAVE_FCHMOD)
1628 result = fchmod(fsp->fh->fd, mode);
1629 #else
1630 result = -1;
1631 errno = ENOSYS;
1632 #endif
1634 END_PROFILE(syscall_fchmod);
1635 return result;
1638 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1640 int result;
1642 START_PROFILE(syscall_chown);
1643 result = chown(path, uid, gid);
1644 END_PROFILE(syscall_chown);
1645 return result;
1648 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1650 #ifdef HAVE_FCHOWN
1651 int result;
1653 START_PROFILE(syscall_fchown);
1654 result = fchown(fsp->fh->fd, uid, gid);
1655 END_PROFILE(syscall_fchown);
1656 return result;
1657 #else
1658 errno = ENOSYS;
1659 return -1;
1660 #endif
1663 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1665 int result;
1667 START_PROFILE(syscall_lchown);
1668 result = lchown(path, uid, gid);
1669 END_PROFILE(syscall_lchown);
1670 return result;
1673 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1675 int result;
1677 START_PROFILE(syscall_chdir);
1678 result = chdir(path);
1679 END_PROFILE(syscall_chdir);
1680 return result;
1683 static char *vfswrap_getwd(vfs_handle_struct *handle)
1685 char *result;
1687 START_PROFILE(syscall_getwd);
1688 result = sys_getwd();
1689 END_PROFILE(syscall_getwd);
1690 return result;
1693 /*********************************************************************
1694 nsec timestamp resolution call. Convert down to whatever the underlying
1695 system will support.
1696 **********************************************************************/
1698 static int vfswrap_ntimes(vfs_handle_struct *handle,
1699 const struct smb_filename *smb_fname,
1700 struct smb_file_time *ft)
1702 int result = -1;
1704 START_PROFILE(syscall_ntimes);
1706 if (smb_fname->stream_name) {
1707 errno = ENOENT;
1708 goto out;
1711 if (ft != NULL) {
1712 if (null_timespec(ft->atime)) {
1713 ft->atime= smb_fname->st.st_ex_atime;
1716 if (null_timespec(ft->mtime)) {
1717 ft->mtime = smb_fname->st.st_ex_mtime;
1720 if (!null_timespec(ft->create_time)) {
1721 set_create_timespec_ea(handle->conn,
1722 smb_fname,
1723 ft->create_time);
1726 if ((timespec_compare(&ft->atime,
1727 &smb_fname->st.st_ex_atime) == 0) &&
1728 (timespec_compare(&ft->mtime,
1729 &smb_fname->st.st_ex_mtime) == 0)) {
1730 return 0;
1734 #if defined(HAVE_UTIMENSAT)
1735 if (ft != NULL) {
1736 struct timespec ts[2];
1737 ts[0] = ft->atime;
1738 ts[1] = ft->mtime;
1739 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1740 } else {
1741 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1743 if (!((result == -1) && (errno == ENOSYS))) {
1744 goto out;
1746 #endif
1747 #if defined(HAVE_UTIMES)
1748 if (ft != NULL) {
1749 struct timeval tv[2];
1750 tv[0] = convert_timespec_to_timeval(ft->atime);
1751 tv[1] = convert_timespec_to_timeval(ft->mtime);
1752 result = utimes(smb_fname->base_name, tv);
1753 } else {
1754 result = utimes(smb_fname->base_name, NULL);
1756 if (!((result == -1) && (errno == ENOSYS))) {
1757 goto out;
1759 #endif
1760 #if defined(HAVE_UTIME)
1761 if (ft != NULL) {
1762 struct utimbuf times;
1763 times.actime = convert_timespec_to_time_t(ft->atime);
1764 times.modtime = convert_timespec_to_time_t(ft->mtime);
1765 result = utime(smb_fname->base_name, &times);
1766 } else {
1767 result = utime(smb_fname->base_name, NULL);
1769 if (!((result == -1) && (errno == ENOSYS))) {
1770 goto out;
1772 #endif
1773 errno = ENOSYS;
1774 result = -1;
1776 out:
1777 END_PROFILE(syscall_ntimes);
1778 return result;
1781 /*********************************************************************
1782 A version of ftruncate that will write the space on disk if strict
1783 allocate is set.
1784 **********************************************************************/
1786 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1788 off_t space_to_write;
1789 uint64_t space_avail;
1790 uint64_t bsize,dfree,dsize;
1791 int ret;
1792 NTSTATUS status;
1793 SMB_STRUCT_STAT *pst;
1795 status = vfs_stat_fsp(fsp);
1796 if (!NT_STATUS_IS_OK(status)) {
1797 return -1;
1799 pst = &fsp->fsp_name->st;
1801 #ifdef S_ISFIFO
1802 if (S_ISFIFO(pst->st_ex_mode))
1803 return 0;
1804 #endif
1806 if (pst->st_ex_size == len)
1807 return 0;
1809 /* Shrink - just ftruncate. */
1810 if (pst->st_ex_size > len)
1811 return ftruncate(fsp->fh->fd, len);
1813 space_to_write = len - pst->st_ex_size;
1815 /* for allocation try fallocate first. This can fail on some
1816 platforms e.g. when the filesystem doesn't support it and no
1817 emulation is being done by the libc (like on AIX with JFS1). In that
1818 case we do our own emulation. fallocate implementations can
1819 return ENOTSUP or EINVAL in cases like that. */
1820 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1821 pst->st_ex_size, space_to_write);
1822 if (ret == -1 && errno == ENOSPC) {
1823 return -1;
1825 if (ret == 0) {
1826 return 0;
1828 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1829 "error %d. Falling back to slow manual allocation\n", errno));
1831 /* available disk space is enough or not? */
1832 space_avail = get_dfree_info(fsp->conn,
1833 fsp->fsp_name->base_name, false,
1834 &bsize,&dfree,&dsize);
1835 /* space_avail is 1k blocks */
1836 if (space_avail == (uint64_t)-1 ||
1837 ((uint64_t)space_to_write/1024 > space_avail) ) {
1838 errno = ENOSPC;
1839 return -1;
1842 /* Write out the real space on disk. */
1843 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1844 if (ret != 0) {
1845 return -1;
1848 return 0;
1851 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1853 int result = -1;
1854 SMB_STRUCT_STAT *pst;
1855 NTSTATUS status;
1856 char c = 0;
1858 START_PROFILE(syscall_ftruncate);
1860 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1861 result = strict_allocate_ftruncate(handle, fsp, len);
1862 END_PROFILE(syscall_ftruncate);
1863 return result;
1866 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1867 ftruncate if the system supports it. Then I discovered that
1868 you can have some filesystems that support ftruncate
1869 expansion and some that don't! On Linux fat can't do
1870 ftruncate extend but ext2 can. */
1872 result = ftruncate(fsp->fh->fd, len);
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;
1887 /* We need to update the files_struct after successful ftruncate */
1888 if (result == 0) {
1889 goto done;
1892 pst = &fsp->fsp_name->st;
1894 #ifdef S_ISFIFO
1895 if (S_ISFIFO(pst->st_ex_mode)) {
1896 result = 0;
1897 goto done;
1899 #endif
1901 if (pst->st_ex_size == len) {
1902 result = 0;
1903 goto done;
1906 if (pst->st_ex_size > len) {
1907 /* the ftruncate should have worked */
1908 goto done;
1911 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1912 goto done;
1915 result = 0;
1917 done:
1919 END_PROFILE(syscall_ftruncate);
1920 return result;
1923 static int vfswrap_fallocate(vfs_handle_struct *handle,
1924 files_struct *fsp,
1925 enum vfs_fallocate_mode mode,
1926 off_t offset,
1927 off_t len)
1929 int result;
1931 START_PROFILE(syscall_fallocate);
1932 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1933 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1935 * posix_fallocate returns 0 on success, errno on error
1936 * and doesn't set errno. Make it behave like fallocate()
1937 * which returns -1, and sets errno on failure.
1939 if (result != 0) {
1940 errno = result;
1941 result = -1;
1943 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1944 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1945 } else {
1946 errno = EINVAL;
1947 result = -1;
1949 END_PROFILE(syscall_fallocate);
1950 return result;
1953 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1955 bool result;
1957 START_PROFILE(syscall_fcntl_lock);
1958 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1959 END_PROFILE(syscall_fcntl_lock);
1960 return result;
1963 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1964 uint32 share_mode, uint32 access_mask)
1966 START_PROFILE(syscall_kernel_flock);
1967 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1968 END_PROFILE(syscall_kernel_flock);
1969 return 0;
1972 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1974 bool result;
1976 START_PROFILE(syscall_fcntl_getlock);
1977 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1978 END_PROFILE(syscall_fcntl_getlock);
1979 return result;
1982 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1983 int leasetype)
1985 int result = -1;
1987 START_PROFILE(syscall_linux_setlease);
1989 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1990 result = linux_setlease(fsp->fh->fd, leasetype);
1991 #else
1992 errno = ENOSYS;
1993 #endif
1994 END_PROFILE(syscall_linux_setlease);
1995 return result;
1998 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2000 int result;
2002 START_PROFILE(syscall_symlink);
2003 result = symlink(oldpath, newpath);
2004 END_PROFILE(syscall_symlink);
2005 return result;
2008 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2010 int result;
2012 START_PROFILE(syscall_readlink);
2013 result = readlink(path, buf, bufsiz);
2014 END_PROFILE(syscall_readlink);
2015 return result;
2018 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2020 int result;
2022 START_PROFILE(syscall_link);
2023 result = link(oldpath, newpath);
2024 END_PROFILE(syscall_link);
2025 return result;
2028 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2030 int result;
2032 START_PROFILE(syscall_mknod);
2033 result = sys_mknod(pathname, mode, dev);
2034 END_PROFILE(syscall_mknod);
2035 return result;
2038 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2040 char *result;
2042 START_PROFILE(syscall_realpath);
2043 #ifdef REALPATH_TAKES_NULL
2044 result = realpath(path, NULL);
2045 #else
2046 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2047 if (result) {
2048 char *resolved_path = realpath(path, result);
2049 if (!resolved_path) {
2050 SAFE_FREE(result);
2051 } else {
2052 /* SMB_ASSERT(result == resolved_path) ? */
2053 result = resolved_path;
2056 #endif
2057 END_PROFILE(syscall_realpath);
2058 return result;
2061 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2062 struct sys_notify_context *ctx,
2063 const char *path,
2064 uint32_t *filter,
2065 uint32_t *subdir_filter,
2066 void (*callback)(struct sys_notify_context *ctx,
2067 void *private_data,
2068 struct notify_event *ev),
2069 void *private_data, void *handle)
2072 * So far inotify is the only supported default notify mechanism. If
2073 * another platform like the the BSD's or a proprietary Unix comes
2074 * along and wants another default, we can play the same trick we
2075 * played with Posix ACLs.
2077 * Until that is the case, hard-code inotify here.
2079 #ifdef HAVE_INOTIFY
2080 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2081 return inotify_watch(ctx, path, filter, subdir_filter,
2082 callback, private_data, handle);
2084 #endif
2086 * Do nothing, leave everything to notify_internal.c
2088 return NT_STATUS_OK;
2091 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2092 unsigned int flags)
2094 #ifdef HAVE_CHFLAGS
2095 return chflags(path, flags);
2096 #else
2097 errno = ENOSYS;
2098 return -1;
2099 #endif
2102 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2103 const SMB_STRUCT_STAT *sbuf)
2105 struct file_id key;
2107 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2108 * blob */
2109 ZERO_STRUCT(key);
2111 key.devid = sbuf->st_ex_dev;
2112 key.inode = sbuf->st_ex_ino;
2113 /* key.extid is unused by default. */
2115 return key;
2118 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2119 struct files_struct *fsp,
2120 const char *fname,
2121 TALLOC_CTX *mem_ctx,
2122 unsigned int *pnum_streams,
2123 struct stream_struct **pstreams)
2125 SMB_STRUCT_STAT sbuf;
2126 struct stream_struct *tmp_streams = NULL;
2127 int ret;
2129 if ((fsp != NULL) && (fsp->is_directory)) {
2131 * No default streams on directories
2133 goto done;
2136 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2137 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2139 else {
2140 struct smb_filename smb_fname;
2142 ZERO_STRUCT(smb_fname);
2143 smb_fname.base_name = discard_const_p(char, fname);
2145 if (lp_posix_pathnames()) {
2146 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2147 } else {
2148 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2150 sbuf = smb_fname.st;
2153 if (ret == -1) {
2154 return map_nt_error_from_unix(errno);
2157 if (S_ISDIR(sbuf.st_ex_mode)) {
2158 goto done;
2161 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2162 (*pnum_streams) + 1);
2163 if (tmp_streams == NULL) {
2164 return NT_STATUS_NO_MEMORY;
2166 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2167 if (tmp_streams[*pnum_streams].name == NULL) {
2168 return NT_STATUS_NO_MEMORY;
2170 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2171 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2173 *pnum_streams += 1;
2174 *pstreams = tmp_streams;
2175 done:
2176 return NT_STATUS_OK;
2179 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2180 const char *path,
2181 const char *name,
2182 TALLOC_CTX *mem_ctx,
2183 char **found_name)
2186 * Don't fall back to get_real_filename so callers can differentiate
2187 * between a full directory scan and an actual case-insensitive stat.
2189 errno = EOPNOTSUPP;
2190 return -1;
2193 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2194 const char *fname)
2196 return handle->conn->connectpath;
2199 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2200 struct byte_range_lock *br_lck,
2201 struct lock_struct *plock,
2202 bool blocking_lock,
2203 struct blocking_lock_record *blr)
2205 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2207 /* Note: blr is not used in the default implementation. */
2208 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2211 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2212 struct messaging_context *msg_ctx,
2213 struct byte_range_lock *br_lck,
2214 const struct lock_struct *plock)
2216 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2218 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2221 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2222 struct byte_range_lock *br_lck,
2223 struct lock_struct *plock,
2224 struct blocking_lock_record *blr)
2226 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2228 /* Note: blr is not used in the default implementation. */
2229 return brl_lock_cancel_default(br_lck, plock);
2232 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2233 files_struct *fsp,
2234 struct lock_struct *plock)
2236 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2237 plock->lock_type == WRITE_LOCK);
2239 return strict_lock_default(fsp, plock);
2242 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2243 files_struct *fsp,
2244 struct lock_struct *plock)
2246 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2247 plock->lock_type == WRITE_LOCK);
2249 strict_unlock_default(fsp, plock);
2252 /* NT ACL operations. */
2254 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2255 files_struct *fsp,
2256 uint32 security_info,
2257 TALLOC_CTX *mem_ctx,
2258 struct security_descriptor **ppdesc)
2260 NTSTATUS result;
2262 START_PROFILE(fget_nt_acl);
2263 result = posix_fget_nt_acl(fsp, security_info,
2264 mem_ctx, ppdesc);
2265 END_PROFILE(fget_nt_acl);
2266 return result;
2269 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2270 const char *name,
2271 uint32 security_info,
2272 TALLOC_CTX *mem_ctx,
2273 struct security_descriptor **ppdesc)
2275 NTSTATUS result;
2277 START_PROFILE(get_nt_acl);
2278 result = posix_get_nt_acl(handle->conn, name, security_info,
2279 mem_ctx, ppdesc);
2280 END_PROFILE(get_nt_acl);
2281 return result;
2284 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2286 NTSTATUS result;
2288 START_PROFILE(fset_nt_acl);
2289 result = set_nt_acl(fsp, security_info_sent, psd);
2290 END_PROFILE(fset_nt_acl);
2291 return result;
2294 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2295 struct smb_filename *file,
2296 struct security_acl *sacl,
2297 uint32_t access_requested,
2298 uint32_t access_denied)
2300 return NT_STATUS_OK; /* Nothing to do here ... */
2303 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2305 #ifdef HAVE_NO_ACL
2306 errno = ENOSYS;
2307 return -1;
2308 #else
2309 int result;
2311 START_PROFILE(chmod_acl);
2312 result = chmod_acl(handle->conn, name, mode);
2313 END_PROFILE(chmod_acl);
2314 return result;
2315 #endif
2318 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2320 #ifdef HAVE_NO_ACL
2321 errno = ENOSYS;
2322 return -1;
2323 #else
2324 int result;
2326 START_PROFILE(fchmod_acl);
2327 result = fchmod_acl(fsp, mode);
2328 END_PROFILE(fchmod_acl);
2329 return result;
2330 #endif
2333 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2334 const char *path_p,
2335 SMB_ACL_TYPE_T type,
2336 TALLOC_CTX *mem_ctx)
2338 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2341 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2342 files_struct *fsp,
2343 TALLOC_CTX *mem_ctx)
2345 return sys_acl_get_fd(handle, fsp, mem_ctx);
2348 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2350 return sys_acl_set_file(handle, name, acltype, theacl);
2353 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2355 return sys_acl_set_fd(handle, fsp, theacl);
2358 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2360 return sys_acl_delete_def_file(handle, path);
2363 /****************************************************************
2364 Extended attribute operations.
2365 *****************************************************************/
2367 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2369 return getxattr(path, name, value, size);
2372 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2374 return fgetxattr(fsp->fh->fd, name, value, size);
2377 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2379 return listxattr(path, list, size);
2382 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2384 return flistxattr(fsp->fh->fd, list, size);
2387 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2389 return removexattr(path, name);
2392 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2394 return fremovexattr(fsp->fh->fd, name);
2397 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2399 return setxattr(path, name, value, size, flags);
2402 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2404 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2407 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2409 return false;
2412 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2413 const struct smb_filename *fname,
2414 SMB_STRUCT_STAT *sbuf)
2416 NTSTATUS status;
2417 char *path;
2418 bool offline = false;
2420 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2421 return false;
2424 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2425 #if defined(ENOTSUP)
2426 errno = ENOTSUP;
2427 #endif
2428 return false;
2431 status = get_full_smb_filename(talloc_tos(), fname, &path);
2432 if (!NT_STATUS_IS_OK(status)) {
2433 errno = map_errno_from_nt_status(status);
2434 return false;
2437 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2439 TALLOC_FREE(path);
2441 return offline;
2444 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2445 const struct smb_filename *fname)
2447 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2448 #if defined(ENOTSUP)
2449 errno = ENOTSUP;
2450 #endif
2451 return -1;
2454 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2455 struct files_struct *fsp,
2456 TALLOC_CTX *mem_ctx,
2457 DATA_BLOB *cookie)
2459 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2462 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2463 struct files_struct *fsp,
2464 const DATA_BLOB old_cookie,
2465 TALLOC_CTX *mem_ctx,
2466 DATA_BLOB *new_cookie)
2468 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2469 new_cookie);
2472 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2473 struct smb_request *smb1req,
2474 struct smbXsrv_open *op,
2475 const DATA_BLOB old_cookie,
2476 TALLOC_CTX *mem_ctx,
2477 struct files_struct **fsp,
2478 DATA_BLOB *new_cookie)
2480 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2481 old_cookie, mem_ctx,
2482 fsp, new_cookie);
2485 static struct vfs_fn_pointers vfs_default_fns = {
2486 /* Disk operations */
2488 .connect_fn = vfswrap_connect,
2489 .disconnect_fn = vfswrap_disconnect,
2490 .disk_free_fn = vfswrap_disk_free,
2491 .get_quota_fn = vfswrap_get_quota,
2492 .set_quota_fn = vfswrap_set_quota,
2493 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2494 .statvfs_fn = vfswrap_statvfs,
2495 .fs_capabilities_fn = vfswrap_fs_capabilities,
2496 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2498 /* Directory operations */
2500 .opendir_fn = vfswrap_opendir,
2501 .fdopendir_fn = vfswrap_fdopendir,
2502 .readdir_fn = vfswrap_readdir,
2503 .seekdir_fn = vfswrap_seekdir,
2504 .telldir_fn = vfswrap_telldir,
2505 .rewind_dir_fn = vfswrap_rewinddir,
2506 .mkdir_fn = vfswrap_mkdir,
2507 .rmdir_fn = vfswrap_rmdir,
2508 .closedir_fn = vfswrap_closedir,
2509 .init_search_op_fn = vfswrap_init_search_op,
2511 /* File operations */
2513 .open_fn = vfswrap_open,
2514 .create_file_fn = vfswrap_create_file,
2515 .close_fn = vfswrap_close,
2516 .read_fn = vfswrap_read,
2517 .pread_fn = vfswrap_pread,
2518 .pread_send_fn = vfswrap_pread_send,
2519 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2520 .write_fn = vfswrap_write,
2521 .pwrite_fn = vfswrap_pwrite,
2522 .pwrite_send_fn = vfswrap_pwrite_send,
2523 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2524 .lseek_fn = vfswrap_lseek,
2525 .sendfile_fn = vfswrap_sendfile,
2526 .recvfile_fn = vfswrap_recvfile,
2527 .rename_fn = vfswrap_rename,
2528 .fsync_fn = vfswrap_fsync,
2529 .fsync_send_fn = vfswrap_fsync_send,
2530 .fsync_recv_fn = vfswrap_asys_int_recv,
2531 .stat_fn = vfswrap_stat,
2532 .fstat_fn = vfswrap_fstat,
2533 .lstat_fn = vfswrap_lstat,
2534 .get_alloc_size_fn = vfswrap_get_alloc_size,
2535 .unlink_fn = vfswrap_unlink,
2536 .chmod_fn = vfswrap_chmod,
2537 .fchmod_fn = vfswrap_fchmod,
2538 .chown_fn = vfswrap_chown,
2539 .fchown_fn = vfswrap_fchown,
2540 .lchown_fn = vfswrap_lchown,
2541 .chdir_fn = vfswrap_chdir,
2542 .getwd_fn = vfswrap_getwd,
2543 .ntimes_fn = vfswrap_ntimes,
2544 .ftruncate_fn = vfswrap_ftruncate,
2545 .fallocate_fn = vfswrap_fallocate,
2546 .lock_fn = vfswrap_lock,
2547 .kernel_flock_fn = vfswrap_kernel_flock,
2548 .linux_setlease_fn = vfswrap_linux_setlease,
2549 .getlock_fn = vfswrap_getlock,
2550 .symlink_fn = vfswrap_symlink,
2551 .readlink_fn = vfswrap_readlink,
2552 .link_fn = vfswrap_link,
2553 .mknod_fn = vfswrap_mknod,
2554 .realpath_fn = vfswrap_realpath,
2555 .notify_watch_fn = vfswrap_notify_watch,
2556 .chflags_fn = vfswrap_chflags,
2557 .file_id_create_fn = vfswrap_file_id_create,
2558 .streaminfo_fn = vfswrap_streaminfo,
2559 .get_real_filename_fn = vfswrap_get_real_filename,
2560 .connectpath_fn = vfswrap_connectpath,
2561 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2562 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2563 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2564 .strict_lock_fn = vfswrap_strict_lock,
2565 .strict_unlock_fn = vfswrap_strict_unlock,
2566 .translate_name_fn = vfswrap_translate_name,
2567 .fsctl_fn = vfswrap_fsctl,
2568 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2569 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2571 /* NT ACL operations. */
2573 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2574 .get_nt_acl_fn = vfswrap_get_nt_acl,
2575 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2576 .audit_file_fn = vfswrap_audit_file,
2578 /* POSIX ACL operations. */
2580 .chmod_acl_fn = vfswrap_chmod_acl,
2581 .fchmod_acl_fn = vfswrap_fchmod_acl,
2583 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2584 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2585 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2586 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2587 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2588 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2589 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2591 /* EA operations. */
2592 .getxattr_fn = vfswrap_getxattr,
2593 .fgetxattr_fn = vfswrap_fgetxattr,
2594 .listxattr_fn = vfswrap_listxattr,
2595 .flistxattr_fn = vfswrap_flistxattr,
2596 .removexattr_fn = vfswrap_removexattr,
2597 .fremovexattr_fn = vfswrap_fremovexattr,
2598 .setxattr_fn = vfswrap_setxattr,
2599 .fsetxattr_fn = vfswrap_fsetxattr,
2601 /* aio operations */
2602 .aio_force_fn = vfswrap_aio_force,
2604 /* offline operations */
2605 .is_offline_fn = vfswrap_is_offline,
2606 .set_offline_fn = vfswrap_set_offline,
2608 /* durable handle operations */
2609 .durable_cookie_fn = vfswrap_durable_cookie,
2610 .durable_disconnect_fn = vfswrap_durable_disconnect,
2611 .durable_reconnect_fn = vfswrap_durable_reconnect,
2614 NTSTATUS vfs_default_init(void);
2615 NTSTATUS vfs_default_init(void)
2617 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2618 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);