libcli/smb: add support for SMB >= 3.1.1 io priorities
[Samba.git] / source3 / modules / vfs_default.c
blob9b434a0dfd59f79f16299c4ed4c12216f0236692
1 /*
2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
44 this possibility. */
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
55 /* Disk operations */
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
59 uint64_t *dsize)
61 uint64_t result;
63 result = sys_disk_free(handle->conn, path, bsize, dfree, dsize);
64 return result;
67 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
69 #ifdef HAVE_SYS_QUOTAS
70 int result;
72 START_PROFILE(syscall_get_quota);
73 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
74 END_PROFILE(syscall_get_quota);
75 return result;
76 #else
77 errno = ENOSYS;
78 return -1;
79 #endif
82 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
84 #ifdef HAVE_SYS_QUOTAS
85 int result;
87 START_PROFILE(syscall_set_quota);
88 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
89 END_PROFILE(syscall_set_quota);
90 return result;
91 #else
92 errno = ENOSYS;
93 return -1;
94 #endif
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
98 struct files_struct *fsp,
99 struct shadow_copy_data *shadow_copy_data,
100 bool labels)
102 errno = ENOSYS;
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
108 return sys_statvfs(path, statbuf);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
112 enum timestamp_set_resolution *p_ts_res)
114 connection_struct *conn = handle->conn;
115 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
116 struct smb_filename *smb_fname_cpath = NULL;
117 struct vfs_statvfs_struct statbuf;
118 int ret;
120 ZERO_STRUCT(statbuf);
121 ret = sys_statvfs(conn->connectpath, &statbuf);
122 if (ret == 0) {
123 caps = statbuf.FsCapabilities;
126 *p_ts_res = TIMESTAMP_SET_SECONDS;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
132 NULL, NULL);
133 if (smb_fname_cpath == NULL) {
134 return caps;
137 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
138 if (ret == -1) {
139 TALLOC_FREE(smb_fname_cpath);
140 return caps;
143 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
145 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res = TIMESTAMP_SET_MSEC;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res = TIMESTAMP_SET_SECONDS;
159 #endif
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
162 "resolution of %s "
163 "available on share %s, directory %s\n",
164 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn->params->service),
166 conn->connectpath ));
168 TALLOC_FREE(smb_fname_cpath);
169 return caps;
172 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
173 struct dfs_GetDFSReferral *r)
175 struct junction_map *junction = NULL;
176 int consumedcnt = 0;
177 bool self_referral = false;
178 char *pathnamep = NULL;
179 char *local_dfs_path = NULL;
180 NTSTATUS status;
181 int i;
182 uint16_t max_referral_level = r->in.req.max_referral_level;
184 if (DEBUGLVL(10)) {
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
188 /* get the junction entry */
189 if (r->in.req.servername == NULL) {
190 return NT_STATUS_NOT_FOUND;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path = talloc_strdup(r, r->in.req.servername);
199 if (local_dfs_path == NULL) {
200 return NT_STATUS_NO_MEMORY;
202 pathnamep = local_dfs_path;
203 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
204 IS_DIRECTORY_SEP(pathnamep[1])) {
205 pathnamep++;
208 junction = talloc_zero(r, struct junction_map);
209 if (junction == NULL) {
210 return NT_STATUS_NO_MEMORY;
213 /* The following call can change cwd. */
214 status = get_referred_path(r, pathnamep,
215 !handle->conn->sconn->using_smb2,
216 junction, &consumedcnt, &self_referral);
217 if (!NT_STATUS_IS_OK(status)) {
218 vfs_ChDir(handle->conn, handle->conn->connectpath);
219 return status;
221 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 if (!self_referral) {
224 pathnamep[consumedcnt] = '\0';
226 if (DEBUGLVL(3)) {
227 dbgtext("Path %s to alternate path(s):",
228 pathnamep);
229 for (i=0; i < junction->referral_count; i++) {
230 dbgtext(" %s",
231 junction->referral_list[i].alternate_path);
233 dbgtext(".\n");
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
253 if (self_referral) {
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
265 case 2:
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
273 t->version = 2;
274 v2->size = VERSION2_REFERRAL_SIZE;
275 if (self_referral) {
276 v2->server_type = DFS_SERVER_ROOT;
277 } else {
278 v2->server_type = DFS_SERVER_NON_ROOT;
280 v2->entry_flags = 0;
281 v2->proximity = ref->proximity;
282 v2->ttl = ref->ttl;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
298 break;
299 case 3:
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
308 t->version = 3;
309 v3->size = VERSION3_REFERRAL_SIZE;
310 if (self_referral) {
311 v3->server_type = DFS_SERVER_ROOT;
312 } else {
313 v3->server_type = DFS_SERVER_NON_ROOT;
315 v3->entry_flags = 0;
316 v3->ttl = ref->ttl;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
331 break;
332 default:
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
338 if (DEBUGLVL(10)) {
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
342 return NT_STATUS_OK;
345 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
346 TALLOC_CTX *mem_ctx,
347 const char *service_path,
348 char **base_volume)
350 return NT_STATUS_NOT_SUPPORTED;
353 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
354 TALLOC_CTX *mem_ctx,
355 const char *base_volume,
356 time_t *tstamp,
357 bool rw,
358 char **base_path,
359 char **snap_path)
361 return NT_STATUS_NOT_SUPPORTED;
364 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
365 TALLOC_CTX *mem_ctx,
366 char *base_path,
367 char *snap_path)
369 return NT_STATUS_NOT_SUPPORTED;
372 /* Directory operations */
374 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
376 DIR *result;
378 START_PROFILE(syscall_opendir);
379 result = opendir(fname);
380 END_PROFILE(syscall_opendir);
381 return result;
384 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
385 files_struct *fsp,
386 const char *mask,
387 uint32_t attr)
389 DIR *result;
391 START_PROFILE(syscall_fdopendir);
392 result = sys_fdopendir(fsp->fh->fd);
393 END_PROFILE(syscall_fdopendir);
394 return result;
398 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
399 DIR *dirp,
400 SMB_STRUCT_STAT *sbuf)
402 struct dirent *result;
404 START_PROFILE(syscall_readdir);
405 result = readdir(dirp);
406 END_PROFILE(syscall_readdir);
407 if (sbuf) {
408 /* Default Posix readdir() does not give us stat info.
409 * Set to invalid to indicate we didn't return this info. */
410 SET_STAT_INVALID(*sbuf);
411 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
412 if (result != NULL) {
413 /* See if we can efficiently return this. */
414 struct stat st;
415 int flags = (lp_posix_pathnames() ?
416 AT_SYMLINK_NOFOLLOW : 0);
417 int ret = fstatat(dirfd(dirp),
418 result->d_name,
419 &st,
420 flags);
421 if (ret == 0) {
422 init_stat_ex_from_stat(sbuf,
423 &st,
424 lp_fake_directory_create_times(
425 SNUM(handle->conn)));
428 #endif
430 return result;
433 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
434 const struct smb_filename *fname,
435 TALLOC_CTX *mem_ctx,
436 struct readdir_attr_data **attr_data)
438 return NT_STATUS_NOT_SUPPORTED;
441 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
443 START_PROFILE(syscall_seekdir);
444 seekdir(dirp, offset);
445 END_PROFILE(syscall_seekdir);
448 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
450 long result;
451 START_PROFILE(syscall_telldir);
452 result = telldir(dirp);
453 END_PROFILE(syscall_telldir);
454 return result;
457 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
459 START_PROFILE(syscall_rewinddir);
460 rewinddir(dirp);
461 END_PROFILE(syscall_rewinddir);
464 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
466 int result;
467 bool has_dacl = False;
468 char *parent = NULL;
470 START_PROFILE(syscall_mkdir);
472 if (lp_inherit_acls(SNUM(handle->conn))
473 && parent_dirname(talloc_tos(), path, &parent, NULL)
474 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
475 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
477 TALLOC_FREE(parent);
479 result = mkdir(path, mode);
481 if (result == 0 && !has_dacl) {
483 * We need to do this as the default behavior of POSIX ACLs
484 * is to set the mask to be the requested group permission
485 * bits, not the group permission bits to be the requested
486 * group permission bits. This is not what we want, as it will
487 * mess up any inherited ACL bits that were set. JRA.
489 int saved_errno = errno; /* We may get ENOSYS */
490 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
491 errno = saved_errno;
494 END_PROFILE(syscall_mkdir);
495 return result;
498 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
500 int result;
502 START_PROFILE(syscall_rmdir);
503 result = rmdir(path);
504 END_PROFILE(syscall_rmdir);
505 return result;
508 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
510 int result;
512 START_PROFILE(syscall_closedir);
513 result = closedir(dirp);
514 END_PROFILE(syscall_closedir);
515 return result;
518 static void vfswrap_init_search_op(vfs_handle_struct *handle,
519 DIR *dirp)
521 /* Default behavior is a NOOP */
524 /* File operations */
526 static int vfswrap_open(vfs_handle_struct *handle,
527 struct smb_filename *smb_fname,
528 files_struct *fsp, int flags, mode_t mode)
530 int result = -1;
532 START_PROFILE(syscall_open);
534 if (smb_fname->stream_name) {
535 errno = ENOENT;
536 goto out;
539 result = open(smb_fname->base_name, flags, mode);
540 out:
541 END_PROFILE(syscall_open);
542 return result;
545 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
546 struct smb_request *req,
547 uint16_t root_dir_fid,
548 struct smb_filename *smb_fname,
549 uint32_t access_mask,
550 uint32_t share_access,
551 uint32_t create_disposition,
552 uint32_t create_options,
553 uint32_t file_attributes,
554 uint32_t oplock_request,
555 struct smb2_lease *lease,
556 uint64_t allocation_size,
557 uint32_t private_flags,
558 struct security_descriptor *sd,
559 struct ea_list *ea_list,
560 files_struct **result,
561 int *pinfo,
562 const struct smb2_create_blobs *in_context_blobs,
563 struct smb2_create_blobs *out_context_blobs)
565 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
566 access_mask, share_access,
567 create_disposition, create_options,
568 file_attributes, oplock_request, lease,
569 allocation_size, private_flags,
570 sd, ea_list, result,
571 pinfo, in_context_blobs, out_context_blobs);
574 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
576 int result;
578 START_PROFILE(syscall_close);
579 result = fd_close_posix(fsp);
580 END_PROFILE(syscall_close);
581 return result;
584 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
586 ssize_t result;
588 START_PROFILE_BYTES(syscall_read, n);
589 result = sys_read(fsp->fh->fd, data, n);
590 END_PROFILE_BYTES(syscall_read);
591 return result;
594 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
595 size_t n, off_t offset)
597 ssize_t result;
599 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
600 START_PROFILE_BYTES(syscall_pread, n);
601 result = sys_pread(fsp->fh->fd, data, n, offset);
602 END_PROFILE_BYTES(syscall_pread);
604 if (result == -1 && errno == ESPIPE) {
605 /* Maintain the fiction that pipes can be seeked (sought?) on. */
606 result = SMB_VFS_READ(fsp, data, n);
607 fsp->fh->pos = 0;
610 #else /* HAVE_PREAD */
611 off_t curr;
612 int lerrno;
614 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
615 if (curr == -1 && errno == ESPIPE) {
616 /* Maintain the fiction that pipes can be seeked (sought?) on. */
617 result = SMB_VFS_READ(fsp, data, n);
618 fsp->fh->pos = 0;
619 return result;
622 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
623 return -1;
626 errno = 0;
627 result = SMB_VFS_READ(fsp, data, n);
628 lerrno = errno;
630 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
631 errno = lerrno;
633 #endif /* HAVE_PREAD */
635 return result;
638 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
640 ssize_t result;
642 START_PROFILE_BYTES(syscall_write, n);
643 result = sys_write(fsp->fh->fd, data, n);
644 END_PROFILE_BYTES(syscall_write);
645 return result;
648 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
649 size_t n, off_t offset)
651 ssize_t result;
653 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
654 START_PROFILE_BYTES(syscall_pwrite, n);
655 result = sys_pwrite(fsp->fh->fd, data, n, offset);
656 END_PROFILE_BYTES(syscall_pwrite);
658 if (result == -1 && errno == ESPIPE) {
659 /* Maintain the fiction that pipes can be sought on. */
660 result = SMB_VFS_WRITE(fsp, data, n);
663 #else /* HAVE_PWRITE */
664 off_t curr;
665 int lerrno;
667 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
668 if (curr == -1) {
669 return -1;
672 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
673 return -1;
676 result = SMB_VFS_WRITE(fsp, data, n);
677 lerrno = errno;
679 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
680 errno = lerrno;
682 #endif /* HAVE_PWRITE */
684 return result;
687 static void vfswrap_asys_finished(struct tevent_context *ev,
688 struct tevent_fd *fde,
689 uint16_t flags, void *p);
691 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
693 int ret;
694 int fd;
696 if (conn->asys_ctx != NULL) {
697 return true;
699 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
700 if (ret != 0) {
701 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
702 return false;
705 fd = asys_signalfd(conn->asys_ctx);
707 set_blocking(fd, false);
709 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
710 TEVENT_FD_READ,
711 vfswrap_asys_finished,
712 conn->asys_ctx);
713 if (conn->asys_fde == NULL) {
714 DEBUG(1, ("tevent_add_fd failed\n"));
715 asys_context_destroy(conn->asys_ctx);
716 conn->asys_ctx = NULL;
717 return false;
719 return true;
722 struct vfswrap_asys_state {
723 struct asys_context *asys_ctx;
724 struct tevent_req *req;
725 ssize_t ret;
726 int err;
727 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
728 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
731 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
733 asys_cancel(s->asys_ctx, s->req);
734 return 0;
737 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
738 TALLOC_CTX *mem_ctx,
739 struct tevent_context *ev,
740 struct files_struct *fsp,
741 void *data,
742 size_t n, off_t offset)
744 struct tevent_req *req;
745 struct vfswrap_asys_state *state;
746 int ret;
748 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
749 if (req == NULL) {
750 return NULL;
752 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
753 tevent_req_oom(req);
754 return tevent_req_post(req, ev);
756 state->asys_ctx = handle->conn->sconn->asys_ctx;
757 state->req = req;
759 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
760 state->profile_bytes, n);
761 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
762 if (ret != 0) {
763 tevent_req_error(req, ret);
764 return tevent_req_post(req, ev);
766 talloc_set_destructor(state, vfswrap_asys_state_destructor);
768 return req;
771 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
772 TALLOC_CTX *mem_ctx,
773 struct tevent_context *ev,
774 struct files_struct *fsp,
775 const void *data,
776 size_t n, off_t offset)
778 struct tevent_req *req;
779 struct vfswrap_asys_state *state;
780 int ret;
782 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
783 if (req == NULL) {
784 return NULL;
786 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
787 tevent_req_oom(req);
788 return tevent_req_post(req, ev);
790 state->asys_ctx = handle->conn->sconn->asys_ctx;
791 state->req = req;
793 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
794 state->profile_bytes, n);
795 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
796 if (ret != 0) {
797 tevent_req_error(req, ret);
798 return tevent_req_post(req, ev);
800 talloc_set_destructor(state, vfswrap_asys_state_destructor);
802 return req;
805 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
806 TALLOC_CTX *mem_ctx,
807 struct tevent_context *ev,
808 struct files_struct *fsp)
810 struct tevent_req *req;
811 struct vfswrap_asys_state *state;
812 int ret;
814 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
815 if (req == NULL) {
816 return NULL;
818 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
819 tevent_req_oom(req);
820 return tevent_req_post(req, ev);
822 state->asys_ctx = handle->conn->sconn->asys_ctx;
823 state->req = req;
825 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
826 state->profile_basic);
827 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
828 if (ret != 0) {
829 tevent_req_error(req, ret);
830 return tevent_req_post(req, ev);
832 talloc_set_destructor(state, vfswrap_asys_state_destructor);
834 return req;
837 static void vfswrap_asys_finished(struct tevent_context *ev,
838 struct tevent_fd *fde,
839 uint16_t flags, void *p)
841 struct asys_context *asys_ctx = (struct asys_context *)p;
842 struct asys_result results[outstanding_aio_calls];
843 int i, ret;
845 if ((flags & TEVENT_FD_READ) == 0) {
846 return;
849 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
850 if (ret < 0) {
851 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
852 return;
855 for (i=0; i<ret; i++) {
856 struct asys_result *result = &results[i];
857 struct tevent_req *req;
858 struct vfswrap_asys_state *state;
860 if ((result->ret == -1) && (result->err == ECANCELED)) {
861 continue;
864 req = talloc_get_type_abort(result->private_data,
865 struct tevent_req);
866 state = tevent_req_data(req, struct vfswrap_asys_state);
868 talloc_set_destructor(state, NULL);
870 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
871 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
872 state->ret = result->ret;
873 state->err = result->err;
874 tevent_req_defer_callback(req, ev);
875 tevent_req_done(req);
879 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
881 struct vfswrap_asys_state *state = tevent_req_data(
882 req, struct vfswrap_asys_state);
884 if (tevent_req_is_unix_error(req, err)) {
885 return -1;
887 *err = state->err;
888 return state->ret;
891 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
893 struct vfswrap_asys_state *state = tevent_req_data(
894 req, struct vfswrap_asys_state);
896 if (tevent_req_is_unix_error(req, err)) {
897 return -1;
899 *err = state->err;
900 return state->ret;
903 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
905 off_t result = 0;
907 START_PROFILE(syscall_lseek);
909 /* Cope with 'stat' file opens. */
910 if (fsp->fh->fd != -1)
911 result = lseek(fsp->fh->fd, offset, whence);
914 * We want to maintain the fiction that we can seek
915 * on a fifo for file system purposes. This allows
916 * people to set up UNIX fifo's that feed data to Windows
917 * applications. JRA.
920 if((result == -1) && (errno == ESPIPE)) {
921 result = 0;
922 errno = 0;
925 END_PROFILE(syscall_lseek);
926 return result;
929 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
930 off_t offset, size_t n)
932 ssize_t result;
934 START_PROFILE_BYTES(syscall_sendfile, n);
935 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
936 END_PROFILE_BYTES(syscall_sendfile);
937 return result;
940 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
941 int fromfd,
942 files_struct *tofsp,
943 off_t offset,
944 size_t n)
946 ssize_t result;
948 START_PROFILE_BYTES(syscall_recvfile, n);
949 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
950 END_PROFILE_BYTES(syscall_recvfile);
951 return result;
954 static int vfswrap_rename(vfs_handle_struct *handle,
955 const struct smb_filename *smb_fname_src,
956 const struct smb_filename *smb_fname_dst)
958 int result = -1;
960 START_PROFILE(syscall_rename);
962 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
963 errno = ENOENT;
964 goto out;
967 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
969 out:
970 END_PROFILE(syscall_rename);
971 return result;
974 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
976 #ifdef HAVE_FSYNC
977 int result;
979 START_PROFILE(syscall_fsync);
980 result = fsync(fsp->fh->fd);
981 END_PROFILE(syscall_fsync);
982 return result;
983 #else
984 return 0;
985 #endif
988 static int vfswrap_stat(vfs_handle_struct *handle,
989 struct smb_filename *smb_fname)
991 int result = -1;
993 START_PROFILE(syscall_stat);
995 if (smb_fname->stream_name) {
996 errno = ENOENT;
997 goto out;
1000 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1001 lp_fake_directory_create_times(SNUM(handle->conn)));
1002 out:
1003 END_PROFILE(syscall_stat);
1004 return result;
1007 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1009 int result;
1011 START_PROFILE(syscall_fstat);
1012 result = sys_fstat(fsp->fh->fd,
1013 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1014 END_PROFILE(syscall_fstat);
1015 return result;
1018 static int vfswrap_lstat(vfs_handle_struct *handle,
1019 struct smb_filename *smb_fname)
1021 int result = -1;
1023 START_PROFILE(syscall_lstat);
1025 if (smb_fname->stream_name) {
1026 errno = ENOENT;
1027 goto out;
1030 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1031 lp_fake_directory_create_times(SNUM(handle->conn)));
1032 out:
1033 END_PROFILE(syscall_lstat);
1034 return result;
1037 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1038 const char *name,
1039 enum vfs_translate_direction direction,
1040 TALLOC_CTX *mem_ctx,
1041 char **mapped_name)
1043 return NT_STATUS_NONE_MAPPED;
1047 * Implement the default fsctl operation.
1049 static bool vfswrap_logged_ioctl_message = false;
1051 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1052 struct files_struct *fsp,
1053 TALLOC_CTX *ctx,
1054 uint32_t function,
1055 uint16_t req_flags, /* Needed for UNICODE ... */
1056 const uint8_t *_in_data,
1057 uint32_t in_len,
1058 uint8_t **_out_data,
1059 uint32_t max_out_len,
1060 uint32_t *out_len)
1062 const char *in_data = (const char *)_in_data;
1063 char **out_data = (char **)_out_data;
1064 NTSTATUS status;
1066 switch (function) {
1067 case FSCTL_SET_SPARSE:
1069 bool set_sparse = true;
1071 if (in_len >= 1 && in_data[0] == 0) {
1072 set_sparse = false;
1075 status = file_set_sparse(handle->conn, fsp, set_sparse);
1077 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1078 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1079 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1080 nt_errstr(status)));
1082 return status;
1085 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1087 unsigned char objid[16];
1088 char *return_data = NULL;
1090 /* This should return the object-id on this file.
1091 * I think I'll make this be the inode+dev. JRA.
1094 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1095 fsp_fnum_dbg(fsp)));
1097 *out_len = MIN(max_out_len, 64);
1099 /* Hmmm, will this cause problems if less data asked for? */
1100 return_data = talloc_array(ctx, char, 64);
1101 if (return_data == NULL) {
1102 return NT_STATUS_NO_MEMORY;
1105 /* For backwards compatibility only store the dev/inode. */
1106 push_file_id_16(return_data, &fsp->file_id);
1107 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1108 push_file_id_16(return_data+32, &fsp->file_id);
1109 memset(return_data+48, 0, 16);
1110 *out_data = return_data;
1111 return NT_STATUS_OK;
1114 case FSCTL_GET_REPARSE_POINT:
1116 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1117 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1118 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1119 return NT_STATUS_NOT_A_REPARSE_POINT;
1122 case FSCTL_SET_REPARSE_POINT:
1124 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1125 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1126 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1127 return NT_STATUS_NOT_A_REPARSE_POINT;
1130 case FSCTL_GET_SHADOW_COPY_DATA:
1133 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1134 * and return their volume names. If max_data_count is 16, then it is just
1135 * asking for the number of volumes and length of the combined names.
1137 * pdata is the data allocated by our caller, but that uses
1138 * total_data_count (which is 0 in our case) rather than max_data_count.
1139 * Allocate the correct amount and return the pointer to let
1140 * it be deallocated when we return.
1142 struct shadow_copy_data *shadow_data = NULL;
1143 bool labels = False;
1144 uint32_t labels_data_count = 0;
1145 uint32_t i;
1146 char *cur_pdata = NULL;
1148 if (max_out_len < 16) {
1149 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1150 max_out_len));
1151 return NT_STATUS_INVALID_PARAMETER;
1154 if (max_out_len > 16) {
1155 labels = True;
1158 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1159 if (shadow_data == NULL) {
1160 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1161 return NT_STATUS_NO_MEMORY;
1165 * Call the VFS routine to actually do the work.
1167 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1168 int log_lev = 0;
1169 if (errno == 0) {
1170 /* broken module didn't set errno on error */
1171 status = NT_STATUS_UNSUCCESSFUL;
1172 } else {
1173 status = map_nt_error_from_unix(errno);
1174 if (NT_STATUS_EQUAL(status,
1175 NT_STATUS_NOT_SUPPORTED)) {
1176 log_lev = 5;
1179 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1180 "connectpath %s, failed - %s.\n",
1181 fsp->conn->connectpath,
1182 nt_errstr(status)));
1183 TALLOC_FREE(shadow_data);
1184 return status;
1187 labels_data_count = (shadow_data->num_volumes * 2 *
1188 sizeof(SHADOW_COPY_LABEL)) + 2;
1190 if (!labels) {
1191 *out_len = 16;
1192 } else {
1193 *out_len = 12 + labels_data_count;
1196 if (max_out_len < *out_len) {
1197 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1198 max_out_len, *out_len));
1199 TALLOC_FREE(shadow_data);
1200 return NT_STATUS_BUFFER_TOO_SMALL;
1203 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1204 if (cur_pdata == NULL) {
1205 TALLOC_FREE(shadow_data);
1206 return NT_STATUS_NO_MEMORY;
1209 *out_data = cur_pdata;
1211 /* num_volumes 4 bytes */
1212 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1214 if (labels) {
1215 /* num_labels 4 bytes */
1216 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1219 /* needed_data_count 4 bytes */
1220 SIVAL(cur_pdata, 8, labels_data_count);
1222 cur_pdata += 12;
1224 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1225 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1226 if (labels && shadow_data->labels) {
1227 for (i=0; i<shadow_data->num_volumes; i++) {
1228 size_t len = 0;
1229 status = srvstr_push(cur_pdata, req_flags,
1230 cur_pdata, shadow_data->labels[i],
1231 2 * sizeof(SHADOW_COPY_LABEL),
1232 STR_UNICODE|STR_TERMINATE, &len);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 TALLOC_FREE(*out_data);
1235 TALLOC_FREE(shadow_data);
1236 return status;
1238 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1239 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1243 TALLOC_FREE(shadow_data);
1245 return NT_STATUS_OK;
1248 case FSCTL_FIND_FILES_BY_SID:
1250 /* pretend this succeeded -
1252 * we have to send back a list with all files owned by this SID
1254 * but I have to check that --metze
1256 struct dom_sid sid;
1257 uid_t uid;
1258 size_t sid_len;
1260 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1261 fsp_fnum_dbg(fsp)));
1263 if (in_len < 8) {
1264 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1265 return NT_STATUS_INVALID_PARAMETER;
1268 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1270 /* unknown 4 bytes: this is not the length of the sid :-( */
1271 /*unknown = IVAL(pdata,0);*/
1273 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1274 return NT_STATUS_INVALID_PARAMETER;
1276 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1278 if (!sid_to_uid(&sid, &uid)) {
1279 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1280 sid_string_dbg(&sid),
1281 (unsigned long)sid_len));
1282 uid = (-1);
1285 /* we can take a look at the find source :-)
1287 * find ./ -uid $uid -name '*' is what we need here
1290 * and send 4bytes len and then NULL terminated unicode strings
1291 * for each file
1293 * but I don't know how to deal with the paged results
1294 * (maybe we can hang the result anywhere in the fsp struct)
1296 * but I don't know how to deal with the paged results
1297 * (maybe we can hang the result anywhere in the fsp struct)
1299 * we don't send all files at once
1300 * and at the next we should *not* start from the beginning,
1301 * so we have to cache the result
1303 * --metze
1306 /* this works for now... */
1307 return NT_STATUS_OK;
1310 case FSCTL_QUERY_ALLOCATED_RANGES:
1312 /* FIXME: This is just a dummy reply, telling that all of the
1313 * file is allocated. MKS cp needs that.
1314 * Adding the real allocated ranges via FIEMAP on Linux
1315 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1316 * this FSCTL correct for sparse files.
1318 uint64_t offset, length;
1319 char *out_data_tmp = NULL;
1321 if (in_len != 16) {
1322 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1323 in_len));
1324 return NT_STATUS_INVALID_PARAMETER;
1327 if (max_out_len < 16) {
1328 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1329 max_out_len));
1330 return NT_STATUS_INVALID_PARAMETER;
1333 offset = BVAL(in_data,0);
1334 length = BVAL(in_data,8);
1336 if (offset + length < offset) {
1337 /* No 64-bit integer wrap. */
1338 return NT_STATUS_INVALID_PARAMETER;
1341 /* Shouldn't this be SMB_VFS_STAT ... ? */
1342 status = vfs_stat_fsp(fsp);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 return status;
1347 *out_len = 16;
1348 out_data_tmp = talloc_array(ctx, char, *out_len);
1349 if (out_data_tmp == NULL) {
1350 DEBUG(10, ("unable to allocate memory for response\n"));
1351 return NT_STATUS_NO_MEMORY;
1354 if (offset > fsp->fsp_name->st.st_ex_size ||
1355 fsp->fsp_name->st.st_ex_size == 0 ||
1356 length == 0) {
1357 memset(out_data_tmp, 0, *out_len);
1358 } else {
1359 uint64_t end = offset + length;
1360 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1361 SBVAL(out_data_tmp, 0, 0);
1362 SBVAL(out_data_tmp, 8, end);
1365 *out_data = out_data_tmp;
1367 return NT_STATUS_OK;
1370 case FSCTL_IS_VOLUME_DIRTY:
1372 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1373 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1375 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1376 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1378 return NT_STATUS_INVALID_PARAMETER;
1381 default:
1383 * Only print once ... unfortunately there could be lots of
1384 * different FSCTLs that are called.
1386 if (!vfswrap_logged_ioctl_message) {
1387 vfswrap_logged_ioctl_message = true;
1388 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1389 __func__, function));
1393 return NT_STATUS_NOT_SUPPORTED;
1396 struct vfs_cc_state {
1397 off_t copied;
1398 uint8_t buf[65536];
1401 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1402 TALLOC_CTX *mem_ctx,
1403 struct tevent_context *ev,
1404 struct files_struct *src_fsp,
1405 off_t src_off,
1406 struct files_struct *dest_fsp,
1407 off_t dest_off,
1408 off_t num)
1410 struct tevent_req *req;
1411 struct vfs_cc_state *vfs_cc_state;
1412 NTSTATUS status;
1414 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1415 (unsigned long)num));
1417 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1418 if (req == NULL) {
1419 return NULL;
1422 status = vfs_stat_fsp(src_fsp);
1423 if (tevent_req_nterror(req, status)) {
1424 return tevent_req_post(req, ev);
1427 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1429 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1430 * If the SourceOffset or SourceOffset + Length extends beyond
1431 * the end of file, the server SHOULD<240> treat this as a
1432 * STATUS_END_OF_FILE error.
1433 * ...
1434 * <240> Section 3.3.5.15.6: Windows servers will return
1435 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1437 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1438 return tevent_req_post(req, ev);
1441 /* could use 2.6.33+ sendfile here to do this in kernel */
1442 while (vfs_cc_state->copied < num) {
1443 ssize_t ret;
1444 struct lock_struct lck;
1445 int saved_errno;
1447 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1448 num - vfs_cc_state->copied);
1450 if (src_fsp->op == NULL) {
1451 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1452 return tevent_req_post(req, ev);
1454 init_strict_lock_struct(src_fsp,
1455 src_fsp->op->global->open_persistent_id,
1456 src_off,
1457 this_num,
1458 READ_LOCK,
1459 &lck);
1461 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1462 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1463 return tevent_req_post(req, ev);
1466 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1467 this_num, src_off);
1468 if (ret == -1) {
1469 saved_errno = errno;
1472 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1474 if (ret == -1) {
1475 errno = saved_errno;
1476 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1477 return tevent_req_post(req, ev);
1479 if (ret != this_num) {
1480 /* zero tolerance for short reads */
1481 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1482 return tevent_req_post(req, ev);
1485 src_off += ret;
1487 if (dest_fsp->op == NULL) {
1488 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1489 return tevent_req_post(req, ev);
1492 init_strict_lock_struct(dest_fsp,
1493 dest_fsp->op->global->open_persistent_id,
1494 dest_off,
1495 this_num,
1496 WRITE_LOCK,
1497 &lck);
1499 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1500 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1501 return tevent_req_post(req, ev);
1504 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1505 this_num, dest_off);
1506 if (ret == -1) {
1507 saved_errno = errno;
1510 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1512 if (ret == -1) {
1513 errno = saved_errno;
1514 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1515 return tevent_req_post(req, ev);
1517 if (ret != this_num) {
1518 /* zero tolerance for short writes */
1519 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1520 return tevent_req_post(req, ev);
1522 dest_off += ret;
1524 vfs_cc_state->copied += this_num;
1527 tevent_req_done(req);
1528 return tevent_req_post(req, ev);
1531 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1532 struct tevent_req *req,
1533 off_t *copied)
1535 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1536 struct vfs_cc_state);
1537 NTSTATUS status;
1539 if (tevent_req_is_nterror(req, &status)) {
1540 DEBUG(2, ("server side copy chunk failed: %s\n",
1541 nt_errstr(status)));
1542 *copied = 0;
1543 tevent_req_received(req);
1544 return status;
1547 *copied = vfs_cc_state->copied;
1548 DEBUG(10, ("server side copy chunk copied %lu\n",
1549 (unsigned long)*copied));
1550 tevent_req_received(req);
1552 return NT_STATUS_OK;
1555 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1556 TALLOC_CTX *mem_ctx,
1557 struct files_struct *fsp,
1558 struct smb_filename *smb_fname,
1559 uint16_t *_compression_fmt)
1561 return NT_STATUS_INVALID_DEVICE_REQUEST;
1564 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1565 TALLOC_CTX *mem_ctx,
1566 struct files_struct *fsp,
1567 uint16_t compression_fmt)
1569 return NT_STATUS_INVALID_DEVICE_REQUEST;
1572 /********************************************************************
1573 Given a stat buffer return the allocated size on disk, taking into
1574 account sparse files.
1575 ********************************************************************/
1576 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1577 struct files_struct *fsp,
1578 const SMB_STRUCT_STAT *sbuf)
1580 uint64_t result;
1582 START_PROFILE(syscall_get_alloc_size);
1584 if(S_ISDIR(sbuf->st_ex_mode)) {
1585 result = 0;
1586 goto out;
1589 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1590 /* The type of st_blocksize is blkcnt_t which *MUST* be
1591 signed (according to POSIX) and can be less than 64-bits.
1592 Ensure when we're converting to 64 bits wide we don't
1593 sign extend. */
1594 #if defined(SIZEOF_BLKCNT_T_8)
1595 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1596 #elif defined(SIZEOF_BLKCNT_T_4)
1598 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1599 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1601 #else
1602 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1603 #endif
1604 if (result == 0) {
1606 * Some file systems do not allocate a block for very
1607 * small files. But for non-empty file should report a
1608 * positive size.
1611 uint64_t filesize = get_file_size_stat(sbuf);
1612 if (filesize > 0) {
1613 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1616 #else
1617 result = get_file_size_stat(sbuf);
1618 #endif
1620 if (fsp && fsp->initial_allocation_size)
1621 result = MAX(result,fsp->initial_allocation_size);
1623 result = smb_roundup(handle->conn, result);
1625 out:
1626 END_PROFILE(syscall_get_alloc_size);
1627 return result;
1630 static int vfswrap_unlink(vfs_handle_struct *handle,
1631 const struct smb_filename *smb_fname)
1633 int result = -1;
1635 START_PROFILE(syscall_unlink);
1637 if (smb_fname->stream_name) {
1638 errno = ENOENT;
1639 goto out;
1641 result = unlink(smb_fname->base_name);
1643 out:
1644 END_PROFILE(syscall_unlink);
1645 return result;
1648 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1650 int result;
1652 START_PROFILE(syscall_chmod);
1655 * We need to do this due to the fact that the default POSIX ACL
1656 * chmod modifies the ACL *mask* for the group owner, not the
1657 * group owner bits directly. JRA.
1662 int saved_errno = errno; /* We might get ENOSYS */
1663 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1664 END_PROFILE(syscall_chmod);
1665 return result;
1667 /* Error - return the old errno. */
1668 errno = saved_errno;
1671 result = chmod(path, mode);
1672 END_PROFILE(syscall_chmod);
1673 return result;
1676 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1678 int result;
1680 START_PROFILE(syscall_fchmod);
1683 * We need to do this due to the fact that the default POSIX ACL
1684 * chmod modifies the ACL *mask* for the group owner, not the
1685 * group owner bits directly. JRA.
1689 int saved_errno = errno; /* We might get ENOSYS */
1690 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1691 END_PROFILE(syscall_fchmod);
1692 return result;
1694 /* Error - return the old errno. */
1695 errno = saved_errno;
1698 #if defined(HAVE_FCHMOD)
1699 result = fchmod(fsp->fh->fd, mode);
1700 #else
1701 result = -1;
1702 errno = ENOSYS;
1703 #endif
1705 END_PROFILE(syscall_fchmod);
1706 return result;
1709 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1711 int result;
1713 START_PROFILE(syscall_chown);
1714 result = chown(path, uid, gid);
1715 END_PROFILE(syscall_chown);
1716 return result;
1719 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1721 #ifdef HAVE_FCHOWN
1722 int result;
1724 START_PROFILE(syscall_fchown);
1725 result = fchown(fsp->fh->fd, uid, gid);
1726 END_PROFILE(syscall_fchown);
1727 return result;
1728 #else
1729 errno = ENOSYS;
1730 return -1;
1731 #endif
1734 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1736 int result;
1738 START_PROFILE(syscall_lchown);
1739 result = lchown(path, uid, gid);
1740 END_PROFILE(syscall_lchown);
1741 return result;
1744 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1746 int result;
1748 START_PROFILE(syscall_chdir);
1749 result = chdir(path);
1750 END_PROFILE(syscall_chdir);
1751 return result;
1754 static char *vfswrap_getwd(vfs_handle_struct *handle)
1756 char *result;
1758 START_PROFILE(syscall_getwd);
1759 result = sys_getwd();
1760 END_PROFILE(syscall_getwd);
1761 return result;
1764 /*********************************************************************
1765 nsec timestamp resolution call. Convert down to whatever the underlying
1766 system will support.
1767 **********************************************************************/
1769 static int vfswrap_ntimes(vfs_handle_struct *handle,
1770 const struct smb_filename *smb_fname,
1771 struct smb_file_time *ft)
1773 int result = -1;
1775 START_PROFILE(syscall_ntimes);
1777 if (smb_fname->stream_name) {
1778 errno = ENOENT;
1779 goto out;
1782 if (ft != NULL) {
1783 if (null_timespec(ft->atime)) {
1784 ft->atime= smb_fname->st.st_ex_atime;
1787 if (null_timespec(ft->mtime)) {
1788 ft->mtime = smb_fname->st.st_ex_mtime;
1791 if (!null_timespec(ft->create_time)) {
1792 set_create_timespec_ea(handle->conn,
1793 smb_fname,
1794 ft->create_time);
1797 if ((timespec_compare(&ft->atime,
1798 &smb_fname->st.st_ex_atime) == 0) &&
1799 (timespec_compare(&ft->mtime,
1800 &smb_fname->st.st_ex_mtime) == 0)) {
1801 return 0;
1805 #if defined(HAVE_UTIMENSAT)
1806 if (ft != NULL) {
1807 struct timespec ts[2];
1808 ts[0] = ft->atime;
1809 ts[1] = ft->mtime;
1810 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1811 } else {
1812 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1814 if (!((result == -1) && (errno == ENOSYS))) {
1815 goto out;
1817 #endif
1818 #if defined(HAVE_UTIMES)
1819 if (ft != NULL) {
1820 struct timeval tv[2];
1821 tv[0] = convert_timespec_to_timeval(ft->atime);
1822 tv[1] = convert_timespec_to_timeval(ft->mtime);
1823 result = utimes(smb_fname->base_name, tv);
1824 } else {
1825 result = utimes(smb_fname->base_name, NULL);
1827 if (!((result == -1) && (errno == ENOSYS))) {
1828 goto out;
1830 #endif
1831 #if defined(HAVE_UTIME)
1832 if (ft != NULL) {
1833 struct utimbuf times;
1834 times.actime = convert_timespec_to_time_t(ft->atime);
1835 times.modtime = convert_timespec_to_time_t(ft->mtime);
1836 result = utime(smb_fname->base_name, &times);
1837 } else {
1838 result = utime(smb_fname->base_name, NULL);
1840 if (!((result == -1) && (errno == ENOSYS))) {
1841 goto out;
1843 #endif
1844 errno = ENOSYS;
1845 result = -1;
1847 out:
1848 END_PROFILE(syscall_ntimes);
1849 return result;
1852 /*********************************************************************
1853 A version of ftruncate that will write the space on disk if strict
1854 allocate is set.
1855 **********************************************************************/
1857 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1859 off_t space_to_write;
1860 uint64_t space_avail;
1861 uint64_t bsize,dfree,dsize;
1862 int ret;
1863 NTSTATUS status;
1864 SMB_STRUCT_STAT *pst;
1866 status = vfs_stat_fsp(fsp);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 return -1;
1870 pst = &fsp->fsp_name->st;
1872 #ifdef S_ISFIFO
1873 if (S_ISFIFO(pst->st_ex_mode))
1874 return 0;
1875 #endif
1877 if (pst->st_ex_size == len)
1878 return 0;
1880 /* Shrink - just ftruncate. */
1881 if (pst->st_ex_size > len)
1882 return ftruncate(fsp->fh->fd, len);
1884 space_to_write = len - pst->st_ex_size;
1886 /* for allocation try fallocate first. This can fail on some
1887 platforms e.g. when the filesystem doesn't support it and no
1888 emulation is being done by the libc (like on AIX with JFS1). In that
1889 case we do our own emulation. fallocate implementations can
1890 return ENOTSUP or EINVAL in cases like that. */
1891 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1892 if (ret == -1 && errno == ENOSPC) {
1893 return -1;
1895 if (ret == 0) {
1896 return 0;
1898 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1899 "error %d. Falling back to slow manual allocation\n", errno));
1901 /* available disk space is enough or not? */
1902 space_avail = get_dfree_info(fsp->conn,
1903 fsp->fsp_name->base_name,
1904 &bsize, &dfree, &dsize);
1905 /* space_avail is 1k blocks */
1906 if (space_avail == (uint64_t)-1 ||
1907 ((uint64_t)space_to_write/1024 > space_avail) ) {
1908 errno = ENOSPC;
1909 return -1;
1912 /* Write out the real space on disk. */
1913 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1914 if (ret != 0) {
1915 return -1;
1918 return 0;
1921 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1923 int result = -1;
1924 SMB_STRUCT_STAT *pst;
1925 NTSTATUS status;
1926 char c = 0;
1928 START_PROFILE(syscall_ftruncate);
1930 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1931 result = strict_allocate_ftruncate(handle, fsp, len);
1932 END_PROFILE(syscall_ftruncate);
1933 return result;
1936 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1937 ftruncate if the system supports it. Then I discovered that
1938 you can have some filesystems that support ftruncate
1939 expansion and some that don't! On Linux fat can't do
1940 ftruncate extend but ext2 can. */
1942 result = ftruncate(fsp->fh->fd, len);
1944 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1945 extend a file with ftruncate. Provide alternate implementation
1946 for this */
1948 /* Do an fstat to see if the file is longer than the requested
1949 size in which case the ftruncate above should have
1950 succeeded or shorter, in which case seek to len - 1 and
1951 write 1 byte of zero */
1952 status = vfs_stat_fsp(fsp);
1953 if (!NT_STATUS_IS_OK(status)) {
1954 goto done;
1957 /* We need to update the files_struct after successful ftruncate */
1958 if (result == 0) {
1959 goto done;
1962 pst = &fsp->fsp_name->st;
1964 #ifdef S_ISFIFO
1965 if (S_ISFIFO(pst->st_ex_mode)) {
1966 result = 0;
1967 goto done;
1969 #endif
1971 if (pst->st_ex_size == len) {
1972 result = 0;
1973 goto done;
1976 if (pst->st_ex_size > len) {
1977 /* the ftruncate should have worked */
1978 goto done;
1981 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1982 goto done;
1985 result = 0;
1987 done:
1989 END_PROFILE(syscall_ftruncate);
1990 return result;
1993 static int vfswrap_fallocate(vfs_handle_struct *handle,
1994 files_struct *fsp,
1995 uint32_t mode,
1996 off_t offset,
1997 off_t len)
1999 int result;
2001 START_PROFILE(syscall_fallocate);
2002 if (mode == 0) {
2003 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2005 * posix_fallocate returns 0 on success, errno on error
2006 * and doesn't set errno. Make it behave like fallocate()
2007 * which returns -1, and sets errno on failure.
2009 if (result != 0) {
2010 errno = result;
2011 result = -1;
2013 } else {
2014 /* sys_fallocate handles filtering of unsupported mode flags */
2015 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2017 END_PROFILE(syscall_fallocate);
2018 return result;
2021 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2023 bool result;
2025 START_PROFILE(syscall_fcntl_lock);
2026 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2027 END_PROFILE(syscall_fcntl_lock);
2028 return result;
2031 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2032 uint32_t share_mode, uint32_t access_mask)
2034 START_PROFILE(syscall_kernel_flock);
2035 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2036 END_PROFILE(syscall_kernel_flock);
2037 return 0;
2040 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2042 bool result;
2044 START_PROFILE(syscall_fcntl_getlock);
2045 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2046 END_PROFILE(syscall_fcntl_getlock);
2047 return result;
2050 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2051 int leasetype)
2053 int result = -1;
2055 START_PROFILE(syscall_linux_setlease);
2057 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2058 result = linux_setlease(fsp->fh->fd, leasetype);
2059 #else
2060 errno = ENOSYS;
2061 #endif
2062 END_PROFILE(syscall_linux_setlease);
2063 return result;
2066 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2068 int result;
2070 START_PROFILE(syscall_symlink);
2071 result = symlink(oldpath, newpath);
2072 END_PROFILE(syscall_symlink);
2073 return result;
2076 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2078 int result;
2080 START_PROFILE(syscall_readlink);
2081 result = readlink(path, buf, bufsiz);
2082 END_PROFILE(syscall_readlink);
2083 return result;
2086 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2088 int result;
2090 START_PROFILE(syscall_link);
2091 result = link(oldpath, newpath);
2092 END_PROFILE(syscall_link);
2093 return result;
2096 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2098 int result;
2100 START_PROFILE(syscall_mknod);
2101 result = sys_mknod(pathname, mode, dev);
2102 END_PROFILE(syscall_mknod);
2103 return result;
2106 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2108 char *result;
2110 START_PROFILE(syscall_realpath);
2111 #ifdef REALPATH_TAKES_NULL
2112 result = realpath(path, NULL);
2113 #else
2114 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2115 if (result) {
2116 char *resolved_path = realpath(path, result);
2117 if (!resolved_path) {
2118 SAFE_FREE(result);
2119 } else {
2120 /* SMB_ASSERT(result == resolved_path) ? */
2121 result = resolved_path;
2124 #endif
2125 END_PROFILE(syscall_realpath);
2126 return result;
2129 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2130 struct sys_notify_context *ctx,
2131 const char *path,
2132 uint32_t *filter,
2133 uint32_t *subdir_filter,
2134 void (*callback)(struct sys_notify_context *ctx,
2135 void *private_data,
2136 struct notify_event *ev),
2137 void *private_data, void *handle)
2140 * So far inotify is the only supported default notify mechanism. If
2141 * another platform like the the BSD's or a proprietary Unix comes
2142 * along and wants another default, we can play the same trick we
2143 * played with Posix ACLs.
2145 * Until that is the case, hard-code inotify here.
2147 #ifdef HAVE_INOTIFY
2148 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2149 int ret;
2150 if (!lp_parm_bool(-1, "notify", "inotify", True)) {
2151 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2154 * "ctx->private_data" is not obvious as a talloc context
2155 * here. Without modifying the VFS we don't have a mem_ctx
2156 * available here, and ctx->private_data was used by
2157 * inotify_watch before it got a real talloc parent.
2159 ret = inotify_watch(ctx->private_data, ctx,
2160 path, filter, subdir_filter,
2161 callback, private_data, handle);
2162 if (ret != 0) {
2163 return map_nt_error_from_unix(ret);
2165 return NT_STATUS_OK;
2167 #endif
2169 * Do nothing, leave everything to notify_internal.c
2171 return NT_STATUS_OK;
2174 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2175 unsigned int flags)
2177 #ifdef HAVE_CHFLAGS
2178 return chflags(path, flags);
2179 #else
2180 errno = ENOSYS;
2181 return -1;
2182 #endif
2185 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2186 const SMB_STRUCT_STAT *sbuf)
2188 struct file_id key;
2190 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2191 * blob */
2192 ZERO_STRUCT(key);
2194 key.devid = sbuf->st_ex_dev;
2195 key.inode = sbuf->st_ex_ino;
2196 /* key.extid is unused by default. */
2198 return key;
2201 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2202 struct files_struct *fsp,
2203 const char *fname,
2204 TALLOC_CTX *mem_ctx,
2205 unsigned int *pnum_streams,
2206 struct stream_struct **pstreams)
2208 SMB_STRUCT_STAT sbuf;
2209 struct stream_struct *tmp_streams = NULL;
2210 int ret;
2212 if ((fsp != NULL) && (fsp->is_directory)) {
2214 * No default streams on directories
2216 goto done;
2219 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2220 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2222 else {
2223 struct smb_filename smb_fname;
2225 ZERO_STRUCT(smb_fname);
2226 smb_fname.base_name = discard_const_p(char, fname);
2228 if (lp_posix_pathnames()) {
2229 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2230 } else {
2231 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2233 sbuf = smb_fname.st;
2236 if (ret == -1) {
2237 return map_nt_error_from_unix(errno);
2240 if (S_ISDIR(sbuf.st_ex_mode)) {
2241 goto done;
2244 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2245 (*pnum_streams) + 1);
2246 if (tmp_streams == NULL) {
2247 return NT_STATUS_NO_MEMORY;
2249 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2250 if (tmp_streams[*pnum_streams].name == NULL) {
2251 return NT_STATUS_NO_MEMORY;
2253 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2254 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2256 *pnum_streams += 1;
2257 *pstreams = tmp_streams;
2258 done:
2259 return NT_STATUS_OK;
2262 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2263 const char *path,
2264 const char *name,
2265 TALLOC_CTX *mem_ctx,
2266 char **found_name)
2269 * Don't fall back to get_real_filename so callers can differentiate
2270 * between a full directory scan and an actual case-insensitive stat.
2272 errno = EOPNOTSUPP;
2273 return -1;
2276 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2277 const char *fname)
2279 return handle->conn->connectpath;
2282 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2283 struct byte_range_lock *br_lck,
2284 struct lock_struct *plock,
2285 bool blocking_lock)
2287 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2289 /* Note: blr is not used in the default implementation. */
2290 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2293 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2294 struct messaging_context *msg_ctx,
2295 struct byte_range_lock *br_lck,
2296 const struct lock_struct *plock)
2298 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2300 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2303 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2304 struct byte_range_lock *br_lck,
2305 struct lock_struct *plock)
2307 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2309 /* Note: blr is not used in the default implementation. */
2310 return brl_lock_cancel_default(br_lck, plock);
2313 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2314 files_struct *fsp,
2315 struct lock_struct *plock)
2317 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2318 plock->lock_type == WRITE_LOCK);
2320 return strict_lock_default(fsp, plock);
2323 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2324 files_struct *fsp,
2325 struct lock_struct *plock)
2327 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2328 plock->lock_type == WRITE_LOCK);
2330 strict_unlock_default(fsp, plock);
2333 /* NT ACL operations. */
2335 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2336 files_struct *fsp,
2337 uint32_t security_info,
2338 TALLOC_CTX *mem_ctx,
2339 struct security_descriptor **ppdesc)
2341 NTSTATUS result;
2343 START_PROFILE(fget_nt_acl);
2344 result = posix_fget_nt_acl(fsp, security_info,
2345 mem_ctx, ppdesc);
2346 END_PROFILE(fget_nt_acl);
2347 return result;
2350 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2351 const char *name,
2352 uint32_t security_info,
2353 TALLOC_CTX *mem_ctx,
2354 struct security_descriptor **ppdesc)
2356 NTSTATUS result;
2358 START_PROFILE(get_nt_acl);
2359 result = posix_get_nt_acl(handle->conn, name, security_info,
2360 mem_ctx, ppdesc);
2361 END_PROFILE(get_nt_acl);
2362 return result;
2365 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2367 NTSTATUS result;
2369 START_PROFILE(fset_nt_acl);
2370 result = set_nt_acl(fsp, security_info_sent, psd);
2371 END_PROFILE(fset_nt_acl);
2372 return result;
2375 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2376 struct smb_filename *file,
2377 struct security_acl *sacl,
2378 uint32_t access_requested,
2379 uint32_t access_denied)
2381 return NT_STATUS_OK; /* Nothing to do here ... */
2384 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2386 #ifdef HAVE_NO_ACL
2387 errno = ENOSYS;
2388 return -1;
2389 #else
2390 int result;
2392 START_PROFILE(chmod_acl);
2393 result = chmod_acl(handle->conn, name, mode);
2394 END_PROFILE(chmod_acl);
2395 return result;
2396 #endif
2399 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2401 #ifdef HAVE_NO_ACL
2402 errno = ENOSYS;
2403 return -1;
2404 #else
2405 int result;
2407 START_PROFILE(fchmod_acl);
2408 result = fchmod_acl(fsp, mode);
2409 END_PROFILE(fchmod_acl);
2410 return result;
2411 #endif
2414 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2415 const char *path_p,
2416 SMB_ACL_TYPE_T type,
2417 TALLOC_CTX *mem_ctx)
2419 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2422 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2423 files_struct *fsp,
2424 TALLOC_CTX *mem_ctx)
2426 return sys_acl_get_fd(handle, fsp, mem_ctx);
2429 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2431 return sys_acl_set_file(handle, name, acltype, theacl);
2434 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2436 return sys_acl_set_fd(handle, fsp, theacl);
2439 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2441 return sys_acl_delete_def_file(handle, path);
2444 /****************************************************************
2445 Extended attribute operations.
2446 *****************************************************************/
2448 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2450 return getxattr(path, name, value, size);
2453 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2455 return fgetxattr(fsp->fh->fd, name, value, size);
2458 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2460 return listxattr(path, list, size);
2463 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2465 return flistxattr(fsp->fh->fd, list, size);
2468 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2470 return removexattr(path, name);
2473 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2475 return fremovexattr(fsp->fh->fd, name);
2478 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2480 return setxattr(path, name, value, size, flags);
2483 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2485 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2488 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2490 return false;
2493 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2494 const struct smb_filename *fname,
2495 SMB_STRUCT_STAT *sbuf)
2497 NTSTATUS status;
2498 char *path;
2499 bool offline = false;
2501 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2502 return false;
2505 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2506 #if defined(ENOTSUP)
2507 errno = ENOTSUP;
2508 #endif
2509 return false;
2512 status = get_full_smb_filename(talloc_tos(), fname, &path);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 errno = map_errno_from_nt_status(status);
2515 return false;
2518 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2520 TALLOC_FREE(path);
2522 return offline;
2525 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2526 const struct smb_filename *fname)
2528 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2529 #if defined(ENOTSUP)
2530 errno = ENOTSUP;
2531 #endif
2532 return -1;
2535 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2536 struct files_struct *fsp,
2537 TALLOC_CTX *mem_ctx,
2538 DATA_BLOB *cookie)
2540 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2543 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2544 struct files_struct *fsp,
2545 const DATA_BLOB old_cookie,
2546 TALLOC_CTX *mem_ctx,
2547 DATA_BLOB *new_cookie)
2549 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2550 new_cookie);
2553 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2554 struct smb_request *smb1req,
2555 struct smbXsrv_open *op,
2556 const DATA_BLOB old_cookie,
2557 TALLOC_CTX *mem_ctx,
2558 struct files_struct **fsp,
2559 DATA_BLOB *new_cookie)
2561 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2562 old_cookie, mem_ctx,
2563 fsp, new_cookie);
2566 static struct vfs_fn_pointers vfs_default_fns = {
2567 /* Disk operations */
2569 .connect_fn = vfswrap_connect,
2570 .disconnect_fn = vfswrap_disconnect,
2571 .disk_free_fn = vfswrap_disk_free,
2572 .get_quota_fn = vfswrap_get_quota,
2573 .set_quota_fn = vfswrap_set_quota,
2574 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2575 .statvfs_fn = vfswrap_statvfs,
2576 .fs_capabilities_fn = vfswrap_fs_capabilities,
2577 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2578 .snap_check_path_fn = vfswrap_snap_check_path,
2579 .snap_create_fn = vfswrap_snap_create,
2580 .snap_delete_fn = vfswrap_snap_delete,
2582 /* Directory operations */
2584 .opendir_fn = vfswrap_opendir,
2585 .fdopendir_fn = vfswrap_fdopendir,
2586 .readdir_fn = vfswrap_readdir,
2587 .readdir_attr_fn = vfswrap_readdir_attr,
2588 .seekdir_fn = vfswrap_seekdir,
2589 .telldir_fn = vfswrap_telldir,
2590 .rewind_dir_fn = vfswrap_rewinddir,
2591 .mkdir_fn = vfswrap_mkdir,
2592 .rmdir_fn = vfswrap_rmdir,
2593 .closedir_fn = vfswrap_closedir,
2594 .init_search_op_fn = vfswrap_init_search_op,
2596 /* File operations */
2598 .open_fn = vfswrap_open,
2599 .create_file_fn = vfswrap_create_file,
2600 .close_fn = vfswrap_close,
2601 .read_fn = vfswrap_read,
2602 .pread_fn = vfswrap_pread,
2603 .pread_send_fn = vfswrap_pread_send,
2604 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2605 .write_fn = vfswrap_write,
2606 .pwrite_fn = vfswrap_pwrite,
2607 .pwrite_send_fn = vfswrap_pwrite_send,
2608 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2609 .lseek_fn = vfswrap_lseek,
2610 .sendfile_fn = vfswrap_sendfile,
2611 .recvfile_fn = vfswrap_recvfile,
2612 .rename_fn = vfswrap_rename,
2613 .fsync_fn = vfswrap_fsync,
2614 .fsync_send_fn = vfswrap_fsync_send,
2615 .fsync_recv_fn = vfswrap_asys_int_recv,
2616 .stat_fn = vfswrap_stat,
2617 .fstat_fn = vfswrap_fstat,
2618 .lstat_fn = vfswrap_lstat,
2619 .get_alloc_size_fn = vfswrap_get_alloc_size,
2620 .unlink_fn = vfswrap_unlink,
2621 .chmod_fn = vfswrap_chmod,
2622 .fchmod_fn = vfswrap_fchmod,
2623 .chown_fn = vfswrap_chown,
2624 .fchown_fn = vfswrap_fchown,
2625 .lchown_fn = vfswrap_lchown,
2626 .chdir_fn = vfswrap_chdir,
2627 .getwd_fn = vfswrap_getwd,
2628 .ntimes_fn = vfswrap_ntimes,
2629 .ftruncate_fn = vfswrap_ftruncate,
2630 .fallocate_fn = vfswrap_fallocate,
2631 .lock_fn = vfswrap_lock,
2632 .kernel_flock_fn = vfswrap_kernel_flock,
2633 .linux_setlease_fn = vfswrap_linux_setlease,
2634 .getlock_fn = vfswrap_getlock,
2635 .symlink_fn = vfswrap_symlink,
2636 .readlink_fn = vfswrap_readlink,
2637 .link_fn = vfswrap_link,
2638 .mknod_fn = vfswrap_mknod,
2639 .realpath_fn = vfswrap_realpath,
2640 .notify_watch_fn = vfswrap_notify_watch,
2641 .chflags_fn = vfswrap_chflags,
2642 .file_id_create_fn = vfswrap_file_id_create,
2643 .streaminfo_fn = vfswrap_streaminfo,
2644 .get_real_filename_fn = vfswrap_get_real_filename,
2645 .connectpath_fn = vfswrap_connectpath,
2646 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2647 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2648 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2649 .strict_lock_fn = vfswrap_strict_lock,
2650 .strict_unlock_fn = vfswrap_strict_unlock,
2651 .translate_name_fn = vfswrap_translate_name,
2652 .fsctl_fn = vfswrap_fsctl,
2653 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2654 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2655 .get_compression_fn = vfswrap_get_compression,
2656 .set_compression_fn = vfswrap_set_compression,
2658 /* NT ACL operations. */
2660 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2661 .get_nt_acl_fn = vfswrap_get_nt_acl,
2662 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2663 .audit_file_fn = vfswrap_audit_file,
2665 /* POSIX ACL operations. */
2667 .chmod_acl_fn = vfswrap_chmod_acl,
2668 .fchmod_acl_fn = vfswrap_fchmod_acl,
2670 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2671 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2672 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2673 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2674 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2675 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2676 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2678 /* EA operations. */
2679 .getxattr_fn = vfswrap_getxattr,
2680 .fgetxattr_fn = vfswrap_fgetxattr,
2681 .listxattr_fn = vfswrap_listxattr,
2682 .flistxattr_fn = vfswrap_flistxattr,
2683 .removexattr_fn = vfswrap_removexattr,
2684 .fremovexattr_fn = vfswrap_fremovexattr,
2685 .setxattr_fn = vfswrap_setxattr,
2686 .fsetxattr_fn = vfswrap_fsetxattr,
2688 /* aio operations */
2689 .aio_force_fn = vfswrap_aio_force,
2691 /* offline operations */
2692 .is_offline_fn = vfswrap_is_offline,
2693 .set_offline_fn = vfswrap_set_offline,
2695 /* durable handle operations */
2696 .durable_cookie_fn = vfswrap_durable_cookie,
2697 .durable_disconnect_fn = vfswrap_durable_disconnect,
2698 .durable_reconnect_fn = vfswrap_durable_reconnect,
2701 NTSTATUS vfs_default_init(void);
2702 NTSTATUS vfs_default_init(void)
2704 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2705 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);