vfs_default: make use of change_to_user_by_fsp() in order to switch between src and...
[Samba.git] / source3 / modules / vfs_default.c
blobbaeb285eeb3480483a2717760f05c648aee4a977
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 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
133 NULL, NULL, 0);
134 if (smb_fname_cpath == NULL) {
135 return caps;
138 ZERO_STRUCT(statbuf);
139 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
140 if (ret == 0) {
141 caps = statbuf.FsCapabilities;
144 *p_ts_res = TIMESTAMP_SET_SECONDS;
146 /* Work out what timestamp resolution we can
147 * use when setting a timestamp. */
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 const char *path = smb_fname->base_name;
502 char *parent = NULL;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && directory_has_default_acl(handle->conn, parent)) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
512 TALLOC_FREE(parent);
514 result = mkdir(path, mode);
516 END_PROFILE(syscall_mkdir);
517 return result;
520 static int vfswrap_rmdir(vfs_handle_struct *handle,
521 const struct smb_filename *smb_fname)
523 int result;
525 START_PROFILE(syscall_rmdir);
526 result = rmdir(smb_fname->base_name);
527 END_PROFILE(syscall_rmdir);
528 return result;
531 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
533 int result;
535 START_PROFILE(syscall_closedir);
536 result = closedir(dirp);
537 END_PROFILE(syscall_closedir);
538 return result;
541 /* File operations */
543 static int vfswrap_open(vfs_handle_struct *handle,
544 struct smb_filename *smb_fname,
545 files_struct *fsp, int flags, mode_t mode)
547 int result = -1;
549 START_PROFILE(syscall_open);
551 if (smb_fname->stream_name) {
552 errno = ENOENT;
553 goto out;
556 result = open(smb_fname->base_name, flags, mode);
557 out:
558 END_PROFILE(syscall_open);
559 return result;
562 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
563 struct smb_request *req,
564 uint16_t root_dir_fid,
565 struct smb_filename *smb_fname,
566 uint32_t access_mask,
567 uint32_t share_access,
568 uint32_t create_disposition,
569 uint32_t create_options,
570 uint32_t file_attributes,
571 uint32_t oplock_request,
572 struct smb2_lease *lease,
573 uint64_t allocation_size,
574 uint32_t private_flags,
575 struct security_descriptor *sd,
576 struct ea_list *ea_list,
577 files_struct **result,
578 int *pinfo,
579 const struct smb2_create_blobs *in_context_blobs,
580 struct smb2_create_blobs *out_context_blobs)
582 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
583 access_mask, share_access,
584 create_disposition, create_options,
585 file_attributes, oplock_request, lease,
586 allocation_size, private_flags,
587 sd, ea_list, result,
588 pinfo, in_context_blobs, out_context_blobs);
591 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
593 int result;
595 START_PROFILE(syscall_close);
596 result = fd_close_posix(fsp);
597 END_PROFILE(syscall_close);
598 return result;
601 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
602 size_t n, off_t offset)
604 ssize_t result;
606 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
607 START_PROFILE_BYTES(syscall_pread, n);
608 result = sys_pread(fsp->fh->fd, data, n, offset);
609 END_PROFILE_BYTES(syscall_pread);
611 if (result == -1 && errno == ESPIPE) {
612 /* Maintain the fiction that pipes can be seeked (sought?) on. */
613 result = sys_read(fsp->fh->fd, data, n);
614 fsp->fh->pos = 0;
617 #else /* HAVE_PREAD */
618 errno = ENOSYS;
619 result = -1;
620 #endif /* HAVE_PREAD */
622 return result;
625 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
626 size_t n, off_t offset)
628 ssize_t result;
630 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
631 START_PROFILE_BYTES(syscall_pwrite, n);
632 result = sys_pwrite(fsp->fh->fd, data, n, offset);
633 END_PROFILE_BYTES(syscall_pwrite);
635 if (result == -1 && errno == ESPIPE) {
636 /* Maintain the fiction that pipes can be sought on. */
637 result = sys_write(fsp->fh->fd, data, n);
640 #else /* HAVE_PWRITE */
641 errno = ENOSYS;
642 result = -1;
643 #endif /* HAVE_PWRITE */
645 return result;
648 struct vfswrap_pread_state {
649 ssize_t ret;
650 int fd;
651 void *buf;
652 size_t count;
653 off_t offset;
655 struct vfs_aio_state vfs_aio_state;
656 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
659 static void vfs_pread_do(void *private_data);
660 static void vfs_pread_done(struct tevent_req *subreq);
661 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
663 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
664 TALLOC_CTX *mem_ctx,
665 struct tevent_context *ev,
666 struct files_struct *fsp,
667 void *data,
668 size_t n, off_t offset)
670 struct tevent_req *req, *subreq;
671 struct vfswrap_pread_state *state;
673 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
674 if (req == NULL) {
675 return NULL;
678 state->ret = -1;
679 state->fd = fsp->fh->fd;
680 state->buf = data;
681 state->count = n;
682 state->offset = offset;
684 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
685 state->profile_bytes, n);
686 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
688 subreq = pthreadpool_tevent_job_send(
689 state, ev, handle->conn->sconn->pool,
690 vfs_pread_do, state);
691 if (tevent_req_nomem(subreq, req)) {
692 return tevent_req_post(req, ev);
694 tevent_req_set_callback(subreq, vfs_pread_done, req);
696 talloc_set_destructor(state, vfs_pread_state_destructor);
698 return req;
701 static void vfs_pread_do(void *private_data)
703 struct vfswrap_pread_state *state = talloc_get_type_abort(
704 private_data, struct vfswrap_pread_state);
705 struct timespec start_time;
706 struct timespec end_time;
708 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
710 PROFILE_TIMESTAMP(&start_time);
712 do {
713 state->ret = pread(state->fd, state->buf, state->count,
714 state->offset);
715 } while ((state->ret == -1) && (errno == EINTR));
717 if (state->ret == -1) {
718 state->vfs_aio_state.error = errno;
721 PROFILE_TIMESTAMP(&end_time);
723 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
725 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
728 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
730 return -1;
733 static void vfs_pread_done(struct tevent_req *subreq)
735 struct tevent_req *req = tevent_req_callback_data(
736 subreq, struct tevent_req);
737 struct vfswrap_pread_state *state = tevent_req_data(
738 req, struct vfswrap_pread_state);
739 int ret;
741 ret = pthreadpool_tevent_job_recv(subreq);
742 TALLOC_FREE(subreq);
743 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
744 talloc_set_destructor(state, NULL);
745 if (tevent_req_error(req, ret)) {
746 return;
749 tevent_req_done(req);
752 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
753 struct vfs_aio_state *vfs_aio_state)
755 struct vfswrap_pread_state *state = tevent_req_data(
756 req, struct vfswrap_pread_state);
758 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
759 return -1;
762 *vfs_aio_state = state->vfs_aio_state;
763 return state->ret;
766 struct vfswrap_pwrite_state {
767 ssize_t ret;
768 int fd;
769 const void *buf;
770 size_t count;
771 off_t offset;
773 struct vfs_aio_state vfs_aio_state;
774 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
777 static void vfs_pwrite_do(void *private_data);
778 static void vfs_pwrite_done(struct tevent_req *subreq);
779 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
781 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
782 TALLOC_CTX *mem_ctx,
783 struct tevent_context *ev,
784 struct files_struct *fsp,
785 const void *data,
786 size_t n, off_t offset)
788 struct tevent_req *req, *subreq;
789 struct vfswrap_pwrite_state *state;
791 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
792 if (req == NULL) {
793 return NULL;
796 state->ret = -1;
797 state->fd = fsp->fh->fd;
798 state->buf = data;
799 state->count = n;
800 state->offset = offset;
802 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
803 state->profile_bytes, n);
804 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 subreq = pthreadpool_tevent_job_send(
807 state, ev, handle->conn->sconn->pool,
808 vfs_pwrite_do, state);
809 if (tevent_req_nomem(subreq, req)) {
810 return tevent_req_post(req, ev);
812 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
814 talloc_set_destructor(state, vfs_pwrite_state_destructor);
816 return req;
819 static void vfs_pwrite_do(void *private_data)
821 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
822 private_data, struct vfswrap_pwrite_state);
823 struct timespec start_time;
824 struct timespec end_time;
826 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
828 PROFILE_TIMESTAMP(&start_time);
830 do {
831 state->ret = pwrite(state->fd, state->buf, state->count,
832 state->offset);
833 } while ((state->ret == -1) && (errno == EINTR));
835 if (state->ret == -1) {
836 state->vfs_aio_state.error = errno;
839 PROFILE_TIMESTAMP(&end_time);
841 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
843 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
846 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
848 return -1;
851 static void vfs_pwrite_done(struct tevent_req *subreq)
853 struct tevent_req *req = tevent_req_callback_data(
854 subreq, struct tevent_req);
855 struct vfswrap_pwrite_state *state = tevent_req_data(
856 req, struct vfswrap_pwrite_state);
857 int ret;
859 ret = pthreadpool_tevent_job_recv(subreq);
860 TALLOC_FREE(subreq);
861 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
862 talloc_set_destructor(state, NULL);
863 if (tevent_req_error(req, ret)) {
864 return;
867 tevent_req_done(req);
870 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
871 struct vfs_aio_state *vfs_aio_state)
873 struct vfswrap_pwrite_state *state = tevent_req_data(
874 req, struct vfswrap_pwrite_state);
876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
877 return -1;
880 *vfs_aio_state = state->vfs_aio_state;
881 return state->ret;
884 struct vfswrap_fsync_state {
885 ssize_t ret;
886 int fd;
888 struct vfs_aio_state vfs_aio_state;
889 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
892 static void vfs_fsync_do(void *private_data);
893 static void vfs_fsync_done(struct tevent_req *subreq);
894 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
896 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
897 TALLOC_CTX *mem_ctx,
898 struct tevent_context *ev,
899 struct files_struct *fsp)
901 struct tevent_req *req, *subreq;
902 struct vfswrap_fsync_state *state;
904 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
905 if (req == NULL) {
906 return NULL;
909 state->ret = -1;
910 state->fd = fsp->fh->fd;
912 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
913 state->profile_basic);
915 subreq = pthreadpool_tevent_job_send(
916 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
917 if (tevent_req_nomem(subreq, req)) {
918 return tevent_req_post(req, ev);
920 tevent_req_set_callback(subreq, vfs_fsync_done, req);
922 talloc_set_destructor(state, vfs_fsync_state_destructor);
924 return req;
927 static void vfs_fsync_do(void *private_data)
929 struct vfswrap_fsync_state *state = talloc_get_type_abort(
930 private_data, struct vfswrap_fsync_state);
931 struct timespec start_time;
932 struct timespec end_time;
934 PROFILE_TIMESTAMP(&start_time);
936 do {
937 state->ret = fsync(state->fd);
938 } while ((state->ret == -1) && (errno == EINTR));
940 if (state->ret == -1) {
941 state->vfs_aio_state.error = errno;
944 PROFILE_TIMESTAMP(&end_time);
946 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
949 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
951 return -1;
954 static void vfs_fsync_done(struct tevent_req *subreq)
956 struct tevent_req *req = tevent_req_callback_data(
957 subreq, struct tevent_req);
958 struct vfswrap_fsync_state *state = tevent_req_data(
959 req, struct vfswrap_fsync_state);
960 int ret;
962 ret = pthreadpool_tevent_job_recv(subreq);
963 TALLOC_FREE(subreq);
964 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
965 talloc_set_destructor(state, NULL);
966 if (tevent_req_error(req, ret)) {
967 return;
970 tevent_req_done(req);
973 static int vfswrap_fsync_recv(struct tevent_req *req,
974 struct vfs_aio_state *vfs_aio_state)
976 struct vfswrap_fsync_state *state = tevent_req_data(
977 req, struct vfswrap_fsync_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 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
989 off_t result = 0;
991 START_PROFILE(syscall_lseek);
993 /* Cope with 'stat' file opens. */
994 if (fsp->fh->fd != -1)
995 result = lseek(fsp->fh->fd, offset, whence);
998 * We want to maintain the fiction that we can seek
999 * on a fifo for file system purposes. This allows
1000 * people to set up UNIX fifo's that feed data to Windows
1001 * applications. JRA.
1004 if((result == -1) && (errno == ESPIPE)) {
1005 result = 0;
1006 errno = 0;
1009 END_PROFILE(syscall_lseek);
1010 return result;
1013 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1014 off_t offset, size_t n)
1016 ssize_t result;
1018 START_PROFILE_BYTES(syscall_sendfile, n);
1019 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1020 END_PROFILE_BYTES(syscall_sendfile);
1021 return result;
1024 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1025 int fromfd,
1026 files_struct *tofsp,
1027 off_t offset,
1028 size_t n)
1030 ssize_t result;
1032 START_PROFILE_BYTES(syscall_recvfile, n);
1033 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1034 END_PROFILE_BYTES(syscall_recvfile);
1035 return result;
1038 static int vfswrap_rename(vfs_handle_struct *handle,
1039 const struct smb_filename *smb_fname_src,
1040 const struct smb_filename *smb_fname_dst)
1042 int result = -1;
1044 START_PROFILE(syscall_rename);
1046 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1047 errno = ENOENT;
1048 goto out;
1051 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1053 out:
1054 END_PROFILE(syscall_rename);
1055 return result;
1058 static int vfswrap_stat(vfs_handle_struct *handle,
1059 struct smb_filename *smb_fname)
1061 int result = -1;
1063 START_PROFILE(syscall_stat);
1065 if (smb_fname->stream_name) {
1066 errno = ENOENT;
1067 goto out;
1070 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1071 lp_fake_directory_create_times(SNUM(handle->conn)));
1072 out:
1073 END_PROFILE(syscall_stat);
1074 return result;
1077 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1079 int result;
1081 START_PROFILE(syscall_fstat);
1082 result = sys_fstat(fsp->fh->fd,
1083 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1084 END_PROFILE(syscall_fstat);
1085 return result;
1088 static int vfswrap_lstat(vfs_handle_struct *handle,
1089 struct smb_filename *smb_fname)
1091 int result = -1;
1093 START_PROFILE(syscall_lstat);
1095 if (smb_fname->stream_name) {
1096 errno = ENOENT;
1097 goto out;
1100 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1101 lp_fake_directory_create_times(SNUM(handle->conn)));
1102 out:
1103 END_PROFILE(syscall_lstat);
1104 return result;
1107 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1108 const char *name,
1109 enum vfs_translate_direction direction,
1110 TALLOC_CTX *mem_ctx,
1111 char **mapped_name)
1113 return NT_STATUS_NONE_MAPPED;
1117 * Implement the default fsctl operation.
1119 static bool vfswrap_logged_ioctl_message = false;
1121 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1122 struct files_struct *fsp,
1123 TALLOC_CTX *ctx,
1124 uint32_t function,
1125 uint16_t req_flags, /* Needed for UNICODE ... */
1126 const uint8_t *_in_data,
1127 uint32_t in_len,
1128 uint8_t **_out_data,
1129 uint32_t max_out_len,
1130 uint32_t *out_len)
1132 const char *in_data = (const char *)_in_data;
1133 char **out_data = (char **)_out_data;
1134 NTSTATUS status;
1136 switch (function) {
1137 case FSCTL_SET_SPARSE:
1139 bool set_sparse = true;
1141 if (in_len >= 1 && in_data[0] == 0) {
1142 set_sparse = false;
1145 status = file_set_sparse(handle->conn, fsp, set_sparse);
1147 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1148 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1149 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1150 nt_errstr(status)));
1152 return status;
1155 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1157 unsigned char objid[16];
1158 char *return_data = NULL;
1160 /* This should return the object-id on this file.
1161 * I think I'll make this be the inode+dev. JRA.
1164 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1165 fsp_fnum_dbg(fsp)));
1167 *out_len = MIN(max_out_len, 64);
1169 /* Hmmm, will this cause problems if less data asked for? */
1170 return_data = talloc_array(ctx, char, 64);
1171 if (return_data == NULL) {
1172 return NT_STATUS_NO_MEMORY;
1175 /* For backwards compatibility only store the dev/inode. */
1176 push_file_id_16(return_data, &fsp->file_id);
1177 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1178 push_file_id_16(return_data+32, &fsp->file_id);
1179 memset(return_data+48, 0, 16);
1180 *out_data = return_data;
1181 return NT_STATUS_OK;
1184 case FSCTL_GET_REPARSE_POINT:
1186 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1187 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1188 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1189 return NT_STATUS_NOT_A_REPARSE_POINT;
1192 case FSCTL_SET_REPARSE_POINT:
1194 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1195 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1196 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1197 return NT_STATUS_NOT_A_REPARSE_POINT;
1200 case FSCTL_GET_SHADOW_COPY_DATA:
1203 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1204 * and return their volume names. If max_data_count is 16, then it is just
1205 * asking for the number of volumes and length of the combined names.
1207 * pdata is the data allocated by our caller, but that uses
1208 * total_data_count (which is 0 in our case) rather than max_data_count.
1209 * Allocate the correct amount and return the pointer to let
1210 * it be deallocated when we return.
1212 struct shadow_copy_data *shadow_data = NULL;
1213 bool labels = False;
1214 uint32_t labels_data_count = 0;
1215 uint32_t i;
1216 char *cur_pdata = NULL;
1218 if (max_out_len < 16) {
1219 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1220 max_out_len));
1221 return NT_STATUS_INVALID_PARAMETER;
1224 if (max_out_len > 16) {
1225 labels = True;
1228 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1229 if (shadow_data == NULL) {
1230 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1231 return NT_STATUS_NO_MEMORY;
1235 * Call the VFS routine to actually do the work.
1237 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1238 int log_lev = 0;
1239 if (errno == 0) {
1240 /* broken module didn't set errno on error */
1241 status = NT_STATUS_UNSUCCESSFUL;
1242 } else {
1243 status = map_nt_error_from_unix(errno);
1244 if (NT_STATUS_EQUAL(status,
1245 NT_STATUS_NOT_SUPPORTED)) {
1246 log_lev = 5;
1249 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1250 "connectpath %s, failed - %s.\n",
1251 fsp->conn->connectpath,
1252 nt_errstr(status)));
1253 TALLOC_FREE(shadow_data);
1254 return status;
1257 labels_data_count = (shadow_data->num_volumes * 2 *
1258 sizeof(SHADOW_COPY_LABEL)) + 2;
1260 if (!labels) {
1261 *out_len = 16;
1262 } else {
1263 *out_len = 12 + labels_data_count;
1266 if (max_out_len < *out_len) {
1267 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1268 max_out_len, *out_len));
1269 TALLOC_FREE(shadow_data);
1270 return NT_STATUS_BUFFER_TOO_SMALL;
1273 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1274 if (cur_pdata == NULL) {
1275 TALLOC_FREE(shadow_data);
1276 return NT_STATUS_NO_MEMORY;
1279 *out_data = cur_pdata;
1281 /* num_volumes 4 bytes */
1282 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1284 if (labels) {
1285 /* num_labels 4 bytes */
1286 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1289 /* needed_data_count 4 bytes */
1290 SIVAL(cur_pdata, 8, labels_data_count);
1292 cur_pdata += 12;
1294 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1295 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1296 if (labels && shadow_data->labels) {
1297 for (i=0; i<shadow_data->num_volumes; i++) {
1298 size_t len = 0;
1299 status = srvstr_push(cur_pdata, req_flags,
1300 cur_pdata, shadow_data->labels[i],
1301 2 * sizeof(SHADOW_COPY_LABEL),
1302 STR_UNICODE|STR_TERMINATE, &len);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 TALLOC_FREE(*out_data);
1305 TALLOC_FREE(shadow_data);
1306 return status;
1308 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1309 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1313 TALLOC_FREE(shadow_data);
1315 return NT_STATUS_OK;
1318 case FSCTL_FIND_FILES_BY_SID:
1320 /* pretend this succeeded -
1322 * we have to send back a list with all files owned by this SID
1324 * but I have to check that --metze
1326 struct dom_sid sid;
1327 uid_t uid;
1328 size_t sid_len;
1330 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1331 fsp_fnum_dbg(fsp)));
1333 if (in_len < 8) {
1334 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1335 return NT_STATUS_INVALID_PARAMETER;
1338 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1340 /* unknown 4 bytes: this is not the length of the sid :-( */
1341 /*unknown = IVAL(pdata,0);*/
1343 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1344 return NT_STATUS_INVALID_PARAMETER;
1346 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1348 if (!sid_to_uid(&sid, &uid)) {
1349 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1350 sid_string_dbg(&sid),
1351 (unsigned long)sid_len));
1352 uid = (-1);
1355 /* we can take a look at the find source :-)
1357 * find ./ -uid $uid -name '*' is what we need here
1360 * and send 4bytes len and then NULL terminated unicode strings
1361 * for each file
1363 * but I don't know how to deal with the paged results
1364 * (maybe we can hang the result anywhere in the fsp struct)
1366 * but I don't know how to deal with the paged results
1367 * (maybe we can hang the result anywhere in the fsp struct)
1369 * we don't send all files at once
1370 * and at the next we should *not* start from the beginning,
1371 * so we have to cache the result
1373 * --metze
1376 /* this works for now... */
1377 return NT_STATUS_OK;
1380 case FSCTL_QUERY_ALLOCATED_RANGES:
1382 /* FIXME: This is just a dummy reply, telling that all of the
1383 * file is allocated. MKS cp needs that.
1384 * Adding the real allocated ranges via FIEMAP on Linux
1385 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1386 * this FSCTL correct for sparse files.
1388 uint64_t offset, length;
1389 char *out_data_tmp = NULL;
1391 if (in_len != 16) {
1392 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1393 in_len));
1394 return NT_STATUS_INVALID_PARAMETER;
1397 if (max_out_len < 16) {
1398 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1399 max_out_len));
1400 return NT_STATUS_INVALID_PARAMETER;
1403 offset = BVAL(in_data,0);
1404 length = BVAL(in_data,8);
1406 if (offset + length < offset) {
1407 /* No 64-bit integer wrap. */
1408 return NT_STATUS_INVALID_PARAMETER;
1411 /* Shouldn't this be SMB_VFS_STAT ... ? */
1412 status = vfs_stat_fsp(fsp);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 return status;
1417 *out_len = 16;
1418 out_data_tmp = talloc_array(ctx, char, *out_len);
1419 if (out_data_tmp == NULL) {
1420 DEBUG(10, ("unable to allocate memory for response\n"));
1421 return NT_STATUS_NO_MEMORY;
1424 if (offset > fsp->fsp_name->st.st_ex_size ||
1425 fsp->fsp_name->st.st_ex_size == 0 ||
1426 length == 0) {
1427 memset(out_data_tmp, 0, *out_len);
1428 } else {
1429 uint64_t end = offset + length;
1430 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1431 SBVAL(out_data_tmp, 0, 0);
1432 SBVAL(out_data_tmp, 8, end);
1435 *out_data = out_data_tmp;
1437 return NT_STATUS_OK;
1440 case FSCTL_IS_VOLUME_DIRTY:
1442 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1443 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1445 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1446 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1448 return NT_STATUS_INVALID_PARAMETER;
1451 default:
1453 * Only print once ... unfortunately there could be lots of
1454 * different FSCTLs that are called.
1456 if (!vfswrap_logged_ioctl_message) {
1457 vfswrap_logged_ioctl_message = true;
1458 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1459 __func__, function));
1463 return NT_STATUS_NOT_SUPPORTED;
1466 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1467 const struct smb_filename *fname,
1468 SMB_STRUCT_STAT *sbuf);
1470 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1471 struct smb_filename *smb_fname,
1472 uint32_t *dosmode)
1474 bool offline;
1476 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1477 if (offline) {
1478 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1481 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1484 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1485 struct files_struct *fsp,
1486 uint32_t *dosmode)
1488 bool offline;
1490 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1491 if (offline) {
1492 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1495 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1498 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1499 const struct smb_filename *smb_fname,
1500 uint32_t dosmode)
1502 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1505 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1506 struct files_struct *fsp,
1507 uint32_t dosmode)
1509 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1512 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1514 struct vfswrap_offload_read_state {
1515 DATA_BLOB token;
1518 static struct tevent_req *vfswrap_offload_read_send(
1519 TALLOC_CTX *mem_ctx,
1520 struct tevent_context *ev,
1521 struct vfs_handle_struct *handle,
1522 struct files_struct *fsp,
1523 uint32_t fsctl,
1524 uint32_t ttl,
1525 off_t offset,
1526 size_t to_copy)
1528 struct tevent_req *req = NULL;
1529 struct vfswrap_offload_read_state *state = NULL;
1530 NTSTATUS status;
1532 req = tevent_req_create(mem_ctx, &state,
1533 struct vfswrap_offload_read_state);
1534 if (req == NULL) {
1535 return NULL;
1538 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1539 &vfswrap_offload_ctx);
1540 if (tevent_req_nterror(req, status)) {
1541 return tevent_req_post(req, ev);
1544 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1545 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1546 return tevent_req_post(req, ev);
1549 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1550 &state->token);
1551 if (tevent_req_nterror(req, status)) {
1552 return tevent_req_post(req, ev);
1555 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1556 &state->token);
1557 if (tevent_req_nterror(req, status)) {
1558 return tevent_req_post(req, ev);
1561 tevent_req_done(req);
1562 return tevent_req_post(req, ev);
1565 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1566 struct vfs_handle_struct *handle,
1567 TALLOC_CTX *mem_ctx,
1568 DATA_BLOB *token)
1570 struct vfswrap_offload_read_state *state = tevent_req_data(
1571 req, struct vfswrap_offload_read_state);
1572 NTSTATUS status;
1574 if (tevent_req_is_nterror(req, &status)) {
1575 tevent_req_received(req);
1576 return status;
1579 token->length = state->token.length;
1580 token->data = talloc_move(mem_ctx, &state->token.data);
1582 tevent_req_received(req);
1583 return NT_STATUS_OK;
1586 struct vfswrap_offload_write_state {
1587 struct tevent_context *ev;
1588 uint8_t *buf;
1589 bool read_lck_locked;
1590 bool write_lck_locked;
1591 DATA_BLOB *token;
1592 struct files_struct *src_fsp;
1593 off_t src_off;
1594 struct files_struct *dst_fsp;
1595 off_t dst_off;
1596 off_t to_copy;
1597 off_t remaining;
1598 size_t next_io_size;
1601 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1602 enum tevent_req_state req_state)
1604 struct vfswrap_offload_write_state *state = tevent_req_data(
1605 req, struct vfswrap_offload_write_state);
1606 bool ok;
1608 if (state->dst_fsp == NULL) {
1609 return;
1612 ok = change_to_user_by_fsp(state->dst_fsp);
1613 SMB_ASSERT(ok);
1614 state->dst_fsp = NULL;
1617 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1619 static struct tevent_req *vfswrap_offload_write_send(
1620 struct vfs_handle_struct *handle,
1621 TALLOC_CTX *mem_ctx,
1622 struct tevent_context *ev,
1623 uint32_t fsctl,
1624 DATA_BLOB *token,
1625 off_t transfer_offset,
1626 struct files_struct *dest_fsp,
1627 off_t dest_off,
1628 off_t to_copy)
1630 struct tevent_req *req;
1631 struct vfswrap_offload_write_state *state = NULL;
1632 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1633 files_struct *src_fsp = NULL;
1634 NTSTATUS status;
1635 bool ok;
1637 req = tevent_req_create(mem_ctx, &state,
1638 struct vfswrap_offload_write_state);
1639 if (req == NULL) {
1640 return NULL;
1643 *state = (struct vfswrap_offload_write_state) {
1644 .ev = ev,
1645 .token = token,
1646 .src_off = transfer_offset,
1647 .dst_fsp = dest_fsp,
1648 .dst_off = dest_off,
1649 .to_copy = to_copy,
1650 .remaining = to_copy,
1653 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1655 switch (fsctl) {
1656 case FSCTL_SRV_COPYCHUNK:
1657 case FSCTL_SRV_COPYCHUNK_WRITE:
1658 break;
1660 case FSCTL_OFFLOAD_WRITE:
1661 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1662 return tevent_req_post(req, ev);
1664 case FSCTL_DUP_EXTENTS_TO_FILE:
1665 DBG_DEBUG("COW clones not supported by vfs_default\n");
1666 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1667 return tevent_req_post(req, ev);
1669 default:
1670 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1671 return tevent_req_post(req, ev);
1675 * From here on we assume a copy-chunk fsctl
1678 if (to_copy == 0) {
1679 tevent_req_done(req);
1680 return tevent_req_post(req, ev);
1683 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1684 token, &src_fsp);
1685 if (tevent_req_nterror(req, status)) {
1686 return tevent_req_post(req, ev);
1688 state->src_fsp = src_fsp;
1690 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1692 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1693 if (!NT_STATUS_IS_OK(status)) {
1694 tevent_req_nterror(req, status);
1695 return tevent_req_post(req, ev);
1698 ok = change_to_user_by_fsp(src_fsp);
1699 if (!ok) {
1700 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
1701 return tevent_req_post(req, ev);
1704 state->buf = talloc_array(state, uint8_t, num);
1705 if (tevent_req_nomem(state->buf, req)) {
1706 return tevent_req_post(req, ev);
1709 status = vfs_stat_fsp(src_fsp);
1710 if (tevent_req_nterror(req, status)) {
1711 return tevent_req_post(req, ev);
1714 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1716 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1717 * If the SourceOffset or SourceOffset + Length extends beyond
1718 * the end of file, the server SHOULD<240> treat this as a
1719 * STATUS_END_OF_FILE error.
1720 * ...
1721 * <240> Section 3.3.5.15.6: Windows servers will return
1722 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1724 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1725 return tevent_req_post(req, ev);
1728 status = vfswrap_offload_write_loop(req);
1729 if (!NT_STATUS_IS_OK(status)) {
1730 tevent_req_nterror(req, status);
1731 return tevent_req_post(req, ev);
1734 return req;
1737 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1739 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1741 struct vfswrap_offload_write_state *state = tevent_req_data(
1742 req, struct vfswrap_offload_write_state);
1743 struct tevent_req *subreq = NULL;
1744 struct lock_struct read_lck;
1745 bool ok;
1748 * This is called under the context of state->src_fsp.
1751 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1753 init_strict_lock_struct(state->src_fsp,
1754 state->src_fsp->op->global->open_persistent_id,
1755 state->src_off,
1756 state->next_io_size,
1757 READ_LOCK,
1758 &read_lck);
1760 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1761 state->src_fsp,
1762 &read_lck);
1763 if (!ok) {
1764 return NT_STATUS_FILE_LOCK_CONFLICT;
1767 subreq = SMB_VFS_PREAD_SEND(state,
1768 state->src_fsp->conn->sconn->ev_ctx,
1769 state->src_fsp,
1770 state->buf,
1771 state->next_io_size,
1772 state->src_off);
1773 if (subreq == NULL) {
1774 return NT_STATUS_NO_MEMORY;
1776 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1778 return NT_STATUS_OK;
1781 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1783 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1785 struct tevent_req *req = tevent_req_callback_data(
1786 subreq, struct tevent_req);
1787 struct vfswrap_offload_write_state *state = tevent_req_data(
1788 req, struct vfswrap_offload_write_state);
1789 struct vfs_aio_state aio_state;
1790 struct lock_struct write_lck;
1791 ssize_t nread;
1792 bool ok;
1794 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1795 TALLOC_FREE(subreq);
1796 if (nread == -1) {
1797 DBG_ERR("read failed: %s\n", strerror(errno));
1798 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1799 return;
1801 if (nread != state->next_io_size) {
1802 DBG_ERR("Short read, only %zd of %zu\n",
1803 nread, state->next_io_size);
1804 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1805 return;
1808 state->src_off += nread;
1810 ok = change_to_user_by_fsp(state->dst_fsp);
1811 if (!ok) {
1812 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1813 return;
1816 init_strict_lock_struct(state->dst_fsp,
1817 state->dst_fsp->op->global->open_persistent_id,
1818 state->dst_off,
1819 state->next_io_size,
1820 WRITE_LOCK,
1821 &write_lck);
1823 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1824 state->dst_fsp,
1825 &write_lck);
1826 if (!ok) {
1827 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1828 return;
1831 subreq = SMB_VFS_PWRITE_SEND(state,
1832 state->ev,
1833 state->dst_fsp,
1834 state->buf,
1835 state->next_io_size,
1836 state->dst_off);
1837 if (subreq == NULL) {
1838 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1839 return;
1841 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1844 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1846 struct tevent_req *req = tevent_req_callback_data(
1847 subreq, struct tevent_req);
1848 struct vfswrap_offload_write_state *state = tevent_req_data(
1849 req, struct vfswrap_offload_write_state);
1850 struct vfs_aio_state aio_state;
1851 ssize_t nwritten;
1852 NTSTATUS status;
1853 bool ok;
1855 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1856 TALLOC_FREE(subreq);
1857 if (nwritten == -1) {
1858 DBG_ERR("write failed: %s\n", strerror(errno));
1859 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1860 return;
1862 if (nwritten != state->next_io_size) {
1863 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1864 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1865 return;
1868 state->dst_off += nwritten;
1870 if (state->remaining < nwritten) {
1871 /* Paranoia check */
1872 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1873 return;
1875 state->remaining -= nwritten;
1876 if (state->remaining == 0) {
1877 tevent_req_done(req);
1878 return;
1881 ok = change_to_user_by_fsp(state->src_fsp);
1882 if (!ok) {
1883 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1884 return;
1887 status = vfswrap_offload_write_loop(req);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 tevent_req_nterror(req, status);
1890 return;
1893 return;
1896 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1897 struct tevent_req *req,
1898 off_t *copied)
1900 struct vfswrap_offload_write_state *state = tevent_req_data(
1901 req, struct vfswrap_offload_write_state);
1902 NTSTATUS status;
1904 if (tevent_req_is_nterror(req, &status)) {
1905 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1906 *copied = 0;
1907 tevent_req_received(req);
1908 return status;
1911 *copied = state->to_copy;
1912 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1913 tevent_req_received(req);
1915 return NT_STATUS_OK;
1918 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1919 TALLOC_CTX *mem_ctx,
1920 struct files_struct *fsp,
1921 struct smb_filename *smb_fname,
1922 uint16_t *_compression_fmt)
1924 return NT_STATUS_INVALID_DEVICE_REQUEST;
1927 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1928 TALLOC_CTX *mem_ctx,
1929 struct files_struct *fsp,
1930 uint16_t compression_fmt)
1932 return NT_STATUS_INVALID_DEVICE_REQUEST;
1935 /********************************************************************
1936 Given a stat buffer return the allocated size on disk, taking into
1937 account sparse files.
1938 ********************************************************************/
1939 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1940 struct files_struct *fsp,
1941 const SMB_STRUCT_STAT *sbuf)
1943 uint64_t result;
1945 START_PROFILE(syscall_get_alloc_size);
1947 if(S_ISDIR(sbuf->st_ex_mode)) {
1948 result = 0;
1949 goto out;
1952 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1953 /* The type of st_blocksize is blkcnt_t which *MUST* be
1954 signed (according to POSIX) and can be less than 64-bits.
1955 Ensure when we're converting to 64 bits wide we don't
1956 sign extend. */
1957 #if defined(SIZEOF_BLKCNT_T_8)
1958 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1959 #elif defined(SIZEOF_BLKCNT_T_4)
1961 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1962 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1964 #else
1965 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1966 #endif
1967 if (result == 0) {
1969 * Some file systems do not allocate a block for very
1970 * small files. But for non-empty file should report a
1971 * positive size.
1974 uint64_t filesize = get_file_size_stat(sbuf);
1975 if (filesize > 0) {
1976 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1979 #else
1980 result = get_file_size_stat(sbuf);
1981 #endif
1983 if (fsp && fsp->initial_allocation_size)
1984 result = MAX(result,fsp->initial_allocation_size);
1986 result = smb_roundup(handle->conn, result);
1988 out:
1989 END_PROFILE(syscall_get_alloc_size);
1990 return result;
1993 static int vfswrap_unlink(vfs_handle_struct *handle,
1994 const struct smb_filename *smb_fname)
1996 int result = -1;
1998 START_PROFILE(syscall_unlink);
2000 if (smb_fname->stream_name) {
2001 errno = ENOENT;
2002 goto out;
2004 result = unlink(smb_fname->base_name);
2006 out:
2007 END_PROFILE(syscall_unlink);
2008 return result;
2011 static int vfswrap_chmod(vfs_handle_struct *handle,
2012 const struct smb_filename *smb_fname,
2013 mode_t mode)
2015 int result;
2017 START_PROFILE(syscall_chmod);
2018 result = chmod(smb_fname->base_name, mode);
2019 END_PROFILE(syscall_chmod);
2020 return result;
2023 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2025 int result;
2027 START_PROFILE(syscall_fchmod);
2028 #if defined(HAVE_FCHMOD)
2029 result = fchmod(fsp->fh->fd, mode);
2030 #else
2031 result = -1;
2032 errno = ENOSYS;
2033 #endif
2035 END_PROFILE(syscall_fchmod);
2036 return result;
2039 static int vfswrap_chown(vfs_handle_struct *handle,
2040 const struct smb_filename *smb_fname,
2041 uid_t uid,
2042 gid_t gid)
2044 int result;
2046 START_PROFILE(syscall_chown);
2047 result = chown(smb_fname->base_name, uid, gid);
2048 END_PROFILE(syscall_chown);
2049 return result;
2052 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2054 #ifdef HAVE_FCHOWN
2055 int result;
2057 START_PROFILE(syscall_fchown);
2058 result = fchown(fsp->fh->fd, uid, gid);
2059 END_PROFILE(syscall_fchown);
2060 return result;
2061 #else
2062 errno = ENOSYS;
2063 return -1;
2064 #endif
2067 static int vfswrap_lchown(vfs_handle_struct *handle,
2068 const struct smb_filename *smb_fname,
2069 uid_t uid,
2070 gid_t gid)
2072 int result;
2074 START_PROFILE(syscall_lchown);
2075 result = lchown(smb_fname->base_name, uid, gid);
2076 END_PROFILE(syscall_lchown);
2077 return result;
2080 static int vfswrap_chdir(vfs_handle_struct *handle,
2081 const struct smb_filename *smb_fname)
2083 int result;
2085 START_PROFILE(syscall_chdir);
2086 result = chdir(smb_fname->base_name);
2087 END_PROFILE(syscall_chdir);
2088 return result;
2091 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2092 TALLOC_CTX *ctx)
2094 char *result;
2095 struct smb_filename *smb_fname = NULL;
2097 START_PROFILE(syscall_getwd);
2098 result = sys_getwd();
2099 END_PROFILE(syscall_getwd);
2101 if (result == NULL) {
2102 return NULL;
2104 smb_fname = synthetic_smb_fname(ctx,
2105 result,
2106 NULL,
2107 NULL,
2110 * sys_getwd() *always* returns malloced memory.
2111 * We must free here to avoid leaks:
2112 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2114 SAFE_FREE(result);
2115 return smb_fname;
2118 /*********************************************************************
2119 nsec timestamp resolution call. Convert down to whatever the underlying
2120 system will support.
2121 **********************************************************************/
2123 static int vfswrap_ntimes(vfs_handle_struct *handle,
2124 const struct smb_filename *smb_fname,
2125 struct smb_file_time *ft)
2127 int result = -1;
2129 START_PROFILE(syscall_ntimes);
2131 if (smb_fname->stream_name) {
2132 errno = ENOENT;
2133 goto out;
2136 if (ft != NULL) {
2137 if (null_timespec(ft->atime)) {
2138 ft->atime= smb_fname->st.st_ex_atime;
2141 if (null_timespec(ft->mtime)) {
2142 ft->mtime = smb_fname->st.st_ex_mtime;
2145 if (!null_timespec(ft->create_time)) {
2146 set_create_timespec_ea(handle->conn,
2147 smb_fname,
2148 ft->create_time);
2151 if ((timespec_compare(&ft->atime,
2152 &smb_fname->st.st_ex_atime) == 0) &&
2153 (timespec_compare(&ft->mtime,
2154 &smb_fname->st.st_ex_mtime) == 0)) {
2155 return 0;
2159 #if defined(HAVE_UTIMENSAT)
2160 if (ft != NULL) {
2161 struct timespec ts[2];
2162 ts[0] = ft->atime;
2163 ts[1] = ft->mtime;
2164 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2165 } else {
2166 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2168 if (!((result == -1) && (errno == ENOSYS))) {
2169 goto out;
2171 #endif
2172 #if defined(HAVE_UTIMES)
2173 if (ft != NULL) {
2174 struct timeval tv[2];
2175 tv[0] = convert_timespec_to_timeval(ft->atime);
2176 tv[1] = convert_timespec_to_timeval(ft->mtime);
2177 result = utimes(smb_fname->base_name, tv);
2178 } else {
2179 result = utimes(smb_fname->base_name, NULL);
2181 if (!((result == -1) && (errno == ENOSYS))) {
2182 goto out;
2184 #endif
2185 #if defined(HAVE_UTIME)
2186 if (ft != NULL) {
2187 struct utimbuf times;
2188 times.actime = convert_timespec_to_time_t(ft->atime);
2189 times.modtime = convert_timespec_to_time_t(ft->mtime);
2190 result = utime(smb_fname->base_name, &times);
2191 } else {
2192 result = utime(smb_fname->base_name, NULL);
2194 if (!((result == -1) && (errno == ENOSYS))) {
2195 goto out;
2197 #endif
2198 errno = ENOSYS;
2199 result = -1;
2201 out:
2202 END_PROFILE(syscall_ntimes);
2203 return result;
2206 /*********************************************************************
2207 A version of ftruncate that will write the space on disk if strict
2208 allocate is set.
2209 **********************************************************************/
2211 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2213 off_t space_to_write;
2214 uint64_t space_avail;
2215 uint64_t bsize,dfree,dsize;
2216 int ret;
2217 NTSTATUS status;
2218 SMB_STRUCT_STAT *pst;
2220 status = vfs_stat_fsp(fsp);
2221 if (!NT_STATUS_IS_OK(status)) {
2222 return -1;
2224 pst = &fsp->fsp_name->st;
2226 #ifdef S_ISFIFO
2227 if (S_ISFIFO(pst->st_ex_mode))
2228 return 0;
2229 #endif
2231 if (pst->st_ex_size == len)
2232 return 0;
2234 /* Shrink - just ftruncate. */
2235 if (pst->st_ex_size > len)
2236 return ftruncate(fsp->fh->fd, len);
2238 space_to_write = len - pst->st_ex_size;
2240 /* for allocation try fallocate first. This can fail on some
2241 platforms e.g. when the filesystem doesn't support it and no
2242 emulation is being done by the libc (like on AIX with JFS1). In that
2243 case we do our own emulation. fallocate implementations can
2244 return ENOTSUP or EINVAL in cases like that. */
2245 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2246 if (ret == -1 && errno == ENOSPC) {
2247 return -1;
2249 if (ret == 0) {
2250 return 0;
2252 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2253 "error %d. Falling back to slow manual allocation\n", errno));
2255 /* available disk space is enough or not? */
2256 space_avail =
2257 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2258 /* space_avail is 1k blocks */
2259 if (space_avail == (uint64_t)-1 ||
2260 ((uint64_t)space_to_write/1024 > space_avail) ) {
2261 errno = ENOSPC;
2262 return -1;
2265 /* Write out the real space on disk. */
2266 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2267 if (ret != 0) {
2268 return -1;
2271 return 0;
2274 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2276 int result = -1;
2277 SMB_STRUCT_STAT *pst;
2278 NTSTATUS status;
2279 char c = 0;
2281 START_PROFILE(syscall_ftruncate);
2283 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2284 result = strict_allocate_ftruncate(handle, fsp, len);
2285 END_PROFILE(syscall_ftruncate);
2286 return result;
2289 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2290 ftruncate if the system supports it. Then I discovered that
2291 you can have some filesystems that support ftruncate
2292 expansion and some that don't! On Linux fat can't do
2293 ftruncate extend but ext2 can. */
2295 result = ftruncate(fsp->fh->fd, len);
2297 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2298 extend a file with ftruncate. Provide alternate implementation
2299 for this */
2301 /* Do an fstat to see if the file is longer than the requested
2302 size in which case the ftruncate above should have
2303 succeeded or shorter, in which case seek to len - 1 and
2304 write 1 byte of zero */
2305 status = vfs_stat_fsp(fsp);
2306 if (!NT_STATUS_IS_OK(status)) {
2307 goto done;
2310 /* We need to update the files_struct after successful ftruncate */
2311 if (result == 0) {
2312 goto done;
2315 pst = &fsp->fsp_name->st;
2317 #ifdef S_ISFIFO
2318 if (S_ISFIFO(pst->st_ex_mode)) {
2319 result = 0;
2320 goto done;
2322 #endif
2324 if (pst->st_ex_size == len) {
2325 result = 0;
2326 goto done;
2329 if (pst->st_ex_size > len) {
2330 /* the ftruncate should have worked */
2331 goto done;
2334 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2335 goto done;
2338 result = 0;
2340 done:
2342 END_PROFILE(syscall_ftruncate);
2343 return result;
2346 static int vfswrap_fallocate(vfs_handle_struct *handle,
2347 files_struct *fsp,
2348 uint32_t mode,
2349 off_t offset,
2350 off_t len)
2352 int result;
2354 START_PROFILE(syscall_fallocate);
2355 if (mode == 0) {
2356 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2358 * posix_fallocate returns 0 on success, errno on error
2359 * and doesn't set errno. Make it behave like fallocate()
2360 * which returns -1, and sets errno on failure.
2362 if (result != 0) {
2363 errno = result;
2364 result = -1;
2366 } else {
2367 /* sys_fallocate handles filtering of unsupported mode flags */
2368 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2370 END_PROFILE(syscall_fallocate);
2371 return result;
2374 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2376 bool result;
2378 START_PROFILE(syscall_fcntl_lock);
2380 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2381 "smbd",
2382 "force process locks",
2383 false)) {
2384 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2387 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2388 END_PROFILE(syscall_fcntl_lock);
2389 return result;
2392 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2393 uint32_t share_mode, uint32_t access_mask)
2395 START_PROFILE(syscall_kernel_flock);
2396 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2397 END_PROFILE(syscall_kernel_flock);
2398 return 0;
2401 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2403 bool result;
2404 int op = F_GETLK;
2406 START_PROFILE(syscall_fcntl_getlock);
2408 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2409 "smbd",
2410 "force process locks",
2411 false)) {
2412 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2415 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2416 END_PROFILE(syscall_fcntl_getlock);
2417 return result;
2420 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2421 int leasetype)
2423 int result = -1;
2425 START_PROFILE(syscall_linux_setlease);
2427 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2428 result = linux_setlease(fsp->fh->fd, leasetype);
2429 #else
2430 errno = ENOSYS;
2431 #endif
2432 END_PROFILE(syscall_linux_setlease);
2433 return result;
2436 static int vfswrap_symlink(vfs_handle_struct *handle,
2437 const char *link_target,
2438 const struct smb_filename *new_smb_fname)
2440 int result;
2442 START_PROFILE(syscall_symlink);
2443 result = symlink(link_target, new_smb_fname->base_name);
2444 END_PROFILE(syscall_symlink);
2445 return result;
2448 static int vfswrap_readlink(vfs_handle_struct *handle,
2449 const struct smb_filename *smb_fname,
2450 char *buf,
2451 size_t bufsiz)
2453 int result;
2455 START_PROFILE(syscall_readlink);
2456 result = readlink(smb_fname->base_name, buf, bufsiz);
2457 END_PROFILE(syscall_readlink);
2458 return result;
2461 static int vfswrap_link(vfs_handle_struct *handle,
2462 const struct smb_filename *old_smb_fname,
2463 const struct smb_filename *new_smb_fname)
2465 int result;
2467 START_PROFILE(syscall_link);
2468 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2469 END_PROFILE(syscall_link);
2470 return result;
2473 static int vfswrap_mknod(vfs_handle_struct *handle,
2474 const struct smb_filename *smb_fname,
2475 mode_t mode,
2476 SMB_DEV_T dev)
2478 int result;
2480 START_PROFILE(syscall_mknod);
2481 result = sys_mknod(smb_fname->base_name, mode, dev);
2482 END_PROFILE(syscall_mknod);
2483 return result;
2486 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2487 TALLOC_CTX *ctx,
2488 const struct smb_filename *smb_fname)
2490 char *result;
2491 struct smb_filename *result_fname = NULL;
2493 START_PROFILE(syscall_realpath);
2494 result = sys_realpath(smb_fname->base_name);
2495 END_PROFILE(syscall_realpath);
2496 if (result) {
2497 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2498 SAFE_FREE(result);
2500 return result_fname;
2503 static int vfswrap_chflags(vfs_handle_struct *handle,
2504 const struct smb_filename *smb_fname,
2505 unsigned int flags)
2507 #ifdef HAVE_CHFLAGS
2508 return chflags(smb_fname->base_name, flags);
2509 #else
2510 errno = ENOSYS;
2511 return -1;
2512 #endif
2515 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2516 const SMB_STRUCT_STAT *sbuf)
2518 struct file_id key;
2520 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2521 * blob */
2522 ZERO_STRUCT(key);
2524 key.devid = sbuf->st_ex_dev;
2525 key.inode = sbuf->st_ex_ino;
2526 /* key.extid is unused by default. */
2528 return key;
2531 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2532 struct files_struct *fsp,
2533 const struct smb_filename *smb_fname,
2534 TALLOC_CTX *mem_ctx,
2535 unsigned int *pnum_streams,
2536 struct stream_struct **pstreams)
2538 SMB_STRUCT_STAT sbuf;
2539 struct stream_struct *tmp_streams = NULL;
2540 int ret;
2542 if ((fsp != NULL) && (fsp->is_directory)) {
2544 * No default streams on directories
2546 goto done;
2549 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2550 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2552 else {
2553 struct smb_filename smb_fname_cp;
2555 ZERO_STRUCT(smb_fname_cp);
2556 smb_fname_cp.base_name = discard_const_p(char,
2557 smb_fname->base_name);
2558 smb_fname_cp.flags = smb_fname->flags;
2560 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2561 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2562 } else {
2563 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2565 sbuf = smb_fname_cp.st;
2568 if (ret == -1) {
2569 return map_nt_error_from_unix(errno);
2572 if (S_ISDIR(sbuf.st_ex_mode)) {
2573 goto done;
2576 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2577 (*pnum_streams) + 1);
2578 if (tmp_streams == NULL) {
2579 return NT_STATUS_NO_MEMORY;
2581 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2582 if (tmp_streams[*pnum_streams].name == NULL) {
2583 return NT_STATUS_NO_MEMORY;
2585 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2586 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2588 *pnum_streams += 1;
2589 *pstreams = tmp_streams;
2590 done:
2591 return NT_STATUS_OK;
2594 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2595 const char *path,
2596 const char *name,
2597 TALLOC_CTX *mem_ctx,
2598 char **found_name)
2601 * Don't fall back to get_real_filename so callers can differentiate
2602 * between a full directory scan and an actual case-insensitive stat.
2604 errno = EOPNOTSUPP;
2605 return -1;
2608 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2609 const struct smb_filename *smb_fname)
2611 return handle->conn->connectpath;
2614 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2615 struct byte_range_lock *br_lck,
2616 struct lock_struct *plock,
2617 bool blocking_lock)
2619 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2621 /* Note: blr is not used in the default implementation. */
2622 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2625 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2626 struct messaging_context *msg_ctx,
2627 struct byte_range_lock *br_lck,
2628 const struct lock_struct *plock)
2630 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2632 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2635 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2636 struct byte_range_lock *br_lck,
2637 struct lock_struct *plock)
2639 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2641 /* Note: blr is not used in the default implementation. */
2642 return brl_lock_cancel_default(br_lck, plock);
2645 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2646 files_struct *fsp,
2647 struct lock_struct *plock)
2649 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2650 plock->lock_type == WRITE_LOCK);
2652 return strict_lock_check_default(fsp, plock);
2655 /* NT ACL operations. */
2657 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2658 files_struct *fsp,
2659 uint32_t security_info,
2660 TALLOC_CTX *mem_ctx,
2661 struct security_descriptor **ppdesc)
2663 NTSTATUS result;
2665 START_PROFILE(fget_nt_acl);
2666 result = posix_fget_nt_acl(fsp, security_info,
2667 mem_ctx, ppdesc);
2668 END_PROFILE(fget_nt_acl);
2669 return result;
2672 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2673 const struct smb_filename *smb_fname,
2674 uint32_t security_info,
2675 TALLOC_CTX *mem_ctx,
2676 struct security_descriptor **ppdesc)
2678 NTSTATUS result;
2680 START_PROFILE(get_nt_acl);
2681 result = posix_get_nt_acl(handle->conn,
2682 smb_fname,
2683 security_info,
2684 mem_ctx,
2685 ppdesc);
2686 END_PROFILE(get_nt_acl);
2687 return result;
2690 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2692 NTSTATUS result;
2694 START_PROFILE(fset_nt_acl);
2695 result = set_nt_acl(fsp, security_info_sent, psd);
2696 END_PROFILE(fset_nt_acl);
2697 return result;
2700 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2701 struct smb_filename *file,
2702 struct security_acl *sacl,
2703 uint32_t access_requested,
2704 uint32_t access_denied)
2706 return NT_STATUS_OK; /* Nothing to do here ... */
2709 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2710 const struct smb_filename *smb_fname,
2711 SMB_ACL_TYPE_T type,
2712 TALLOC_CTX *mem_ctx)
2714 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2717 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2718 files_struct *fsp,
2719 TALLOC_CTX *mem_ctx)
2721 return sys_acl_get_fd(handle, fsp, mem_ctx);
2724 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2725 const struct smb_filename *smb_fname,
2726 SMB_ACL_TYPE_T acltype,
2727 SMB_ACL_T theacl)
2729 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2732 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2734 return sys_acl_set_fd(handle, fsp, theacl);
2737 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2738 const struct smb_filename *smb_fname)
2740 return sys_acl_delete_def_file(handle, smb_fname);
2743 /****************************************************************
2744 Extended attribute operations.
2745 *****************************************************************/
2747 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2748 const struct smb_filename *smb_fname,
2749 const char *name,
2750 void *value,
2751 size_t size)
2753 return getxattr(smb_fname->base_name, name, value, size);
2756 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2758 return fgetxattr(fsp->fh->fd, name, value, size);
2761 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2762 const struct smb_filename *smb_fname,
2763 char *list,
2764 size_t size)
2766 return listxattr(smb_fname->base_name, list, size);
2769 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2771 return flistxattr(fsp->fh->fd, list, size);
2774 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2775 const struct smb_filename *smb_fname,
2776 const char *name)
2778 return removexattr(smb_fname->base_name, name);
2781 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2783 return fremovexattr(fsp->fh->fd, name);
2786 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2787 const struct smb_filename *smb_fname,
2788 const char *name,
2789 const void *value,
2790 size_t size,
2791 int flags)
2793 return setxattr(smb_fname->base_name, name, value, size, flags);
2796 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2798 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2801 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2803 return false;
2806 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2807 const struct smb_filename *fname,
2808 SMB_STRUCT_STAT *sbuf)
2810 NTSTATUS status;
2811 char *path;
2812 bool offline = false;
2814 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2815 return false;
2818 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2819 #if defined(ENOTSUP)
2820 errno = ENOTSUP;
2821 #endif
2822 return false;
2825 status = get_full_smb_filename(talloc_tos(), fname, &path);
2826 if (!NT_STATUS_IS_OK(status)) {
2827 errno = map_errno_from_nt_status(status);
2828 return false;
2831 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2833 TALLOC_FREE(path);
2835 return offline;
2838 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2839 struct files_struct *fsp,
2840 TALLOC_CTX *mem_ctx,
2841 DATA_BLOB *cookie)
2843 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2846 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2847 struct files_struct *fsp,
2848 const DATA_BLOB old_cookie,
2849 TALLOC_CTX *mem_ctx,
2850 DATA_BLOB *new_cookie)
2852 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2853 new_cookie);
2856 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2857 struct smb_request *smb1req,
2858 struct smbXsrv_open *op,
2859 const DATA_BLOB old_cookie,
2860 TALLOC_CTX *mem_ctx,
2861 struct files_struct **fsp,
2862 DATA_BLOB *new_cookie)
2864 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2865 old_cookie, mem_ctx,
2866 fsp, new_cookie);
2869 static struct vfs_fn_pointers vfs_default_fns = {
2870 /* Disk operations */
2872 .connect_fn = vfswrap_connect,
2873 .disconnect_fn = vfswrap_disconnect,
2874 .disk_free_fn = vfswrap_disk_free,
2875 .get_quota_fn = vfswrap_get_quota,
2876 .set_quota_fn = vfswrap_set_quota,
2877 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2878 .statvfs_fn = vfswrap_statvfs,
2879 .fs_capabilities_fn = vfswrap_fs_capabilities,
2880 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2881 .snap_check_path_fn = vfswrap_snap_check_path,
2882 .snap_create_fn = vfswrap_snap_create,
2883 .snap_delete_fn = vfswrap_snap_delete,
2885 /* Directory operations */
2887 .opendir_fn = vfswrap_opendir,
2888 .fdopendir_fn = vfswrap_fdopendir,
2889 .readdir_fn = vfswrap_readdir,
2890 .readdir_attr_fn = vfswrap_readdir_attr,
2891 .seekdir_fn = vfswrap_seekdir,
2892 .telldir_fn = vfswrap_telldir,
2893 .rewind_dir_fn = vfswrap_rewinddir,
2894 .mkdir_fn = vfswrap_mkdir,
2895 .rmdir_fn = vfswrap_rmdir,
2896 .closedir_fn = vfswrap_closedir,
2898 /* File operations */
2900 .open_fn = vfswrap_open,
2901 .create_file_fn = vfswrap_create_file,
2902 .close_fn = vfswrap_close,
2903 .pread_fn = vfswrap_pread,
2904 .pread_send_fn = vfswrap_pread_send,
2905 .pread_recv_fn = vfswrap_pread_recv,
2906 .pwrite_fn = vfswrap_pwrite,
2907 .pwrite_send_fn = vfswrap_pwrite_send,
2908 .pwrite_recv_fn = vfswrap_pwrite_recv,
2909 .lseek_fn = vfswrap_lseek,
2910 .sendfile_fn = vfswrap_sendfile,
2911 .recvfile_fn = vfswrap_recvfile,
2912 .rename_fn = vfswrap_rename,
2913 .fsync_send_fn = vfswrap_fsync_send,
2914 .fsync_recv_fn = vfswrap_fsync_recv,
2915 .stat_fn = vfswrap_stat,
2916 .fstat_fn = vfswrap_fstat,
2917 .lstat_fn = vfswrap_lstat,
2918 .get_alloc_size_fn = vfswrap_get_alloc_size,
2919 .unlink_fn = vfswrap_unlink,
2920 .chmod_fn = vfswrap_chmod,
2921 .fchmod_fn = vfswrap_fchmod,
2922 .chown_fn = vfswrap_chown,
2923 .fchown_fn = vfswrap_fchown,
2924 .lchown_fn = vfswrap_lchown,
2925 .chdir_fn = vfswrap_chdir,
2926 .getwd_fn = vfswrap_getwd,
2927 .ntimes_fn = vfswrap_ntimes,
2928 .ftruncate_fn = vfswrap_ftruncate,
2929 .fallocate_fn = vfswrap_fallocate,
2930 .lock_fn = vfswrap_lock,
2931 .kernel_flock_fn = vfswrap_kernel_flock,
2932 .linux_setlease_fn = vfswrap_linux_setlease,
2933 .getlock_fn = vfswrap_getlock,
2934 .symlink_fn = vfswrap_symlink,
2935 .readlink_fn = vfswrap_readlink,
2936 .link_fn = vfswrap_link,
2937 .mknod_fn = vfswrap_mknod,
2938 .realpath_fn = vfswrap_realpath,
2939 .chflags_fn = vfswrap_chflags,
2940 .file_id_create_fn = vfswrap_file_id_create,
2941 .streaminfo_fn = vfswrap_streaminfo,
2942 .get_real_filename_fn = vfswrap_get_real_filename,
2943 .connectpath_fn = vfswrap_connectpath,
2944 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2945 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2946 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2947 .strict_lock_check_fn = vfswrap_strict_lock_check,
2948 .translate_name_fn = vfswrap_translate_name,
2949 .fsctl_fn = vfswrap_fsctl,
2950 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2951 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2952 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2953 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2954 .offload_read_send_fn = vfswrap_offload_read_send,
2955 .offload_read_recv_fn = vfswrap_offload_read_recv,
2956 .offload_write_send_fn = vfswrap_offload_write_send,
2957 .offload_write_recv_fn = vfswrap_offload_write_recv,
2958 .get_compression_fn = vfswrap_get_compression,
2959 .set_compression_fn = vfswrap_set_compression,
2961 /* NT ACL operations. */
2963 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2964 .get_nt_acl_fn = vfswrap_get_nt_acl,
2965 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2966 .audit_file_fn = vfswrap_audit_file,
2968 /* POSIX ACL operations. */
2970 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2971 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2972 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2973 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2974 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2975 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2976 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2978 /* EA operations. */
2979 .getxattr_fn = vfswrap_getxattr,
2980 .fgetxattr_fn = vfswrap_fgetxattr,
2981 .listxattr_fn = vfswrap_listxattr,
2982 .flistxattr_fn = vfswrap_flistxattr,
2983 .removexattr_fn = vfswrap_removexattr,
2984 .fremovexattr_fn = vfswrap_fremovexattr,
2985 .setxattr_fn = vfswrap_setxattr,
2986 .fsetxattr_fn = vfswrap_fsetxattr,
2988 /* aio operations */
2989 .aio_force_fn = vfswrap_aio_force,
2991 /* durable handle operations */
2992 .durable_cookie_fn = vfswrap_durable_cookie,
2993 .durable_disconnect_fn = vfswrap_durable_disconnect,
2994 .durable_reconnect_fn = vfswrap_durable_reconnect,
2997 static_decl_vfs;
2998 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3000 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3001 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);