libads: abstract out SASL wrapping code
[Samba.git] / source3 / modules / vfs_default.c
blobfa89f7f255147c2a9ace76ebbd90be02c4f9afac
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"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
45 this possibility. */
47 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct *handle)
56 /* Disk operations */
58 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
59 uint64_t *bsize, uint64_t *dfree,
60 uint64_t *dsize)
62 if (sys_fsusage(path, dfree, dsize) != 0) {
63 return (uint64_t)-1;
66 *bsize = 512;
67 return *dfree / 2;
70 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
71 enum SMB_QUOTA_TYPE qtype, unid_t id,
72 SMB_DISK_QUOTA *qt)
74 #ifdef HAVE_SYS_QUOTAS
75 int result;
77 START_PROFILE(syscall_get_quota);
78 result = sys_get_quota(path, qtype, id, qt);
79 END_PROFILE(syscall_get_quota);
80 return result;
81 #else
82 errno = ENOSYS;
83 return -1;
84 #endif
87 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
89 #ifdef HAVE_SYS_QUOTAS
90 int result;
92 START_PROFILE(syscall_set_quota);
93 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
94 END_PROFILE(syscall_set_quota);
95 return result;
96 #else
97 errno = ENOSYS;
98 return -1;
99 #endif
102 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
103 struct files_struct *fsp,
104 struct shadow_copy_data *shadow_copy_data,
105 bool labels)
107 errno = ENOSYS;
108 return -1; /* Not implemented. */
111 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
113 return sys_statvfs(path, statbuf);
116 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
117 enum timestamp_set_resolution *p_ts_res)
119 connection_struct *conn = handle->conn;
120 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
121 struct smb_filename *smb_fname_cpath = NULL;
122 struct vfs_statvfs_struct statbuf;
123 int ret;
125 ZERO_STRUCT(statbuf);
126 ret = sys_statvfs(conn->connectpath, &statbuf);
127 if (ret == 0) {
128 caps = statbuf.FsCapabilities;
131 *p_ts_res = TIMESTAMP_SET_SECONDS;
133 /* Work out what timestamp resolution we can
134 * use when setting a timestamp. */
136 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 NULL, NULL, 0);
138 if (smb_fname_cpath == NULL) {
139 return caps;
142 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 if (ret == -1) {
144 TALLOC_FREE(smb_fname_cpath);
145 return caps;
148 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
150 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
151 /* If any of the normal UNIX directory timestamps
152 * have a non-zero tv_nsec component assume
153 * we might be able to set sub-second timestamps.
154 * See what filetime set primitives we have.
156 #if defined(HAVE_UTIMENSAT)
157 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
158 #elif defined(HAVE_UTIMES)
159 /* utimes allows msec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_MSEC;
161 #elif defined(HAVE_UTIME)
162 /* utime only allows sec timestamps to be set. */
163 *p_ts_res = TIMESTAMP_SET_SECONDS;
164 #endif
166 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "resolution of %s "
168 "available on share %s, directory %s\n",
169 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
170 lp_servicename(talloc_tos(), conn->params->service),
171 conn->connectpath ));
173 TALLOC_FREE(smb_fname_cpath);
174 return caps;
177 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
178 struct dfs_GetDFSReferral *r)
180 struct junction_map *junction = NULL;
181 int consumedcnt = 0;
182 bool self_referral = false;
183 char *pathnamep = NULL;
184 char *local_dfs_path = NULL;
185 NTSTATUS status;
186 int i;
187 uint16_t max_referral_level = r->in.req.max_referral_level;
189 if (DEBUGLVL(10)) {
190 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
193 /* get the junction entry */
194 if (r->in.req.servername == NULL) {
195 return NT_STATUS_NOT_FOUND;
199 * Trim pathname sent by client so it begins with only one backslash.
200 * Two backslashes confuse some dfs clients
203 local_dfs_path = talloc_strdup(r, r->in.req.servername);
204 if (local_dfs_path == NULL) {
205 return NT_STATUS_NO_MEMORY;
207 pathnamep = local_dfs_path;
208 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
209 IS_DIRECTORY_SEP(pathnamep[1])) {
210 pathnamep++;
213 junction = talloc_zero(r, struct junction_map);
214 if (junction == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 /* The following call can change cwd. */
219 status = get_referred_path(r, pathnamep,
220 !handle->conn->sconn->using_smb2,
221 junction, &consumedcnt, &self_referral);
222 if (!NT_STATUS_IS_OK(status)) {
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
224 return status;
226 vfs_ChDir(handle->conn, handle->conn->connectpath);
228 if (!self_referral) {
229 pathnamep[consumedcnt] = '\0';
231 if (DEBUGLVL(3)) {
232 dbgtext("Path %s to alternate path(s):",
233 pathnamep);
234 for (i=0; i < junction->referral_count; i++) {
235 dbgtext(" %s",
236 junction->referral_list[i].alternate_path);
238 dbgtext(".\n");
242 if (r->in.req.max_referral_level <= 2) {
243 max_referral_level = 2;
245 if (r->in.req.max_referral_level >= 3) {
246 max_referral_level = 3;
249 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
250 if (r->out.resp == NULL) {
251 return NT_STATUS_NO_MEMORY;
254 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
255 r->out.resp->nb_referrals = junction->referral_count;
257 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 if (self_referral) {
259 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
262 r->out.resp->referral_entries = talloc_zero_array(r,
263 struct dfs_referral_type,
264 r->out.resp->nb_referrals);
265 if (r->out.resp->referral_entries == NULL) {
266 return NT_STATUS_NO_MEMORY;
269 switch (max_referral_level) {
270 case 2:
271 for(i=0; i < junction->referral_count; i++) {
272 struct referral *ref = &junction->referral_list[i];
273 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
274 struct dfs_referral_type *t =
275 &r->out.resp->referral_entries[i];
276 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 t->version = 2;
279 v2->size = VERSION2_REFERRAL_SIZE;
280 if (self_referral) {
281 v2->server_type = DFS_SERVER_ROOT;
282 } else {
283 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->entry_flags = 0;
286 v2->proximity = ref->proximity;
287 v2->ttl = ref->ttl;
288 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
289 if (v2->DFS_path == NULL) {
290 return NT_STATUS_NO_MEMORY;
292 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
293 if (v2->DFS_alt_path == NULL) {
294 return NT_STATUS_NO_MEMORY;
296 v2->netw_address = talloc_strdup(mem_ctx,
297 ref->alternate_path);
298 if (v2->netw_address == NULL) {
299 return NT_STATUS_NO_MEMORY;
303 break;
304 case 3:
305 for(i=0; i < junction->referral_count; i++) {
306 struct referral *ref = &junction->referral_list[i];
307 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
308 struct dfs_referral_type *t =
309 &r->out.resp->referral_entries[i];
310 struct dfs_referral_v3 *v3 = &t->referral.v3;
311 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 t->version = 3;
314 v3->size = VERSION3_REFERRAL_SIZE;
315 if (self_referral) {
316 v3->server_type = DFS_SERVER_ROOT;
317 } else {
318 v3->server_type = DFS_SERVER_NON_ROOT;
320 v3->entry_flags = 0;
321 v3->ttl = ref->ttl;
322 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
323 if (r1->DFS_path == NULL) {
324 return NT_STATUS_NO_MEMORY;
326 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
327 if (r1->DFS_alt_path == NULL) {
328 return NT_STATUS_NO_MEMORY;
330 r1->netw_address = talloc_strdup(mem_ctx,
331 ref->alternate_path);
332 if (r1->netw_address == NULL) {
333 return NT_STATUS_NO_MEMORY;
336 break;
337 default:
338 DEBUG(0,("Invalid dfs referral version: %d\n",
339 max_referral_level));
340 return NT_STATUS_INVALID_LEVEL;
343 if (DEBUGLVL(10)) {
344 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
347 return NT_STATUS_OK;
350 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 TALLOC_CTX *mem_ctx,
352 const char *service_path,
353 char **base_volume)
355 return NT_STATUS_NOT_SUPPORTED;
358 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 TALLOC_CTX *mem_ctx,
360 const char *base_volume,
361 time_t *tstamp,
362 bool rw,
363 char **base_path,
364 char **snap_path)
366 return NT_STATUS_NOT_SUPPORTED;
369 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
370 TALLOC_CTX *mem_ctx,
371 char *base_path,
372 char *snap_path)
374 return NT_STATUS_NOT_SUPPORTED;
377 /* Directory operations */
379 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
380 const struct smb_filename *smb_fname,
381 const char *mask,
382 uint32_t attr)
384 DIR *result;
386 START_PROFILE(syscall_opendir);
387 result = opendir(smb_fname->base_name);
388 END_PROFILE(syscall_opendir);
389 return result;
392 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
393 files_struct *fsp,
394 const char *mask,
395 uint32_t attr)
397 DIR *result;
399 START_PROFILE(syscall_fdopendir);
400 result = sys_fdopendir(fsp->fh->fd);
401 END_PROFILE(syscall_fdopendir);
402 return result;
406 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
407 DIR *dirp,
408 SMB_STRUCT_STAT *sbuf)
410 struct dirent *result;
412 START_PROFILE(syscall_readdir);
413 result = readdir(dirp);
414 END_PROFILE(syscall_readdir);
415 if (sbuf) {
416 /* Default Posix readdir() does not give us stat info.
417 * Set to invalid to indicate we didn't return this info. */
418 SET_STAT_INVALID(*sbuf);
419 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
420 if (result != NULL) {
421 /* See if we can efficiently return this. */
422 struct stat st;
423 int flags = AT_SYMLINK_NOFOLLOW;
424 int ret = fstatat(dirfd(dirp),
425 result->d_name,
426 &st,
427 flags);
429 * As this is an optimization,
430 * ignore it if we stat'ed a
431 * symlink. Make the caller
432 * do it again as we don't
433 * know if they wanted the link
434 * info, or its target info.
436 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
437 init_stat_ex_from_stat(sbuf,
438 &st,
439 lp_fake_directory_create_times(
440 SNUM(handle->conn)));
443 #endif
445 return result;
448 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
449 const struct smb_filename *fname,
450 TALLOC_CTX *mem_ctx,
451 struct readdir_attr_data **attr_data)
453 return NT_STATUS_NOT_SUPPORTED;
456 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
458 START_PROFILE(syscall_seekdir);
459 seekdir(dirp, offset);
460 END_PROFILE(syscall_seekdir);
463 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
465 long result;
466 START_PROFILE(syscall_telldir);
467 result = telldir(dirp);
468 END_PROFILE(syscall_telldir);
469 return result;
472 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
474 START_PROFILE(syscall_rewinddir);
475 rewinddir(dirp);
476 END_PROFILE(syscall_rewinddir);
479 static int vfswrap_mkdir(vfs_handle_struct *handle,
480 const struct smb_filename *smb_fname,
481 mode_t mode)
483 int result;
484 bool has_dacl = False;
485 const char *path = smb_fname->base_name;
486 char *parent = NULL;
488 START_PROFILE(syscall_mkdir);
490 if (lp_inherit_acls(SNUM(handle->conn))
491 && parent_dirname(talloc_tos(), path, &parent, NULL)
492 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
493 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
496 TALLOC_FREE(parent);
498 result = mkdir(path, mode);
500 if (result == 0 && !has_dacl) {
502 * We need to do this as the default behavior of POSIX ACLs
503 * is to set the mask to be the requested group permission
504 * bits, not the group permission bits to be the requested
505 * group permission bits. This is not what we want, as it will
506 * mess up any inherited ACL bits that were set. JRA.
508 int saved_errno = errno; /* We may get ENOSYS */
509 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
510 (errno == ENOSYS)) {
511 errno = saved_errno;
515 END_PROFILE(syscall_mkdir);
516 return result;
519 static int vfswrap_rmdir(vfs_handle_struct *handle,
520 const struct smb_filename *smb_fname)
522 int result;
524 START_PROFILE(syscall_rmdir);
525 result = rmdir(smb_fname->base_name);
526 END_PROFILE(syscall_rmdir);
527 return result;
530 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
532 int result;
534 START_PROFILE(syscall_closedir);
535 result = closedir(dirp);
536 END_PROFILE(syscall_closedir);
537 return result;
540 static void vfswrap_init_search_op(vfs_handle_struct *handle,
541 DIR *dirp)
543 /* Default behavior is a NOOP */
546 /* File operations */
548 static int vfswrap_open(vfs_handle_struct *handle,
549 struct smb_filename *smb_fname,
550 files_struct *fsp, int flags, mode_t mode)
552 int result = -1;
554 START_PROFILE(syscall_open);
556 if (smb_fname->stream_name) {
557 errno = ENOENT;
558 goto out;
561 result = open(smb_fname->base_name, flags, mode);
562 out:
563 END_PROFILE(syscall_open);
564 return result;
567 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
568 struct smb_request *req,
569 uint16_t root_dir_fid,
570 struct smb_filename *smb_fname,
571 uint32_t access_mask,
572 uint32_t share_access,
573 uint32_t create_disposition,
574 uint32_t create_options,
575 uint32_t file_attributes,
576 uint32_t oplock_request,
577 struct smb2_lease *lease,
578 uint64_t allocation_size,
579 uint32_t private_flags,
580 struct security_descriptor *sd,
581 struct ea_list *ea_list,
582 files_struct **result,
583 int *pinfo,
584 const struct smb2_create_blobs *in_context_blobs,
585 struct smb2_create_blobs *out_context_blobs)
587 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
588 access_mask, share_access,
589 create_disposition, create_options,
590 file_attributes, oplock_request, lease,
591 allocation_size, private_flags,
592 sd, ea_list, result,
593 pinfo, in_context_blobs, out_context_blobs);
596 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
598 int result;
600 START_PROFILE(syscall_close);
601 result = fd_close_posix(fsp);
602 END_PROFILE(syscall_close);
603 return result;
606 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
608 ssize_t result;
610 START_PROFILE_BYTES(syscall_read, n);
611 result = sys_read(fsp->fh->fd, data, n);
612 END_PROFILE_BYTES(syscall_read);
613 return result;
616 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
617 size_t n, off_t offset)
619 ssize_t result;
621 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
622 START_PROFILE_BYTES(syscall_pread, n);
623 result = sys_pread(fsp->fh->fd, data, n, offset);
624 END_PROFILE_BYTES(syscall_pread);
626 if (result == -1 && errno == ESPIPE) {
627 /* Maintain the fiction that pipes can be seeked (sought?) on. */
628 result = SMB_VFS_READ(fsp, data, n);
629 fsp->fh->pos = 0;
632 #else /* HAVE_PREAD */
633 off_t curr;
634 int lerrno;
636 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
637 if (curr == -1 && errno == ESPIPE) {
638 /* Maintain the fiction that pipes can be seeked (sought?) on. */
639 result = SMB_VFS_READ(fsp, data, n);
640 fsp->fh->pos = 0;
641 return result;
644 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
645 return -1;
648 errno = 0;
649 result = SMB_VFS_READ(fsp, data, n);
650 lerrno = errno;
652 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
653 errno = lerrno;
655 #endif /* HAVE_PREAD */
657 return result;
660 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
662 ssize_t result;
664 START_PROFILE_BYTES(syscall_write, n);
665 result = sys_write(fsp->fh->fd, data, n);
666 END_PROFILE_BYTES(syscall_write);
667 return result;
670 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
671 size_t n, off_t offset)
673 ssize_t result;
675 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
676 START_PROFILE_BYTES(syscall_pwrite, n);
677 result = sys_pwrite(fsp->fh->fd, data, n, offset);
678 END_PROFILE_BYTES(syscall_pwrite);
680 if (result == -1 && errno == ESPIPE) {
681 /* Maintain the fiction that pipes can be sought on. */
682 result = SMB_VFS_WRITE(fsp, data, n);
685 #else /* HAVE_PWRITE */
686 off_t curr;
687 int lerrno;
689 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
690 if (curr == -1) {
691 return -1;
694 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
695 return -1;
698 result = SMB_VFS_WRITE(fsp, data, n);
699 lerrno = errno;
701 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
702 errno = lerrno;
704 #endif /* HAVE_PWRITE */
706 return result;
709 static int vfswrap_init_pool(struct smbd_server_connection *conn)
711 int ret;
713 if (conn->pool != NULL) {
714 return 0;
717 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
718 &conn->pool);
719 return ret;
722 struct vfswrap_pread_state {
723 ssize_t ret;
724 int err;
725 int fd;
726 void *buf;
727 size_t count;
728 off_t offset;
730 struct vfs_aio_state vfs_aio_state;
731 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
734 static void vfs_pread_do(void *private_data);
735 static void vfs_pread_done(struct tevent_req *subreq);
737 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
738 TALLOC_CTX *mem_ctx,
739 struct tevent_context *ev,
740 struct files_struct *fsp,
741 void *data,
742 size_t n, off_t offset)
744 struct tevent_req *req, *subreq;
745 struct vfswrap_pread_state *state;
746 int ret;
748 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
749 if (req == NULL) {
750 return NULL;
753 ret = vfswrap_init_pool(handle->conn->sconn);
754 if (tevent_req_error(req, ret)) {
755 return tevent_req_post(req, ev);
758 state->ret = -1;
759 state->fd = fsp->fh->fd;
760 state->buf = data;
761 state->count = n;
762 state->offset = offset;
764 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
765 state->profile_bytes, n);
766 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
768 subreq = pthreadpool_tevent_job_send(
769 state, ev, handle->conn->sconn->pool,
770 vfs_pread_do, state);
771 if (tevent_req_nomem(subreq, req)) {
772 return tevent_req_post(req, ev);
774 tevent_req_set_callback(subreq, vfs_pread_done, req);
776 return req;
779 static void vfs_pread_do(void *private_data)
781 struct vfswrap_pread_state *state = talloc_get_type_abort(
782 private_data, struct vfswrap_pread_state);
783 struct timespec start_time;
784 struct timespec end_time;
786 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
788 PROFILE_TIMESTAMP(&start_time);
790 do {
791 state->ret = pread(state->fd, state->buf, state->count,
792 state->offset);
793 } while ((state->ret == -1) && (errno == EINTR));
795 state->err = errno;
797 PROFILE_TIMESTAMP(&end_time);
799 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
801 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
804 static void vfs_pread_done(struct tevent_req *subreq)
806 struct tevent_req *req = tevent_req_callback_data(
807 subreq, struct tevent_req);
808 #ifdef WITH_PROFILE
809 struct vfswrap_pread_state *state = tevent_req_data(
810 req, struct vfswrap_pread_state);
811 #endif
812 int ret;
814 ret = pthreadpool_tevent_job_recv(subreq);
815 TALLOC_FREE(subreq);
816 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
817 if (tevent_req_error(req, ret)) {
818 return;
821 tevent_req_done(req);
824 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
825 struct vfs_aio_state *vfs_aio_state)
827 struct vfswrap_pread_state *state = tevent_req_data(
828 req, struct vfswrap_pread_state);
830 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
831 return -1;
834 *vfs_aio_state = state->vfs_aio_state;
835 return state->ret;
838 struct vfswrap_pwrite_state {
839 ssize_t ret;
840 int err;
841 int fd;
842 const void *buf;
843 size_t count;
844 off_t offset;
846 struct vfs_aio_state vfs_aio_state;
847 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
850 static void vfs_pwrite_do(void *private_data);
851 static void vfs_pwrite_done(struct tevent_req *subreq);
853 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
854 TALLOC_CTX *mem_ctx,
855 struct tevent_context *ev,
856 struct files_struct *fsp,
857 const void *data,
858 size_t n, off_t offset)
860 struct tevent_req *req, *subreq;
861 struct vfswrap_pwrite_state *state;
862 int ret;
864 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
865 if (req == NULL) {
866 return NULL;
869 ret = vfswrap_init_pool(handle->conn->sconn);
870 if (tevent_req_error(req, ret)) {
871 return tevent_req_post(req, ev);
874 state->ret = -1;
875 state->fd = fsp->fh->fd;
876 state->buf = data;
877 state->count = n;
878 state->offset = offset;
880 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
881 state->profile_bytes, n);
882 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
884 subreq = pthreadpool_tevent_job_send(
885 state, ev, handle->conn->sconn->pool,
886 vfs_pwrite_do, state);
887 if (tevent_req_nomem(subreq, req)) {
888 return tevent_req_post(req, ev);
890 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
892 return req;
895 static void vfs_pwrite_do(void *private_data)
897 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
898 private_data, struct vfswrap_pwrite_state);
899 struct timespec start_time;
900 struct timespec end_time;
902 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
904 PROFILE_TIMESTAMP(&start_time);
906 do {
907 state->ret = pwrite(state->fd, state->buf, state->count,
908 state->offset);
909 } while ((state->ret == -1) && (errno == EINTR));
911 state->err = errno;
913 PROFILE_TIMESTAMP(&end_time);
915 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
917 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
920 static void vfs_pwrite_done(struct tevent_req *subreq)
922 struct tevent_req *req = tevent_req_callback_data(
923 subreq, struct tevent_req);
924 #ifdef WITH_PROFILE
925 struct vfswrap_pwrite_state *state = tevent_req_data(
926 req, struct vfswrap_pwrite_state);
927 #endif
928 int ret;
930 ret = pthreadpool_tevent_job_recv(subreq);
931 TALLOC_FREE(subreq);
932 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
933 if (tevent_req_error(req, ret)) {
934 return;
937 tevent_req_done(req);
940 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
941 struct vfs_aio_state *vfs_aio_state)
943 struct vfswrap_pwrite_state *state = tevent_req_data(
944 req, struct vfswrap_pwrite_state);
946 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
947 return -1;
950 *vfs_aio_state = state->vfs_aio_state;
951 return state->ret;
954 struct vfswrap_fsync_state {
955 ssize_t ret;
956 int err;
957 int fd;
959 struct vfs_aio_state vfs_aio_state;
960 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
963 static void vfs_fsync_do(void *private_data);
964 static void vfs_fsync_done(struct tevent_req *subreq);
966 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
967 TALLOC_CTX *mem_ctx,
968 struct tevent_context *ev,
969 struct files_struct *fsp)
971 struct tevent_req *req, *subreq;
972 struct vfswrap_fsync_state *state;
973 int ret;
975 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
976 if (req == NULL) {
977 return NULL;
980 ret = vfswrap_init_pool(handle->conn->sconn);
981 if (tevent_req_error(req, ret)) {
982 return tevent_req_post(req, ev);
985 state->ret = -1;
986 state->fd = fsp->fh->fd;
988 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
989 state->profile_basic);
991 subreq = pthreadpool_tevent_job_send(
992 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
993 if (tevent_req_nomem(subreq, req)) {
994 return tevent_req_post(req, ev);
996 tevent_req_set_callback(subreq, vfs_fsync_done, req);
998 return req;
1001 static void vfs_fsync_do(void *private_data)
1003 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1004 private_data, struct vfswrap_fsync_state);
1005 struct timespec start_time;
1006 struct timespec end_time;
1008 PROFILE_TIMESTAMP(&start_time);
1010 do {
1011 state->ret = fsync(state->fd);
1012 } while ((state->ret == -1) && (errno == EINTR));
1014 state->err = errno;
1016 PROFILE_TIMESTAMP(&end_time);
1018 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1021 static void vfs_fsync_done(struct tevent_req *subreq)
1023 struct tevent_req *req = tevent_req_callback_data(
1024 subreq, struct tevent_req);
1025 #ifdef WITH_PROFILE
1026 struct vfswrap_fsync_state *state = tevent_req_data(
1027 req, struct vfswrap_fsync_state);
1028 #endif
1029 int ret;
1031 ret = pthreadpool_tevent_job_recv(subreq);
1032 TALLOC_FREE(subreq);
1033 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1034 if (tevent_req_error(req, ret)) {
1035 return;
1038 tevent_req_done(req);
1041 static int vfswrap_fsync_recv(struct tevent_req *req,
1042 struct vfs_aio_state *vfs_aio_state)
1044 struct vfswrap_fsync_state *state = tevent_req_data(
1045 req, struct vfswrap_fsync_state);
1047 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1048 return -1;
1051 *vfs_aio_state = state->vfs_aio_state;
1052 return state->ret;
1055 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1057 off_t result = 0;
1059 START_PROFILE(syscall_lseek);
1061 /* Cope with 'stat' file opens. */
1062 if (fsp->fh->fd != -1)
1063 result = lseek(fsp->fh->fd, offset, whence);
1066 * We want to maintain the fiction that we can seek
1067 * on a fifo for file system purposes. This allows
1068 * people to set up UNIX fifo's that feed data to Windows
1069 * applications. JRA.
1072 if((result == -1) && (errno == ESPIPE)) {
1073 result = 0;
1074 errno = 0;
1077 END_PROFILE(syscall_lseek);
1078 return result;
1081 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1082 off_t offset, size_t n)
1084 ssize_t result;
1086 START_PROFILE_BYTES(syscall_sendfile, n);
1087 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1088 END_PROFILE_BYTES(syscall_sendfile);
1089 return result;
1092 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1093 int fromfd,
1094 files_struct *tofsp,
1095 off_t offset,
1096 size_t n)
1098 ssize_t result;
1100 START_PROFILE_BYTES(syscall_recvfile, n);
1101 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1102 END_PROFILE_BYTES(syscall_recvfile);
1103 return result;
1106 static int vfswrap_rename(vfs_handle_struct *handle,
1107 const struct smb_filename *smb_fname_src,
1108 const struct smb_filename *smb_fname_dst)
1110 int result = -1;
1112 START_PROFILE(syscall_rename);
1114 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1115 errno = ENOENT;
1116 goto out;
1119 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1121 out:
1122 END_PROFILE(syscall_rename);
1123 return result;
1126 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1128 #ifdef HAVE_FSYNC
1129 int result;
1131 START_PROFILE(syscall_fsync);
1132 result = fsync(fsp->fh->fd);
1133 END_PROFILE(syscall_fsync);
1134 return result;
1135 #else
1136 return 0;
1137 #endif
1140 static int vfswrap_stat(vfs_handle_struct *handle,
1141 struct smb_filename *smb_fname)
1143 int result = -1;
1145 START_PROFILE(syscall_stat);
1147 if (smb_fname->stream_name) {
1148 errno = ENOENT;
1149 goto out;
1152 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1153 lp_fake_directory_create_times(SNUM(handle->conn)));
1154 out:
1155 END_PROFILE(syscall_stat);
1156 return result;
1159 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1161 int result;
1163 START_PROFILE(syscall_fstat);
1164 result = sys_fstat(fsp->fh->fd,
1165 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1166 END_PROFILE(syscall_fstat);
1167 return result;
1170 static int vfswrap_lstat(vfs_handle_struct *handle,
1171 struct smb_filename *smb_fname)
1173 int result = -1;
1175 START_PROFILE(syscall_lstat);
1177 if (smb_fname->stream_name) {
1178 errno = ENOENT;
1179 goto out;
1182 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1183 lp_fake_directory_create_times(SNUM(handle->conn)));
1184 out:
1185 END_PROFILE(syscall_lstat);
1186 return result;
1189 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1190 const char *name,
1191 enum vfs_translate_direction direction,
1192 TALLOC_CTX *mem_ctx,
1193 char **mapped_name)
1195 return NT_STATUS_NONE_MAPPED;
1199 * Implement the default fsctl operation.
1201 static bool vfswrap_logged_ioctl_message = false;
1203 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1204 struct files_struct *fsp,
1205 TALLOC_CTX *ctx,
1206 uint32_t function,
1207 uint16_t req_flags, /* Needed for UNICODE ... */
1208 const uint8_t *_in_data,
1209 uint32_t in_len,
1210 uint8_t **_out_data,
1211 uint32_t max_out_len,
1212 uint32_t *out_len)
1214 const char *in_data = (const char *)_in_data;
1215 char **out_data = (char **)_out_data;
1216 NTSTATUS status;
1218 switch (function) {
1219 case FSCTL_SET_SPARSE:
1221 bool set_sparse = true;
1223 if (in_len >= 1 && in_data[0] == 0) {
1224 set_sparse = false;
1227 status = file_set_sparse(handle->conn, fsp, set_sparse);
1229 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1230 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1231 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1232 nt_errstr(status)));
1234 return status;
1237 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1239 unsigned char objid[16];
1240 char *return_data = NULL;
1242 /* This should return the object-id on this file.
1243 * I think I'll make this be the inode+dev. JRA.
1246 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1247 fsp_fnum_dbg(fsp)));
1249 *out_len = MIN(max_out_len, 64);
1251 /* Hmmm, will this cause problems if less data asked for? */
1252 return_data = talloc_array(ctx, char, 64);
1253 if (return_data == NULL) {
1254 return NT_STATUS_NO_MEMORY;
1257 /* For backwards compatibility only store the dev/inode. */
1258 push_file_id_16(return_data, &fsp->file_id);
1259 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1260 push_file_id_16(return_data+32, &fsp->file_id);
1261 memset(return_data+48, 0, 16);
1262 *out_data = return_data;
1263 return NT_STATUS_OK;
1266 case FSCTL_GET_REPARSE_POINT:
1268 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1269 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1270 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1271 return NT_STATUS_NOT_A_REPARSE_POINT;
1274 case FSCTL_SET_REPARSE_POINT:
1276 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1277 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1278 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1279 return NT_STATUS_NOT_A_REPARSE_POINT;
1282 case FSCTL_GET_SHADOW_COPY_DATA:
1285 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1286 * and return their volume names. If max_data_count is 16, then it is just
1287 * asking for the number of volumes and length of the combined names.
1289 * pdata is the data allocated by our caller, but that uses
1290 * total_data_count (which is 0 in our case) rather than max_data_count.
1291 * Allocate the correct amount and return the pointer to let
1292 * it be deallocated when we return.
1294 struct shadow_copy_data *shadow_data = NULL;
1295 bool labels = False;
1296 uint32_t labels_data_count = 0;
1297 uint32_t i;
1298 char *cur_pdata = NULL;
1300 if (max_out_len < 16) {
1301 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1302 max_out_len));
1303 return NT_STATUS_INVALID_PARAMETER;
1306 if (max_out_len > 16) {
1307 labels = True;
1310 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1311 if (shadow_data == NULL) {
1312 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1313 return NT_STATUS_NO_MEMORY;
1317 * Call the VFS routine to actually do the work.
1319 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1320 int log_lev = 0;
1321 if (errno == 0) {
1322 /* broken module didn't set errno on error */
1323 status = NT_STATUS_UNSUCCESSFUL;
1324 } else {
1325 status = map_nt_error_from_unix(errno);
1326 if (NT_STATUS_EQUAL(status,
1327 NT_STATUS_NOT_SUPPORTED)) {
1328 log_lev = 5;
1331 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1332 "connectpath %s, failed - %s.\n",
1333 fsp->conn->connectpath,
1334 nt_errstr(status)));
1335 TALLOC_FREE(shadow_data);
1336 return status;
1339 labels_data_count = (shadow_data->num_volumes * 2 *
1340 sizeof(SHADOW_COPY_LABEL)) + 2;
1342 if (!labels) {
1343 *out_len = 16;
1344 } else {
1345 *out_len = 12 + labels_data_count;
1348 if (max_out_len < *out_len) {
1349 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1350 max_out_len, *out_len));
1351 TALLOC_FREE(shadow_data);
1352 return NT_STATUS_BUFFER_TOO_SMALL;
1355 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1356 if (cur_pdata == NULL) {
1357 TALLOC_FREE(shadow_data);
1358 return NT_STATUS_NO_MEMORY;
1361 *out_data = cur_pdata;
1363 /* num_volumes 4 bytes */
1364 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1366 if (labels) {
1367 /* num_labels 4 bytes */
1368 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1371 /* needed_data_count 4 bytes */
1372 SIVAL(cur_pdata, 8, labels_data_count);
1374 cur_pdata += 12;
1376 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1377 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1378 if (labels && shadow_data->labels) {
1379 for (i=0; i<shadow_data->num_volumes; i++) {
1380 size_t len = 0;
1381 status = srvstr_push(cur_pdata, req_flags,
1382 cur_pdata, shadow_data->labels[i],
1383 2 * sizeof(SHADOW_COPY_LABEL),
1384 STR_UNICODE|STR_TERMINATE, &len);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 TALLOC_FREE(*out_data);
1387 TALLOC_FREE(shadow_data);
1388 return status;
1390 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1391 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1395 TALLOC_FREE(shadow_data);
1397 return NT_STATUS_OK;
1400 case FSCTL_FIND_FILES_BY_SID:
1402 /* pretend this succeeded -
1404 * we have to send back a list with all files owned by this SID
1406 * but I have to check that --metze
1408 struct dom_sid sid;
1409 uid_t uid;
1410 size_t sid_len;
1412 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1413 fsp_fnum_dbg(fsp)));
1415 if (in_len < 8) {
1416 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1417 return NT_STATUS_INVALID_PARAMETER;
1420 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1422 /* unknown 4 bytes: this is not the length of the sid :-( */
1423 /*unknown = IVAL(pdata,0);*/
1425 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1426 return NT_STATUS_INVALID_PARAMETER;
1428 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1430 if (!sid_to_uid(&sid, &uid)) {
1431 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1432 sid_string_dbg(&sid),
1433 (unsigned long)sid_len));
1434 uid = (-1);
1437 /* we can take a look at the find source :-)
1439 * find ./ -uid $uid -name '*' is what we need here
1442 * and send 4bytes len and then NULL terminated unicode strings
1443 * for each file
1445 * but I don't know how to deal with the paged results
1446 * (maybe we can hang the result anywhere in the fsp struct)
1448 * but I don't know how to deal with the paged results
1449 * (maybe we can hang the result anywhere in the fsp struct)
1451 * we don't send all files at once
1452 * and at the next we should *not* start from the beginning,
1453 * so we have to cache the result
1455 * --metze
1458 /* this works for now... */
1459 return NT_STATUS_OK;
1462 case FSCTL_QUERY_ALLOCATED_RANGES:
1464 /* FIXME: This is just a dummy reply, telling that all of the
1465 * file is allocated. MKS cp needs that.
1466 * Adding the real allocated ranges via FIEMAP on Linux
1467 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1468 * this FSCTL correct for sparse files.
1470 uint64_t offset, length;
1471 char *out_data_tmp = NULL;
1473 if (in_len != 16) {
1474 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1475 in_len));
1476 return NT_STATUS_INVALID_PARAMETER;
1479 if (max_out_len < 16) {
1480 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1481 max_out_len));
1482 return NT_STATUS_INVALID_PARAMETER;
1485 offset = BVAL(in_data,0);
1486 length = BVAL(in_data,8);
1488 if (offset + length < offset) {
1489 /* No 64-bit integer wrap. */
1490 return NT_STATUS_INVALID_PARAMETER;
1493 /* Shouldn't this be SMB_VFS_STAT ... ? */
1494 status = vfs_stat_fsp(fsp);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 return status;
1499 *out_len = 16;
1500 out_data_tmp = talloc_array(ctx, char, *out_len);
1501 if (out_data_tmp == NULL) {
1502 DEBUG(10, ("unable to allocate memory for response\n"));
1503 return NT_STATUS_NO_MEMORY;
1506 if (offset > fsp->fsp_name->st.st_ex_size ||
1507 fsp->fsp_name->st.st_ex_size == 0 ||
1508 length == 0) {
1509 memset(out_data_tmp, 0, *out_len);
1510 } else {
1511 uint64_t end = offset + length;
1512 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1513 SBVAL(out_data_tmp, 0, 0);
1514 SBVAL(out_data_tmp, 8, end);
1517 *out_data = out_data_tmp;
1519 return NT_STATUS_OK;
1522 case FSCTL_IS_VOLUME_DIRTY:
1524 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1525 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1527 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1528 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1530 return NT_STATUS_INVALID_PARAMETER;
1533 default:
1535 * Only print once ... unfortunately there could be lots of
1536 * different FSCTLs that are called.
1538 if (!vfswrap_logged_ioctl_message) {
1539 vfswrap_logged_ioctl_message = true;
1540 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1541 __func__, function));
1545 return NT_STATUS_NOT_SUPPORTED;
1548 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1549 const struct smb_filename *fname,
1550 SMB_STRUCT_STAT *sbuf);
1552 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1553 struct smb_filename *smb_fname,
1554 uint32_t *dosmode)
1556 bool offline;
1558 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1559 if (offline) {
1560 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1563 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1566 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1567 struct files_struct *fsp,
1568 uint32_t *dosmode)
1570 bool offline;
1572 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1573 if (offline) {
1574 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1577 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1580 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1581 const struct smb_filename *smb_fname,
1582 uint32_t dosmode)
1584 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1587 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1588 struct files_struct *fsp,
1589 uint32_t dosmode)
1591 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1594 struct vfs_cc_state {
1595 struct tevent_context *ev;
1596 uint8_t *buf;
1597 bool read_lck_locked;
1598 struct lock_struct read_lck;
1599 bool write_lck_locked;
1600 struct lock_struct write_lck;
1601 struct files_struct *src_fsp;
1602 off_t src_off;
1603 struct files_struct *dst_fsp;
1604 off_t dst_off;
1605 off_t to_copy;
1606 off_t remaining;
1607 size_t next_io_size;
1608 uint32_t flags;
1611 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1613 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1614 TALLOC_CTX *mem_ctx,
1615 struct tevent_context *ev,
1616 struct files_struct *src_fsp,
1617 off_t src_off,
1618 struct files_struct *dest_fsp,
1619 off_t dest_off,
1620 off_t to_copy,
1621 uint32_t flags)
1623 struct tevent_req *req;
1624 struct vfs_cc_state *state = NULL;
1625 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1626 NTSTATUS status;
1628 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1630 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1631 if (req == NULL) {
1632 return NULL;
1635 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1636 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1637 return tevent_req_post(req, ev);
1640 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1641 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1642 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1643 return tevent_req_post(req, ev);
1646 *state = (struct vfs_cc_state) {
1647 .ev = ev,
1648 .src_fsp = src_fsp,
1649 .src_off = src_off,
1650 .dst_fsp = dest_fsp,
1651 .dst_off = dest_off,
1652 .to_copy = to_copy,
1653 .remaining = to_copy,
1654 .flags = flags,
1656 state->buf = talloc_array(state, uint8_t, num);
1657 if (tevent_req_nomem(state->buf, req)) {
1658 return tevent_req_post(req, ev);
1661 status = vfs_stat_fsp(src_fsp);
1662 if (tevent_req_nterror(req, status)) {
1663 return tevent_req_post(req, ev);
1666 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1668 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1669 * If the SourceOffset or SourceOffset + Length extends beyond
1670 * the end of file, the server SHOULD<240> treat this as a
1671 * STATUS_END_OF_FILE error.
1672 * ...
1673 * <240> Section 3.3.5.15.6: Windows servers will return
1674 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1676 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1677 return tevent_req_post(req, ev);
1680 if (src_fsp->op == NULL) {
1681 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1682 return tevent_req_post(req, ev);
1685 if (dest_fsp->op == NULL) {
1686 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1687 return tevent_req_post(req, ev);
1690 status = copy_chunk_loop(req);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 tevent_req_nterror(req, status);
1693 return tevent_req_post(req, ev);
1696 return req;
1699 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1701 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1703 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1704 struct tevent_req *subreq = NULL;
1705 bool ok;
1707 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1709 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1710 init_strict_lock_struct(state->src_fsp,
1711 state->src_fsp->op->global->open_persistent_id,
1712 state->src_off,
1713 state->next_io_size,
1714 READ_LOCK,
1715 &state->read_lck);
1717 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1718 state->src_fsp,
1719 &state->read_lck);
1720 if (!ok) {
1721 return NT_STATUS_FILE_LOCK_CONFLICT;
1725 subreq = SMB_VFS_PREAD_SEND(state,
1726 state->src_fsp->conn->sconn->ev_ctx,
1727 state->src_fsp,
1728 state->buf,
1729 state->next_io_size,
1730 state->src_off);
1731 if (subreq == NULL) {
1732 return NT_STATUS_NO_MEMORY;
1734 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1736 return NT_STATUS_OK;
1739 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1741 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1743 struct tevent_req *req = tevent_req_callback_data(
1744 subreq, struct tevent_req);
1745 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1746 struct vfs_aio_state aio_state;
1747 ssize_t nread;
1748 bool ok;
1750 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1751 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1752 state->src_fsp,
1753 &state->read_lck);
1754 ZERO_STRUCT(state->read_lck);
1757 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1758 TALLOC_FREE(subreq);
1759 if (nread == -1) {
1760 DBG_ERR("read failed: %s\n", strerror(errno));
1761 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1762 return;
1764 if (nread != state->next_io_size) {
1765 DBG_ERR("Short read, only %zd of %zu\n",
1766 nread, state->next_io_size);
1767 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1768 return;
1771 state->src_off += nread;
1773 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1774 init_strict_lock_struct(state->dst_fsp,
1775 state->dst_fsp->op->global->open_persistent_id,
1776 state->dst_off,
1777 state->next_io_size,
1778 WRITE_LOCK,
1779 &state->write_lck);
1781 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1782 state->dst_fsp,
1783 &state->write_lck);
1784 if (!ok) {
1785 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1786 return;
1790 subreq = SMB_VFS_PWRITE_SEND(state,
1791 state->ev,
1792 state->dst_fsp,
1793 state->buf,
1794 state->next_io_size,
1795 state->dst_off);
1796 if (subreq == NULL) {
1797 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1798 return;
1800 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1803 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1805 struct tevent_req *req = tevent_req_callback_data(
1806 subreq, struct tevent_req);
1807 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1808 struct vfs_aio_state aio_state;
1809 ssize_t nwritten;
1810 NTSTATUS status;
1812 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1813 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1814 state->dst_fsp,
1815 &state->write_lck);
1816 ZERO_STRUCT(state->write_lck);
1819 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1820 TALLOC_FREE(subreq);
1821 if (nwritten == -1) {
1822 DBG_ERR("write failed: %s\n", strerror(errno));
1823 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1824 return;
1826 if (nwritten != state->next_io_size) {
1827 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1828 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1829 return;
1832 state->dst_off += nwritten;
1834 if (state->remaining < nwritten) {
1835 /* Paranoia check */
1836 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1837 return;
1839 state->remaining -= nwritten;
1840 if (state->remaining == 0) {
1841 tevent_req_done(req);
1842 return;
1845 status = copy_chunk_loop(req);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 tevent_req_nterror(req, status);
1848 return;
1851 return;
1854 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1855 struct tevent_req *req,
1856 off_t *copied)
1858 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1859 NTSTATUS status;
1861 if (tevent_req_is_nterror(req, &status)) {
1862 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1863 *copied = 0;
1864 tevent_req_received(req);
1865 return status;
1868 *copied = state->to_copy;
1869 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1870 tevent_req_received(req);
1872 return NT_STATUS_OK;
1875 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1876 TALLOC_CTX *mem_ctx,
1877 struct files_struct *fsp,
1878 struct smb_filename *smb_fname,
1879 uint16_t *_compression_fmt)
1881 return NT_STATUS_INVALID_DEVICE_REQUEST;
1884 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1885 TALLOC_CTX *mem_ctx,
1886 struct files_struct *fsp,
1887 uint16_t compression_fmt)
1889 return NT_STATUS_INVALID_DEVICE_REQUEST;
1892 /********************************************************************
1893 Given a stat buffer return the allocated size on disk, taking into
1894 account sparse files.
1895 ********************************************************************/
1896 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1897 struct files_struct *fsp,
1898 const SMB_STRUCT_STAT *sbuf)
1900 uint64_t result;
1902 START_PROFILE(syscall_get_alloc_size);
1904 if(S_ISDIR(sbuf->st_ex_mode)) {
1905 result = 0;
1906 goto out;
1909 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1910 /* The type of st_blocksize is blkcnt_t which *MUST* be
1911 signed (according to POSIX) and can be less than 64-bits.
1912 Ensure when we're converting to 64 bits wide we don't
1913 sign extend. */
1914 #if defined(SIZEOF_BLKCNT_T_8)
1915 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1916 #elif defined(SIZEOF_BLKCNT_T_4)
1918 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1919 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1921 #else
1922 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1923 #endif
1924 if (result == 0) {
1926 * Some file systems do not allocate a block for very
1927 * small files. But for non-empty file should report a
1928 * positive size.
1931 uint64_t filesize = get_file_size_stat(sbuf);
1932 if (filesize > 0) {
1933 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1936 #else
1937 result = get_file_size_stat(sbuf);
1938 #endif
1940 if (fsp && fsp->initial_allocation_size)
1941 result = MAX(result,fsp->initial_allocation_size);
1943 result = smb_roundup(handle->conn, result);
1945 out:
1946 END_PROFILE(syscall_get_alloc_size);
1947 return result;
1950 static int vfswrap_unlink(vfs_handle_struct *handle,
1951 const struct smb_filename *smb_fname)
1953 int result = -1;
1955 START_PROFILE(syscall_unlink);
1957 if (smb_fname->stream_name) {
1958 errno = ENOENT;
1959 goto out;
1961 result = unlink(smb_fname->base_name);
1963 out:
1964 END_PROFILE(syscall_unlink);
1965 return result;
1968 static int vfswrap_chmod(vfs_handle_struct *handle,
1969 const struct smb_filename *smb_fname,
1970 mode_t mode)
1972 int result;
1974 START_PROFILE(syscall_chmod);
1977 * We need to do this due to the fact that the default POSIX ACL
1978 * chmod modifies the ACL *mask* for the group owner, not the
1979 * group owner bits directly. JRA.
1984 int saved_errno = errno; /* We might get ENOSYS */
1985 result = SMB_VFS_CHMOD_ACL(handle->conn,
1986 smb_fname,
1987 mode);
1988 if (result == 0) {
1989 END_PROFILE(syscall_chmod);
1990 return result;
1992 /* Error - return the old errno. */
1993 errno = saved_errno;
1996 result = chmod(smb_fname->base_name, mode);
1997 END_PROFILE(syscall_chmod);
1998 return result;
2001 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2003 int result;
2005 START_PROFILE(syscall_fchmod);
2008 * We need to do this due to the fact that the default POSIX ACL
2009 * chmod modifies the ACL *mask* for the group owner, not the
2010 * group owner bits directly. JRA.
2014 int saved_errno = errno; /* We might get ENOSYS */
2015 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2016 END_PROFILE(syscall_fchmod);
2017 return result;
2019 /* Error - return the old errno. */
2020 errno = saved_errno;
2023 #if defined(HAVE_FCHMOD)
2024 result = fchmod(fsp->fh->fd, mode);
2025 #else
2026 result = -1;
2027 errno = ENOSYS;
2028 #endif
2030 END_PROFILE(syscall_fchmod);
2031 return result;
2034 static int vfswrap_chown(vfs_handle_struct *handle,
2035 const struct smb_filename *smb_fname,
2036 uid_t uid,
2037 gid_t gid)
2039 int result;
2041 START_PROFILE(syscall_chown);
2042 result = chown(smb_fname->base_name, uid, gid);
2043 END_PROFILE(syscall_chown);
2044 return result;
2047 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2049 #ifdef HAVE_FCHOWN
2050 int result;
2052 START_PROFILE(syscall_fchown);
2053 result = fchown(fsp->fh->fd, uid, gid);
2054 END_PROFILE(syscall_fchown);
2055 return result;
2056 #else
2057 errno = ENOSYS;
2058 return -1;
2059 #endif
2062 static int vfswrap_lchown(vfs_handle_struct *handle,
2063 const struct smb_filename *smb_fname,
2064 uid_t uid,
2065 gid_t gid)
2067 int result;
2069 START_PROFILE(syscall_lchown);
2070 result = lchown(smb_fname->base_name, uid, gid);
2071 END_PROFILE(syscall_lchown);
2072 return result;
2075 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2077 int result;
2079 START_PROFILE(syscall_chdir);
2080 result = chdir(path);
2081 END_PROFILE(syscall_chdir);
2082 return result;
2085 static char *vfswrap_getwd(vfs_handle_struct *handle)
2087 char *result;
2089 START_PROFILE(syscall_getwd);
2090 result = sys_getwd();
2091 END_PROFILE(syscall_getwd);
2092 return result;
2095 /*********************************************************************
2096 nsec timestamp resolution call. Convert down to whatever the underlying
2097 system will support.
2098 **********************************************************************/
2100 static int vfswrap_ntimes(vfs_handle_struct *handle,
2101 const struct smb_filename *smb_fname,
2102 struct smb_file_time *ft)
2104 int result = -1;
2106 START_PROFILE(syscall_ntimes);
2108 if (smb_fname->stream_name) {
2109 errno = ENOENT;
2110 goto out;
2113 if (ft != NULL) {
2114 if (null_timespec(ft->atime)) {
2115 ft->atime= smb_fname->st.st_ex_atime;
2118 if (null_timespec(ft->mtime)) {
2119 ft->mtime = smb_fname->st.st_ex_mtime;
2122 if (!null_timespec(ft->create_time)) {
2123 set_create_timespec_ea(handle->conn,
2124 smb_fname,
2125 ft->create_time);
2128 if ((timespec_compare(&ft->atime,
2129 &smb_fname->st.st_ex_atime) == 0) &&
2130 (timespec_compare(&ft->mtime,
2131 &smb_fname->st.st_ex_mtime) == 0)) {
2132 return 0;
2136 #if defined(HAVE_UTIMENSAT)
2137 if (ft != NULL) {
2138 struct timespec ts[2];
2139 ts[0] = ft->atime;
2140 ts[1] = ft->mtime;
2141 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2142 } else {
2143 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2145 if (!((result == -1) && (errno == ENOSYS))) {
2146 goto out;
2148 #endif
2149 #if defined(HAVE_UTIMES)
2150 if (ft != NULL) {
2151 struct timeval tv[2];
2152 tv[0] = convert_timespec_to_timeval(ft->atime);
2153 tv[1] = convert_timespec_to_timeval(ft->mtime);
2154 result = utimes(smb_fname->base_name, tv);
2155 } else {
2156 result = utimes(smb_fname->base_name, NULL);
2158 if (!((result == -1) && (errno == ENOSYS))) {
2159 goto out;
2161 #endif
2162 #if defined(HAVE_UTIME)
2163 if (ft != NULL) {
2164 struct utimbuf times;
2165 times.actime = convert_timespec_to_time_t(ft->atime);
2166 times.modtime = convert_timespec_to_time_t(ft->mtime);
2167 result = utime(smb_fname->base_name, &times);
2168 } else {
2169 result = utime(smb_fname->base_name, NULL);
2171 if (!((result == -1) && (errno == ENOSYS))) {
2172 goto out;
2174 #endif
2175 errno = ENOSYS;
2176 result = -1;
2178 out:
2179 END_PROFILE(syscall_ntimes);
2180 return result;
2183 /*********************************************************************
2184 A version of ftruncate that will write the space on disk if strict
2185 allocate is set.
2186 **********************************************************************/
2188 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2190 off_t space_to_write;
2191 uint64_t space_avail;
2192 uint64_t bsize,dfree,dsize;
2193 int ret;
2194 NTSTATUS status;
2195 SMB_STRUCT_STAT *pst;
2197 status = vfs_stat_fsp(fsp);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 return -1;
2201 pst = &fsp->fsp_name->st;
2203 #ifdef S_ISFIFO
2204 if (S_ISFIFO(pst->st_ex_mode))
2205 return 0;
2206 #endif
2208 if (pst->st_ex_size == len)
2209 return 0;
2211 /* Shrink - just ftruncate. */
2212 if (pst->st_ex_size > len)
2213 return ftruncate(fsp->fh->fd, len);
2215 space_to_write = len - pst->st_ex_size;
2217 /* for allocation try fallocate first. This can fail on some
2218 platforms e.g. when the filesystem doesn't support it and no
2219 emulation is being done by the libc (like on AIX with JFS1). In that
2220 case we do our own emulation. fallocate implementations can
2221 return ENOTSUP or EINVAL in cases like that. */
2222 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2223 if (ret == -1 && errno == ENOSPC) {
2224 return -1;
2226 if (ret == 0) {
2227 return 0;
2229 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2230 "error %d. Falling back to slow manual allocation\n", errno));
2232 /* available disk space is enough or not? */
2233 space_avail =
2234 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2235 /* space_avail is 1k blocks */
2236 if (space_avail == (uint64_t)-1 ||
2237 ((uint64_t)space_to_write/1024 > space_avail) ) {
2238 errno = ENOSPC;
2239 return -1;
2242 /* Write out the real space on disk. */
2243 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2244 if (ret != 0) {
2245 return -1;
2248 return 0;
2251 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2253 int result = -1;
2254 SMB_STRUCT_STAT *pst;
2255 NTSTATUS status;
2256 char c = 0;
2258 START_PROFILE(syscall_ftruncate);
2260 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2261 result = strict_allocate_ftruncate(handle, fsp, len);
2262 END_PROFILE(syscall_ftruncate);
2263 return result;
2266 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2267 ftruncate if the system supports it. Then I discovered that
2268 you can have some filesystems that support ftruncate
2269 expansion and some that don't! On Linux fat can't do
2270 ftruncate extend but ext2 can. */
2272 result = ftruncate(fsp->fh->fd, len);
2274 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2275 extend a file with ftruncate. Provide alternate implementation
2276 for this */
2278 /* Do an fstat to see if the file is longer than the requested
2279 size in which case the ftruncate above should have
2280 succeeded or shorter, in which case seek to len - 1 and
2281 write 1 byte of zero */
2282 status = vfs_stat_fsp(fsp);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 goto done;
2287 /* We need to update the files_struct after successful ftruncate */
2288 if (result == 0) {
2289 goto done;
2292 pst = &fsp->fsp_name->st;
2294 #ifdef S_ISFIFO
2295 if (S_ISFIFO(pst->st_ex_mode)) {
2296 result = 0;
2297 goto done;
2299 #endif
2301 if (pst->st_ex_size == len) {
2302 result = 0;
2303 goto done;
2306 if (pst->st_ex_size > len) {
2307 /* the ftruncate should have worked */
2308 goto done;
2311 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2312 goto done;
2315 result = 0;
2317 done:
2319 END_PROFILE(syscall_ftruncate);
2320 return result;
2323 static int vfswrap_fallocate(vfs_handle_struct *handle,
2324 files_struct *fsp,
2325 uint32_t mode,
2326 off_t offset,
2327 off_t len)
2329 int result;
2331 START_PROFILE(syscall_fallocate);
2332 if (mode == 0) {
2333 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2335 * posix_fallocate returns 0 on success, errno on error
2336 * and doesn't set errno. Make it behave like fallocate()
2337 * which returns -1, and sets errno on failure.
2339 if (result != 0) {
2340 errno = result;
2341 result = -1;
2343 } else {
2344 /* sys_fallocate handles filtering of unsupported mode flags */
2345 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2347 END_PROFILE(syscall_fallocate);
2348 return result;
2351 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2353 bool result;
2355 START_PROFILE(syscall_fcntl_lock);
2357 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2358 "smbd",
2359 "force process locks",
2360 false)) {
2361 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2364 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2365 END_PROFILE(syscall_fcntl_lock);
2366 return result;
2369 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2370 uint32_t share_mode, uint32_t access_mask)
2372 START_PROFILE(syscall_kernel_flock);
2373 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2374 END_PROFILE(syscall_kernel_flock);
2375 return 0;
2378 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2380 bool result;
2381 int op = F_GETLK;
2383 START_PROFILE(syscall_fcntl_getlock);
2385 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2386 "smbd",
2387 "force process locks",
2388 false)) {
2389 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2392 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2393 END_PROFILE(syscall_fcntl_getlock);
2394 return result;
2397 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2398 int leasetype)
2400 int result = -1;
2402 START_PROFILE(syscall_linux_setlease);
2404 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2405 result = linux_setlease(fsp->fh->fd, leasetype);
2406 #else
2407 errno = ENOSYS;
2408 #endif
2409 END_PROFILE(syscall_linux_setlease);
2410 return result;
2413 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2415 int result;
2417 START_PROFILE(syscall_symlink);
2418 result = symlink(oldpath, newpath);
2419 END_PROFILE(syscall_symlink);
2420 return result;
2423 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2425 int result;
2427 START_PROFILE(syscall_readlink);
2428 result = readlink(path, buf, bufsiz);
2429 END_PROFILE(syscall_readlink);
2430 return result;
2433 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2435 int result;
2437 START_PROFILE(syscall_link);
2438 result = link(oldpath, newpath);
2439 END_PROFILE(syscall_link);
2440 return result;
2443 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2445 int result;
2447 START_PROFILE(syscall_mknod);
2448 result = sys_mknod(pathname, mode, dev);
2449 END_PROFILE(syscall_mknod);
2450 return result;
2453 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2455 char *result;
2457 START_PROFILE(syscall_realpath);
2458 result = sys_realpath(path);
2459 END_PROFILE(syscall_realpath);
2460 return result;
2463 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2464 unsigned int flags)
2466 #ifdef HAVE_CHFLAGS
2467 return chflags(path, flags);
2468 #else
2469 errno = ENOSYS;
2470 return -1;
2471 #endif
2474 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2475 const SMB_STRUCT_STAT *sbuf)
2477 struct file_id key;
2479 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2480 * blob */
2481 ZERO_STRUCT(key);
2483 key.devid = sbuf->st_ex_dev;
2484 key.inode = sbuf->st_ex_ino;
2485 /* key.extid is unused by default. */
2487 return key;
2490 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2491 struct files_struct *fsp,
2492 const struct smb_filename *smb_fname,
2493 TALLOC_CTX *mem_ctx,
2494 unsigned int *pnum_streams,
2495 struct stream_struct **pstreams)
2497 SMB_STRUCT_STAT sbuf;
2498 struct stream_struct *tmp_streams = NULL;
2499 int ret;
2501 if ((fsp != NULL) && (fsp->is_directory)) {
2503 * No default streams on directories
2505 goto done;
2508 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2509 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2511 else {
2512 struct smb_filename smb_fname_cp;
2514 ZERO_STRUCT(smb_fname_cp);
2515 smb_fname_cp.base_name = discard_const_p(char,
2516 smb_fname->base_name);
2517 smb_fname_cp.flags = smb_fname->flags;
2519 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2520 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2521 } else {
2522 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2524 sbuf = smb_fname_cp.st;
2527 if (ret == -1) {
2528 return map_nt_error_from_unix(errno);
2531 if (S_ISDIR(sbuf.st_ex_mode)) {
2532 goto done;
2535 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2536 (*pnum_streams) + 1);
2537 if (tmp_streams == NULL) {
2538 return NT_STATUS_NO_MEMORY;
2540 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2541 if (tmp_streams[*pnum_streams].name == NULL) {
2542 return NT_STATUS_NO_MEMORY;
2544 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2545 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2547 *pnum_streams += 1;
2548 *pstreams = tmp_streams;
2549 done:
2550 return NT_STATUS_OK;
2553 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2554 const char *path,
2555 const char *name,
2556 TALLOC_CTX *mem_ctx,
2557 char **found_name)
2560 * Don't fall back to get_real_filename so callers can differentiate
2561 * between a full directory scan and an actual case-insensitive stat.
2563 errno = EOPNOTSUPP;
2564 return -1;
2567 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2568 const char *fname)
2570 return handle->conn->connectpath;
2573 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2574 struct byte_range_lock *br_lck,
2575 struct lock_struct *plock,
2576 bool blocking_lock)
2578 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2580 /* Note: blr is not used in the default implementation. */
2581 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2584 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2585 struct messaging_context *msg_ctx,
2586 struct byte_range_lock *br_lck,
2587 const struct lock_struct *plock)
2589 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2591 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2594 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2595 struct byte_range_lock *br_lck,
2596 struct lock_struct *plock)
2598 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2600 /* Note: blr is not used in the default implementation. */
2601 return brl_lock_cancel_default(br_lck, plock);
2604 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2605 files_struct *fsp,
2606 struct lock_struct *plock)
2608 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2609 plock->lock_type == WRITE_LOCK);
2611 return strict_lock_default(fsp, plock);
2614 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2615 files_struct *fsp,
2616 struct lock_struct *plock)
2618 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2619 plock->lock_type == WRITE_LOCK);
2621 strict_unlock_default(fsp, plock);
2624 /* NT ACL operations. */
2626 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2627 files_struct *fsp,
2628 uint32_t security_info,
2629 TALLOC_CTX *mem_ctx,
2630 struct security_descriptor **ppdesc)
2632 NTSTATUS result;
2634 START_PROFILE(fget_nt_acl);
2635 result = posix_fget_nt_acl(fsp, security_info,
2636 mem_ctx, ppdesc);
2637 END_PROFILE(fget_nt_acl);
2638 return result;
2641 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2642 const struct smb_filename *smb_fname,
2643 uint32_t security_info,
2644 TALLOC_CTX *mem_ctx,
2645 struct security_descriptor **ppdesc)
2647 NTSTATUS result;
2649 START_PROFILE(get_nt_acl);
2650 result = posix_get_nt_acl(handle->conn,
2651 smb_fname,
2652 security_info,
2653 mem_ctx,
2654 ppdesc);
2655 END_PROFILE(get_nt_acl);
2656 return result;
2659 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2661 NTSTATUS result;
2663 START_PROFILE(fset_nt_acl);
2664 result = set_nt_acl(fsp, security_info_sent, psd);
2665 END_PROFILE(fset_nt_acl);
2666 return result;
2669 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2670 struct smb_filename *file,
2671 struct security_acl *sacl,
2672 uint32_t access_requested,
2673 uint32_t access_denied)
2675 return NT_STATUS_OK; /* Nothing to do here ... */
2678 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2679 const struct smb_filename *smb_fname,
2680 mode_t mode)
2682 #ifdef HAVE_NO_ACL
2683 errno = ENOSYS;
2684 return -1;
2685 #else
2686 int result;
2688 START_PROFILE(chmod_acl);
2689 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2690 END_PROFILE(chmod_acl);
2691 return result;
2692 #endif
2695 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2697 #ifdef HAVE_NO_ACL
2698 errno = ENOSYS;
2699 return -1;
2700 #else
2701 int result;
2703 START_PROFILE(fchmod_acl);
2704 result = fchmod_acl(fsp, mode);
2705 END_PROFILE(fchmod_acl);
2706 return result;
2707 #endif
2710 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2711 const char *path_p,
2712 SMB_ACL_TYPE_T type,
2713 TALLOC_CTX *mem_ctx)
2715 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2718 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2719 files_struct *fsp,
2720 TALLOC_CTX *mem_ctx)
2722 return sys_acl_get_fd(handle, fsp, mem_ctx);
2725 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2727 return sys_acl_set_file(handle, name, acltype, theacl);
2730 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2732 return sys_acl_set_fd(handle, fsp, theacl);
2735 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2737 return sys_acl_delete_def_file(handle, path);
2740 /****************************************************************
2741 Extended attribute operations.
2742 *****************************************************************/
2744 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2746 return getxattr(path, name, value, size);
2749 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2751 return fgetxattr(fsp->fh->fd, name, value, size);
2754 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2756 return listxattr(path, list, size);
2759 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2761 return flistxattr(fsp->fh->fd, list, size);
2764 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2766 return removexattr(path, name);
2769 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2771 return fremovexattr(fsp->fh->fd, name);
2774 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2776 return setxattr(path, name, value, size, flags);
2779 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2781 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2784 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2786 return false;
2789 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2790 const struct smb_filename *fname,
2791 SMB_STRUCT_STAT *sbuf)
2793 NTSTATUS status;
2794 char *path;
2795 bool offline = false;
2797 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2798 return false;
2801 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2802 #if defined(ENOTSUP)
2803 errno = ENOTSUP;
2804 #endif
2805 return false;
2808 status = get_full_smb_filename(talloc_tos(), fname, &path);
2809 if (!NT_STATUS_IS_OK(status)) {
2810 errno = map_errno_from_nt_status(status);
2811 return false;
2814 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2816 TALLOC_FREE(path);
2818 return offline;
2821 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2822 struct files_struct *fsp,
2823 TALLOC_CTX *mem_ctx,
2824 DATA_BLOB *cookie)
2826 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2829 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2830 struct files_struct *fsp,
2831 const DATA_BLOB old_cookie,
2832 TALLOC_CTX *mem_ctx,
2833 DATA_BLOB *new_cookie)
2835 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2836 new_cookie);
2839 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2840 struct smb_request *smb1req,
2841 struct smbXsrv_open *op,
2842 const DATA_BLOB old_cookie,
2843 TALLOC_CTX *mem_ctx,
2844 struct files_struct **fsp,
2845 DATA_BLOB *new_cookie)
2847 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2848 old_cookie, mem_ctx,
2849 fsp, new_cookie);
2852 static struct vfs_fn_pointers vfs_default_fns = {
2853 /* Disk operations */
2855 .connect_fn = vfswrap_connect,
2856 .disconnect_fn = vfswrap_disconnect,
2857 .disk_free_fn = vfswrap_disk_free,
2858 .get_quota_fn = vfswrap_get_quota,
2859 .set_quota_fn = vfswrap_set_quota,
2860 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2861 .statvfs_fn = vfswrap_statvfs,
2862 .fs_capabilities_fn = vfswrap_fs_capabilities,
2863 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2864 .snap_check_path_fn = vfswrap_snap_check_path,
2865 .snap_create_fn = vfswrap_snap_create,
2866 .snap_delete_fn = vfswrap_snap_delete,
2868 /* Directory operations */
2870 .opendir_fn = vfswrap_opendir,
2871 .fdopendir_fn = vfswrap_fdopendir,
2872 .readdir_fn = vfswrap_readdir,
2873 .readdir_attr_fn = vfswrap_readdir_attr,
2874 .seekdir_fn = vfswrap_seekdir,
2875 .telldir_fn = vfswrap_telldir,
2876 .rewind_dir_fn = vfswrap_rewinddir,
2877 .mkdir_fn = vfswrap_mkdir,
2878 .rmdir_fn = vfswrap_rmdir,
2879 .closedir_fn = vfswrap_closedir,
2880 .init_search_op_fn = vfswrap_init_search_op,
2882 /* File operations */
2884 .open_fn = vfswrap_open,
2885 .create_file_fn = vfswrap_create_file,
2886 .close_fn = vfswrap_close,
2887 .read_fn = vfswrap_read,
2888 .pread_fn = vfswrap_pread,
2889 .pread_send_fn = vfswrap_pread_send,
2890 .pread_recv_fn = vfswrap_pread_recv,
2891 .write_fn = vfswrap_write,
2892 .pwrite_fn = vfswrap_pwrite,
2893 .pwrite_send_fn = vfswrap_pwrite_send,
2894 .pwrite_recv_fn = vfswrap_pwrite_recv,
2895 .lseek_fn = vfswrap_lseek,
2896 .sendfile_fn = vfswrap_sendfile,
2897 .recvfile_fn = vfswrap_recvfile,
2898 .rename_fn = vfswrap_rename,
2899 .fsync_fn = vfswrap_fsync,
2900 .fsync_send_fn = vfswrap_fsync_send,
2901 .fsync_recv_fn = vfswrap_fsync_recv,
2902 .stat_fn = vfswrap_stat,
2903 .fstat_fn = vfswrap_fstat,
2904 .lstat_fn = vfswrap_lstat,
2905 .get_alloc_size_fn = vfswrap_get_alloc_size,
2906 .unlink_fn = vfswrap_unlink,
2907 .chmod_fn = vfswrap_chmod,
2908 .fchmod_fn = vfswrap_fchmod,
2909 .chown_fn = vfswrap_chown,
2910 .fchown_fn = vfswrap_fchown,
2911 .lchown_fn = vfswrap_lchown,
2912 .chdir_fn = vfswrap_chdir,
2913 .getwd_fn = vfswrap_getwd,
2914 .ntimes_fn = vfswrap_ntimes,
2915 .ftruncate_fn = vfswrap_ftruncate,
2916 .fallocate_fn = vfswrap_fallocate,
2917 .lock_fn = vfswrap_lock,
2918 .kernel_flock_fn = vfswrap_kernel_flock,
2919 .linux_setlease_fn = vfswrap_linux_setlease,
2920 .getlock_fn = vfswrap_getlock,
2921 .symlink_fn = vfswrap_symlink,
2922 .readlink_fn = vfswrap_readlink,
2923 .link_fn = vfswrap_link,
2924 .mknod_fn = vfswrap_mknod,
2925 .realpath_fn = vfswrap_realpath,
2926 .chflags_fn = vfswrap_chflags,
2927 .file_id_create_fn = vfswrap_file_id_create,
2928 .streaminfo_fn = vfswrap_streaminfo,
2929 .get_real_filename_fn = vfswrap_get_real_filename,
2930 .connectpath_fn = vfswrap_connectpath,
2931 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2932 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2933 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2934 .strict_lock_fn = vfswrap_strict_lock,
2935 .strict_unlock_fn = vfswrap_strict_unlock,
2936 .translate_name_fn = vfswrap_translate_name,
2937 .fsctl_fn = vfswrap_fsctl,
2938 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2939 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2940 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2941 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2942 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2943 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2944 .get_compression_fn = vfswrap_get_compression,
2945 .set_compression_fn = vfswrap_set_compression,
2947 /* NT ACL operations. */
2949 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2950 .get_nt_acl_fn = vfswrap_get_nt_acl,
2951 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2952 .audit_file_fn = vfswrap_audit_file,
2954 /* POSIX ACL operations. */
2956 .chmod_acl_fn = vfswrap_chmod_acl,
2957 .fchmod_acl_fn = vfswrap_fchmod_acl,
2959 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2960 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2961 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2962 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2963 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2964 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2965 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2967 /* EA operations. */
2968 .getxattr_fn = vfswrap_getxattr,
2969 .fgetxattr_fn = vfswrap_fgetxattr,
2970 .listxattr_fn = vfswrap_listxattr,
2971 .flistxattr_fn = vfswrap_flistxattr,
2972 .removexattr_fn = vfswrap_removexattr,
2973 .fremovexattr_fn = vfswrap_fremovexattr,
2974 .setxattr_fn = vfswrap_setxattr,
2975 .fsetxattr_fn = vfswrap_fsetxattr,
2977 /* aio operations */
2978 .aio_force_fn = vfswrap_aio_force,
2980 /* durable handle operations */
2981 .durable_cookie_fn = vfswrap_durable_cookie,
2982 .durable_disconnect_fn = vfswrap_durable_disconnect,
2983 .durable_reconnect_fn = vfswrap_durable_reconnect,
2986 NTSTATUS vfs_default_init(TALLOC_CTX *);
2987 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
2989 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2990 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);