Fix spelling s/Everytime/Every time/
[Samba.git] / source3 / modules / vfs_default.c
blobe335e270650ff256fe1041eb8806e58a641a69f0
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 bool has_dacl = False;
502 const char *path = smb_fname->base_name;
503 char *parent = NULL;
505 START_PROFILE(syscall_mkdir);
507 if (lp_inherit_acls(SNUM(handle->conn))
508 && parent_dirname(talloc_tos(), path, &parent, NULL)
509 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
510 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
513 TALLOC_FREE(parent);
515 result = mkdir(path, mode);
517 if (result == 0 && !has_dacl) {
519 * We need to do this as the default behavior of POSIX ACLs
520 * is to set the mask to be the requested group permission
521 * bits, not the group permission bits to be the requested
522 * group permission bits. This is not what we want, as it will
523 * mess up any inherited ACL bits that were set. JRA.
525 int saved_errno = errno; /* We may get ENOSYS */
526 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
527 (errno == ENOSYS)) {
528 errno = saved_errno;
532 END_PROFILE(syscall_mkdir);
533 return result;
536 static int vfswrap_rmdir(vfs_handle_struct *handle,
537 const struct smb_filename *smb_fname)
539 int result;
541 START_PROFILE(syscall_rmdir);
542 result = rmdir(smb_fname->base_name);
543 END_PROFILE(syscall_rmdir);
544 return result;
547 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
549 int result;
551 START_PROFILE(syscall_closedir);
552 result = closedir(dirp);
553 END_PROFILE(syscall_closedir);
554 return result;
557 /* File operations */
559 static int vfswrap_open(vfs_handle_struct *handle,
560 struct smb_filename *smb_fname,
561 files_struct *fsp, int flags, mode_t mode)
563 int result = -1;
565 START_PROFILE(syscall_open);
567 if (smb_fname->stream_name) {
568 errno = ENOENT;
569 goto out;
572 result = open(smb_fname->base_name, flags, mode);
573 out:
574 END_PROFILE(syscall_open);
575 return result;
578 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
579 struct smb_request *req,
580 uint16_t root_dir_fid,
581 struct smb_filename *smb_fname,
582 uint32_t access_mask,
583 uint32_t share_access,
584 uint32_t create_disposition,
585 uint32_t create_options,
586 uint32_t file_attributes,
587 uint32_t oplock_request,
588 struct smb2_lease *lease,
589 uint64_t allocation_size,
590 uint32_t private_flags,
591 struct security_descriptor *sd,
592 struct ea_list *ea_list,
593 files_struct **result,
594 int *pinfo,
595 const struct smb2_create_blobs *in_context_blobs,
596 struct smb2_create_blobs *out_context_blobs)
598 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
599 access_mask, share_access,
600 create_disposition, create_options,
601 file_attributes, oplock_request, lease,
602 allocation_size, private_flags,
603 sd, ea_list, result,
604 pinfo, in_context_blobs, out_context_blobs);
607 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
609 int result;
611 START_PROFILE(syscall_close);
612 result = fd_close_posix(fsp);
613 END_PROFILE(syscall_close);
614 return result;
617 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
618 size_t n, off_t offset)
620 ssize_t result;
622 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
623 START_PROFILE_BYTES(syscall_pread, n);
624 result = sys_pread(fsp->fh->fd, data, n, offset);
625 END_PROFILE_BYTES(syscall_pread);
627 if (result == -1 && errno == ESPIPE) {
628 /* Maintain the fiction that pipes can be seeked (sought?) on. */
629 result = sys_read(fsp->fh->fd, data, n);
630 fsp->fh->pos = 0;
633 #else /* HAVE_PREAD */
634 errno = ENOSYS;
635 result = -1;
636 #endif /* HAVE_PREAD */
638 return result;
641 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
642 size_t n, off_t offset)
644 ssize_t result;
646 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
647 START_PROFILE_BYTES(syscall_pwrite, n);
648 result = sys_pwrite(fsp->fh->fd, data, n, offset);
649 END_PROFILE_BYTES(syscall_pwrite);
651 if (result == -1 && errno == ESPIPE) {
652 /* Maintain the fiction that pipes can be sought on. */
653 result = sys_write(fsp->fh->fd, data, n);
656 #else /* HAVE_PWRITE */
657 errno = ENOSYS;
658 result = -1;
659 #endif /* HAVE_PWRITE */
661 return result;
664 struct vfswrap_pread_state {
665 ssize_t ret;
666 int fd;
667 void *buf;
668 size_t count;
669 off_t offset;
671 struct vfs_aio_state vfs_aio_state;
672 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
675 static void vfs_pread_do(void *private_data);
676 static void vfs_pread_done(struct tevent_req *subreq);
677 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
679 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
680 TALLOC_CTX *mem_ctx,
681 struct tevent_context *ev,
682 struct files_struct *fsp,
683 void *data,
684 size_t n, off_t offset)
686 struct tevent_req *req, *subreq;
687 struct vfswrap_pread_state *state;
689 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
690 if (req == NULL) {
691 return NULL;
694 state->ret = -1;
695 state->fd = fsp->fh->fd;
696 state->buf = data;
697 state->count = n;
698 state->offset = offset;
700 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
701 state->profile_bytes, n);
702 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
704 subreq = pthreadpool_tevent_job_send(
705 state, ev, handle->conn->sconn->pool,
706 vfs_pread_do, state);
707 if (tevent_req_nomem(subreq, req)) {
708 return tevent_req_post(req, ev);
710 tevent_req_set_callback(subreq, vfs_pread_done, req);
712 talloc_set_destructor(state, vfs_pread_state_destructor);
714 return req;
717 static void vfs_pread_do(void *private_data)
719 struct vfswrap_pread_state *state = talloc_get_type_abort(
720 private_data, struct vfswrap_pread_state);
721 struct timespec start_time;
722 struct timespec end_time;
724 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
726 PROFILE_TIMESTAMP(&start_time);
728 do {
729 state->ret = pread(state->fd, state->buf, state->count,
730 state->offset);
731 } while ((state->ret == -1) && (errno == EINTR));
733 if (state->ret == -1) {
734 state->vfs_aio_state.error = errno;
737 PROFILE_TIMESTAMP(&end_time);
739 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
741 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
744 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
746 return -1;
749 static void vfs_pread_done(struct tevent_req *subreq)
751 struct tevent_req *req = tevent_req_callback_data(
752 subreq, struct tevent_req);
753 struct vfswrap_pread_state *state = tevent_req_data(
754 req, struct vfswrap_pread_state);
755 int ret;
757 ret = pthreadpool_tevent_job_recv(subreq);
758 TALLOC_FREE(subreq);
759 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
760 talloc_set_destructor(state, NULL);
761 if (tevent_req_error(req, ret)) {
762 return;
765 tevent_req_done(req);
768 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
769 struct vfs_aio_state *vfs_aio_state)
771 struct vfswrap_pread_state *state = tevent_req_data(
772 req, struct vfswrap_pread_state);
774 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
775 return -1;
778 *vfs_aio_state = state->vfs_aio_state;
779 return state->ret;
782 struct vfswrap_pwrite_state {
783 ssize_t ret;
784 int fd;
785 const void *buf;
786 size_t count;
787 off_t offset;
789 struct vfs_aio_state vfs_aio_state;
790 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
793 static void vfs_pwrite_do(void *private_data);
794 static void vfs_pwrite_done(struct tevent_req *subreq);
795 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
797 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
798 TALLOC_CTX *mem_ctx,
799 struct tevent_context *ev,
800 struct files_struct *fsp,
801 const void *data,
802 size_t n, off_t offset)
804 struct tevent_req *req, *subreq;
805 struct vfswrap_pwrite_state *state;
807 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
808 if (req == NULL) {
809 return NULL;
812 state->ret = -1;
813 state->fd = fsp->fh->fd;
814 state->buf = data;
815 state->count = n;
816 state->offset = offset;
818 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
819 state->profile_bytes, n);
820 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
822 subreq = pthreadpool_tevent_job_send(
823 state, ev, handle->conn->sconn->pool,
824 vfs_pwrite_do, state);
825 if (tevent_req_nomem(subreq, req)) {
826 return tevent_req_post(req, ev);
828 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
830 talloc_set_destructor(state, vfs_pwrite_state_destructor);
832 return req;
835 static void vfs_pwrite_do(void *private_data)
837 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
838 private_data, struct vfswrap_pwrite_state);
839 struct timespec start_time;
840 struct timespec end_time;
842 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
844 PROFILE_TIMESTAMP(&start_time);
846 do {
847 state->ret = pwrite(state->fd, state->buf, state->count,
848 state->offset);
849 } while ((state->ret == -1) && (errno == EINTR));
851 if (state->ret == -1) {
852 state->vfs_aio_state.error = errno;
855 PROFILE_TIMESTAMP(&end_time);
857 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
859 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
862 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
864 return -1;
867 static void vfs_pwrite_done(struct tevent_req *subreq)
869 struct tevent_req *req = tevent_req_callback_data(
870 subreq, struct tevent_req);
871 struct vfswrap_pwrite_state *state = tevent_req_data(
872 req, struct vfswrap_pwrite_state);
873 int ret;
875 ret = pthreadpool_tevent_job_recv(subreq);
876 TALLOC_FREE(subreq);
877 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
878 talloc_set_destructor(state, NULL);
879 if (tevent_req_error(req, ret)) {
880 return;
883 tevent_req_done(req);
886 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
887 struct vfs_aio_state *vfs_aio_state)
889 struct vfswrap_pwrite_state *state = tevent_req_data(
890 req, struct vfswrap_pwrite_state);
892 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
893 return -1;
896 *vfs_aio_state = state->vfs_aio_state;
897 return state->ret;
900 struct vfswrap_fsync_state {
901 ssize_t ret;
902 int fd;
904 struct vfs_aio_state vfs_aio_state;
905 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
908 static void vfs_fsync_do(void *private_data);
909 static void vfs_fsync_done(struct tevent_req *subreq);
910 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
912 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
913 TALLOC_CTX *mem_ctx,
914 struct tevent_context *ev,
915 struct files_struct *fsp)
917 struct tevent_req *req, *subreq;
918 struct vfswrap_fsync_state *state;
920 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
921 if (req == NULL) {
922 return NULL;
925 state->ret = -1;
926 state->fd = fsp->fh->fd;
928 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
929 state->profile_basic);
931 subreq = pthreadpool_tevent_job_send(
932 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
933 if (tevent_req_nomem(subreq, req)) {
934 return tevent_req_post(req, ev);
936 tevent_req_set_callback(subreq, vfs_fsync_done, req);
938 talloc_set_destructor(state, vfs_fsync_state_destructor);
940 return req;
943 static void vfs_fsync_do(void *private_data)
945 struct vfswrap_fsync_state *state = talloc_get_type_abort(
946 private_data, struct vfswrap_fsync_state);
947 struct timespec start_time;
948 struct timespec end_time;
950 PROFILE_TIMESTAMP(&start_time);
952 do {
953 state->ret = fsync(state->fd);
954 } while ((state->ret == -1) && (errno == EINTR));
956 if (state->ret == -1) {
957 state->vfs_aio_state.error = errno;
960 PROFILE_TIMESTAMP(&end_time);
962 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
965 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
967 return -1;
970 static void vfs_fsync_done(struct tevent_req *subreq)
972 struct tevent_req *req = tevent_req_callback_data(
973 subreq, struct tevent_req);
974 struct vfswrap_fsync_state *state = tevent_req_data(
975 req, struct vfswrap_fsync_state);
976 int ret;
978 ret = pthreadpool_tevent_job_recv(subreq);
979 TALLOC_FREE(subreq);
980 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
981 talloc_set_destructor(state, NULL);
982 if (tevent_req_error(req, ret)) {
983 return;
986 tevent_req_done(req);
989 static int vfswrap_fsync_recv(struct tevent_req *req,
990 struct vfs_aio_state *vfs_aio_state)
992 struct vfswrap_fsync_state *state = tevent_req_data(
993 req, struct vfswrap_fsync_state);
995 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
996 return -1;
999 *vfs_aio_state = state->vfs_aio_state;
1000 return state->ret;
1003 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1005 off_t result = 0;
1007 START_PROFILE(syscall_lseek);
1009 /* Cope with 'stat' file opens. */
1010 if (fsp->fh->fd != -1)
1011 result = lseek(fsp->fh->fd, offset, whence);
1014 * We want to maintain the fiction that we can seek
1015 * on a fifo for file system purposes. This allows
1016 * people to set up UNIX fifo's that feed data to Windows
1017 * applications. JRA.
1020 if((result == -1) && (errno == ESPIPE)) {
1021 result = 0;
1022 errno = 0;
1025 END_PROFILE(syscall_lseek);
1026 return result;
1029 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1030 off_t offset, size_t n)
1032 ssize_t result;
1034 START_PROFILE_BYTES(syscall_sendfile, n);
1035 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1036 END_PROFILE_BYTES(syscall_sendfile);
1037 return result;
1040 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1041 int fromfd,
1042 files_struct *tofsp,
1043 off_t offset,
1044 size_t n)
1046 ssize_t result;
1048 START_PROFILE_BYTES(syscall_recvfile, n);
1049 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1050 END_PROFILE_BYTES(syscall_recvfile);
1051 return result;
1054 static int vfswrap_rename(vfs_handle_struct *handle,
1055 const struct smb_filename *smb_fname_src,
1056 const struct smb_filename *smb_fname_dst)
1058 int result = -1;
1060 START_PROFILE(syscall_rename);
1062 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1063 errno = ENOENT;
1064 goto out;
1067 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1069 out:
1070 END_PROFILE(syscall_rename);
1071 return result;
1074 static int vfswrap_stat(vfs_handle_struct *handle,
1075 struct smb_filename *smb_fname)
1077 int result = -1;
1079 START_PROFILE(syscall_stat);
1081 if (smb_fname->stream_name) {
1082 errno = ENOENT;
1083 goto out;
1086 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1087 lp_fake_directory_create_times(SNUM(handle->conn)));
1088 out:
1089 END_PROFILE(syscall_stat);
1090 return result;
1093 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1095 int result;
1097 START_PROFILE(syscall_fstat);
1098 result = sys_fstat(fsp->fh->fd,
1099 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1100 END_PROFILE(syscall_fstat);
1101 return result;
1104 static int vfswrap_lstat(vfs_handle_struct *handle,
1105 struct smb_filename *smb_fname)
1107 int result = -1;
1109 START_PROFILE(syscall_lstat);
1111 if (smb_fname->stream_name) {
1112 errno = ENOENT;
1113 goto out;
1116 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1117 lp_fake_directory_create_times(SNUM(handle->conn)));
1118 out:
1119 END_PROFILE(syscall_lstat);
1120 return result;
1123 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1124 const char *name,
1125 enum vfs_translate_direction direction,
1126 TALLOC_CTX *mem_ctx,
1127 char **mapped_name)
1129 return NT_STATUS_NONE_MAPPED;
1133 * Implement the default fsctl operation.
1135 static bool vfswrap_logged_ioctl_message = false;
1137 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1138 struct files_struct *fsp,
1139 TALLOC_CTX *ctx,
1140 uint32_t function,
1141 uint16_t req_flags, /* Needed for UNICODE ... */
1142 const uint8_t *_in_data,
1143 uint32_t in_len,
1144 uint8_t **_out_data,
1145 uint32_t max_out_len,
1146 uint32_t *out_len)
1148 const char *in_data = (const char *)_in_data;
1149 char **out_data = (char **)_out_data;
1150 NTSTATUS status;
1152 switch (function) {
1153 case FSCTL_SET_SPARSE:
1155 bool set_sparse = true;
1157 if (in_len >= 1 && in_data[0] == 0) {
1158 set_sparse = false;
1161 status = file_set_sparse(handle->conn, fsp, set_sparse);
1163 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1164 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1165 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1166 nt_errstr(status)));
1168 return status;
1171 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1173 unsigned char objid[16];
1174 char *return_data = NULL;
1176 /* This should return the object-id on this file.
1177 * I think I'll make this be the inode+dev. JRA.
1180 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1181 fsp_fnum_dbg(fsp)));
1183 *out_len = MIN(max_out_len, 64);
1185 /* Hmmm, will this cause problems if less data asked for? */
1186 return_data = talloc_array(ctx, char, 64);
1187 if (return_data == NULL) {
1188 return NT_STATUS_NO_MEMORY;
1191 /* For backwards compatibility only store the dev/inode. */
1192 push_file_id_16(return_data, &fsp->file_id);
1193 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1194 push_file_id_16(return_data+32, &fsp->file_id);
1195 memset(return_data+48, 0, 16);
1196 *out_data = return_data;
1197 return NT_STATUS_OK;
1200 case FSCTL_GET_REPARSE_POINT:
1202 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1203 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1204 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1205 return NT_STATUS_NOT_A_REPARSE_POINT;
1208 case FSCTL_SET_REPARSE_POINT:
1210 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1211 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1212 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1213 return NT_STATUS_NOT_A_REPARSE_POINT;
1216 case FSCTL_GET_SHADOW_COPY_DATA:
1219 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1220 * and return their volume names. If max_data_count is 16, then it is just
1221 * asking for the number of volumes and length of the combined names.
1223 * pdata is the data allocated by our caller, but that uses
1224 * total_data_count (which is 0 in our case) rather than max_data_count.
1225 * Allocate the correct amount and return the pointer to let
1226 * it be deallocated when we return.
1228 struct shadow_copy_data *shadow_data = NULL;
1229 bool labels = False;
1230 uint32_t labels_data_count = 0;
1231 uint32_t i;
1232 char *cur_pdata = NULL;
1234 if (max_out_len < 16) {
1235 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1236 max_out_len));
1237 return NT_STATUS_INVALID_PARAMETER;
1240 if (max_out_len > 16) {
1241 labels = True;
1244 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1245 if (shadow_data == NULL) {
1246 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1247 return NT_STATUS_NO_MEMORY;
1251 * Call the VFS routine to actually do the work.
1253 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1254 int log_lev = 0;
1255 if (errno == 0) {
1256 /* broken module didn't set errno on error */
1257 status = NT_STATUS_UNSUCCESSFUL;
1258 } else {
1259 status = map_nt_error_from_unix(errno);
1260 if (NT_STATUS_EQUAL(status,
1261 NT_STATUS_NOT_SUPPORTED)) {
1262 log_lev = 5;
1265 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1266 "connectpath %s, failed - %s.\n",
1267 fsp->conn->connectpath,
1268 nt_errstr(status)));
1269 TALLOC_FREE(shadow_data);
1270 return status;
1273 labels_data_count = (shadow_data->num_volumes * 2 *
1274 sizeof(SHADOW_COPY_LABEL)) + 2;
1276 if (!labels) {
1277 *out_len = 16;
1278 } else {
1279 *out_len = 12 + labels_data_count;
1282 if (max_out_len < *out_len) {
1283 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1284 max_out_len, *out_len));
1285 TALLOC_FREE(shadow_data);
1286 return NT_STATUS_BUFFER_TOO_SMALL;
1289 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1290 if (cur_pdata == NULL) {
1291 TALLOC_FREE(shadow_data);
1292 return NT_STATUS_NO_MEMORY;
1295 *out_data = cur_pdata;
1297 /* num_volumes 4 bytes */
1298 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1300 if (labels) {
1301 /* num_labels 4 bytes */
1302 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1305 /* needed_data_count 4 bytes */
1306 SIVAL(cur_pdata, 8, labels_data_count);
1308 cur_pdata += 12;
1310 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1311 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1312 if (labels && shadow_data->labels) {
1313 for (i=0; i<shadow_data->num_volumes; i++) {
1314 size_t len = 0;
1315 status = srvstr_push(cur_pdata, req_flags,
1316 cur_pdata, shadow_data->labels[i],
1317 2 * sizeof(SHADOW_COPY_LABEL),
1318 STR_UNICODE|STR_TERMINATE, &len);
1319 if (!NT_STATUS_IS_OK(status)) {
1320 TALLOC_FREE(*out_data);
1321 TALLOC_FREE(shadow_data);
1322 return status;
1324 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1325 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1329 TALLOC_FREE(shadow_data);
1331 return NT_STATUS_OK;
1334 case FSCTL_FIND_FILES_BY_SID:
1336 /* pretend this succeeded -
1338 * we have to send back a list with all files owned by this SID
1340 * but I have to check that --metze
1342 struct dom_sid sid;
1343 uid_t uid;
1344 size_t sid_len;
1346 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1347 fsp_fnum_dbg(fsp)));
1349 if (in_len < 8) {
1350 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1351 return NT_STATUS_INVALID_PARAMETER;
1354 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1356 /* unknown 4 bytes: this is not the length of the sid :-( */
1357 /*unknown = IVAL(pdata,0);*/
1359 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1360 return NT_STATUS_INVALID_PARAMETER;
1362 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1364 if (!sid_to_uid(&sid, &uid)) {
1365 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1366 sid_string_dbg(&sid),
1367 (unsigned long)sid_len));
1368 uid = (-1);
1371 /* we can take a look at the find source :-)
1373 * find ./ -uid $uid -name '*' is what we need here
1376 * and send 4bytes len and then NULL terminated unicode strings
1377 * for each file
1379 * but I don't know how to deal with the paged results
1380 * (maybe we can hang the result anywhere in the fsp struct)
1382 * but I don't know how to deal with the paged results
1383 * (maybe we can hang the result anywhere in the fsp struct)
1385 * we don't send all files at once
1386 * and at the next we should *not* start from the beginning,
1387 * so we have to cache the result
1389 * --metze
1392 /* this works for now... */
1393 return NT_STATUS_OK;
1396 case FSCTL_QUERY_ALLOCATED_RANGES:
1398 /* FIXME: This is just a dummy reply, telling that all of the
1399 * file is allocated. MKS cp needs that.
1400 * Adding the real allocated ranges via FIEMAP on Linux
1401 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1402 * this FSCTL correct for sparse files.
1404 uint64_t offset, length;
1405 char *out_data_tmp = NULL;
1407 if (in_len != 16) {
1408 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1409 in_len));
1410 return NT_STATUS_INVALID_PARAMETER;
1413 if (max_out_len < 16) {
1414 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1415 max_out_len));
1416 return NT_STATUS_INVALID_PARAMETER;
1419 offset = BVAL(in_data,0);
1420 length = BVAL(in_data,8);
1422 if (offset + length < offset) {
1423 /* No 64-bit integer wrap. */
1424 return NT_STATUS_INVALID_PARAMETER;
1427 /* Shouldn't this be SMB_VFS_STAT ... ? */
1428 status = vfs_stat_fsp(fsp);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 return status;
1433 *out_len = 16;
1434 out_data_tmp = talloc_array(ctx, char, *out_len);
1435 if (out_data_tmp == NULL) {
1436 DEBUG(10, ("unable to allocate memory for response\n"));
1437 return NT_STATUS_NO_MEMORY;
1440 if (offset > fsp->fsp_name->st.st_ex_size ||
1441 fsp->fsp_name->st.st_ex_size == 0 ||
1442 length == 0) {
1443 memset(out_data_tmp, 0, *out_len);
1444 } else {
1445 uint64_t end = offset + length;
1446 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1447 SBVAL(out_data_tmp, 0, 0);
1448 SBVAL(out_data_tmp, 8, end);
1451 *out_data = out_data_tmp;
1453 return NT_STATUS_OK;
1456 case FSCTL_IS_VOLUME_DIRTY:
1458 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1459 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1461 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1462 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1464 return NT_STATUS_INVALID_PARAMETER;
1467 default:
1469 * Only print once ... unfortunately there could be lots of
1470 * different FSCTLs that are called.
1472 if (!vfswrap_logged_ioctl_message) {
1473 vfswrap_logged_ioctl_message = true;
1474 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1475 __func__, function));
1479 return NT_STATUS_NOT_SUPPORTED;
1482 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1483 const struct smb_filename *fname,
1484 SMB_STRUCT_STAT *sbuf);
1486 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1487 struct smb_filename *smb_fname,
1488 uint32_t *dosmode)
1490 bool offline;
1492 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1493 if (offline) {
1494 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1497 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1500 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1501 struct files_struct *fsp,
1502 uint32_t *dosmode)
1504 bool offline;
1506 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1507 if (offline) {
1508 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1511 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1514 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1515 const struct smb_filename *smb_fname,
1516 uint32_t dosmode)
1518 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1521 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1522 struct files_struct *fsp,
1523 uint32_t dosmode)
1525 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1528 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1530 struct vfswrap_offload_read_state {
1531 DATA_BLOB token;
1534 static struct tevent_req *vfswrap_offload_read_send(
1535 TALLOC_CTX *mem_ctx,
1536 struct tevent_context *ev,
1537 struct vfs_handle_struct *handle,
1538 struct files_struct *fsp,
1539 uint32_t fsctl,
1540 uint32_t ttl,
1541 off_t offset,
1542 size_t to_copy)
1544 struct tevent_req *req = NULL;
1545 struct vfswrap_offload_read_state *state = NULL;
1546 NTSTATUS status;
1548 req = tevent_req_create(mem_ctx, &state,
1549 struct vfswrap_offload_read_state);
1550 if (req == NULL) {
1551 return NULL;
1554 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1555 &vfswrap_offload_ctx);
1556 if (tevent_req_nterror(req, status)) {
1557 return tevent_req_post(req, ev);
1560 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1561 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1562 return tevent_req_post(req, ev);
1565 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1566 &state->token);
1567 if (tevent_req_nterror(req, status)) {
1568 return tevent_req_post(req, ev);
1571 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1572 &state->token);
1573 if (tevent_req_nterror(req, status)) {
1574 return tevent_req_post(req, ev);
1577 tevent_req_done(req);
1578 return tevent_req_post(req, ev);
1581 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1582 struct vfs_handle_struct *handle,
1583 TALLOC_CTX *mem_ctx,
1584 DATA_BLOB *token)
1586 struct vfswrap_offload_read_state *state = tevent_req_data(
1587 req, struct vfswrap_offload_read_state);
1588 NTSTATUS status;
1590 if (tevent_req_is_nterror(req, &status)) {
1591 tevent_req_received(req);
1592 return status;
1595 token->length = state->token.length;
1596 token->data = talloc_move(mem_ctx, &state->token.data);
1598 tevent_req_received(req);
1599 return NT_STATUS_OK;
1602 struct vfswrap_offload_write_state {
1603 struct tevent_context *ev;
1604 uint8_t *buf;
1605 bool read_lck_locked;
1606 bool write_lck_locked;
1607 DATA_BLOB *token;
1608 struct files_struct *src_fsp;
1609 off_t src_off;
1610 struct files_struct *dst_fsp;
1611 off_t dst_off;
1612 off_t to_copy;
1613 off_t remaining;
1614 size_t next_io_size;
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;
1636 req = tevent_req_create(mem_ctx, &state,
1637 struct vfswrap_offload_write_state);
1638 if (req == NULL) {
1639 return NULL;
1642 *state = (struct vfswrap_offload_write_state) {
1643 .ev = ev,
1644 .token = token,
1645 .src_off = transfer_offset,
1646 .dst_fsp = dest_fsp,
1647 .dst_off = dest_off,
1648 .to_copy = to_copy,
1649 .remaining = to_copy,
1652 switch (fsctl) {
1653 case FSCTL_SRV_COPYCHUNK:
1654 case FSCTL_SRV_COPYCHUNK_WRITE:
1655 break;
1657 case FSCTL_OFFLOAD_WRITE:
1658 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1659 return tevent_req_post(req, ev);
1661 case FSCTL_DUP_EXTENTS_TO_FILE:
1662 DBG_DEBUG("COW clones not supported by vfs_default\n");
1663 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1664 return tevent_req_post(req, ev);
1666 default:
1667 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1668 return tevent_req_post(req, ev);
1672 * From here on we assume a copy-chunk fsctl
1675 if (to_copy == 0) {
1676 tevent_req_done(req);
1677 return tevent_req_post(req, ev);
1680 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1681 token, &src_fsp);
1682 if (tevent_req_nterror(req, status)) {
1683 return tevent_req_post(req, ev);
1685 state->src_fsp = src_fsp;
1687 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1689 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1690 if (!NT_STATUS_IS_OK(status)) {
1691 tevent_req_nterror(req, status);
1692 return tevent_req_post(req, ev);
1695 state->buf = talloc_array(state, uint8_t, num);
1696 if (tevent_req_nomem(state->buf, req)) {
1697 return tevent_req_post(req, ev);
1700 status = vfs_stat_fsp(src_fsp);
1701 if (tevent_req_nterror(req, status)) {
1702 return tevent_req_post(req, ev);
1705 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1707 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1708 * If the SourceOffset or SourceOffset + Length extends beyond
1709 * the end of file, the server SHOULD<240> treat this as a
1710 * STATUS_END_OF_FILE error.
1711 * ...
1712 * <240> Section 3.3.5.15.6: Windows servers will return
1713 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1715 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1716 return tevent_req_post(req, ev);
1719 if (src_fsp->op == NULL) {
1720 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1721 return tevent_req_post(req, ev);
1724 if (dest_fsp->op == NULL) {
1725 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1726 return tevent_req_post(req, ev);
1729 status = vfswrap_offload_write_loop(req);
1730 if (!NT_STATUS_IS_OK(status)) {
1731 tevent_req_nterror(req, status);
1732 return tevent_req_post(req, ev);
1735 return req;
1738 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1740 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1742 struct vfswrap_offload_write_state *state = tevent_req_data(
1743 req, struct vfswrap_offload_write_state);
1744 struct tevent_req *subreq = NULL;
1745 struct lock_struct read_lck;
1746 bool ok;
1748 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1750 init_strict_lock_struct(state->src_fsp,
1751 state->src_fsp->op->global->open_persistent_id,
1752 state->src_off,
1753 state->next_io_size,
1754 READ_LOCK,
1755 &read_lck);
1757 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1758 state->src_fsp,
1759 &read_lck);
1760 if (!ok) {
1761 return NT_STATUS_FILE_LOCK_CONFLICT;
1764 subreq = SMB_VFS_PREAD_SEND(state,
1765 state->src_fsp->conn->sconn->ev_ctx,
1766 state->src_fsp,
1767 state->buf,
1768 state->next_io_size,
1769 state->src_off);
1770 if (subreq == NULL) {
1771 return NT_STATUS_NO_MEMORY;
1773 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1775 return NT_STATUS_OK;
1778 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1780 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1782 struct tevent_req *req = tevent_req_callback_data(
1783 subreq, struct tevent_req);
1784 struct vfswrap_offload_write_state *state = tevent_req_data(
1785 req, struct vfswrap_offload_write_state);
1786 struct vfs_aio_state aio_state;
1787 struct lock_struct write_lck;
1788 ssize_t nread;
1789 bool ok;
1791 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1792 TALLOC_FREE(subreq);
1793 if (nread == -1) {
1794 DBG_ERR("read failed: %s\n", strerror(errno));
1795 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1796 return;
1798 if (nread != state->next_io_size) {
1799 DBG_ERR("Short read, only %zd of %zu\n",
1800 nread, state->next_io_size);
1801 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1802 return;
1805 state->src_off += nread;
1807 init_strict_lock_struct(state->dst_fsp,
1808 state->dst_fsp->op->global->open_persistent_id,
1809 state->dst_off,
1810 state->next_io_size,
1811 WRITE_LOCK,
1812 &write_lck);
1814 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1815 state->dst_fsp,
1816 &write_lck);
1817 if (!ok) {
1818 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1819 return;
1822 subreq = SMB_VFS_PWRITE_SEND(state,
1823 state->ev,
1824 state->dst_fsp,
1825 state->buf,
1826 state->next_io_size,
1827 state->dst_off);
1828 if (subreq == NULL) {
1829 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1830 return;
1832 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1835 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1837 struct tevent_req *req = tevent_req_callback_data(
1838 subreq, struct tevent_req);
1839 struct vfswrap_offload_write_state *state = tevent_req_data(
1840 req, struct vfswrap_offload_write_state);
1841 struct vfs_aio_state aio_state;
1842 ssize_t nwritten;
1843 NTSTATUS status;
1845 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1846 TALLOC_FREE(subreq);
1847 if (nwritten == -1) {
1848 DBG_ERR("write failed: %s\n", strerror(errno));
1849 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1850 return;
1852 if (nwritten != state->next_io_size) {
1853 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1854 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1855 return;
1858 state->dst_off += nwritten;
1860 if (state->remaining < nwritten) {
1861 /* Paranoia check */
1862 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1863 return;
1865 state->remaining -= nwritten;
1866 if (state->remaining == 0) {
1867 tevent_req_done(req);
1868 return;
1871 status = vfswrap_offload_write_loop(req);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 tevent_req_nterror(req, status);
1874 return;
1877 return;
1880 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1881 struct tevent_req *req,
1882 off_t *copied)
1884 struct vfswrap_offload_write_state *state = tevent_req_data(
1885 req, struct vfswrap_offload_write_state);
1886 NTSTATUS status;
1888 if (tevent_req_is_nterror(req, &status)) {
1889 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1890 *copied = 0;
1891 tevent_req_received(req);
1892 return status;
1895 *copied = state->to_copy;
1896 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1897 tevent_req_received(req);
1899 return NT_STATUS_OK;
1902 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1903 TALLOC_CTX *mem_ctx,
1904 struct files_struct *fsp,
1905 struct smb_filename *smb_fname,
1906 uint16_t *_compression_fmt)
1908 return NT_STATUS_INVALID_DEVICE_REQUEST;
1911 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1912 TALLOC_CTX *mem_ctx,
1913 struct files_struct *fsp,
1914 uint16_t compression_fmt)
1916 return NT_STATUS_INVALID_DEVICE_REQUEST;
1919 /********************************************************************
1920 Given a stat buffer return the allocated size on disk, taking into
1921 account sparse files.
1922 ********************************************************************/
1923 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1924 struct files_struct *fsp,
1925 const SMB_STRUCT_STAT *sbuf)
1927 uint64_t result;
1929 START_PROFILE(syscall_get_alloc_size);
1931 if(S_ISDIR(sbuf->st_ex_mode)) {
1932 result = 0;
1933 goto out;
1936 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1937 /* The type of st_blocksize is blkcnt_t which *MUST* be
1938 signed (according to POSIX) and can be less than 64-bits.
1939 Ensure when we're converting to 64 bits wide we don't
1940 sign extend. */
1941 #if defined(SIZEOF_BLKCNT_T_8)
1942 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1943 #elif defined(SIZEOF_BLKCNT_T_4)
1945 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1946 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1948 #else
1949 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1950 #endif
1951 if (result == 0) {
1953 * Some file systems do not allocate a block for very
1954 * small files. But for non-empty file should report a
1955 * positive size.
1958 uint64_t filesize = get_file_size_stat(sbuf);
1959 if (filesize > 0) {
1960 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1963 #else
1964 result = get_file_size_stat(sbuf);
1965 #endif
1967 if (fsp && fsp->initial_allocation_size)
1968 result = MAX(result,fsp->initial_allocation_size);
1970 result = smb_roundup(handle->conn, result);
1972 out:
1973 END_PROFILE(syscall_get_alloc_size);
1974 return result;
1977 static int vfswrap_unlink(vfs_handle_struct *handle,
1978 const struct smb_filename *smb_fname)
1980 int result = -1;
1982 START_PROFILE(syscall_unlink);
1984 if (smb_fname->stream_name) {
1985 errno = ENOENT;
1986 goto out;
1988 result = unlink(smb_fname->base_name);
1990 out:
1991 END_PROFILE(syscall_unlink);
1992 return result;
1995 static int vfswrap_chmod(vfs_handle_struct *handle,
1996 const struct smb_filename *smb_fname,
1997 mode_t mode)
1999 int result;
2001 START_PROFILE(syscall_chmod);
2004 * We need to do this due to the fact that the default POSIX ACL
2005 * chmod modifies the ACL *mask* for the group owner, not the
2006 * group owner bits directly. JRA.
2011 int saved_errno = errno; /* We might get ENOSYS */
2012 result = SMB_VFS_CHMOD_ACL(handle->conn,
2013 smb_fname,
2014 mode);
2015 if (result == 0) {
2016 END_PROFILE(syscall_chmod);
2017 return result;
2019 /* Error - return the old errno. */
2020 errno = saved_errno;
2023 result = chmod(smb_fname->base_name, mode);
2024 END_PROFILE(syscall_chmod);
2025 return result;
2028 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2030 int result;
2032 START_PROFILE(syscall_fchmod);
2035 * We need to do this due to the fact that the default POSIX ACL
2036 * chmod modifies the ACL *mask* for the group owner, not the
2037 * group owner bits directly. JRA.
2041 int saved_errno = errno; /* We might get ENOSYS */
2042 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2043 END_PROFILE(syscall_fchmod);
2044 return result;
2046 /* Error - return the old errno. */
2047 errno = saved_errno;
2050 #if defined(HAVE_FCHMOD)
2051 result = fchmod(fsp->fh->fd, mode);
2052 #else
2053 result = -1;
2054 errno = ENOSYS;
2055 #endif
2057 END_PROFILE(syscall_fchmod);
2058 return result;
2061 static int vfswrap_chown(vfs_handle_struct *handle,
2062 const struct smb_filename *smb_fname,
2063 uid_t uid,
2064 gid_t gid)
2066 int result;
2068 START_PROFILE(syscall_chown);
2069 result = chown(smb_fname->base_name, uid, gid);
2070 END_PROFILE(syscall_chown);
2071 return result;
2074 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2076 #ifdef HAVE_FCHOWN
2077 int result;
2079 START_PROFILE(syscall_fchown);
2080 result = fchown(fsp->fh->fd, uid, gid);
2081 END_PROFILE(syscall_fchown);
2082 return result;
2083 #else
2084 errno = ENOSYS;
2085 return -1;
2086 #endif
2089 static int vfswrap_lchown(vfs_handle_struct *handle,
2090 const struct smb_filename *smb_fname,
2091 uid_t uid,
2092 gid_t gid)
2094 int result;
2096 START_PROFILE(syscall_lchown);
2097 result = lchown(smb_fname->base_name, uid, gid);
2098 END_PROFILE(syscall_lchown);
2099 return result;
2102 static int vfswrap_chdir(vfs_handle_struct *handle,
2103 const struct smb_filename *smb_fname)
2105 int result;
2107 START_PROFILE(syscall_chdir);
2108 result = chdir(smb_fname->base_name);
2109 END_PROFILE(syscall_chdir);
2110 return result;
2113 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2114 TALLOC_CTX *ctx)
2116 char *result;
2117 struct smb_filename *smb_fname = NULL;
2119 START_PROFILE(syscall_getwd);
2120 result = sys_getwd();
2121 END_PROFILE(syscall_getwd);
2123 if (result == NULL) {
2124 return NULL;
2126 smb_fname = synthetic_smb_fname(ctx,
2127 result,
2128 NULL,
2129 NULL,
2132 * sys_getwd() *always* returns malloced memory.
2133 * We must free here to avoid leaks:
2134 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2136 SAFE_FREE(result);
2137 return smb_fname;
2140 /*********************************************************************
2141 nsec timestamp resolution call. Convert down to whatever the underlying
2142 system will support.
2143 **********************************************************************/
2145 static int vfswrap_ntimes(vfs_handle_struct *handle,
2146 const struct smb_filename *smb_fname,
2147 struct smb_file_time *ft)
2149 int result = -1;
2151 START_PROFILE(syscall_ntimes);
2153 if (smb_fname->stream_name) {
2154 errno = ENOENT;
2155 goto out;
2158 if (ft != NULL) {
2159 if (null_timespec(ft->atime)) {
2160 ft->atime= smb_fname->st.st_ex_atime;
2163 if (null_timespec(ft->mtime)) {
2164 ft->mtime = smb_fname->st.st_ex_mtime;
2167 if (!null_timespec(ft->create_time)) {
2168 set_create_timespec_ea(handle->conn,
2169 smb_fname,
2170 ft->create_time);
2173 if ((timespec_compare(&ft->atime,
2174 &smb_fname->st.st_ex_atime) == 0) &&
2175 (timespec_compare(&ft->mtime,
2176 &smb_fname->st.st_ex_mtime) == 0)) {
2177 return 0;
2181 #if defined(HAVE_UTIMENSAT)
2182 if (ft != NULL) {
2183 struct timespec ts[2];
2184 ts[0] = ft->atime;
2185 ts[1] = ft->mtime;
2186 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2187 } else {
2188 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2190 if (!((result == -1) && (errno == ENOSYS))) {
2191 goto out;
2193 #endif
2194 #if defined(HAVE_UTIMES)
2195 if (ft != NULL) {
2196 struct timeval tv[2];
2197 tv[0] = convert_timespec_to_timeval(ft->atime);
2198 tv[1] = convert_timespec_to_timeval(ft->mtime);
2199 result = utimes(smb_fname->base_name, tv);
2200 } else {
2201 result = utimes(smb_fname->base_name, NULL);
2203 if (!((result == -1) && (errno == ENOSYS))) {
2204 goto out;
2206 #endif
2207 #if defined(HAVE_UTIME)
2208 if (ft != NULL) {
2209 struct utimbuf times;
2210 times.actime = convert_timespec_to_time_t(ft->atime);
2211 times.modtime = convert_timespec_to_time_t(ft->mtime);
2212 result = utime(smb_fname->base_name, &times);
2213 } else {
2214 result = utime(smb_fname->base_name, NULL);
2216 if (!((result == -1) && (errno == ENOSYS))) {
2217 goto out;
2219 #endif
2220 errno = ENOSYS;
2221 result = -1;
2223 out:
2224 END_PROFILE(syscall_ntimes);
2225 return result;
2228 /*********************************************************************
2229 A version of ftruncate that will write the space on disk if strict
2230 allocate is set.
2231 **********************************************************************/
2233 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2235 off_t space_to_write;
2236 uint64_t space_avail;
2237 uint64_t bsize,dfree,dsize;
2238 int ret;
2239 NTSTATUS status;
2240 SMB_STRUCT_STAT *pst;
2242 status = vfs_stat_fsp(fsp);
2243 if (!NT_STATUS_IS_OK(status)) {
2244 return -1;
2246 pst = &fsp->fsp_name->st;
2248 #ifdef S_ISFIFO
2249 if (S_ISFIFO(pst->st_ex_mode))
2250 return 0;
2251 #endif
2253 if (pst->st_ex_size == len)
2254 return 0;
2256 /* Shrink - just ftruncate. */
2257 if (pst->st_ex_size > len)
2258 return ftruncate(fsp->fh->fd, len);
2260 space_to_write = len - pst->st_ex_size;
2262 /* for allocation try fallocate first. This can fail on some
2263 platforms e.g. when the filesystem doesn't support it and no
2264 emulation is being done by the libc (like on AIX with JFS1). In that
2265 case we do our own emulation. fallocate implementations can
2266 return ENOTSUP or EINVAL in cases like that. */
2267 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2268 if (ret == -1 && errno == ENOSPC) {
2269 return -1;
2271 if (ret == 0) {
2272 return 0;
2274 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2275 "error %d. Falling back to slow manual allocation\n", errno));
2277 /* available disk space is enough or not? */
2278 space_avail =
2279 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2280 /* space_avail is 1k blocks */
2281 if (space_avail == (uint64_t)-1 ||
2282 ((uint64_t)space_to_write/1024 > space_avail) ) {
2283 errno = ENOSPC;
2284 return -1;
2287 /* Write out the real space on disk. */
2288 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2289 if (ret != 0) {
2290 return -1;
2293 return 0;
2296 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2298 int result = -1;
2299 SMB_STRUCT_STAT *pst;
2300 NTSTATUS status;
2301 char c = 0;
2303 START_PROFILE(syscall_ftruncate);
2305 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2306 result = strict_allocate_ftruncate(handle, fsp, len);
2307 END_PROFILE(syscall_ftruncate);
2308 return result;
2311 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2312 ftruncate if the system supports it. Then I discovered that
2313 you can have some filesystems that support ftruncate
2314 expansion and some that don't! On Linux fat can't do
2315 ftruncate extend but ext2 can. */
2317 result = ftruncate(fsp->fh->fd, len);
2319 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2320 extend a file with ftruncate. Provide alternate implementation
2321 for this */
2323 /* Do an fstat to see if the file is longer than the requested
2324 size in which case the ftruncate above should have
2325 succeeded or shorter, in which case seek to len - 1 and
2326 write 1 byte of zero */
2327 status = vfs_stat_fsp(fsp);
2328 if (!NT_STATUS_IS_OK(status)) {
2329 goto done;
2332 /* We need to update the files_struct after successful ftruncate */
2333 if (result == 0) {
2334 goto done;
2337 pst = &fsp->fsp_name->st;
2339 #ifdef S_ISFIFO
2340 if (S_ISFIFO(pst->st_ex_mode)) {
2341 result = 0;
2342 goto done;
2344 #endif
2346 if (pst->st_ex_size == len) {
2347 result = 0;
2348 goto done;
2351 if (pst->st_ex_size > len) {
2352 /* the ftruncate should have worked */
2353 goto done;
2356 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2357 goto done;
2360 result = 0;
2362 done:
2364 END_PROFILE(syscall_ftruncate);
2365 return result;
2368 static int vfswrap_fallocate(vfs_handle_struct *handle,
2369 files_struct *fsp,
2370 uint32_t mode,
2371 off_t offset,
2372 off_t len)
2374 int result;
2376 START_PROFILE(syscall_fallocate);
2377 if (mode == 0) {
2378 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2380 * posix_fallocate returns 0 on success, errno on error
2381 * and doesn't set errno. Make it behave like fallocate()
2382 * which returns -1, and sets errno on failure.
2384 if (result != 0) {
2385 errno = result;
2386 result = -1;
2388 } else {
2389 /* sys_fallocate handles filtering of unsupported mode flags */
2390 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2392 END_PROFILE(syscall_fallocate);
2393 return result;
2396 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2398 bool result;
2400 START_PROFILE(syscall_fcntl_lock);
2402 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2403 "smbd",
2404 "force process locks",
2405 false)) {
2406 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2409 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2410 END_PROFILE(syscall_fcntl_lock);
2411 return result;
2414 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2415 uint32_t share_mode, uint32_t access_mask)
2417 START_PROFILE(syscall_kernel_flock);
2418 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2419 END_PROFILE(syscall_kernel_flock);
2420 return 0;
2423 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2425 bool result;
2426 int op = F_GETLK;
2428 START_PROFILE(syscall_fcntl_getlock);
2430 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2431 "smbd",
2432 "force process locks",
2433 false)) {
2434 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2437 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2438 END_PROFILE(syscall_fcntl_getlock);
2439 return result;
2442 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2443 int leasetype)
2445 int result = -1;
2447 START_PROFILE(syscall_linux_setlease);
2449 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2450 result = linux_setlease(fsp->fh->fd, leasetype);
2451 #else
2452 errno = ENOSYS;
2453 #endif
2454 END_PROFILE(syscall_linux_setlease);
2455 return result;
2458 static int vfswrap_symlink(vfs_handle_struct *handle,
2459 const char *link_target,
2460 const struct smb_filename *new_smb_fname)
2462 int result;
2464 START_PROFILE(syscall_symlink);
2465 result = symlink(link_target, new_smb_fname->base_name);
2466 END_PROFILE(syscall_symlink);
2467 return result;
2470 static int vfswrap_readlink(vfs_handle_struct *handle,
2471 const struct smb_filename *smb_fname,
2472 char *buf,
2473 size_t bufsiz)
2475 int result;
2477 START_PROFILE(syscall_readlink);
2478 result = readlink(smb_fname->base_name, buf, bufsiz);
2479 END_PROFILE(syscall_readlink);
2480 return result;
2483 static int vfswrap_link(vfs_handle_struct *handle,
2484 const struct smb_filename *old_smb_fname,
2485 const struct smb_filename *new_smb_fname)
2487 int result;
2489 START_PROFILE(syscall_link);
2490 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2491 END_PROFILE(syscall_link);
2492 return result;
2495 static int vfswrap_mknod(vfs_handle_struct *handle,
2496 const struct smb_filename *smb_fname,
2497 mode_t mode,
2498 SMB_DEV_T dev)
2500 int result;
2502 START_PROFILE(syscall_mknod);
2503 result = sys_mknod(smb_fname->base_name, mode, dev);
2504 END_PROFILE(syscall_mknod);
2505 return result;
2508 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2509 TALLOC_CTX *ctx,
2510 const struct smb_filename *smb_fname)
2512 char *result;
2513 struct smb_filename *result_fname = NULL;
2515 START_PROFILE(syscall_realpath);
2516 result = sys_realpath(smb_fname->base_name);
2517 END_PROFILE(syscall_realpath);
2518 if (result) {
2519 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2520 SAFE_FREE(result);
2522 return result_fname;
2525 static int vfswrap_chflags(vfs_handle_struct *handle,
2526 const struct smb_filename *smb_fname,
2527 unsigned int flags)
2529 #ifdef HAVE_CHFLAGS
2530 return chflags(smb_fname->base_name, flags);
2531 #else
2532 errno = ENOSYS;
2533 return -1;
2534 #endif
2537 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2538 const SMB_STRUCT_STAT *sbuf)
2540 struct file_id key;
2542 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2543 * blob */
2544 ZERO_STRUCT(key);
2546 key.devid = sbuf->st_ex_dev;
2547 key.inode = sbuf->st_ex_ino;
2548 /* key.extid is unused by default. */
2550 return key;
2553 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2554 struct files_struct *fsp,
2555 const struct smb_filename *smb_fname,
2556 TALLOC_CTX *mem_ctx,
2557 unsigned int *pnum_streams,
2558 struct stream_struct **pstreams)
2560 SMB_STRUCT_STAT sbuf;
2561 struct stream_struct *tmp_streams = NULL;
2562 int ret;
2564 if ((fsp != NULL) && (fsp->is_directory)) {
2566 * No default streams on directories
2568 goto done;
2571 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2572 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2574 else {
2575 struct smb_filename smb_fname_cp;
2577 ZERO_STRUCT(smb_fname_cp);
2578 smb_fname_cp.base_name = discard_const_p(char,
2579 smb_fname->base_name);
2580 smb_fname_cp.flags = smb_fname->flags;
2582 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2583 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2584 } else {
2585 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2587 sbuf = smb_fname_cp.st;
2590 if (ret == -1) {
2591 return map_nt_error_from_unix(errno);
2594 if (S_ISDIR(sbuf.st_ex_mode)) {
2595 goto done;
2598 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2599 (*pnum_streams) + 1);
2600 if (tmp_streams == NULL) {
2601 return NT_STATUS_NO_MEMORY;
2603 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2604 if (tmp_streams[*pnum_streams].name == NULL) {
2605 return NT_STATUS_NO_MEMORY;
2607 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2608 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2610 *pnum_streams += 1;
2611 *pstreams = tmp_streams;
2612 done:
2613 return NT_STATUS_OK;
2616 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2617 const char *path,
2618 const char *name,
2619 TALLOC_CTX *mem_ctx,
2620 char **found_name)
2623 * Don't fall back to get_real_filename so callers can differentiate
2624 * between a full directory scan and an actual case-insensitive stat.
2626 errno = EOPNOTSUPP;
2627 return -1;
2630 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2631 const struct smb_filename *smb_fname)
2633 return handle->conn->connectpath;
2636 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2637 struct byte_range_lock *br_lck,
2638 struct lock_struct *plock,
2639 bool blocking_lock)
2641 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2643 /* Note: blr is not used in the default implementation. */
2644 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2647 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2648 struct messaging_context *msg_ctx,
2649 struct byte_range_lock *br_lck,
2650 const struct lock_struct *plock)
2652 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2654 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2657 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2658 struct byte_range_lock *br_lck,
2659 struct lock_struct *plock)
2661 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2663 /* Note: blr is not used in the default implementation. */
2664 return brl_lock_cancel_default(br_lck, plock);
2667 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2668 files_struct *fsp,
2669 struct lock_struct *plock)
2671 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2672 plock->lock_type == WRITE_LOCK);
2674 return strict_lock_check_default(fsp, plock);
2677 /* NT ACL operations. */
2679 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2680 files_struct *fsp,
2681 uint32_t security_info,
2682 TALLOC_CTX *mem_ctx,
2683 struct security_descriptor **ppdesc)
2685 NTSTATUS result;
2687 START_PROFILE(fget_nt_acl);
2688 result = posix_fget_nt_acl(fsp, security_info,
2689 mem_ctx, ppdesc);
2690 END_PROFILE(fget_nt_acl);
2691 return result;
2694 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2695 const struct smb_filename *smb_fname,
2696 uint32_t security_info,
2697 TALLOC_CTX *mem_ctx,
2698 struct security_descriptor **ppdesc)
2700 NTSTATUS result;
2702 START_PROFILE(get_nt_acl);
2703 result = posix_get_nt_acl(handle->conn,
2704 smb_fname,
2705 security_info,
2706 mem_ctx,
2707 ppdesc);
2708 END_PROFILE(get_nt_acl);
2709 return result;
2712 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2714 NTSTATUS result;
2716 START_PROFILE(fset_nt_acl);
2717 result = set_nt_acl(fsp, security_info_sent, psd);
2718 END_PROFILE(fset_nt_acl);
2719 return result;
2722 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2723 struct smb_filename *file,
2724 struct security_acl *sacl,
2725 uint32_t access_requested,
2726 uint32_t access_denied)
2728 return NT_STATUS_OK; /* Nothing to do here ... */
2731 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2732 const struct smb_filename *smb_fname,
2733 mode_t mode)
2735 #ifdef HAVE_NO_ACL
2736 errno = ENOSYS;
2737 return -1;
2738 #else
2739 int result;
2741 START_PROFILE(chmod_acl);
2742 result = chmod_acl(handle->conn, smb_fname, mode);
2743 END_PROFILE(chmod_acl);
2744 return result;
2745 #endif
2748 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2750 #ifdef HAVE_NO_ACL
2751 errno = ENOSYS;
2752 return -1;
2753 #else
2754 int result;
2756 START_PROFILE(fchmod_acl);
2757 result = fchmod_acl(fsp, mode);
2758 END_PROFILE(fchmod_acl);
2759 return result;
2760 #endif
2763 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2764 const struct smb_filename *smb_fname,
2765 SMB_ACL_TYPE_T type,
2766 TALLOC_CTX *mem_ctx)
2768 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2771 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2772 files_struct *fsp,
2773 TALLOC_CTX *mem_ctx)
2775 return sys_acl_get_fd(handle, fsp, mem_ctx);
2778 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2779 const struct smb_filename *smb_fname,
2780 SMB_ACL_TYPE_T acltype,
2781 SMB_ACL_T theacl)
2783 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2786 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2788 return sys_acl_set_fd(handle, fsp, theacl);
2791 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2792 const struct smb_filename *smb_fname)
2794 return sys_acl_delete_def_file(handle, smb_fname);
2797 /****************************************************************
2798 Extended attribute operations.
2799 *****************************************************************/
2801 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2802 const struct smb_filename *smb_fname,
2803 const char *name,
2804 void *value,
2805 size_t size)
2807 return getxattr(smb_fname->base_name, name, value, size);
2810 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2812 return fgetxattr(fsp->fh->fd, name, value, size);
2815 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2816 const struct smb_filename *smb_fname,
2817 char *list,
2818 size_t size)
2820 return listxattr(smb_fname->base_name, list, size);
2823 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2825 return flistxattr(fsp->fh->fd, list, size);
2828 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2829 const struct smb_filename *smb_fname,
2830 const char *name)
2832 return removexattr(smb_fname->base_name, name);
2835 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2837 return fremovexattr(fsp->fh->fd, name);
2840 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2841 const struct smb_filename *smb_fname,
2842 const char *name,
2843 const void *value,
2844 size_t size,
2845 int flags)
2847 return setxattr(smb_fname->base_name, name, value, size, flags);
2850 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2852 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2855 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2857 return false;
2860 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2861 const struct smb_filename *fname,
2862 SMB_STRUCT_STAT *sbuf)
2864 NTSTATUS status;
2865 char *path;
2866 bool offline = false;
2868 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2869 return false;
2872 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2873 #if defined(ENOTSUP)
2874 errno = ENOTSUP;
2875 #endif
2876 return false;
2879 status = get_full_smb_filename(talloc_tos(), fname, &path);
2880 if (!NT_STATUS_IS_OK(status)) {
2881 errno = map_errno_from_nt_status(status);
2882 return false;
2885 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2887 TALLOC_FREE(path);
2889 return offline;
2892 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2893 struct files_struct *fsp,
2894 TALLOC_CTX *mem_ctx,
2895 DATA_BLOB *cookie)
2897 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2900 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2901 struct files_struct *fsp,
2902 const DATA_BLOB old_cookie,
2903 TALLOC_CTX *mem_ctx,
2904 DATA_BLOB *new_cookie)
2906 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2907 new_cookie);
2910 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2911 struct smb_request *smb1req,
2912 struct smbXsrv_open *op,
2913 const DATA_BLOB old_cookie,
2914 TALLOC_CTX *mem_ctx,
2915 struct files_struct **fsp,
2916 DATA_BLOB *new_cookie)
2918 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2919 old_cookie, mem_ctx,
2920 fsp, new_cookie);
2923 static struct vfs_fn_pointers vfs_default_fns = {
2924 /* Disk operations */
2926 .connect_fn = vfswrap_connect,
2927 .disconnect_fn = vfswrap_disconnect,
2928 .disk_free_fn = vfswrap_disk_free,
2929 .get_quota_fn = vfswrap_get_quota,
2930 .set_quota_fn = vfswrap_set_quota,
2931 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2932 .statvfs_fn = vfswrap_statvfs,
2933 .fs_capabilities_fn = vfswrap_fs_capabilities,
2934 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2935 .snap_check_path_fn = vfswrap_snap_check_path,
2936 .snap_create_fn = vfswrap_snap_create,
2937 .snap_delete_fn = vfswrap_snap_delete,
2939 /* Directory operations */
2941 .opendir_fn = vfswrap_opendir,
2942 .fdopendir_fn = vfswrap_fdopendir,
2943 .readdir_fn = vfswrap_readdir,
2944 .readdir_attr_fn = vfswrap_readdir_attr,
2945 .seekdir_fn = vfswrap_seekdir,
2946 .telldir_fn = vfswrap_telldir,
2947 .rewind_dir_fn = vfswrap_rewinddir,
2948 .mkdir_fn = vfswrap_mkdir,
2949 .rmdir_fn = vfswrap_rmdir,
2950 .closedir_fn = vfswrap_closedir,
2952 /* File operations */
2954 .open_fn = vfswrap_open,
2955 .create_file_fn = vfswrap_create_file,
2956 .close_fn = vfswrap_close,
2957 .pread_fn = vfswrap_pread,
2958 .pread_send_fn = vfswrap_pread_send,
2959 .pread_recv_fn = vfswrap_pread_recv,
2960 .pwrite_fn = vfswrap_pwrite,
2961 .pwrite_send_fn = vfswrap_pwrite_send,
2962 .pwrite_recv_fn = vfswrap_pwrite_recv,
2963 .lseek_fn = vfswrap_lseek,
2964 .sendfile_fn = vfswrap_sendfile,
2965 .recvfile_fn = vfswrap_recvfile,
2966 .rename_fn = vfswrap_rename,
2967 .fsync_send_fn = vfswrap_fsync_send,
2968 .fsync_recv_fn = vfswrap_fsync_recv,
2969 .stat_fn = vfswrap_stat,
2970 .fstat_fn = vfswrap_fstat,
2971 .lstat_fn = vfswrap_lstat,
2972 .get_alloc_size_fn = vfswrap_get_alloc_size,
2973 .unlink_fn = vfswrap_unlink,
2974 .chmod_fn = vfswrap_chmod,
2975 .fchmod_fn = vfswrap_fchmod,
2976 .chown_fn = vfswrap_chown,
2977 .fchown_fn = vfswrap_fchown,
2978 .lchown_fn = vfswrap_lchown,
2979 .chdir_fn = vfswrap_chdir,
2980 .getwd_fn = vfswrap_getwd,
2981 .ntimes_fn = vfswrap_ntimes,
2982 .ftruncate_fn = vfswrap_ftruncate,
2983 .fallocate_fn = vfswrap_fallocate,
2984 .lock_fn = vfswrap_lock,
2985 .kernel_flock_fn = vfswrap_kernel_flock,
2986 .linux_setlease_fn = vfswrap_linux_setlease,
2987 .getlock_fn = vfswrap_getlock,
2988 .symlink_fn = vfswrap_symlink,
2989 .readlink_fn = vfswrap_readlink,
2990 .link_fn = vfswrap_link,
2991 .mknod_fn = vfswrap_mknod,
2992 .realpath_fn = vfswrap_realpath,
2993 .chflags_fn = vfswrap_chflags,
2994 .file_id_create_fn = vfswrap_file_id_create,
2995 .streaminfo_fn = vfswrap_streaminfo,
2996 .get_real_filename_fn = vfswrap_get_real_filename,
2997 .connectpath_fn = vfswrap_connectpath,
2998 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2999 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3000 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3001 .strict_lock_check_fn = vfswrap_strict_lock_check,
3002 .translate_name_fn = vfswrap_translate_name,
3003 .fsctl_fn = vfswrap_fsctl,
3004 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3005 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3006 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3007 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3008 .offload_read_send_fn = vfswrap_offload_read_send,
3009 .offload_read_recv_fn = vfswrap_offload_read_recv,
3010 .offload_write_send_fn = vfswrap_offload_write_send,
3011 .offload_write_recv_fn = vfswrap_offload_write_recv,
3012 .get_compression_fn = vfswrap_get_compression,
3013 .set_compression_fn = vfswrap_set_compression,
3015 /* NT ACL operations. */
3017 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3018 .get_nt_acl_fn = vfswrap_get_nt_acl,
3019 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3020 .audit_file_fn = vfswrap_audit_file,
3022 /* POSIX ACL operations. */
3024 .chmod_acl_fn = vfswrap_chmod_acl,
3025 .fchmod_acl_fn = vfswrap_fchmod_acl,
3027 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3028 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3029 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3030 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3031 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3032 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3033 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3035 /* EA operations. */
3036 .getxattr_fn = vfswrap_getxattr,
3037 .fgetxattr_fn = vfswrap_fgetxattr,
3038 .listxattr_fn = vfswrap_listxattr,
3039 .flistxattr_fn = vfswrap_flistxattr,
3040 .removexattr_fn = vfswrap_removexattr,
3041 .fremovexattr_fn = vfswrap_fremovexattr,
3042 .setxattr_fn = vfswrap_setxattr,
3043 .fsetxattr_fn = vfswrap_fsetxattr,
3045 /* aio operations */
3046 .aio_force_fn = vfswrap_aio_force,
3048 /* durable handle operations */
3049 .durable_cookie_fn = vfswrap_durable_cookie,
3050 .durable_disconnect_fn = vfswrap_durable_disconnect,
3051 .durable_reconnect_fn = vfswrap_durable_reconnect,
3054 static_decl_vfs;
3055 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3057 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3058 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);