winbindd: queryuser - only get group name if needed
[Samba.git] / source3 / modules / vfs_default.c
blobfbfe654f1fd3fadad0ed00f5f2695f6d39eee55e
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 ZERO_STRUCT(statbuf);
133 ret = sys_statvfs(conn->connectpath, &statbuf);
134 if (ret == 0) {
135 caps = statbuf.FsCapabilities;
138 *p_ts_res = TIMESTAMP_SET_SECONDS;
140 /* Work out what timestamp resolution we can
141 * use when setting a timestamp. */
143 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
144 NULL, NULL, 0);
145 if (smb_fname_cpath == NULL) {
146 return caps;
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 static void vfswrap_init_search_op(vfs_handle_struct *handle,
558 DIR *dirp)
560 /* Default behavior is a NOOP */
563 /* File operations */
565 static int vfswrap_open(vfs_handle_struct *handle,
566 struct smb_filename *smb_fname,
567 files_struct *fsp, int flags, mode_t mode)
569 int result = -1;
571 START_PROFILE(syscall_open);
573 if (smb_fname->stream_name) {
574 errno = ENOENT;
575 goto out;
578 result = open(smb_fname->base_name, flags, mode);
579 out:
580 END_PROFILE(syscall_open);
581 return result;
584 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
585 struct smb_request *req,
586 uint16_t root_dir_fid,
587 struct smb_filename *smb_fname,
588 uint32_t access_mask,
589 uint32_t share_access,
590 uint32_t create_disposition,
591 uint32_t create_options,
592 uint32_t file_attributes,
593 uint32_t oplock_request,
594 struct smb2_lease *lease,
595 uint64_t allocation_size,
596 uint32_t private_flags,
597 struct security_descriptor *sd,
598 struct ea_list *ea_list,
599 files_struct **result,
600 int *pinfo,
601 const struct smb2_create_blobs *in_context_blobs,
602 struct smb2_create_blobs *out_context_blobs)
604 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
605 access_mask, share_access,
606 create_disposition, create_options,
607 file_attributes, oplock_request, lease,
608 allocation_size, private_flags,
609 sd, ea_list, result,
610 pinfo, in_context_blobs, out_context_blobs);
613 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
615 int result;
617 START_PROFILE(syscall_close);
618 result = fd_close_posix(fsp);
619 END_PROFILE(syscall_close);
620 return result;
623 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
625 ssize_t result;
627 START_PROFILE_BYTES(syscall_read, n);
628 result = sys_read(fsp->fh->fd, data, n);
629 END_PROFILE_BYTES(syscall_read);
630 return result;
633 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
634 size_t n, off_t offset)
636 ssize_t result;
638 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
639 START_PROFILE_BYTES(syscall_pread, n);
640 result = sys_pread(fsp->fh->fd, data, n, offset);
641 END_PROFILE_BYTES(syscall_pread);
643 if (result == -1 && errno == ESPIPE) {
644 /* Maintain the fiction that pipes can be seeked (sought?) on. */
645 result = SMB_VFS_READ(fsp, data, n);
646 fsp->fh->pos = 0;
649 #else /* HAVE_PREAD */
650 off_t curr;
651 int lerrno;
653 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
654 if (curr == -1 && errno == ESPIPE) {
655 /* Maintain the fiction that pipes can be seeked (sought?) on. */
656 result = SMB_VFS_READ(fsp, data, n);
657 fsp->fh->pos = 0;
658 return result;
661 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
662 return -1;
665 errno = 0;
666 result = SMB_VFS_READ(fsp, data, n);
667 lerrno = errno;
669 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
670 errno = lerrno;
672 #endif /* HAVE_PREAD */
674 return result;
677 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
679 ssize_t result;
681 START_PROFILE_BYTES(syscall_write, n);
682 result = sys_write(fsp->fh->fd, data, n);
683 END_PROFILE_BYTES(syscall_write);
684 return result;
687 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
688 size_t n, off_t offset)
690 ssize_t result;
692 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
693 START_PROFILE_BYTES(syscall_pwrite, n);
694 result = sys_pwrite(fsp->fh->fd, data, n, offset);
695 END_PROFILE_BYTES(syscall_pwrite);
697 if (result == -1 && errno == ESPIPE) {
698 /* Maintain the fiction that pipes can be sought on. */
699 result = SMB_VFS_WRITE(fsp, data, n);
702 #else /* HAVE_PWRITE */
703 off_t curr;
704 int lerrno;
706 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
707 if (curr == -1) {
708 return -1;
711 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
712 return -1;
715 result = SMB_VFS_WRITE(fsp, data, n);
716 lerrno = errno;
718 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
719 errno = lerrno;
721 #endif /* HAVE_PWRITE */
723 return result;
726 static int vfswrap_init_pool(struct smbd_server_connection *conn)
728 int ret;
730 if (conn->pool != NULL) {
731 return 0;
734 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
735 &conn->pool);
736 return ret;
739 struct vfswrap_pread_state {
740 ssize_t ret;
741 int err;
742 int fd;
743 void *buf;
744 size_t count;
745 off_t offset;
747 struct vfs_aio_state vfs_aio_state;
748 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
751 static void vfs_pread_do(void *private_data);
752 static void vfs_pread_done(struct tevent_req *subreq);
753 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
755 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
756 TALLOC_CTX *mem_ctx,
757 struct tevent_context *ev,
758 struct files_struct *fsp,
759 void *data,
760 size_t n, off_t offset)
762 struct tevent_req *req, *subreq;
763 struct vfswrap_pread_state *state;
764 int ret;
766 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
767 if (req == NULL) {
768 return NULL;
771 ret = vfswrap_init_pool(handle->conn->sconn);
772 if (tevent_req_error(req, ret)) {
773 return tevent_req_post(req, ev);
776 state->ret = -1;
777 state->fd = fsp->fh->fd;
778 state->buf = data;
779 state->count = n;
780 state->offset = offset;
782 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
783 state->profile_bytes, n);
784 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
786 subreq = pthreadpool_tevent_job_send(
787 state, ev, handle->conn->sconn->pool,
788 vfs_pread_do, state);
789 if (tevent_req_nomem(subreq, req)) {
790 return tevent_req_post(req, ev);
792 tevent_req_set_callback(subreq, vfs_pread_done, req);
794 talloc_set_destructor(state, vfs_pread_state_destructor);
796 return req;
799 static void vfs_pread_do(void *private_data)
801 struct vfswrap_pread_state *state = talloc_get_type_abort(
802 private_data, struct vfswrap_pread_state);
803 struct timespec start_time;
804 struct timespec end_time;
806 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
808 PROFILE_TIMESTAMP(&start_time);
810 do {
811 state->ret = pread(state->fd, state->buf, state->count,
812 state->offset);
813 } while ((state->ret == -1) && (errno == EINTR));
815 state->err = errno;
817 PROFILE_TIMESTAMP(&end_time);
819 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
821 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
824 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
826 return -1;
829 static void vfs_pread_done(struct tevent_req *subreq)
831 struct tevent_req *req = tevent_req_callback_data(
832 subreq, struct tevent_req);
833 struct vfswrap_pread_state *state = tevent_req_data(
834 req, struct vfswrap_pread_state);
835 int ret;
837 ret = pthreadpool_tevent_job_recv(subreq);
838 TALLOC_FREE(subreq);
839 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
840 talloc_set_destructor(state, NULL);
841 if (tevent_req_error(req, ret)) {
842 return;
845 tevent_req_done(req);
848 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
849 struct vfs_aio_state *vfs_aio_state)
851 struct vfswrap_pread_state *state = tevent_req_data(
852 req, struct vfswrap_pread_state);
854 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
855 return -1;
858 *vfs_aio_state = state->vfs_aio_state;
859 return state->ret;
862 struct vfswrap_pwrite_state {
863 ssize_t ret;
864 int err;
865 int fd;
866 const void *buf;
867 size_t count;
868 off_t offset;
870 struct vfs_aio_state vfs_aio_state;
871 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
874 static void vfs_pwrite_do(void *private_data);
875 static void vfs_pwrite_done(struct tevent_req *subreq);
876 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
878 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
879 TALLOC_CTX *mem_ctx,
880 struct tevent_context *ev,
881 struct files_struct *fsp,
882 const void *data,
883 size_t n, off_t offset)
885 struct tevent_req *req, *subreq;
886 struct vfswrap_pwrite_state *state;
887 int ret;
889 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
890 if (req == NULL) {
891 return NULL;
894 ret = vfswrap_init_pool(handle->conn->sconn);
895 if (tevent_req_error(req, ret)) {
896 return tevent_req_post(req, ev);
899 state->ret = -1;
900 state->fd = fsp->fh->fd;
901 state->buf = data;
902 state->count = n;
903 state->offset = offset;
905 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
906 state->profile_bytes, n);
907 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
909 subreq = pthreadpool_tevent_job_send(
910 state, ev, handle->conn->sconn->pool,
911 vfs_pwrite_do, state);
912 if (tevent_req_nomem(subreq, req)) {
913 return tevent_req_post(req, ev);
915 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
917 talloc_set_destructor(state, vfs_pwrite_state_destructor);
919 return req;
922 static void vfs_pwrite_do(void *private_data)
924 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
925 private_data, struct vfswrap_pwrite_state);
926 struct timespec start_time;
927 struct timespec end_time;
929 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
931 PROFILE_TIMESTAMP(&start_time);
933 do {
934 state->ret = pwrite(state->fd, state->buf, state->count,
935 state->offset);
936 } while ((state->ret == -1) && (errno == EINTR));
938 state->err = errno;
940 PROFILE_TIMESTAMP(&end_time);
942 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
944 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
947 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
949 return -1;
952 static void vfs_pwrite_done(struct tevent_req *subreq)
954 struct tevent_req *req = tevent_req_callback_data(
955 subreq, struct tevent_req);
956 struct vfswrap_pwrite_state *state = tevent_req_data(
957 req, struct vfswrap_pwrite_state);
958 int ret;
960 ret = pthreadpool_tevent_job_recv(subreq);
961 TALLOC_FREE(subreq);
962 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
963 talloc_set_destructor(state, NULL);
964 if (tevent_req_error(req, ret)) {
965 return;
968 tevent_req_done(req);
971 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
972 struct vfs_aio_state *vfs_aio_state)
974 struct vfswrap_pwrite_state *state = tevent_req_data(
975 req, struct vfswrap_pwrite_state);
977 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
978 return -1;
981 *vfs_aio_state = state->vfs_aio_state;
982 return state->ret;
985 struct vfswrap_fsync_state {
986 ssize_t ret;
987 int err;
988 int fd;
990 struct vfs_aio_state vfs_aio_state;
991 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
994 static void vfs_fsync_do(void *private_data);
995 static void vfs_fsync_done(struct tevent_req *subreq);
996 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
998 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
999 TALLOC_CTX *mem_ctx,
1000 struct tevent_context *ev,
1001 struct files_struct *fsp)
1003 struct tevent_req *req, *subreq;
1004 struct vfswrap_fsync_state *state;
1005 int ret;
1007 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1008 if (req == NULL) {
1009 return NULL;
1012 ret = vfswrap_init_pool(handle->conn->sconn);
1013 if (tevent_req_error(req, ret)) {
1014 return tevent_req_post(req, ev);
1017 state->ret = -1;
1018 state->fd = fsp->fh->fd;
1020 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1021 state->profile_basic);
1023 subreq = pthreadpool_tevent_job_send(
1024 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1025 if (tevent_req_nomem(subreq, req)) {
1026 return tevent_req_post(req, ev);
1028 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1030 talloc_set_destructor(state, vfs_fsync_state_destructor);
1032 return req;
1035 static void vfs_fsync_do(void *private_data)
1037 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1038 private_data, struct vfswrap_fsync_state);
1039 struct timespec start_time;
1040 struct timespec end_time;
1042 PROFILE_TIMESTAMP(&start_time);
1044 do {
1045 state->ret = fsync(state->fd);
1046 } while ((state->ret == -1) && (errno == EINTR));
1048 state->err = errno;
1050 PROFILE_TIMESTAMP(&end_time);
1052 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1055 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1057 return -1;
1060 static void vfs_fsync_done(struct tevent_req *subreq)
1062 struct tevent_req *req = tevent_req_callback_data(
1063 subreq, struct tevent_req);
1064 struct vfswrap_fsync_state *state = tevent_req_data(
1065 req, struct vfswrap_fsync_state);
1066 int ret;
1068 ret = pthreadpool_tevent_job_recv(subreq);
1069 TALLOC_FREE(subreq);
1070 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1071 talloc_set_destructor(state, NULL);
1072 if (tevent_req_error(req, ret)) {
1073 return;
1076 tevent_req_done(req);
1079 static int vfswrap_fsync_recv(struct tevent_req *req,
1080 struct vfs_aio_state *vfs_aio_state)
1082 struct vfswrap_fsync_state *state = tevent_req_data(
1083 req, struct vfswrap_fsync_state);
1085 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1086 return -1;
1089 *vfs_aio_state = state->vfs_aio_state;
1090 return state->ret;
1093 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1095 off_t result = 0;
1097 START_PROFILE(syscall_lseek);
1099 /* Cope with 'stat' file opens. */
1100 if (fsp->fh->fd != -1)
1101 result = lseek(fsp->fh->fd, offset, whence);
1104 * We want to maintain the fiction that we can seek
1105 * on a fifo for file system purposes. This allows
1106 * people to set up UNIX fifo's that feed data to Windows
1107 * applications. JRA.
1110 if((result == -1) && (errno == ESPIPE)) {
1111 result = 0;
1112 errno = 0;
1115 END_PROFILE(syscall_lseek);
1116 return result;
1119 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1120 off_t offset, size_t n)
1122 ssize_t result;
1124 START_PROFILE_BYTES(syscall_sendfile, n);
1125 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1126 END_PROFILE_BYTES(syscall_sendfile);
1127 return result;
1130 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1131 int fromfd,
1132 files_struct *tofsp,
1133 off_t offset,
1134 size_t n)
1136 ssize_t result;
1138 START_PROFILE_BYTES(syscall_recvfile, n);
1139 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1140 END_PROFILE_BYTES(syscall_recvfile);
1141 return result;
1144 static int vfswrap_rename(vfs_handle_struct *handle,
1145 const struct smb_filename *smb_fname_src,
1146 const struct smb_filename *smb_fname_dst)
1148 int result = -1;
1150 START_PROFILE(syscall_rename);
1152 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1153 errno = ENOENT;
1154 goto out;
1157 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1159 out:
1160 END_PROFILE(syscall_rename);
1161 return result;
1164 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1166 #ifdef HAVE_FSYNC
1167 int result;
1169 START_PROFILE(syscall_fsync);
1170 result = fsync(fsp->fh->fd);
1171 END_PROFILE(syscall_fsync);
1172 return result;
1173 #else
1174 return 0;
1175 #endif
1178 static int vfswrap_stat(vfs_handle_struct *handle,
1179 struct smb_filename *smb_fname)
1181 int result = -1;
1183 START_PROFILE(syscall_stat);
1185 if (smb_fname->stream_name) {
1186 errno = ENOENT;
1187 goto out;
1190 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1191 lp_fake_directory_create_times(SNUM(handle->conn)));
1192 out:
1193 END_PROFILE(syscall_stat);
1194 return result;
1197 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1199 int result;
1201 START_PROFILE(syscall_fstat);
1202 result = sys_fstat(fsp->fh->fd,
1203 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1204 END_PROFILE(syscall_fstat);
1205 return result;
1208 static int vfswrap_lstat(vfs_handle_struct *handle,
1209 struct smb_filename *smb_fname)
1211 int result = -1;
1213 START_PROFILE(syscall_lstat);
1215 if (smb_fname->stream_name) {
1216 errno = ENOENT;
1217 goto out;
1220 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1221 lp_fake_directory_create_times(SNUM(handle->conn)));
1222 out:
1223 END_PROFILE(syscall_lstat);
1224 return result;
1227 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1228 const char *name,
1229 enum vfs_translate_direction direction,
1230 TALLOC_CTX *mem_ctx,
1231 char **mapped_name)
1233 return NT_STATUS_NONE_MAPPED;
1237 * Implement the default fsctl operation.
1239 static bool vfswrap_logged_ioctl_message = false;
1241 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1242 struct files_struct *fsp,
1243 TALLOC_CTX *ctx,
1244 uint32_t function,
1245 uint16_t req_flags, /* Needed for UNICODE ... */
1246 const uint8_t *_in_data,
1247 uint32_t in_len,
1248 uint8_t **_out_data,
1249 uint32_t max_out_len,
1250 uint32_t *out_len)
1252 const char *in_data = (const char *)_in_data;
1253 char **out_data = (char **)_out_data;
1254 NTSTATUS status;
1256 switch (function) {
1257 case FSCTL_SET_SPARSE:
1259 bool set_sparse = true;
1261 if (in_len >= 1 && in_data[0] == 0) {
1262 set_sparse = false;
1265 status = file_set_sparse(handle->conn, fsp, set_sparse);
1267 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1268 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1269 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1270 nt_errstr(status)));
1272 return status;
1275 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1277 unsigned char objid[16];
1278 char *return_data = NULL;
1280 /* This should return the object-id on this file.
1281 * I think I'll make this be the inode+dev. JRA.
1284 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1285 fsp_fnum_dbg(fsp)));
1287 *out_len = MIN(max_out_len, 64);
1289 /* Hmmm, will this cause problems if less data asked for? */
1290 return_data = talloc_array(ctx, char, 64);
1291 if (return_data == NULL) {
1292 return NT_STATUS_NO_MEMORY;
1295 /* For backwards compatibility only store the dev/inode. */
1296 push_file_id_16(return_data, &fsp->file_id);
1297 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1298 push_file_id_16(return_data+32, &fsp->file_id);
1299 memset(return_data+48, 0, 16);
1300 *out_data = return_data;
1301 return NT_STATUS_OK;
1304 case FSCTL_GET_REPARSE_POINT:
1306 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1307 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1308 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1309 return NT_STATUS_NOT_A_REPARSE_POINT;
1312 case FSCTL_SET_REPARSE_POINT:
1314 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1315 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1316 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1317 return NT_STATUS_NOT_A_REPARSE_POINT;
1320 case FSCTL_GET_SHADOW_COPY_DATA:
1323 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1324 * and return their volume names. If max_data_count is 16, then it is just
1325 * asking for the number of volumes and length of the combined names.
1327 * pdata is the data allocated by our caller, but that uses
1328 * total_data_count (which is 0 in our case) rather than max_data_count.
1329 * Allocate the correct amount and return the pointer to let
1330 * it be deallocated when we return.
1332 struct shadow_copy_data *shadow_data = NULL;
1333 bool labels = False;
1334 uint32_t labels_data_count = 0;
1335 uint32_t i;
1336 char *cur_pdata = NULL;
1338 if (max_out_len < 16) {
1339 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1340 max_out_len));
1341 return NT_STATUS_INVALID_PARAMETER;
1344 if (max_out_len > 16) {
1345 labels = True;
1348 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1349 if (shadow_data == NULL) {
1350 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1351 return NT_STATUS_NO_MEMORY;
1355 * Call the VFS routine to actually do the work.
1357 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1358 int log_lev = 0;
1359 if (errno == 0) {
1360 /* broken module didn't set errno on error */
1361 status = NT_STATUS_UNSUCCESSFUL;
1362 } else {
1363 status = map_nt_error_from_unix(errno);
1364 if (NT_STATUS_EQUAL(status,
1365 NT_STATUS_NOT_SUPPORTED)) {
1366 log_lev = 5;
1369 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1370 "connectpath %s, failed - %s.\n",
1371 fsp->conn->connectpath,
1372 nt_errstr(status)));
1373 TALLOC_FREE(shadow_data);
1374 return status;
1377 labels_data_count = (shadow_data->num_volumes * 2 *
1378 sizeof(SHADOW_COPY_LABEL)) + 2;
1380 if (!labels) {
1381 *out_len = 16;
1382 } else {
1383 *out_len = 12 + labels_data_count;
1386 if (max_out_len < *out_len) {
1387 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1388 max_out_len, *out_len));
1389 TALLOC_FREE(shadow_data);
1390 return NT_STATUS_BUFFER_TOO_SMALL;
1393 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1394 if (cur_pdata == NULL) {
1395 TALLOC_FREE(shadow_data);
1396 return NT_STATUS_NO_MEMORY;
1399 *out_data = cur_pdata;
1401 /* num_volumes 4 bytes */
1402 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1404 if (labels) {
1405 /* num_labels 4 bytes */
1406 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1409 /* needed_data_count 4 bytes */
1410 SIVAL(cur_pdata, 8, labels_data_count);
1412 cur_pdata += 12;
1414 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1415 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1416 if (labels && shadow_data->labels) {
1417 for (i=0; i<shadow_data->num_volumes; i++) {
1418 size_t len = 0;
1419 status = srvstr_push(cur_pdata, req_flags,
1420 cur_pdata, shadow_data->labels[i],
1421 2 * sizeof(SHADOW_COPY_LABEL),
1422 STR_UNICODE|STR_TERMINATE, &len);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 TALLOC_FREE(*out_data);
1425 TALLOC_FREE(shadow_data);
1426 return status;
1428 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1429 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1433 TALLOC_FREE(shadow_data);
1435 return NT_STATUS_OK;
1438 case FSCTL_FIND_FILES_BY_SID:
1440 /* pretend this succeeded -
1442 * we have to send back a list with all files owned by this SID
1444 * but I have to check that --metze
1446 struct dom_sid sid;
1447 uid_t uid;
1448 size_t sid_len;
1450 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1451 fsp_fnum_dbg(fsp)));
1453 if (in_len < 8) {
1454 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1455 return NT_STATUS_INVALID_PARAMETER;
1458 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1460 /* unknown 4 bytes: this is not the length of the sid :-( */
1461 /*unknown = IVAL(pdata,0);*/
1463 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1464 return NT_STATUS_INVALID_PARAMETER;
1466 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1468 if (!sid_to_uid(&sid, &uid)) {
1469 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1470 sid_string_dbg(&sid),
1471 (unsigned long)sid_len));
1472 uid = (-1);
1475 /* we can take a look at the find source :-)
1477 * find ./ -uid $uid -name '*' is what we need here
1480 * and send 4bytes len and then NULL terminated unicode strings
1481 * for each file
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 * but I don't know how to deal with the paged results
1487 * (maybe we can hang the result anywhere in the fsp struct)
1489 * we don't send all files at once
1490 * and at the next we should *not* start from the beginning,
1491 * so we have to cache the result
1493 * --metze
1496 /* this works for now... */
1497 return NT_STATUS_OK;
1500 case FSCTL_QUERY_ALLOCATED_RANGES:
1502 /* FIXME: This is just a dummy reply, telling that all of the
1503 * file is allocated. MKS cp needs that.
1504 * Adding the real allocated ranges via FIEMAP on Linux
1505 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1506 * this FSCTL correct for sparse files.
1508 uint64_t offset, length;
1509 char *out_data_tmp = NULL;
1511 if (in_len != 16) {
1512 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1513 in_len));
1514 return NT_STATUS_INVALID_PARAMETER;
1517 if (max_out_len < 16) {
1518 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1519 max_out_len));
1520 return NT_STATUS_INVALID_PARAMETER;
1523 offset = BVAL(in_data,0);
1524 length = BVAL(in_data,8);
1526 if (offset + length < offset) {
1527 /* No 64-bit integer wrap. */
1528 return NT_STATUS_INVALID_PARAMETER;
1531 /* Shouldn't this be SMB_VFS_STAT ... ? */
1532 status = vfs_stat_fsp(fsp);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 return status;
1537 *out_len = 16;
1538 out_data_tmp = talloc_array(ctx, char, *out_len);
1539 if (out_data_tmp == NULL) {
1540 DEBUG(10, ("unable to allocate memory for response\n"));
1541 return NT_STATUS_NO_MEMORY;
1544 if (offset > fsp->fsp_name->st.st_ex_size ||
1545 fsp->fsp_name->st.st_ex_size == 0 ||
1546 length == 0) {
1547 memset(out_data_tmp, 0, *out_len);
1548 } else {
1549 uint64_t end = offset + length;
1550 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1551 SBVAL(out_data_tmp, 0, 0);
1552 SBVAL(out_data_tmp, 8, end);
1555 *out_data = out_data_tmp;
1557 return NT_STATUS_OK;
1560 case FSCTL_IS_VOLUME_DIRTY:
1562 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1563 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1565 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1566 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1568 return NT_STATUS_INVALID_PARAMETER;
1571 default:
1573 * Only print once ... unfortunately there could be lots of
1574 * different FSCTLs that are called.
1576 if (!vfswrap_logged_ioctl_message) {
1577 vfswrap_logged_ioctl_message = true;
1578 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1579 __func__, function));
1583 return NT_STATUS_NOT_SUPPORTED;
1586 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1587 const struct smb_filename *fname,
1588 SMB_STRUCT_STAT *sbuf);
1590 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1591 struct smb_filename *smb_fname,
1592 uint32_t *dosmode)
1594 bool offline;
1596 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1597 if (offline) {
1598 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1601 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1604 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1605 struct files_struct *fsp,
1606 uint32_t *dosmode)
1608 bool offline;
1610 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1611 if (offline) {
1612 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1615 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1618 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1619 const struct smb_filename *smb_fname,
1620 uint32_t dosmode)
1622 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1625 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1626 struct files_struct *fsp,
1627 uint32_t dosmode)
1629 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1632 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1634 struct vfswrap_offload_read_state {
1635 DATA_BLOB token;
1638 static struct tevent_req *vfswrap_offload_read_send(
1639 TALLOC_CTX *mem_ctx,
1640 struct tevent_context *ev,
1641 struct vfs_handle_struct *handle,
1642 struct files_struct *fsp,
1643 uint32_t fsctl,
1644 uint32_t ttl,
1645 off_t offset,
1646 size_t to_copy)
1648 struct tevent_req *req = NULL;
1649 struct vfswrap_offload_read_state *state = NULL;
1650 NTSTATUS status;
1652 req = tevent_req_create(mem_ctx, &state,
1653 struct vfswrap_offload_read_state);
1654 if (req == NULL) {
1655 return NULL;
1658 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1659 &vfswrap_offload_ctx);
1660 if (tevent_req_nterror(req, status)) {
1661 return tevent_req_post(req, ev);
1664 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1665 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1666 return tevent_req_post(req, ev);
1669 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1670 &state->token);
1671 if (tevent_req_nterror(req, status)) {
1672 return tevent_req_post(req, ev);
1675 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1676 &state->token);
1677 if (tevent_req_nterror(req, status)) {
1678 return tevent_req_post(req, ev);
1681 tevent_req_done(req);
1682 return tevent_req_post(req, ev);
1685 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1686 struct vfs_handle_struct *handle,
1687 TALLOC_CTX *mem_ctx,
1688 DATA_BLOB *token)
1690 struct vfswrap_offload_read_state *state = tevent_req_data(
1691 req, struct vfswrap_offload_read_state);
1692 NTSTATUS status;
1694 if (tevent_req_is_nterror(req, &status)) {
1695 tevent_req_received(req);
1696 return status;
1699 token->length = state->token.length;
1700 token->data = talloc_move(mem_ctx, &state->token.data);
1702 tevent_req_received(req);
1703 return NT_STATUS_OK;
1706 struct vfswrap_offload_write_state {
1707 struct tevent_context *ev;
1708 uint8_t *buf;
1709 bool read_lck_locked;
1710 bool write_lck_locked;
1711 DATA_BLOB *token;
1712 struct files_struct *src_fsp;
1713 off_t src_off;
1714 struct files_struct *dst_fsp;
1715 off_t dst_off;
1716 off_t to_copy;
1717 off_t remaining;
1718 size_t next_io_size;
1721 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1723 static struct tevent_req *vfswrap_offload_write_send(
1724 struct vfs_handle_struct *handle,
1725 TALLOC_CTX *mem_ctx,
1726 struct tevent_context *ev,
1727 uint32_t fsctl,
1728 DATA_BLOB *token,
1729 off_t transfer_offset,
1730 struct files_struct *dest_fsp,
1731 off_t dest_off,
1732 off_t to_copy)
1734 struct tevent_req *req;
1735 struct vfswrap_offload_write_state *state = NULL;
1736 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1737 files_struct *src_fsp = NULL;
1738 NTSTATUS status;
1740 req = tevent_req_create(mem_ctx, &state,
1741 struct vfswrap_offload_write_state);
1742 if (req == NULL) {
1743 return NULL;
1746 *state = (struct vfswrap_offload_write_state) {
1747 .ev = ev,
1748 .token = token,
1749 .src_off = transfer_offset,
1750 .dst_fsp = dest_fsp,
1751 .dst_off = dest_off,
1752 .to_copy = to_copy,
1753 .remaining = to_copy,
1756 switch (fsctl) {
1757 case FSCTL_SRV_COPYCHUNK:
1758 case FSCTL_SRV_COPYCHUNK_WRITE:
1759 break;
1761 case FSCTL_OFFLOAD_WRITE:
1762 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1763 return tevent_req_post(req, ev);
1765 case FSCTL_DUP_EXTENTS_TO_FILE:
1766 DBG_DEBUG("COW clones not supported by vfs_default\n");
1767 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1768 return tevent_req_post(req, ev);
1770 default:
1771 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1772 return tevent_req_post(req, ev);
1776 * From here on we assume a copy-chunk fsctl
1779 if (to_copy == 0) {
1780 tevent_req_done(req);
1781 return tevent_req_post(req, ev);
1784 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1785 token, &src_fsp);
1786 if (tevent_req_nterror(req, status)) {
1787 return tevent_req_post(req, ev);
1789 state->src_fsp = src_fsp;
1791 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1793 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1794 if (!NT_STATUS_IS_OK(status)) {
1795 tevent_req_nterror(req, status);
1796 return tevent_req_post(req, ev);
1799 state->buf = talloc_array(state, uint8_t, num);
1800 if (tevent_req_nomem(state->buf, req)) {
1801 return tevent_req_post(req, ev);
1804 status = vfs_stat_fsp(src_fsp);
1805 if (tevent_req_nterror(req, status)) {
1806 return tevent_req_post(req, ev);
1809 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1811 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1812 * If the SourceOffset or SourceOffset + Length extends beyond
1813 * the end of file, the server SHOULD<240> treat this as a
1814 * STATUS_END_OF_FILE error.
1815 * ...
1816 * <240> Section 3.3.5.15.6: Windows servers will return
1817 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1819 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1820 return tevent_req_post(req, ev);
1823 if (src_fsp->op == NULL) {
1824 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1825 return tevent_req_post(req, ev);
1828 if (dest_fsp->op == NULL) {
1829 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1830 return tevent_req_post(req, ev);
1833 status = vfswrap_offload_write_loop(req);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 tevent_req_nterror(req, status);
1836 return tevent_req_post(req, ev);
1839 return req;
1842 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1844 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1846 struct vfswrap_offload_write_state *state = tevent_req_data(
1847 req, struct vfswrap_offload_write_state);
1848 struct tevent_req *subreq = NULL;
1849 struct lock_struct read_lck;
1850 bool ok;
1852 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1854 init_strict_lock_struct(state->src_fsp,
1855 state->src_fsp->op->global->open_persistent_id,
1856 state->src_off,
1857 state->next_io_size,
1858 READ_LOCK,
1859 &read_lck);
1861 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
1862 state->src_fsp,
1863 &read_lck);
1864 if (!ok) {
1865 return NT_STATUS_FILE_LOCK_CONFLICT;
1868 subreq = SMB_VFS_PREAD_SEND(state,
1869 state->src_fsp->conn->sconn->ev_ctx,
1870 state->src_fsp,
1871 state->buf,
1872 state->next_io_size,
1873 state->src_off);
1874 if (subreq == NULL) {
1875 return NT_STATUS_NO_MEMORY;
1877 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1879 return NT_STATUS_OK;
1882 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1884 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1886 struct tevent_req *req = tevent_req_callback_data(
1887 subreq, struct tevent_req);
1888 struct vfswrap_offload_write_state *state = tevent_req_data(
1889 req, struct vfswrap_offload_write_state);
1890 struct vfs_aio_state aio_state;
1891 struct lock_struct write_lck;
1892 ssize_t nread;
1893 bool ok;
1895 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1896 TALLOC_FREE(subreq);
1897 if (nread == -1) {
1898 DBG_ERR("read failed: %s\n", strerror(errno));
1899 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1900 return;
1902 if (nread != state->next_io_size) {
1903 DBG_ERR("Short read, only %zd of %zu\n",
1904 nread, state->next_io_size);
1905 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1906 return;
1909 state->src_off += nread;
1911 init_strict_lock_struct(state->dst_fsp,
1912 state->dst_fsp->op->global->open_persistent_id,
1913 state->dst_off,
1914 state->next_io_size,
1915 WRITE_LOCK,
1916 &write_lck);
1918 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
1919 state->dst_fsp,
1920 &write_lck);
1921 if (!ok) {
1922 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1923 return;
1926 subreq = SMB_VFS_PWRITE_SEND(state,
1927 state->ev,
1928 state->dst_fsp,
1929 state->buf,
1930 state->next_io_size,
1931 state->dst_off);
1932 if (subreq == NULL) {
1933 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1934 return;
1936 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1939 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1941 struct tevent_req *req = tevent_req_callback_data(
1942 subreq, struct tevent_req);
1943 struct vfswrap_offload_write_state *state = tevent_req_data(
1944 req, struct vfswrap_offload_write_state);
1945 struct vfs_aio_state aio_state;
1946 ssize_t nwritten;
1947 NTSTATUS status;
1949 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1950 TALLOC_FREE(subreq);
1951 if (nwritten == -1) {
1952 DBG_ERR("write failed: %s\n", strerror(errno));
1953 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1954 return;
1956 if (nwritten != state->next_io_size) {
1957 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1958 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1959 return;
1962 state->dst_off += nwritten;
1964 if (state->remaining < nwritten) {
1965 /* Paranoia check */
1966 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1967 return;
1969 state->remaining -= nwritten;
1970 if (state->remaining == 0) {
1971 tevent_req_done(req);
1972 return;
1975 status = vfswrap_offload_write_loop(req);
1976 if (!NT_STATUS_IS_OK(status)) {
1977 tevent_req_nterror(req, status);
1978 return;
1981 return;
1984 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1985 struct tevent_req *req,
1986 off_t *copied)
1988 struct vfswrap_offload_write_state *state = tevent_req_data(
1989 req, struct vfswrap_offload_write_state);
1990 NTSTATUS status;
1992 if (tevent_req_is_nterror(req, &status)) {
1993 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1994 *copied = 0;
1995 tevent_req_received(req);
1996 return status;
1999 *copied = state->to_copy;
2000 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2001 tevent_req_received(req);
2003 return NT_STATUS_OK;
2006 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2007 TALLOC_CTX *mem_ctx,
2008 struct files_struct *fsp,
2009 struct smb_filename *smb_fname,
2010 uint16_t *_compression_fmt)
2012 return NT_STATUS_INVALID_DEVICE_REQUEST;
2015 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2016 TALLOC_CTX *mem_ctx,
2017 struct files_struct *fsp,
2018 uint16_t compression_fmt)
2020 return NT_STATUS_INVALID_DEVICE_REQUEST;
2023 /********************************************************************
2024 Given a stat buffer return the allocated size on disk, taking into
2025 account sparse files.
2026 ********************************************************************/
2027 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2028 struct files_struct *fsp,
2029 const SMB_STRUCT_STAT *sbuf)
2031 uint64_t result;
2033 START_PROFILE(syscall_get_alloc_size);
2035 if(S_ISDIR(sbuf->st_ex_mode)) {
2036 result = 0;
2037 goto out;
2040 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2041 /* The type of st_blocksize is blkcnt_t which *MUST* be
2042 signed (according to POSIX) and can be less than 64-bits.
2043 Ensure when we're converting to 64 bits wide we don't
2044 sign extend. */
2045 #if defined(SIZEOF_BLKCNT_T_8)
2046 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2047 #elif defined(SIZEOF_BLKCNT_T_4)
2049 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2050 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2052 #else
2053 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2054 #endif
2055 if (result == 0) {
2057 * Some file systems do not allocate a block for very
2058 * small files. But for non-empty file should report a
2059 * positive size.
2062 uint64_t filesize = get_file_size_stat(sbuf);
2063 if (filesize > 0) {
2064 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2067 #else
2068 result = get_file_size_stat(sbuf);
2069 #endif
2071 if (fsp && fsp->initial_allocation_size)
2072 result = MAX(result,fsp->initial_allocation_size);
2074 result = smb_roundup(handle->conn, result);
2076 out:
2077 END_PROFILE(syscall_get_alloc_size);
2078 return result;
2081 static int vfswrap_unlink(vfs_handle_struct *handle,
2082 const struct smb_filename *smb_fname)
2084 int result = -1;
2086 START_PROFILE(syscall_unlink);
2088 if (smb_fname->stream_name) {
2089 errno = ENOENT;
2090 goto out;
2092 result = unlink(smb_fname->base_name);
2094 out:
2095 END_PROFILE(syscall_unlink);
2096 return result;
2099 static int vfswrap_chmod(vfs_handle_struct *handle,
2100 const struct smb_filename *smb_fname,
2101 mode_t mode)
2103 int result;
2105 START_PROFILE(syscall_chmod);
2108 * We need to do this due to the fact that the default POSIX ACL
2109 * chmod modifies the ACL *mask* for the group owner, not the
2110 * group owner bits directly. JRA.
2115 int saved_errno = errno; /* We might get ENOSYS */
2116 result = SMB_VFS_CHMOD_ACL(handle->conn,
2117 smb_fname,
2118 mode);
2119 if (result == 0) {
2120 END_PROFILE(syscall_chmod);
2121 return result;
2123 /* Error - return the old errno. */
2124 errno = saved_errno;
2127 result = chmod(smb_fname->base_name, mode);
2128 END_PROFILE(syscall_chmod);
2129 return result;
2132 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2134 int result;
2136 START_PROFILE(syscall_fchmod);
2139 * We need to do this due to the fact that the default POSIX ACL
2140 * chmod modifies the ACL *mask* for the group owner, not the
2141 * group owner bits directly. JRA.
2145 int saved_errno = errno; /* We might get ENOSYS */
2146 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2147 END_PROFILE(syscall_fchmod);
2148 return result;
2150 /* Error - return the old errno. */
2151 errno = saved_errno;
2154 #if defined(HAVE_FCHMOD)
2155 result = fchmod(fsp->fh->fd, mode);
2156 #else
2157 result = -1;
2158 errno = ENOSYS;
2159 #endif
2161 END_PROFILE(syscall_fchmod);
2162 return result;
2165 static int vfswrap_chown(vfs_handle_struct *handle,
2166 const struct smb_filename *smb_fname,
2167 uid_t uid,
2168 gid_t gid)
2170 int result;
2172 START_PROFILE(syscall_chown);
2173 result = chown(smb_fname->base_name, uid, gid);
2174 END_PROFILE(syscall_chown);
2175 return result;
2178 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2180 #ifdef HAVE_FCHOWN
2181 int result;
2183 START_PROFILE(syscall_fchown);
2184 result = fchown(fsp->fh->fd, uid, gid);
2185 END_PROFILE(syscall_fchown);
2186 return result;
2187 #else
2188 errno = ENOSYS;
2189 return -1;
2190 #endif
2193 static int vfswrap_lchown(vfs_handle_struct *handle,
2194 const struct smb_filename *smb_fname,
2195 uid_t uid,
2196 gid_t gid)
2198 int result;
2200 START_PROFILE(syscall_lchown);
2201 result = lchown(smb_fname->base_name, uid, gid);
2202 END_PROFILE(syscall_lchown);
2203 return result;
2206 static int vfswrap_chdir(vfs_handle_struct *handle,
2207 const struct smb_filename *smb_fname)
2209 int result;
2211 START_PROFILE(syscall_chdir);
2212 result = chdir(smb_fname->base_name);
2213 END_PROFILE(syscall_chdir);
2214 return result;
2217 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2218 TALLOC_CTX *ctx)
2220 char *result;
2221 struct smb_filename *smb_fname = NULL;
2223 START_PROFILE(syscall_getwd);
2224 result = sys_getwd();
2225 END_PROFILE(syscall_getwd);
2226 smb_fname = synthetic_smb_fname(ctx,
2227 result,
2228 NULL,
2229 NULL,
2231 if (smb_fname == NULL) {
2232 SAFE_FREE(result);
2234 return smb_fname;
2237 /*********************************************************************
2238 nsec timestamp resolution call. Convert down to whatever the underlying
2239 system will support.
2240 **********************************************************************/
2242 static int vfswrap_ntimes(vfs_handle_struct *handle,
2243 const struct smb_filename *smb_fname,
2244 struct smb_file_time *ft)
2246 int result = -1;
2248 START_PROFILE(syscall_ntimes);
2250 if (smb_fname->stream_name) {
2251 errno = ENOENT;
2252 goto out;
2255 if (ft != NULL) {
2256 if (null_timespec(ft->atime)) {
2257 ft->atime= smb_fname->st.st_ex_atime;
2260 if (null_timespec(ft->mtime)) {
2261 ft->mtime = smb_fname->st.st_ex_mtime;
2264 if (!null_timespec(ft->create_time)) {
2265 set_create_timespec_ea(handle->conn,
2266 smb_fname,
2267 ft->create_time);
2270 if ((timespec_compare(&ft->atime,
2271 &smb_fname->st.st_ex_atime) == 0) &&
2272 (timespec_compare(&ft->mtime,
2273 &smb_fname->st.st_ex_mtime) == 0)) {
2274 return 0;
2278 #if defined(HAVE_UTIMENSAT)
2279 if (ft != NULL) {
2280 struct timespec ts[2];
2281 ts[0] = ft->atime;
2282 ts[1] = ft->mtime;
2283 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2284 } else {
2285 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2287 if (!((result == -1) && (errno == ENOSYS))) {
2288 goto out;
2290 #endif
2291 #if defined(HAVE_UTIMES)
2292 if (ft != NULL) {
2293 struct timeval tv[2];
2294 tv[0] = convert_timespec_to_timeval(ft->atime);
2295 tv[1] = convert_timespec_to_timeval(ft->mtime);
2296 result = utimes(smb_fname->base_name, tv);
2297 } else {
2298 result = utimes(smb_fname->base_name, NULL);
2300 if (!((result == -1) && (errno == ENOSYS))) {
2301 goto out;
2303 #endif
2304 #if defined(HAVE_UTIME)
2305 if (ft != NULL) {
2306 struct utimbuf times;
2307 times.actime = convert_timespec_to_time_t(ft->atime);
2308 times.modtime = convert_timespec_to_time_t(ft->mtime);
2309 result = utime(smb_fname->base_name, &times);
2310 } else {
2311 result = utime(smb_fname->base_name, NULL);
2313 if (!((result == -1) && (errno == ENOSYS))) {
2314 goto out;
2316 #endif
2317 errno = ENOSYS;
2318 result = -1;
2320 out:
2321 END_PROFILE(syscall_ntimes);
2322 return result;
2325 /*********************************************************************
2326 A version of ftruncate that will write the space on disk if strict
2327 allocate is set.
2328 **********************************************************************/
2330 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2332 off_t space_to_write;
2333 uint64_t space_avail;
2334 uint64_t bsize,dfree,dsize;
2335 int ret;
2336 NTSTATUS status;
2337 SMB_STRUCT_STAT *pst;
2339 status = vfs_stat_fsp(fsp);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 return -1;
2343 pst = &fsp->fsp_name->st;
2345 #ifdef S_ISFIFO
2346 if (S_ISFIFO(pst->st_ex_mode))
2347 return 0;
2348 #endif
2350 if (pst->st_ex_size == len)
2351 return 0;
2353 /* Shrink - just ftruncate. */
2354 if (pst->st_ex_size > len)
2355 return ftruncate(fsp->fh->fd, len);
2357 space_to_write = len - pst->st_ex_size;
2359 /* for allocation try fallocate first. This can fail on some
2360 platforms e.g. when the filesystem doesn't support it and no
2361 emulation is being done by the libc (like on AIX with JFS1). In that
2362 case we do our own emulation. fallocate implementations can
2363 return ENOTSUP or EINVAL in cases like that. */
2364 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2365 if (ret == -1 && errno == ENOSPC) {
2366 return -1;
2368 if (ret == 0) {
2369 return 0;
2371 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2372 "error %d. Falling back to slow manual allocation\n", errno));
2374 /* available disk space is enough or not? */
2375 space_avail =
2376 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2377 /* space_avail is 1k blocks */
2378 if (space_avail == (uint64_t)-1 ||
2379 ((uint64_t)space_to_write/1024 > space_avail) ) {
2380 errno = ENOSPC;
2381 return -1;
2384 /* Write out the real space on disk. */
2385 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2386 if (ret != 0) {
2387 return -1;
2390 return 0;
2393 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2395 int result = -1;
2396 SMB_STRUCT_STAT *pst;
2397 NTSTATUS status;
2398 char c = 0;
2400 START_PROFILE(syscall_ftruncate);
2402 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2403 result = strict_allocate_ftruncate(handle, fsp, len);
2404 END_PROFILE(syscall_ftruncate);
2405 return result;
2408 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2409 ftruncate if the system supports it. Then I discovered that
2410 you can have some filesystems that support ftruncate
2411 expansion and some that don't! On Linux fat can't do
2412 ftruncate extend but ext2 can. */
2414 result = ftruncate(fsp->fh->fd, len);
2416 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2417 extend a file with ftruncate. Provide alternate implementation
2418 for this */
2420 /* Do an fstat to see if the file is longer than the requested
2421 size in which case the ftruncate above should have
2422 succeeded or shorter, in which case seek to len - 1 and
2423 write 1 byte of zero */
2424 status = vfs_stat_fsp(fsp);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 goto done;
2429 /* We need to update the files_struct after successful ftruncate */
2430 if (result == 0) {
2431 goto done;
2434 pst = &fsp->fsp_name->st;
2436 #ifdef S_ISFIFO
2437 if (S_ISFIFO(pst->st_ex_mode)) {
2438 result = 0;
2439 goto done;
2441 #endif
2443 if (pst->st_ex_size == len) {
2444 result = 0;
2445 goto done;
2448 if (pst->st_ex_size > len) {
2449 /* the ftruncate should have worked */
2450 goto done;
2453 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2454 goto done;
2457 result = 0;
2459 done:
2461 END_PROFILE(syscall_ftruncate);
2462 return result;
2465 static int vfswrap_fallocate(vfs_handle_struct *handle,
2466 files_struct *fsp,
2467 uint32_t mode,
2468 off_t offset,
2469 off_t len)
2471 int result;
2473 START_PROFILE(syscall_fallocate);
2474 if (mode == 0) {
2475 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2477 * posix_fallocate returns 0 on success, errno on error
2478 * and doesn't set errno. Make it behave like fallocate()
2479 * which returns -1, and sets errno on failure.
2481 if (result != 0) {
2482 errno = result;
2483 result = -1;
2485 } else {
2486 /* sys_fallocate handles filtering of unsupported mode flags */
2487 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2489 END_PROFILE(syscall_fallocate);
2490 return result;
2493 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2495 bool result;
2497 START_PROFILE(syscall_fcntl_lock);
2499 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2500 "smbd",
2501 "force process locks",
2502 false)) {
2503 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2506 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2507 END_PROFILE(syscall_fcntl_lock);
2508 return result;
2511 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2512 uint32_t share_mode, uint32_t access_mask)
2514 START_PROFILE(syscall_kernel_flock);
2515 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2516 END_PROFILE(syscall_kernel_flock);
2517 return 0;
2520 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2522 bool result;
2523 int op = F_GETLK;
2525 START_PROFILE(syscall_fcntl_getlock);
2527 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2528 "smbd",
2529 "force process locks",
2530 false)) {
2531 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2534 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2535 END_PROFILE(syscall_fcntl_getlock);
2536 return result;
2539 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2540 int leasetype)
2542 int result = -1;
2544 START_PROFILE(syscall_linux_setlease);
2546 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2547 result = linux_setlease(fsp->fh->fd, leasetype);
2548 #else
2549 errno = ENOSYS;
2550 #endif
2551 END_PROFILE(syscall_linux_setlease);
2552 return result;
2555 static int vfswrap_symlink(vfs_handle_struct *handle,
2556 const char *link_target,
2557 const struct smb_filename *new_smb_fname)
2559 int result;
2561 START_PROFILE(syscall_symlink);
2562 result = symlink(link_target, new_smb_fname->base_name);
2563 END_PROFILE(syscall_symlink);
2564 return result;
2567 static int vfswrap_readlink(vfs_handle_struct *handle,
2568 const struct smb_filename *smb_fname,
2569 char *buf,
2570 size_t bufsiz)
2572 int result;
2574 START_PROFILE(syscall_readlink);
2575 result = readlink(smb_fname->base_name, buf, bufsiz);
2576 END_PROFILE(syscall_readlink);
2577 return result;
2580 static int vfswrap_link(vfs_handle_struct *handle,
2581 const struct smb_filename *old_smb_fname,
2582 const struct smb_filename *new_smb_fname)
2584 int result;
2586 START_PROFILE(syscall_link);
2587 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2588 END_PROFILE(syscall_link);
2589 return result;
2592 static int vfswrap_mknod(vfs_handle_struct *handle,
2593 const struct smb_filename *smb_fname,
2594 mode_t mode,
2595 SMB_DEV_T dev)
2597 int result;
2599 START_PROFILE(syscall_mknod);
2600 result = sys_mknod(smb_fname->base_name, mode, dev);
2601 END_PROFILE(syscall_mknod);
2602 return result;
2605 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2606 TALLOC_CTX *ctx,
2607 const struct smb_filename *smb_fname)
2609 char *result;
2610 struct smb_filename *result_fname = NULL;
2612 START_PROFILE(syscall_realpath);
2613 result = sys_realpath(smb_fname->base_name);
2614 END_PROFILE(syscall_realpath);
2615 if (result) {
2616 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2617 SAFE_FREE(result);
2619 return result_fname;
2622 static int vfswrap_chflags(vfs_handle_struct *handle,
2623 const struct smb_filename *smb_fname,
2624 unsigned int flags)
2626 #ifdef HAVE_CHFLAGS
2627 return chflags(smb_fname->base_name, flags);
2628 #else
2629 errno = ENOSYS;
2630 return -1;
2631 #endif
2634 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2635 const SMB_STRUCT_STAT *sbuf)
2637 struct file_id key;
2639 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2640 * blob */
2641 ZERO_STRUCT(key);
2643 key.devid = sbuf->st_ex_dev;
2644 key.inode = sbuf->st_ex_ino;
2645 /* key.extid is unused by default. */
2647 return key;
2650 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2651 struct files_struct *fsp,
2652 const struct smb_filename *smb_fname,
2653 TALLOC_CTX *mem_ctx,
2654 unsigned int *pnum_streams,
2655 struct stream_struct **pstreams)
2657 SMB_STRUCT_STAT sbuf;
2658 struct stream_struct *tmp_streams = NULL;
2659 int ret;
2661 if ((fsp != NULL) && (fsp->is_directory)) {
2663 * No default streams on directories
2665 goto done;
2668 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2669 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2671 else {
2672 struct smb_filename smb_fname_cp;
2674 ZERO_STRUCT(smb_fname_cp);
2675 smb_fname_cp.base_name = discard_const_p(char,
2676 smb_fname->base_name);
2677 smb_fname_cp.flags = smb_fname->flags;
2679 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2680 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2681 } else {
2682 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2684 sbuf = smb_fname_cp.st;
2687 if (ret == -1) {
2688 return map_nt_error_from_unix(errno);
2691 if (S_ISDIR(sbuf.st_ex_mode)) {
2692 goto done;
2695 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2696 (*pnum_streams) + 1);
2697 if (tmp_streams == NULL) {
2698 return NT_STATUS_NO_MEMORY;
2700 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2701 if (tmp_streams[*pnum_streams].name == NULL) {
2702 return NT_STATUS_NO_MEMORY;
2704 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2705 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2707 *pnum_streams += 1;
2708 *pstreams = tmp_streams;
2709 done:
2710 return NT_STATUS_OK;
2713 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2714 const char *path,
2715 const char *name,
2716 TALLOC_CTX *mem_ctx,
2717 char **found_name)
2720 * Don't fall back to get_real_filename so callers can differentiate
2721 * between a full directory scan and an actual case-insensitive stat.
2723 errno = EOPNOTSUPP;
2724 return -1;
2727 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2728 const struct smb_filename *smb_fname)
2730 return handle->conn->connectpath;
2733 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2734 struct byte_range_lock *br_lck,
2735 struct lock_struct *plock,
2736 bool blocking_lock)
2738 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2740 /* Note: blr is not used in the default implementation. */
2741 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2744 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2745 struct messaging_context *msg_ctx,
2746 struct byte_range_lock *br_lck,
2747 const struct lock_struct *plock)
2749 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2751 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2754 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2755 struct byte_range_lock *br_lck,
2756 struct lock_struct *plock)
2758 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2760 /* Note: blr is not used in the default implementation. */
2761 return brl_lock_cancel_default(br_lck, plock);
2764 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2765 files_struct *fsp,
2766 struct lock_struct *plock)
2768 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2769 plock->lock_type == WRITE_LOCK);
2771 return strict_lock_check_default(fsp, plock);
2774 /* NT ACL operations. */
2776 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2777 files_struct *fsp,
2778 uint32_t security_info,
2779 TALLOC_CTX *mem_ctx,
2780 struct security_descriptor **ppdesc)
2782 NTSTATUS result;
2784 START_PROFILE(fget_nt_acl);
2785 result = posix_fget_nt_acl(fsp, security_info,
2786 mem_ctx, ppdesc);
2787 END_PROFILE(fget_nt_acl);
2788 return result;
2791 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2792 const struct smb_filename *smb_fname,
2793 uint32_t security_info,
2794 TALLOC_CTX *mem_ctx,
2795 struct security_descriptor **ppdesc)
2797 NTSTATUS result;
2799 START_PROFILE(get_nt_acl);
2800 result = posix_get_nt_acl(handle->conn,
2801 smb_fname,
2802 security_info,
2803 mem_ctx,
2804 ppdesc);
2805 END_PROFILE(get_nt_acl);
2806 return result;
2809 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2811 NTSTATUS result;
2813 START_PROFILE(fset_nt_acl);
2814 result = set_nt_acl(fsp, security_info_sent, psd);
2815 END_PROFILE(fset_nt_acl);
2816 return result;
2819 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2820 struct smb_filename *file,
2821 struct security_acl *sacl,
2822 uint32_t access_requested,
2823 uint32_t access_denied)
2825 return NT_STATUS_OK; /* Nothing to do here ... */
2828 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2829 const struct smb_filename *smb_fname,
2830 mode_t mode)
2832 #ifdef HAVE_NO_ACL
2833 errno = ENOSYS;
2834 return -1;
2835 #else
2836 int result;
2838 START_PROFILE(chmod_acl);
2839 result = chmod_acl(handle->conn, smb_fname, mode);
2840 END_PROFILE(chmod_acl);
2841 return result;
2842 #endif
2845 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2847 #ifdef HAVE_NO_ACL
2848 errno = ENOSYS;
2849 return -1;
2850 #else
2851 int result;
2853 START_PROFILE(fchmod_acl);
2854 result = fchmod_acl(fsp, mode);
2855 END_PROFILE(fchmod_acl);
2856 return result;
2857 #endif
2860 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2861 const struct smb_filename *smb_fname,
2862 SMB_ACL_TYPE_T type,
2863 TALLOC_CTX *mem_ctx)
2865 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2868 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2869 files_struct *fsp,
2870 TALLOC_CTX *mem_ctx)
2872 return sys_acl_get_fd(handle, fsp, mem_ctx);
2875 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2876 const struct smb_filename *smb_fname,
2877 SMB_ACL_TYPE_T acltype,
2878 SMB_ACL_T theacl)
2880 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2883 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2885 return sys_acl_set_fd(handle, fsp, theacl);
2888 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2889 const struct smb_filename *smb_fname)
2891 return sys_acl_delete_def_file(handle, smb_fname);
2894 /****************************************************************
2895 Extended attribute operations.
2896 *****************************************************************/
2898 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2899 const struct smb_filename *smb_fname,
2900 const char *name,
2901 void *value,
2902 size_t size)
2904 return getxattr(smb_fname->base_name, name, value, size);
2907 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2909 return fgetxattr(fsp->fh->fd, name, value, size);
2912 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2913 const struct smb_filename *smb_fname,
2914 char *list,
2915 size_t size)
2917 return listxattr(smb_fname->base_name, list, size);
2920 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2922 return flistxattr(fsp->fh->fd, list, size);
2925 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2926 const struct smb_filename *smb_fname,
2927 const char *name)
2929 return removexattr(smb_fname->base_name, name);
2932 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2934 return fremovexattr(fsp->fh->fd, name);
2937 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2938 const struct smb_filename *smb_fname,
2939 const char *name,
2940 const void *value,
2941 size_t size,
2942 int flags)
2944 return setxattr(smb_fname->base_name, name, value, size, flags);
2947 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2949 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2952 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2954 return false;
2957 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2958 const struct smb_filename *fname,
2959 SMB_STRUCT_STAT *sbuf)
2961 NTSTATUS status;
2962 char *path;
2963 bool offline = false;
2965 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2966 return false;
2969 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2970 #if defined(ENOTSUP)
2971 errno = ENOTSUP;
2972 #endif
2973 return false;
2976 status = get_full_smb_filename(talloc_tos(), fname, &path);
2977 if (!NT_STATUS_IS_OK(status)) {
2978 errno = map_errno_from_nt_status(status);
2979 return false;
2982 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2984 TALLOC_FREE(path);
2986 return offline;
2989 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2990 struct files_struct *fsp,
2991 TALLOC_CTX *mem_ctx,
2992 DATA_BLOB *cookie)
2994 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2997 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2998 struct files_struct *fsp,
2999 const DATA_BLOB old_cookie,
3000 TALLOC_CTX *mem_ctx,
3001 DATA_BLOB *new_cookie)
3003 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3004 new_cookie);
3007 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3008 struct smb_request *smb1req,
3009 struct smbXsrv_open *op,
3010 const DATA_BLOB old_cookie,
3011 TALLOC_CTX *mem_ctx,
3012 struct files_struct **fsp,
3013 DATA_BLOB *new_cookie)
3015 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3016 old_cookie, mem_ctx,
3017 fsp, new_cookie);
3020 static struct vfs_fn_pointers vfs_default_fns = {
3021 /* Disk operations */
3023 .connect_fn = vfswrap_connect,
3024 .disconnect_fn = vfswrap_disconnect,
3025 .disk_free_fn = vfswrap_disk_free,
3026 .get_quota_fn = vfswrap_get_quota,
3027 .set_quota_fn = vfswrap_set_quota,
3028 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3029 .statvfs_fn = vfswrap_statvfs,
3030 .fs_capabilities_fn = vfswrap_fs_capabilities,
3031 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3032 .snap_check_path_fn = vfswrap_snap_check_path,
3033 .snap_create_fn = vfswrap_snap_create,
3034 .snap_delete_fn = vfswrap_snap_delete,
3036 /* Directory operations */
3038 .opendir_fn = vfswrap_opendir,
3039 .fdopendir_fn = vfswrap_fdopendir,
3040 .readdir_fn = vfswrap_readdir,
3041 .readdir_attr_fn = vfswrap_readdir_attr,
3042 .seekdir_fn = vfswrap_seekdir,
3043 .telldir_fn = vfswrap_telldir,
3044 .rewind_dir_fn = vfswrap_rewinddir,
3045 .mkdir_fn = vfswrap_mkdir,
3046 .rmdir_fn = vfswrap_rmdir,
3047 .closedir_fn = vfswrap_closedir,
3048 .init_search_op_fn = vfswrap_init_search_op,
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 NTSTATUS vfs_default_init(TALLOC_CTX *);
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);