s3: smbd: vfs_fruit: Replace code in fruit_fget_nt_acl() with remove_virtual_nfs_aces().
[Samba.git] / source3 / modules / vfs_default.c
bloba26bec457ae59dadc5dc82c316eb6b4106781526
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 static int vfswrap_init_pool(struct smbd_server_connection *conn)
722 int ret;
724 if (conn->pool != NULL) {
725 return 0;
728 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
729 &conn->pool);
730 return ret;
733 struct vfswrap_pread_state {
734 ssize_t ret;
735 int fd;
736 void *buf;
737 size_t count;
738 off_t offset;
740 struct vfs_aio_state vfs_aio_state;
741 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
744 static void vfs_pread_do(void *private_data);
745 static void vfs_pread_done(struct tevent_req *subreq);
746 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
748 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
749 TALLOC_CTX *mem_ctx,
750 struct tevent_context *ev,
751 struct files_struct *fsp,
752 void *data,
753 size_t n, off_t offset)
755 struct tevent_req *req, *subreq;
756 struct vfswrap_pread_state *state;
757 int ret;
759 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
760 if (req == NULL) {
761 return NULL;
764 ret = vfswrap_init_pool(handle->conn->sconn);
765 if (tevent_req_error(req, ret)) {
766 return tevent_req_post(req, ev);
769 state->ret = -1;
770 state->fd = fsp->fh->fd;
771 state->buf = data;
772 state->count = n;
773 state->offset = offset;
775 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
776 state->profile_bytes, n);
777 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
779 subreq = pthreadpool_tevent_job_send(
780 state, ev, handle->conn->sconn->pool,
781 vfs_pread_do, state);
782 if (tevent_req_nomem(subreq, req)) {
783 return tevent_req_post(req, ev);
785 tevent_req_set_callback(subreq, vfs_pread_done, req);
787 talloc_set_destructor(state, vfs_pread_state_destructor);
789 return req;
792 static void vfs_pread_do(void *private_data)
794 struct vfswrap_pread_state *state = talloc_get_type_abort(
795 private_data, struct vfswrap_pread_state);
796 struct timespec start_time;
797 struct timespec end_time;
799 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
801 PROFILE_TIMESTAMP(&start_time);
803 do {
804 state->ret = pread(state->fd, state->buf, state->count,
805 state->offset);
806 } while ((state->ret == -1) && (errno == EINTR));
808 if (state->ret == -1) {
809 state->vfs_aio_state.error = errno;
812 PROFILE_TIMESTAMP(&end_time);
814 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
816 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
819 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
821 return -1;
824 static void vfs_pread_done(struct tevent_req *subreq)
826 struct tevent_req *req = tevent_req_callback_data(
827 subreq, struct tevent_req);
828 struct vfswrap_pread_state *state = tevent_req_data(
829 req, struct vfswrap_pread_state);
830 int ret;
832 ret = pthreadpool_tevent_job_recv(subreq);
833 TALLOC_FREE(subreq);
834 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
835 talloc_set_destructor(state, NULL);
836 if (tevent_req_error(req, ret)) {
837 return;
840 tevent_req_done(req);
843 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
844 struct vfs_aio_state *vfs_aio_state)
846 struct vfswrap_pread_state *state = tevent_req_data(
847 req, struct vfswrap_pread_state);
849 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
850 return -1;
853 *vfs_aio_state = state->vfs_aio_state;
854 return state->ret;
857 struct vfswrap_pwrite_state {
858 ssize_t ret;
859 int fd;
860 const void *buf;
861 size_t count;
862 off_t offset;
864 struct vfs_aio_state vfs_aio_state;
865 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
868 static void vfs_pwrite_do(void *private_data);
869 static void vfs_pwrite_done(struct tevent_req *subreq);
870 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
872 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
873 TALLOC_CTX *mem_ctx,
874 struct tevent_context *ev,
875 struct files_struct *fsp,
876 const void *data,
877 size_t n, off_t offset)
879 struct tevent_req *req, *subreq;
880 struct vfswrap_pwrite_state *state;
881 int ret;
883 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
884 if (req == NULL) {
885 return NULL;
888 ret = vfswrap_init_pool(handle->conn->sconn);
889 if (tevent_req_error(req, ret)) {
890 return tevent_req_post(req, ev);
893 state->ret = -1;
894 state->fd = fsp->fh->fd;
895 state->buf = data;
896 state->count = n;
897 state->offset = offset;
899 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
900 state->profile_bytes, n);
901 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
903 subreq = pthreadpool_tevent_job_send(
904 state, ev, handle->conn->sconn->pool,
905 vfs_pwrite_do, state);
906 if (tevent_req_nomem(subreq, req)) {
907 return tevent_req_post(req, ev);
909 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
911 talloc_set_destructor(state, vfs_pwrite_state_destructor);
913 return req;
916 static void vfs_pwrite_do(void *private_data)
918 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
919 private_data, struct vfswrap_pwrite_state);
920 struct timespec start_time;
921 struct timespec end_time;
923 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
925 PROFILE_TIMESTAMP(&start_time);
927 do {
928 state->ret = pwrite(state->fd, state->buf, state->count,
929 state->offset);
930 } while ((state->ret == -1) && (errno == EINTR));
932 if (state->ret == -1) {
933 state->vfs_aio_state.error = errno;
936 PROFILE_TIMESTAMP(&end_time);
938 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
940 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
943 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
945 return -1;
948 static void vfs_pwrite_done(struct tevent_req *subreq)
950 struct tevent_req *req = tevent_req_callback_data(
951 subreq, struct tevent_req);
952 struct vfswrap_pwrite_state *state = tevent_req_data(
953 req, struct vfswrap_pwrite_state);
954 int ret;
956 ret = pthreadpool_tevent_job_recv(subreq);
957 TALLOC_FREE(subreq);
958 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
959 talloc_set_destructor(state, NULL);
960 if (tevent_req_error(req, ret)) {
961 return;
964 tevent_req_done(req);
967 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
968 struct vfs_aio_state *vfs_aio_state)
970 struct vfswrap_pwrite_state *state = tevent_req_data(
971 req, struct vfswrap_pwrite_state);
973 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
974 return -1;
977 *vfs_aio_state = state->vfs_aio_state;
978 return state->ret;
981 struct vfswrap_fsync_state {
982 ssize_t ret;
983 int fd;
985 struct vfs_aio_state vfs_aio_state;
986 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
989 static void vfs_fsync_do(void *private_data);
990 static void vfs_fsync_done(struct tevent_req *subreq);
991 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
993 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
994 TALLOC_CTX *mem_ctx,
995 struct tevent_context *ev,
996 struct files_struct *fsp)
998 struct tevent_req *req, *subreq;
999 struct vfswrap_fsync_state *state;
1000 int ret;
1002 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1003 if (req == NULL) {
1004 return NULL;
1007 ret = vfswrap_init_pool(handle->conn->sconn);
1008 if (tevent_req_error(req, ret)) {
1009 return tevent_req_post(req, ev);
1012 state->ret = -1;
1013 state->fd = fsp->fh->fd;
1015 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1016 state->profile_basic);
1018 subreq = pthreadpool_tevent_job_send(
1019 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1020 if (tevent_req_nomem(subreq, req)) {
1021 return tevent_req_post(req, ev);
1023 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1025 talloc_set_destructor(state, vfs_fsync_state_destructor);
1027 return req;
1030 static void vfs_fsync_do(void *private_data)
1032 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1033 private_data, struct vfswrap_fsync_state);
1034 struct timespec start_time;
1035 struct timespec end_time;
1037 PROFILE_TIMESTAMP(&start_time);
1039 do {
1040 state->ret = fsync(state->fd);
1041 } while ((state->ret == -1) && (errno == EINTR));
1043 if (state->ret == -1) {
1044 state->vfs_aio_state.error = errno;
1047 PROFILE_TIMESTAMP(&end_time);
1049 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1052 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1054 return -1;
1057 static void vfs_fsync_done(struct tevent_req *subreq)
1059 struct tevent_req *req = tevent_req_callback_data(
1060 subreq, struct tevent_req);
1061 struct vfswrap_fsync_state *state = tevent_req_data(
1062 req, struct vfswrap_fsync_state);
1063 int ret;
1065 ret = pthreadpool_tevent_job_recv(subreq);
1066 TALLOC_FREE(subreq);
1067 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1068 talloc_set_destructor(state, NULL);
1069 if (tevent_req_error(req, ret)) {
1070 return;
1073 tevent_req_done(req);
1076 static int vfswrap_fsync_recv(struct tevent_req *req,
1077 struct vfs_aio_state *vfs_aio_state)
1079 struct vfswrap_fsync_state *state = tevent_req_data(
1080 req, struct vfswrap_fsync_state);
1082 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1083 return -1;
1086 *vfs_aio_state = state->vfs_aio_state;
1087 return state->ret;
1090 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1092 off_t result = 0;
1094 START_PROFILE(syscall_lseek);
1096 /* Cope with 'stat' file opens. */
1097 if (fsp->fh->fd != -1)
1098 result = lseek(fsp->fh->fd, offset, whence);
1101 * We want to maintain the fiction that we can seek
1102 * on a fifo for file system purposes. This allows
1103 * people to set up UNIX fifo's that feed data to Windows
1104 * applications. JRA.
1107 if((result == -1) && (errno == ESPIPE)) {
1108 result = 0;
1109 errno = 0;
1112 END_PROFILE(syscall_lseek);
1113 return result;
1116 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1117 off_t offset, size_t n)
1119 ssize_t result;
1121 START_PROFILE_BYTES(syscall_sendfile, n);
1122 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1123 END_PROFILE_BYTES(syscall_sendfile);
1124 return result;
1127 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1128 int fromfd,
1129 files_struct *tofsp,
1130 off_t offset,
1131 size_t n)
1133 ssize_t result;
1135 START_PROFILE_BYTES(syscall_recvfile, n);
1136 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1137 END_PROFILE_BYTES(syscall_recvfile);
1138 return result;
1141 static int vfswrap_rename(vfs_handle_struct *handle,
1142 const struct smb_filename *smb_fname_src,
1143 const struct smb_filename *smb_fname_dst)
1145 int result = -1;
1147 START_PROFILE(syscall_rename);
1149 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1150 errno = ENOENT;
1151 goto out;
1154 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1156 out:
1157 END_PROFILE(syscall_rename);
1158 return result;
1161 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1163 #ifdef HAVE_FSYNC
1164 int result;
1166 START_PROFILE(syscall_fsync);
1167 result = fsync(fsp->fh->fd);
1168 END_PROFILE(syscall_fsync);
1169 return result;
1170 #else
1171 return 0;
1172 #endif
1175 static int vfswrap_stat(vfs_handle_struct *handle,
1176 struct smb_filename *smb_fname)
1178 int result = -1;
1180 START_PROFILE(syscall_stat);
1182 if (smb_fname->stream_name) {
1183 errno = ENOENT;
1184 goto out;
1187 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1188 lp_fake_directory_create_times(SNUM(handle->conn)));
1189 out:
1190 END_PROFILE(syscall_stat);
1191 return result;
1194 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1196 int result;
1198 START_PROFILE(syscall_fstat);
1199 result = sys_fstat(fsp->fh->fd,
1200 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1201 END_PROFILE(syscall_fstat);
1202 return result;
1205 static int vfswrap_lstat(vfs_handle_struct *handle,
1206 struct smb_filename *smb_fname)
1208 int result = -1;
1210 START_PROFILE(syscall_lstat);
1212 if (smb_fname->stream_name) {
1213 errno = ENOENT;
1214 goto out;
1217 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1218 lp_fake_directory_create_times(SNUM(handle->conn)));
1219 out:
1220 END_PROFILE(syscall_lstat);
1221 return result;
1224 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1225 const char *name,
1226 enum vfs_translate_direction direction,
1227 TALLOC_CTX *mem_ctx,
1228 char **mapped_name)
1230 return NT_STATUS_NONE_MAPPED;
1234 * Implement the default fsctl operation.
1236 static bool vfswrap_logged_ioctl_message = false;
1238 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1239 struct files_struct *fsp,
1240 TALLOC_CTX *ctx,
1241 uint32_t function,
1242 uint16_t req_flags, /* Needed for UNICODE ... */
1243 const uint8_t *_in_data,
1244 uint32_t in_len,
1245 uint8_t **_out_data,
1246 uint32_t max_out_len,
1247 uint32_t *out_len)
1249 const char *in_data = (const char *)_in_data;
1250 char **out_data = (char **)_out_data;
1251 NTSTATUS status;
1253 switch (function) {
1254 case FSCTL_SET_SPARSE:
1256 bool set_sparse = true;
1258 if (in_len >= 1 && in_data[0] == 0) {
1259 set_sparse = false;
1262 status = file_set_sparse(handle->conn, fsp, set_sparse);
1264 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1265 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1266 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1267 nt_errstr(status)));
1269 return status;
1272 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1274 unsigned char objid[16];
1275 char *return_data = NULL;
1277 /* This should return the object-id on this file.
1278 * I think I'll make this be the inode+dev. JRA.
1281 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1282 fsp_fnum_dbg(fsp)));
1284 *out_len = MIN(max_out_len, 64);
1286 /* Hmmm, will this cause problems if less data asked for? */
1287 return_data = talloc_array(ctx, char, 64);
1288 if (return_data == NULL) {
1289 return NT_STATUS_NO_MEMORY;
1292 /* For backwards compatibility only store the dev/inode. */
1293 push_file_id_16(return_data, &fsp->file_id);
1294 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1295 push_file_id_16(return_data+32, &fsp->file_id);
1296 memset(return_data+48, 0, 16);
1297 *out_data = return_data;
1298 return NT_STATUS_OK;
1301 case FSCTL_GET_REPARSE_POINT:
1303 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1304 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1305 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1306 return NT_STATUS_NOT_A_REPARSE_POINT;
1309 case FSCTL_SET_REPARSE_POINT:
1311 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1312 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1313 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1314 return NT_STATUS_NOT_A_REPARSE_POINT;
1317 case FSCTL_GET_SHADOW_COPY_DATA:
1320 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1321 * and return their volume names. If max_data_count is 16, then it is just
1322 * asking for the number of volumes and length of the combined names.
1324 * pdata is the data allocated by our caller, but that uses
1325 * total_data_count (which is 0 in our case) rather than max_data_count.
1326 * Allocate the correct amount and return the pointer to let
1327 * it be deallocated when we return.
1329 struct shadow_copy_data *shadow_data = NULL;
1330 bool labels = False;
1331 uint32_t labels_data_count = 0;
1332 uint32_t i;
1333 char *cur_pdata = NULL;
1335 if (max_out_len < 16) {
1336 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1337 max_out_len));
1338 return NT_STATUS_INVALID_PARAMETER;
1341 if (max_out_len > 16) {
1342 labels = True;
1345 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1346 if (shadow_data == NULL) {
1347 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1348 return NT_STATUS_NO_MEMORY;
1352 * Call the VFS routine to actually do the work.
1354 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1355 int log_lev = 0;
1356 if (errno == 0) {
1357 /* broken module didn't set errno on error */
1358 status = NT_STATUS_UNSUCCESSFUL;
1359 } else {
1360 status = map_nt_error_from_unix(errno);
1361 if (NT_STATUS_EQUAL(status,
1362 NT_STATUS_NOT_SUPPORTED)) {
1363 log_lev = 5;
1366 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1367 "connectpath %s, failed - %s.\n",
1368 fsp->conn->connectpath,
1369 nt_errstr(status)));
1370 TALLOC_FREE(shadow_data);
1371 return status;
1374 labels_data_count = (shadow_data->num_volumes * 2 *
1375 sizeof(SHADOW_COPY_LABEL)) + 2;
1377 if (!labels) {
1378 *out_len = 16;
1379 } else {
1380 *out_len = 12 + labels_data_count;
1383 if (max_out_len < *out_len) {
1384 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1385 max_out_len, *out_len));
1386 TALLOC_FREE(shadow_data);
1387 return NT_STATUS_BUFFER_TOO_SMALL;
1390 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1391 if (cur_pdata == NULL) {
1392 TALLOC_FREE(shadow_data);
1393 return NT_STATUS_NO_MEMORY;
1396 *out_data = cur_pdata;
1398 /* num_volumes 4 bytes */
1399 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1401 if (labels) {
1402 /* num_labels 4 bytes */
1403 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1406 /* needed_data_count 4 bytes */
1407 SIVAL(cur_pdata, 8, labels_data_count);
1409 cur_pdata += 12;
1411 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1412 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1413 if (labels && shadow_data->labels) {
1414 for (i=0; i<shadow_data->num_volumes; i++) {
1415 size_t len = 0;
1416 status = srvstr_push(cur_pdata, req_flags,
1417 cur_pdata, shadow_data->labels[i],
1418 2 * sizeof(SHADOW_COPY_LABEL),
1419 STR_UNICODE|STR_TERMINATE, &len);
1420 if (!NT_STATUS_IS_OK(status)) {
1421 TALLOC_FREE(*out_data);
1422 TALLOC_FREE(shadow_data);
1423 return status;
1425 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1426 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1430 TALLOC_FREE(shadow_data);
1432 return NT_STATUS_OK;
1435 case FSCTL_FIND_FILES_BY_SID:
1437 /* pretend this succeeded -
1439 * we have to send back a list with all files owned by this SID
1441 * but I have to check that --metze
1443 struct dom_sid sid;
1444 uid_t uid;
1445 size_t sid_len;
1447 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1448 fsp_fnum_dbg(fsp)));
1450 if (in_len < 8) {
1451 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1452 return NT_STATUS_INVALID_PARAMETER;
1455 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1457 /* unknown 4 bytes: this is not the length of the sid :-( */
1458 /*unknown = IVAL(pdata,0);*/
1460 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1461 return NT_STATUS_INVALID_PARAMETER;
1463 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1465 if (!sid_to_uid(&sid, &uid)) {
1466 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1467 sid_string_dbg(&sid),
1468 (unsigned long)sid_len));
1469 uid = (-1);
1472 /* we can take a look at the find source :-)
1474 * find ./ -uid $uid -name '*' is what we need here
1477 * and send 4bytes len and then NULL terminated unicode strings
1478 * for each file
1480 * but I don't know how to deal with the paged results
1481 * (maybe we can hang the result anywhere in the fsp struct)
1483 * but I don't know how to deal with the paged results
1484 * (maybe we can hang the result anywhere in the fsp struct)
1486 * we don't send all files at once
1487 * and at the next we should *not* start from the beginning,
1488 * so we have to cache the result
1490 * --metze
1493 /* this works for now... */
1494 return NT_STATUS_OK;
1497 case FSCTL_QUERY_ALLOCATED_RANGES:
1499 /* FIXME: This is just a dummy reply, telling that all of the
1500 * file is allocated. MKS cp needs that.
1501 * Adding the real allocated ranges via FIEMAP on Linux
1502 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1503 * this FSCTL correct for sparse files.
1505 uint64_t offset, length;
1506 char *out_data_tmp = NULL;
1508 if (in_len != 16) {
1509 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1510 in_len));
1511 return NT_STATUS_INVALID_PARAMETER;
1514 if (max_out_len < 16) {
1515 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1516 max_out_len));
1517 return NT_STATUS_INVALID_PARAMETER;
1520 offset = BVAL(in_data,0);
1521 length = BVAL(in_data,8);
1523 if (offset + length < offset) {
1524 /* No 64-bit integer wrap. */
1525 return NT_STATUS_INVALID_PARAMETER;
1528 /* Shouldn't this be SMB_VFS_STAT ... ? */
1529 status = vfs_stat_fsp(fsp);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 return status;
1534 *out_len = 16;
1535 out_data_tmp = talloc_array(ctx, char, *out_len);
1536 if (out_data_tmp == NULL) {
1537 DEBUG(10, ("unable to allocate memory for response\n"));
1538 return NT_STATUS_NO_MEMORY;
1541 if (offset > fsp->fsp_name->st.st_ex_size ||
1542 fsp->fsp_name->st.st_ex_size == 0 ||
1543 length == 0) {
1544 memset(out_data_tmp, 0, *out_len);
1545 } else {
1546 uint64_t end = offset + length;
1547 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1548 SBVAL(out_data_tmp, 0, 0);
1549 SBVAL(out_data_tmp, 8, end);
1552 *out_data = out_data_tmp;
1554 return NT_STATUS_OK;
1557 case FSCTL_IS_VOLUME_DIRTY:
1559 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1560 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1562 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1563 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1565 return NT_STATUS_INVALID_PARAMETER;
1568 default:
1570 * Only print once ... unfortunately there could be lots of
1571 * different FSCTLs that are called.
1573 if (!vfswrap_logged_ioctl_message) {
1574 vfswrap_logged_ioctl_message = true;
1575 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1576 __func__, function));
1580 return NT_STATUS_NOT_SUPPORTED;
1583 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1584 const struct smb_filename *fname,
1585 SMB_STRUCT_STAT *sbuf);
1587 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1588 struct smb_filename *smb_fname,
1589 uint32_t *dosmode)
1591 bool offline;
1593 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1594 if (offline) {
1595 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1598 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1601 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1602 struct files_struct *fsp,
1603 uint32_t *dosmode)
1605 bool offline;
1607 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1608 if (offline) {
1609 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1612 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1615 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1616 const struct smb_filename *smb_fname,
1617 uint32_t dosmode)
1619 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1622 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1623 struct files_struct *fsp,
1624 uint32_t dosmode)
1626 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1629 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1631 struct vfswrap_offload_read_state {
1632 DATA_BLOB token;
1635 static struct tevent_req *vfswrap_offload_read_send(
1636 TALLOC_CTX *mem_ctx,
1637 struct tevent_context *ev,
1638 struct vfs_handle_struct *handle,
1639 struct files_struct *fsp,
1640 uint32_t fsctl,
1641 uint32_t ttl,
1642 off_t offset,
1643 size_t to_copy)
1645 struct tevent_req *req = NULL;
1646 struct vfswrap_offload_read_state *state = NULL;
1647 NTSTATUS status;
1649 req = tevent_req_create(mem_ctx, &state,
1650 struct vfswrap_offload_read_state);
1651 if (req == NULL) {
1652 return NULL;
1655 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1656 &vfswrap_offload_ctx);
1657 if (tevent_req_nterror(req, status)) {
1658 return tevent_req_post(req, ev);
1661 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1662 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1663 return tevent_req_post(req, ev);
1666 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1667 &state->token);
1668 if (tevent_req_nterror(req, status)) {
1669 return tevent_req_post(req, ev);
1672 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1673 &state->token);
1674 if (tevent_req_nterror(req, status)) {
1675 return tevent_req_post(req, ev);
1678 tevent_req_done(req);
1679 return tevent_req_post(req, ev);
1682 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1683 struct vfs_handle_struct *handle,
1684 TALLOC_CTX *mem_ctx,
1685 DATA_BLOB *token)
1687 struct vfswrap_offload_read_state *state = tevent_req_data(
1688 req, struct vfswrap_offload_read_state);
1689 NTSTATUS status;
1691 if (tevent_req_is_nterror(req, &status)) {
1692 tevent_req_received(req);
1693 return status;
1696 token->length = state->token.length;
1697 token->data = talloc_move(mem_ctx, &state->token.data);
1699 tevent_req_received(req);
1700 return NT_STATUS_OK;
1703 struct vfswrap_offload_write_state {
1704 struct tevent_context *ev;
1705 uint8_t *buf;
1706 bool read_lck_locked;
1707 bool write_lck_locked;
1708 DATA_BLOB *token;
1709 struct files_struct *src_fsp;
1710 off_t src_off;
1711 struct files_struct *dst_fsp;
1712 off_t dst_off;
1713 off_t to_copy;
1714 off_t remaining;
1715 size_t next_io_size;
1718 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1720 static struct tevent_req *vfswrap_offload_write_send(
1721 struct vfs_handle_struct *handle,
1722 TALLOC_CTX *mem_ctx,
1723 struct tevent_context *ev,
1724 uint32_t fsctl,
1725 DATA_BLOB *token,
1726 off_t transfer_offset,
1727 struct files_struct *dest_fsp,
1728 off_t dest_off,
1729 off_t to_copy)
1731 struct tevent_req *req;
1732 struct vfswrap_offload_write_state *state = NULL;
1733 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1734 files_struct *src_fsp = NULL;
1735 NTSTATUS status;
1737 req = tevent_req_create(mem_ctx, &state,
1738 struct vfswrap_offload_write_state);
1739 if (req == NULL) {
1740 return NULL;
1743 *state = (struct vfswrap_offload_write_state) {
1744 .ev = ev,
1745 .token = token,
1746 .src_off = transfer_offset,
1747 .dst_fsp = dest_fsp,
1748 .dst_off = dest_off,
1749 .to_copy = to_copy,
1750 .remaining = to_copy,
1753 switch (fsctl) {
1754 case FSCTL_SRV_COPYCHUNK:
1755 case FSCTL_SRV_COPYCHUNK_WRITE:
1756 break;
1758 case FSCTL_OFFLOAD_WRITE:
1759 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1760 return tevent_req_post(req, ev);
1762 case FSCTL_DUP_EXTENTS_TO_FILE:
1763 DBG_DEBUG("COW clones not supported by vfs_default\n");
1764 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1765 return tevent_req_post(req, ev);
1767 default:
1768 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1769 return tevent_req_post(req, ev);
1773 * From here on we assume a copy-chunk fsctl
1776 if (to_copy == 0) {
1777 tevent_req_done(req);
1778 return tevent_req_post(req, ev);
1781 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1782 token, &src_fsp);
1783 if (tevent_req_nterror(req, status)) {
1784 return tevent_req_post(req, ev);
1786 state->src_fsp = src_fsp;
1788 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1790 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1791 if (!NT_STATUS_IS_OK(status)) {
1792 tevent_req_nterror(req, status);
1793 return tevent_req_post(req, ev);
1796 state->buf = talloc_array(state, uint8_t, num);
1797 if (tevent_req_nomem(state->buf, req)) {
1798 return tevent_req_post(req, ev);
1801 status = vfs_stat_fsp(src_fsp);
1802 if (tevent_req_nterror(req, status)) {
1803 return tevent_req_post(req, ev);
1806 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1808 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1809 * If the SourceOffset or SourceOffset + Length extends beyond
1810 * the end of file, the server SHOULD<240> treat this as a
1811 * STATUS_END_OF_FILE error.
1812 * ...
1813 * <240> Section 3.3.5.15.6: Windows servers will return
1814 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1816 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1817 return tevent_req_post(req, ev);
1820 if (src_fsp->op == NULL) {
1821 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1822 return tevent_req_post(req, ev);
1825 if (dest_fsp->op == NULL) {
1826 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1827 return tevent_req_post(req, ev);
1830 status = vfswrap_offload_write_loop(req);
1831 if (!NT_STATUS_IS_OK(status)) {
1832 tevent_req_nterror(req, status);
1833 return tevent_req_post(req, ev);
1836 return req;
1839 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1841 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1843 struct vfswrap_offload_write_state *state = tevent_req_data(
1844 req, struct vfswrap_offload_write_state);
1845 struct tevent_req *subreq = NULL;
1846 struct lock_struct read_lck;
1847 bool ok;
1849 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1851 init_strict_lock_struct(state->src_fsp,
1852 state->src_fsp->op->global->open_persistent_id,
1853 state->src_off,
1854 state->next_io_size,
1855 READ_LOCK,
1856 &read_lck);
1858 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1859 state->src_fsp,
1860 &read_lck);
1861 if (!ok) {
1862 return NT_STATUS_FILE_LOCK_CONFLICT;
1865 subreq = SMB_VFS_PREAD_SEND(state,
1866 state->src_fsp->conn->sconn->ev_ctx,
1867 state->src_fsp,
1868 state->buf,
1869 state->next_io_size,
1870 state->src_off);
1871 if (subreq == NULL) {
1872 return NT_STATUS_NO_MEMORY;
1874 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1876 return NT_STATUS_OK;
1879 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1881 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1883 struct tevent_req *req = tevent_req_callback_data(
1884 subreq, struct tevent_req);
1885 struct vfswrap_offload_write_state *state = tevent_req_data(
1886 req, struct vfswrap_offload_write_state);
1887 struct vfs_aio_state aio_state;
1888 struct lock_struct write_lck;
1889 ssize_t nread;
1890 bool ok;
1892 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1893 TALLOC_FREE(subreq);
1894 if (nread == -1) {
1895 DBG_ERR("read failed: %s\n", strerror(errno));
1896 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1897 return;
1899 if (nread != state->next_io_size) {
1900 DBG_ERR("Short read, only %zd of %zu\n",
1901 nread, state->next_io_size);
1902 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1903 return;
1906 state->src_off += nread;
1908 init_strict_lock_struct(state->dst_fsp,
1909 state->dst_fsp->op->global->open_persistent_id,
1910 state->dst_off,
1911 state->next_io_size,
1912 WRITE_LOCK,
1913 &write_lck);
1915 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1916 state->dst_fsp,
1917 &write_lck);
1918 if (!ok) {
1919 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1920 return;
1923 subreq = SMB_VFS_PWRITE_SEND(state,
1924 state->ev,
1925 state->dst_fsp,
1926 state->buf,
1927 state->next_io_size,
1928 state->dst_off);
1929 if (subreq == NULL) {
1930 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1931 return;
1933 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1936 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1938 struct tevent_req *req = tevent_req_callback_data(
1939 subreq, struct tevent_req);
1940 struct vfswrap_offload_write_state *state = tevent_req_data(
1941 req, struct vfswrap_offload_write_state);
1942 struct vfs_aio_state aio_state;
1943 ssize_t nwritten;
1944 NTSTATUS status;
1946 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1947 TALLOC_FREE(subreq);
1948 if (nwritten == -1) {
1949 DBG_ERR("write failed: %s\n", strerror(errno));
1950 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1951 return;
1953 if (nwritten != state->next_io_size) {
1954 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1955 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1956 return;
1959 state->dst_off += nwritten;
1961 if (state->remaining < nwritten) {
1962 /* Paranoia check */
1963 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1964 return;
1966 state->remaining -= nwritten;
1967 if (state->remaining == 0) {
1968 tevent_req_done(req);
1969 return;
1972 status = vfswrap_offload_write_loop(req);
1973 if (!NT_STATUS_IS_OK(status)) {
1974 tevent_req_nterror(req, status);
1975 return;
1978 return;
1981 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1982 struct tevent_req *req,
1983 off_t *copied)
1985 struct vfswrap_offload_write_state *state = tevent_req_data(
1986 req, struct vfswrap_offload_write_state);
1987 NTSTATUS status;
1989 if (tevent_req_is_nterror(req, &status)) {
1990 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1991 *copied = 0;
1992 tevent_req_received(req);
1993 return status;
1996 *copied = state->to_copy;
1997 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1998 tevent_req_received(req);
2000 return NT_STATUS_OK;
2003 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2004 TALLOC_CTX *mem_ctx,
2005 struct files_struct *fsp,
2006 struct smb_filename *smb_fname,
2007 uint16_t *_compression_fmt)
2009 return NT_STATUS_INVALID_DEVICE_REQUEST;
2012 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2013 TALLOC_CTX *mem_ctx,
2014 struct files_struct *fsp,
2015 uint16_t compression_fmt)
2017 return NT_STATUS_INVALID_DEVICE_REQUEST;
2020 /********************************************************************
2021 Given a stat buffer return the allocated size on disk, taking into
2022 account sparse files.
2023 ********************************************************************/
2024 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2025 struct files_struct *fsp,
2026 const SMB_STRUCT_STAT *sbuf)
2028 uint64_t result;
2030 START_PROFILE(syscall_get_alloc_size);
2032 if(S_ISDIR(sbuf->st_ex_mode)) {
2033 result = 0;
2034 goto out;
2037 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2038 /* The type of st_blocksize is blkcnt_t which *MUST* be
2039 signed (according to POSIX) and can be less than 64-bits.
2040 Ensure when we're converting to 64 bits wide we don't
2041 sign extend. */
2042 #if defined(SIZEOF_BLKCNT_T_8)
2043 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2044 #elif defined(SIZEOF_BLKCNT_T_4)
2046 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2047 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2049 #else
2050 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2051 #endif
2052 if (result == 0) {
2054 * Some file systems do not allocate a block for very
2055 * small files. But for non-empty file should report a
2056 * positive size.
2059 uint64_t filesize = get_file_size_stat(sbuf);
2060 if (filesize > 0) {
2061 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2064 #else
2065 result = get_file_size_stat(sbuf);
2066 #endif
2068 if (fsp && fsp->initial_allocation_size)
2069 result = MAX(result,fsp->initial_allocation_size);
2071 result = smb_roundup(handle->conn, result);
2073 out:
2074 END_PROFILE(syscall_get_alloc_size);
2075 return result;
2078 static int vfswrap_unlink(vfs_handle_struct *handle,
2079 const struct smb_filename *smb_fname)
2081 int result = -1;
2083 START_PROFILE(syscall_unlink);
2085 if (smb_fname->stream_name) {
2086 errno = ENOENT;
2087 goto out;
2089 result = unlink(smb_fname->base_name);
2091 out:
2092 END_PROFILE(syscall_unlink);
2093 return result;
2096 static int vfswrap_chmod(vfs_handle_struct *handle,
2097 const struct smb_filename *smb_fname,
2098 mode_t mode)
2100 int result;
2102 START_PROFILE(syscall_chmod);
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.
2112 int saved_errno = errno; /* We might get ENOSYS */
2113 result = SMB_VFS_CHMOD_ACL(handle->conn,
2114 smb_fname,
2115 mode);
2116 if (result == 0) {
2117 END_PROFILE(syscall_chmod);
2118 return result;
2120 /* Error - return the old errno. */
2121 errno = saved_errno;
2124 result = chmod(smb_fname->base_name, mode);
2125 END_PROFILE(syscall_chmod);
2126 return result;
2129 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2131 int result;
2133 START_PROFILE(syscall_fchmod);
2136 * We need to do this due to the fact that the default POSIX ACL
2137 * chmod modifies the ACL *mask* for the group owner, not the
2138 * group owner bits directly. JRA.
2142 int saved_errno = errno; /* We might get ENOSYS */
2143 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2144 END_PROFILE(syscall_fchmod);
2145 return result;
2147 /* Error - return the old errno. */
2148 errno = saved_errno;
2151 #if defined(HAVE_FCHMOD)
2152 result = fchmod(fsp->fh->fd, mode);
2153 #else
2154 result = -1;
2155 errno = ENOSYS;
2156 #endif
2158 END_PROFILE(syscall_fchmod);
2159 return result;
2162 static int vfswrap_chown(vfs_handle_struct *handle,
2163 const struct smb_filename *smb_fname,
2164 uid_t uid,
2165 gid_t gid)
2167 int result;
2169 START_PROFILE(syscall_chown);
2170 result = chown(smb_fname->base_name, uid, gid);
2171 END_PROFILE(syscall_chown);
2172 return result;
2175 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2177 #ifdef HAVE_FCHOWN
2178 int result;
2180 START_PROFILE(syscall_fchown);
2181 result = fchown(fsp->fh->fd, uid, gid);
2182 END_PROFILE(syscall_fchown);
2183 return result;
2184 #else
2185 errno = ENOSYS;
2186 return -1;
2187 #endif
2190 static int vfswrap_lchown(vfs_handle_struct *handle,
2191 const struct smb_filename *smb_fname,
2192 uid_t uid,
2193 gid_t gid)
2195 int result;
2197 START_PROFILE(syscall_lchown);
2198 result = lchown(smb_fname->base_name, uid, gid);
2199 END_PROFILE(syscall_lchown);
2200 return result;
2203 static int vfswrap_chdir(vfs_handle_struct *handle,
2204 const struct smb_filename *smb_fname)
2206 int result;
2208 START_PROFILE(syscall_chdir);
2209 result = chdir(smb_fname->base_name);
2210 END_PROFILE(syscall_chdir);
2211 return result;
2214 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2215 TALLOC_CTX *ctx)
2217 char *result;
2218 struct smb_filename *smb_fname = NULL;
2220 START_PROFILE(syscall_getwd);
2221 result = sys_getwd();
2222 END_PROFILE(syscall_getwd);
2224 if (result == NULL) {
2225 return NULL;
2227 smb_fname = synthetic_smb_fname(ctx,
2228 result,
2229 NULL,
2230 NULL,
2232 if (smb_fname == NULL) {
2233 SAFE_FREE(result);
2235 return smb_fname;
2238 /*********************************************************************
2239 nsec timestamp resolution call. Convert down to whatever the underlying
2240 system will support.
2241 **********************************************************************/
2243 static int vfswrap_ntimes(vfs_handle_struct *handle,
2244 const struct smb_filename *smb_fname,
2245 struct smb_file_time *ft)
2247 int result = -1;
2249 START_PROFILE(syscall_ntimes);
2251 if (smb_fname->stream_name) {
2252 errno = ENOENT;
2253 goto out;
2256 if (ft != NULL) {
2257 if (null_timespec(ft->atime)) {
2258 ft->atime= smb_fname->st.st_ex_atime;
2261 if (null_timespec(ft->mtime)) {
2262 ft->mtime = smb_fname->st.st_ex_mtime;
2265 if (!null_timespec(ft->create_time)) {
2266 set_create_timespec_ea(handle->conn,
2267 smb_fname,
2268 ft->create_time);
2271 if ((timespec_compare(&ft->atime,
2272 &smb_fname->st.st_ex_atime) == 0) &&
2273 (timespec_compare(&ft->mtime,
2274 &smb_fname->st.st_ex_mtime) == 0)) {
2275 return 0;
2279 #if defined(HAVE_UTIMENSAT)
2280 if (ft != NULL) {
2281 struct timespec ts[2];
2282 ts[0] = ft->atime;
2283 ts[1] = ft->mtime;
2284 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2285 } else {
2286 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2288 if (!((result == -1) && (errno == ENOSYS))) {
2289 goto out;
2291 #endif
2292 #if defined(HAVE_UTIMES)
2293 if (ft != NULL) {
2294 struct timeval tv[2];
2295 tv[0] = convert_timespec_to_timeval(ft->atime);
2296 tv[1] = convert_timespec_to_timeval(ft->mtime);
2297 result = utimes(smb_fname->base_name, tv);
2298 } else {
2299 result = utimes(smb_fname->base_name, NULL);
2301 if (!((result == -1) && (errno == ENOSYS))) {
2302 goto out;
2304 #endif
2305 #if defined(HAVE_UTIME)
2306 if (ft != NULL) {
2307 struct utimbuf times;
2308 times.actime = convert_timespec_to_time_t(ft->atime);
2309 times.modtime = convert_timespec_to_time_t(ft->mtime);
2310 result = utime(smb_fname->base_name, &times);
2311 } else {
2312 result = utime(smb_fname->base_name, NULL);
2314 if (!((result == -1) && (errno == ENOSYS))) {
2315 goto out;
2317 #endif
2318 errno = ENOSYS;
2319 result = -1;
2321 out:
2322 END_PROFILE(syscall_ntimes);
2323 return result;
2326 /*********************************************************************
2327 A version of ftruncate that will write the space on disk if strict
2328 allocate is set.
2329 **********************************************************************/
2331 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2333 off_t space_to_write;
2334 uint64_t space_avail;
2335 uint64_t bsize,dfree,dsize;
2336 int ret;
2337 NTSTATUS status;
2338 SMB_STRUCT_STAT *pst;
2340 status = vfs_stat_fsp(fsp);
2341 if (!NT_STATUS_IS_OK(status)) {
2342 return -1;
2344 pst = &fsp->fsp_name->st;
2346 #ifdef S_ISFIFO
2347 if (S_ISFIFO(pst->st_ex_mode))
2348 return 0;
2349 #endif
2351 if (pst->st_ex_size == len)
2352 return 0;
2354 /* Shrink - just ftruncate. */
2355 if (pst->st_ex_size > len)
2356 return ftruncate(fsp->fh->fd, len);
2358 space_to_write = len - pst->st_ex_size;
2360 /* for allocation try fallocate first. This can fail on some
2361 platforms e.g. when the filesystem doesn't support it and no
2362 emulation is being done by the libc (like on AIX with JFS1). In that
2363 case we do our own emulation. fallocate implementations can
2364 return ENOTSUP or EINVAL in cases like that. */
2365 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2366 if (ret == -1 && errno == ENOSPC) {
2367 return -1;
2369 if (ret == 0) {
2370 return 0;
2372 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2373 "error %d. Falling back to slow manual allocation\n", errno));
2375 /* available disk space is enough or not? */
2376 space_avail =
2377 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2378 /* space_avail is 1k blocks */
2379 if (space_avail == (uint64_t)-1 ||
2380 ((uint64_t)space_to_write/1024 > space_avail) ) {
2381 errno = ENOSPC;
2382 return -1;
2385 /* Write out the real space on disk. */
2386 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2387 if (ret != 0) {
2388 return -1;
2391 return 0;
2394 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2396 int result = -1;
2397 SMB_STRUCT_STAT *pst;
2398 NTSTATUS status;
2399 char c = 0;
2401 START_PROFILE(syscall_ftruncate);
2403 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2404 result = strict_allocate_ftruncate(handle, fsp, len);
2405 END_PROFILE(syscall_ftruncate);
2406 return result;
2409 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2410 ftruncate if the system supports it. Then I discovered that
2411 you can have some filesystems that support ftruncate
2412 expansion and some that don't! On Linux fat can't do
2413 ftruncate extend but ext2 can. */
2415 result = ftruncate(fsp->fh->fd, len);
2417 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2418 extend a file with ftruncate. Provide alternate implementation
2419 for this */
2421 /* Do an fstat to see if the file is longer than the requested
2422 size in which case the ftruncate above should have
2423 succeeded or shorter, in which case seek to len - 1 and
2424 write 1 byte of zero */
2425 status = vfs_stat_fsp(fsp);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 goto done;
2430 /* We need to update the files_struct after successful ftruncate */
2431 if (result == 0) {
2432 goto done;
2435 pst = &fsp->fsp_name->st;
2437 #ifdef S_ISFIFO
2438 if (S_ISFIFO(pst->st_ex_mode)) {
2439 result = 0;
2440 goto done;
2442 #endif
2444 if (pst->st_ex_size == len) {
2445 result = 0;
2446 goto done;
2449 if (pst->st_ex_size > len) {
2450 /* the ftruncate should have worked */
2451 goto done;
2454 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2455 goto done;
2458 result = 0;
2460 done:
2462 END_PROFILE(syscall_ftruncate);
2463 return result;
2466 static int vfswrap_fallocate(vfs_handle_struct *handle,
2467 files_struct *fsp,
2468 uint32_t mode,
2469 off_t offset,
2470 off_t len)
2472 int result;
2474 START_PROFILE(syscall_fallocate);
2475 if (mode == 0) {
2476 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2478 * posix_fallocate returns 0 on success, errno on error
2479 * and doesn't set errno. Make it behave like fallocate()
2480 * which returns -1, and sets errno on failure.
2482 if (result != 0) {
2483 errno = result;
2484 result = -1;
2486 } else {
2487 /* sys_fallocate handles filtering of unsupported mode flags */
2488 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2490 END_PROFILE(syscall_fallocate);
2491 return result;
2494 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2496 bool result;
2498 START_PROFILE(syscall_fcntl_lock);
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_lock(fsp->fh->fd, op, offset, count, type);
2508 END_PROFILE(syscall_fcntl_lock);
2509 return result;
2512 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2513 uint32_t share_mode, uint32_t access_mask)
2515 START_PROFILE(syscall_kernel_flock);
2516 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2517 END_PROFILE(syscall_kernel_flock);
2518 return 0;
2521 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2523 bool result;
2524 int op = F_GETLK;
2526 START_PROFILE(syscall_fcntl_getlock);
2528 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2529 "smbd",
2530 "force process locks",
2531 false)) {
2532 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2535 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2536 END_PROFILE(syscall_fcntl_getlock);
2537 return result;
2540 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2541 int leasetype)
2543 int result = -1;
2545 START_PROFILE(syscall_linux_setlease);
2547 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2548 result = linux_setlease(fsp->fh->fd, leasetype);
2549 #else
2550 errno = ENOSYS;
2551 #endif
2552 END_PROFILE(syscall_linux_setlease);
2553 return result;
2556 static int vfswrap_symlink(vfs_handle_struct *handle,
2557 const char *link_target,
2558 const struct smb_filename *new_smb_fname)
2560 int result;
2562 START_PROFILE(syscall_symlink);
2563 result = symlink(link_target, new_smb_fname->base_name);
2564 END_PROFILE(syscall_symlink);
2565 return result;
2568 static int vfswrap_readlink(vfs_handle_struct *handle,
2569 const struct smb_filename *smb_fname,
2570 char *buf,
2571 size_t bufsiz)
2573 int result;
2575 START_PROFILE(syscall_readlink);
2576 result = readlink(smb_fname->base_name, buf, bufsiz);
2577 END_PROFILE(syscall_readlink);
2578 return result;
2581 static int vfswrap_link(vfs_handle_struct *handle,
2582 const struct smb_filename *old_smb_fname,
2583 const struct smb_filename *new_smb_fname)
2585 int result;
2587 START_PROFILE(syscall_link);
2588 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2589 END_PROFILE(syscall_link);
2590 return result;
2593 static int vfswrap_mknod(vfs_handle_struct *handle,
2594 const struct smb_filename *smb_fname,
2595 mode_t mode,
2596 SMB_DEV_T dev)
2598 int result;
2600 START_PROFILE(syscall_mknod);
2601 result = sys_mknod(smb_fname->base_name, mode, dev);
2602 END_PROFILE(syscall_mknod);
2603 return result;
2606 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2607 TALLOC_CTX *ctx,
2608 const struct smb_filename *smb_fname)
2610 char *result;
2611 struct smb_filename *result_fname = NULL;
2613 START_PROFILE(syscall_realpath);
2614 result = sys_realpath(smb_fname->base_name);
2615 END_PROFILE(syscall_realpath);
2616 if (result) {
2617 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2618 SAFE_FREE(result);
2620 return result_fname;
2623 static int vfswrap_chflags(vfs_handle_struct *handle,
2624 const struct smb_filename *smb_fname,
2625 unsigned int flags)
2627 #ifdef HAVE_CHFLAGS
2628 return chflags(smb_fname->base_name, flags);
2629 #else
2630 errno = ENOSYS;
2631 return -1;
2632 #endif
2635 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2636 const SMB_STRUCT_STAT *sbuf)
2638 struct file_id key;
2640 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2641 * blob */
2642 ZERO_STRUCT(key);
2644 key.devid = sbuf->st_ex_dev;
2645 key.inode = sbuf->st_ex_ino;
2646 /* key.extid is unused by default. */
2648 return key;
2651 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2652 struct files_struct *fsp,
2653 const struct smb_filename *smb_fname,
2654 TALLOC_CTX *mem_ctx,
2655 unsigned int *pnum_streams,
2656 struct stream_struct **pstreams)
2658 SMB_STRUCT_STAT sbuf;
2659 struct stream_struct *tmp_streams = NULL;
2660 int ret;
2662 if ((fsp != NULL) && (fsp->is_directory)) {
2664 * No default streams on directories
2666 goto done;
2669 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2670 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2672 else {
2673 struct smb_filename smb_fname_cp;
2675 ZERO_STRUCT(smb_fname_cp);
2676 smb_fname_cp.base_name = discard_const_p(char,
2677 smb_fname->base_name);
2678 smb_fname_cp.flags = smb_fname->flags;
2680 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2681 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2682 } else {
2683 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2685 sbuf = smb_fname_cp.st;
2688 if (ret == -1) {
2689 return map_nt_error_from_unix(errno);
2692 if (S_ISDIR(sbuf.st_ex_mode)) {
2693 goto done;
2696 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2697 (*pnum_streams) + 1);
2698 if (tmp_streams == NULL) {
2699 return NT_STATUS_NO_MEMORY;
2701 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2702 if (tmp_streams[*pnum_streams].name == NULL) {
2703 return NT_STATUS_NO_MEMORY;
2705 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2706 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2708 *pnum_streams += 1;
2709 *pstreams = tmp_streams;
2710 done:
2711 return NT_STATUS_OK;
2714 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2715 const char *path,
2716 const char *name,
2717 TALLOC_CTX *mem_ctx,
2718 char **found_name)
2721 * Don't fall back to get_real_filename so callers can differentiate
2722 * between a full directory scan and an actual case-insensitive stat.
2724 errno = EOPNOTSUPP;
2725 return -1;
2728 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2729 const struct smb_filename *smb_fname)
2731 return handle->conn->connectpath;
2734 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2735 struct byte_range_lock *br_lck,
2736 struct lock_struct *plock,
2737 bool blocking_lock)
2739 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2741 /* Note: blr is not used in the default implementation. */
2742 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2745 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2746 struct messaging_context *msg_ctx,
2747 struct byte_range_lock *br_lck,
2748 const struct lock_struct *plock)
2750 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2752 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2755 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2756 struct byte_range_lock *br_lck,
2757 struct lock_struct *plock)
2759 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2761 /* Note: blr is not used in the default implementation. */
2762 return brl_lock_cancel_default(br_lck, plock);
2765 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2766 files_struct *fsp,
2767 struct lock_struct *plock)
2769 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2770 plock->lock_type == WRITE_LOCK);
2772 return strict_lock_check_default(fsp, plock);
2775 /* NT ACL operations. */
2777 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2778 files_struct *fsp,
2779 uint32_t security_info,
2780 TALLOC_CTX *mem_ctx,
2781 struct security_descriptor **ppdesc)
2783 NTSTATUS result;
2785 START_PROFILE(fget_nt_acl);
2786 result = posix_fget_nt_acl(fsp, security_info,
2787 mem_ctx, ppdesc);
2788 END_PROFILE(fget_nt_acl);
2789 return result;
2792 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2793 const struct smb_filename *smb_fname,
2794 uint32_t security_info,
2795 TALLOC_CTX *mem_ctx,
2796 struct security_descriptor **ppdesc)
2798 NTSTATUS result;
2800 START_PROFILE(get_nt_acl);
2801 result = posix_get_nt_acl(handle->conn,
2802 smb_fname,
2803 security_info,
2804 mem_ctx,
2805 ppdesc);
2806 END_PROFILE(get_nt_acl);
2807 return result;
2810 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2812 NTSTATUS result;
2814 START_PROFILE(fset_nt_acl);
2815 result = set_nt_acl(fsp, security_info_sent, psd);
2816 END_PROFILE(fset_nt_acl);
2817 return result;
2820 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2821 struct smb_filename *file,
2822 struct security_acl *sacl,
2823 uint32_t access_requested,
2824 uint32_t access_denied)
2826 return NT_STATUS_OK; /* Nothing to do here ... */
2829 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2830 const struct smb_filename *smb_fname,
2831 mode_t mode)
2833 #ifdef HAVE_NO_ACL
2834 errno = ENOSYS;
2835 return -1;
2836 #else
2837 int result;
2839 START_PROFILE(chmod_acl);
2840 result = chmod_acl(handle->conn, smb_fname, mode);
2841 END_PROFILE(chmod_acl);
2842 return result;
2843 #endif
2846 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2848 #ifdef HAVE_NO_ACL
2849 errno = ENOSYS;
2850 return -1;
2851 #else
2852 int result;
2854 START_PROFILE(fchmod_acl);
2855 result = fchmod_acl(fsp, mode);
2856 END_PROFILE(fchmod_acl);
2857 return result;
2858 #endif
2861 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2862 const struct smb_filename *smb_fname,
2863 SMB_ACL_TYPE_T type,
2864 TALLOC_CTX *mem_ctx)
2866 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2869 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2870 files_struct *fsp,
2871 TALLOC_CTX *mem_ctx)
2873 return sys_acl_get_fd(handle, fsp, mem_ctx);
2876 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2877 const struct smb_filename *smb_fname,
2878 SMB_ACL_TYPE_T acltype,
2879 SMB_ACL_T theacl)
2881 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2884 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2886 return sys_acl_set_fd(handle, fsp, theacl);
2889 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2890 const struct smb_filename *smb_fname)
2892 return sys_acl_delete_def_file(handle, smb_fname);
2895 /****************************************************************
2896 Extended attribute operations.
2897 *****************************************************************/
2899 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2900 const struct smb_filename *smb_fname,
2901 const char *name,
2902 void *value,
2903 size_t size)
2905 return getxattr(smb_fname->base_name, name, value, size);
2908 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2910 return fgetxattr(fsp->fh->fd, name, value, size);
2913 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2914 const struct smb_filename *smb_fname,
2915 char *list,
2916 size_t size)
2918 return listxattr(smb_fname->base_name, list, size);
2921 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2923 return flistxattr(fsp->fh->fd, list, size);
2926 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2927 const struct smb_filename *smb_fname,
2928 const char *name)
2930 return removexattr(smb_fname->base_name, name);
2933 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2935 return fremovexattr(fsp->fh->fd, name);
2938 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2939 const struct smb_filename *smb_fname,
2940 const char *name,
2941 const void *value,
2942 size_t size,
2943 int flags)
2945 return setxattr(smb_fname->base_name, name, value, size, flags);
2948 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2950 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2953 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2955 return false;
2958 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2959 const struct smb_filename *fname,
2960 SMB_STRUCT_STAT *sbuf)
2962 NTSTATUS status;
2963 char *path;
2964 bool offline = false;
2966 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2967 return false;
2970 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2971 #if defined(ENOTSUP)
2972 errno = ENOTSUP;
2973 #endif
2974 return false;
2977 status = get_full_smb_filename(talloc_tos(), fname, &path);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 errno = map_errno_from_nt_status(status);
2980 return false;
2983 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2985 TALLOC_FREE(path);
2987 return offline;
2990 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2991 struct files_struct *fsp,
2992 TALLOC_CTX *mem_ctx,
2993 DATA_BLOB *cookie)
2995 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2998 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2999 struct files_struct *fsp,
3000 const DATA_BLOB old_cookie,
3001 TALLOC_CTX *mem_ctx,
3002 DATA_BLOB *new_cookie)
3004 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3005 new_cookie);
3008 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3009 struct smb_request *smb1req,
3010 struct smbXsrv_open *op,
3011 const DATA_BLOB old_cookie,
3012 TALLOC_CTX *mem_ctx,
3013 struct files_struct **fsp,
3014 DATA_BLOB *new_cookie)
3016 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3017 old_cookie, mem_ctx,
3018 fsp, new_cookie);
3021 static struct vfs_fn_pointers vfs_default_fns = {
3022 /* Disk operations */
3024 .connect_fn = vfswrap_connect,
3025 .disconnect_fn = vfswrap_disconnect,
3026 .disk_free_fn = vfswrap_disk_free,
3027 .get_quota_fn = vfswrap_get_quota,
3028 .set_quota_fn = vfswrap_set_quota,
3029 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3030 .statvfs_fn = vfswrap_statvfs,
3031 .fs_capabilities_fn = vfswrap_fs_capabilities,
3032 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3033 .snap_check_path_fn = vfswrap_snap_check_path,
3034 .snap_create_fn = vfswrap_snap_create,
3035 .snap_delete_fn = vfswrap_snap_delete,
3037 /* Directory operations */
3039 .opendir_fn = vfswrap_opendir,
3040 .fdopendir_fn = vfswrap_fdopendir,
3041 .readdir_fn = vfswrap_readdir,
3042 .readdir_attr_fn = vfswrap_readdir_attr,
3043 .seekdir_fn = vfswrap_seekdir,
3044 .telldir_fn = vfswrap_telldir,
3045 .rewind_dir_fn = vfswrap_rewinddir,
3046 .mkdir_fn = vfswrap_mkdir,
3047 .rmdir_fn = vfswrap_rmdir,
3048 .closedir_fn = vfswrap_closedir,
3050 /* File operations */
3052 .open_fn = vfswrap_open,
3053 .create_file_fn = vfswrap_create_file,
3054 .close_fn = vfswrap_close,
3055 .read_fn = vfswrap_read,
3056 .pread_fn = vfswrap_pread,
3057 .pread_send_fn = vfswrap_pread_send,
3058 .pread_recv_fn = vfswrap_pread_recv,
3059 .write_fn = vfswrap_write,
3060 .pwrite_fn = vfswrap_pwrite,
3061 .pwrite_send_fn = vfswrap_pwrite_send,
3062 .pwrite_recv_fn = vfswrap_pwrite_recv,
3063 .lseek_fn = vfswrap_lseek,
3064 .sendfile_fn = vfswrap_sendfile,
3065 .recvfile_fn = vfswrap_recvfile,
3066 .rename_fn = vfswrap_rename,
3067 .fsync_fn = vfswrap_fsync,
3068 .fsync_send_fn = vfswrap_fsync_send,
3069 .fsync_recv_fn = vfswrap_fsync_recv,
3070 .stat_fn = vfswrap_stat,
3071 .fstat_fn = vfswrap_fstat,
3072 .lstat_fn = vfswrap_lstat,
3073 .get_alloc_size_fn = vfswrap_get_alloc_size,
3074 .unlink_fn = vfswrap_unlink,
3075 .chmod_fn = vfswrap_chmod,
3076 .fchmod_fn = vfswrap_fchmod,
3077 .chown_fn = vfswrap_chown,
3078 .fchown_fn = vfswrap_fchown,
3079 .lchown_fn = vfswrap_lchown,
3080 .chdir_fn = vfswrap_chdir,
3081 .getwd_fn = vfswrap_getwd,
3082 .ntimes_fn = vfswrap_ntimes,
3083 .ftruncate_fn = vfswrap_ftruncate,
3084 .fallocate_fn = vfswrap_fallocate,
3085 .lock_fn = vfswrap_lock,
3086 .kernel_flock_fn = vfswrap_kernel_flock,
3087 .linux_setlease_fn = vfswrap_linux_setlease,
3088 .getlock_fn = vfswrap_getlock,
3089 .symlink_fn = vfswrap_symlink,
3090 .readlink_fn = vfswrap_readlink,
3091 .link_fn = vfswrap_link,
3092 .mknod_fn = vfswrap_mknod,
3093 .realpath_fn = vfswrap_realpath,
3094 .chflags_fn = vfswrap_chflags,
3095 .file_id_create_fn = vfswrap_file_id_create,
3096 .streaminfo_fn = vfswrap_streaminfo,
3097 .get_real_filename_fn = vfswrap_get_real_filename,
3098 .connectpath_fn = vfswrap_connectpath,
3099 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3100 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3101 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3102 .strict_lock_check_fn = vfswrap_strict_lock_check,
3103 .translate_name_fn = vfswrap_translate_name,
3104 .fsctl_fn = vfswrap_fsctl,
3105 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3106 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3107 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3108 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3109 .offload_read_send_fn = vfswrap_offload_read_send,
3110 .offload_read_recv_fn = vfswrap_offload_read_recv,
3111 .offload_write_send_fn = vfswrap_offload_write_send,
3112 .offload_write_recv_fn = vfswrap_offload_write_recv,
3113 .get_compression_fn = vfswrap_get_compression,
3114 .set_compression_fn = vfswrap_set_compression,
3116 /* NT ACL operations. */
3118 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3119 .get_nt_acl_fn = vfswrap_get_nt_acl,
3120 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3121 .audit_file_fn = vfswrap_audit_file,
3123 /* POSIX ACL operations. */
3125 .chmod_acl_fn = vfswrap_chmod_acl,
3126 .fchmod_acl_fn = vfswrap_fchmod_acl,
3128 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3129 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3130 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3131 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3132 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3133 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3134 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3136 /* EA operations. */
3137 .getxattr_fn = vfswrap_getxattr,
3138 .fgetxattr_fn = vfswrap_fgetxattr,
3139 .listxattr_fn = vfswrap_listxattr,
3140 .flistxattr_fn = vfswrap_flistxattr,
3141 .removexattr_fn = vfswrap_removexattr,
3142 .fremovexattr_fn = vfswrap_fremovexattr,
3143 .setxattr_fn = vfswrap_setxattr,
3144 .fsetxattr_fn = vfswrap_fsetxattr,
3146 /* aio operations */
3147 .aio_force_fn = vfswrap_aio_force,
3149 /* durable handle operations */
3150 .durable_cookie_fn = vfswrap_durable_cookie,
3151 .durable_disconnect_fn = vfswrap_durable_disconnect,
3152 .durable_reconnect_fn = vfswrap_durable_reconnect,
3155 static_decl_vfs;
3156 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3158 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3159 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);