s3:net_idmap_dump add missing braces
[Samba/gebeck_regimport.git] / source3 / modules / vfs_default.c
blob8a03ea372a244e5d1ddb7e6c0a6773474170b9d0
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 NTSTATUS status;
117 int ret;
119 ZERO_STRUCT(statbuf);
120 ret = sys_statvfs(conn->connectpath, &statbuf);
121 if (ret == 0) {
122 caps = statbuf.FsCapabilities;
125 *p_ts_res = TIMESTAMP_SET_SECONDS;
127 /* Work out what timestamp resolution we can
128 * use when setting a timestamp. */
130 status = create_synthetic_smb_fname(talloc_tos(),
131 conn->connectpath,
132 NULL,
133 NULL,
134 &smb_fname_cpath);
135 if (!NT_STATUS_IS_OK(status)) {
136 return caps;
139 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
140 if (ret == -1) {
141 TALLOC_FREE(smb_fname_cpath);
142 return caps;
145 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
146 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
147 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
148 /* If any of the normal UNIX directory timestamps
149 * have a non-zero tv_nsec component assume
150 * we might be able to set sub-second timestamps.
151 * See what filetime set primitives we have.
153 #if defined(HAVE_UTIMENSAT)
154 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
155 #elif defined(HAVE_UTIMES)
156 /* utimes allows msec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_MSEC;
158 #elif defined(HAVE_UTIME)
159 /* utime only allows sec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_SECONDS;
161 #endif
163 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
164 "resolution of %s "
165 "available on share %s, directory %s\n",
166 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
167 lp_servicename(talloc_tos(), conn->params->service),
168 conn->connectpath ));
170 TALLOC_FREE(smb_fname_cpath);
171 return caps;
174 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
175 struct dfs_GetDFSReferral *r)
177 struct junction_map *junction = NULL;
178 int consumedcnt = 0;
179 bool self_referral = false;
180 char *pathnamep = NULL;
181 char *local_dfs_path = NULL;
182 NTSTATUS status;
183 int i;
184 uint16_t max_referral_level = r->in.req.max_referral_level;
186 if (DEBUGLVL(10)) {
187 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
190 /* get the junction entry */
191 if (r->in.req.servername == NULL) {
192 return NT_STATUS_NOT_FOUND;
196 * Trim pathname sent by client so it begins with only one backslash.
197 * Two backslashes confuse some dfs clients
200 local_dfs_path = talloc_strdup(r, r->in.req.servername);
201 if (local_dfs_path == NULL) {
202 return NT_STATUS_NO_MEMORY;
204 pathnamep = local_dfs_path;
205 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
206 IS_DIRECTORY_SEP(pathnamep[1])) {
207 pathnamep++;
210 junction = talloc_zero(r, struct junction_map);
211 if (junction == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 /* The following call can change cwd. */
216 status = get_referred_path(r, pathnamep,
217 !handle->conn->sconn->using_smb2,
218 junction, &consumedcnt, &self_referral);
219 if (!NT_STATUS_IS_OK(status)) {
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 return status;
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 if (!self_referral) {
226 pathnamep[consumedcnt] = '\0';
228 if (DEBUGLVL(3)) {
229 dbgtext("setup_dfs_referral: Path %s to "
230 "alternate path(s):",
231 pathnamep);
232 for (i=0; i < junction->referral_count; i++) {
233 dbgtext(" %s",
234 junction->referral_list[i].alternate_path);
236 dbgtext(".\n");
240 if (r->in.req.max_referral_level <= 2) {
241 max_referral_level = 2;
243 if (r->in.req.max_referral_level >= 3) {
244 max_referral_level = 3;
247 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
248 if (r->out.resp == NULL) {
249 return NT_STATUS_NO_MEMORY;
252 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
253 r->out.resp->nb_referrals = junction->referral_count;
255 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
256 if (self_referral) {
257 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
260 r->out.resp->referral_entries = talloc_zero_array(r,
261 struct dfs_referral_type,
262 r->out.resp->nb_referrals);
263 if (r->out.resp->referral_entries == NULL) {
264 return NT_STATUS_NO_MEMORY;
267 switch (max_referral_level) {
268 case 2:
269 for(i=0; i < junction->referral_count; i++) {
270 struct referral *ref = &junction->referral_list[i];
271 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
272 struct dfs_referral_type *t =
273 &r->out.resp->referral_entries[i];
274 struct dfs_referral_v2 *v2 = &t->referral.v2;
276 t->version = 2;
277 v2->size = VERSION2_REFERRAL_SIZE;
278 if (self_referral) {
279 v2->server_type = DFS_SERVER_ROOT;
280 } else {
281 v2->server_type = DFS_SERVER_NON_ROOT;
283 v2->entry_flags = 0;
284 v2->proximity = ref->proximity;
285 v2->ttl = ref->ttl;
286 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
287 if (v2->DFS_path == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
291 if (v2->DFS_alt_path == NULL) {
292 return NT_STATUS_NO_MEMORY;
294 v2->netw_address = talloc_strdup(mem_ctx,
295 ref->alternate_path);
296 if (v2->netw_address == NULL) {
297 return NT_STATUS_NO_MEMORY;
301 break;
302 case 3:
303 for(i=0; i < junction->referral_count; i++) {
304 struct referral *ref = &junction->referral_list[i];
305 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
306 struct dfs_referral_type *t =
307 &r->out.resp->referral_entries[i];
308 struct dfs_referral_v3 *v3 = &t->referral.v3;
309 struct dfs_normal_referral *r1 = &v3->referrals.r1;
311 t->version = 3;
312 v3->size = VERSION3_REFERRAL_SIZE;
313 if (self_referral) {
314 v3->server_type = DFS_SERVER_ROOT;
315 } else {
316 v3->server_type = DFS_SERVER_NON_ROOT;
318 v3->entry_flags = 0;
319 v3->ttl = ref->ttl;
320 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
321 if (r1->DFS_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
325 if (r1->DFS_alt_path == NULL) {
326 return NT_STATUS_NO_MEMORY;
328 r1->netw_address = talloc_strdup(mem_ctx,
329 ref->alternate_path);
330 if (r1->netw_address == NULL) {
331 return NT_STATUS_NO_MEMORY;
334 break;
335 default:
336 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
337 "version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
342 if (DEBUGLVL(10)) {
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
346 return NT_STATUS_OK;
349 /* Directory operations */
351 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
353 DIR *result;
355 START_PROFILE(syscall_opendir);
356 result = opendir(fname);
357 END_PROFILE(syscall_opendir);
358 return result;
361 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
362 files_struct *fsp,
363 const char *mask,
364 uint32 attr)
366 DIR *result;
368 START_PROFILE(syscall_fdopendir);
369 result = sys_fdopendir(fsp->fh->fd);
370 END_PROFILE(syscall_fdopendir);
371 return result;
375 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
376 DIR *dirp,
377 SMB_STRUCT_STAT *sbuf)
379 struct dirent *result;
381 START_PROFILE(syscall_readdir);
382 result = readdir(dirp);
383 /* Default Posix readdir() does not give us stat info.
384 * Set to invalid to indicate we didn't return this info. */
385 if (sbuf)
386 SET_STAT_INVALID(*sbuf);
387 END_PROFILE(syscall_readdir);
388 return result;
391 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
393 START_PROFILE(syscall_seekdir);
394 seekdir(dirp, offset);
395 END_PROFILE(syscall_seekdir);
398 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
400 long result;
401 START_PROFILE(syscall_telldir);
402 result = telldir(dirp);
403 END_PROFILE(syscall_telldir);
404 return result;
407 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
409 START_PROFILE(syscall_rewinddir);
410 rewinddir(dirp);
411 END_PROFILE(syscall_rewinddir);
414 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
416 int result;
417 bool has_dacl = False;
418 char *parent = NULL;
420 START_PROFILE(syscall_mkdir);
422 if (lp_inherit_acls(SNUM(handle->conn))
423 && parent_dirname(talloc_tos(), path, &parent, NULL)
424 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
425 mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
427 TALLOC_FREE(parent);
429 result = mkdir(path, mode);
431 if (result == 0 && !has_dacl) {
433 * We need to do this as the default behavior of POSIX ACLs
434 * is to set the mask to be the requested group permission
435 * bits, not the group permission bits to be the requested
436 * group permission bits. This is not what we want, as it will
437 * mess up any inherited ACL bits that were set. JRA.
439 int saved_errno = errno; /* We may get ENOSYS */
440 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
441 errno = saved_errno;
444 END_PROFILE(syscall_mkdir);
445 return result;
448 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
450 int result;
452 START_PROFILE(syscall_rmdir);
453 result = rmdir(path);
454 END_PROFILE(syscall_rmdir);
455 return result;
458 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
460 int result;
462 START_PROFILE(syscall_closedir);
463 result = closedir(dirp);
464 END_PROFILE(syscall_closedir);
465 return result;
468 static void vfswrap_init_search_op(vfs_handle_struct *handle,
469 DIR *dirp)
471 /* Default behavior is a NOOP */
474 /* File operations */
476 static int vfswrap_open(vfs_handle_struct *handle,
477 struct smb_filename *smb_fname,
478 files_struct *fsp, int flags, mode_t mode)
480 int result = -1;
482 START_PROFILE(syscall_open);
484 if (smb_fname->stream_name) {
485 errno = ENOENT;
486 goto out;
489 result = open(smb_fname->base_name, flags, mode);
490 out:
491 END_PROFILE(syscall_open);
492 return result;
495 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
496 struct smb_request *req,
497 uint16_t root_dir_fid,
498 struct smb_filename *smb_fname,
499 uint32_t access_mask,
500 uint32_t share_access,
501 uint32_t create_disposition,
502 uint32_t create_options,
503 uint32_t file_attributes,
504 uint32_t oplock_request,
505 uint64_t allocation_size,
506 uint32_t private_flags,
507 struct security_descriptor *sd,
508 struct ea_list *ea_list,
509 files_struct **result,
510 int *pinfo)
512 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
513 access_mask, share_access,
514 create_disposition, create_options,
515 file_attributes, oplock_request,
516 allocation_size, private_flags,
517 sd, ea_list, result,
518 pinfo);
521 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
523 int result;
525 START_PROFILE(syscall_close);
526 result = fd_close_posix(fsp);
527 END_PROFILE(syscall_close);
528 return result;
531 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
533 ssize_t result;
535 START_PROFILE_BYTES(syscall_read, n);
536 result = sys_read(fsp->fh->fd, data, n);
537 END_PROFILE(syscall_read);
538 return result;
541 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
542 size_t n, off_t offset)
544 ssize_t result;
546 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
547 START_PROFILE_BYTES(syscall_pread, n);
548 result = sys_pread(fsp->fh->fd, data, n, offset);
549 END_PROFILE(syscall_pread);
551 if (result == -1 && errno == ESPIPE) {
552 /* Maintain the fiction that pipes can be seeked (sought?) on. */
553 result = SMB_VFS_READ(fsp, data, n);
554 fsp->fh->pos = 0;
557 #else /* HAVE_PREAD */
558 off_t curr;
559 int lerrno;
561 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
562 if (curr == -1 && errno == ESPIPE) {
563 /* Maintain the fiction that pipes can be seeked (sought?) on. */
564 result = SMB_VFS_READ(fsp, data, n);
565 fsp->fh->pos = 0;
566 return result;
569 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
570 return -1;
573 errno = 0;
574 result = SMB_VFS_READ(fsp, data, n);
575 lerrno = errno;
577 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
578 errno = lerrno;
580 #endif /* HAVE_PREAD */
582 return result;
585 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
587 ssize_t result;
589 START_PROFILE_BYTES(syscall_write, n);
590 result = sys_write(fsp->fh->fd, data, n);
591 END_PROFILE(syscall_write);
592 return result;
595 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
596 size_t n, off_t offset)
598 ssize_t result;
600 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
601 START_PROFILE_BYTES(syscall_pwrite, n);
602 result = sys_pwrite(fsp->fh->fd, data, n, offset);
603 END_PROFILE(syscall_pwrite);
605 if (result == -1 && errno == ESPIPE) {
606 /* Maintain the fiction that pipes can be sought on. */
607 result = SMB_VFS_WRITE(fsp, data, n);
610 #else /* HAVE_PWRITE */
611 off_t curr;
612 int lerrno;
614 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
615 if (curr == -1) {
616 return -1;
619 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
620 return -1;
623 result = SMB_VFS_WRITE(fsp, data, n);
624 lerrno = errno;
626 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
627 errno = lerrno;
629 #endif /* HAVE_PWRITE */
631 return result;
634 static void vfswrap_asys_finished(struct tevent_context *ev,
635 struct tevent_fd *fde,
636 uint16_t flags, void *p);
638 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
640 int ret;
641 int fd;
643 if (conn->asys_ctx != NULL) {
644 return true;
646 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
647 if (ret != 0) {
648 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
649 return false;
652 fd = asys_signalfd(conn->asys_ctx);
654 set_blocking(fd, false);
656 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
657 TEVENT_FD_READ,
658 vfswrap_asys_finished,
659 conn->asys_ctx);
660 if (conn->asys_fde == NULL) {
661 DEBUG(1, ("tevent_add_fd failed\n"));
662 asys_context_destroy(conn->asys_ctx);
663 conn->asys_ctx = NULL;
664 return false;
666 return true;
669 struct vfswrap_asys_state {
670 struct asys_context *asys_ctx;
671 struct tevent_req *req;
672 ssize_t ret;
673 int err;
676 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
678 asys_cancel(s->asys_ctx, s->req);
679 return 0;
682 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
683 TALLOC_CTX *mem_ctx,
684 struct tevent_context *ev,
685 struct files_struct *fsp,
686 void *data,
687 size_t n, off_t offset)
689 struct tevent_req *req;
690 struct vfswrap_asys_state *state;
691 int ret;
693 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
694 if (req == NULL) {
695 return NULL;
697 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
698 tevent_req_oom(req);
699 return tevent_req_post(req, ev);
701 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
702 state->req = req;
704 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
705 if (ret != 0) {
706 tevent_req_error(req, ret);
707 return tevent_req_post(req, ev);
709 talloc_set_destructor(state, vfswrap_asys_state_destructor);
711 return req;
714 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
715 TALLOC_CTX *mem_ctx,
716 struct tevent_context *ev,
717 struct files_struct *fsp,
718 const void *data,
719 size_t n, off_t offset)
721 struct tevent_req *req;
722 struct vfswrap_asys_state *state;
723 int ret;
725 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
726 if (req == NULL) {
727 return NULL;
729 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
730 tevent_req_oom(req);
731 return tevent_req_post(req, ev);
733 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
734 state->req = req;
736 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
737 if (ret != 0) {
738 tevent_req_error(req, ret);
739 return tevent_req_post(req, ev);
741 talloc_set_destructor(state, vfswrap_asys_state_destructor);
743 return req;
746 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
747 TALLOC_CTX *mem_ctx,
748 struct tevent_context *ev,
749 struct files_struct *fsp)
751 struct tevent_req *req;
752 struct vfswrap_asys_state *state;
753 int ret;
755 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
756 if (req == NULL) {
757 return NULL;
759 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
760 tevent_req_oom(req);
761 return tevent_req_post(req, ev);
763 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
764 state->req = req;
766 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
767 if (ret != 0) {
768 tevent_req_error(req, ret);
769 return tevent_req_post(req, ev);
771 talloc_set_destructor(state, vfswrap_asys_state_destructor);
773 return req;
776 static void vfswrap_asys_finished(struct tevent_context *ev,
777 struct tevent_fd *fde,
778 uint16_t flags, void *p)
780 struct asys_context *asys_ctx = (struct asys_context *)p;
781 struct tevent_req *req;
782 struct vfswrap_asys_state *state;
783 int res;
784 ssize_t ret;
785 int err;
786 void *private_data;
788 if ((flags & TEVENT_FD_READ) == 0) {
789 return;
792 while (true) {
793 res = asys_result(asys_ctx, &ret, &err, &private_data);
794 if (res == EINTR || res == EAGAIN) {
795 return;
797 #ifdef EWOULDBLOCK
798 if (res == EWOULDBLOCK) {
799 return;
801 #endif
803 if (res == ECANCELED) {
804 return;
807 if (res != 0) {
808 DEBUG(1, ("asys_result returned %s\n", strerror(res)));
809 return;
812 req = talloc_get_type_abort(private_data, struct tevent_req);
813 state = tevent_req_data(req, struct vfswrap_asys_state);
815 talloc_set_destructor(state, NULL);
817 state->ret = ret;
818 state->err = err;
819 tevent_req_defer_callback(req, ev);
820 tevent_req_done(req);
824 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
826 struct vfswrap_asys_state *state = tevent_req_data(
827 req, struct vfswrap_asys_state);
829 if (tevent_req_is_unix_error(req, err)) {
830 return -1;
832 *err = state->err;
833 return state->ret;
836 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
838 struct vfswrap_asys_state *state = tevent_req_data(
839 req, struct vfswrap_asys_state);
841 if (tevent_req_is_unix_error(req, err)) {
842 return -1;
844 *err = state->err;
845 return state->ret;
848 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
850 off_t result = 0;
852 START_PROFILE(syscall_lseek);
854 /* Cope with 'stat' file opens. */
855 if (fsp->fh->fd != -1)
856 result = lseek(fsp->fh->fd, offset, whence);
859 * We want to maintain the fiction that we can seek
860 * on a fifo for file system purposes. This allows
861 * people to set up UNIX fifo's that feed data to Windows
862 * applications. JRA.
865 if((result == -1) && (errno == ESPIPE)) {
866 result = 0;
867 errno = 0;
870 END_PROFILE(syscall_lseek);
871 return result;
874 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
875 off_t offset, size_t n)
877 ssize_t result;
879 START_PROFILE_BYTES(syscall_sendfile, n);
880 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
881 END_PROFILE(syscall_sendfile);
882 return result;
885 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
886 int fromfd,
887 files_struct *tofsp,
888 off_t offset,
889 size_t n)
891 ssize_t result;
893 START_PROFILE_BYTES(syscall_recvfile, n);
894 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
895 END_PROFILE(syscall_recvfile);
896 return result;
899 static int vfswrap_rename(vfs_handle_struct *handle,
900 const struct smb_filename *smb_fname_src,
901 const struct smb_filename *smb_fname_dst)
903 int result = -1;
905 START_PROFILE(syscall_rename);
907 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
908 errno = ENOENT;
909 goto out;
912 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
914 out:
915 END_PROFILE(syscall_rename);
916 return result;
919 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
921 #ifdef HAVE_FSYNC
922 int result;
924 START_PROFILE(syscall_fsync);
925 result = fsync(fsp->fh->fd);
926 END_PROFILE(syscall_fsync);
927 return result;
928 #else
929 return 0;
930 #endif
933 static int vfswrap_stat(vfs_handle_struct *handle,
934 struct smb_filename *smb_fname)
936 int result = -1;
938 START_PROFILE(syscall_stat);
940 if (smb_fname->stream_name) {
941 errno = ENOENT;
942 goto out;
945 result = sys_stat(smb_fname->base_name, &smb_fname->st,
946 lp_fake_dir_create_times(SNUM(handle->conn)));
947 out:
948 END_PROFILE(syscall_stat);
949 return result;
952 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
954 int result;
956 START_PROFILE(syscall_fstat);
957 result = sys_fstat(fsp->fh->fd,
958 sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
959 END_PROFILE(syscall_fstat);
960 return result;
963 static int vfswrap_lstat(vfs_handle_struct *handle,
964 struct smb_filename *smb_fname)
966 int result = -1;
968 START_PROFILE(syscall_lstat);
970 if (smb_fname->stream_name) {
971 errno = ENOENT;
972 goto out;
975 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
976 lp_fake_dir_create_times(SNUM(handle->conn)));
977 out:
978 END_PROFILE(syscall_lstat);
979 return result;
982 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
983 const char *name,
984 enum vfs_translate_direction direction,
985 TALLOC_CTX *mem_ctx,
986 char **mapped_name)
988 return NT_STATUS_NONE_MAPPED;
992 * Implement the default fsctl operation.
994 static bool vfswrap_logged_ioctl_message = false;
996 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
997 struct files_struct *fsp,
998 TALLOC_CTX *ctx,
999 uint32_t function,
1000 uint16_t req_flags, /* Needed for UNICODE ... */
1001 const uint8_t *_in_data,
1002 uint32_t in_len,
1003 uint8_t **_out_data,
1004 uint32_t max_out_len,
1005 uint32_t *out_len)
1007 const char *in_data = (const char *)_in_data;
1008 char **out_data = (char **)_out_data;
1010 switch (function) {
1011 case FSCTL_SET_SPARSE:
1013 bool set_sparse = true;
1014 NTSTATUS status;
1016 if (in_len >= 1 && in_data[0] == 0) {
1017 set_sparse = false;
1020 status = file_set_sparse(handle->conn, fsp, set_sparse);
1022 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1023 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1024 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1025 nt_errstr(status)));
1027 return status;
1030 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1032 unsigned char objid[16];
1033 char *return_data = NULL;
1035 /* This should return the object-id on this file.
1036 * I think I'll make this be the inode+dev. JRA.
1039 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1040 fsp_fnum_dbg(fsp)));
1042 *out_len = (max_out_len >= 64) ? 64 : max_out_len;
1043 /* Hmmm, will this cause problems if less data asked for? */
1044 return_data = talloc_array(ctx, char, 64);
1045 if (return_data == NULL) {
1046 return NT_STATUS_NO_MEMORY;
1049 /* For backwards compatibility only store the dev/inode. */
1050 push_file_id_16(return_data, &fsp->file_id);
1051 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1052 push_file_id_16(return_data+32, &fsp->file_id);
1053 *out_data = return_data;
1054 return NT_STATUS_OK;
1057 case FSCTL_GET_REPARSE_POINT:
1059 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1060 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1061 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1062 return NT_STATUS_NOT_A_REPARSE_POINT;
1065 case FSCTL_SET_REPARSE_POINT:
1067 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1068 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1069 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1070 return NT_STATUS_NOT_A_REPARSE_POINT;
1073 case FSCTL_GET_SHADOW_COPY_DATA:
1076 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1077 * and return their volume names. If max_data_count is 16, then it is just
1078 * asking for the number of volumes and length of the combined names.
1080 * pdata is the data allocated by our caller, but that uses
1081 * total_data_count (which is 0 in our case) rather than max_data_count.
1082 * Allocate the correct amount and return the pointer to let
1083 * it be deallocated when we return.
1085 struct shadow_copy_data *shadow_data = NULL;
1086 bool labels = False;
1087 uint32 labels_data_count = 0;
1088 uint32 i;
1089 char *cur_pdata = NULL;
1091 if (max_out_len < 16) {
1092 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1093 max_out_len));
1094 return NT_STATUS_INVALID_PARAMETER;
1097 if (max_out_len > 16) {
1098 labels = True;
1101 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1102 if (shadow_data == NULL) {
1103 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1104 return NT_STATUS_NO_MEMORY;
1108 * Call the VFS routine to actually do the work.
1110 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1111 TALLOC_FREE(shadow_data);
1112 if (errno == ENOSYS) {
1113 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
1114 fsp->conn->connectpath));
1115 return NT_STATUS_NOT_SUPPORTED;
1116 } else {
1117 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
1118 fsp->conn->connectpath));
1119 return NT_STATUS_UNSUCCESSFUL;
1123 labels_data_count = (shadow_data->num_volumes * 2 *
1124 sizeof(SHADOW_COPY_LABEL)) + 2;
1126 if (!labels) {
1127 *out_len = 16;
1128 } else {
1129 *out_len = 12 + labels_data_count + 4;
1132 if (max_out_len < *out_len) {
1133 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1134 max_out_len, *out_len));
1135 TALLOC_FREE(shadow_data);
1136 return NT_STATUS_BUFFER_TOO_SMALL;
1139 cur_pdata = talloc_array(ctx, char, *out_len);
1140 if (cur_pdata == NULL) {
1141 TALLOC_FREE(shadow_data);
1142 return NT_STATUS_NO_MEMORY;
1145 *out_data = cur_pdata;
1147 /* num_volumes 4 bytes */
1148 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1150 if (labels) {
1151 /* num_labels 4 bytes */
1152 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1155 /* needed_data_count 4 bytes */
1156 SIVAL(cur_pdata, 8, labels_data_count + 4);
1158 cur_pdata += 12;
1160 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1161 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1162 if (labels && shadow_data->labels) {
1163 for (i=0; i<shadow_data->num_volumes; i++) {
1164 srvstr_push(cur_pdata, req_flags,
1165 cur_pdata, shadow_data->labels[i],
1166 2 * sizeof(SHADOW_COPY_LABEL),
1167 STR_UNICODE|STR_TERMINATE);
1168 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1169 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1173 TALLOC_FREE(shadow_data);
1175 return NT_STATUS_OK;
1178 case FSCTL_FIND_FILES_BY_SID:
1180 /* pretend this succeeded -
1182 * we have to send back a list with all files owned by this SID
1184 * but I have to check that --metze
1186 struct dom_sid sid;
1187 uid_t uid;
1188 size_t sid_len;
1190 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1191 fsp_fnum_dbg(fsp)));
1193 if (in_len < 8) {
1194 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1195 return NT_STATUS_INVALID_PARAMETER;
1198 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1200 /* unknown 4 bytes: this is not the length of the sid :-( */
1201 /*unknown = IVAL(pdata,0);*/
1203 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1204 return NT_STATUS_INVALID_PARAMETER;
1206 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1208 if (!sid_to_uid(&sid, &uid)) {
1209 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1210 sid_string_dbg(&sid),
1211 (unsigned long)sid_len));
1212 uid = (-1);
1215 /* we can take a look at the find source :-)
1217 * find ./ -uid $uid -name '*' is what we need here
1220 * and send 4bytes len and then NULL terminated unicode strings
1221 * for each file
1223 * but I don't know how to deal with the paged results
1224 * (maybe we can hang the result anywhere in the fsp struct)
1226 * but I don't know how to deal with the paged results
1227 * (maybe we can hang the result anywhere in the fsp struct)
1229 * we don't send all files at once
1230 * and at the next we should *not* start from the beginning,
1231 * so we have to cache the result
1233 * --metze
1236 /* this works for now... */
1237 return NT_STATUS_OK;
1240 case FSCTL_QUERY_ALLOCATED_RANGES:
1242 /* FIXME: This is just a dummy reply, telling that all of the
1243 * file is allocated. MKS cp needs that.
1244 * Adding the real allocated ranges via FIEMAP on Linux
1245 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1246 * this FSCTL correct for sparse files.
1248 NTSTATUS status;
1249 uint64_t offset, length;
1250 char *out_data_tmp = NULL;
1252 if (in_len != 16) {
1253 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1254 in_len));
1255 return NT_STATUS_INVALID_PARAMETER;
1258 if (max_out_len < 16) {
1259 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1260 max_out_len));
1261 return NT_STATUS_INVALID_PARAMETER;
1264 offset = BVAL(in_data,0);
1265 length = BVAL(in_data,8);
1267 if (offset + length < offset) {
1268 /* No 64-bit integer wrap. */
1269 return NT_STATUS_INVALID_PARAMETER;
1272 /* Shouldn't this be SMB_VFS_STAT ... ? */
1273 status = vfs_stat_fsp(fsp);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 return status;
1278 *out_len = 16;
1279 out_data_tmp = talloc_array(ctx, char, *out_len);
1280 if (out_data_tmp == NULL) {
1281 DEBUG(10, ("unable to allocate memory for response\n"));
1282 return NT_STATUS_NO_MEMORY;
1285 if (offset > fsp->fsp_name->st.st_ex_size ||
1286 fsp->fsp_name->st.st_ex_size == 0 ||
1287 length == 0) {
1288 memset(out_data_tmp, 0, *out_len);
1289 } else {
1290 uint64_t end = offset + length;
1291 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1292 SBVAL(out_data_tmp, 0, 0);
1293 SBVAL(out_data_tmp, 8, end);
1296 *out_data = out_data_tmp;
1298 return NT_STATUS_OK;
1301 case FSCTL_IS_VOLUME_DIRTY:
1303 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1304 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1306 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1307 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1309 return NT_STATUS_INVALID_PARAMETER;
1312 default:
1314 * Only print once ... unfortunately there could be lots of
1315 * different FSCTLs that are called.
1317 if (!vfswrap_logged_ioctl_message) {
1318 vfswrap_logged_ioctl_message = true;
1319 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1320 __func__, function));
1324 return NT_STATUS_NOT_SUPPORTED;
1327 struct vfs_cc_state {
1328 off_t copied;
1329 uint8_t buf[65536];
1332 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1333 TALLOC_CTX *mem_ctx,
1334 struct tevent_context *ev,
1335 struct files_struct *src_fsp,
1336 off_t src_off,
1337 struct files_struct *dest_fsp,
1338 off_t dest_off,
1339 off_t num)
1341 struct tevent_req *req;
1342 struct vfs_cc_state *vfs_cc_state;
1343 NTSTATUS status;
1345 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1346 (unsigned long)num));
1348 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1349 if (req == NULL) {
1350 return NULL;
1353 status = vfs_stat_fsp(src_fsp);
1354 if (tevent_req_nterror(req, status)) {
1355 return tevent_req_post(req, ev);
1358 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1360 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1361 * If the SourceOffset or SourceOffset + Length extends beyond
1362 * the end of file, the server SHOULD<240> treat this as a
1363 * STATUS_END_OF_FILE error.
1364 * ...
1365 * <240> Section 3.3.5.15.6: Windows servers will return
1366 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1368 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1369 return tevent_req_post(req, ev);
1372 /* could use 2.6.33+ sendfile here to do this in kernel */
1373 while (vfs_cc_state->copied < num) {
1374 ssize_t ret;
1375 struct lock_struct lck;
1376 int saved_errno;
1378 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1379 num - vfs_cc_state->copied);
1381 init_strict_lock_struct(src_fsp,
1382 src_fsp->op->global->open_persistent_id,
1383 src_off,
1384 this_num,
1385 READ_LOCK,
1386 &lck);
1388 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1389 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1390 return tevent_req_post(req, ev);
1393 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1394 this_num, src_off);
1395 if (ret == -1) {
1396 saved_errno = errno;
1399 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1401 if (ret == -1) {
1402 errno = saved_errno;
1403 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1404 return tevent_req_post(req, ev);
1406 if (ret != this_num) {
1407 /* zero tolerance for short reads */
1408 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1409 return tevent_req_post(req, ev);
1412 src_off += ret;
1414 init_strict_lock_struct(dest_fsp,
1415 dest_fsp->op->global->open_persistent_id,
1416 dest_off,
1417 this_num,
1418 WRITE_LOCK,
1419 &lck);
1421 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1422 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1423 return tevent_req_post(req, ev);
1426 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1427 this_num, dest_off);
1428 if (ret == -1) {
1429 saved_errno = errno;
1432 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1434 if (ret == -1) {
1435 errno = saved_errno;
1436 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1437 return tevent_req_post(req, ev);
1439 if (ret != this_num) {
1440 /* zero tolerance for short writes */
1441 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1442 return tevent_req_post(req, ev);
1444 dest_off += ret;
1446 vfs_cc_state->copied += this_num;
1449 tevent_req_done(req);
1450 return tevent_req_post(req, ev);
1453 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1454 struct tevent_req *req,
1455 off_t *copied)
1457 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1458 struct vfs_cc_state);
1459 NTSTATUS status;
1461 if (tevent_req_is_nterror(req, &status)) {
1462 DEBUG(2, ("server side copy chunk failed: %s\n",
1463 nt_errstr(status)));
1464 *copied = 0;
1465 tevent_req_received(req);
1466 return status;
1469 *copied = vfs_cc_state->copied;
1470 DEBUG(10, ("server side copy chunk copied %lu\n",
1471 (unsigned long)*copied));
1472 tevent_req_received(req);
1474 return NT_STATUS_OK;
1477 /********************************************************************
1478 Given a stat buffer return the allocated size on disk, taking into
1479 account sparse files.
1480 ********************************************************************/
1481 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1482 struct files_struct *fsp,
1483 const SMB_STRUCT_STAT *sbuf)
1485 uint64_t result;
1487 START_PROFILE(syscall_get_alloc_size);
1489 if(S_ISDIR(sbuf->st_ex_mode)) {
1490 result = 0;
1491 goto out;
1494 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1495 /* The type of st_blocksize is blkcnt_t which *MUST* be
1496 signed (according to POSIX) and can be less than 64-bits.
1497 Ensure when we're converting to 64 bits wide we don't
1498 sign extend. */
1499 #if defined(SIZEOF_BLKCNT_T_8)
1500 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1501 #elif defined(SIZEOF_BLKCNT_T_4)
1503 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1504 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1506 #else
1507 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1508 #endif
1509 #else
1510 result = get_file_size_stat(sbuf);
1511 #endif
1513 if (fsp && fsp->initial_allocation_size)
1514 result = MAX(result,fsp->initial_allocation_size);
1516 result = smb_roundup(handle->conn, result);
1518 out:
1519 END_PROFILE(syscall_get_alloc_size);
1520 return result;
1523 static int vfswrap_unlink(vfs_handle_struct *handle,
1524 const struct smb_filename *smb_fname)
1526 int result = -1;
1528 START_PROFILE(syscall_unlink);
1530 if (smb_fname->stream_name) {
1531 errno = ENOENT;
1532 goto out;
1534 result = unlink(smb_fname->base_name);
1536 out:
1537 END_PROFILE(syscall_unlink);
1538 return result;
1541 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1543 int result;
1545 START_PROFILE(syscall_chmod);
1548 * We need to do this due to the fact that the default POSIX ACL
1549 * chmod modifies the ACL *mask* for the group owner, not the
1550 * group owner bits directly. JRA.
1555 int saved_errno = errno; /* We might get ENOSYS */
1556 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1557 END_PROFILE(syscall_chmod);
1558 return result;
1560 /* Error - return the old errno. */
1561 errno = saved_errno;
1564 result = chmod(path, mode);
1565 END_PROFILE(syscall_chmod);
1566 return result;
1569 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1571 int result;
1573 START_PROFILE(syscall_fchmod);
1576 * We need to do this due to the fact that the default POSIX ACL
1577 * chmod modifies the ACL *mask* for the group owner, not the
1578 * group owner bits directly. JRA.
1582 int saved_errno = errno; /* We might get ENOSYS */
1583 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1584 END_PROFILE(syscall_fchmod);
1585 return result;
1587 /* Error - return the old errno. */
1588 errno = saved_errno;
1591 #if defined(HAVE_FCHMOD)
1592 result = fchmod(fsp->fh->fd, mode);
1593 #else
1594 result = -1;
1595 errno = ENOSYS;
1596 #endif
1598 END_PROFILE(syscall_fchmod);
1599 return result;
1602 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1604 int result;
1606 START_PROFILE(syscall_chown);
1607 result = chown(path, uid, gid);
1608 END_PROFILE(syscall_chown);
1609 return result;
1612 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1614 #ifdef HAVE_FCHOWN
1615 int result;
1617 START_PROFILE(syscall_fchown);
1618 result = fchown(fsp->fh->fd, uid, gid);
1619 END_PROFILE(syscall_fchown);
1620 return result;
1621 #else
1622 errno = ENOSYS;
1623 return -1;
1624 #endif
1627 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1629 int result;
1631 START_PROFILE(syscall_lchown);
1632 result = lchown(path, uid, gid);
1633 END_PROFILE(syscall_lchown);
1634 return result;
1637 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1639 int result;
1641 START_PROFILE(syscall_chdir);
1642 result = chdir(path);
1643 END_PROFILE(syscall_chdir);
1644 return result;
1647 static char *vfswrap_getwd(vfs_handle_struct *handle)
1649 char *result;
1651 START_PROFILE(syscall_getwd);
1652 result = sys_getwd();
1653 END_PROFILE(syscall_getwd);
1654 return result;
1657 /*********************************************************************
1658 nsec timestamp resolution call. Convert down to whatever the underlying
1659 system will support.
1660 **********************************************************************/
1662 static int vfswrap_ntimes(vfs_handle_struct *handle,
1663 const struct smb_filename *smb_fname,
1664 struct smb_file_time *ft)
1666 int result = -1;
1668 START_PROFILE(syscall_ntimes);
1670 if (smb_fname->stream_name) {
1671 errno = ENOENT;
1672 goto out;
1675 if (ft != NULL) {
1676 if (null_timespec(ft->atime)) {
1677 ft->atime= smb_fname->st.st_ex_atime;
1680 if (null_timespec(ft->mtime)) {
1681 ft->mtime = smb_fname->st.st_ex_mtime;
1684 if (!null_timespec(ft->create_time)) {
1685 set_create_timespec_ea(handle->conn,
1686 smb_fname,
1687 ft->create_time);
1690 if ((timespec_compare(&ft->atime,
1691 &smb_fname->st.st_ex_atime) == 0) &&
1692 (timespec_compare(&ft->mtime,
1693 &smb_fname->st.st_ex_mtime) == 0)) {
1694 return 0;
1698 #if defined(HAVE_UTIMENSAT)
1699 if (ft != NULL) {
1700 struct timespec ts[2];
1701 ts[0] = ft->atime;
1702 ts[1] = ft->mtime;
1703 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1704 } else {
1705 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1707 if (!((result == -1) && (errno == ENOSYS))) {
1708 goto out;
1710 #endif
1711 #if defined(HAVE_UTIMES)
1712 if (ft != NULL) {
1713 struct timeval tv[2];
1714 tv[0] = convert_timespec_to_timeval(ft->atime);
1715 tv[1] = convert_timespec_to_timeval(ft->mtime);
1716 result = utimes(smb_fname->base_name, tv);
1717 } else {
1718 result = utimes(smb_fname->base_name, NULL);
1720 if (!((result == -1) && (errno == ENOSYS))) {
1721 goto out;
1723 #endif
1724 #if defined(HAVE_UTIME)
1725 if (ft != NULL) {
1726 struct utimbuf times;
1727 times.actime = convert_timespec_to_time_t(ft->atime);
1728 times.modtime = convert_timespec_to_time_t(ft->mtime);
1729 result = utime(smb_fname->base_name, &times);
1730 } else {
1731 result = utime(smb_fname->base_name, NULL);
1733 if (!((result == -1) && (errno == ENOSYS))) {
1734 goto out;
1736 #endif
1737 errno = ENOSYS;
1738 result = -1;
1740 out:
1741 END_PROFILE(syscall_ntimes);
1742 return result;
1745 /*********************************************************************
1746 A version of ftruncate that will write the space on disk if strict
1747 allocate is set.
1748 **********************************************************************/
1750 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1752 off_t space_to_write;
1753 uint64_t space_avail;
1754 uint64_t bsize,dfree,dsize;
1755 int ret;
1756 NTSTATUS status;
1757 SMB_STRUCT_STAT *pst;
1759 status = vfs_stat_fsp(fsp);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 return -1;
1763 pst = &fsp->fsp_name->st;
1765 #ifdef S_ISFIFO
1766 if (S_ISFIFO(pst->st_ex_mode))
1767 return 0;
1768 #endif
1770 if (pst->st_ex_size == len)
1771 return 0;
1773 /* Shrink - just ftruncate. */
1774 if (pst->st_ex_size > len)
1775 return ftruncate(fsp->fh->fd, len);
1777 space_to_write = len - pst->st_ex_size;
1779 /* for allocation try fallocate first. This can fail on some
1780 platforms e.g. when the filesystem doesn't support it and no
1781 emulation is being done by the libc (like on AIX with JFS1). In that
1782 case we do our own emulation. fallocate implementations can
1783 return ENOTSUP or EINVAL in cases like that. */
1784 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1785 pst->st_ex_size, space_to_write);
1786 if (ret == ENOSPC) {
1787 errno = ENOSPC;
1788 return -1;
1790 if (ret == 0) {
1791 return 0;
1793 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1794 "error %d. Falling back to slow manual allocation\n", ret));
1796 /* available disk space is enough or not? */
1797 space_avail = get_dfree_info(fsp->conn,
1798 fsp->fsp_name->base_name, false,
1799 &bsize,&dfree,&dsize);
1800 /* space_avail is 1k blocks */
1801 if (space_avail == (uint64_t)-1 ||
1802 ((uint64_t)space_to_write/1024 > space_avail) ) {
1803 errno = ENOSPC;
1804 return -1;
1807 /* Write out the real space on disk. */
1808 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1809 if (ret != 0) {
1810 errno = ret;
1811 ret = -1;
1814 return 0;
1817 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1819 int result = -1;
1820 SMB_STRUCT_STAT *pst;
1821 NTSTATUS status;
1822 char c = 0;
1824 START_PROFILE(syscall_ftruncate);
1826 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1827 result = strict_allocate_ftruncate(handle, fsp, len);
1828 END_PROFILE(syscall_ftruncate);
1829 return result;
1832 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1833 ftruncate if the system supports it. Then I discovered that
1834 you can have some filesystems that support ftruncate
1835 expansion and some that don't! On Linux fat can't do
1836 ftruncate extend but ext2 can. */
1838 result = ftruncate(fsp->fh->fd, len);
1839 if (result == 0)
1840 goto done;
1842 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1843 extend a file with ftruncate. Provide alternate implementation
1844 for this */
1846 /* Do an fstat to see if the file is longer than the requested
1847 size in which case the ftruncate above should have
1848 succeeded or shorter, in which case seek to len - 1 and
1849 write 1 byte of zero */
1850 status = vfs_stat_fsp(fsp);
1851 if (!NT_STATUS_IS_OK(status)) {
1852 goto done;
1854 pst = &fsp->fsp_name->st;
1856 #ifdef S_ISFIFO
1857 if (S_ISFIFO(pst->st_ex_mode)) {
1858 result = 0;
1859 goto done;
1861 #endif
1863 if (pst->st_ex_size == len) {
1864 result = 0;
1865 goto done;
1868 if (pst->st_ex_size > len) {
1869 /* the ftruncate should have worked */
1870 goto done;
1873 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1874 goto done;
1877 result = 0;
1879 done:
1881 END_PROFILE(syscall_ftruncate);
1882 return result;
1885 static int vfswrap_fallocate(vfs_handle_struct *handle,
1886 files_struct *fsp,
1887 enum vfs_fallocate_mode mode,
1888 off_t offset,
1889 off_t len)
1891 int result;
1893 START_PROFILE(syscall_fallocate);
1894 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1895 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1896 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1897 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1898 } else {
1899 errno = EINVAL;
1900 result = -1;
1902 END_PROFILE(syscall_fallocate);
1903 return result;
1906 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1908 bool result;
1910 START_PROFILE(syscall_fcntl_lock);
1911 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1912 END_PROFILE(syscall_fcntl_lock);
1913 return result;
1916 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1917 uint32 share_mode, uint32 access_mask)
1919 START_PROFILE(syscall_kernel_flock);
1920 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1921 END_PROFILE(syscall_kernel_flock);
1922 return 0;
1925 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1927 bool result;
1929 START_PROFILE(syscall_fcntl_getlock);
1930 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1931 END_PROFILE(syscall_fcntl_getlock);
1932 return result;
1935 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1936 int leasetype)
1938 int result = -1;
1940 START_PROFILE(syscall_linux_setlease);
1942 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1943 result = linux_setlease(fsp->fh->fd, leasetype);
1944 #else
1945 errno = ENOSYS;
1946 #endif
1947 END_PROFILE(syscall_linux_setlease);
1948 return result;
1951 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1953 int result;
1955 START_PROFILE(syscall_symlink);
1956 result = symlink(oldpath, newpath);
1957 END_PROFILE(syscall_symlink);
1958 return result;
1961 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
1963 int result;
1965 START_PROFILE(syscall_readlink);
1966 result = readlink(path, buf, bufsiz);
1967 END_PROFILE(syscall_readlink);
1968 return result;
1971 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1973 int result;
1975 START_PROFILE(syscall_link);
1976 result = link(oldpath, newpath);
1977 END_PROFILE(syscall_link);
1978 return result;
1981 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
1983 int result;
1985 START_PROFILE(syscall_mknod);
1986 result = sys_mknod(pathname, mode, dev);
1987 END_PROFILE(syscall_mknod);
1988 return result;
1991 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
1993 char *result;
1995 START_PROFILE(syscall_realpath);
1996 #ifdef REALPATH_TAKES_NULL
1997 result = realpath(path, NULL);
1998 #else
1999 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2000 if (result) {
2001 char *resolved_path = realpath(path, result);
2002 if (!resolved_path) {
2003 SAFE_FREE(result);
2004 } else {
2005 /* SMB_ASSERT(result == resolved_path) ? */
2006 result = resolved_path;
2009 #endif
2010 END_PROFILE(syscall_realpath);
2011 return result;
2014 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2015 struct sys_notify_context *ctx,
2016 const char *path,
2017 uint32_t *filter,
2018 uint32_t *subdir_filter,
2019 void (*callback)(struct sys_notify_context *ctx,
2020 void *private_data,
2021 struct notify_event *ev),
2022 void *private_data, void *handle)
2025 * So far inotify is the only supported default notify mechanism. If
2026 * another platform like the the BSD's or a proprietary Unix comes
2027 * along and wants another default, we can play the same trick we
2028 * played with Posix ACLs.
2030 * Until that is the case, hard-code inotify here.
2032 #ifdef HAVE_INOTIFY
2033 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2034 return inotify_watch(ctx, path, filter, subdir_filter,
2035 callback, private_data, handle);
2037 #endif
2039 * Do nothing, leave everything to notify_internal.c
2041 return NT_STATUS_OK;
2044 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2045 unsigned int flags)
2047 #ifdef HAVE_CHFLAGS
2048 return chflags(path, flags);
2049 #else
2050 errno = ENOSYS;
2051 return -1;
2052 #endif
2055 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2056 const SMB_STRUCT_STAT *sbuf)
2058 struct file_id key;
2060 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2061 * blob */
2062 ZERO_STRUCT(key);
2064 key.devid = sbuf->st_ex_dev;
2065 key.inode = sbuf->st_ex_ino;
2066 /* key.extid is unused by default. */
2068 return key;
2071 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2072 struct files_struct *fsp,
2073 const char *fname,
2074 TALLOC_CTX *mem_ctx,
2075 unsigned int *pnum_streams,
2076 struct stream_struct **pstreams)
2078 SMB_STRUCT_STAT sbuf;
2079 struct stream_struct *tmp_streams = NULL;
2080 int ret;
2082 if ((fsp != NULL) && (fsp->is_directory)) {
2084 * No default streams on directories
2086 goto done;
2089 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2090 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2092 else {
2093 struct smb_filename smb_fname;
2095 ZERO_STRUCT(smb_fname);
2096 smb_fname.base_name = discard_const_p(char, fname);
2098 if (lp_posix_pathnames()) {
2099 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2100 } else {
2101 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2103 sbuf = smb_fname.st;
2106 if (ret == -1) {
2107 return map_nt_error_from_unix(errno);
2110 if (S_ISDIR(sbuf.st_ex_mode)) {
2111 goto done;
2114 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2115 (*pnum_streams) + 1);
2116 if (tmp_streams == NULL) {
2117 return NT_STATUS_NO_MEMORY;
2119 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2120 if (tmp_streams[*pnum_streams].name == NULL) {
2121 return NT_STATUS_NO_MEMORY;
2123 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2124 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2126 *pnum_streams += 1;
2127 *pstreams = tmp_streams;
2128 done:
2129 return NT_STATUS_OK;
2132 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2133 const char *path,
2134 const char *name,
2135 TALLOC_CTX *mem_ctx,
2136 char **found_name)
2139 * Don't fall back to get_real_filename so callers can differentiate
2140 * between a full directory scan and an actual case-insensitive stat.
2142 errno = EOPNOTSUPP;
2143 return -1;
2146 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2147 const char *fname)
2149 return handle->conn->connectpath;
2152 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2153 struct byte_range_lock *br_lck,
2154 struct lock_struct *plock,
2155 bool blocking_lock,
2156 struct blocking_lock_record *blr)
2158 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2160 /* Note: blr is not used in the default implementation. */
2161 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2164 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2165 struct messaging_context *msg_ctx,
2166 struct byte_range_lock *br_lck,
2167 const struct lock_struct *plock)
2169 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2171 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2174 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2175 struct byte_range_lock *br_lck,
2176 struct lock_struct *plock,
2177 struct blocking_lock_record *blr)
2179 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2181 /* Note: blr is not used in the default implementation. */
2182 return brl_lock_cancel_default(br_lck, plock);
2185 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2186 files_struct *fsp,
2187 struct lock_struct *plock)
2189 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2190 plock->lock_type == WRITE_LOCK);
2192 return strict_lock_default(fsp, plock);
2195 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2196 files_struct *fsp,
2197 struct lock_struct *plock)
2199 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2200 plock->lock_type == WRITE_LOCK);
2202 strict_unlock_default(fsp, plock);
2205 /* NT ACL operations. */
2207 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2208 files_struct *fsp,
2209 uint32 security_info,
2210 TALLOC_CTX *mem_ctx,
2211 struct security_descriptor **ppdesc)
2213 NTSTATUS result;
2215 START_PROFILE(fget_nt_acl);
2216 result = posix_fget_nt_acl(fsp, security_info,
2217 mem_ctx, ppdesc);
2218 END_PROFILE(fget_nt_acl);
2219 return result;
2222 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2223 const char *name,
2224 uint32 security_info,
2225 TALLOC_CTX *mem_ctx,
2226 struct security_descriptor **ppdesc)
2228 NTSTATUS result;
2230 START_PROFILE(get_nt_acl);
2231 result = posix_get_nt_acl(handle->conn, name, security_info,
2232 mem_ctx, ppdesc);
2233 END_PROFILE(get_nt_acl);
2234 return result;
2237 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2239 NTSTATUS result;
2241 START_PROFILE(fset_nt_acl);
2242 result = set_nt_acl(fsp, security_info_sent, psd);
2243 END_PROFILE(fset_nt_acl);
2244 return result;
2247 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2248 struct smb_filename *file,
2249 struct security_acl *sacl,
2250 uint32_t access_requested,
2251 uint32_t access_denied)
2253 return NT_STATUS_OK; /* Nothing to do here ... */
2256 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2258 #ifdef HAVE_NO_ACL
2259 errno = ENOSYS;
2260 return -1;
2261 #else
2262 int result;
2264 START_PROFILE(chmod_acl);
2265 result = chmod_acl(handle->conn, name, mode);
2266 END_PROFILE(chmod_acl);
2267 return result;
2268 #endif
2271 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2273 #ifdef HAVE_NO_ACL
2274 errno = ENOSYS;
2275 return -1;
2276 #else
2277 int result;
2279 START_PROFILE(fchmod_acl);
2280 result = fchmod_acl(fsp, mode);
2281 END_PROFILE(fchmod_acl);
2282 return result;
2283 #endif
2286 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2287 const char *path_p,
2288 SMB_ACL_TYPE_T type,
2289 TALLOC_CTX *mem_ctx)
2291 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2294 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2295 files_struct *fsp,
2296 TALLOC_CTX *mem_ctx)
2298 return sys_acl_get_fd(handle, fsp, mem_ctx);
2301 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2303 return sys_acl_set_file(handle, name, acltype, theacl);
2306 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2308 return sys_acl_set_fd(handle, fsp, theacl);
2311 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2313 return sys_acl_delete_def_file(handle, path);
2316 /****************************************************************
2317 Extended attribute operations.
2318 *****************************************************************/
2320 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2322 return getxattr(path, name, value, size);
2325 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2327 return fgetxattr(fsp->fh->fd, name, value, size);
2330 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2332 return listxattr(path, list, size);
2335 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2337 return flistxattr(fsp->fh->fd, list, size);
2340 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2342 return removexattr(path, name);
2345 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2347 return fremovexattr(fsp->fh->fd, name);
2350 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2352 return setxattr(path, name, value, size, flags);
2355 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2357 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2360 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2362 return false;
2365 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2366 const struct smb_filename *fname,
2367 SMB_STRUCT_STAT *sbuf)
2369 NTSTATUS status;
2370 char *path;
2371 bool offline = false;
2373 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2374 return false;
2377 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2378 #if defined(ENOTSUP)
2379 errno = ENOTSUP;
2380 #endif
2381 return false;
2384 status = get_full_smb_filename(talloc_tos(), fname, &path);
2385 if (!NT_STATUS_IS_OK(status)) {
2386 errno = map_errno_from_nt_status(status);
2387 return false;
2390 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2392 TALLOC_FREE(path);
2394 return offline;
2397 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2398 const struct smb_filename *fname)
2400 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2401 #if defined(ENOTSUP)
2402 errno = ENOTSUP;
2403 #endif
2404 return -1;
2407 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2408 struct files_struct *fsp,
2409 TALLOC_CTX *mem_ctx,
2410 DATA_BLOB *cookie)
2412 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2415 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2416 struct files_struct *fsp,
2417 const DATA_BLOB old_cookie,
2418 TALLOC_CTX *mem_ctx,
2419 DATA_BLOB *new_cookie)
2421 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2422 new_cookie);
2425 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2426 struct smb_request *smb1req,
2427 struct smbXsrv_open *op,
2428 const DATA_BLOB old_cookie,
2429 TALLOC_CTX *mem_ctx,
2430 struct files_struct **fsp,
2431 DATA_BLOB *new_cookie)
2433 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2434 old_cookie, mem_ctx,
2435 fsp, new_cookie);
2438 static struct vfs_fn_pointers vfs_default_fns = {
2439 /* Disk operations */
2441 .connect_fn = vfswrap_connect,
2442 .disconnect_fn = vfswrap_disconnect,
2443 .disk_free_fn = vfswrap_disk_free,
2444 .get_quota_fn = vfswrap_get_quota,
2445 .set_quota_fn = vfswrap_set_quota,
2446 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2447 .statvfs_fn = vfswrap_statvfs,
2448 .fs_capabilities_fn = vfswrap_fs_capabilities,
2449 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2451 /* Directory operations */
2453 .opendir_fn = vfswrap_opendir,
2454 .fdopendir_fn = vfswrap_fdopendir,
2455 .readdir_fn = vfswrap_readdir,
2456 .seekdir_fn = vfswrap_seekdir,
2457 .telldir_fn = vfswrap_telldir,
2458 .rewind_dir_fn = vfswrap_rewinddir,
2459 .mkdir_fn = vfswrap_mkdir,
2460 .rmdir_fn = vfswrap_rmdir,
2461 .closedir_fn = vfswrap_closedir,
2462 .init_search_op_fn = vfswrap_init_search_op,
2464 /* File operations */
2466 .open_fn = vfswrap_open,
2467 .create_file_fn = vfswrap_create_file,
2468 .close_fn = vfswrap_close,
2469 .read_fn = vfswrap_read,
2470 .pread_fn = vfswrap_pread,
2471 .pread_send_fn = vfswrap_pread_send,
2472 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2473 .write_fn = vfswrap_write,
2474 .pwrite_fn = vfswrap_pwrite,
2475 .pwrite_send_fn = vfswrap_pwrite_send,
2476 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2477 .lseek_fn = vfswrap_lseek,
2478 .sendfile_fn = vfswrap_sendfile,
2479 .recvfile_fn = vfswrap_recvfile,
2480 .rename_fn = vfswrap_rename,
2481 .fsync_fn = vfswrap_fsync,
2482 .fsync_send_fn = vfswrap_fsync_send,
2483 .fsync_recv_fn = vfswrap_asys_int_recv,
2484 .stat_fn = vfswrap_stat,
2485 .fstat_fn = vfswrap_fstat,
2486 .lstat_fn = vfswrap_lstat,
2487 .get_alloc_size_fn = vfswrap_get_alloc_size,
2488 .unlink_fn = vfswrap_unlink,
2489 .chmod_fn = vfswrap_chmod,
2490 .fchmod_fn = vfswrap_fchmod,
2491 .chown_fn = vfswrap_chown,
2492 .fchown_fn = vfswrap_fchown,
2493 .lchown_fn = vfswrap_lchown,
2494 .chdir_fn = vfswrap_chdir,
2495 .getwd_fn = vfswrap_getwd,
2496 .ntimes_fn = vfswrap_ntimes,
2497 .ftruncate_fn = vfswrap_ftruncate,
2498 .fallocate_fn = vfswrap_fallocate,
2499 .lock_fn = vfswrap_lock,
2500 .kernel_flock_fn = vfswrap_kernel_flock,
2501 .linux_setlease_fn = vfswrap_linux_setlease,
2502 .getlock_fn = vfswrap_getlock,
2503 .symlink_fn = vfswrap_symlink,
2504 .readlink_fn = vfswrap_readlink,
2505 .link_fn = vfswrap_link,
2506 .mknod_fn = vfswrap_mknod,
2507 .realpath_fn = vfswrap_realpath,
2508 .notify_watch_fn = vfswrap_notify_watch,
2509 .chflags_fn = vfswrap_chflags,
2510 .file_id_create_fn = vfswrap_file_id_create,
2511 .streaminfo_fn = vfswrap_streaminfo,
2512 .get_real_filename_fn = vfswrap_get_real_filename,
2513 .connectpath_fn = vfswrap_connectpath,
2514 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2515 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2516 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2517 .strict_lock_fn = vfswrap_strict_lock,
2518 .strict_unlock_fn = vfswrap_strict_unlock,
2519 .translate_name_fn = vfswrap_translate_name,
2520 .fsctl_fn = vfswrap_fsctl,
2521 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2522 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2524 /* NT ACL operations. */
2526 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2527 .get_nt_acl_fn = vfswrap_get_nt_acl,
2528 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2529 .audit_file_fn = vfswrap_audit_file,
2531 /* POSIX ACL operations. */
2533 .chmod_acl_fn = vfswrap_chmod_acl,
2534 .fchmod_acl_fn = vfswrap_fchmod_acl,
2536 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2537 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2538 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2539 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2540 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2541 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2542 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2544 /* EA operations. */
2545 .getxattr_fn = vfswrap_getxattr,
2546 .fgetxattr_fn = vfswrap_fgetxattr,
2547 .listxattr_fn = vfswrap_listxattr,
2548 .flistxattr_fn = vfswrap_flistxattr,
2549 .removexattr_fn = vfswrap_removexattr,
2550 .fremovexattr_fn = vfswrap_fremovexattr,
2551 .setxattr_fn = vfswrap_setxattr,
2552 .fsetxattr_fn = vfswrap_fsetxattr,
2554 /* aio operations */
2555 .aio_force_fn = vfswrap_aio_force,
2557 /* offline operations */
2558 .is_offline_fn = vfswrap_is_offline,
2559 .set_offline_fn = vfswrap_set_offline,
2561 /* durable handle operations */
2562 .durable_cookie_fn = vfswrap_durable_cookie,
2563 .durable_disconnect_fn = vfswrap_durable_disconnect,
2564 .durable_reconnect_fn = vfswrap_durable_reconnect,
2567 NTSTATUS vfs_default_init(void);
2568 NTSTATUS vfs_default_init(void)
2570 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2571 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);