s3:smbd: call pthreadpool_tevent_init() already in smbd_process()
[Samba.git] / source3 / modules / vfs_default.c
blobe2efdabf47ce98d62ebfc67e4bee84dd42fe4c07
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_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
619 ssize_t result;
621 START_PROFILE_BYTES(syscall_read, n);
622 result = sys_read(fsp->fh->fd, data, n);
623 END_PROFILE_BYTES(syscall_read);
624 return result;
627 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
628 size_t n, off_t offset)
630 ssize_t result;
632 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
633 START_PROFILE_BYTES(syscall_pread, n);
634 result = sys_pread(fsp->fh->fd, data, n, offset);
635 END_PROFILE_BYTES(syscall_pread);
637 if (result == -1 && errno == ESPIPE) {
638 /* Maintain the fiction that pipes can be seeked (sought?) on. */
639 result = SMB_VFS_READ(fsp, data, n);
640 fsp->fh->pos = 0;
643 #else /* HAVE_PREAD */
644 off_t curr;
645 int lerrno;
647 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
648 if (curr == -1 && errno == ESPIPE) {
649 /* Maintain the fiction that pipes can be seeked (sought?) on. */
650 result = SMB_VFS_READ(fsp, data, n);
651 fsp->fh->pos = 0;
652 return result;
655 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
656 return -1;
659 errno = 0;
660 result = SMB_VFS_READ(fsp, data, n);
661 lerrno = errno;
663 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
664 errno = lerrno;
666 #endif /* HAVE_PREAD */
668 return result;
671 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
673 ssize_t result;
675 START_PROFILE_BYTES(syscall_write, n);
676 result = sys_write(fsp->fh->fd, data, n);
677 END_PROFILE_BYTES(syscall_write);
678 return result;
681 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
682 size_t n, off_t offset)
684 ssize_t result;
686 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
687 START_PROFILE_BYTES(syscall_pwrite, n);
688 result = sys_pwrite(fsp->fh->fd, data, n, offset);
689 END_PROFILE_BYTES(syscall_pwrite);
691 if (result == -1 && errno == ESPIPE) {
692 /* Maintain the fiction that pipes can be sought on. */
693 result = SMB_VFS_WRITE(fsp, data, n);
696 #else /* HAVE_PWRITE */
697 off_t curr;
698 int lerrno;
700 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
701 if (curr == -1) {
702 return -1;
705 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
706 return -1;
709 result = SMB_VFS_WRITE(fsp, data, n);
710 lerrno = errno;
712 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
713 errno = lerrno;
715 #endif /* HAVE_PWRITE */
717 return result;
720 struct vfswrap_pread_state {
721 ssize_t ret;
722 int fd;
723 void *buf;
724 size_t count;
725 off_t offset;
727 struct vfs_aio_state vfs_aio_state;
728 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
731 static void vfs_pread_do(void *private_data);
732 static void vfs_pread_done(struct tevent_req *subreq);
733 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
735 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
736 TALLOC_CTX *mem_ctx,
737 struct tevent_context *ev,
738 struct files_struct *fsp,
739 void *data,
740 size_t n, off_t offset)
742 struct tevent_req *req, *subreq;
743 struct vfswrap_pread_state *state;
745 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
746 if (req == NULL) {
747 return NULL;
750 state->ret = -1;
751 state->fd = fsp->fh->fd;
752 state->buf = data;
753 state->count = n;
754 state->offset = offset;
756 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
757 state->profile_bytes, n);
758 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
760 subreq = pthreadpool_tevent_job_send(
761 state, ev, handle->conn->sconn->pool,
762 vfs_pread_do, state);
763 if (tevent_req_nomem(subreq, req)) {
764 return tevent_req_post(req, ev);
766 tevent_req_set_callback(subreq, vfs_pread_done, req);
768 talloc_set_destructor(state, vfs_pread_state_destructor);
770 return req;
773 static void vfs_pread_do(void *private_data)
775 struct vfswrap_pread_state *state = talloc_get_type_abort(
776 private_data, struct vfswrap_pread_state);
777 struct timespec start_time;
778 struct timespec end_time;
780 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
782 PROFILE_TIMESTAMP(&start_time);
784 do {
785 state->ret = pread(state->fd, state->buf, state->count,
786 state->offset);
787 } while ((state->ret == -1) && (errno == EINTR));
789 if (state->ret == -1) {
790 state->vfs_aio_state.error = errno;
793 PROFILE_TIMESTAMP(&end_time);
795 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
797 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
800 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
802 return -1;
805 static void vfs_pread_done(struct tevent_req *subreq)
807 struct tevent_req *req = tevent_req_callback_data(
808 subreq, struct tevent_req);
809 struct vfswrap_pread_state *state = tevent_req_data(
810 req, struct vfswrap_pread_state);
811 int ret;
813 ret = pthreadpool_tevent_job_recv(subreq);
814 TALLOC_FREE(subreq);
815 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
816 talloc_set_destructor(state, NULL);
817 if (tevent_req_error(req, ret)) {
818 return;
821 tevent_req_done(req);
824 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
825 struct vfs_aio_state *vfs_aio_state)
827 struct vfswrap_pread_state *state = tevent_req_data(
828 req, struct vfswrap_pread_state);
830 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
831 return -1;
834 *vfs_aio_state = state->vfs_aio_state;
835 return state->ret;
838 struct vfswrap_pwrite_state {
839 ssize_t ret;
840 int fd;
841 const void *buf;
842 size_t count;
843 off_t offset;
845 struct vfs_aio_state vfs_aio_state;
846 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
849 static void vfs_pwrite_do(void *private_data);
850 static void vfs_pwrite_done(struct tevent_req *subreq);
851 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
853 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
854 TALLOC_CTX *mem_ctx,
855 struct tevent_context *ev,
856 struct files_struct *fsp,
857 const void *data,
858 size_t n, off_t offset)
860 struct tevent_req *req, *subreq;
861 struct vfswrap_pwrite_state *state;
863 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
864 if (req == NULL) {
865 return NULL;
868 state->ret = -1;
869 state->fd = fsp->fh->fd;
870 state->buf = data;
871 state->count = n;
872 state->offset = offset;
874 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
875 state->profile_bytes, n);
876 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
878 subreq = pthreadpool_tevent_job_send(
879 state, ev, handle->conn->sconn->pool,
880 vfs_pwrite_do, state);
881 if (tevent_req_nomem(subreq, req)) {
882 return tevent_req_post(req, ev);
884 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
886 talloc_set_destructor(state, vfs_pwrite_state_destructor);
888 return req;
891 static void vfs_pwrite_do(void *private_data)
893 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
894 private_data, struct vfswrap_pwrite_state);
895 struct timespec start_time;
896 struct timespec end_time;
898 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
900 PROFILE_TIMESTAMP(&start_time);
902 do {
903 state->ret = pwrite(state->fd, state->buf, state->count,
904 state->offset);
905 } while ((state->ret == -1) && (errno == EINTR));
907 if (state->ret == -1) {
908 state->vfs_aio_state.error = errno;
911 PROFILE_TIMESTAMP(&end_time);
913 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
915 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
918 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
920 return -1;
923 static void vfs_pwrite_done(struct tevent_req *subreq)
925 struct tevent_req *req = tevent_req_callback_data(
926 subreq, struct tevent_req);
927 struct vfswrap_pwrite_state *state = tevent_req_data(
928 req, struct vfswrap_pwrite_state);
929 int ret;
931 ret = pthreadpool_tevent_job_recv(subreq);
932 TALLOC_FREE(subreq);
933 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
934 talloc_set_destructor(state, NULL);
935 if (tevent_req_error(req, ret)) {
936 return;
939 tevent_req_done(req);
942 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
943 struct vfs_aio_state *vfs_aio_state)
945 struct vfswrap_pwrite_state *state = tevent_req_data(
946 req, struct vfswrap_pwrite_state);
948 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
949 return -1;
952 *vfs_aio_state = state->vfs_aio_state;
953 return state->ret;
956 struct vfswrap_fsync_state {
957 ssize_t ret;
958 int fd;
960 struct vfs_aio_state vfs_aio_state;
961 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
964 static void vfs_fsync_do(void *private_data);
965 static void vfs_fsync_done(struct tevent_req *subreq);
966 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
968 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
969 TALLOC_CTX *mem_ctx,
970 struct tevent_context *ev,
971 struct files_struct *fsp)
973 struct tevent_req *req, *subreq;
974 struct vfswrap_fsync_state *state;
976 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
977 if (req == NULL) {
978 return NULL;
981 state->ret = -1;
982 state->fd = fsp->fh->fd;
984 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
985 state->profile_basic);
987 subreq = pthreadpool_tevent_job_send(
988 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
989 if (tevent_req_nomem(subreq, req)) {
990 return tevent_req_post(req, ev);
992 tevent_req_set_callback(subreq, vfs_fsync_done, req);
994 talloc_set_destructor(state, vfs_fsync_state_destructor);
996 return req;
999 static void vfs_fsync_do(void *private_data)
1001 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1002 private_data, struct vfswrap_fsync_state);
1003 struct timespec start_time;
1004 struct timespec end_time;
1006 PROFILE_TIMESTAMP(&start_time);
1008 do {
1009 state->ret = fsync(state->fd);
1010 } while ((state->ret == -1) && (errno == EINTR));
1012 if (state->ret == -1) {
1013 state->vfs_aio_state.error = errno;
1016 PROFILE_TIMESTAMP(&end_time);
1018 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1021 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1023 return -1;
1026 static void vfs_fsync_done(struct tevent_req *subreq)
1028 struct tevent_req *req = tevent_req_callback_data(
1029 subreq, struct tevent_req);
1030 struct vfswrap_fsync_state *state = tevent_req_data(
1031 req, struct vfswrap_fsync_state);
1032 int ret;
1034 ret = pthreadpool_tevent_job_recv(subreq);
1035 TALLOC_FREE(subreq);
1036 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1037 talloc_set_destructor(state, NULL);
1038 if (tevent_req_error(req, ret)) {
1039 return;
1042 tevent_req_done(req);
1045 static int vfswrap_fsync_recv(struct tevent_req *req,
1046 struct vfs_aio_state *vfs_aio_state)
1048 struct vfswrap_fsync_state *state = tevent_req_data(
1049 req, struct vfswrap_fsync_state);
1051 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1052 return -1;
1055 *vfs_aio_state = state->vfs_aio_state;
1056 return state->ret;
1059 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1061 off_t result = 0;
1063 START_PROFILE(syscall_lseek);
1065 /* Cope with 'stat' file opens. */
1066 if (fsp->fh->fd != -1)
1067 result = lseek(fsp->fh->fd, offset, whence);
1070 * We want to maintain the fiction that we can seek
1071 * on a fifo for file system purposes. This allows
1072 * people to set up UNIX fifo's that feed data to Windows
1073 * applications. JRA.
1076 if((result == -1) && (errno == ESPIPE)) {
1077 result = 0;
1078 errno = 0;
1081 END_PROFILE(syscall_lseek);
1082 return result;
1085 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1086 off_t offset, size_t n)
1088 ssize_t result;
1090 START_PROFILE_BYTES(syscall_sendfile, n);
1091 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1092 END_PROFILE_BYTES(syscall_sendfile);
1093 return result;
1096 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1097 int fromfd,
1098 files_struct *tofsp,
1099 off_t offset,
1100 size_t n)
1102 ssize_t result;
1104 START_PROFILE_BYTES(syscall_recvfile, n);
1105 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1106 END_PROFILE_BYTES(syscall_recvfile);
1107 return result;
1110 static int vfswrap_rename(vfs_handle_struct *handle,
1111 const struct smb_filename *smb_fname_src,
1112 const struct smb_filename *smb_fname_dst)
1114 int result = -1;
1116 START_PROFILE(syscall_rename);
1118 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1119 errno = ENOENT;
1120 goto out;
1123 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1125 out:
1126 END_PROFILE(syscall_rename);
1127 return result;
1130 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1132 #ifdef HAVE_FSYNC
1133 int result;
1135 START_PROFILE(syscall_fsync);
1136 result = fsync(fsp->fh->fd);
1137 END_PROFILE(syscall_fsync);
1138 return result;
1139 #else
1140 return 0;
1141 #endif
1144 static int vfswrap_stat(vfs_handle_struct *handle,
1145 struct smb_filename *smb_fname)
1147 int result = -1;
1149 START_PROFILE(syscall_stat);
1151 if (smb_fname->stream_name) {
1152 errno = ENOENT;
1153 goto out;
1156 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1157 lp_fake_directory_create_times(SNUM(handle->conn)));
1158 out:
1159 END_PROFILE(syscall_stat);
1160 return result;
1163 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1165 int result;
1167 START_PROFILE(syscall_fstat);
1168 result = sys_fstat(fsp->fh->fd,
1169 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1170 END_PROFILE(syscall_fstat);
1171 return result;
1174 static int vfswrap_lstat(vfs_handle_struct *handle,
1175 struct smb_filename *smb_fname)
1177 int result = -1;
1179 START_PROFILE(syscall_lstat);
1181 if (smb_fname->stream_name) {
1182 errno = ENOENT;
1183 goto out;
1186 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1187 lp_fake_directory_create_times(SNUM(handle->conn)));
1188 out:
1189 END_PROFILE(syscall_lstat);
1190 return result;
1193 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1194 const char *name,
1195 enum vfs_translate_direction direction,
1196 TALLOC_CTX *mem_ctx,
1197 char **mapped_name)
1199 return NT_STATUS_NONE_MAPPED;
1203 * Implement the default fsctl operation.
1205 static bool vfswrap_logged_ioctl_message = false;
1207 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1208 struct files_struct *fsp,
1209 TALLOC_CTX *ctx,
1210 uint32_t function,
1211 uint16_t req_flags, /* Needed for UNICODE ... */
1212 const uint8_t *_in_data,
1213 uint32_t in_len,
1214 uint8_t **_out_data,
1215 uint32_t max_out_len,
1216 uint32_t *out_len)
1218 const char *in_data = (const char *)_in_data;
1219 char **out_data = (char **)_out_data;
1220 NTSTATUS status;
1222 switch (function) {
1223 case FSCTL_SET_SPARSE:
1225 bool set_sparse = true;
1227 if (in_len >= 1 && in_data[0] == 0) {
1228 set_sparse = false;
1231 status = file_set_sparse(handle->conn, fsp, set_sparse);
1233 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1234 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1235 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1236 nt_errstr(status)));
1238 return status;
1241 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1243 unsigned char objid[16];
1244 char *return_data = NULL;
1246 /* This should return the object-id on this file.
1247 * I think I'll make this be the inode+dev. JRA.
1250 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1251 fsp_fnum_dbg(fsp)));
1253 *out_len = MIN(max_out_len, 64);
1255 /* Hmmm, will this cause problems if less data asked for? */
1256 return_data = talloc_array(ctx, char, 64);
1257 if (return_data == NULL) {
1258 return NT_STATUS_NO_MEMORY;
1261 /* For backwards compatibility only store the dev/inode. */
1262 push_file_id_16(return_data, &fsp->file_id);
1263 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1264 push_file_id_16(return_data+32, &fsp->file_id);
1265 memset(return_data+48, 0, 16);
1266 *out_data = return_data;
1267 return NT_STATUS_OK;
1270 case FSCTL_GET_REPARSE_POINT:
1272 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1273 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1274 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1275 return NT_STATUS_NOT_A_REPARSE_POINT;
1278 case FSCTL_SET_REPARSE_POINT:
1280 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1281 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1282 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1283 return NT_STATUS_NOT_A_REPARSE_POINT;
1286 case FSCTL_GET_SHADOW_COPY_DATA:
1289 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1290 * and return their volume names. If max_data_count is 16, then it is just
1291 * asking for the number of volumes and length of the combined names.
1293 * pdata is the data allocated by our caller, but that uses
1294 * total_data_count (which is 0 in our case) rather than max_data_count.
1295 * Allocate the correct amount and return the pointer to let
1296 * it be deallocated when we return.
1298 struct shadow_copy_data *shadow_data = NULL;
1299 bool labels = False;
1300 uint32_t labels_data_count = 0;
1301 uint32_t i;
1302 char *cur_pdata = NULL;
1304 if (max_out_len < 16) {
1305 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1306 max_out_len));
1307 return NT_STATUS_INVALID_PARAMETER;
1310 if (max_out_len > 16) {
1311 labels = True;
1314 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1315 if (shadow_data == NULL) {
1316 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1317 return NT_STATUS_NO_MEMORY;
1321 * Call the VFS routine to actually do the work.
1323 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1324 int log_lev = 0;
1325 if (errno == 0) {
1326 /* broken module didn't set errno on error */
1327 status = NT_STATUS_UNSUCCESSFUL;
1328 } else {
1329 status = map_nt_error_from_unix(errno);
1330 if (NT_STATUS_EQUAL(status,
1331 NT_STATUS_NOT_SUPPORTED)) {
1332 log_lev = 5;
1335 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1336 "connectpath %s, failed - %s.\n",
1337 fsp->conn->connectpath,
1338 nt_errstr(status)));
1339 TALLOC_FREE(shadow_data);
1340 return status;
1343 labels_data_count = (shadow_data->num_volumes * 2 *
1344 sizeof(SHADOW_COPY_LABEL)) + 2;
1346 if (!labels) {
1347 *out_len = 16;
1348 } else {
1349 *out_len = 12 + labels_data_count;
1352 if (max_out_len < *out_len) {
1353 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1354 max_out_len, *out_len));
1355 TALLOC_FREE(shadow_data);
1356 return NT_STATUS_BUFFER_TOO_SMALL;
1359 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1360 if (cur_pdata == NULL) {
1361 TALLOC_FREE(shadow_data);
1362 return NT_STATUS_NO_MEMORY;
1365 *out_data = cur_pdata;
1367 /* num_volumes 4 bytes */
1368 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1370 if (labels) {
1371 /* num_labels 4 bytes */
1372 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1375 /* needed_data_count 4 bytes */
1376 SIVAL(cur_pdata, 8, labels_data_count);
1378 cur_pdata += 12;
1380 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1381 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1382 if (labels && shadow_data->labels) {
1383 for (i=0; i<shadow_data->num_volumes; i++) {
1384 size_t len = 0;
1385 status = srvstr_push(cur_pdata, req_flags,
1386 cur_pdata, shadow_data->labels[i],
1387 2 * sizeof(SHADOW_COPY_LABEL),
1388 STR_UNICODE|STR_TERMINATE, &len);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 TALLOC_FREE(*out_data);
1391 TALLOC_FREE(shadow_data);
1392 return status;
1394 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1395 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1399 TALLOC_FREE(shadow_data);
1401 return NT_STATUS_OK;
1404 case FSCTL_FIND_FILES_BY_SID:
1406 /* pretend this succeeded -
1408 * we have to send back a list with all files owned by this SID
1410 * but I have to check that --metze
1412 struct dom_sid sid;
1413 uid_t uid;
1414 size_t sid_len;
1416 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1417 fsp_fnum_dbg(fsp)));
1419 if (in_len < 8) {
1420 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1421 return NT_STATUS_INVALID_PARAMETER;
1424 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1426 /* unknown 4 bytes: this is not the length of the sid :-( */
1427 /*unknown = IVAL(pdata,0);*/
1429 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1430 return NT_STATUS_INVALID_PARAMETER;
1432 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1434 if (!sid_to_uid(&sid, &uid)) {
1435 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1436 sid_string_dbg(&sid),
1437 (unsigned long)sid_len));
1438 uid = (-1);
1441 /* we can take a look at the find source :-)
1443 * find ./ -uid $uid -name '*' is what we need here
1446 * and send 4bytes len and then NULL terminated unicode strings
1447 * for each file
1449 * but I don't know how to deal with the paged results
1450 * (maybe we can hang the result anywhere in the fsp struct)
1452 * but I don't know how to deal with the paged results
1453 * (maybe we can hang the result anywhere in the fsp struct)
1455 * we don't send all files at once
1456 * and at the next we should *not* start from the beginning,
1457 * so we have to cache the result
1459 * --metze
1462 /* this works for now... */
1463 return NT_STATUS_OK;
1466 case FSCTL_QUERY_ALLOCATED_RANGES:
1468 /* FIXME: This is just a dummy reply, telling that all of the
1469 * file is allocated. MKS cp needs that.
1470 * Adding the real allocated ranges via FIEMAP on Linux
1471 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1472 * this FSCTL correct for sparse files.
1474 uint64_t offset, length;
1475 char *out_data_tmp = NULL;
1477 if (in_len != 16) {
1478 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1479 in_len));
1480 return NT_STATUS_INVALID_PARAMETER;
1483 if (max_out_len < 16) {
1484 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1485 max_out_len));
1486 return NT_STATUS_INVALID_PARAMETER;
1489 offset = BVAL(in_data,0);
1490 length = BVAL(in_data,8);
1492 if (offset + length < offset) {
1493 /* No 64-bit integer wrap. */
1494 return NT_STATUS_INVALID_PARAMETER;
1497 /* Shouldn't this be SMB_VFS_STAT ... ? */
1498 status = vfs_stat_fsp(fsp);
1499 if (!NT_STATUS_IS_OK(status)) {
1500 return status;
1503 *out_len = 16;
1504 out_data_tmp = talloc_array(ctx, char, *out_len);
1505 if (out_data_tmp == NULL) {
1506 DEBUG(10, ("unable to allocate memory for response\n"));
1507 return NT_STATUS_NO_MEMORY;
1510 if (offset > fsp->fsp_name->st.st_ex_size ||
1511 fsp->fsp_name->st.st_ex_size == 0 ||
1512 length == 0) {
1513 memset(out_data_tmp, 0, *out_len);
1514 } else {
1515 uint64_t end = offset + length;
1516 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1517 SBVAL(out_data_tmp, 0, 0);
1518 SBVAL(out_data_tmp, 8, end);
1521 *out_data = out_data_tmp;
1523 return NT_STATUS_OK;
1526 case FSCTL_IS_VOLUME_DIRTY:
1528 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1529 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1531 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1532 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1534 return NT_STATUS_INVALID_PARAMETER;
1537 default:
1539 * Only print once ... unfortunately there could be lots of
1540 * different FSCTLs that are called.
1542 if (!vfswrap_logged_ioctl_message) {
1543 vfswrap_logged_ioctl_message = true;
1544 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1545 __func__, function));
1549 return NT_STATUS_NOT_SUPPORTED;
1552 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1553 const struct smb_filename *fname,
1554 SMB_STRUCT_STAT *sbuf);
1556 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1557 struct smb_filename *smb_fname,
1558 uint32_t *dosmode)
1560 bool offline;
1562 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1563 if (offline) {
1564 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1567 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1570 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1571 struct files_struct *fsp,
1572 uint32_t *dosmode)
1574 bool offline;
1576 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1577 if (offline) {
1578 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1581 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1584 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1585 const struct smb_filename *smb_fname,
1586 uint32_t dosmode)
1588 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1591 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1592 struct files_struct *fsp,
1593 uint32_t dosmode)
1595 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1598 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1600 struct vfswrap_offload_read_state {
1601 DATA_BLOB token;
1604 static struct tevent_req *vfswrap_offload_read_send(
1605 TALLOC_CTX *mem_ctx,
1606 struct tevent_context *ev,
1607 struct vfs_handle_struct *handle,
1608 struct files_struct *fsp,
1609 uint32_t fsctl,
1610 uint32_t ttl,
1611 off_t offset,
1612 size_t to_copy)
1614 struct tevent_req *req = NULL;
1615 struct vfswrap_offload_read_state *state = NULL;
1616 NTSTATUS status;
1618 req = tevent_req_create(mem_ctx, &state,
1619 struct vfswrap_offload_read_state);
1620 if (req == NULL) {
1621 return NULL;
1624 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1625 &vfswrap_offload_ctx);
1626 if (tevent_req_nterror(req, status)) {
1627 return tevent_req_post(req, ev);
1630 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1631 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1632 return tevent_req_post(req, ev);
1635 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1636 &state->token);
1637 if (tevent_req_nterror(req, status)) {
1638 return tevent_req_post(req, ev);
1641 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1642 &state->token);
1643 if (tevent_req_nterror(req, status)) {
1644 return tevent_req_post(req, ev);
1647 tevent_req_done(req);
1648 return tevent_req_post(req, ev);
1651 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1652 struct vfs_handle_struct *handle,
1653 TALLOC_CTX *mem_ctx,
1654 DATA_BLOB *token)
1656 struct vfswrap_offload_read_state *state = tevent_req_data(
1657 req, struct vfswrap_offload_read_state);
1658 NTSTATUS status;
1660 if (tevent_req_is_nterror(req, &status)) {
1661 tevent_req_received(req);
1662 return status;
1665 token->length = state->token.length;
1666 token->data = talloc_move(mem_ctx, &state->token.data);
1668 tevent_req_received(req);
1669 return NT_STATUS_OK;
1672 struct vfswrap_offload_write_state {
1673 struct tevent_context *ev;
1674 uint8_t *buf;
1675 bool read_lck_locked;
1676 bool write_lck_locked;
1677 DATA_BLOB *token;
1678 struct files_struct *src_fsp;
1679 off_t src_off;
1680 struct files_struct *dst_fsp;
1681 off_t dst_off;
1682 off_t to_copy;
1683 off_t remaining;
1684 size_t next_io_size;
1687 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1689 static struct tevent_req *vfswrap_offload_write_send(
1690 struct vfs_handle_struct *handle,
1691 TALLOC_CTX *mem_ctx,
1692 struct tevent_context *ev,
1693 uint32_t fsctl,
1694 DATA_BLOB *token,
1695 off_t transfer_offset,
1696 struct files_struct *dest_fsp,
1697 off_t dest_off,
1698 off_t to_copy)
1700 struct tevent_req *req;
1701 struct vfswrap_offload_write_state *state = NULL;
1702 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1703 files_struct *src_fsp = NULL;
1704 NTSTATUS status;
1706 req = tevent_req_create(mem_ctx, &state,
1707 struct vfswrap_offload_write_state);
1708 if (req == NULL) {
1709 return NULL;
1712 *state = (struct vfswrap_offload_write_state) {
1713 .ev = ev,
1714 .token = token,
1715 .src_off = transfer_offset,
1716 .dst_fsp = dest_fsp,
1717 .dst_off = dest_off,
1718 .to_copy = to_copy,
1719 .remaining = to_copy,
1722 switch (fsctl) {
1723 case FSCTL_SRV_COPYCHUNK:
1724 case FSCTL_SRV_COPYCHUNK_WRITE:
1725 break;
1727 case FSCTL_OFFLOAD_WRITE:
1728 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1729 return tevent_req_post(req, ev);
1731 case FSCTL_DUP_EXTENTS_TO_FILE:
1732 DBG_DEBUG("COW clones not supported by vfs_default\n");
1733 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1734 return tevent_req_post(req, ev);
1736 default:
1737 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1738 return tevent_req_post(req, ev);
1742 * From here on we assume a copy-chunk fsctl
1745 if (to_copy == 0) {
1746 tevent_req_done(req);
1747 return tevent_req_post(req, ev);
1750 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1751 token, &src_fsp);
1752 if (tevent_req_nterror(req, status)) {
1753 return tevent_req_post(req, ev);
1755 state->src_fsp = src_fsp;
1757 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1759 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 tevent_req_nterror(req, status);
1762 return tevent_req_post(req, ev);
1765 state->buf = talloc_array(state, uint8_t, num);
1766 if (tevent_req_nomem(state->buf, req)) {
1767 return tevent_req_post(req, ev);
1770 status = vfs_stat_fsp(src_fsp);
1771 if (tevent_req_nterror(req, status)) {
1772 return tevent_req_post(req, ev);
1775 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1777 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1778 * If the SourceOffset or SourceOffset + Length extends beyond
1779 * the end of file, the server SHOULD<240> treat this as a
1780 * STATUS_END_OF_FILE error.
1781 * ...
1782 * <240> Section 3.3.5.15.6: Windows servers will return
1783 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1785 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1786 return tevent_req_post(req, ev);
1789 if (src_fsp->op == NULL) {
1790 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1791 return tevent_req_post(req, ev);
1794 if (dest_fsp->op == NULL) {
1795 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1796 return tevent_req_post(req, ev);
1799 status = vfswrap_offload_write_loop(req);
1800 if (!NT_STATUS_IS_OK(status)) {
1801 tevent_req_nterror(req, status);
1802 return tevent_req_post(req, ev);
1805 return req;
1808 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1810 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1812 struct vfswrap_offload_write_state *state = tevent_req_data(
1813 req, struct vfswrap_offload_write_state);
1814 struct tevent_req *subreq = NULL;
1815 struct lock_struct read_lck;
1816 bool ok;
1818 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1820 init_strict_lock_struct(state->src_fsp,
1821 state->src_fsp->op->global->open_persistent_id,
1822 state->src_off,
1823 state->next_io_size,
1824 READ_LOCK,
1825 &read_lck);
1827 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1828 state->src_fsp,
1829 &read_lck);
1830 if (!ok) {
1831 return NT_STATUS_FILE_LOCK_CONFLICT;
1834 subreq = SMB_VFS_PREAD_SEND(state,
1835 state->src_fsp->conn->sconn->ev_ctx,
1836 state->src_fsp,
1837 state->buf,
1838 state->next_io_size,
1839 state->src_off);
1840 if (subreq == NULL) {
1841 return NT_STATUS_NO_MEMORY;
1843 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1845 return NT_STATUS_OK;
1848 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1850 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1852 struct tevent_req *req = tevent_req_callback_data(
1853 subreq, struct tevent_req);
1854 struct vfswrap_offload_write_state *state = tevent_req_data(
1855 req, struct vfswrap_offload_write_state);
1856 struct vfs_aio_state aio_state;
1857 struct lock_struct write_lck;
1858 ssize_t nread;
1859 bool ok;
1861 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1862 TALLOC_FREE(subreq);
1863 if (nread == -1) {
1864 DBG_ERR("read failed: %s\n", strerror(errno));
1865 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1866 return;
1868 if (nread != state->next_io_size) {
1869 DBG_ERR("Short read, only %zd of %zu\n",
1870 nread, state->next_io_size);
1871 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1872 return;
1875 state->src_off += nread;
1877 init_strict_lock_struct(state->dst_fsp,
1878 state->dst_fsp->op->global->open_persistent_id,
1879 state->dst_off,
1880 state->next_io_size,
1881 WRITE_LOCK,
1882 &write_lck);
1884 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1885 state->dst_fsp,
1886 &write_lck);
1887 if (!ok) {
1888 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1889 return;
1892 subreq = SMB_VFS_PWRITE_SEND(state,
1893 state->ev,
1894 state->dst_fsp,
1895 state->buf,
1896 state->next_io_size,
1897 state->dst_off);
1898 if (subreq == NULL) {
1899 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1900 return;
1902 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1905 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1907 struct tevent_req *req = tevent_req_callback_data(
1908 subreq, struct tevent_req);
1909 struct vfswrap_offload_write_state *state = tevent_req_data(
1910 req, struct vfswrap_offload_write_state);
1911 struct vfs_aio_state aio_state;
1912 ssize_t nwritten;
1913 NTSTATUS status;
1915 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1916 TALLOC_FREE(subreq);
1917 if (nwritten == -1) {
1918 DBG_ERR("write failed: %s\n", strerror(errno));
1919 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1920 return;
1922 if (nwritten != state->next_io_size) {
1923 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1924 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1925 return;
1928 state->dst_off += nwritten;
1930 if (state->remaining < nwritten) {
1931 /* Paranoia check */
1932 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1933 return;
1935 state->remaining -= nwritten;
1936 if (state->remaining == 0) {
1937 tevent_req_done(req);
1938 return;
1941 status = vfswrap_offload_write_loop(req);
1942 if (!NT_STATUS_IS_OK(status)) {
1943 tevent_req_nterror(req, status);
1944 return;
1947 return;
1950 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1951 struct tevent_req *req,
1952 off_t *copied)
1954 struct vfswrap_offload_write_state *state = tevent_req_data(
1955 req, struct vfswrap_offload_write_state);
1956 NTSTATUS status;
1958 if (tevent_req_is_nterror(req, &status)) {
1959 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1960 *copied = 0;
1961 tevent_req_received(req);
1962 return status;
1965 *copied = state->to_copy;
1966 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1967 tevent_req_received(req);
1969 return NT_STATUS_OK;
1972 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1973 TALLOC_CTX *mem_ctx,
1974 struct files_struct *fsp,
1975 struct smb_filename *smb_fname,
1976 uint16_t *_compression_fmt)
1978 return NT_STATUS_INVALID_DEVICE_REQUEST;
1981 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1982 TALLOC_CTX *mem_ctx,
1983 struct files_struct *fsp,
1984 uint16_t compression_fmt)
1986 return NT_STATUS_INVALID_DEVICE_REQUEST;
1989 /********************************************************************
1990 Given a stat buffer return the allocated size on disk, taking into
1991 account sparse files.
1992 ********************************************************************/
1993 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1994 struct files_struct *fsp,
1995 const SMB_STRUCT_STAT *sbuf)
1997 uint64_t result;
1999 START_PROFILE(syscall_get_alloc_size);
2001 if(S_ISDIR(sbuf->st_ex_mode)) {
2002 result = 0;
2003 goto out;
2006 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2007 /* The type of st_blocksize is blkcnt_t which *MUST* be
2008 signed (according to POSIX) and can be less than 64-bits.
2009 Ensure when we're converting to 64 bits wide we don't
2010 sign extend. */
2011 #if defined(SIZEOF_BLKCNT_T_8)
2012 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2013 #elif defined(SIZEOF_BLKCNT_T_4)
2015 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2016 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2018 #else
2019 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2020 #endif
2021 if (result == 0) {
2023 * Some file systems do not allocate a block for very
2024 * small files. But for non-empty file should report a
2025 * positive size.
2028 uint64_t filesize = get_file_size_stat(sbuf);
2029 if (filesize > 0) {
2030 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2033 #else
2034 result = get_file_size_stat(sbuf);
2035 #endif
2037 if (fsp && fsp->initial_allocation_size)
2038 result = MAX(result,fsp->initial_allocation_size);
2040 result = smb_roundup(handle->conn, result);
2042 out:
2043 END_PROFILE(syscall_get_alloc_size);
2044 return result;
2047 static int vfswrap_unlink(vfs_handle_struct *handle,
2048 const struct smb_filename *smb_fname)
2050 int result = -1;
2052 START_PROFILE(syscall_unlink);
2054 if (smb_fname->stream_name) {
2055 errno = ENOENT;
2056 goto out;
2058 result = unlink(smb_fname->base_name);
2060 out:
2061 END_PROFILE(syscall_unlink);
2062 return result;
2065 static int vfswrap_chmod(vfs_handle_struct *handle,
2066 const struct smb_filename *smb_fname,
2067 mode_t mode)
2069 int result;
2071 START_PROFILE(syscall_chmod);
2074 * We need to do this due to the fact that the default POSIX ACL
2075 * chmod modifies the ACL *mask* for the group owner, not the
2076 * group owner bits directly. JRA.
2081 int saved_errno = errno; /* We might get ENOSYS */
2082 result = SMB_VFS_CHMOD_ACL(handle->conn,
2083 smb_fname,
2084 mode);
2085 if (result == 0) {
2086 END_PROFILE(syscall_chmod);
2087 return result;
2089 /* Error - return the old errno. */
2090 errno = saved_errno;
2093 result = chmod(smb_fname->base_name, mode);
2094 END_PROFILE(syscall_chmod);
2095 return result;
2098 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2100 int result;
2102 START_PROFILE(syscall_fchmod);
2105 * We need to do this due to the fact that the default POSIX ACL
2106 * chmod modifies the ACL *mask* for the group owner, not the
2107 * group owner bits directly. JRA.
2111 int saved_errno = errno; /* We might get ENOSYS */
2112 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2113 END_PROFILE(syscall_fchmod);
2114 return result;
2116 /* Error - return the old errno. */
2117 errno = saved_errno;
2120 #if defined(HAVE_FCHMOD)
2121 result = fchmod(fsp->fh->fd, mode);
2122 #else
2123 result = -1;
2124 errno = ENOSYS;
2125 #endif
2127 END_PROFILE(syscall_fchmod);
2128 return result;
2131 static int vfswrap_chown(vfs_handle_struct *handle,
2132 const struct smb_filename *smb_fname,
2133 uid_t uid,
2134 gid_t gid)
2136 int result;
2138 START_PROFILE(syscall_chown);
2139 result = chown(smb_fname->base_name, uid, gid);
2140 END_PROFILE(syscall_chown);
2141 return result;
2144 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2146 #ifdef HAVE_FCHOWN
2147 int result;
2149 START_PROFILE(syscall_fchown);
2150 result = fchown(fsp->fh->fd, uid, gid);
2151 END_PROFILE(syscall_fchown);
2152 return result;
2153 #else
2154 errno = ENOSYS;
2155 return -1;
2156 #endif
2159 static int vfswrap_lchown(vfs_handle_struct *handle,
2160 const struct smb_filename *smb_fname,
2161 uid_t uid,
2162 gid_t gid)
2164 int result;
2166 START_PROFILE(syscall_lchown);
2167 result = lchown(smb_fname->base_name, uid, gid);
2168 END_PROFILE(syscall_lchown);
2169 return result;
2172 static int vfswrap_chdir(vfs_handle_struct *handle,
2173 const struct smb_filename *smb_fname)
2175 int result;
2177 START_PROFILE(syscall_chdir);
2178 result = chdir(smb_fname->base_name);
2179 END_PROFILE(syscall_chdir);
2180 return result;
2183 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2184 TALLOC_CTX *ctx)
2186 char *result;
2187 struct smb_filename *smb_fname = NULL;
2189 START_PROFILE(syscall_getwd);
2190 result = sys_getwd();
2191 END_PROFILE(syscall_getwd);
2193 if (result == NULL) {
2194 return NULL;
2196 smb_fname = synthetic_smb_fname(ctx,
2197 result,
2198 NULL,
2199 NULL,
2202 * sys_getwd() *always* returns malloced memory.
2203 * We must free here to avoid leaks:
2204 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2206 SAFE_FREE(result);
2207 return smb_fname;
2210 /*********************************************************************
2211 nsec timestamp resolution call. Convert down to whatever the underlying
2212 system will support.
2213 **********************************************************************/
2215 static int vfswrap_ntimes(vfs_handle_struct *handle,
2216 const struct smb_filename *smb_fname,
2217 struct smb_file_time *ft)
2219 int result = -1;
2221 START_PROFILE(syscall_ntimes);
2223 if (smb_fname->stream_name) {
2224 errno = ENOENT;
2225 goto out;
2228 if (ft != NULL) {
2229 if (null_timespec(ft->atime)) {
2230 ft->atime= smb_fname->st.st_ex_atime;
2233 if (null_timespec(ft->mtime)) {
2234 ft->mtime = smb_fname->st.st_ex_mtime;
2237 if (!null_timespec(ft->create_time)) {
2238 set_create_timespec_ea(handle->conn,
2239 smb_fname,
2240 ft->create_time);
2243 if ((timespec_compare(&ft->atime,
2244 &smb_fname->st.st_ex_atime) == 0) &&
2245 (timespec_compare(&ft->mtime,
2246 &smb_fname->st.st_ex_mtime) == 0)) {
2247 return 0;
2251 #if defined(HAVE_UTIMENSAT)
2252 if (ft != NULL) {
2253 struct timespec ts[2];
2254 ts[0] = ft->atime;
2255 ts[1] = ft->mtime;
2256 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2257 } else {
2258 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2260 if (!((result == -1) && (errno == ENOSYS))) {
2261 goto out;
2263 #endif
2264 #if defined(HAVE_UTIMES)
2265 if (ft != NULL) {
2266 struct timeval tv[2];
2267 tv[0] = convert_timespec_to_timeval(ft->atime);
2268 tv[1] = convert_timespec_to_timeval(ft->mtime);
2269 result = utimes(smb_fname->base_name, tv);
2270 } else {
2271 result = utimes(smb_fname->base_name, NULL);
2273 if (!((result == -1) && (errno == ENOSYS))) {
2274 goto out;
2276 #endif
2277 #if defined(HAVE_UTIME)
2278 if (ft != NULL) {
2279 struct utimbuf times;
2280 times.actime = convert_timespec_to_time_t(ft->atime);
2281 times.modtime = convert_timespec_to_time_t(ft->mtime);
2282 result = utime(smb_fname->base_name, &times);
2283 } else {
2284 result = utime(smb_fname->base_name, NULL);
2286 if (!((result == -1) && (errno == ENOSYS))) {
2287 goto out;
2289 #endif
2290 errno = ENOSYS;
2291 result = -1;
2293 out:
2294 END_PROFILE(syscall_ntimes);
2295 return result;
2298 /*********************************************************************
2299 A version of ftruncate that will write the space on disk if strict
2300 allocate is set.
2301 **********************************************************************/
2303 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2305 off_t space_to_write;
2306 uint64_t space_avail;
2307 uint64_t bsize,dfree,dsize;
2308 int ret;
2309 NTSTATUS status;
2310 SMB_STRUCT_STAT *pst;
2312 status = vfs_stat_fsp(fsp);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 return -1;
2316 pst = &fsp->fsp_name->st;
2318 #ifdef S_ISFIFO
2319 if (S_ISFIFO(pst->st_ex_mode))
2320 return 0;
2321 #endif
2323 if (pst->st_ex_size == len)
2324 return 0;
2326 /* Shrink - just ftruncate. */
2327 if (pst->st_ex_size > len)
2328 return ftruncate(fsp->fh->fd, len);
2330 space_to_write = len - pst->st_ex_size;
2332 /* for allocation try fallocate first. This can fail on some
2333 platforms e.g. when the filesystem doesn't support it and no
2334 emulation is being done by the libc (like on AIX with JFS1). In that
2335 case we do our own emulation. fallocate implementations can
2336 return ENOTSUP or EINVAL in cases like that. */
2337 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2338 if (ret == -1 && errno == ENOSPC) {
2339 return -1;
2341 if (ret == 0) {
2342 return 0;
2344 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2345 "error %d. Falling back to slow manual allocation\n", errno));
2347 /* available disk space is enough or not? */
2348 space_avail =
2349 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2350 /* space_avail is 1k blocks */
2351 if (space_avail == (uint64_t)-1 ||
2352 ((uint64_t)space_to_write/1024 > space_avail) ) {
2353 errno = ENOSPC;
2354 return -1;
2357 /* Write out the real space on disk. */
2358 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2359 if (ret != 0) {
2360 return -1;
2363 return 0;
2366 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2368 int result = -1;
2369 SMB_STRUCT_STAT *pst;
2370 NTSTATUS status;
2371 char c = 0;
2373 START_PROFILE(syscall_ftruncate);
2375 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2376 result = strict_allocate_ftruncate(handle, fsp, len);
2377 END_PROFILE(syscall_ftruncate);
2378 return result;
2381 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2382 ftruncate if the system supports it. Then I discovered that
2383 you can have some filesystems that support ftruncate
2384 expansion and some that don't! On Linux fat can't do
2385 ftruncate extend but ext2 can. */
2387 result = ftruncate(fsp->fh->fd, len);
2389 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2390 extend a file with ftruncate. Provide alternate implementation
2391 for this */
2393 /* Do an fstat to see if the file is longer than the requested
2394 size in which case the ftruncate above should have
2395 succeeded or shorter, in which case seek to len - 1 and
2396 write 1 byte of zero */
2397 status = vfs_stat_fsp(fsp);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 goto done;
2402 /* We need to update the files_struct after successful ftruncate */
2403 if (result == 0) {
2404 goto done;
2407 pst = &fsp->fsp_name->st;
2409 #ifdef S_ISFIFO
2410 if (S_ISFIFO(pst->st_ex_mode)) {
2411 result = 0;
2412 goto done;
2414 #endif
2416 if (pst->st_ex_size == len) {
2417 result = 0;
2418 goto done;
2421 if (pst->st_ex_size > len) {
2422 /* the ftruncate should have worked */
2423 goto done;
2426 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2427 goto done;
2430 result = 0;
2432 done:
2434 END_PROFILE(syscall_ftruncate);
2435 return result;
2438 static int vfswrap_fallocate(vfs_handle_struct *handle,
2439 files_struct *fsp,
2440 uint32_t mode,
2441 off_t offset,
2442 off_t len)
2444 int result;
2446 START_PROFILE(syscall_fallocate);
2447 if (mode == 0) {
2448 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2450 * posix_fallocate returns 0 on success, errno on error
2451 * and doesn't set errno. Make it behave like fallocate()
2452 * which returns -1, and sets errno on failure.
2454 if (result != 0) {
2455 errno = result;
2456 result = -1;
2458 } else {
2459 /* sys_fallocate handles filtering of unsupported mode flags */
2460 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2462 END_PROFILE(syscall_fallocate);
2463 return result;
2466 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2468 bool result;
2470 START_PROFILE(syscall_fcntl_lock);
2472 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2473 "smbd",
2474 "force process locks",
2475 false)) {
2476 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2479 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2480 END_PROFILE(syscall_fcntl_lock);
2481 return result;
2484 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2485 uint32_t share_mode, uint32_t access_mask)
2487 START_PROFILE(syscall_kernel_flock);
2488 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2489 END_PROFILE(syscall_kernel_flock);
2490 return 0;
2493 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2495 bool result;
2496 int op = F_GETLK;
2498 START_PROFILE(syscall_fcntl_getlock);
2500 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2501 "smbd",
2502 "force process locks",
2503 false)) {
2504 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2507 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2508 END_PROFILE(syscall_fcntl_getlock);
2509 return result;
2512 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2513 int leasetype)
2515 int result = -1;
2517 START_PROFILE(syscall_linux_setlease);
2519 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2520 result = linux_setlease(fsp->fh->fd, leasetype);
2521 #else
2522 errno = ENOSYS;
2523 #endif
2524 END_PROFILE(syscall_linux_setlease);
2525 return result;
2528 static int vfswrap_symlink(vfs_handle_struct *handle,
2529 const char *link_target,
2530 const struct smb_filename *new_smb_fname)
2532 int result;
2534 START_PROFILE(syscall_symlink);
2535 result = symlink(link_target, new_smb_fname->base_name);
2536 END_PROFILE(syscall_symlink);
2537 return result;
2540 static int vfswrap_readlink(vfs_handle_struct *handle,
2541 const struct smb_filename *smb_fname,
2542 char *buf,
2543 size_t bufsiz)
2545 int result;
2547 START_PROFILE(syscall_readlink);
2548 result = readlink(smb_fname->base_name, buf, bufsiz);
2549 END_PROFILE(syscall_readlink);
2550 return result;
2553 static int vfswrap_link(vfs_handle_struct *handle,
2554 const struct smb_filename *old_smb_fname,
2555 const struct smb_filename *new_smb_fname)
2557 int result;
2559 START_PROFILE(syscall_link);
2560 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2561 END_PROFILE(syscall_link);
2562 return result;
2565 static int vfswrap_mknod(vfs_handle_struct *handle,
2566 const struct smb_filename *smb_fname,
2567 mode_t mode,
2568 SMB_DEV_T dev)
2570 int result;
2572 START_PROFILE(syscall_mknod);
2573 result = sys_mknod(smb_fname->base_name, mode, dev);
2574 END_PROFILE(syscall_mknod);
2575 return result;
2578 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2579 TALLOC_CTX *ctx,
2580 const struct smb_filename *smb_fname)
2582 char *result;
2583 struct smb_filename *result_fname = NULL;
2585 START_PROFILE(syscall_realpath);
2586 result = sys_realpath(smb_fname->base_name);
2587 END_PROFILE(syscall_realpath);
2588 if (result) {
2589 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2590 SAFE_FREE(result);
2592 return result_fname;
2595 static int vfswrap_chflags(vfs_handle_struct *handle,
2596 const struct smb_filename *smb_fname,
2597 unsigned int flags)
2599 #ifdef HAVE_CHFLAGS
2600 return chflags(smb_fname->base_name, flags);
2601 #else
2602 errno = ENOSYS;
2603 return -1;
2604 #endif
2607 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2608 const SMB_STRUCT_STAT *sbuf)
2610 struct file_id key;
2612 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2613 * blob */
2614 ZERO_STRUCT(key);
2616 key.devid = sbuf->st_ex_dev;
2617 key.inode = sbuf->st_ex_ino;
2618 /* key.extid is unused by default. */
2620 return key;
2623 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2624 struct files_struct *fsp,
2625 const struct smb_filename *smb_fname,
2626 TALLOC_CTX *mem_ctx,
2627 unsigned int *pnum_streams,
2628 struct stream_struct **pstreams)
2630 SMB_STRUCT_STAT sbuf;
2631 struct stream_struct *tmp_streams = NULL;
2632 int ret;
2634 if ((fsp != NULL) && (fsp->is_directory)) {
2636 * No default streams on directories
2638 goto done;
2641 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2642 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2644 else {
2645 struct smb_filename smb_fname_cp;
2647 ZERO_STRUCT(smb_fname_cp);
2648 smb_fname_cp.base_name = discard_const_p(char,
2649 smb_fname->base_name);
2650 smb_fname_cp.flags = smb_fname->flags;
2652 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2653 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2654 } else {
2655 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2657 sbuf = smb_fname_cp.st;
2660 if (ret == -1) {
2661 return map_nt_error_from_unix(errno);
2664 if (S_ISDIR(sbuf.st_ex_mode)) {
2665 goto done;
2668 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2669 (*pnum_streams) + 1);
2670 if (tmp_streams == NULL) {
2671 return NT_STATUS_NO_MEMORY;
2673 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2674 if (tmp_streams[*pnum_streams].name == NULL) {
2675 return NT_STATUS_NO_MEMORY;
2677 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2678 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2680 *pnum_streams += 1;
2681 *pstreams = tmp_streams;
2682 done:
2683 return NT_STATUS_OK;
2686 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2687 const char *path,
2688 const char *name,
2689 TALLOC_CTX *mem_ctx,
2690 char **found_name)
2693 * Don't fall back to get_real_filename so callers can differentiate
2694 * between a full directory scan and an actual case-insensitive stat.
2696 errno = EOPNOTSUPP;
2697 return -1;
2700 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2701 const struct smb_filename *smb_fname)
2703 return handle->conn->connectpath;
2706 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2707 struct byte_range_lock *br_lck,
2708 struct lock_struct *plock,
2709 bool blocking_lock)
2711 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2713 /* Note: blr is not used in the default implementation. */
2714 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2717 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2718 struct messaging_context *msg_ctx,
2719 struct byte_range_lock *br_lck,
2720 const struct lock_struct *plock)
2722 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2724 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2727 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2728 struct byte_range_lock *br_lck,
2729 struct lock_struct *plock)
2731 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2733 /* Note: blr is not used in the default implementation. */
2734 return brl_lock_cancel_default(br_lck, plock);
2737 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2738 files_struct *fsp,
2739 struct lock_struct *plock)
2741 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2742 plock->lock_type == WRITE_LOCK);
2744 return strict_lock_check_default(fsp, plock);
2747 /* NT ACL operations. */
2749 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2750 files_struct *fsp,
2751 uint32_t security_info,
2752 TALLOC_CTX *mem_ctx,
2753 struct security_descriptor **ppdesc)
2755 NTSTATUS result;
2757 START_PROFILE(fget_nt_acl);
2758 result = posix_fget_nt_acl(fsp, security_info,
2759 mem_ctx, ppdesc);
2760 END_PROFILE(fget_nt_acl);
2761 return result;
2764 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2765 const struct smb_filename *smb_fname,
2766 uint32_t security_info,
2767 TALLOC_CTX *mem_ctx,
2768 struct security_descriptor **ppdesc)
2770 NTSTATUS result;
2772 START_PROFILE(get_nt_acl);
2773 result = posix_get_nt_acl(handle->conn,
2774 smb_fname,
2775 security_info,
2776 mem_ctx,
2777 ppdesc);
2778 END_PROFILE(get_nt_acl);
2779 return result;
2782 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2784 NTSTATUS result;
2786 START_PROFILE(fset_nt_acl);
2787 result = set_nt_acl(fsp, security_info_sent, psd);
2788 END_PROFILE(fset_nt_acl);
2789 return result;
2792 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2793 struct smb_filename *file,
2794 struct security_acl *sacl,
2795 uint32_t access_requested,
2796 uint32_t access_denied)
2798 return NT_STATUS_OK; /* Nothing to do here ... */
2801 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2802 const struct smb_filename *smb_fname,
2803 mode_t mode)
2805 #ifdef HAVE_NO_ACL
2806 errno = ENOSYS;
2807 return -1;
2808 #else
2809 int result;
2811 START_PROFILE(chmod_acl);
2812 result = chmod_acl(handle->conn, smb_fname, mode);
2813 END_PROFILE(chmod_acl);
2814 return result;
2815 #endif
2818 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2820 #ifdef HAVE_NO_ACL
2821 errno = ENOSYS;
2822 return -1;
2823 #else
2824 int result;
2826 START_PROFILE(fchmod_acl);
2827 result = fchmod_acl(fsp, mode);
2828 END_PROFILE(fchmod_acl);
2829 return result;
2830 #endif
2833 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2834 const struct smb_filename *smb_fname,
2835 SMB_ACL_TYPE_T type,
2836 TALLOC_CTX *mem_ctx)
2838 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2841 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2842 files_struct *fsp,
2843 TALLOC_CTX *mem_ctx)
2845 return sys_acl_get_fd(handle, fsp, mem_ctx);
2848 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2849 const struct smb_filename *smb_fname,
2850 SMB_ACL_TYPE_T acltype,
2851 SMB_ACL_T theacl)
2853 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2856 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2858 return sys_acl_set_fd(handle, fsp, theacl);
2861 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2862 const struct smb_filename *smb_fname)
2864 return sys_acl_delete_def_file(handle, smb_fname);
2867 /****************************************************************
2868 Extended attribute operations.
2869 *****************************************************************/
2871 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2872 const struct smb_filename *smb_fname,
2873 const char *name,
2874 void *value,
2875 size_t size)
2877 return getxattr(smb_fname->base_name, name, value, size);
2880 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2882 return fgetxattr(fsp->fh->fd, name, value, size);
2885 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2886 const struct smb_filename *smb_fname,
2887 char *list,
2888 size_t size)
2890 return listxattr(smb_fname->base_name, list, size);
2893 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2895 return flistxattr(fsp->fh->fd, list, size);
2898 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2899 const struct smb_filename *smb_fname,
2900 const char *name)
2902 return removexattr(smb_fname->base_name, name);
2905 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2907 return fremovexattr(fsp->fh->fd, name);
2910 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2911 const struct smb_filename *smb_fname,
2912 const char *name,
2913 const void *value,
2914 size_t size,
2915 int flags)
2917 return setxattr(smb_fname->base_name, name, value, size, flags);
2920 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2922 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2925 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2927 return false;
2930 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2931 const struct smb_filename *fname,
2932 SMB_STRUCT_STAT *sbuf)
2934 NTSTATUS status;
2935 char *path;
2936 bool offline = false;
2938 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2939 return false;
2942 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2943 #if defined(ENOTSUP)
2944 errno = ENOTSUP;
2945 #endif
2946 return false;
2949 status = get_full_smb_filename(talloc_tos(), fname, &path);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 errno = map_errno_from_nt_status(status);
2952 return false;
2955 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2957 TALLOC_FREE(path);
2959 return offline;
2962 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2963 struct files_struct *fsp,
2964 TALLOC_CTX *mem_ctx,
2965 DATA_BLOB *cookie)
2967 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2970 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2971 struct files_struct *fsp,
2972 const DATA_BLOB old_cookie,
2973 TALLOC_CTX *mem_ctx,
2974 DATA_BLOB *new_cookie)
2976 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2977 new_cookie);
2980 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2981 struct smb_request *smb1req,
2982 struct smbXsrv_open *op,
2983 const DATA_BLOB old_cookie,
2984 TALLOC_CTX *mem_ctx,
2985 struct files_struct **fsp,
2986 DATA_BLOB *new_cookie)
2988 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2989 old_cookie, mem_ctx,
2990 fsp, new_cookie);
2993 static struct vfs_fn_pointers vfs_default_fns = {
2994 /* Disk operations */
2996 .connect_fn = vfswrap_connect,
2997 .disconnect_fn = vfswrap_disconnect,
2998 .disk_free_fn = vfswrap_disk_free,
2999 .get_quota_fn = vfswrap_get_quota,
3000 .set_quota_fn = vfswrap_set_quota,
3001 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3002 .statvfs_fn = vfswrap_statvfs,
3003 .fs_capabilities_fn = vfswrap_fs_capabilities,
3004 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3005 .snap_check_path_fn = vfswrap_snap_check_path,
3006 .snap_create_fn = vfswrap_snap_create,
3007 .snap_delete_fn = vfswrap_snap_delete,
3009 /* Directory operations */
3011 .opendir_fn = vfswrap_opendir,
3012 .fdopendir_fn = vfswrap_fdopendir,
3013 .readdir_fn = vfswrap_readdir,
3014 .readdir_attr_fn = vfswrap_readdir_attr,
3015 .seekdir_fn = vfswrap_seekdir,
3016 .telldir_fn = vfswrap_telldir,
3017 .rewind_dir_fn = vfswrap_rewinddir,
3018 .mkdir_fn = vfswrap_mkdir,
3019 .rmdir_fn = vfswrap_rmdir,
3020 .closedir_fn = vfswrap_closedir,
3022 /* File operations */
3024 .open_fn = vfswrap_open,
3025 .create_file_fn = vfswrap_create_file,
3026 .close_fn = vfswrap_close,
3027 .read_fn = vfswrap_read,
3028 .pread_fn = vfswrap_pread,
3029 .pread_send_fn = vfswrap_pread_send,
3030 .pread_recv_fn = vfswrap_pread_recv,
3031 .write_fn = vfswrap_write,
3032 .pwrite_fn = vfswrap_pwrite,
3033 .pwrite_send_fn = vfswrap_pwrite_send,
3034 .pwrite_recv_fn = vfswrap_pwrite_recv,
3035 .lseek_fn = vfswrap_lseek,
3036 .sendfile_fn = vfswrap_sendfile,
3037 .recvfile_fn = vfswrap_recvfile,
3038 .rename_fn = vfswrap_rename,
3039 .fsync_fn = vfswrap_fsync,
3040 .fsync_send_fn = vfswrap_fsync_send,
3041 .fsync_recv_fn = vfswrap_fsync_recv,
3042 .stat_fn = vfswrap_stat,
3043 .fstat_fn = vfswrap_fstat,
3044 .lstat_fn = vfswrap_lstat,
3045 .get_alloc_size_fn = vfswrap_get_alloc_size,
3046 .unlink_fn = vfswrap_unlink,
3047 .chmod_fn = vfswrap_chmod,
3048 .fchmod_fn = vfswrap_fchmod,
3049 .chown_fn = vfswrap_chown,
3050 .fchown_fn = vfswrap_fchown,
3051 .lchown_fn = vfswrap_lchown,
3052 .chdir_fn = vfswrap_chdir,
3053 .getwd_fn = vfswrap_getwd,
3054 .ntimes_fn = vfswrap_ntimes,
3055 .ftruncate_fn = vfswrap_ftruncate,
3056 .fallocate_fn = vfswrap_fallocate,
3057 .lock_fn = vfswrap_lock,
3058 .kernel_flock_fn = vfswrap_kernel_flock,
3059 .linux_setlease_fn = vfswrap_linux_setlease,
3060 .getlock_fn = vfswrap_getlock,
3061 .symlink_fn = vfswrap_symlink,
3062 .readlink_fn = vfswrap_readlink,
3063 .link_fn = vfswrap_link,
3064 .mknod_fn = vfswrap_mknod,
3065 .realpath_fn = vfswrap_realpath,
3066 .chflags_fn = vfswrap_chflags,
3067 .file_id_create_fn = vfswrap_file_id_create,
3068 .streaminfo_fn = vfswrap_streaminfo,
3069 .get_real_filename_fn = vfswrap_get_real_filename,
3070 .connectpath_fn = vfswrap_connectpath,
3071 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3072 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3073 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3074 .strict_lock_check_fn = vfswrap_strict_lock_check,
3075 .translate_name_fn = vfswrap_translate_name,
3076 .fsctl_fn = vfswrap_fsctl,
3077 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3078 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3079 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3080 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3081 .offload_read_send_fn = vfswrap_offload_read_send,
3082 .offload_read_recv_fn = vfswrap_offload_read_recv,
3083 .offload_write_send_fn = vfswrap_offload_write_send,
3084 .offload_write_recv_fn = vfswrap_offload_write_recv,
3085 .get_compression_fn = vfswrap_get_compression,
3086 .set_compression_fn = vfswrap_set_compression,
3088 /* NT ACL operations. */
3090 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3091 .get_nt_acl_fn = vfswrap_get_nt_acl,
3092 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3093 .audit_file_fn = vfswrap_audit_file,
3095 /* POSIX ACL operations. */
3097 .chmod_acl_fn = vfswrap_chmod_acl,
3098 .fchmod_acl_fn = vfswrap_fchmod_acl,
3100 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3101 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3102 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3103 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3104 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3105 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3106 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3108 /* EA operations. */
3109 .getxattr_fn = vfswrap_getxattr,
3110 .fgetxattr_fn = vfswrap_fgetxattr,
3111 .listxattr_fn = vfswrap_listxattr,
3112 .flistxattr_fn = vfswrap_flistxattr,
3113 .removexattr_fn = vfswrap_removexattr,
3114 .fremovexattr_fn = vfswrap_fremovexattr,
3115 .setxattr_fn = vfswrap_setxattr,
3116 .fsetxattr_fn = vfswrap_fsetxattr,
3118 /* aio operations */
3119 .aio_force_fn = vfswrap_aio_force,
3121 /* durable handle operations */
3122 .durable_cookie_fn = vfswrap_durable_cookie,
3123 .durable_disconnect_fn = vfswrap_durable_disconnect,
3124 .durable_reconnect_fn = vfswrap_durable_reconnect,
3127 static_decl_vfs;
3128 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3130 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3131 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);