s4:dsdb/password_hash: split out a password_hash_needed() function
[Samba.git] / source3 / modules / vfs_default.c
blobde5a4a3dd5571e76d88f064cb639c1a2c31a7d1f
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/util/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 if (sys_fsusage(path, dfree, dsize) != 0) {
62 return (uint64_t)-1;
65 *bsize = 512;
66 return *dfree / 2;
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
71 SMB_DISK_QUOTA *qt)
73 #ifdef HAVE_SYS_QUOTAS
74 int result;
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
79 return result;
80 #else
81 errno = ENOSYS;
82 return -1;
83 #endif
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
89 int result;
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
94 return result;
95 #else
96 errno = ENOSYS;
97 return -1;
98 #endif
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
104 bool labels)
106 errno = ENOSYS;
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
122 int ret;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
126 if (ret == 0) {
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
136 NULL, NULL, 0);
137 if (smb_fname_cpath == NULL) {
138 return caps;
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
142 if (ret == -1) {
143 TALLOC_FREE(smb_fname_cpath);
144 return caps;
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
163 #endif
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
166 "resolution of %s "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
173 return caps;
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
180 int consumedcnt = 0;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
184 NTSTATUS status;
185 int i;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
188 if (DEBUGLVL(10)) {
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
209 pathnamep++;
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 return status;
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
230 if (DEBUGLVL(3)) {
231 dbgtext("Path %s to alternate path(s):",
232 pathnamep);
233 for (i=0; i < junction->referral_count; i++) {
234 dbgtext(" %s",
235 junction->referral_list[i].alternate_path);
237 dbgtext(".\n");
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
257 if (self_referral) {
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
269 case 2:
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
277 t->version = 2;
278 v2->size = VERSION2_REFERRAL_SIZE;
279 if (self_referral) {
280 v2->server_type = DFS_SERVER_ROOT;
281 } else {
282 v2->server_type = DFS_SERVER_NON_ROOT;
284 v2->entry_flags = 0;
285 v2->proximity = ref->proximity;
286 v2->ttl = ref->ttl;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
302 break;
303 case 3:
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
312 t->version = 3;
313 v3->size = VERSION3_REFERRAL_SIZE;
314 if (self_referral) {
315 v3->server_type = DFS_SERVER_ROOT;
316 } else {
317 v3->server_type = DFS_SERVER_NON_ROOT;
319 v3->entry_flags = 0;
320 v3->ttl = ref->ttl;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
335 break;
336 default:
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
342 if (DEBUGLVL(10)) {
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
346 return NT_STATUS_OK;
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
350 TALLOC_CTX *mem_ctx,
351 const char *service_path,
352 char **base_volume)
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
358 TALLOC_CTX *mem_ctx,
359 const char *base_volume,
360 time_t *tstamp,
361 bool rw,
362 char **base_path,
363 char **snap_path)
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
369 TALLOC_CTX *mem_ctx,
370 char *base_path,
371 char *snap_path)
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
379 const struct smb_filename *smb_fname,
380 const char *mask,
381 uint32_t attr)
383 DIR *result;
385 START_PROFILE(syscall_opendir);
386 result = opendir(smb_fname->base_name);
387 END_PROFILE(syscall_opendir);
388 return result;
391 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
392 files_struct *fsp,
393 const char *mask,
394 uint32_t attr)
396 DIR *result;
398 START_PROFILE(syscall_fdopendir);
399 result = sys_fdopendir(fsp->fh->fd);
400 END_PROFILE(syscall_fdopendir);
401 return result;
405 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
406 DIR *dirp,
407 SMB_STRUCT_STAT *sbuf)
409 struct dirent *result;
411 START_PROFILE(syscall_readdir);
412 result = readdir(dirp);
413 END_PROFILE(syscall_readdir);
414 if (sbuf) {
415 /* Default Posix readdir() does not give us stat info.
416 * Set to invalid to indicate we didn't return this info. */
417 SET_STAT_INVALID(*sbuf);
418 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
419 if (result != NULL) {
420 /* See if we can efficiently return this. */
421 struct stat st;
422 int flags = AT_SYMLINK_NOFOLLOW;
423 int ret = fstatat(dirfd(dirp),
424 result->d_name,
425 &st,
426 flags);
428 * As this is an optimization,
429 * ignore it if we stat'ed a
430 * symlink. Make the caller
431 * do it again as we don't
432 * know if they wanted the link
433 * info, or its target info.
435 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
436 init_stat_ex_from_stat(sbuf,
437 &st,
438 lp_fake_directory_create_times(
439 SNUM(handle->conn)));
442 #endif
444 return result;
447 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
448 const struct smb_filename *fname,
449 TALLOC_CTX *mem_ctx,
450 struct readdir_attr_data **attr_data)
452 return NT_STATUS_NOT_SUPPORTED;
455 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
457 START_PROFILE(syscall_seekdir);
458 seekdir(dirp, offset);
459 END_PROFILE(syscall_seekdir);
462 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
464 long result;
465 START_PROFILE(syscall_telldir);
466 result = telldir(dirp);
467 END_PROFILE(syscall_telldir);
468 return result;
471 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
473 START_PROFILE(syscall_rewinddir);
474 rewinddir(dirp);
475 END_PROFILE(syscall_rewinddir);
478 static int vfswrap_mkdir(vfs_handle_struct *handle,
479 const struct smb_filename *smb_fname,
480 mode_t mode)
482 int result;
483 bool has_dacl = False;
484 const char *path = smb_fname->base_name;
485 char *parent = NULL;
487 START_PROFILE(syscall_mkdir);
489 if (lp_inherit_acls(SNUM(handle->conn))
490 && parent_dirname(talloc_tos(), path, &parent, NULL)
491 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
492 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
495 TALLOC_FREE(parent);
497 result = mkdir(path, mode);
499 if (result == 0 && !has_dacl) {
501 * We need to do this as the default behavior of POSIX ACLs
502 * is to set the mask to be the requested group permission
503 * bits, not the group permission bits to be the requested
504 * group permission bits. This is not what we want, as it will
505 * mess up any inherited ACL bits that were set. JRA.
507 int saved_errno = errno; /* We may get ENOSYS */
508 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
509 (errno == ENOSYS)) {
510 errno = saved_errno;
514 END_PROFILE(syscall_mkdir);
515 return result;
518 static int vfswrap_rmdir(vfs_handle_struct *handle,
519 const struct smb_filename *smb_fname)
521 int result;
523 START_PROFILE(syscall_rmdir);
524 result = rmdir(smb_fname->base_name);
525 END_PROFILE(syscall_rmdir);
526 return result;
529 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
531 int result;
533 START_PROFILE(syscall_closedir);
534 result = closedir(dirp);
535 END_PROFILE(syscall_closedir);
536 return result;
539 static void vfswrap_init_search_op(vfs_handle_struct *handle,
540 DIR *dirp)
542 /* Default behavior is a NOOP */
545 /* File operations */
547 static int vfswrap_open(vfs_handle_struct *handle,
548 struct smb_filename *smb_fname,
549 files_struct *fsp, int flags, mode_t mode)
551 int result = -1;
553 START_PROFILE(syscall_open);
555 if (smb_fname->stream_name) {
556 errno = ENOENT;
557 goto out;
560 result = open(smb_fname->base_name, flags, mode);
561 out:
562 END_PROFILE(syscall_open);
563 return result;
566 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
567 struct smb_request *req,
568 uint16_t root_dir_fid,
569 struct smb_filename *smb_fname,
570 uint32_t access_mask,
571 uint32_t share_access,
572 uint32_t create_disposition,
573 uint32_t create_options,
574 uint32_t file_attributes,
575 uint32_t oplock_request,
576 struct smb2_lease *lease,
577 uint64_t allocation_size,
578 uint32_t private_flags,
579 struct security_descriptor *sd,
580 struct ea_list *ea_list,
581 files_struct **result,
582 int *pinfo,
583 const struct smb2_create_blobs *in_context_blobs,
584 struct smb2_create_blobs *out_context_blobs)
586 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
587 access_mask, share_access,
588 create_disposition, create_options,
589 file_attributes, oplock_request, lease,
590 allocation_size, private_flags,
591 sd, ea_list, result,
592 pinfo, in_context_blobs, out_context_blobs);
595 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
597 int result;
599 START_PROFILE(syscall_close);
600 result = fd_close_posix(fsp);
601 END_PROFILE(syscall_close);
602 return result;
605 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
607 ssize_t result;
609 START_PROFILE_BYTES(syscall_read, n);
610 result = sys_read(fsp->fh->fd, data, n);
611 END_PROFILE_BYTES(syscall_read);
612 return result;
615 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
616 size_t n, off_t offset)
618 ssize_t result;
620 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
621 START_PROFILE_BYTES(syscall_pread, n);
622 result = sys_pread(fsp->fh->fd, data, n, offset);
623 END_PROFILE_BYTES(syscall_pread);
625 if (result == -1 && errno == ESPIPE) {
626 /* Maintain the fiction that pipes can be seeked (sought?) on. */
627 result = SMB_VFS_READ(fsp, data, n);
628 fsp->fh->pos = 0;
631 #else /* HAVE_PREAD */
632 off_t curr;
633 int lerrno;
635 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
636 if (curr == -1 && errno == ESPIPE) {
637 /* Maintain the fiction that pipes can be seeked (sought?) on. */
638 result = SMB_VFS_READ(fsp, data, n);
639 fsp->fh->pos = 0;
640 return result;
643 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
644 return -1;
647 errno = 0;
648 result = SMB_VFS_READ(fsp, data, n);
649 lerrno = errno;
651 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
652 errno = lerrno;
654 #endif /* HAVE_PREAD */
656 return result;
659 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
661 ssize_t result;
663 START_PROFILE_BYTES(syscall_write, n);
664 result = sys_write(fsp->fh->fd, data, n);
665 END_PROFILE_BYTES(syscall_write);
666 return result;
669 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
670 size_t n, off_t offset)
672 ssize_t result;
674 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
675 START_PROFILE_BYTES(syscall_pwrite, n);
676 result = sys_pwrite(fsp->fh->fd, data, n, offset);
677 END_PROFILE_BYTES(syscall_pwrite);
679 if (result == -1 && errno == ESPIPE) {
680 /* Maintain the fiction that pipes can be sought on. */
681 result = SMB_VFS_WRITE(fsp, data, n);
684 #else /* HAVE_PWRITE */
685 off_t curr;
686 int lerrno;
688 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
689 if (curr == -1) {
690 return -1;
693 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
694 return -1;
697 result = SMB_VFS_WRITE(fsp, data, n);
698 lerrno = errno;
700 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
701 errno = lerrno;
703 #endif /* HAVE_PWRITE */
705 return result;
708 static void vfswrap_asys_finished(struct tevent_context *ev,
709 struct tevent_fd *fde,
710 uint16_t flags, void *p);
712 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
714 struct asys_context *ctx;
715 struct tevent_fd *fde;
716 int ret;
717 int fd;
719 if (conn->asys_ctx != NULL) {
720 return true;
723 ret = asys_context_init(&ctx, lp_aio_max_threads());
724 if (ret != 0) {
725 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
726 return false;
729 fd = asys_signalfd(ctx);
731 ret = set_blocking(fd, false);
732 if (ret != 0) {
733 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
734 goto fail;
737 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
738 vfswrap_asys_finished, ctx);
739 if (fde == NULL) {
740 DEBUG(1, ("tevent_add_fd failed\n"));
741 goto fail;
744 conn->asys_ctx = ctx;
745 conn->asys_fde = fde;
746 return true;
748 fail:
749 asys_context_destroy(ctx);
750 return false;
753 struct vfswrap_asys_state {
754 struct asys_context *asys_ctx;
755 struct tevent_req *req;
756 ssize_t ret;
757 struct vfs_aio_state vfs_aio_state;
758 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
759 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
762 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
764 asys_cancel(s->asys_ctx, s->req);
765 return 0;
768 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
769 TALLOC_CTX *mem_ctx,
770 struct tevent_context *ev,
771 struct files_struct *fsp,
772 void *data,
773 size_t n, off_t offset)
775 struct tevent_req *req;
776 struct vfswrap_asys_state *state;
777 int ret;
779 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
780 if (req == NULL) {
781 return NULL;
783 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
784 tevent_req_oom(req);
785 return tevent_req_post(req, ev);
787 state->asys_ctx = handle->conn->sconn->asys_ctx;
788 state->req = req;
790 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
791 state->profile_bytes, n);
792 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
793 if (ret != 0) {
794 tevent_req_error(req, ret);
795 return tevent_req_post(req, ev);
797 talloc_set_destructor(state, vfswrap_asys_state_destructor);
799 return req;
802 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
803 TALLOC_CTX *mem_ctx,
804 struct tevent_context *ev,
805 struct files_struct *fsp,
806 const void *data,
807 size_t n, off_t offset)
809 struct tevent_req *req;
810 struct vfswrap_asys_state *state;
811 int ret;
813 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
814 if (req == NULL) {
815 return NULL;
817 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
818 tevent_req_oom(req);
819 return tevent_req_post(req, ev);
821 state->asys_ctx = handle->conn->sconn->asys_ctx;
822 state->req = req;
824 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
825 state->profile_bytes, n);
826 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
827 if (ret != 0) {
828 tevent_req_error(req, ret);
829 return tevent_req_post(req, ev);
831 talloc_set_destructor(state, vfswrap_asys_state_destructor);
833 return req;
836 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
837 TALLOC_CTX *mem_ctx,
838 struct tevent_context *ev,
839 struct files_struct *fsp)
841 struct tevent_req *req;
842 struct vfswrap_asys_state *state;
843 int ret;
845 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
846 if (req == NULL) {
847 return NULL;
849 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
850 tevent_req_oom(req);
851 return tevent_req_post(req, ev);
853 state->asys_ctx = handle->conn->sconn->asys_ctx;
854 state->req = req;
856 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
857 state->profile_basic);
858 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
859 if (ret != 0) {
860 tevent_req_error(req, ret);
861 return tevent_req_post(req, ev);
863 talloc_set_destructor(state, vfswrap_asys_state_destructor);
865 return req;
868 static void vfswrap_asys_finished(struct tevent_context *ev,
869 struct tevent_fd *fde,
870 uint16_t flags, void *p)
872 struct asys_context *asys_ctx = (struct asys_context *)p;
873 struct asys_result results[get_outstanding_aio_calls()];
874 int i, ret;
876 if ((flags & TEVENT_FD_READ) == 0) {
877 return;
880 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
881 if (ret < 0) {
882 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
883 return;
886 for (i=0; i<ret; i++) {
887 struct asys_result *result = &results[i];
888 struct tevent_req *req;
889 struct vfswrap_asys_state *state;
891 if ((result->ret == -1) && (result->err == ECANCELED)) {
892 continue;
895 req = talloc_get_type_abort(result->private_data,
896 struct tevent_req);
897 state = tevent_req_data(req, struct vfswrap_asys_state);
899 talloc_set_destructor(state, NULL);
901 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
902 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
903 state->ret = result->ret;
904 state->vfs_aio_state.error = result->err;
905 state->vfs_aio_state.duration = result->duration;
906 tevent_req_defer_callback(req, ev);
907 tevent_req_done(req);
911 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
912 struct vfs_aio_state *vfs_aio_state)
914 struct vfswrap_asys_state *state = tevent_req_data(
915 req, struct vfswrap_asys_state);
917 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
918 return -1;
920 *vfs_aio_state = state->vfs_aio_state;
921 return state->ret;
924 static int vfswrap_asys_int_recv(struct tevent_req *req,
925 struct vfs_aio_state *vfs_aio_state)
927 struct vfswrap_asys_state *state = tevent_req_data(
928 req, struct vfswrap_asys_state);
930 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
931 return -1;
933 *vfs_aio_state = state->vfs_aio_state;
934 return state->ret;
937 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
939 off_t result = 0;
941 START_PROFILE(syscall_lseek);
943 /* Cope with 'stat' file opens. */
944 if (fsp->fh->fd != -1)
945 result = lseek(fsp->fh->fd, offset, whence);
948 * We want to maintain the fiction that we can seek
949 * on a fifo for file system purposes. This allows
950 * people to set up UNIX fifo's that feed data to Windows
951 * applications. JRA.
954 if((result == -1) && (errno == ESPIPE)) {
955 result = 0;
956 errno = 0;
959 END_PROFILE(syscall_lseek);
960 return result;
963 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
964 off_t offset, size_t n)
966 ssize_t result;
968 START_PROFILE_BYTES(syscall_sendfile, n);
969 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
970 END_PROFILE_BYTES(syscall_sendfile);
971 return result;
974 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
975 int fromfd,
976 files_struct *tofsp,
977 off_t offset,
978 size_t n)
980 ssize_t result;
982 START_PROFILE_BYTES(syscall_recvfile, n);
983 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
984 END_PROFILE_BYTES(syscall_recvfile);
985 return result;
988 static int vfswrap_rename(vfs_handle_struct *handle,
989 const struct smb_filename *smb_fname_src,
990 const struct smb_filename *smb_fname_dst)
992 int result = -1;
994 START_PROFILE(syscall_rename);
996 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
997 errno = ENOENT;
998 goto out;
1001 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1003 out:
1004 END_PROFILE(syscall_rename);
1005 return result;
1008 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1010 #ifdef HAVE_FSYNC
1011 int result;
1013 START_PROFILE(syscall_fsync);
1014 result = fsync(fsp->fh->fd);
1015 END_PROFILE(syscall_fsync);
1016 return result;
1017 #else
1018 return 0;
1019 #endif
1022 static int vfswrap_stat(vfs_handle_struct *handle,
1023 struct smb_filename *smb_fname)
1025 int result = -1;
1027 START_PROFILE(syscall_stat);
1029 if (smb_fname->stream_name) {
1030 errno = ENOENT;
1031 goto out;
1034 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1035 lp_fake_directory_create_times(SNUM(handle->conn)));
1036 out:
1037 END_PROFILE(syscall_stat);
1038 return result;
1041 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1043 int result;
1045 START_PROFILE(syscall_fstat);
1046 result = sys_fstat(fsp->fh->fd,
1047 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1048 END_PROFILE(syscall_fstat);
1049 return result;
1052 static int vfswrap_lstat(vfs_handle_struct *handle,
1053 struct smb_filename *smb_fname)
1055 int result = -1;
1057 START_PROFILE(syscall_lstat);
1059 if (smb_fname->stream_name) {
1060 errno = ENOENT;
1061 goto out;
1064 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1065 lp_fake_directory_create_times(SNUM(handle->conn)));
1066 out:
1067 END_PROFILE(syscall_lstat);
1068 return result;
1071 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1072 const char *name,
1073 enum vfs_translate_direction direction,
1074 TALLOC_CTX *mem_ctx,
1075 char **mapped_name)
1077 return NT_STATUS_NONE_MAPPED;
1081 * Implement the default fsctl operation.
1083 static bool vfswrap_logged_ioctl_message = false;
1085 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1086 struct files_struct *fsp,
1087 TALLOC_CTX *ctx,
1088 uint32_t function,
1089 uint16_t req_flags, /* Needed for UNICODE ... */
1090 const uint8_t *_in_data,
1091 uint32_t in_len,
1092 uint8_t **_out_data,
1093 uint32_t max_out_len,
1094 uint32_t *out_len)
1096 const char *in_data = (const char *)_in_data;
1097 char **out_data = (char **)_out_data;
1098 NTSTATUS status;
1100 switch (function) {
1101 case FSCTL_SET_SPARSE:
1103 bool set_sparse = true;
1105 if (in_len >= 1 && in_data[0] == 0) {
1106 set_sparse = false;
1109 status = file_set_sparse(handle->conn, fsp, set_sparse);
1111 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1112 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1113 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1114 nt_errstr(status)));
1116 return status;
1119 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1121 unsigned char objid[16];
1122 char *return_data = NULL;
1124 /* This should return the object-id on this file.
1125 * I think I'll make this be the inode+dev. JRA.
1128 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1129 fsp_fnum_dbg(fsp)));
1131 *out_len = MIN(max_out_len, 64);
1133 /* Hmmm, will this cause problems if less data asked for? */
1134 return_data = talloc_array(ctx, char, 64);
1135 if (return_data == NULL) {
1136 return NT_STATUS_NO_MEMORY;
1139 /* For backwards compatibility only store the dev/inode. */
1140 push_file_id_16(return_data, &fsp->file_id);
1141 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1142 push_file_id_16(return_data+32, &fsp->file_id);
1143 memset(return_data+48, 0, 16);
1144 *out_data = return_data;
1145 return NT_STATUS_OK;
1148 case FSCTL_GET_REPARSE_POINT:
1150 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1151 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1152 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1153 return NT_STATUS_NOT_A_REPARSE_POINT;
1156 case FSCTL_SET_REPARSE_POINT:
1158 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1159 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1160 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1161 return NT_STATUS_NOT_A_REPARSE_POINT;
1164 case FSCTL_GET_SHADOW_COPY_DATA:
1167 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1168 * and return their volume names. If max_data_count is 16, then it is just
1169 * asking for the number of volumes and length of the combined names.
1171 * pdata is the data allocated by our caller, but that uses
1172 * total_data_count (which is 0 in our case) rather than max_data_count.
1173 * Allocate the correct amount and return the pointer to let
1174 * it be deallocated when we return.
1176 struct shadow_copy_data *shadow_data = NULL;
1177 bool labels = False;
1178 uint32_t labels_data_count = 0;
1179 uint32_t i;
1180 char *cur_pdata = NULL;
1182 if (max_out_len < 16) {
1183 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1184 max_out_len));
1185 return NT_STATUS_INVALID_PARAMETER;
1188 if (max_out_len > 16) {
1189 labels = True;
1192 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1193 if (shadow_data == NULL) {
1194 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1195 return NT_STATUS_NO_MEMORY;
1199 * Call the VFS routine to actually do the work.
1201 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1202 int log_lev = 0;
1203 if (errno == 0) {
1204 /* broken module didn't set errno on error */
1205 status = NT_STATUS_UNSUCCESSFUL;
1206 } else {
1207 status = map_nt_error_from_unix(errno);
1208 if (NT_STATUS_EQUAL(status,
1209 NT_STATUS_NOT_SUPPORTED)) {
1210 log_lev = 5;
1213 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1214 "connectpath %s, failed - %s.\n",
1215 fsp->conn->connectpath,
1216 nt_errstr(status)));
1217 TALLOC_FREE(shadow_data);
1218 return status;
1221 labels_data_count = (shadow_data->num_volumes * 2 *
1222 sizeof(SHADOW_COPY_LABEL)) + 2;
1224 if (!labels) {
1225 *out_len = 16;
1226 } else {
1227 *out_len = 12 + labels_data_count;
1230 if (max_out_len < *out_len) {
1231 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1232 max_out_len, *out_len));
1233 TALLOC_FREE(shadow_data);
1234 return NT_STATUS_BUFFER_TOO_SMALL;
1237 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1238 if (cur_pdata == NULL) {
1239 TALLOC_FREE(shadow_data);
1240 return NT_STATUS_NO_MEMORY;
1243 *out_data = cur_pdata;
1245 /* num_volumes 4 bytes */
1246 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1248 if (labels) {
1249 /* num_labels 4 bytes */
1250 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1253 /* needed_data_count 4 bytes */
1254 SIVAL(cur_pdata, 8, labels_data_count);
1256 cur_pdata += 12;
1258 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1259 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1260 if (labels && shadow_data->labels) {
1261 for (i=0; i<shadow_data->num_volumes; i++) {
1262 size_t len = 0;
1263 status = srvstr_push(cur_pdata, req_flags,
1264 cur_pdata, shadow_data->labels[i],
1265 2 * sizeof(SHADOW_COPY_LABEL),
1266 STR_UNICODE|STR_TERMINATE, &len);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 TALLOC_FREE(*out_data);
1269 TALLOC_FREE(shadow_data);
1270 return status;
1272 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1273 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1277 TALLOC_FREE(shadow_data);
1279 return NT_STATUS_OK;
1282 case FSCTL_FIND_FILES_BY_SID:
1284 /* pretend this succeeded -
1286 * we have to send back a list with all files owned by this SID
1288 * but I have to check that --metze
1290 struct dom_sid sid;
1291 uid_t uid;
1292 size_t sid_len;
1294 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1295 fsp_fnum_dbg(fsp)));
1297 if (in_len < 8) {
1298 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1299 return NT_STATUS_INVALID_PARAMETER;
1302 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1304 /* unknown 4 bytes: this is not the length of the sid :-( */
1305 /*unknown = IVAL(pdata,0);*/
1307 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1308 return NT_STATUS_INVALID_PARAMETER;
1310 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1312 if (!sid_to_uid(&sid, &uid)) {
1313 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1314 sid_string_dbg(&sid),
1315 (unsigned long)sid_len));
1316 uid = (-1);
1319 /* we can take a look at the find source :-)
1321 * find ./ -uid $uid -name '*' is what we need here
1324 * and send 4bytes len and then NULL terminated unicode strings
1325 * for each file
1327 * but I don't know how to deal with the paged results
1328 * (maybe we can hang the result anywhere in the fsp struct)
1330 * but I don't know how to deal with the paged results
1331 * (maybe we can hang the result anywhere in the fsp struct)
1333 * we don't send all files at once
1334 * and at the next we should *not* start from the beginning,
1335 * so we have to cache the result
1337 * --metze
1340 /* this works for now... */
1341 return NT_STATUS_OK;
1344 case FSCTL_QUERY_ALLOCATED_RANGES:
1346 /* FIXME: This is just a dummy reply, telling that all of the
1347 * file is allocated. MKS cp needs that.
1348 * Adding the real allocated ranges via FIEMAP on Linux
1349 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1350 * this FSCTL correct for sparse files.
1352 uint64_t offset, length;
1353 char *out_data_tmp = NULL;
1355 if (in_len != 16) {
1356 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1357 in_len));
1358 return NT_STATUS_INVALID_PARAMETER;
1361 if (max_out_len < 16) {
1362 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1363 max_out_len));
1364 return NT_STATUS_INVALID_PARAMETER;
1367 offset = BVAL(in_data,0);
1368 length = BVAL(in_data,8);
1370 if (offset + length < offset) {
1371 /* No 64-bit integer wrap. */
1372 return NT_STATUS_INVALID_PARAMETER;
1375 /* Shouldn't this be SMB_VFS_STAT ... ? */
1376 status = vfs_stat_fsp(fsp);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 return status;
1381 *out_len = 16;
1382 out_data_tmp = talloc_array(ctx, char, *out_len);
1383 if (out_data_tmp == NULL) {
1384 DEBUG(10, ("unable to allocate memory for response\n"));
1385 return NT_STATUS_NO_MEMORY;
1388 if (offset > fsp->fsp_name->st.st_ex_size ||
1389 fsp->fsp_name->st.st_ex_size == 0 ||
1390 length == 0) {
1391 memset(out_data_tmp, 0, *out_len);
1392 } else {
1393 uint64_t end = offset + length;
1394 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1395 SBVAL(out_data_tmp, 0, 0);
1396 SBVAL(out_data_tmp, 8, end);
1399 *out_data = out_data_tmp;
1401 return NT_STATUS_OK;
1404 case FSCTL_IS_VOLUME_DIRTY:
1406 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1407 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1409 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1410 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1412 return NT_STATUS_INVALID_PARAMETER;
1415 default:
1417 * Only print once ... unfortunately there could be lots of
1418 * different FSCTLs that are called.
1420 if (!vfswrap_logged_ioctl_message) {
1421 vfswrap_logged_ioctl_message = true;
1422 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1423 __func__, function));
1427 return NT_STATUS_NOT_SUPPORTED;
1430 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1431 struct smb_filename *smb_fname,
1432 uint32_t *dosmode)
1434 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1437 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1438 struct files_struct *fsp,
1439 uint32_t *dosmode)
1441 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1444 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1445 const struct smb_filename *smb_fname,
1446 uint32_t dosmode)
1448 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1451 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1452 struct files_struct *fsp,
1453 uint32_t dosmode)
1455 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1458 struct vfs_cc_state {
1459 off_t copied;
1460 uint8_t *buf;
1463 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1464 TALLOC_CTX *mem_ctx,
1465 struct tevent_context *ev,
1466 struct files_struct *src_fsp,
1467 off_t src_off,
1468 struct files_struct *dest_fsp,
1469 off_t dest_off,
1470 off_t num)
1472 struct tevent_req *req;
1473 struct vfs_cc_state *vfs_cc_state;
1474 NTSTATUS status;
1476 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1477 (unsigned long)num));
1479 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1480 if (req == NULL) {
1481 return NULL;
1484 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1485 MIN(num, 8*1024*1024));
1486 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1487 return tevent_req_post(req, ev);
1490 status = vfs_stat_fsp(src_fsp);
1491 if (tevent_req_nterror(req, status)) {
1492 return tevent_req_post(req, ev);
1495 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1497 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1498 * If the SourceOffset or SourceOffset + Length extends beyond
1499 * the end of file, the server SHOULD<240> treat this as a
1500 * STATUS_END_OF_FILE error.
1501 * ...
1502 * <240> Section 3.3.5.15.6: Windows servers will return
1503 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1505 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1506 return tevent_req_post(req, ev);
1509 /* could use 2.6.33+ sendfile here to do this in kernel */
1510 while (vfs_cc_state->copied < num) {
1511 ssize_t ret;
1512 struct lock_struct lck;
1513 int saved_errno;
1515 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1516 num - vfs_cc_state->copied);
1518 if (src_fsp->op == NULL) {
1519 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1520 return tevent_req_post(req, ev);
1522 init_strict_lock_struct(src_fsp,
1523 src_fsp->op->global->open_persistent_id,
1524 src_off,
1525 this_num,
1526 READ_LOCK,
1527 &lck);
1529 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1530 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1531 return tevent_req_post(req, ev);
1534 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1535 this_num, src_off);
1536 if (ret == -1) {
1537 saved_errno = errno;
1540 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1542 if (ret == -1) {
1543 errno = saved_errno;
1544 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1545 return tevent_req_post(req, ev);
1547 if (ret != this_num) {
1548 /* zero tolerance for short reads */
1549 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1550 return tevent_req_post(req, ev);
1553 src_off += ret;
1555 if (dest_fsp->op == NULL) {
1556 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1557 return tevent_req_post(req, ev);
1560 init_strict_lock_struct(dest_fsp,
1561 dest_fsp->op->global->open_persistent_id,
1562 dest_off,
1563 this_num,
1564 WRITE_LOCK,
1565 &lck);
1567 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1568 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1569 return tevent_req_post(req, ev);
1572 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1573 this_num, dest_off);
1574 if (ret == -1) {
1575 saved_errno = errno;
1578 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1580 if (ret == -1) {
1581 errno = saved_errno;
1582 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1583 return tevent_req_post(req, ev);
1585 if (ret != this_num) {
1586 /* zero tolerance for short writes */
1587 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1588 return tevent_req_post(req, ev);
1590 dest_off += ret;
1592 vfs_cc_state->copied += this_num;
1595 tevent_req_done(req);
1596 return tevent_req_post(req, ev);
1599 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1600 struct tevent_req *req,
1601 off_t *copied)
1603 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1604 struct vfs_cc_state);
1605 NTSTATUS status;
1607 if (tevent_req_is_nterror(req, &status)) {
1608 DEBUG(2, ("server side copy chunk failed: %s\n",
1609 nt_errstr(status)));
1610 *copied = 0;
1611 tevent_req_received(req);
1612 return status;
1615 *copied = vfs_cc_state->copied;
1616 DEBUG(10, ("server side copy chunk copied %lu\n",
1617 (unsigned long)*copied));
1618 tevent_req_received(req);
1620 return NT_STATUS_OK;
1623 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1624 TALLOC_CTX *mem_ctx,
1625 struct files_struct *fsp,
1626 struct smb_filename *smb_fname,
1627 uint16_t *_compression_fmt)
1629 return NT_STATUS_INVALID_DEVICE_REQUEST;
1632 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1633 TALLOC_CTX *mem_ctx,
1634 struct files_struct *fsp,
1635 uint16_t compression_fmt)
1637 return NT_STATUS_INVALID_DEVICE_REQUEST;
1640 /********************************************************************
1641 Given a stat buffer return the allocated size on disk, taking into
1642 account sparse files.
1643 ********************************************************************/
1644 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1645 struct files_struct *fsp,
1646 const SMB_STRUCT_STAT *sbuf)
1648 uint64_t result;
1650 START_PROFILE(syscall_get_alloc_size);
1652 if(S_ISDIR(sbuf->st_ex_mode)) {
1653 result = 0;
1654 goto out;
1657 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1658 /* The type of st_blocksize is blkcnt_t which *MUST* be
1659 signed (according to POSIX) and can be less than 64-bits.
1660 Ensure when we're converting to 64 bits wide we don't
1661 sign extend. */
1662 #if defined(SIZEOF_BLKCNT_T_8)
1663 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1664 #elif defined(SIZEOF_BLKCNT_T_4)
1666 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1667 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1669 #else
1670 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1671 #endif
1672 if (result == 0) {
1674 * Some file systems do not allocate a block for very
1675 * small files. But for non-empty file should report a
1676 * positive size.
1679 uint64_t filesize = get_file_size_stat(sbuf);
1680 if (filesize > 0) {
1681 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1684 #else
1685 result = get_file_size_stat(sbuf);
1686 #endif
1688 if (fsp && fsp->initial_allocation_size)
1689 result = MAX(result,fsp->initial_allocation_size);
1691 result = smb_roundup(handle->conn, result);
1693 out:
1694 END_PROFILE(syscall_get_alloc_size);
1695 return result;
1698 static int vfswrap_unlink(vfs_handle_struct *handle,
1699 const struct smb_filename *smb_fname)
1701 int result = -1;
1703 START_PROFILE(syscall_unlink);
1705 if (smb_fname->stream_name) {
1706 errno = ENOENT;
1707 goto out;
1709 result = unlink(smb_fname->base_name);
1711 out:
1712 END_PROFILE(syscall_unlink);
1713 return result;
1716 static int vfswrap_chmod(vfs_handle_struct *handle,
1717 const struct smb_filename *smb_fname,
1718 mode_t mode)
1720 int result;
1722 START_PROFILE(syscall_chmod);
1725 * We need to do this due to the fact that the default POSIX ACL
1726 * chmod modifies the ACL *mask* for the group owner, not the
1727 * group owner bits directly. JRA.
1732 int saved_errno = errno; /* We might get ENOSYS */
1733 result = SMB_VFS_CHMOD_ACL(handle->conn,
1734 smb_fname,
1735 mode);
1736 if (result == 0) {
1737 END_PROFILE(syscall_chmod);
1738 return result;
1740 /* Error - return the old errno. */
1741 errno = saved_errno;
1744 result = chmod(smb_fname->base_name, mode);
1745 END_PROFILE(syscall_chmod);
1746 return result;
1749 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1751 int result;
1753 START_PROFILE(syscall_fchmod);
1756 * We need to do this due to the fact that the default POSIX ACL
1757 * chmod modifies the ACL *mask* for the group owner, not the
1758 * group owner bits directly. JRA.
1762 int saved_errno = errno; /* We might get ENOSYS */
1763 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1764 END_PROFILE(syscall_fchmod);
1765 return result;
1767 /* Error - return the old errno. */
1768 errno = saved_errno;
1771 #if defined(HAVE_FCHMOD)
1772 result = fchmod(fsp->fh->fd, mode);
1773 #else
1774 result = -1;
1775 errno = ENOSYS;
1776 #endif
1778 END_PROFILE(syscall_fchmod);
1779 return result;
1782 static int vfswrap_chown(vfs_handle_struct *handle,
1783 const struct smb_filename *smb_fname,
1784 uid_t uid,
1785 gid_t gid)
1787 int result;
1789 START_PROFILE(syscall_chown);
1790 result = chown(smb_fname->base_name, uid, gid);
1791 END_PROFILE(syscall_chown);
1792 return result;
1795 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1797 #ifdef HAVE_FCHOWN
1798 int result;
1800 START_PROFILE(syscall_fchown);
1801 result = fchown(fsp->fh->fd, uid, gid);
1802 END_PROFILE(syscall_fchown);
1803 return result;
1804 #else
1805 errno = ENOSYS;
1806 return -1;
1807 #endif
1810 static int vfswrap_lchown(vfs_handle_struct *handle,
1811 const struct smb_filename *smb_fname,
1812 uid_t uid,
1813 gid_t gid)
1815 int result;
1817 START_PROFILE(syscall_lchown);
1818 result = lchown(smb_fname->base_name, uid, gid);
1819 END_PROFILE(syscall_lchown);
1820 return result;
1823 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1825 int result;
1827 START_PROFILE(syscall_chdir);
1828 result = chdir(path);
1829 END_PROFILE(syscall_chdir);
1830 return result;
1833 static char *vfswrap_getwd(vfs_handle_struct *handle)
1835 char *result;
1837 START_PROFILE(syscall_getwd);
1838 result = sys_getwd();
1839 END_PROFILE(syscall_getwd);
1840 return result;
1843 /*********************************************************************
1844 nsec timestamp resolution call. Convert down to whatever the underlying
1845 system will support.
1846 **********************************************************************/
1848 static int vfswrap_ntimes(vfs_handle_struct *handle,
1849 const struct smb_filename *smb_fname,
1850 struct smb_file_time *ft)
1852 int result = -1;
1854 START_PROFILE(syscall_ntimes);
1856 if (smb_fname->stream_name) {
1857 errno = ENOENT;
1858 goto out;
1861 if (ft != NULL) {
1862 if (null_timespec(ft->atime)) {
1863 ft->atime= smb_fname->st.st_ex_atime;
1866 if (null_timespec(ft->mtime)) {
1867 ft->mtime = smb_fname->st.st_ex_mtime;
1870 if (!null_timespec(ft->create_time)) {
1871 set_create_timespec_ea(handle->conn,
1872 smb_fname,
1873 ft->create_time);
1876 if ((timespec_compare(&ft->atime,
1877 &smb_fname->st.st_ex_atime) == 0) &&
1878 (timespec_compare(&ft->mtime,
1879 &smb_fname->st.st_ex_mtime) == 0)) {
1880 return 0;
1884 #if defined(HAVE_UTIMENSAT)
1885 if (ft != NULL) {
1886 struct timespec ts[2];
1887 ts[0] = ft->atime;
1888 ts[1] = ft->mtime;
1889 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1890 } else {
1891 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1893 if (!((result == -1) && (errno == ENOSYS))) {
1894 goto out;
1896 #endif
1897 #if defined(HAVE_UTIMES)
1898 if (ft != NULL) {
1899 struct timeval tv[2];
1900 tv[0] = convert_timespec_to_timeval(ft->atime);
1901 tv[1] = convert_timespec_to_timeval(ft->mtime);
1902 result = utimes(smb_fname->base_name, tv);
1903 } else {
1904 result = utimes(smb_fname->base_name, NULL);
1906 if (!((result == -1) && (errno == ENOSYS))) {
1907 goto out;
1909 #endif
1910 #if defined(HAVE_UTIME)
1911 if (ft != NULL) {
1912 struct utimbuf times;
1913 times.actime = convert_timespec_to_time_t(ft->atime);
1914 times.modtime = convert_timespec_to_time_t(ft->mtime);
1915 result = utime(smb_fname->base_name, &times);
1916 } else {
1917 result = utime(smb_fname->base_name, NULL);
1919 if (!((result == -1) && (errno == ENOSYS))) {
1920 goto out;
1922 #endif
1923 errno = ENOSYS;
1924 result = -1;
1926 out:
1927 END_PROFILE(syscall_ntimes);
1928 return result;
1931 /*********************************************************************
1932 A version of ftruncate that will write the space on disk if strict
1933 allocate is set.
1934 **********************************************************************/
1936 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1938 off_t space_to_write;
1939 uint64_t space_avail;
1940 uint64_t bsize,dfree,dsize;
1941 int ret;
1942 NTSTATUS status;
1943 SMB_STRUCT_STAT *pst;
1945 status = vfs_stat_fsp(fsp);
1946 if (!NT_STATUS_IS_OK(status)) {
1947 return -1;
1949 pst = &fsp->fsp_name->st;
1951 #ifdef S_ISFIFO
1952 if (S_ISFIFO(pst->st_ex_mode))
1953 return 0;
1954 #endif
1956 if (pst->st_ex_size == len)
1957 return 0;
1959 /* Shrink - just ftruncate. */
1960 if (pst->st_ex_size > len)
1961 return ftruncate(fsp->fh->fd, len);
1963 space_to_write = len - pst->st_ex_size;
1965 /* for allocation try fallocate first. This can fail on some
1966 platforms e.g. when the filesystem doesn't support it and no
1967 emulation is being done by the libc (like on AIX with JFS1). In that
1968 case we do our own emulation. fallocate implementations can
1969 return ENOTSUP or EINVAL in cases like that. */
1970 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1971 if (ret == -1 && errno == ENOSPC) {
1972 return -1;
1974 if (ret == 0) {
1975 return 0;
1977 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1978 "error %d. Falling back to slow manual allocation\n", errno));
1980 /* available disk space is enough or not? */
1981 space_avail = get_dfree_info(fsp->conn,
1982 fsp->fsp_name->base_name,
1983 &bsize, &dfree, &dsize);
1984 /* space_avail is 1k blocks */
1985 if (space_avail == (uint64_t)-1 ||
1986 ((uint64_t)space_to_write/1024 > space_avail) ) {
1987 errno = ENOSPC;
1988 return -1;
1991 /* Write out the real space on disk. */
1992 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1993 if (ret != 0) {
1994 return -1;
1997 return 0;
2000 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2002 int result = -1;
2003 SMB_STRUCT_STAT *pst;
2004 NTSTATUS status;
2005 char c = 0;
2007 START_PROFILE(syscall_ftruncate);
2009 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2010 result = strict_allocate_ftruncate(handle, fsp, len);
2011 END_PROFILE(syscall_ftruncate);
2012 return result;
2015 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2016 ftruncate if the system supports it. Then I discovered that
2017 you can have some filesystems that support ftruncate
2018 expansion and some that don't! On Linux fat can't do
2019 ftruncate extend but ext2 can. */
2021 result = ftruncate(fsp->fh->fd, len);
2023 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2024 extend a file with ftruncate. Provide alternate implementation
2025 for this */
2027 /* Do an fstat to see if the file is longer than the requested
2028 size in which case the ftruncate above should have
2029 succeeded or shorter, in which case seek to len - 1 and
2030 write 1 byte of zero */
2031 status = vfs_stat_fsp(fsp);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 goto done;
2036 /* We need to update the files_struct after successful ftruncate */
2037 if (result == 0) {
2038 goto done;
2041 pst = &fsp->fsp_name->st;
2043 #ifdef S_ISFIFO
2044 if (S_ISFIFO(pst->st_ex_mode)) {
2045 result = 0;
2046 goto done;
2048 #endif
2050 if (pst->st_ex_size == len) {
2051 result = 0;
2052 goto done;
2055 if (pst->st_ex_size > len) {
2056 /* the ftruncate should have worked */
2057 goto done;
2060 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2061 goto done;
2064 result = 0;
2066 done:
2068 END_PROFILE(syscall_ftruncate);
2069 return result;
2072 static int vfswrap_fallocate(vfs_handle_struct *handle,
2073 files_struct *fsp,
2074 uint32_t mode,
2075 off_t offset,
2076 off_t len)
2078 int result;
2080 START_PROFILE(syscall_fallocate);
2081 if (mode == 0) {
2082 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2084 * posix_fallocate returns 0 on success, errno on error
2085 * and doesn't set errno. Make it behave like fallocate()
2086 * which returns -1, and sets errno on failure.
2088 if (result != 0) {
2089 errno = result;
2090 result = -1;
2092 } else {
2093 /* sys_fallocate handles filtering of unsupported mode flags */
2094 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2096 END_PROFILE(syscall_fallocate);
2097 return result;
2100 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2102 bool result;
2104 START_PROFILE(syscall_fcntl_lock);
2106 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2107 "smbd",
2108 "force process locks",
2109 false)) {
2110 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2113 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2114 END_PROFILE(syscall_fcntl_lock);
2115 return result;
2118 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2119 uint32_t share_mode, uint32_t access_mask)
2121 START_PROFILE(syscall_kernel_flock);
2122 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2123 END_PROFILE(syscall_kernel_flock);
2124 return 0;
2127 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2129 bool result;
2130 int op = F_GETLK;
2132 START_PROFILE(syscall_fcntl_getlock);
2134 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2135 "smbd",
2136 "force process locks",
2137 false)) {
2138 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2141 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2142 END_PROFILE(syscall_fcntl_getlock);
2143 return result;
2146 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2147 int leasetype)
2149 int result = -1;
2151 START_PROFILE(syscall_linux_setlease);
2153 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2154 result = linux_setlease(fsp->fh->fd, leasetype);
2155 #else
2156 errno = ENOSYS;
2157 #endif
2158 END_PROFILE(syscall_linux_setlease);
2159 return result;
2162 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2164 int result;
2166 START_PROFILE(syscall_symlink);
2167 result = symlink(oldpath, newpath);
2168 END_PROFILE(syscall_symlink);
2169 return result;
2172 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2174 int result;
2176 START_PROFILE(syscall_readlink);
2177 result = readlink(path, buf, bufsiz);
2178 END_PROFILE(syscall_readlink);
2179 return result;
2182 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2184 int result;
2186 START_PROFILE(syscall_link);
2187 result = link(oldpath, newpath);
2188 END_PROFILE(syscall_link);
2189 return result;
2192 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2194 int result;
2196 START_PROFILE(syscall_mknod);
2197 result = sys_mknod(pathname, mode, dev);
2198 END_PROFILE(syscall_mknod);
2199 return result;
2202 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2204 char *result;
2206 START_PROFILE(syscall_realpath);
2207 result = sys_realpath(path);
2208 END_PROFILE(syscall_realpath);
2209 return result;
2212 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2213 unsigned int flags)
2215 #ifdef HAVE_CHFLAGS
2216 return chflags(path, flags);
2217 #else
2218 errno = ENOSYS;
2219 return -1;
2220 #endif
2223 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2224 const SMB_STRUCT_STAT *sbuf)
2226 struct file_id key;
2228 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2229 * blob */
2230 ZERO_STRUCT(key);
2232 key.devid = sbuf->st_ex_dev;
2233 key.inode = sbuf->st_ex_ino;
2234 /* key.extid is unused by default. */
2236 return key;
2239 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2240 struct files_struct *fsp,
2241 const struct smb_filename *smb_fname,
2242 TALLOC_CTX *mem_ctx,
2243 unsigned int *pnum_streams,
2244 struct stream_struct **pstreams)
2246 SMB_STRUCT_STAT sbuf;
2247 struct stream_struct *tmp_streams = NULL;
2248 int ret;
2250 if ((fsp != NULL) && (fsp->is_directory)) {
2252 * No default streams on directories
2254 goto done;
2257 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2258 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2260 else {
2261 struct smb_filename smb_fname_cp;
2263 ZERO_STRUCT(smb_fname_cp);
2264 smb_fname_cp.base_name = discard_const_p(char,
2265 smb_fname->base_name);
2266 smb_fname_cp.flags = smb_fname->flags;
2268 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2269 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2270 } else {
2271 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2273 sbuf = smb_fname_cp.st;
2276 if (ret == -1) {
2277 return map_nt_error_from_unix(errno);
2280 if (S_ISDIR(sbuf.st_ex_mode)) {
2281 goto done;
2284 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2285 (*pnum_streams) + 1);
2286 if (tmp_streams == NULL) {
2287 return NT_STATUS_NO_MEMORY;
2289 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2290 if (tmp_streams[*pnum_streams].name == NULL) {
2291 return NT_STATUS_NO_MEMORY;
2293 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2294 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2296 *pnum_streams += 1;
2297 *pstreams = tmp_streams;
2298 done:
2299 return NT_STATUS_OK;
2302 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2303 const char *path,
2304 const char *name,
2305 TALLOC_CTX *mem_ctx,
2306 char **found_name)
2309 * Don't fall back to get_real_filename so callers can differentiate
2310 * between a full directory scan and an actual case-insensitive stat.
2312 errno = EOPNOTSUPP;
2313 return -1;
2316 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2317 const char *fname)
2319 return handle->conn->connectpath;
2322 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2323 struct byte_range_lock *br_lck,
2324 struct lock_struct *plock,
2325 bool blocking_lock)
2327 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2329 /* Note: blr is not used in the default implementation. */
2330 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2333 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2334 struct messaging_context *msg_ctx,
2335 struct byte_range_lock *br_lck,
2336 const struct lock_struct *plock)
2338 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2340 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2343 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2344 struct byte_range_lock *br_lck,
2345 struct lock_struct *plock)
2347 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2349 /* Note: blr is not used in the default implementation. */
2350 return brl_lock_cancel_default(br_lck, plock);
2353 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2354 files_struct *fsp,
2355 struct lock_struct *plock)
2357 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2358 plock->lock_type == WRITE_LOCK);
2360 return strict_lock_default(fsp, plock);
2363 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2364 files_struct *fsp,
2365 struct lock_struct *plock)
2367 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2368 plock->lock_type == WRITE_LOCK);
2370 strict_unlock_default(fsp, plock);
2373 /* NT ACL operations. */
2375 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2376 files_struct *fsp,
2377 uint32_t security_info,
2378 TALLOC_CTX *mem_ctx,
2379 struct security_descriptor **ppdesc)
2381 NTSTATUS result;
2383 START_PROFILE(fget_nt_acl);
2384 result = posix_fget_nt_acl(fsp, security_info,
2385 mem_ctx, ppdesc);
2386 END_PROFILE(fget_nt_acl);
2387 return result;
2390 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2391 const struct smb_filename *smb_fname,
2392 uint32_t security_info,
2393 TALLOC_CTX *mem_ctx,
2394 struct security_descriptor **ppdesc)
2396 NTSTATUS result;
2398 START_PROFILE(get_nt_acl);
2399 result = posix_get_nt_acl(handle->conn,
2400 smb_fname,
2401 security_info,
2402 mem_ctx,
2403 ppdesc);
2404 END_PROFILE(get_nt_acl);
2405 return result;
2408 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2410 NTSTATUS result;
2412 START_PROFILE(fset_nt_acl);
2413 result = set_nt_acl(fsp, security_info_sent, psd);
2414 END_PROFILE(fset_nt_acl);
2415 return result;
2418 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2419 struct smb_filename *file,
2420 struct security_acl *sacl,
2421 uint32_t access_requested,
2422 uint32_t access_denied)
2424 return NT_STATUS_OK; /* Nothing to do here ... */
2427 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2428 const struct smb_filename *smb_fname,
2429 mode_t mode)
2431 #ifdef HAVE_NO_ACL
2432 errno = ENOSYS;
2433 return -1;
2434 #else
2435 int result;
2437 START_PROFILE(chmod_acl);
2438 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2439 END_PROFILE(chmod_acl);
2440 return result;
2441 #endif
2444 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2446 #ifdef HAVE_NO_ACL
2447 errno = ENOSYS;
2448 return -1;
2449 #else
2450 int result;
2452 START_PROFILE(fchmod_acl);
2453 result = fchmod_acl(fsp, mode);
2454 END_PROFILE(fchmod_acl);
2455 return result;
2456 #endif
2459 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2460 const char *path_p,
2461 SMB_ACL_TYPE_T type,
2462 TALLOC_CTX *mem_ctx)
2464 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2467 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2468 files_struct *fsp,
2469 TALLOC_CTX *mem_ctx)
2471 return sys_acl_get_fd(handle, fsp, mem_ctx);
2474 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2476 return sys_acl_set_file(handle, name, acltype, theacl);
2479 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2481 return sys_acl_set_fd(handle, fsp, theacl);
2484 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2486 return sys_acl_delete_def_file(handle, path);
2489 /****************************************************************
2490 Extended attribute operations.
2491 *****************************************************************/
2493 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2495 return getxattr(path, name, value, size);
2498 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2500 return fgetxattr(fsp->fh->fd, name, value, size);
2503 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2505 return listxattr(path, list, size);
2508 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2510 return flistxattr(fsp->fh->fd, list, size);
2513 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2515 return removexattr(path, name);
2518 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2520 return fremovexattr(fsp->fh->fd, name);
2523 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2525 return setxattr(path, name, value, size, flags);
2528 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2530 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2533 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2535 return false;
2538 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2539 const struct smb_filename *fname,
2540 SMB_STRUCT_STAT *sbuf)
2542 NTSTATUS status;
2543 char *path;
2544 bool offline = false;
2546 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2547 return false;
2550 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2551 #if defined(ENOTSUP)
2552 errno = ENOTSUP;
2553 #endif
2554 return false;
2557 status = get_full_smb_filename(talloc_tos(), fname, &path);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 errno = map_errno_from_nt_status(status);
2560 return false;
2563 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2565 TALLOC_FREE(path);
2567 return offline;
2570 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2571 const struct smb_filename *fname)
2573 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2574 #if defined(ENOTSUP)
2575 errno = ENOTSUP;
2576 #endif
2577 return -1;
2580 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2581 struct files_struct *fsp,
2582 TALLOC_CTX *mem_ctx,
2583 DATA_BLOB *cookie)
2585 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2588 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2589 struct files_struct *fsp,
2590 const DATA_BLOB old_cookie,
2591 TALLOC_CTX *mem_ctx,
2592 DATA_BLOB *new_cookie)
2594 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2595 new_cookie);
2598 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2599 struct smb_request *smb1req,
2600 struct smbXsrv_open *op,
2601 const DATA_BLOB old_cookie,
2602 TALLOC_CTX *mem_ctx,
2603 struct files_struct **fsp,
2604 DATA_BLOB *new_cookie)
2606 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2607 old_cookie, mem_ctx,
2608 fsp, new_cookie);
2611 static struct vfs_fn_pointers vfs_default_fns = {
2612 /* Disk operations */
2614 .connect_fn = vfswrap_connect,
2615 .disconnect_fn = vfswrap_disconnect,
2616 .disk_free_fn = vfswrap_disk_free,
2617 .get_quota_fn = vfswrap_get_quota,
2618 .set_quota_fn = vfswrap_set_quota,
2619 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2620 .statvfs_fn = vfswrap_statvfs,
2621 .fs_capabilities_fn = vfswrap_fs_capabilities,
2622 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2623 .snap_check_path_fn = vfswrap_snap_check_path,
2624 .snap_create_fn = vfswrap_snap_create,
2625 .snap_delete_fn = vfswrap_snap_delete,
2627 /* Directory operations */
2629 .opendir_fn = vfswrap_opendir,
2630 .fdopendir_fn = vfswrap_fdopendir,
2631 .readdir_fn = vfswrap_readdir,
2632 .readdir_attr_fn = vfswrap_readdir_attr,
2633 .seekdir_fn = vfswrap_seekdir,
2634 .telldir_fn = vfswrap_telldir,
2635 .rewind_dir_fn = vfswrap_rewinddir,
2636 .mkdir_fn = vfswrap_mkdir,
2637 .rmdir_fn = vfswrap_rmdir,
2638 .closedir_fn = vfswrap_closedir,
2639 .init_search_op_fn = vfswrap_init_search_op,
2641 /* File operations */
2643 .open_fn = vfswrap_open,
2644 .create_file_fn = vfswrap_create_file,
2645 .close_fn = vfswrap_close,
2646 .read_fn = vfswrap_read,
2647 .pread_fn = vfswrap_pread,
2648 .pread_send_fn = vfswrap_pread_send,
2649 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2650 .write_fn = vfswrap_write,
2651 .pwrite_fn = vfswrap_pwrite,
2652 .pwrite_send_fn = vfswrap_pwrite_send,
2653 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2654 .lseek_fn = vfswrap_lseek,
2655 .sendfile_fn = vfswrap_sendfile,
2656 .recvfile_fn = vfswrap_recvfile,
2657 .rename_fn = vfswrap_rename,
2658 .fsync_fn = vfswrap_fsync,
2659 .fsync_send_fn = vfswrap_fsync_send,
2660 .fsync_recv_fn = vfswrap_asys_int_recv,
2661 .stat_fn = vfswrap_stat,
2662 .fstat_fn = vfswrap_fstat,
2663 .lstat_fn = vfswrap_lstat,
2664 .get_alloc_size_fn = vfswrap_get_alloc_size,
2665 .unlink_fn = vfswrap_unlink,
2666 .chmod_fn = vfswrap_chmod,
2667 .fchmod_fn = vfswrap_fchmod,
2668 .chown_fn = vfswrap_chown,
2669 .fchown_fn = vfswrap_fchown,
2670 .lchown_fn = vfswrap_lchown,
2671 .chdir_fn = vfswrap_chdir,
2672 .getwd_fn = vfswrap_getwd,
2673 .ntimes_fn = vfswrap_ntimes,
2674 .ftruncate_fn = vfswrap_ftruncate,
2675 .fallocate_fn = vfswrap_fallocate,
2676 .lock_fn = vfswrap_lock,
2677 .kernel_flock_fn = vfswrap_kernel_flock,
2678 .linux_setlease_fn = vfswrap_linux_setlease,
2679 .getlock_fn = vfswrap_getlock,
2680 .symlink_fn = vfswrap_symlink,
2681 .readlink_fn = vfswrap_readlink,
2682 .link_fn = vfswrap_link,
2683 .mknod_fn = vfswrap_mknod,
2684 .realpath_fn = vfswrap_realpath,
2685 .chflags_fn = vfswrap_chflags,
2686 .file_id_create_fn = vfswrap_file_id_create,
2687 .streaminfo_fn = vfswrap_streaminfo,
2688 .get_real_filename_fn = vfswrap_get_real_filename,
2689 .connectpath_fn = vfswrap_connectpath,
2690 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2691 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2692 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2693 .strict_lock_fn = vfswrap_strict_lock,
2694 .strict_unlock_fn = vfswrap_strict_unlock,
2695 .translate_name_fn = vfswrap_translate_name,
2696 .fsctl_fn = vfswrap_fsctl,
2697 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2698 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2699 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2700 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2701 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2702 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2703 .get_compression_fn = vfswrap_get_compression,
2704 .set_compression_fn = vfswrap_set_compression,
2706 /* NT ACL operations. */
2708 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2709 .get_nt_acl_fn = vfswrap_get_nt_acl,
2710 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2711 .audit_file_fn = vfswrap_audit_file,
2713 /* POSIX ACL operations. */
2715 .chmod_acl_fn = vfswrap_chmod_acl,
2716 .fchmod_acl_fn = vfswrap_fchmod_acl,
2718 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2719 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2720 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2721 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2722 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2723 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2724 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2726 /* EA operations. */
2727 .getxattr_fn = vfswrap_getxattr,
2728 .fgetxattr_fn = vfswrap_fgetxattr,
2729 .listxattr_fn = vfswrap_listxattr,
2730 .flistxattr_fn = vfswrap_flistxattr,
2731 .removexattr_fn = vfswrap_removexattr,
2732 .fremovexattr_fn = vfswrap_fremovexattr,
2733 .setxattr_fn = vfswrap_setxattr,
2734 .fsetxattr_fn = vfswrap_fsetxattr,
2736 /* aio operations */
2737 .aio_force_fn = vfswrap_aio_force,
2739 /* offline operations */
2740 .is_offline_fn = vfswrap_is_offline,
2741 .set_offline_fn = vfswrap_set_offline,
2743 /* durable handle operations */
2744 .durable_cookie_fn = vfswrap_durable_cookie,
2745 .durable_disconnect_fn = vfswrap_durable_disconnect,
2746 .durable_reconnect_fn = vfswrap_durable_reconnect,
2749 NTSTATUS vfs_default_init(void);
2750 NTSTATUS vfs_default_init(void)
2752 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2753 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);