vfs_default: Fix passing of errno from async calls
[Samba.git] / source3 / modules / vfs_default.c
blob0a56e457ab925102543bef3299b398c26cb7a130
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/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
46 this possibility. */
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 /* Disk operations */
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
61 uint64_t *bsize,
62 uint64_t *dfree,
63 uint64_t *dsize)
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
66 return (uint64_t)-1;
69 *bsize = 512;
70 return *dfree / 2;
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
76 unid_t id,
77 SMB_DISK_QUOTA *qt)
79 #ifdef HAVE_SYS_QUOTAS
80 int result;
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
85 return result;
86 #else
87 errno = ENOSYS;
88 return -1;
89 #endif
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
95 int result;
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
100 return result;
101 #else
102 errno = ENOSYS;
103 return -1;
104 #endif
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
110 bool labels)
112 errno = ENOSYS;
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 connection_struct *conn = handle->conn;
127 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128 struct smb_filename *smb_fname_cpath = NULL;
129 struct vfs_statvfs_struct statbuf;
130 int ret;
132 ZERO_STRUCT(statbuf);
133 ret = sys_statvfs(conn->connectpath, &statbuf);
134 if (ret == 0) {
135 caps = statbuf.FsCapabilities;
138 *p_ts_res = TIMESTAMP_SET_SECONDS;
140 /* Work out what timestamp resolution we can
141 * use when setting a timestamp. */
143 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
144 NULL, NULL, 0);
145 if (smb_fname_cpath == NULL) {
146 return caps;
149 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
150 if (ret == -1) {
151 TALLOC_FREE(smb_fname_cpath);
152 return caps;
155 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
157 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
158 /* If any of the normal UNIX directory timestamps
159 * have a non-zero tv_nsec component assume
160 * we might be able to set sub-second timestamps.
161 * See what filetime set primitives we have.
163 #if defined(HAVE_UTIMENSAT)
164 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
165 #elif defined(HAVE_UTIMES)
166 /* utimes allows msec timestamps to be set. */
167 *p_ts_res = TIMESTAMP_SET_MSEC;
168 #elif defined(HAVE_UTIME)
169 /* utime only allows sec timestamps to be set. */
170 *p_ts_res = TIMESTAMP_SET_SECONDS;
171 #endif
173 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
174 "resolution of %s "
175 "available on share %s, directory %s\n",
176 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
177 lp_servicename(talloc_tos(), conn->params->service),
178 conn->connectpath ));
180 TALLOC_FREE(smb_fname_cpath);
181 return caps;
184 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
185 struct dfs_GetDFSReferral *r)
187 struct junction_map *junction = NULL;
188 int consumedcnt = 0;
189 bool self_referral = false;
190 char *pathnamep = NULL;
191 char *local_dfs_path = NULL;
192 NTSTATUS status;
193 int i;
194 uint16_t max_referral_level = r->in.req.max_referral_level;
196 if (DEBUGLVL(10)) {
197 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
200 /* get the junction entry */
201 if (r->in.req.servername == NULL) {
202 return NT_STATUS_NOT_FOUND;
206 * Trim pathname sent by client so it begins with only one backslash.
207 * Two backslashes confuse some dfs clients
210 local_dfs_path = talloc_strdup(r, r->in.req.servername);
211 if (local_dfs_path == NULL) {
212 return NT_STATUS_NO_MEMORY;
214 pathnamep = local_dfs_path;
215 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
216 IS_DIRECTORY_SEP(pathnamep[1])) {
217 pathnamep++;
220 junction = talloc_zero(r, struct junction_map);
221 if (junction == NULL) {
222 return NT_STATUS_NO_MEMORY;
225 /* The following call can change cwd. */
226 status = get_referred_path(r, pathnamep,
227 handle->conn->sconn->remote_address,
228 handle->conn->sconn->local_address,
229 !handle->conn->sconn->using_smb2,
230 junction, &consumedcnt, &self_referral);
231 if (!NT_STATUS_IS_OK(status)) {
232 struct smb_filename connectpath_fname = {
233 .base_name = handle->conn->connectpath
235 vfs_ChDir(handle->conn, &connectpath_fname);
236 return status;
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
245 if (!self_referral) {
246 pathnamep[consumedcnt] = '\0';
248 if (DEBUGLVL(3)) {
249 dbgtext("Path %s to alternate path(s):",
250 pathnamep);
251 for (i=0; i < junction->referral_count; i++) {
252 dbgtext(" %s",
253 junction->referral_list[i].alternate_path);
255 dbgtext(".\n");
259 if (r->in.req.max_referral_level <= 2) {
260 max_referral_level = 2;
262 if (r->in.req.max_referral_level >= 3) {
263 max_referral_level = 3;
266 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
267 if (r->out.resp == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
272 r->out.resp->nb_referrals = junction->referral_count;
274 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
275 if (self_referral) {
276 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
279 r->out.resp->referral_entries = talloc_zero_array(r,
280 struct dfs_referral_type,
281 r->out.resp->nb_referrals);
282 if (r->out.resp->referral_entries == NULL) {
283 return NT_STATUS_NO_MEMORY;
286 switch (max_referral_level) {
287 case 2:
288 for(i=0; i < junction->referral_count; i++) {
289 struct referral *ref = &junction->referral_list[i];
290 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
291 struct dfs_referral_type *t =
292 &r->out.resp->referral_entries[i];
293 struct dfs_referral_v2 *v2 = &t->referral.v2;
295 t->version = 2;
296 v2->size = VERSION2_REFERRAL_SIZE;
297 if (self_referral) {
298 v2->server_type = DFS_SERVER_ROOT;
299 } else {
300 v2->server_type = DFS_SERVER_NON_ROOT;
302 v2->entry_flags = 0;
303 v2->proximity = ref->proximity;
304 v2->ttl = ref->ttl;
305 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
306 if (v2->DFS_path == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
310 if (v2->DFS_alt_path == NULL) {
311 return NT_STATUS_NO_MEMORY;
313 v2->netw_address = talloc_strdup(mem_ctx,
314 ref->alternate_path);
315 if (v2->netw_address == NULL) {
316 return NT_STATUS_NO_MEMORY;
320 break;
321 case 3:
322 for(i=0; i < junction->referral_count; i++) {
323 struct referral *ref = &junction->referral_list[i];
324 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
325 struct dfs_referral_type *t =
326 &r->out.resp->referral_entries[i];
327 struct dfs_referral_v3 *v3 = &t->referral.v3;
328 struct dfs_normal_referral *r1 = &v3->referrals.r1;
330 t->version = 3;
331 v3->size = VERSION3_REFERRAL_SIZE;
332 if (self_referral) {
333 v3->server_type = DFS_SERVER_ROOT;
334 } else {
335 v3->server_type = DFS_SERVER_NON_ROOT;
337 v3->entry_flags = 0;
338 v3->ttl = ref->ttl;
339 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
340 if (r1->DFS_path == NULL) {
341 return NT_STATUS_NO_MEMORY;
343 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
344 if (r1->DFS_alt_path == NULL) {
345 return NT_STATUS_NO_MEMORY;
347 r1->netw_address = talloc_strdup(mem_ctx,
348 ref->alternate_path);
349 if (r1->netw_address == NULL) {
350 return NT_STATUS_NO_MEMORY;
353 break;
354 default:
355 DEBUG(0,("Invalid dfs referral version: %d\n",
356 max_referral_level));
357 return NT_STATUS_INVALID_LEVEL;
360 if (DEBUGLVL(10)) {
361 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
364 return NT_STATUS_OK;
367 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
368 TALLOC_CTX *mem_ctx,
369 const char *service_path,
370 char **base_volume)
372 return NT_STATUS_NOT_SUPPORTED;
375 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
376 TALLOC_CTX *mem_ctx,
377 const char *base_volume,
378 time_t *tstamp,
379 bool rw,
380 char **base_path,
381 char **snap_path)
383 return NT_STATUS_NOT_SUPPORTED;
386 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
387 TALLOC_CTX *mem_ctx,
388 char *base_path,
389 char *snap_path)
391 return NT_STATUS_NOT_SUPPORTED;
394 /* Directory operations */
396 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
397 const struct smb_filename *smb_fname,
398 const char *mask,
399 uint32_t attr)
401 DIR *result;
403 START_PROFILE(syscall_opendir);
404 result = opendir(smb_fname->base_name);
405 END_PROFILE(syscall_opendir);
406 return result;
409 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
410 files_struct *fsp,
411 const char *mask,
412 uint32_t attr)
414 DIR *result;
416 START_PROFILE(syscall_fdopendir);
417 result = sys_fdopendir(fsp->fh->fd);
418 END_PROFILE(syscall_fdopendir);
419 return result;
423 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
424 DIR *dirp,
425 SMB_STRUCT_STAT *sbuf)
427 struct dirent *result;
429 START_PROFILE(syscall_readdir);
430 result = readdir(dirp);
431 END_PROFILE(syscall_readdir);
432 if (sbuf) {
433 /* Default Posix readdir() does not give us stat info.
434 * Set to invalid to indicate we didn't return this info. */
435 SET_STAT_INVALID(*sbuf);
436 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
437 if (result != NULL) {
438 /* See if we can efficiently return this. */
439 struct stat st;
440 int flags = AT_SYMLINK_NOFOLLOW;
441 int ret = fstatat(dirfd(dirp),
442 result->d_name,
443 &st,
444 flags);
446 * As this is an optimization,
447 * ignore it if we stat'ed a
448 * symlink. Make the caller
449 * do it again as we don't
450 * know if they wanted the link
451 * info, or its target info.
453 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
454 init_stat_ex_from_stat(sbuf,
455 &st,
456 lp_fake_directory_create_times(
457 SNUM(handle->conn)));
460 #endif
462 return result;
465 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
466 const struct smb_filename *fname,
467 TALLOC_CTX *mem_ctx,
468 struct readdir_attr_data **attr_data)
470 return NT_STATUS_NOT_SUPPORTED;
473 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
475 START_PROFILE(syscall_seekdir);
476 seekdir(dirp, offset);
477 END_PROFILE(syscall_seekdir);
480 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
482 long result;
483 START_PROFILE(syscall_telldir);
484 result = telldir(dirp);
485 END_PROFILE(syscall_telldir);
486 return result;
489 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
491 START_PROFILE(syscall_rewinddir);
492 rewinddir(dirp);
493 END_PROFILE(syscall_rewinddir);
496 static int vfswrap_mkdir(vfs_handle_struct *handle,
497 const struct smb_filename *smb_fname,
498 mode_t mode)
500 int result;
501 bool has_dacl = False;
502 const char *path = smb_fname->base_name;
503 char *parent = NULL;
505 START_PROFILE(syscall_mkdir);
507 if (lp_inherit_acls(SNUM(handle->conn))
508 && parent_dirname(talloc_tos(), path, &parent, NULL)
509 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
510 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
513 TALLOC_FREE(parent);
515 result = mkdir(path, mode);
517 if (result == 0 && !has_dacl) {
519 * We need to do this as the default behavior of POSIX ACLs
520 * is to set the mask to be the requested group permission
521 * bits, not the group permission bits to be the requested
522 * group permission bits. This is not what we want, as it will
523 * mess up any inherited ACL bits that were set. JRA.
525 int saved_errno = errno; /* We may get ENOSYS */
526 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
527 (errno == ENOSYS)) {
528 errno = saved_errno;
532 END_PROFILE(syscall_mkdir);
533 return result;
536 static int vfswrap_rmdir(vfs_handle_struct *handle,
537 const struct smb_filename *smb_fname)
539 int result;
541 START_PROFILE(syscall_rmdir);
542 result = rmdir(smb_fname->base_name);
543 END_PROFILE(syscall_rmdir);
544 return result;
547 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
549 int result;
551 START_PROFILE(syscall_closedir);
552 result = closedir(dirp);
553 END_PROFILE(syscall_closedir);
554 return result;
557 static void vfswrap_init_search_op(vfs_handle_struct *handle,
558 DIR *dirp)
560 /* Default behavior is a NOOP */
563 /* File operations */
565 static int vfswrap_open(vfs_handle_struct *handle,
566 struct smb_filename *smb_fname,
567 files_struct *fsp, int flags, mode_t mode)
569 int result = -1;
571 START_PROFILE(syscall_open);
573 if (smb_fname->stream_name) {
574 errno = ENOENT;
575 goto out;
578 result = open(smb_fname->base_name, flags, mode);
579 out:
580 END_PROFILE(syscall_open);
581 return result;
584 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
585 struct smb_request *req,
586 uint16_t root_dir_fid,
587 struct smb_filename *smb_fname,
588 uint32_t access_mask,
589 uint32_t share_access,
590 uint32_t create_disposition,
591 uint32_t create_options,
592 uint32_t file_attributes,
593 uint32_t oplock_request,
594 struct smb2_lease *lease,
595 uint64_t allocation_size,
596 uint32_t private_flags,
597 struct security_descriptor *sd,
598 struct ea_list *ea_list,
599 files_struct **result,
600 int *pinfo,
601 const struct smb2_create_blobs *in_context_blobs,
602 struct smb2_create_blobs *out_context_blobs)
604 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
605 access_mask, share_access,
606 create_disposition, create_options,
607 file_attributes, oplock_request, lease,
608 allocation_size, private_flags,
609 sd, ea_list, result,
610 pinfo, in_context_blobs, out_context_blobs);
613 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
615 int result;
617 START_PROFILE(syscall_close);
618 result = fd_close_posix(fsp);
619 END_PROFILE(syscall_close);
620 return result;
623 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
625 ssize_t result;
627 START_PROFILE_BYTES(syscall_read, n);
628 result = sys_read(fsp->fh->fd, data, n);
629 END_PROFILE_BYTES(syscall_read);
630 return result;
633 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
634 size_t n, off_t offset)
636 ssize_t result;
638 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
639 START_PROFILE_BYTES(syscall_pread, n);
640 result = sys_pread(fsp->fh->fd, data, n, offset);
641 END_PROFILE_BYTES(syscall_pread);
643 if (result == -1 && errno == ESPIPE) {
644 /* Maintain the fiction that pipes can be seeked (sought?) on. */
645 result = SMB_VFS_READ(fsp, data, n);
646 fsp->fh->pos = 0;
649 #else /* HAVE_PREAD */
650 off_t curr;
651 int lerrno;
653 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
654 if (curr == -1 && errno == ESPIPE) {
655 /* Maintain the fiction that pipes can be seeked (sought?) on. */
656 result = SMB_VFS_READ(fsp, data, n);
657 fsp->fh->pos = 0;
658 return result;
661 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
662 return -1;
665 errno = 0;
666 result = SMB_VFS_READ(fsp, data, n);
667 lerrno = errno;
669 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
670 errno = lerrno;
672 #endif /* HAVE_PREAD */
674 return result;
677 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
679 ssize_t result;
681 START_PROFILE_BYTES(syscall_write, n);
682 result = sys_write(fsp->fh->fd, data, n);
683 END_PROFILE_BYTES(syscall_write);
684 return result;
687 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
688 size_t n, off_t offset)
690 ssize_t result;
692 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
693 START_PROFILE_BYTES(syscall_pwrite, n);
694 result = sys_pwrite(fsp->fh->fd, data, n, offset);
695 END_PROFILE_BYTES(syscall_pwrite);
697 if (result == -1 && errno == ESPIPE) {
698 /* Maintain the fiction that pipes can be sought on. */
699 result = SMB_VFS_WRITE(fsp, data, n);
702 #else /* HAVE_PWRITE */
703 off_t curr;
704 int lerrno;
706 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
707 if (curr == -1) {
708 return -1;
711 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
712 return -1;
715 result = SMB_VFS_WRITE(fsp, data, n);
716 lerrno = errno;
718 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
719 errno = lerrno;
721 #endif /* HAVE_PWRITE */
723 return result;
726 static int vfswrap_init_pool(struct smbd_server_connection *conn)
728 int ret;
730 if (conn->pool != NULL) {
731 return 0;
734 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
735 &conn->pool);
736 return ret;
739 struct vfswrap_pread_state {
740 ssize_t ret;
741 int fd;
742 void *buf;
743 size_t count;
744 off_t offset;
746 struct vfs_aio_state vfs_aio_state;
747 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
750 static void vfs_pread_do(void *private_data);
751 static void vfs_pread_done(struct tevent_req *subreq);
752 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
754 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
755 TALLOC_CTX *mem_ctx,
756 struct tevent_context *ev,
757 struct files_struct *fsp,
758 void *data,
759 size_t n, off_t offset)
761 struct tevent_req *req, *subreq;
762 struct vfswrap_pread_state *state;
763 int ret;
765 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
766 if (req == NULL) {
767 return NULL;
770 ret = vfswrap_init_pool(handle->conn->sconn);
771 if (tevent_req_error(req, ret)) {
772 return tevent_req_post(req, ev);
775 state->ret = -1;
776 state->fd = fsp->fh->fd;
777 state->buf = data;
778 state->count = n;
779 state->offset = offset;
781 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
782 state->profile_bytes, n);
783 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
785 subreq = pthreadpool_tevent_job_send(
786 state, ev, handle->conn->sconn->pool,
787 vfs_pread_do, state);
788 if (tevent_req_nomem(subreq, req)) {
789 return tevent_req_post(req, ev);
791 tevent_req_set_callback(subreq, vfs_pread_done, req);
793 talloc_set_destructor(state, vfs_pread_state_destructor);
795 return req;
798 static void vfs_pread_do(void *private_data)
800 struct vfswrap_pread_state *state = talloc_get_type_abort(
801 private_data, struct vfswrap_pread_state);
802 struct timespec start_time;
803 struct timespec end_time;
805 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
807 PROFILE_TIMESTAMP(&start_time);
809 do {
810 state->ret = pread(state->fd, state->buf, state->count,
811 state->offset);
812 } while ((state->ret == -1) && (errno == EINTR));
814 if (state->ret == -1) {
815 state->vfs_aio_state.error = errno;
818 PROFILE_TIMESTAMP(&end_time);
820 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
822 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
825 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
827 return -1;
830 static void vfs_pread_done(struct tevent_req *subreq)
832 struct tevent_req *req = tevent_req_callback_data(
833 subreq, struct tevent_req);
834 struct vfswrap_pread_state *state = tevent_req_data(
835 req, struct vfswrap_pread_state);
836 int ret;
838 ret = pthreadpool_tevent_job_recv(subreq);
839 TALLOC_FREE(subreq);
840 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
841 talloc_set_destructor(state, NULL);
842 if (tevent_req_error(req, ret)) {
843 return;
846 tevent_req_done(req);
849 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
850 struct vfs_aio_state *vfs_aio_state)
852 struct vfswrap_pread_state *state = tevent_req_data(
853 req, struct vfswrap_pread_state);
855 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
856 return -1;
859 *vfs_aio_state = state->vfs_aio_state;
860 return state->ret;
863 struct vfswrap_pwrite_state {
864 ssize_t ret;
865 int fd;
866 const void *buf;
867 size_t count;
868 off_t offset;
870 struct vfs_aio_state vfs_aio_state;
871 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
874 static void vfs_pwrite_do(void *private_data);
875 static void vfs_pwrite_done(struct tevent_req *subreq);
876 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
878 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
879 TALLOC_CTX *mem_ctx,
880 struct tevent_context *ev,
881 struct files_struct *fsp,
882 const void *data,
883 size_t n, off_t offset)
885 struct tevent_req *req, *subreq;
886 struct vfswrap_pwrite_state *state;
887 int ret;
889 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
890 if (req == NULL) {
891 return NULL;
894 ret = vfswrap_init_pool(handle->conn->sconn);
895 if (tevent_req_error(req, ret)) {
896 return tevent_req_post(req, ev);
899 state->ret = -1;
900 state->fd = fsp->fh->fd;
901 state->buf = data;
902 state->count = n;
903 state->offset = offset;
905 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
906 state->profile_bytes, n);
907 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
909 subreq = pthreadpool_tevent_job_send(
910 state, ev, handle->conn->sconn->pool,
911 vfs_pwrite_do, state);
912 if (tevent_req_nomem(subreq, req)) {
913 return tevent_req_post(req, ev);
915 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
917 talloc_set_destructor(state, vfs_pwrite_state_destructor);
919 return req;
922 static void vfs_pwrite_do(void *private_data)
924 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
925 private_data, struct vfswrap_pwrite_state);
926 struct timespec start_time;
927 struct timespec end_time;
929 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
931 PROFILE_TIMESTAMP(&start_time);
933 do {
934 state->ret = pwrite(state->fd, state->buf, state->count,
935 state->offset);
936 } while ((state->ret == -1) && (errno == EINTR));
938 if (state->ret == -1) {
939 state->vfs_aio_state.error = errno;
942 PROFILE_TIMESTAMP(&end_time);
944 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
946 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
949 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
951 return -1;
954 static void vfs_pwrite_done(struct tevent_req *subreq)
956 struct tevent_req *req = tevent_req_callback_data(
957 subreq, struct tevent_req);
958 struct vfswrap_pwrite_state *state = tevent_req_data(
959 req, struct vfswrap_pwrite_state);
960 int ret;
962 ret = pthreadpool_tevent_job_recv(subreq);
963 TALLOC_FREE(subreq);
964 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
965 talloc_set_destructor(state, NULL);
966 if (tevent_req_error(req, ret)) {
967 return;
970 tevent_req_done(req);
973 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
974 struct vfs_aio_state *vfs_aio_state)
976 struct vfswrap_pwrite_state *state = tevent_req_data(
977 req, struct vfswrap_pwrite_state);
979 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
980 return -1;
983 *vfs_aio_state = state->vfs_aio_state;
984 return state->ret;
987 struct vfswrap_fsync_state {
988 ssize_t ret;
989 int fd;
991 struct vfs_aio_state vfs_aio_state;
992 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
995 static void vfs_fsync_do(void *private_data);
996 static void vfs_fsync_done(struct tevent_req *subreq);
997 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
999 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1000 TALLOC_CTX *mem_ctx,
1001 struct tevent_context *ev,
1002 struct files_struct *fsp)
1004 struct tevent_req *req, *subreq;
1005 struct vfswrap_fsync_state *state;
1006 int ret;
1008 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1009 if (req == NULL) {
1010 return NULL;
1013 ret = vfswrap_init_pool(handle->conn->sconn);
1014 if (tevent_req_error(req, ret)) {
1015 return tevent_req_post(req, ev);
1018 state->ret = -1;
1019 state->fd = fsp->fh->fd;
1021 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1022 state->profile_basic);
1024 subreq = pthreadpool_tevent_job_send(
1025 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1026 if (tevent_req_nomem(subreq, req)) {
1027 return tevent_req_post(req, ev);
1029 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1031 talloc_set_destructor(state, vfs_fsync_state_destructor);
1033 return req;
1036 static void vfs_fsync_do(void *private_data)
1038 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1039 private_data, struct vfswrap_fsync_state);
1040 struct timespec start_time;
1041 struct timespec end_time;
1043 PROFILE_TIMESTAMP(&start_time);
1045 do {
1046 state->ret = fsync(state->fd);
1047 } while ((state->ret == -1) && (errno == EINTR));
1049 if (state->ret == -1) {
1050 state->vfs_aio_state.error = errno;
1053 PROFILE_TIMESTAMP(&end_time);
1055 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1058 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1060 return -1;
1063 static void vfs_fsync_done(struct tevent_req *subreq)
1065 struct tevent_req *req = tevent_req_callback_data(
1066 subreq, struct tevent_req);
1067 struct vfswrap_fsync_state *state = tevent_req_data(
1068 req, struct vfswrap_fsync_state);
1069 int ret;
1071 ret = pthreadpool_tevent_job_recv(subreq);
1072 TALLOC_FREE(subreq);
1073 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1074 talloc_set_destructor(state, NULL);
1075 if (tevent_req_error(req, ret)) {
1076 return;
1079 tevent_req_done(req);
1082 static int vfswrap_fsync_recv(struct tevent_req *req,
1083 struct vfs_aio_state *vfs_aio_state)
1085 struct vfswrap_fsync_state *state = tevent_req_data(
1086 req, struct vfswrap_fsync_state);
1088 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1089 return -1;
1092 *vfs_aio_state = state->vfs_aio_state;
1093 return state->ret;
1096 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1098 off_t result = 0;
1100 START_PROFILE(syscall_lseek);
1102 /* Cope with 'stat' file opens. */
1103 if (fsp->fh->fd != -1)
1104 result = lseek(fsp->fh->fd, offset, whence);
1107 * We want to maintain the fiction that we can seek
1108 * on a fifo for file system purposes. This allows
1109 * people to set up UNIX fifo's that feed data to Windows
1110 * applications. JRA.
1113 if((result == -1) && (errno == ESPIPE)) {
1114 result = 0;
1115 errno = 0;
1118 END_PROFILE(syscall_lseek);
1119 return result;
1122 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1123 off_t offset, size_t n)
1125 ssize_t result;
1127 START_PROFILE_BYTES(syscall_sendfile, n);
1128 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1129 END_PROFILE_BYTES(syscall_sendfile);
1130 return result;
1133 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1134 int fromfd,
1135 files_struct *tofsp,
1136 off_t offset,
1137 size_t n)
1139 ssize_t result;
1141 START_PROFILE_BYTES(syscall_recvfile, n);
1142 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1143 END_PROFILE_BYTES(syscall_recvfile);
1144 return result;
1147 static int vfswrap_rename(vfs_handle_struct *handle,
1148 const struct smb_filename *smb_fname_src,
1149 const struct smb_filename *smb_fname_dst)
1151 int result = -1;
1153 START_PROFILE(syscall_rename);
1155 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1156 errno = ENOENT;
1157 goto out;
1160 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1162 out:
1163 END_PROFILE(syscall_rename);
1164 return result;
1167 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1169 #ifdef HAVE_FSYNC
1170 int result;
1172 START_PROFILE(syscall_fsync);
1173 result = fsync(fsp->fh->fd);
1174 END_PROFILE(syscall_fsync);
1175 return result;
1176 #else
1177 return 0;
1178 #endif
1181 static int vfswrap_stat(vfs_handle_struct *handle,
1182 struct smb_filename *smb_fname)
1184 int result = -1;
1186 START_PROFILE(syscall_stat);
1188 if (smb_fname->stream_name) {
1189 errno = ENOENT;
1190 goto out;
1193 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1194 lp_fake_directory_create_times(SNUM(handle->conn)));
1195 out:
1196 END_PROFILE(syscall_stat);
1197 return result;
1200 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1202 int result;
1204 START_PROFILE(syscall_fstat);
1205 result = sys_fstat(fsp->fh->fd,
1206 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1207 END_PROFILE(syscall_fstat);
1208 return result;
1211 static int vfswrap_lstat(vfs_handle_struct *handle,
1212 struct smb_filename *smb_fname)
1214 int result = -1;
1216 START_PROFILE(syscall_lstat);
1218 if (smb_fname->stream_name) {
1219 errno = ENOENT;
1220 goto out;
1223 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1224 lp_fake_directory_create_times(SNUM(handle->conn)));
1225 out:
1226 END_PROFILE(syscall_lstat);
1227 return result;
1230 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1231 const char *name,
1232 enum vfs_translate_direction direction,
1233 TALLOC_CTX *mem_ctx,
1234 char **mapped_name)
1236 return NT_STATUS_NONE_MAPPED;
1240 * Implement the default fsctl operation.
1242 static bool vfswrap_logged_ioctl_message = false;
1244 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1245 struct files_struct *fsp,
1246 TALLOC_CTX *ctx,
1247 uint32_t function,
1248 uint16_t req_flags, /* Needed for UNICODE ... */
1249 const uint8_t *_in_data,
1250 uint32_t in_len,
1251 uint8_t **_out_data,
1252 uint32_t max_out_len,
1253 uint32_t *out_len)
1255 const char *in_data = (const char *)_in_data;
1256 char **out_data = (char **)_out_data;
1257 NTSTATUS status;
1259 switch (function) {
1260 case FSCTL_SET_SPARSE:
1262 bool set_sparse = true;
1264 if (in_len >= 1 && in_data[0] == 0) {
1265 set_sparse = false;
1268 status = file_set_sparse(handle->conn, fsp, set_sparse);
1270 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1271 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1272 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1273 nt_errstr(status)));
1275 return status;
1278 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1280 unsigned char objid[16];
1281 char *return_data = NULL;
1283 /* This should return the object-id on this file.
1284 * I think I'll make this be the inode+dev. JRA.
1287 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1288 fsp_fnum_dbg(fsp)));
1290 *out_len = MIN(max_out_len, 64);
1292 /* Hmmm, will this cause problems if less data asked for? */
1293 return_data = talloc_array(ctx, char, 64);
1294 if (return_data == NULL) {
1295 return NT_STATUS_NO_MEMORY;
1298 /* For backwards compatibility only store the dev/inode. */
1299 push_file_id_16(return_data, &fsp->file_id);
1300 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1301 push_file_id_16(return_data+32, &fsp->file_id);
1302 memset(return_data+48, 0, 16);
1303 *out_data = return_data;
1304 return NT_STATUS_OK;
1307 case FSCTL_GET_REPARSE_POINT:
1309 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1310 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1311 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1312 return NT_STATUS_NOT_A_REPARSE_POINT;
1315 case FSCTL_SET_REPARSE_POINT:
1317 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1318 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1319 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1320 return NT_STATUS_NOT_A_REPARSE_POINT;
1323 case FSCTL_GET_SHADOW_COPY_DATA:
1326 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1327 * and return their volume names. If max_data_count is 16, then it is just
1328 * asking for the number of volumes and length of the combined names.
1330 * pdata is the data allocated by our caller, but that uses
1331 * total_data_count (which is 0 in our case) rather than max_data_count.
1332 * Allocate the correct amount and return the pointer to let
1333 * it be deallocated when we return.
1335 struct shadow_copy_data *shadow_data = NULL;
1336 bool labels = False;
1337 uint32_t labels_data_count = 0;
1338 uint32_t i;
1339 char *cur_pdata = NULL;
1341 if (max_out_len < 16) {
1342 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1343 max_out_len));
1344 return NT_STATUS_INVALID_PARAMETER;
1347 if (max_out_len > 16) {
1348 labels = True;
1351 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1352 if (shadow_data == NULL) {
1353 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1354 return NT_STATUS_NO_MEMORY;
1358 * Call the VFS routine to actually do the work.
1360 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1361 int log_lev = 0;
1362 if (errno == 0) {
1363 /* broken module didn't set errno on error */
1364 status = NT_STATUS_UNSUCCESSFUL;
1365 } else {
1366 status = map_nt_error_from_unix(errno);
1367 if (NT_STATUS_EQUAL(status,
1368 NT_STATUS_NOT_SUPPORTED)) {
1369 log_lev = 5;
1372 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1373 "connectpath %s, failed - %s.\n",
1374 fsp->conn->connectpath,
1375 nt_errstr(status)));
1376 TALLOC_FREE(shadow_data);
1377 return status;
1380 labels_data_count = (shadow_data->num_volumes * 2 *
1381 sizeof(SHADOW_COPY_LABEL)) + 2;
1383 if (!labels) {
1384 *out_len = 16;
1385 } else {
1386 *out_len = 12 + labels_data_count;
1389 if (max_out_len < *out_len) {
1390 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1391 max_out_len, *out_len));
1392 TALLOC_FREE(shadow_data);
1393 return NT_STATUS_BUFFER_TOO_SMALL;
1396 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1397 if (cur_pdata == NULL) {
1398 TALLOC_FREE(shadow_data);
1399 return NT_STATUS_NO_MEMORY;
1402 *out_data = cur_pdata;
1404 /* num_volumes 4 bytes */
1405 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1407 if (labels) {
1408 /* num_labels 4 bytes */
1409 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1412 /* needed_data_count 4 bytes */
1413 SIVAL(cur_pdata, 8, labels_data_count);
1415 cur_pdata += 12;
1417 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1418 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1419 if (labels && shadow_data->labels) {
1420 for (i=0; i<shadow_data->num_volumes; i++) {
1421 size_t len = 0;
1422 status = srvstr_push(cur_pdata, req_flags,
1423 cur_pdata, shadow_data->labels[i],
1424 2 * sizeof(SHADOW_COPY_LABEL),
1425 STR_UNICODE|STR_TERMINATE, &len);
1426 if (!NT_STATUS_IS_OK(status)) {
1427 TALLOC_FREE(*out_data);
1428 TALLOC_FREE(shadow_data);
1429 return status;
1431 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1432 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1436 TALLOC_FREE(shadow_data);
1438 return NT_STATUS_OK;
1441 case FSCTL_FIND_FILES_BY_SID:
1443 /* pretend this succeeded -
1445 * we have to send back a list with all files owned by this SID
1447 * but I have to check that --metze
1449 struct dom_sid sid;
1450 uid_t uid;
1451 size_t sid_len;
1453 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1454 fsp_fnum_dbg(fsp)));
1456 if (in_len < 8) {
1457 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1458 return NT_STATUS_INVALID_PARAMETER;
1461 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1463 /* unknown 4 bytes: this is not the length of the sid :-( */
1464 /*unknown = IVAL(pdata,0);*/
1466 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1467 return NT_STATUS_INVALID_PARAMETER;
1469 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1471 if (!sid_to_uid(&sid, &uid)) {
1472 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1473 sid_string_dbg(&sid),
1474 (unsigned long)sid_len));
1475 uid = (-1);
1478 /* we can take a look at the find source :-)
1480 * find ./ -uid $uid -name '*' is what we need here
1483 * and send 4bytes len and then NULL terminated unicode strings
1484 * for each file
1486 * but I don't know how to deal with the paged results
1487 * (maybe we can hang the result anywhere in the fsp struct)
1489 * but I don't know how to deal with the paged results
1490 * (maybe we can hang the result anywhere in the fsp struct)
1492 * we don't send all files at once
1493 * and at the next we should *not* start from the beginning,
1494 * so we have to cache the result
1496 * --metze
1499 /* this works for now... */
1500 return NT_STATUS_OK;
1503 case FSCTL_QUERY_ALLOCATED_RANGES:
1505 /* FIXME: This is just a dummy reply, telling that all of the
1506 * file is allocated. MKS cp needs that.
1507 * Adding the real allocated ranges via FIEMAP on Linux
1508 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1509 * this FSCTL correct for sparse files.
1511 uint64_t offset, length;
1512 char *out_data_tmp = NULL;
1514 if (in_len != 16) {
1515 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1516 in_len));
1517 return NT_STATUS_INVALID_PARAMETER;
1520 if (max_out_len < 16) {
1521 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1522 max_out_len));
1523 return NT_STATUS_INVALID_PARAMETER;
1526 offset = BVAL(in_data,0);
1527 length = BVAL(in_data,8);
1529 if (offset + length < offset) {
1530 /* No 64-bit integer wrap. */
1531 return NT_STATUS_INVALID_PARAMETER;
1534 /* Shouldn't this be SMB_VFS_STAT ... ? */
1535 status = vfs_stat_fsp(fsp);
1536 if (!NT_STATUS_IS_OK(status)) {
1537 return status;
1540 *out_len = 16;
1541 out_data_tmp = talloc_array(ctx, char, *out_len);
1542 if (out_data_tmp == NULL) {
1543 DEBUG(10, ("unable to allocate memory for response\n"));
1544 return NT_STATUS_NO_MEMORY;
1547 if (offset > fsp->fsp_name->st.st_ex_size ||
1548 fsp->fsp_name->st.st_ex_size == 0 ||
1549 length == 0) {
1550 memset(out_data_tmp, 0, *out_len);
1551 } else {
1552 uint64_t end = offset + length;
1553 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1554 SBVAL(out_data_tmp, 0, 0);
1555 SBVAL(out_data_tmp, 8, end);
1558 *out_data = out_data_tmp;
1560 return NT_STATUS_OK;
1563 case FSCTL_IS_VOLUME_DIRTY:
1565 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1566 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1568 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1569 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1571 return NT_STATUS_INVALID_PARAMETER;
1574 default:
1576 * Only print once ... unfortunately there could be lots of
1577 * different FSCTLs that are called.
1579 if (!vfswrap_logged_ioctl_message) {
1580 vfswrap_logged_ioctl_message = true;
1581 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1582 __func__, function));
1586 return NT_STATUS_NOT_SUPPORTED;
1589 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1590 const struct smb_filename *fname,
1591 SMB_STRUCT_STAT *sbuf);
1593 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1594 struct smb_filename *smb_fname,
1595 uint32_t *dosmode)
1597 bool offline;
1599 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1600 if (offline) {
1601 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1604 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1607 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1608 struct files_struct *fsp,
1609 uint32_t *dosmode)
1611 bool offline;
1613 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1614 if (offline) {
1615 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1618 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1621 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1622 const struct smb_filename *smb_fname,
1623 uint32_t dosmode)
1625 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1628 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1629 struct files_struct *fsp,
1630 uint32_t dosmode)
1632 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1635 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1637 struct vfswrap_offload_read_state {
1638 DATA_BLOB token;
1641 static struct tevent_req *vfswrap_offload_read_send(
1642 TALLOC_CTX *mem_ctx,
1643 struct tevent_context *ev,
1644 struct vfs_handle_struct *handle,
1645 struct files_struct *fsp,
1646 uint32_t fsctl,
1647 uint32_t ttl,
1648 off_t offset,
1649 size_t to_copy)
1651 struct tevent_req *req = NULL;
1652 struct vfswrap_offload_read_state *state = NULL;
1653 NTSTATUS status;
1655 req = tevent_req_create(mem_ctx, &state,
1656 struct vfswrap_offload_read_state);
1657 if (req == NULL) {
1658 return NULL;
1661 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1662 &vfswrap_offload_ctx);
1663 if (tevent_req_nterror(req, status)) {
1664 return tevent_req_post(req, ev);
1667 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1668 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1669 return tevent_req_post(req, ev);
1672 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1673 &state->token);
1674 if (tevent_req_nterror(req, status)) {
1675 return tevent_req_post(req, ev);
1678 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1679 &state->token);
1680 if (tevent_req_nterror(req, status)) {
1681 return tevent_req_post(req, ev);
1684 tevent_req_done(req);
1685 return tevent_req_post(req, ev);
1688 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1689 struct vfs_handle_struct *handle,
1690 TALLOC_CTX *mem_ctx,
1691 DATA_BLOB *token)
1693 struct vfswrap_offload_read_state *state = tevent_req_data(
1694 req, struct vfswrap_offload_read_state);
1695 NTSTATUS status;
1697 if (tevent_req_is_nterror(req, &status)) {
1698 tevent_req_received(req);
1699 return status;
1702 token->length = state->token.length;
1703 token->data = talloc_move(mem_ctx, &state->token.data);
1705 tevent_req_received(req);
1706 return NT_STATUS_OK;
1709 struct vfswrap_offload_write_state {
1710 struct tevent_context *ev;
1711 uint8_t *buf;
1712 bool read_lck_locked;
1713 bool write_lck_locked;
1714 DATA_BLOB *token;
1715 struct files_struct *src_fsp;
1716 off_t src_off;
1717 struct files_struct *dst_fsp;
1718 off_t dst_off;
1719 off_t to_copy;
1720 off_t remaining;
1721 size_t next_io_size;
1724 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1726 static struct tevent_req *vfswrap_offload_write_send(
1727 struct vfs_handle_struct *handle,
1728 TALLOC_CTX *mem_ctx,
1729 struct tevent_context *ev,
1730 uint32_t fsctl,
1731 DATA_BLOB *token,
1732 off_t transfer_offset,
1733 struct files_struct *dest_fsp,
1734 off_t dest_off,
1735 off_t to_copy)
1737 struct tevent_req *req;
1738 struct vfswrap_offload_write_state *state = NULL;
1739 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1740 files_struct *src_fsp = NULL;
1741 NTSTATUS status;
1743 req = tevent_req_create(mem_ctx, &state,
1744 struct vfswrap_offload_write_state);
1745 if (req == NULL) {
1746 return NULL;
1749 *state = (struct vfswrap_offload_write_state) {
1750 .ev = ev,
1751 .token = token,
1752 .src_off = transfer_offset,
1753 .dst_fsp = dest_fsp,
1754 .dst_off = dest_off,
1755 .to_copy = to_copy,
1756 .remaining = to_copy,
1759 switch (fsctl) {
1760 case FSCTL_SRV_COPYCHUNK:
1761 case FSCTL_SRV_COPYCHUNK_WRITE:
1762 break;
1764 case FSCTL_OFFLOAD_WRITE:
1765 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1766 return tevent_req_post(req, ev);
1768 case FSCTL_DUP_EXTENTS_TO_FILE:
1769 DBG_DEBUG("COW clones not supported by vfs_default\n");
1770 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1771 return tevent_req_post(req, ev);
1773 default:
1774 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1775 return tevent_req_post(req, ev);
1779 * From here on we assume a copy-chunk fsctl
1782 if (to_copy == 0) {
1783 tevent_req_done(req);
1784 return tevent_req_post(req, ev);
1787 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1788 token, &src_fsp);
1789 if (tevent_req_nterror(req, status)) {
1790 return tevent_req_post(req, ev);
1792 state->src_fsp = src_fsp;
1794 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1796 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 tevent_req_nterror(req, status);
1799 return tevent_req_post(req, ev);
1802 state->buf = talloc_array(state, uint8_t, num);
1803 if (tevent_req_nomem(state->buf, req)) {
1804 return tevent_req_post(req, ev);
1807 status = vfs_stat_fsp(src_fsp);
1808 if (tevent_req_nterror(req, status)) {
1809 return tevent_req_post(req, ev);
1812 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1814 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1815 * If the SourceOffset or SourceOffset + Length extends beyond
1816 * the end of file, the server SHOULD<240> treat this as a
1817 * STATUS_END_OF_FILE error.
1818 * ...
1819 * <240> Section 3.3.5.15.6: Windows servers will return
1820 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1822 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1823 return tevent_req_post(req, ev);
1826 if (src_fsp->op == NULL) {
1827 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1828 return tevent_req_post(req, ev);
1831 if (dest_fsp->op == NULL) {
1832 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1833 return tevent_req_post(req, ev);
1836 status = vfswrap_offload_write_loop(req);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 tevent_req_nterror(req, status);
1839 return tevent_req_post(req, ev);
1842 return req;
1845 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1847 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1849 struct vfswrap_offload_write_state *state = tevent_req_data(
1850 req, struct vfswrap_offload_write_state);
1851 struct tevent_req *subreq = NULL;
1852 struct lock_struct read_lck;
1853 bool ok;
1855 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1857 init_strict_lock_struct(state->src_fsp,
1858 state->src_fsp->op->global->open_persistent_id,
1859 state->src_off,
1860 state->next_io_size,
1861 READ_LOCK,
1862 &read_lck);
1864 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1865 state->src_fsp,
1866 &read_lck);
1867 if (!ok) {
1868 return NT_STATUS_FILE_LOCK_CONFLICT;
1871 subreq = SMB_VFS_PREAD_SEND(state,
1872 state->src_fsp->conn->sconn->ev_ctx,
1873 state->src_fsp,
1874 state->buf,
1875 state->next_io_size,
1876 state->src_off);
1877 if (subreq == NULL) {
1878 return NT_STATUS_NO_MEMORY;
1880 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1882 return NT_STATUS_OK;
1885 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1887 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1889 struct tevent_req *req = tevent_req_callback_data(
1890 subreq, struct tevent_req);
1891 struct vfswrap_offload_write_state *state = tevent_req_data(
1892 req, struct vfswrap_offload_write_state);
1893 struct vfs_aio_state aio_state;
1894 struct lock_struct write_lck;
1895 ssize_t nread;
1896 bool ok;
1898 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1899 TALLOC_FREE(subreq);
1900 if (nread == -1) {
1901 DBG_ERR("read failed: %s\n", strerror(errno));
1902 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1903 return;
1905 if (nread != state->next_io_size) {
1906 DBG_ERR("Short read, only %zd of %zu\n",
1907 nread, state->next_io_size);
1908 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1909 return;
1912 state->src_off += nread;
1914 init_strict_lock_struct(state->dst_fsp,
1915 state->dst_fsp->op->global->open_persistent_id,
1916 state->dst_off,
1917 state->next_io_size,
1918 WRITE_LOCK,
1919 &write_lck);
1921 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1922 state->dst_fsp,
1923 &write_lck);
1924 if (!ok) {
1925 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1926 return;
1929 subreq = SMB_VFS_PWRITE_SEND(state,
1930 state->ev,
1931 state->dst_fsp,
1932 state->buf,
1933 state->next_io_size,
1934 state->dst_off);
1935 if (subreq == NULL) {
1936 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1937 return;
1939 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1942 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1944 struct tevent_req *req = tevent_req_callback_data(
1945 subreq, struct tevent_req);
1946 struct vfswrap_offload_write_state *state = tevent_req_data(
1947 req, struct vfswrap_offload_write_state);
1948 struct vfs_aio_state aio_state;
1949 ssize_t nwritten;
1950 NTSTATUS status;
1952 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1953 TALLOC_FREE(subreq);
1954 if (nwritten == -1) {
1955 DBG_ERR("write failed: %s\n", strerror(errno));
1956 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1957 return;
1959 if (nwritten != state->next_io_size) {
1960 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1961 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1962 return;
1965 state->dst_off += nwritten;
1967 if (state->remaining < nwritten) {
1968 /* Paranoia check */
1969 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1970 return;
1972 state->remaining -= nwritten;
1973 if (state->remaining == 0) {
1974 tevent_req_done(req);
1975 return;
1978 status = vfswrap_offload_write_loop(req);
1979 if (!NT_STATUS_IS_OK(status)) {
1980 tevent_req_nterror(req, status);
1981 return;
1984 return;
1987 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1988 struct tevent_req *req,
1989 off_t *copied)
1991 struct vfswrap_offload_write_state *state = tevent_req_data(
1992 req, struct vfswrap_offload_write_state);
1993 NTSTATUS status;
1995 if (tevent_req_is_nterror(req, &status)) {
1996 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1997 *copied = 0;
1998 tevent_req_received(req);
1999 return status;
2002 *copied = state->to_copy;
2003 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2004 tevent_req_received(req);
2006 return NT_STATUS_OK;
2009 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2010 TALLOC_CTX *mem_ctx,
2011 struct files_struct *fsp,
2012 struct smb_filename *smb_fname,
2013 uint16_t *_compression_fmt)
2015 return NT_STATUS_INVALID_DEVICE_REQUEST;
2018 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2019 TALLOC_CTX *mem_ctx,
2020 struct files_struct *fsp,
2021 uint16_t compression_fmt)
2023 return NT_STATUS_INVALID_DEVICE_REQUEST;
2026 /********************************************************************
2027 Given a stat buffer return the allocated size on disk, taking into
2028 account sparse files.
2029 ********************************************************************/
2030 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2031 struct files_struct *fsp,
2032 const SMB_STRUCT_STAT *sbuf)
2034 uint64_t result;
2036 START_PROFILE(syscall_get_alloc_size);
2038 if(S_ISDIR(sbuf->st_ex_mode)) {
2039 result = 0;
2040 goto out;
2043 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2044 /* The type of st_blocksize is blkcnt_t which *MUST* be
2045 signed (according to POSIX) and can be less than 64-bits.
2046 Ensure when we're converting to 64 bits wide we don't
2047 sign extend. */
2048 #if defined(SIZEOF_BLKCNT_T_8)
2049 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2050 #elif defined(SIZEOF_BLKCNT_T_4)
2052 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2053 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2055 #else
2056 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2057 #endif
2058 if (result == 0) {
2060 * Some file systems do not allocate a block for very
2061 * small files. But for non-empty file should report a
2062 * positive size.
2065 uint64_t filesize = get_file_size_stat(sbuf);
2066 if (filesize > 0) {
2067 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2070 #else
2071 result = get_file_size_stat(sbuf);
2072 #endif
2074 if (fsp && fsp->initial_allocation_size)
2075 result = MAX(result,fsp->initial_allocation_size);
2077 result = smb_roundup(handle->conn, result);
2079 out:
2080 END_PROFILE(syscall_get_alloc_size);
2081 return result;
2084 static int vfswrap_unlink(vfs_handle_struct *handle,
2085 const struct smb_filename *smb_fname)
2087 int result = -1;
2089 START_PROFILE(syscall_unlink);
2091 if (smb_fname->stream_name) {
2092 errno = ENOENT;
2093 goto out;
2095 result = unlink(smb_fname->base_name);
2097 out:
2098 END_PROFILE(syscall_unlink);
2099 return result;
2102 static int vfswrap_chmod(vfs_handle_struct *handle,
2103 const struct smb_filename *smb_fname,
2104 mode_t mode)
2106 int result;
2108 START_PROFILE(syscall_chmod);
2111 * We need to do this due to the fact that the default POSIX ACL
2112 * chmod modifies the ACL *mask* for the group owner, not the
2113 * group owner bits directly. JRA.
2118 int saved_errno = errno; /* We might get ENOSYS */
2119 result = SMB_VFS_CHMOD_ACL(handle->conn,
2120 smb_fname,
2121 mode);
2122 if (result == 0) {
2123 END_PROFILE(syscall_chmod);
2124 return result;
2126 /* Error - return the old errno. */
2127 errno = saved_errno;
2130 result = chmod(smb_fname->base_name, mode);
2131 END_PROFILE(syscall_chmod);
2132 return result;
2135 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2137 int result;
2139 START_PROFILE(syscall_fchmod);
2142 * We need to do this due to the fact that the default POSIX ACL
2143 * chmod modifies the ACL *mask* for the group owner, not the
2144 * group owner bits directly. JRA.
2148 int saved_errno = errno; /* We might get ENOSYS */
2149 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2150 END_PROFILE(syscall_fchmod);
2151 return result;
2153 /* Error - return the old errno. */
2154 errno = saved_errno;
2157 #if defined(HAVE_FCHMOD)
2158 result = fchmod(fsp->fh->fd, mode);
2159 #else
2160 result = -1;
2161 errno = ENOSYS;
2162 #endif
2164 END_PROFILE(syscall_fchmod);
2165 return result;
2168 static int vfswrap_chown(vfs_handle_struct *handle,
2169 const struct smb_filename *smb_fname,
2170 uid_t uid,
2171 gid_t gid)
2173 int result;
2175 START_PROFILE(syscall_chown);
2176 result = chown(smb_fname->base_name, uid, gid);
2177 END_PROFILE(syscall_chown);
2178 return result;
2181 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2183 #ifdef HAVE_FCHOWN
2184 int result;
2186 START_PROFILE(syscall_fchown);
2187 result = fchown(fsp->fh->fd, uid, gid);
2188 END_PROFILE(syscall_fchown);
2189 return result;
2190 #else
2191 errno = ENOSYS;
2192 return -1;
2193 #endif
2196 static int vfswrap_lchown(vfs_handle_struct *handle,
2197 const struct smb_filename *smb_fname,
2198 uid_t uid,
2199 gid_t gid)
2201 int result;
2203 START_PROFILE(syscall_lchown);
2204 result = lchown(smb_fname->base_name, uid, gid);
2205 END_PROFILE(syscall_lchown);
2206 return result;
2209 static int vfswrap_chdir(vfs_handle_struct *handle,
2210 const struct smb_filename *smb_fname)
2212 int result;
2214 START_PROFILE(syscall_chdir);
2215 result = chdir(smb_fname->base_name);
2216 END_PROFILE(syscall_chdir);
2217 return result;
2220 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2221 TALLOC_CTX *ctx)
2223 char *result;
2224 struct smb_filename *smb_fname = NULL;
2226 START_PROFILE(syscall_getwd);
2227 result = sys_getwd();
2228 END_PROFILE(syscall_getwd);
2229 smb_fname = synthetic_smb_fname(ctx,
2230 result,
2231 NULL,
2232 NULL,
2234 if (smb_fname == NULL) {
2235 SAFE_FREE(result);
2237 return smb_fname;
2240 /*********************************************************************
2241 nsec timestamp resolution call. Convert down to whatever the underlying
2242 system will support.
2243 **********************************************************************/
2245 static int vfswrap_ntimes(vfs_handle_struct *handle,
2246 const struct smb_filename *smb_fname,
2247 struct smb_file_time *ft)
2249 int result = -1;
2251 START_PROFILE(syscall_ntimes);
2253 if (smb_fname->stream_name) {
2254 errno = ENOENT;
2255 goto out;
2258 if (ft != NULL) {
2259 if (null_timespec(ft->atime)) {
2260 ft->atime= smb_fname->st.st_ex_atime;
2263 if (null_timespec(ft->mtime)) {
2264 ft->mtime = smb_fname->st.st_ex_mtime;
2267 if (!null_timespec(ft->create_time)) {
2268 set_create_timespec_ea(handle->conn,
2269 smb_fname,
2270 ft->create_time);
2273 if ((timespec_compare(&ft->atime,
2274 &smb_fname->st.st_ex_atime) == 0) &&
2275 (timespec_compare(&ft->mtime,
2276 &smb_fname->st.st_ex_mtime) == 0)) {
2277 return 0;
2281 #if defined(HAVE_UTIMENSAT)
2282 if (ft != NULL) {
2283 struct timespec ts[2];
2284 ts[0] = ft->atime;
2285 ts[1] = ft->mtime;
2286 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2287 } else {
2288 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2290 if (!((result == -1) && (errno == ENOSYS))) {
2291 goto out;
2293 #endif
2294 #if defined(HAVE_UTIMES)
2295 if (ft != NULL) {
2296 struct timeval tv[2];
2297 tv[0] = convert_timespec_to_timeval(ft->atime);
2298 tv[1] = convert_timespec_to_timeval(ft->mtime);
2299 result = utimes(smb_fname->base_name, tv);
2300 } else {
2301 result = utimes(smb_fname->base_name, NULL);
2303 if (!((result == -1) && (errno == ENOSYS))) {
2304 goto out;
2306 #endif
2307 #if defined(HAVE_UTIME)
2308 if (ft != NULL) {
2309 struct utimbuf times;
2310 times.actime = convert_timespec_to_time_t(ft->atime);
2311 times.modtime = convert_timespec_to_time_t(ft->mtime);
2312 result = utime(smb_fname->base_name, &times);
2313 } else {
2314 result = utime(smb_fname->base_name, NULL);
2316 if (!((result == -1) && (errno == ENOSYS))) {
2317 goto out;
2319 #endif
2320 errno = ENOSYS;
2321 result = -1;
2323 out:
2324 END_PROFILE(syscall_ntimes);
2325 return result;
2328 /*********************************************************************
2329 A version of ftruncate that will write the space on disk if strict
2330 allocate is set.
2331 **********************************************************************/
2333 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2335 off_t space_to_write;
2336 uint64_t space_avail;
2337 uint64_t bsize,dfree,dsize;
2338 int ret;
2339 NTSTATUS status;
2340 SMB_STRUCT_STAT *pst;
2342 status = vfs_stat_fsp(fsp);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 return -1;
2346 pst = &fsp->fsp_name->st;
2348 #ifdef S_ISFIFO
2349 if (S_ISFIFO(pst->st_ex_mode))
2350 return 0;
2351 #endif
2353 if (pst->st_ex_size == len)
2354 return 0;
2356 /* Shrink - just ftruncate. */
2357 if (pst->st_ex_size > len)
2358 return ftruncate(fsp->fh->fd, len);
2360 space_to_write = len - pst->st_ex_size;
2362 /* for allocation try fallocate first. This can fail on some
2363 platforms e.g. when the filesystem doesn't support it and no
2364 emulation is being done by the libc (like on AIX with JFS1). In that
2365 case we do our own emulation. fallocate implementations can
2366 return ENOTSUP or EINVAL in cases like that. */
2367 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2368 if (ret == -1 && errno == ENOSPC) {
2369 return -1;
2371 if (ret == 0) {
2372 return 0;
2374 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2375 "error %d. Falling back to slow manual allocation\n", errno));
2377 /* available disk space is enough or not? */
2378 space_avail =
2379 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2380 /* space_avail is 1k blocks */
2381 if (space_avail == (uint64_t)-1 ||
2382 ((uint64_t)space_to_write/1024 > space_avail) ) {
2383 errno = ENOSPC;
2384 return -1;
2387 /* Write out the real space on disk. */
2388 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2389 if (ret != 0) {
2390 return -1;
2393 return 0;
2396 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2398 int result = -1;
2399 SMB_STRUCT_STAT *pst;
2400 NTSTATUS status;
2401 char c = 0;
2403 START_PROFILE(syscall_ftruncate);
2405 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2406 result = strict_allocate_ftruncate(handle, fsp, len);
2407 END_PROFILE(syscall_ftruncate);
2408 return result;
2411 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2412 ftruncate if the system supports it. Then I discovered that
2413 you can have some filesystems that support ftruncate
2414 expansion and some that don't! On Linux fat can't do
2415 ftruncate extend but ext2 can. */
2417 result = ftruncate(fsp->fh->fd, len);
2419 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2420 extend a file with ftruncate. Provide alternate implementation
2421 for this */
2423 /* Do an fstat to see if the file is longer than the requested
2424 size in which case the ftruncate above should have
2425 succeeded or shorter, in which case seek to len - 1 and
2426 write 1 byte of zero */
2427 status = vfs_stat_fsp(fsp);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 goto done;
2432 /* We need to update the files_struct after successful ftruncate */
2433 if (result == 0) {
2434 goto done;
2437 pst = &fsp->fsp_name->st;
2439 #ifdef S_ISFIFO
2440 if (S_ISFIFO(pst->st_ex_mode)) {
2441 result = 0;
2442 goto done;
2444 #endif
2446 if (pst->st_ex_size == len) {
2447 result = 0;
2448 goto done;
2451 if (pst->st_ex_size > len) {
2452 /* the ftruncate should have worked */
2453 goto done;
2456 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2457 goto done;
2460 result = 0;
2462 done:
2464 END_PROFILE(syscall_ftruncate);
2465 return result;
2468 static int vfswrap_fallocate(vfs_handle_struct *handle,
2469 files_struct *fsp,
2470 uint32_t mode,
2471 off_t offset,
2472 off_t len)
2474 int result;
2476 START_PROFILE(syscall_fallocate);
2477 if (mode == 0) {
2478 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2480 * posix_fallocate returns 0 on success, errno on error
2481 * and doesn't set errno. Make it behave like fallocate()
2482 * which returns -1, and sets errno on failure.
2484 if (result != 0) {
2485 errno = result;
2486 result = -1;
2488 } else {
2489 /* sys_fallocate handles filtering of unsupported mode flags */
2490 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2492 END_PROFILE(syscall_fallocate);
2493 return result;
2496 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2498 bool result;
2500 START_PROFILE(syscall_fcntl_lock);
2502 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2503 "smbd",
2504 "force process locks",
2505 false)) {
2506 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2509 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2510 END_PROFILE(syscall_fcntl_lock);
2511 return result;
2514 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2515 uint32_t share_mode, uint32_t access_mask)
2517 START_PROFILE(syscall_kernel_flock);
2518 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2519 END_PROFILE(syscall_kernel_flock);
2520 return 0;
2523 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2525 bool result;
2526 int op = F_GETLK;
2528 START_PROFILE(syscall_fcntl_getlock);
2530 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2531 "smbd",
2532 "force process locks",
2533 false)) {
2534 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2537 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2538 END_PROFILE(syscall_fcntl_getlock);
2539 return result;
2542 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2543 int leasetype)
2545 int result = -1;
2547 START_PROFILE(syscall_linux_setlease);
2549 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2550 result = linux_setlease(fsp->fh->fd, leasetype);
2551 #else
2552 errno = ENOSYS;
2553 #endif
2554 END_PROFILE(syscall_linux_setlease);
2555 return result;
2558 static int vfswrap_symlink(vfs_handle_struct *handle,
2559 const char *link_target,
2560 const struct smb_filename *new_smb_fname)
2562 int result;
2564 START_PROFILE(syscall_symlink);
2565 result = symlink(link_target, new_smb_fname->base_name);
2566 END_PROFILE(syscall_symlink);
2567 return result;
2570 static int vfswrap_readlink(vfs_handle_struct *handle,
2571 const struct smb_filename *smb_fname,
2572 char *buf,
2573 size_t bufsiz)
2575 int result;
2577 START_PROFILE(syscall_readlink);
2578 result = readlink(smb_fname->base_name, buf, bufsiz);
2579 END_PROFILE(syscall_readlink);
2580 return result;
2583 static int vfswrap_link(vfs_handle_struct *handle,
2584 const struct smb_filename *old_smb_fname,
2585 const struct smb_filename *new_smb_fname)
2587 int result;
2589 START_PROFILE(syscall_link);
2590 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2591 END_PROFILE(syscall_link);
2592 return result;
2595 static int vfswrap_mknod(vfs_handle_struct *handle,
2596 const struct smb_filename *smb_fname,
2597 mode_t mode,
2598 SMB_DEV_T dev)
2600 int result;
2602 START_PROFILE(syscall_mknod);
2603 result = sys_mknod(smb_fname->base_name, mode, dev);
2604 END_PROFILE(syscall_mknod);
2605 return result;
2608 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2609 TALLOC_CTX *ctx,
2610 const struct smb_filename *smb_fname)
2612 char *result;
2613 struct smb_filename *result_fname = NULL;
2615 START_PROFILE(syscall_realpath);
2616 result = sys_realpath(smb_fname->base_name);
2617 END_PROFILE(syscall_realpath);
2618 if (result) {
2619 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2620 SAFE_FREE(result);
2622 return result_fname;
2625 static int vfswrap_chflags(vfs_handle_struct *handle,
2626 const struct smb_filename *smb_fname,
2627 unsigned int flags)
2629 #ifdef HAVE_CHFLAGS
2630 return chflags(smb_fname->base_name, flags);
2631 #else
2632 errno = ENOSYS;
2633 return -1;
2634 #endif
2637 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2638 const SMB_STRUCT_STAT *sbuf)
2640 struct file_id key;
2642 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2643 * blob */
2644 ZERO_STRUCT(key);
2646 key.devid = sbuf->st_ex_dev;
2647 key.inode = sbuf->st_ex_ino;
2648 /* key.extid is unused by default. */
2650 return key;
2653 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2654 struct files_struct *fsp,
2655 const struct smb_filename *smb_fname,
2656 TALLOC_CTX *mem_ctx,
2657 unsigned int *pnum_streams,
2658 struct stream_struct **pstreams)
2660 SMB_STRUCT_STAT sbuf;
2661 struct stream_struct *tmp_streams = NULL;
2662 int ret;
2664 if ((fsp != NULL) && (fsp->is_directory)) {
2666 * No default streams on directories
2668 goto done;
2671 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2672 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2674 else {
2675 struct smb_filename smb_fname_cp;
2677 ZERO_STRUCT(smb_fname_cp);
2678 smb_fname_cp.base_name = discard_const_p(char,
2679 smb_fname->base_name);
2680 smb_fname_cp.flags = smb_fname->flags;
2682 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2683 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2684 } else {
2685 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2687 sbuf = smb_fname_cp.st;
2690 if (ret == -1) {
2691 return map_nt_error_from_unix(errno);
2694 if (S_ISDIR(sbuf.st_ex_mode)) {
2695 goto done;
2698 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2699 (*pnum_streams) + 1);
2700 if (tmp_streams == NULL) {
2701 return NT_STATUS_NO_MEMORY;
2703 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2704 if (tmp_streams[*pnum_streams].name == NULL) {
2705 return NT_STATUS_NO_MEMORY;
2707 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2708 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2710 *pnum_streams += 1;
2711 *pstreams = tmp_streams;
2712 done:
2713 return NT_STATUS_OK;
2716 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2717 const char *path,
2718 const char *name,
2719 TALLOC_CTX *mem_ctx,
2720 char **found_name)
2723 * Don't fall back to get_real_filename so callers can differentiate
2724 * between a full directory scan and an actual case-insensitive stat.
2726 errno = EOPNOTSUPP;
2727 return -1;
2730 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2731 const struct smb_filename *smb_fname)
2733 return handle->conn->connectpath;
2736 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2737 struct byte_range_lock *br_lck,
2738 struct lock_struct *plock,
2739 bool blocking_lock)
2741 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2743 /* Note: blr is not used in the default implementation. */
2744 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2747 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2748 struct messaging_context *msg_ctx,
2749 struct byte_range_lock *br_lck,
2750 const struct lock_struct *plock)
2752 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2754 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2757 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2758 struct byte_range_lock *br_lck,
2759 struct lock_struct *plock)
2761 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2763 /* Note: blr is not used in the default implementation. */
2764 return brl_lock_cancel_default(br_lck, plock);
2767 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2768 files_struct *fsp,
2769 struct lock_struct *plock)
2771 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2772 plock->lock_type == WRITE_LOCK);
2774 return strict_lock_check_default(fsp, plock);
2777 /* NT ACL operations. */
2779 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2780 files_struct *fsp,
2781 uint32_t security_info,
2782 TALLOC_CTX *mem_ctx,
2783 struct security_descriptor **ppdesc)
2785 NTSTATUS result;
2787 START_PROFILE(fget_nt_acl);
2788 result = posix_fget_nt_acl(fsp, security_info,
2789 mem_ctx, ppdesc);
2790 END_PROFILE(fget_nt_acl);
2791 return result;
2794 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2795 const struct smb_filename *smb_fname,
2796 uint32_t security_info,
2797 TALLOC_CTX *mem_ctx,
2798 struct security_descriptor **ppdesc)
2800 NTSTATUS result;
2802 START_PROFILE(get_nt_acl);
2803 result = posix_get_nt_acl(handle->conn,
2804 smb_fname,
2805 security_info,
2806 mem_ctx,
2807 ppdesc);
2808 END_PROFILE(get_nt_acl);
2809 return result;
2812 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2814 NTSTATUS result;
2816 START_PROFILE(fset_nt_acl);
2817 result = set_nt_acl(fsp, security_info_sent, psd);
2818 END_PROFILE(fset_nt_acl);
2819 return result;
2822 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2823 struct smb_filename *file,
2824 struct security_acl *sacl,
2825 uint32_t access_requested,
2826 uint32_t access_denied)
2828 return NT_STATUS_OK; /* Nothing to do here ... */
2831 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2832 const struct smb_filename *smb_fname,
2833 mode_t mode)
2835 #ifdef HAVE_NO_ACL
2836 errno = ENOSYS;
2837 return -1;
2838 #else
2839 int result;
2841 START_PROFILE(chmod_acl);
2842 result = chmod_acl(handle->conn, smb_fname, mode);
2843 END_PROFILE(chmod_acl);
2844 return result;
2845 #endif
2848 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2850 #ifdef HAVE_NO_ACL
2851 errno = ENOSYS;
2852 return -1;
2853 #else
2854 int result;
2856 START_PROFILE(fchmod_acl);
2857 result = fchmod_acl(fsp, mode);
2858 END_PROFILE(fchmod_acl);
2859 return result;
2860 #endif
2863 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2864 const struct smb_filename *smb_fname,
2865 SMB_ACL_TYPE_T type,
2866 TALLOC_CTX *mem_ctx)
2868 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2871 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2872 files_struct *fsp,
2873 TALLOC_CTX *mem_ctx)
2875 return sys_acl_get_fd(handle, fsp, mem_ctx);
2878 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2879 const struct smb_filename *smb_fname,
2880 SMB_ACL_TYPE_T acltype,
2881 SMB_ACL_T theacl)
2883 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2886 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2888 return sys_acl_set_fd(handle, fsp, theacl);
2891 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2892 const struct smb_filename *smb_fname)
2894 return sys_acl_delete_def_file(handle, smb_fname);
2897 /****************************************************************
2898 Extended attribute operations.
2899 *****************************************************************/
2901 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2902 const struct smb_filename *smb_fname,
2903 const char *name,
2904 void *value,
2905 size_t size)
2907 return getxattr(smb_fname->base_name, name, value, size);
2910 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2912 return fgetxattr(fsp->fh->fd, name, value, size);
2915 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2916 const struct smb_filename *smb_fname,
2917 char *list,
2918 size_t size)
2920 return listxattr(smb_fname->base_name, list, size);
2923 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2925 return flistxattr(fsp->fh->fd, list, size);
2928 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2929 const struct smb_filename *smb_fname,
2930 const char *name)
2932 return removexattr(smb_fname->base_name, name);
2935 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2937 return fremovexattr(fsp->fh->fd, name);
2940 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2941 const struct smb_filename *smb_fname,
2942 const char *name,
2943 const void *value,
2944 size_t size,
2945 int flags)
2947 return setxattr(smb_fname->base_name, name, value, size, flags);
2950 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2952 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2955 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2957 return false;
2960 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2961 const struct smb_filename *fname,
2962 SMB_STRUCT_STAT *sbuf)
2964 NTSTATUS status;
2965 char *path;
2966 bool offline = false;
2968 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2969 return false;
2972 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2973 #if defined(ENOTSUP)
2974 errno = ENOTSUP;
2975 #endif
2976 return false;
2979 status = get_full_smb_filename(talloc_tos(), fname, &path);
2980 if (!NT_STATUS_IS_OK(status)) {
2981 errno = map_errno_from_nt_status(status);
2982 return false;
2985 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2987 TALLOC_FREE(path);
2989 return offline;
2992 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2993 struct files_struct *fsp,
2994 TALLOC_CTX *mem_ctx,
2995 DATA_BLOB *cookie)
2997 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3000 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3001 struct files_struct *fsp,
3002 const DATA_BLOB old_cookie,
3003 TALLOC_CTX *mem_ctx,
3004 DATA_BLOB *new_cookie)
3006 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3007 new_cookie);
3010 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3011 struct smb_request *smb1req,
3012 struct smbXsrv_open *op,
3013 const DATA_BLOB old_cookie,
3014 TALLOC_CTX *mem_ctx,
3015 struct files_struct **fsp,
3016 DATA_BLOB *new_cookie)
3018 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3019 old_cookie, mem_ctx,
3020 fsp, new_cookie);
3023 static struct vfs_fn_pointers vfs_default_fns = {
3024 /* Disk operations */
3026 .connect_fn = vfswrap_connect,
3027 .disconnect_fn = vfswrap_disconnect,
3028 .disk_free_fn = vfswrap_disk_free,
3029 .get_quota_fn = vfswrap_get_quota,
3030 .set_quota_fn = vfswrap_set_quota,
3031 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3032 .statvfs_fn = vfswrap_statvfs,
3033 .fs_capabilities_fn = vfswrap_fs_capabilities,
3034 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3035 .snap_check_path_fn = vfswrap_snap_check_path,
3036 .snap_create_fn = vfswrap_snap_create,
3037 .snap_delete_fn = vfswrap_snap_delete,
3039 /* Directory operations */
3041 .opendir_fn = vfswrap_opendir,
3042 .fdopendir_fn = vfswrap_fdopendir,
3043 .readdir_fn = vfswrap_readdir,
3044 .readdir_attr_fn = vfswrap_readdir_attr,
3045 .seekdir_fn = vfswrap_seekdir,
3046 .telldir_fn = vfswrap_telldir,
3047 .rewind_dir_fn = vfswrap_rewinddir,
3048 .mkdir_fn = vfswrap_mkdir,
3049 .rmdir_fn = vfswrap_rmdir,
3050 .closedir_fn = vfswrap_closedir,
3051 .init_search_op_fn = vfswrap_init_search_op,
3053 /* File operations */
3055 .open_fn = vfswrap_open,
3056 .create_file_fn = vfswrap_create_file,
3057 .close_fn = vfswrap_close,
3058 .read_fn = vfswrap_read,
3059 .pread_fn = vfswrap_pread,
3060 .pread_send_fn = vfswrap_pread_send,
3061 .pread_recv_fn = vfswrap_pread_recv,
3062 .write_fn = vfswrap_write,
3063 .pwrite_fn = vfswrap_pwrite,
3064 .pwrite_send_fn = vfswrap_pwrite_send,
3065 .pwrite_recv_fn = vfswrap_pwrite_recv,
3066 .lseek_fn = vfswrap_lseek,
3067 .sendfile_fn = vfswrap_sendfile,
3068 .recvfile_fn = vfswrap_recvfile,
3069 .rename_fn = vfswrap_rename,
3070 .fsync_fn = vfswrap_fsync,
3071 .fsync_send_fn = vfswrap_fsync_send,
3072 .fsync_recv_fn = vfswrap_fsync_recv,
3073 .stat_fn = vfswrap_stat,
3074 .fstat_fn = vfswrap_fstat,
3075 .lstat_fn = vfswrap_lstat,
3076 .get_alloc_size_fn = vfswrap_get_alloc_size,
3077 .unlink_fn = vfswrap_unlink,
3078 .chmod_fn = vfswrap_chmod,
3079 .fchmod_fn = vfswrap_fchmod,
3080 .chown_fn = vfswrap_chown,
3081 .fchown_fn = vfswrap_fchown,
3082 .lchown_fn = vfswrap_lchown,
3083 .chdir_fn = vfswrap_chdir,
3084 .getwd_fn = vfswrap_getwd,
3085 .ntimes_fn = vfswrap_ntimes,
3086 .ftruncate_fn = vfswrap_ftruncate,
3087 .fallocate_fn = vfswrap_fallocate,
3088 .lock_fn = vfswrap_lock,
3089 .kernel_flock_fn = vfswrap_kernel_flock,
3090 .linux_setlease_fn = vfswrap_linux_setlease,
3091 .getlock_fn = vfswrap_getlock,
3092 .symlink_fn = vfswrap_symlink,
3093 .readlink_fn = vfswrap_readlink,
3094 .link_fn = vfswrap_link,
3095 .mknod_fn = vfswrap_mknod,
3096 .realpath_fn = vfswrap_realpath,
3097 .chflags_fn = vfswrap_chflags,
3098 .file_id_create_fn = vfswrap_file_id_create,
3099 .streaminfo_fn = vfswrap_streaminfo,
3100 .get_real_filename_fn = vfswrap_get_real_filename,
3101 .connectpath_fn = vfswrap_connectpath,
3102 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3103 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3104 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3105 .strict_lock_check_fn = vfswrap_strict_lock_check,
3106 .translate_name_fn = vfswrap_translate_name,
3107 .fsctl_fn = vfswrap_fsctl,
3108 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3109 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3110 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3111 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3112 .offload_read_send_fn = vfswrap_offload_read_send,
3113 .offload_read_recv_fn = vfswrap_offload_read_recv,
3114 .offload_write_send_fn = vfswrap_offload_write_send,
3115 .offload_write_recv_fn = vfswrap_offload_write_recv,
3116 .get_compression_fn = vfswrap_get_compression,
3117 .set_compression_fn = vfswrap_set_compression,
3119 /* NT ACL operations. */
3121 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3122 .get_nt_acl_fn = vfswrap_get_nt_acl,
3123 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3124 .audit_file_fn = vfswrap_audit_file,
3126 /* POSIX ACL operations. */
3128 .chmod_acl_fn = vfswrap_chmod_acl,
3129 .fchmod_acl_fn = vfswrap_fchmod_acl,
3131 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3132 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3133 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3134 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3135 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3136 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3137 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3139 /* EA operations. */
3140 .getxattr_fn = vfswrap_getxattr,
3141 .fgetxattr_fn = vfswrap_fgetxattr,
3142 .listxattr_fn = vfswrap_listxattr,
3143 .flistxattr_fn = vfswrap_flistxattr,
3144 .removexattr_fn = vfswrap_removexattr,
3145 .fremovexattr_fn = vfswrap_fremovexattr,
3146 .setxattr_fn = vfswrap_setxattr,
3147 .fsetxattr_fn = vfswrap_fsetxattr,
3149 /* aio operations */
3150 .aio_force_fn = vfswrap_aio_force,
3152 /* durable handle operations */
3153 .durable_cookie_fn = vfswrap_durable_cookie,
3154 .durable_disconnect_fn = vfswrap_durable_disconnect,
3155 .durable_reconnect_fn = vfswrap_durable_reconnect,
3158 NTSTATUS vfs_default_init(TALLOC_CTX *);
3159 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3161 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3162 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);