torture: Improve winbindd.pac test to check multiple GENSEC mechanims
[Samba.git] / source3 / modules / vfs_default.c
blob5634cc0fe96e38565f7afa201a8ea673ff7d9474
1 /*
2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
44 this possibility. */
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
55 /* Disk operations */
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
58 uint64_t *dfree, uint64_t *dsize)
60 uint64_t result;
62 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
63 return result;
66 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
68 #ifdef HAVE_SYS_QUOTAS
69 int result;
71 START_PROFILE(syscall_get_quota);
72 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
73 END_PROFILE(syscall_get_quota);
74 return result;
75 #else
76 errno = ENOSYS;
77 return -1;
78 #endif
81 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
83 #ifdef HAVE_SYS_QUOTAS
84 int result;
86 START_PROFILE(syscall_set_quota);
87 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
88 END_PROFILE(syscall_set_quota);
89 return result;
90 #else
91 errno = ENOSYS;
92 return -1;
93 #endif
96 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
97 struct files_struct *fsp,
98 struct shadow_copy_data *shadow_copy_data,
99 bool labels)
101 errno = ENOSYS;
102 return -1; /* Not implemented. */
105 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
107 return sys_statvfs(path, statbuf);
110 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
111 enum timestamp_set_resolution *p_ts_res)
113 connection_struct *conn = handle->conn;
114 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
115 struct smb_filename *smb_fname_cpath = NULL;
116 struct vfs_statvfs_struct statbuf;
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 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
131 NULL, NULL);
132 if (smb_fname_cpath == NULL) {
133 return caps;
136 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
137 if (ret == -1) {
138 TALLOC_FREE(smb_fname_cpath);
139 return caps;
142 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
145 /* If any of the normal UNIX directory timestamps
146 * have a non-zero tv_nsec component assume
147 * we might be able to set sub-second timestamps.
148 * See what filetime set primitives we have.
150 #if defined(HAVE_UTIMENSAT)
151 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
152 #elif defined(HAVE_UTIMES)
153 /* utimes allows msec timestamps to be set. */
154 *p_ts_res = TIMESTAMP_SET_MSEC;
155 #elif defined(HAVE_UTIME)
156 /* utime only allows sec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_SECONDS;
158 #endif
160 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
161 "resolution of %s "
162 "available on share %s, directory %s\n",
163 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
164 lp_servicename(talloc_tos(), conn->params->service),
165 conn->connectpath ));
167 TALLOC_FREE(smb_fname_cpath);
168 return caps;
171 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
172 struct dfs_GetDFSReferral *r)
174 struct junction_map *junction = NULL;
175 int consumedcnt = 0;
176 bool self_referral = false;
177 char *pathnamep = NULL;
178 char *local_dfs_path = NULL;
179 NTSTATUS status;
180 int i;
181 uint16_t max_referral_level = r->in.req.max_referral_level;
183 if (DEBUGLVL(10)) {
184 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
187 /* get the junction entry */
188 if (r->in.req.servername == NULL) {
189 return NT_STATUS_NOT_FOUND;
193 * Trim pathname sent by client so it begins with only one backslash.
194 * Two backslashes confuse some dfs clients
197 local_dfs_path = talloc_strdup(r, r->in.req.servername);
198 if (local_dfs_path == NULL) {
199 return NT_STATUS_NO_MEMORY;
201 pathnamep = local_dfs_path;
202 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
203 IS_DIRECTORY_SEP(pathnamep[1])) {
204 pathnamep++;
207 junction = talloc_zero(r, struct junction_map);
208 if (junction == NULL) {
209 return NT_STATUS_NO_MEMORY;
212 /* The following call can change cwd. */
213 status = get_referred_path(r, pathnamep,
214 !handle->conn->sconn->using_smb2,
215 junction, &consumedcnt, &self_referral);
216 if (!NT_STATUS_IS_OK(status)) {
217 vfs_ChDir(handle->conn, handle->conn->connectpath);
218 return status;
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
222 if (!self_referral) {
223 pathnamep[consumedcnt] = '\0';
225 if (DEBUGLVL(3)) {
226 dbgtext("setup_dfs_referral: Path %s to "
227 "alternate path(s):",
228 pathnamep);
229 for (i=0; i < junction->referral_count; i++) {
230 dbgtext(" %s",
231 junction->referral_list[i].alternate_path);
233 dbgtext(".\n");
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
253 if (self_referral) {
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
265 case 2:
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
273 t->version = 2;
274 v2->size = VERSION2_REFERRAL_SIZE;
275 if (self_referral) {
276 v2->server_type = DFS_SERVER_ROOT;
277 } else {
278 v2->server_type = DFS_SERVER_NON_ROOT;
280 v2->entry_flags = 0;
281 v2->proximity = ref->proximity;
282 v2->ttl = ref->ttl;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
298 break;
299 case 3:
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
308 t->version = 3;
309 v3->size = VERSION3_REFERRAL_SIZE;
310 if (self_referral) {
311 v3->server_type = DFS_SERVER_ROOT;
312 } else {
313 v3->server_type = DFS_SERVER_NON_ROOT;
315 v3->entry_flags = 0;
316 v3->ttl = ref->ttl;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
331 break;
332 default:
333 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
334 "version: %d\n",
335 max_referral_level));
336 return NT_STATUS_INVALID_LEVEL;
339 if (DEBUGLVL(10)) {
340 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
343 return NT_STATUS_OK;
346 /* Directory operations */
348 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
350 DIR *result;
352 START_PROFILE(syscall_opendir);
353 result = opendir(fname);
354 END_PROFILE(syscall_opendir);
355 return result;
358 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
359 files_struct *fsp,
360 const char *mask,
361 uint32 attr)
363 DIR *result;
365 START_PROFILE(syscall_fdopendir);
366 result = sys_fdopendir(fsp->fh->fd);
367 END_PROFILE(syscall_fdopendir);
368 return result;
372 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
373 DIR *dirp,
374 SMB_STRUCT_STAT *sbuf)
376 struct dirent *result;
378 START_PROFILE(syscall_readdir);
379 result = readdir(dirp);
380 END_PROFILE(syscall_readdir);
381 if (sbuf) {
382 /* Default Posix readdir() does not give us stat info.
383 * Set to invalid to indicate we didn't return this info. */
384 SET_STAT_INVALID(*sbuf);
385 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
386 if (result != NULL) {
387 /* See if we can efficiently return this. */
388 struct stat st;
389 int flags = (lp_posix_pathnames() ?
390 AT_SYMLINK_NOFOLLOW : 0);
391 int ret = fstatat(dirfd(dirp),
392 result->d_name,
393 &st,
394 flags);
395 if (ret == 0) {
396 init_stat_ex_from_stat(sbuf,
397 &st,
398 lp_fake_directory_create_times(
399 SNUM(handle->conn)));
402 #endif
404 return result;
407 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
408 const struct smb_filename *fname,
409 TALLOC_CTX *mem_ctx,
410 struct readdir_attr_data **attr_data)
412 return NT_STATUS_NOT_SUPPORTED;
415 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
417 START_PROFILE(syscall_seekdir);
418 seekdir(dirp, offset);
419 END_PROFILE(syscall_seekdir);
422 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
424 long result;
425 START_PROFILE(syscall_telldir);
426 result = telldir(dirp);
427 END_PROFILE(syscall_telldir);
428 return result;
431 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
433 START_PROFILE(syscall_rewinddir);
434 rewinddir(dirp);
435 END_PROFILE(syscall_rewinddir);
438 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
440 int result;
441 bool has_dacl = False;
442 char *parent = NULL;
444 START_PROFILE(syscall_mkdir);
446 if (lp_inherit_acls(SNUM(handle->conn))
447 && parent_dirname(talloc_tos(), path, &parent, NULL)
448 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
449 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
451 TALLOC_FREE(parent);
453 result = mkdir(path, mode);
455 if (result == 0 && !has_dacl) {
457 * We need to do this as the default behavior of POSIX ACLs
458 * is to set the mask to be the requested group permission
459 * bits, not the group permission bits to be the requested
460 * group permission bits. This is not what we want, as it will
461 * mess up any inherited ACL bits that were set. JRA.
463 int saved_errno = errno; /* We may get ENOSYS */
464 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
465 errno = saved_errno;
468 END_PROFILE(syscall_mkdir);
469 return result;
472 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
474 int result;
476 START_PROFILE(syscall_rmdir);
477 result = rmdir(path);
478 END_PROFILE(syscall_rmdir);
479 return result;
482 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
484 int result;
486 START_PROFILE(syscall_closedir);
487 result = closedir(dirp);
488 END_PROFILE(syscall_closedir);
489 return result;
492 static void vfswrap_init_search_op(vfs_handle_struct *handle,
493 DIR *dirp)
495 /* Default behavior is a NOOP */
498 /* File operations */
500 static int vfswrap_open(vfs_handle_struct *handle,
501 struct smb_filename *smb_fname,
502 files_struct *fsp, int flags, mode_t mode)
504 int result = -1;
506 START_PROFILE(syscall_open);
508 if (smb_fname->stream_name) {
509 errno = ENOENT;
510 goto out;
513 result = open(smb_fname->base_name, flags, mode);
514 out:
515 END_PROFILE(syscall_open);
516 return result;
519 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
520 struct smb_request *req,
521 uint16_t root_dir_fid,
522 struct smb_filename *smb_fname,
523 uint32_t access_mask,
524 uint32_t share_access,
525 uint32_t create_disposition,
526 uint32_t create_options,
527 uint32_t file_attributes,
528 uint32_t oplock_request,
529 struct smb2_lease *lease,
530 uint64_t allocation_size,
531 uint32_t private_flags,
532 struct security_descriptor *sd,
533 struct ea_list *ea_list,
534 files_struct **result,
535 int *pinfo,
536 const struct smb2_create_blobs *in_context_blobs,
537 struct smb2_create_blobs *out_context_blobs)
539 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
540 access_mask, share_access,
541 create_disposition, create_options,
542 file_attributes, oplock_request, lease,
543 allocation_size, private_flags,
544 sd, ea_list, result,
545 pinfo, in_context_blobs, out_context_blobs);
548 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
550 int result;
552 START_PROFILE(syscall_close);
553 result = fd_close_posix(fsp);
554 END_PROFILE(syscall_close);
555 return result;
558 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
560 ssize_t result;
562 START_PROFILE_BYTES(syscall_read, n);
563 result = sys_read(fsp->fh->fd, data, n);
564 END_PROFILE_BYTES(syscall_read);
565 return result;
568 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
569 size_t n, off_t offset)
571 ssize_t result;
573 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
574 START_PROFILE_BYTES(syscall_pread, n);
575 result = sys_pread(fsp->fh->fd, data, n, offset);
576 END_PROFILE_BYTES(syscall_pread);
578 if (result == -1 && errno == ESPIPE) {
579 /* Maintain the fiction that pipes can be seeked (sought?) on. */
580 result = SMB_VFS_READ(fsp, data, n);
581 fsp->fh->pos = 0;
584 #else /* HAVE_PREAD */
585 off_t curr;
586 int lerrno;
588 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
589 if (curr == -1 && errno == ESPIPE) {
590 /* Maintain the fiction that pipes can be seeked (sought?) on. */
591 result = SMB_VFS_READ(fsp, data, n);
592 fsp->fh->pos = 0;
593 return result;
596 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
597 return -1;
600 errno = 0;
601 result = SMB_VFS_READ(fsp, data, n);
602 lerrno = errno;
604 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
605 errno = lerrno;
607 #endif /* HAVE_PREAD */
609 return result;
612 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
614 ssize_t result;
616 START_PROFILE_BYTES(syscall_write, n);
617 result = sys_write(fsp->fh->fd, data, n);
618 END_PROFILE_BYTES(syscall_write);
619 return result;
622 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
623 size_t n, off_t offset)
625 ssize_t result;
627 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
628 START_PROFILE_BYTES(syscall_pwrite, n);
629 result = sys_pwrite(fsp->fh->fd, data, n, offset);
630 END_PROFILE_BYTES(syscall_pwrite);
632 if (result == -1 && errno == ESPIPE) {
633 /* Maintain the fiction that pipes can be sought on. */
634 result = SMB_VFS_WRITE(fsp, data, n);
637 #else /* HAVE_PWRITE */
638 off_t curr;
639 int lerrno;
641 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
642 if (curr == -1) {
643 return -1;
646 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
647 return -1;
650 result = SMB_VFS_WRITE(fsp, data, n);
651 lerrno = errno;
653 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
654 errno = lerrno;
656 #endif /* HAVE_PWRITE */
658 return result;
661 static void vfswrap_asys_finished(struct tevent_context *ev,
662 struct tevent_fd *fde,
663 uint16_t flags, void *p);
665 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
667 int ret;
668 int fd;
670 if (conn->asys_ctx != NULL) {
671 return true;
673 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
674 if (ret != 0) {
675 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
676 return false;
679 fd = asys_signalfd(conn->asys_ctx);
681 set_blocking(fd, false);
683 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
684 TEVENT_FD_READ,
685 vfswrap_asys_finished,
686 conn->asys_ctx);
687 if (conn->asys_fde == NULL) {
688 DEBUG(1, ("tevent_add_fd failed\n"));
689 asys_context_destroy(conn->asys_ctx);
690 conn->asys_ctx = NULL;
691 return false;
693 return true;
696 struct vfswrap_asys_state {
697 struct asys_context *asys_ctx;
698 struct tevent_req *req;
699 ssize_t ret;
700 int err;
701 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
702 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
705 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
707 asys_cancel(s->asys_ctx, s->req);
708 return 0;
711 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
712 TALLOC_CTX *mem_ctx,
713 struct tevent_context *ev,
714 struct files_struct *fsp,
715 void *data,
716 size_t n, off_t offset)
718 struct tevent_req *req;
719 struct vfswrap_asys_state *state;
720 int ret;
722 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
723 if (req == NULL) {
724 return NULL;
726 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
727 tevent_req_oom(req);
728 return tevent_req_post(req, ev);
730 state->asys_ctx = handle->conn->sconn->asys_ctx;
731 state->req = req;
733 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
734 state->profile_bytes, n);
735 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
736 if (ret != 0) {
737 tevent_req_error(req, ret);
738 return tevent_req_post(req, ev);
740 talloc_set_destructor(state, vfswrap_asys_state_destructor);
742 return req;
745 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
746 TALLOC_CTX *mem_ctx,
747 struct tevent_context *ev,
748 struct files_struct *fsp,
749 const void *data,
750 size_t n, off_t offset)
752 struct tevent_req *req;
753 struct vfswrap_asys_state *state;
754 int ret;
756 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
757 if (req == NULL) {
758 return NULL;
760 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
761 tevent_req_oom(req);
762 return tevent_req_post(req, ev);
764 state->asys_ctx = handle->conn->sconn->asys_ctx;
765 state->req = req;
767 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
768 state->profile_bytes, n);
769 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
770 if (ret != 0) {
771 tevent_req_error(req, ret);
772 return tevent_req_post(req, ev);
774 talloc_set_destructor(state, vfswrap_asys_state_destructor);
776 return req;
779 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
780 TALLOC_CTX *mem_ctx,
781 struct tevent_context *ev,
782 struct files_struct *fsp)
784 struct tevent_req *req;
785 struct vfswrap_asys_state *state;
786 int ret;
788 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
789 if (req == NULL) {
790 return NULL;
792 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
793 tevent_req_oom(req);
794 return tevent_req_post(req, ev);
796 state->asys_ctx = handle->conn->sconn->asys_ctx;
797 state->req = req;
799 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
800 state->profile_basic);
801 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
802 if (ret != 0) {
803 tevent_req_error(req, ret);
804 return tevent_req_post(req, ev);
806 talloc_set_destructor(state, vfswrap_asys_state_destructor);
808 return req;
811 static void vfswrap_asys_finished(struct tevent_context *ev,
812 struct tevent_fd *fde,
813 uint16_t flags, void *p)
815 struct asys_context *asys_ctx = (struct asys_context *)p;
816 struct asys_result results[outstanding_aio_calls];
817 int i, ret;
819 if ((flags & TEVENT_FD_READ) == 0) {
820 return;
823 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
824 if (ret < 0) {
825 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
826 return;
829 for (i=0; i<ret; i++) {
830 struct asys_result *result = &results[i];
831 struct tevent_req *req;
832 struct vfswrap_asys_state *state;
834 if ((result->ret == -1) && (result->err == ECANCELED)) {
835 continue;
838 req = talloc_get_type_abort(result->private_data,
839 struct tevent_req);
840 state = tevent_req_data(req, struct vfswrap_asys_state);
842 talloc_set_destructor(state, NULL);
844 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
845 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
846 state->ret = result->ret;
847 state->err = result->err;
848 tevent_req_defer_callback(req, ev);
849 tevent_req_done(req);
853 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
855 struct vfswrap_asys_state *state = tevent_req_data(
856 req, struct vfswrap_asys_state);
858 if (tevent_req_is_unix_error(req, err)) {
859 return -1;
861 *err = state->err;
862 return state->ret;
865 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
867 struct vfswrap_asys_state *state = tevent_req_data(
868 req, struct vfswrap_asys_state);
870 if (tevent_req_is_unix_error(req, err)) {
871 return -1;
873 *err = state->err;
874 return state->ret;
877 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
879 off_t result = 0;
881 START_PROFILE(syscall_lseek);
883 /* Cope with 'stat' file opens. */
884 if (fsp->fh->fd != -1)
885 result = lseek(fsp->fh->fd, offset, whence);
888 * We want to maintain the fiction that we can seek
889 * on a fifo for file system purposes. This allows
890 * people to set up UNIX fifo's that feed data to Windows
891 * applications. JRA.
894 if((result == -1) && (errno == ESPIPE)) {
895 result = 0;
896 errno = 0;
899 END_PROFILE(syscall_lseek);
900 return result;
903 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
904 off_t offset, size_t n)
906 ssize_t result;
908 START_PROFILE_BYTES(syscall_sendfile, n);
909 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
910 END_PROFILE_BYTES(syscall_sendfile);
911 return result;
914 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
915 int fromfd,
916 files_struct *tofsp,
917 off_t offset,
918 size_t n)
920 ssize_t result;
922 START_PROFILE_BYTES(syscall_recvfile, n);
923 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
924 END_PROFILE_BYTES(syscall_recvfile);
925 return result;
928 static int vfswrap_rename(vfs_handle_struct *handle,
929 const struct smb_filename *smb_fname_src,
930 const struct smb_filename *smb_fname_dst)
932 int result = -1;
934 START_PROFILE(syscall_rename);
936 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
937 errno = ENOENT;
938 goto out;
941 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
943 out:
944 END_PROFILE(syscall_rename);
945 return result;
948 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
950 #ifdef HAVE_FSYNC
951 int result;
953 START_PROFILE(syscall_fsync);
954 result = fsync(fsp->fh->fd);
955 END_PROFILE(syscall_fsync);
956 return result;
957 #else
958 return 0;
959 #endif
962 static int vfswrap_stat(vfs_handle_struct *handle,
963 struct smb_filename *smb_fname)
965 int result = -1;
967 START_PROFILE(syscall_stat);
969 if (smb_fname->stream_name) {
970 errno = ENOENT;
971 goto out;
974 result = sys_stat(smb_fname->base_name, &smb_fname->st,
975 lp_fake_directory_create_times(SNUM(handle->conn)));
976 out:
977 END_PROFILE(syscall_stat);
978 return result;
981 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
983 int result;
985 START_PROFILE(syscall_fstat);
986 result = sys_fstat(fsp->fh->fd,
987 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
988 END_PROFILE(syscall_fstat);
989 return result;
992 static int vfswrap_lstat(vfs_handle_struct *handle,
993 struct smb_filename *smb_fname)
995 int result = -1;
997 START_PROFILE(syscall_lstat);
999 if (smb_fname->stream_name) {
1000 errno = ENOENT;
1001 goto out;
1004 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1005 lp_fake_directory_create_times(SNUM(handle->conn)));
1006 out:
1007 END_PROFILE(syscall_lstat);
1008 return result;
1011 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1012 const char *name,
1013 enum vfs_translate_direction direction,
1014 TALLOC_CTX *mem_ctx,
1015 char **mapped_name)
1017 return NT_STATUS_NONE_MAPPED;
1021 * Implement the default fsctl operation.
1023 static bool vfswrap_logged_ioctl_message = false;
1025 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1026 struct files_struct *fsp,
1027 TALLOC_CTX *ctx,
1028 uint32_t function,
1029 uint16_t req_flags, /* Needed for UNICODE ... */
1030 const uint8_t *_in_data,
1031 uint32_t in_len,
1032 uint8_t **_out_data,
1033 uint32_t max_out_len,
1034 uint32_t *out_len)
1036 const char *in_data = (const char *)_in_data;
1037 char **out_data = (char **)_out_data;
1038 NTSTATUS status;
1040 switch (function) {
1041 case FSCTL_SET_SPARSE:
1043 bool set_sparse = true;
1045 if (in_len >= 1 && in_data[0] == 0) {
1046 set_sparse = false;
1049 status = file_set_sparse(handle->conn, fsp, set_sparse);
1051 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1052 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1053 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1054 nt_errstr(status)));
1056 return status;
1059 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1061 unsigned char objid[16];
1062 char *return_data = NULL;
1064 /* This should return the object-id on this file.
1065 * I think I'll make this be the inode+dev. JRA.
1068 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1069 fsp_fnum_dbg(fsp)));
1071 *out_len = MIN(max_out_len, 64);
1073 /* Hmmm, will this cause problems if less data asked for? */
1074 return_data = talloc_array(ctx, char, 64);
1075 if (return_data == NULL) {
1076 return NT_STATUS_NO_MEMORY;
1079 /* For backwards compatibility only store the dev/inode. */
1080 push_file_id_16(return_data, &fsp->file_id);
1081 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1082 push_file_id_16(return_data+32, &fsp->file_id);
1083 memset(return_data+48, 0, 16);
1084 *out_data = return_data;
1085 return NT_STATUS_OK;
1088 case FSCTL_GET_REPARSE_POINT:
1090 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1091 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1092 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1093 return NT_STATUS_NOT_A_REPARSE_POINT;
1096 case FSCTL_SET_REPARSE_POINT:
1098 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1099 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1100 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1101 return NT_STATUS_NOT_A_REPARSE_POINT;
1104 case FSCTL_GET_SHADOW_COPY_DATA:
1107 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1108 * and return their volume names. If max_data_count is 16, then it is just
1109 * asking for the number of volumes and length of the combined names.
1111 * pdata is the data allocated by our caller, but that uses
1112 * total_data_count (which is 0 in our case) rather than max_data_count.
1113 * Allocate the correct amount and return the pointer to let
1114 * it be deallocated when we return.
1116 struct shadow_copy_data *shadow_data = NULL;
1117 bool labels = False;
1118 uint32 labels_data_count = 0;
1119 uint32 i;
1120 char *cur_pdata = NULL;
1122 if (max_out_len < 16) {
1123 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1124 max_out_len));
1125 return NT_STATUS_INVALID_PARAMETER;
1128 if (max_out_len > 16) {
1129 labels = True;
1132 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1133 if (shadow_data == NULL) {
1134 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1135 return NT_STATUS_NO_MEMORY;
1139 * Call the VFS routine to actually do the work.
1141 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1142 int log_lev = 0;
1143 if (errno == 0) {
1144 /* broken module didn't set errno on error */
1145 status = NT_STATUS_UNSUCCESSFUL;
1146 } else {
1147 status = map_nt_error_from_unix(errno);
1148 if (NT_STATUS_EQUAL(status,
1149 NT_STATUS_NOT_SUPPORTED)) {
1150 log_lev = 5;
1153 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1154 "connectpath %s, failed - %s.\n",
1155 fsp->conn->connectpath,
1156 nt_errstr(status)));
1157 TALLOC_FREE(shadow_data);
1158 return status;
1161 labels_data_count = (shadow_data->num_volumes * 2 *
1162 sizeof(SHADOW_COPY_LABEL)) + 2;
1164 if (!labels) {
1165 *out_len = 16;
1166 } else {
1167 *out_len = 12 + labels_data_count;
1170 if (max_out_len < *out_len) {
1171 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1172 max_out_len, *out_len));
1173 TALLOC_FREE(shadow_data);
1174 return NT_STATUS_BUFFER_TOO_SMALL;
1177 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1178 if (cur_pdata == NULL) {
1179 TALLOC_FREE(shadow_data);
1180 return NT_STATUS_NO_MEMORY;
1183 *out_data = cur_pdata;
1185 /* num_volumes 4 bytes */
1186 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1188 if (labels) {
1189 /* num_labels 4 bytes */
1190 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1193 /* needed_data_count 4 bytes */
1194 SIVAL(cur_pdata, 8, labels_data_count);
1196 cur_pdata += 12;
1198 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1199 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1200 if (labels && shadow_data->labels) {
1201 for (i=0; i<shadow_data->num_volumes; i++) {
1202 size_t len = 0;
1203 status = srvstr_push(cur_pdata, req_flags,
1204 cur_pdata, shadow_data->labels[i],
1205 2 * sizeof(SHADOW_COPY_LABEL),
1206 STR_UNICODE|STR_TERMINATE, &len);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 TALLOC_FREE(*out_data);
1209 TALLOC_FREE(shadow_data);
1210 return status;
1212 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1213 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1217 TALLOC_FREE(shadow_data);
1219 return NT_STATUS_OK;
1222 case FSCTL_FIND_FILES_BY_SID:
1224 /* pretend this succeeded -
1226 * we have to send back a list with all files owned by this SID
1228 * but I have to check that --metze
1230 struct dom_sid sid;
1231 uid_t uid;
1232 size_t sid_len;
1234 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1235 fsp_fnum_dbg(fsp)));
1237 if (in_len < 8) {
1238 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1239 return NT_STATUS_INVALID_PARAMETER;
1242 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1244 /* unknown 4 bytes: this is not the length of the sid :-( */
1245 /*unknown = IVAL(pdata,0);*/
1247 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1248 return NT_STATUS_INVALID_PARAMETER;
1250 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1252 if (!sid_to_uid(&sid, &uid)) {
1253 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1254 sid_string_dbg(&sid),
1255 (unsigned long)sid_len));
1256 uid = (-1);
1259 /* we can take a look at the find source :-)
1261 * find ./ -uid $uid -name '*' is what we need here
1264 * and send 4bytes len and then NULL terminated unicode strings
1265 * for each file
1267 * but I don't know how to deal with the paged results
1268 * (maybe we can hang the result anywhere in the fsp struct)
1270 * but I don't know how to deal with the paged results
1271 * (maybe we can hang the result anywhere in the fsp struct)
1273 * we don't send all files at once
1274 * and at the next we should *not* start from the beginning,
1275 * so we have to cache the result
1277 * --metze
1280 /* this works for now... */
1281 return NT_STATUS_OK;
1284 case FSCTL_QUERY_ALLOCATED_RANGES:
1286 /* FIXME: This is just a dummy reply, telling that all of the
1287 * file is allocated. MKS cp needs that.
1288 * Adding the real allocated ranges via FIEMAP on Linux
1289 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1290 * this FSCTL correct for sparse files.
1292 uint64_t offset, length;
1293 char *out_data_tmp = NULL;
1295 if (in_len != 16) {
1296 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1297 in_len));
1298 return NT_STATUS_INVALID_PARAMETER;
1301 if (max_out_len < 16) {
1302 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1303 max_out_len));
1304 return NT_STATUS_INVALID_PARAMETER;
1307 offset = BVAL(in_data,0);
1308 length = BVAL(in_data,8);
1310 if (offset + length < offset) {
1311 /* No 64-bit integer wrap. */
1312 return NT_STATUS_INVALID_PARAMETER;
1315 /* Shouldn't this be SMB_VFS_STAT ... ? */
1316 status = vfs_stat_fsp(fsp);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 return status;
1321 *out_len = 16;
1322 out_data_tmp = talloc_array(ctx, char, *out_len);
1323 if (out_data_tmp == NULL) {
1324 DEBUG(10, ("unable to allocate memory for response\n"));
1325 return NT_STATUS_NO_MEMORY;
1328 if (offset > fsp->fsp_name->st.st_ex_size ||
1329 fsp->fsp_name->st.st_ex_size == 0 ||
1330 length == 0) {
1331 memset(out_data_tmp, 0, *out_len);
1332 } else {
1333 uint64_t end = offset + length;
1334 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1335 SBVAL(out_data_tmp, 0, 0);
1336 SBVAL(out_data_tmp, 8, end);
1339 *out_data = out_data_tmp;
1341 return NT_STATUS_OK;
1344 case FSCTL_IS_VOLUME_DIRTY:
1346 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1347 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1349 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1350 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1352 return NT_STATUS_INVALID_PARAMETER;
1355 default:
1357 * Only print once ... unfortunately there could be lots of
1358 * different FSCTLs that are called.
1360 if (!vfswrap_logged_ioctl_message) {
1361 vfswrap_logged_ioctl_message = true;
1362 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1363 __func__, function));
1367 return NT_STATUS_NOT_SUPPORTED;
1370 struct vfs_cc_state {
1371 off_t copied;
1372 uint8_t buf[65536];
1375 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1376 TALLOC_CTX *mem_ctx,
1377 struct tevent_context *ev,
1378 struct files_struct *src_fsp,
1379 off_t src_off,
1380 struct files_struct *dest_fsp,
1381 off_t dest_off,
1382 off_t num)
1384 struct tevent_req *req;
1385 struct vfs_cc_state *vfs_cc_state;
1386 NTSTATUS status;
1388 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1389 (unsigned long)num));
1391 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1392 if (req == NULL) {
1393 return NULL;
1396 status = vfs_stat_fsp(src_fsp);
1397 if (tevent_req_nterror(req, status)) {
1398 return tevent_req_post(req, ev);
1401 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1403 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1404 * If the SourceOffset or SourceOffset + Length extends beyond
1405 * the end of file, the server SHOULD<240> treat this as a
1406 * STATUS_END_OF_FILE error.
1407 * ...
1408 * <240> Section 3.3.5.15.6: Windows servers will return
1409 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1411 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1412 return tevent_req_post(req, ev);
1415 /* could use 2.6.33+ sendfile here to do this in kernel */
1416 while (vfs_cc_state->copied < num) {
1417 ssize_t ret;
1418 struct lock_struct lck;
1419 int saved_errno;
1421 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1422 num - vfs_cc_state->copied);
1424 if (src_fsp->op == NULL) {
1425 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1426 return tevent_req_post(req, ev);
1428 init_strict_lock_struct(src_fsp,
1429 src_fsp->op->global->open_persistent_id,
1430 src_off,
1431 this_num,
1432 READ_LOCK,
1433 &lck);
1435 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1436 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1437 return tevent_req_post(req, ev);
1440 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1441 this_num, src_off);
1442 if (ret == -1) {
1443 saved_errno = errno;
1446 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1448 if (ret == -1) {
1449 errno = saved_errno;
1450 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1451 return tevent_req_post(req, ev);
1453 if (ret != this_num) {
1454 /* zero tolerance for short reads */
1455 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1456 return tevent_req_post(req, ev);
1459 src_off += ret;
1461 if (dest_fsp->op == NULL) {
1462 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1463 return tevent_req_post(req, ev);
1466 init_strict_lock_struct(dest_fsp,
1467 dest_fsp->op->global->open_persistent_id,
1468 dest_off,
1469 this_num,
1470 WRITE_LOCK,
1471 &lck);
1473 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1474 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1475 return tevent_req_post(req, ev);
1478 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1479 this_num, dest_off);
1480 if (ret == -1) {
1481 saved_errno = errno;
1484 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1486 if (ret == -1) {
1487 errno = saved_errno;
1488 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1489 return tevent_req_post(req, ev);
1491 if (ret != this_num) {
1492 /* zero tolerance for short writes */
1493 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1494 return tevent_req_post(req, ev);
1496 dest_off += ret;
1498 vfs_cc_state->copied += this_num;
1501 tevent_req_done(req);
1502 return tevent_req_post(req, ev);
1505 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1506 struct tevent_req *req,
1507 off_t *copied)
1509 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1510 struct vfs_cc_state);
1511 NTSTATUS status;
1513 if (tevent_req_is_nterror(req, &status)) {
1514 DEBUG(2, ("server side copy chunk failed: %s\n",
1515 nt_errstr(status)));
1516 *copied = 0;
1517 tevent_req_received(req);
1518 return status;
1521 *copied = vfs_cc_state->copied;
1522 DEBUG(10, ("server side copy chunk copied %lu\n",
1523 (unsigned long)*copied));
1524 tevent_req_received(req);
1526 return NT_STATUS_OK;
1529 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1530 TALLOC_CTX *mem_ctx,
1531 struct files_struct *fsp,
1532 struct smb_filename *smb_fname,
1533 uint16_t *_compression_fmt)
1535 return NT_STATUS_INVALID_DEVICE_REQUEST;
1538 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1539 TALLOC_CTX *mem_ctx,
1540 struct files_struct *fsp,
1541 uint16_t compression_fmt)
1543 return NT_STATUS_INVALID_DEVICE_REQUEST;
1546 /********************************************************************
1547 Given a stat buffer return the allocated size on disk, taking into
1548 account sparse files.
1549 ********************************************************************/
1550 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1551 struct files_struct *fsp,
1552 const SMB_STRUCT_STAT *sbuf)
1554 uint64_t result;
1556 START_PROFILE(syscall_get_alloc_size);
1558 if(S_ISDIR(sbuf->st_ex_mode)) {
1559 result = 0;
1560 goto out;
1563 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1564 /* The type of st_blocksize is blkcnt_t which *MUST* be
1565 signed (according to POSIX) and can be less than 64-bits.
1566 Ensure when we're converting to 64 bits wide we don't
1567 sign extend. */
1568 #if defined(SIZEOF_BLKCNT_T_8)
1569 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1570 #elif defined(SIZEOF_BLKCNT_T_4)
1572 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1573 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1575 #else
1576 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1577 #endif
1578 if (result == 0) {
1580 * Some file systems do not allocate a block for very
1581 * small files. But for non-empty file should report a
1582 * positive size.
1585 uint64_t filesize = get_file_size_stat(sbuf);
1586 if (filesize > 0) {
1587 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1590 #else
1591 result = get_file_size_stat(sbuf);
1592 #endif
1594 if (fsp && fsp->initial_allocation_size)
1595 result = MAX(result,fsp->initial_allocation_size);
1597 result = smb_roundup(handle->conn, result);
1599 out:
1600 END_PROFILE(syscall_get_alloc_size);
1601 return result;
1604 static int vfswrap_unlink(vfs_handle_struct *handle,
1605 const struct smb_filename *smb_fname)
1607 int result = -1;
1609 START_PROFILE(syscall_unlink);
1611 if (smb_fname->stream_name) {
1612 errno = ENOENT;
1613 goto out;
1615 result = unlink(smb_fname->base_name);
1617 out:
1618 END_PROFILE(syscall_unlink);
1619 return result;
1622 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1624 int result;
1626 START_PROFILE(syscall_chmod);
1629 * We need to do this due to the fact that the default POSIX ACL
1630 * chmod modifies the ACL *mask* for the group owner, not the
1631 * group owner bits directly. JRA.
1636 int saved_errno = errno; /* We might get ENOSYS */
1637 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1638 END_PROFILE(syscall_chmod);
1639 return result;
1641 /* Error - return the old errno. */
1642 errno = saved_errno;
1645 result = chmod(path, mode);
1646 END_PROFILE(syscall_chmod);
1647 return result;
1650 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1652 int result;
1654 START_PROFILE(syscall_fchmod);
1657 * We need to do this due to the fact that the default POSIX ACL
1658 * chmod modifies the ACL *mask* for the group owner, not the
1659 * group owner bits directly. JRA.
1663 int saved_errno = errno; /* We might get ENOSYS */
1664 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1665 END_PROFILE(syscall_fchmod);
1666 return result;
1668 /* Error - return the old errno. */
1669 errno = saved_errno;
1672 #if defined(HAVE_FCHMOD)
1673 result = fchmod(fsp->fh->fd, mode);
1674 #else
1675 result = -1;
1676 errno = ENOSYS;
1677 #endif
1679 END_PROFILE(syscall_fchmod);
1680 return result;
1683 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1685 int result;
1687 START_PROFILE(syscall_chown);
1688 result = chown(path, uid, gid);
1689 END_PROFILE(syscall_chown);
1690 return result;
1693 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1695 #ifdef HAVE_FCHOWN
1696 int result;
1698 START_PROFILE(syscall_fchown);
1699 result = fchown(fsp->fh->fd, uid, gid);
1700 END_PROFILE(syscall_fchown);
1701 return result;
1702 #else
1703 errno = ENOSYS;
1704 return -1;
1705 #endif
1708 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1710 int result;
1712 START_PROFILE(syscall_lchown);
1713 result = lchown(path, uid, gid);
1714 END_PROFILE(syscall_lchown);
1715 return result;
1718 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1720 int result;
1722 START_PROFILE(syscall_chdir);
1723 result = chdir(path);
1724 END_PROFILE(syscall_chdir);
1725 return result;
1728 static char *vfswrap_getwd(vfs_handle_struct *handle)
1730 char *result;
1732 START_PROFILE(syscall_getwd);
1733 result = sys_getwd();
1734 END_PROFILE(syscall_getwd);
1735 return result;
1738 /*********************************************************************
1739 nsec timestamp resolution call. Convert down to whatever the underlying
1740 system will support.
1741 **********************************************************************/
1743 static int vfswrap_ntimes(vfs_handle_struct *handle,
1744 const struct smb_filename *smb_fname,
1745 struct smb_file_time *ft)
1747 int result = -1;
1749 START_PROFILE(syscall_ntimes);
1751 if (smb_fname->stream_name) {
1752 errno = ENOENT;
1753 goto out;
1756 if (ft != NULL) {
1757 if (null_timespec(ft->atime)) {
1758 ft->atime= smb_fname->st.st_ex_atime;
1761 if (null_timespec(ft->mtime)) {
1762 ft->mtime = smb_fname->st.st_ex_mtime;
1765 if (!null_timespec(ft->create_time)) {
1766 set_create_timespec_ea(handle->conn,
1767 smb_fname,
1768 ft->create_time);
1771 if ((timespec_compare(&ft->atime,
1772 &smb_fname->st.st_ex_atime) == 0) &&
1773 (timespec_compare(&ft->mtime,
1774 &smb_fname->st.st_ex_mtime) == 0)) {
1775 return 0;
1779 #if defined(HAVE_UTIMENSAT)
1780 if (ft != NULL) {
1781 struct timespec ts[2];
1782 ts[0] = ft->atime;
1783 ts[1] = ft->mtime;
1784 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1785 } else {
1786 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1788 if (!((result == -1) && (errno == ENOSYS))) {
1789 goto out;
1791 #endif
1792 #if defined(HAVE_UTIMES)
1793 if (ft != NULL) {
1794 struct timeval tv[2];
1795 tv[0] = convert_timespec_to_timeval(ft->atime);
1796 tv[1] = convert_timespec_to_timeval(ft->mtime);
1797 result = utimes(smb_fname->base_name, tv);
1798 } else {
1799 result = utimes(smb_fname->base_name, NULL);
1801 if (!((result == -1) && (errno == ENOSYS))) {
1802 goto out;
1804 #endif
1805 #if defined(HAVE_UTIME)
1806 if (ft != NULL) {
1807 struct utimbuf times;
1808 times.actime = convert_timespec_to_time_t(ft->atime);
1809 times.modtime = convert_timespec_to_time_t(ft->mtime);
1810 result = utime(smb_fname->base_name, &times);
1811 } else {
1812 result = utime(smb_fname->base_name, NULL);
1814 if (!((result == -1) && (errno == ENOSYS))) {
1815 goto out;
1817 #endif
1818 errno = ENOSYS;
1819 result = -1;
1821 out:
1822 END_PROFILE(syscall_ntimes);
1823 return result;
1826 /*********************************************************************
1827 A version of ftruncate that will write the space on disk if strict
1828 allocate is set.
1829 **********************************************************************/
1831 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1833 off_t space_to_write;
1834 uint64_t space_avail;
1835 uint64_t bsize,dfree,dsize;
1836 int ret;
1837 NTSTATUS status;
1838 SMB_STRUCT_STAT *pst;
1840 status = vfs_stat_fsp(fsp);
1841 if (!NT_STATUS_IS_OK(status)) {
1842 return -1;
1844 pst = &fsp->fsp_name->st;
1846 #ifdef S_ISFIFO
1847 if (S_ISFIFO(pst->st_ex_mode))
1848 return 0;
1849 #endif
1851 if (pst->st_ex_size == len)
1852 return 0;
1854 /* Shrink - just ftruncate. */
1855 if (pst->st_ex_size > len)
1856 return ftruncate(fsp->fh->fd, len);
1858 space_to_write = len - pst->st_ex_size;
1860 /* for allocation try fallocate first. This can fail on some
1861 platforms e.g. when the filesystem doesn't support it and no
1862 emulation is being done by the libc (like on AIX with JFS1). In that
1863 case we do our own emulation. fallocate implementations can
1864 return ENOTSUP or EINVAL in cases like that. */
1865 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1866 pst->st_ex_size, space_to_write);
1867 if (ret == -1 && errno == ENOSPC) {
1868 return -1;
1870 if (ret == 0) {
1871 return 0;
1873 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1874 "error %d. Falling back to slow manual allocation\n", errno));
1876 /* available disk space is enough or not? */
1877 space_avail = get_dfree_info(fsp->conn,
1878 fsp->fsp_name->base_name, false,
1879 &bsize,&dfree,&dsize);
1880 /* space_avail is 1k blocks */
1881 if (space_avail == (uint64_t)-1 ||
1882 ((uint64_t)space_to_write/1024 > space_avail) ) {
1883 errno = ENOSPC;
1884 return -1;
1887 /* Write out the real space on disk. */
1888 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1889 if (ret != 0) {
1890 return -1;
1893 return 0;
1896 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1898 int result = -1;
1899 SMB_STRUCT_STAT *pst;
1900 NTSTATUS status;
1901 char c = 0;
1903 START_PROFILE(syscall_ftruncate);
1905 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1906 result = strict_allocate_ftruncate(handle, fsp, len);
1907 END_PROFILE(syscall_ftruncate);
1908 return result;
1911 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1912 ftruncate if the system supports it. Then I discovered that
1913 you can have some filesystems that support ftruncate
1914 expansion and some that don't! On Linux fat can't do
1915 ftruncate extend but ext2 can. */
1917 result = ftruncate(fsp->fh->fd, len);
1918 if (result == 0)
1919 goto done;
1921 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1922 extend a file with ftruncate. Provide alternate implementation
1923 for this */
1925 /* Do an fstat to see if the file is longer than the requested
1926 size in which case the ftruncate above should have
1927 succeeded or shorter, in which case seek to len - 1 and
1928 write 1 byte of zero */
1929 status = vfs_stat_fsp(fsp);
1930 if (!NT_STATUS_IS_OK(status)) {
1931 goto done;
1933 pst = &fsp->fsp_name->st;
1935 #ifdef S_ISFIFO
1936 if (S_ISFIFO(pst->st_ex_mode)) {
1937 result = 0;
1938 goto done;
1940 #endif
1942 if (pst->st_ex_size == len) {
1943 result = 0;
1944 goto done;
1947 if (pst->st_ex_size > len) {
1948 /* the ftruncate should have worked */
1949 goto done;
1952 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1953 goto done;
1956 result = 0;
1958 done:
1960 END_PROFILE(syscall_ftruncate);
1961 return result;
1964 static int vfswrap_fallocate(vfs_handle_struct *handle,
1965 files_struct *fsp,
1966 enum vfs_fallocate_mode mode,
1967 off_t offset,
1968 off_t len)
1970 int result;
1972 START_PROFILE(syscall_fallocate);
1973 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1974 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1976 * posix_fallocate returns 0 on success, errno on error
1977 * and doesn't set errno. Make it behave like fallocate()
1978 * which returns -1, and sets errno on failure.
1980 if (result != 0) {
1981 errno = result;
1982 result = -1;
1984 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1985 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1986 } else {
1987 errno = EINVAL;
1988 result = -1;
1990 END_PROFILE(syscall_fallocate);
1991 return result;
1994 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1996 bool result;
1998 START_PROFILE(syscall_fcntl_lock);
1999 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2000 END_PROFILE(syscall_fcntl_lock);
2001 return result;
2004 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2005 uint32 share_mode, uint32 access_mask)
2007 START_PROFILE(syscall_kernel_flock);
2008 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2009 END_PROFILE(syscall_kernel_flock);
2010 return 0;
2013 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2015 bool result;
2017 START_PROFILE(syscall_fcntl_getlock);
2018 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2019 END_PROFILE(syscall_fcntl_getlock);
2020 return result;
2023 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2024 int leasetype)
2026 int result = -1;
2028 START_PROFILE(syscall_linux_setlease);
2030 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2031 result = linux_setlease(fsp->fh->fd, leasetype);
2032 #else
2033 errno = ENOSYS;
2034 #endif
2035 END_PROFILE(syscall_linux_setlease);
2036 return result;
2039 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2041 int result;
2043 START_PROFILE(syscall_symlink);
2044 result = symlink(oldpath, newpath);
2045 END_PROFILE(syscall_symlink);
2046 return result;
2049 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2051 int result;
2053 START_PROFILE(syscall_readlink);
2054 result = readlink(path, buf, bufsiz);
2055 END_PROFILE(syscall_readlink);
2056 return result;
2059 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2061 int result;
2063 START_PROFILE(syscall_link);
2064 result = link(oldpath, newpath);
2065 END_PROFILE(syscall_link);
2066 return result;
2069 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2071 int result;
2073 START_PROFILE(syscall_mknod);
2074 result = sys_mknod(pathname, mode, dev);
2075 END_PROFILE(syscall_mknod);
2076 return result;
2079 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2081 char *result;
2083 START_PROFILE(syscall_realpath);
2084 #ifdef REALPATH_TAKES_NULL
2085 result = realpath(path, NULL);
2086 #else
2087 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2088 if (result) {
2089 char *resolved_path = realpath(path, result);
2090 if (!resolved_path) {
2091 SAFE_FREE(result);
2092 } else {
2093 /* SMB_ASSERT(result == resolved_path) ? */
2094 result = resolved_path;
2097 #endif
2098 END_PROFILE(syscall_realpath);
2099 return result;
2102 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2103 struct sys_notify_context *ctx,
2104 const char *path,
2105 uint32_t *filter,
2106 uint32_t *subdir_filter,
2107 void (*callback)(struct sys_notify_context *ctx,
2108 void *private_data,
2109 struct notify_event *ev),
2110 void *private_data, void *handle)
2113 * So far inotify is the only supported default notify mechanism. If
2114 * another platform like the the BSD's or a proprietary Unix comes
2115 * along and wants another default, we can play the same trick we
2116 * played with Posix ACLs.
2118 * Until that is the case, hard-code inotify here.
2120 #ifdef HAVE_INOTIFY
2121 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2122 int ret;
2123 if (!lp_parm_bool(-1, "notify", "inotify", True)) {
2124 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2127 * "ctx->private_data" is not obvious as a talloc context
2128 * here. Without modifying the VFS we don't have a mem_ctx
2129 * available here, and ctx->private_data was used by
2130 * inotify_watch before it got a real talloc parent.
2132 ret = inotify_watch(ctx->private_data, ctx,
2133 path, filter, subdir_filter,
2134 callback, private_data, handle);
2135 if (ret != 0) {
2136 return map_nt_error_from_unix(ret);
2138 return NT_STATUS_OK;
2140 #endif
2142 * Do nothing, leave everything to notify_internal.c
2144 return NT_STATUS_OK;
2147 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2148 unsigned int flags)
2150 #ifdef HAVE_CHFLAGS
2151 return chflags(path, flags);
2152 #else
2153 errno = ENOSYS;
2154 return -1;
2155 #endif
2158 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2159 const SMB_STRUCT_STAT *sbuf)
2161 struct file_id key;
2163 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2164 * blob */
2165 ZERO_STRUCT(key);
2167 key.devid = sbuf->st_ex_dev;
2168 key.inode = sbuf->st_ex_ino;
2169 /* key.extid is unused by default. */
2171 return key;
2174 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2175 struct files_struct *fsp,
2176 const char *fname,
2177 TALLOC_CTX *mem_ctx,
2178 unsigned int *pnum_streams,
2179 struct stream_struct **pstreams)
2181 SMB_STRUCT_STAT sbuf;
2182 struct stream_struct *tmp_streams = NULL;
2183 int ret;
2185 if ((fsp != NULL) && (fsp->is_directory)) {
2187 * No default streams on directories
2189 goto done;
2192 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2193 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2195 else {
2196 struct smb_filename smb_fname;
2198 ZERO_STRUCT(smb_fname);
2199 smb_fname.base_name = discard_const_p(char, fname);
2201 if (lp_posix_pathnames()) {
2202 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2203 } else {
2204 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2206 sbuf = smb_fname.st;
2209 if (ret == -1) {
2210 return map_nt_error_from_unix(errno);
2213 if (S_ISDIR(sbuf.st_ex_mode)) {
2214 goto done;
2217 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2218 (*pnum_streams) + 1);
2219 if (tmp_streams == NULL) {
2220 return NT_STATUS_NO_MEMORY;
2222 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2223 if (tmp_streams[*pnum_streams].name == NULL) {
2224 return NT_STATUS_NO_MEMORY;
2226 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2227 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2229 *pnum_streams += 1;
2230 *pstreams = tmp_streams;
2231 done:
2232 return NT_STATUS_OK;
2235 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2236 const char *path,
2237 const char *name,
2238 TALLOC_CTX *mem_ctx,
2239 char **found_name)
2242 * Don't fall back to get_real_filename so callers can differentiate
2243 * between a full directory scan and an actual case-insensitive stat.
2245 errno = EOPNOTSUPP;
2246 return -1;
2249 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2250 const char *fname)
2252 return handle->conn->connectpath;
2255 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2256 struct byte_range_lock *br_lck,
2257 struct lock_struct *plock,
2258 bool blocking_lock)
2260 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2262 /* Note: blr is not used in the default implementation. */
2263 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2266 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2267 struct messaging_context *msg_ctx,
2268 struct byte_range_lock *br_lck,
2269 const struct lock_struct *plock)
2271 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2273 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2276 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2277 struct byte_range_lock *br_lck,
2278 struct lock_struct *plock)
2280 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2282 /* Note: blr is not used in the default implementation. */
2283 return brl_lock_cancel_default(br_lck, plock);
2286 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2287 files_struct *fsp,
2288 struct lock_struct *plock)
2290 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2291 plock->lock_type == WRITE_LOCK);
2293 return strict_lock_default(fsp, plock);
2296 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2297 files_struct *fsp,
2298 struct lock_struct *plock)
2300 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2301 plock->lock_type == WRITE_LOCK);
2303 strict_unlock_default(fsp, plock);
2306 /* NT ACL operations. */
2308 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2309 files_struct *fsp,
2310 uint32 security_info,
2311 TALLOC_CTX *mem_ctx,
2312 struct security_descriptor **ppdesc)
2314 NTSTATUS result;
2316 START_PROFILE(fget_nt_acl);
2317 result = posix_fget_nt_acl(fsp, security_info,
2318 mem_ctx, ppdesc);
2319 END_PROFILE(fget_nt_acl);
2320 return result;
2323 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2324 const char *name,
2325 uint32 security_info,
2326 TALLOC_CTX *mem_ctx,
2327 struct security_descriptor **ppdesc)
2329 NTSTATUS result;
2331 START_PROFILE(get_nt_acl);
2332 result = posix_get_nt_acl(handle->conn, name, security_info,
2333 mem_ctx, ppdesc);
2334 END_PROFILE(get_nt_acl);
2335 return result;
2338 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2340 NTSTATUS result;
2342 START_PROFILE(fset_nt_acl);
2343 result = set_nt_acl(fsp, security_info_sent, psd);
2344 END_PROFILE(fset_nt_acl);
2345 return result;
2348 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2349 struct smb_filename *file,
2350 struct security_acl *sacl,
2351 uint32_t access_requested,
2352 uint32_t access_denied)
2354 return NT_STATUS_OK; /* Nothing to do here ... */
2357 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2359 #ifdef HAVE_NO_ACL
2360 errno = ENOSYS;
2361 return -1;
2362 #else
2363 int result;
2365 START_PROFILE(chmod_acl);
2366 result = chmod_acl(handle->conn, name, mode);
2367 END_PROFILE(chmod_acl);
2368 return result;
2369 #endif
2372 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2374 #ifdef HAVE_NO_ACL
2375 errno = ENOSYS;
2376 return -1;
2377 #else
2378 int result;
2380 START_PROFILE(fchmod_acl);
2381 result = fchmod_acl(fsp, mode);
2382 END_PROFILE(fchmod_acl);
2383 return result;
2384 #endif
2387 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2388 const char *path_p,
2389 SMB_ACL_TYPE_T type,
2390 TALLOC_CTX *mem_ctx)
2392 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2395 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2396 files_struct *fsp,
2397 TALLOC_CTX *mem_ctx)
2399 return sys_acl_get_fd(handle, fsp, mem_ctx);
2402 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2404 return sys_acl_set_file(handle, name, acltype, theacl);
2407 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2409 return sys_acl_set_fd(handle, fsp, theacl);
2412 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2414 return sys_acl_delete_def_file(handle, path);
2417 /****************************************************************
2418 Extended attribute operations.
2419 *****************************************************************/
2421 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2423 return getxattr(path, name, value, size);
2426 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2428 return fgetxattr(fsp->fh->fd, name, value, size);
2431 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2433 return listxattr(path, list, size);
2436 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2438 return flistxattr(fsp->fh->fd, list, size);
2441 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2443 return removexattr(path, name);
2446 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2448 return fremovexattr(fsp->fh->fd, name);
2451 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2453 return setxattr(path, name, value, size, flags);
2456 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2458 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2461 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2463 return false;
2466 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2467 const struct smb_filename *fname,
2468 SMB_STRUCT_STAT *sbuf)
2470 NTSTATUS status;
2471 char *path;
2472 bool offline = false;
2474 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2475 return false;
2478 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2479 #if defined(ENOTSUP)
2480 errno = ENOTSUP;
2481 #endif
2482 return false;
2485 status = get_full_smb_filename(talloc_tos(), fname, &path);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 errno = map_errno_from_nt_status(status);
2488 return false;
2491 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2493 TALLOC_FREE(path);
2495 return offline;
2498 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2499 const struct smb_filename *fname)
2501 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2502 #if defined(ENOTSUP)
2503 errno = ENOTSUP;
2504 #endif
2505 return -1;
2508 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2509 struct files_struct *fsp,
2510 TALLOC_CTX *mem_ctx,
2511 DATA_BLOB *cookie)
2513 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2516 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2517 struct files_struct *fsp,
2518 const DATA_BLOB old_cookie,
2519 TALLOC_CTX *mem_ctx,
2520 DATA_BLOB *new_cookie)
2522 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2523 new_cookie);
2526 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2527 struct smb_request *smb1req,
2528 struct smbXsrv_open *op,
2529 const DATA_BLOB old_cookie,
2530 TALLOC_CTX *mem_ctx,
2531 struct files_struct **fsp,
2532 DATA_BLOB *new_cookie)
2534 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2535 old_cookie, mem_ctx,
2536 fsp, new_cookie);
2539 static struct vfs_fn_pointers vfs_default_fns = {
2540 /* Disk operations */
2542 .connect_fn = vfswrap_connect,
2543 .disconnect_fn = vfswrap_disconnect,
2544 .disk_free_fn = vfswrap_disk_free,
2545 .get_quota_fn = vfswrap_get_quota,
2546 .set_quota_fn = vfswrap_set_quota,
2547 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2548 .statvfs_fn = vfswrap_statvfs,
2549 .fs_capabilities_fn = vfswrap_fs_capabilities,
2550 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2552 /* Directory operations */
2554 .opendir_fn = vfswrap_opendir,
2555 .fdopendir_fn = vfswrap_fdopendir,
2556 .readdir_fn = vfswrap_readdir,
2557 .readdir_attr_fn = vfswrap_readdir_attr,
2558 .seekdir_fn = vfswrap_seekdir,
2559 .telldir_fn = vfswrap_telldir,
2560 .rewind_dir_fn = vfswrap_rewinddir,
2561 .mkdir_fn = vfswrap_mkdir,
2562 .rmdir_fn = vfswrap_rmdir,
2563 .closedir_fn = vfswrap_closedir,
2564 .init_search_op_fn = vfswrap_init_search_op,
2566 /* File operations */
2568 .open_fn = vfswrap_open,
2569 .create_file_fn = vfswrap_create_file,
2570 .close_fn = vfswrap_close,
2571 .read_fn = vfswrap_read,
2572 .pread_fn = vfswrap_pread,
2573 .pread_send_fn = vfswrap_pread_send,
2574 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2575 .write_fn = vfswrap_write,
2576 .pwrite_fn = vfswrap_pwrite,
2577 .pwrite_send_fn = vfswrap_pwrite_send,
2578 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2579 .lseek_fn = vfswrap_lseek,
2580 .sendfile_fn = vfswrap_sendfile,
2581 .recvfile_fn = vfswrap_recvfile,
2582 .rename_fn = vfswrap_rename,
2583 .fsync_fn = vfswrap_fsync,
2584 .fsync_send_fn = vfswrap_fsync_send,
2585 .fsync_recv_fn = vfswrap_asys_int_recv,
2586 .stat_fn = vfswrap_stat,
2587 .fstat_fn = vfswrap_fstat,
2588 .lstat_fn = vfswrap_lstat,
2589 .get_alloc_size_fn = vfswrap_get_alloc_size,
2590 .unlink_fn = vfswrap_unlink,
2591 .chmod_fn = vfswrap_chmod,
2592 .fchmod_fn = vfswrap_fchmod,
2593 .chown_fn = vfswrap_chown,
2594 .fchown_fn = vfswrap_fchown,
2595 .lchown_fn = vfswrap_lchown,
2596 .chdir_fn = vfswrap_chdir,
2597 .getwd_fn = vfswrap_getwd,
2598 .ntimes_fn = vfswrap_ntimes,
2599 .ftruncate_fn = vfswrap_ftruncate,
2600 .fallocate_fn = vfswrap_fallocate,
2601 .lock_fn = vfswrap_lock,
2602 .kernel_flock_fn = vfswrap_kernel_flock,
2603 .linux_setlease_fn = vfswrap_linux_setlease,
2604 .getlock_fn = vfswrap_getlock,
2605 .symlink_fn = vfswrap_symlink,
2606 .readlink_fn = vfswrap_readlink,
2607 .link_fn = vfswrap_link,
2608 .mknod_fn = vfswrap_mknod,
2609 .realpath_fn = vfswrap_realpath,
2610 .notify_watch_fn = vfswrap_notify_watch,
2611 .chflags_fn = vfswrap_chflags,
2612 .file_id_create_fn = vfswrap_file_id_create,
2613 .streaminfo_fn = vfswrap_streaminfo,
2614 .get_real_filename_fn = vfswrap_get_real_filename,
2615 .connectpath_fn = vfswrap_connectpath,
2616 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2617 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2618 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2619 .strict_lock_fn = vfswrap_strict_lock,
2620 .strict_unlock_fn = vfswrap_strict_unlock,
2621 .translate_name_fn = vfswrap_translate_name,
2622 .fsctl_fn = vfswrap_fsctl,
2623 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2624 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2625 .get_compression_fn = vfswrap_get_compression,
2626 .set_compression_fn = vfswrap_set_compression,
2628 /* NT ACL operations. */
2630 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2631 .get_nt_acl_fn = vfswrap_get_nt_acl,
2632 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2633 .audit_file_fn = vfswrap_audit_file,
2635 /* POSIX ACL operations. */
2637 .chmod_acl_fn = vfswrap_chmod_acl,
2638 .fchmod_acl_fn = vfswrap_fchmod_acl,
2640 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2641 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2642 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2643 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2644 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2645 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2646 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2648 /* EA operations. */
2649 .getxattr_fn = vfswrap_getxattr,
2650 .fgetxattr_fn = vfswrap_fgetxattr,
2651 .listxattr_fn = vfswrap_listxattr,
2652 .flistxattr_fn = vfswrap_flistxattr,
2653 .removexattr_fn = vfswrap_removexattr,
2654 .fremovexattr_fn = vfswrap_fremovexattr,
2655 .setxattr_fn = vfswrap_setxattr,
2656 .fsetxattr_fn = vfswrap_fsetxattr,
2658 /* aio operations */
2659 .aio_force_fn = vfswrap_aio_force,
2661 /* offline operations */
2662 .is_offline_fn = vfswrap_is_offline,
2663 .set_offline_fn = vfswrap_set_offline,
2665 /* durable handle operations */
2666 .durable_cookie_fn = vfswrap_durable_cookie,
2667 .durable_disconnect_fn = vfswrap_durable_disconnect,
2668 .durable_reconnect_fn = vfswrap_durable_reconnect,
2671 NTSTATUS vfs_default_init(void);
2672 NTSTATUS vfs_default_init(void)
2674 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2675 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);