s3: VFS: Change SMB_VFS_SYS_ACL_DELETE_DEF_FILE to use const struct smb_filename...
[Samba.git] / source3 / modules / vfs_default.c
blob19b6925a3a4090975c0c5496644d0507dcfa50e8
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"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
45 this possibility. */
47 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct *handle)
56 /* Disk operations */
58 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
59 uint64_t *bsize, uint64_t *dfree,
60 uint64_t *dsize)
62 if (sys_fsusage(path, dfree, dsize) != 0) {
63 return (uint64_t)-1;
66 *bsize = 512;
67 return *dfree / 2;
70 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
71 enum SMB_QUOTA_TYPE qtype, unid_t id,
72 SMB_DISK_QUOTA *qt)
74 #ifdef HAVE_SYS_QUOTAS
75 int result;
77 START_PROFILE(syscall_get_quota);
78 result = sys_get_quota(path, qtype, id, qt);
79 END_PROFILE(syscall_get_quota);
80 return result;
81 #else
82 errno = ENOSYS;
83 return -1;
84 #endif
87 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
89 #ifdef HAVE_SYS_QUOTAS
90 int result;
92 START_PROFILE(syscall_set_quota);
93 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
94 END_PROFILE(syscall_set_quota);
95 return result;
96 #else
97 errno = ENOSYS;
98 return -1;
99 #endif
102 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
103 struct files_struct *fsp,
104 struct shadow_copy_data *shadow_copy_data,
105 bool labels)
107 errno = ENOSYS;
108 return -1; /* Not implemented. */
111 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
113 return sys_statvfs(path, statbuf);
116 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
117 enum timestamp_set_resolution *p_ts_res)
119 connection_struct *conn = handle->conn;
120 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
121 struct smb_filename *smb_fname_cpath = NULL;
122 struct vfs_statvfs_struct statbuf;
123 int ret;
125 ZERO_STRUCT(statbuf);
126 ret = sys_statvfs(conn->connectpath, &statbuf);
127 if (ret == 0) {
128 caps = statbuf.FsCapabilities;
131 *p_ts_res = TIMESTAMP_SET_SECONDS;
133 /* Work out what timestamp resolution we can
134 * use when setting a timestamp. */
136 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 NULL, NULL, 0);
138 if (smb_fname_cpath == NULL) {
139 return caps;
142 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 if (ret == -1) {
144 TALLOC_FREE(smb_fname_cpath);
145 return caps;
148 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
150 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
151 /* If any of the normal UNIX directory timestamps
152 * have a non-zero tv_nsec component assume
153 * we might be able to set sub-second timestamps.
154 * See what filetime set primitives we have.
156 #if defined(HAVE_UTIMENSAT)
157 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
158 #elif defined(HAVE_UTIMES)
159 /* utimes allows msec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_MSEC;
161 #elif defined(HAVE_UTIME)
162 /* utime only allows sec timestamps to be set. */
163 *p_ts_res = TIMESTAMP_SET_SECONDS;
164 #endif
166 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "resolution of %s "
168 "available on share %s, directory %s\n",
169 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
170 lp_servicename(talloc_tos(), conn->params->service),
171 conn->connectpath ));
173 TALLOC_FREE(smb_fname_cpath);
174 return caps;
177 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
178 struct dfs_GetDFSReferral *r)
180 struct junction_map *junction = NULL;
181 int consumedcnt = 0;
182 bool self_referral = false;
183 char *pathnamep = NULL;
184 char *local_dfs_path = NULL;
185 NTSTATUS status;
186 int i;
187 uint16_t max_referral_level = r->in.req.max_referral_level;
189 if (DEBUGLVL(10)) {
190 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
193 /* get the junction entry */
194 if (r->in.req.servername == NULL) {
195 return NT_STATUS_NOT_FOUND;
199 * Trim pathname sent by client so it begins with only one backslash.
200 * Two backslashes confuse some dfs clients
203 local_dfs_path = talloc_strdup(r, r->in.req.servername);
204 if (local_dfs_path == NULL) {
205 return NT_STATUS_NO_MEMORY;
207 pathnamep = local_dfs_path;
208 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
209 IS_DIRECTORY_SEP(pathnamep[1])) {
210 pathnamep++;
213 junction = talloc_zero(r, struct junction_map);
214 if (junction == NULL) {
215 return NT_STATUS_NO_MEMORY;
218 /* The following call can change cwd. */
219 status = get_referred_path(r, pathnamep,
220 handle->conn->sconn->remote_address,
221 handle->conn->sconn->local_address,
222 !handle->conn->sconn->using_smb2,
223 junction, &consumedcnt, &self_referral);
224 if (!NT_STATUS_IS_OK(status)) {
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
226 return status;
228 vfs_ChDir(handle->conn, handle->conn->connectpath);
230 if (!self_referral) {
231 pathnamep[consumedcnt] = '\0';
233 if (DEBUGLVL(3)) {
234 dbgtext("Path %s to alternate path(s):",
235 pathnamep);
236 for (i=0; i < junction->referral_count; i++) {
237 dbgtext(" %s",
238 junction->referral_list[i].alternate_path);
240 dbgtext(".\n");
244 if (r->in.req.max_referral_level <= 2) {
245 max_referral_level = 2;
247 if (r->in.req.max_referral_level >= 3) {
248 max_referral_level = 3;
251 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
252 if (r->out.resp == NULL) {
253 return NT_STATUS_NO_MEMORY;
256 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
257 r->out.resp->nb_referrals = junction->referral_count;
259 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
260 if (self_referral) {
261 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
264 r->out.resp->referral_entries = talloc_zero_array(r,
265 struct dfs_referral_type,
266 r->out.resp->nb_referrals);
267 if (r->out.resp->referral_entries == NULL) {
268 return NT_STATUS_NO_MEMORY;
271 switch (max_referral_level) {
272 case 2:
273 for(i=0; i < junction->referral_count; i++) {
274 struct referral *ref = &junction->referral_list[i];
275 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
276 struct dfs_referral_type *t =
277 &r->out.resp->referral_entries[i];
278 struct dfs_referral_v2 *v2 = &t->referral.v2;
280 t->version = 2;
281 v2->size = VERSION2_REFERRAL_SIZE;
282 if (self_referral) {
283 v2->server_type = DFS_SERVER_ROOT;
284 } else {
285 v2->server_type = DFS_SERVER_NON_ROOT;
287 v2->entry_flags = 0;
288 v2->proximity = ref->proximity;
289 v2->ttl = ref->ttl;
290 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
291 if (v2->DFS_path == NULL) {
292 return NT_STATUS_NO_MEMORY;
294 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
295 if (v2->DFS_alt_path == NULL) {
296 return NT_STATUS_NO_MEMORY;
298 v2->netw_address = talloc_strdup(mem_ctx,
299 ref->alternate_path);
300 if (v2->netw_address == NULL) {
301 return NT_STATUS_NO_MEMORY;
305 break;
306 case 3:
307 for(i=0; i < junction->referral_count; i++) {
308 struct referral *ref = &junction->referral_list[i];
309 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
310 struct dfs_referral_type *t =
311 &r->out.resp->referral_entries[i];
312 struct dfs_referral_v3 *v3 = &t->referral.v3;
313 struct dfs_normal_referral *r1 = &v3->referrals.r1;
315 t->version = 3;
316 v3->size = VERSION3_REFERRAL_SIZE;
317 if (self_referral) {
318 v3->server_type = DFS_SERVER_ROOT;
319 } else {
320 v3->server_type = DFS_SERVER_NON_ROOT;
322 v3->entry_flags = 0;
323 v3->ttl = ref->ttl;
324 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
325 if (r1->DFS_path == NULL) {
326 return NT_STATUS_NO_MEMORY;
328 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
329 if (r1->DFS_alt_path == NULL) {
330 return NT_STATUS_NO_MEMORY;
332 r1->netw_address = talloc_strdup(mem_ctx,
333 ref->alternate_path);
334 if (r1->netw_address == NULL) {
335 return NT_STATUS_NO_MEMORY;
338 break;
339 default:
340 DEBUG(0,("Invalid dfs referral version: %d\n",
341 max_referral_level));
342 return NT_STATUS_INVALID_LEVEL;
345 if (DEBUGLVL(10)) {
346 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 return NT_STATUS_OK;
352 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
353 TALLOC_CTX *mem_ctx,
354 const char *service_path,
355 char **base_volume)
357 return NT_STATUS_NOT_SUPPORTED;
360 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
361 TALLOC_CTX *mem_ctx,
362 const char *base_volume,
363 time_t *tstamp,
364 bool rw,
365 char **base_path,
366 char **snap_path)
368 return NT_STATUS_NOT_SUPPORTED;
371 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
372 TALLOC_CTX *mem_ctx,
373 char *base_path,
374 char *snap_path)
376 return NT_STATUS_NOT_SUPPORTED;
379 /* Directory operations */
381 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
382 const struct smb_filename *smb_fname,
383 const char *mask,
384 uint32_t attr)
386 DIR *result;
388 START_PROFILE(syscall_opendir);
389 result = opendir(smb_fname->base_name);
390 END_PROFILE(syscall_opendir);
391 return result;
394 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
395 files_struct *fsp,
396 const char *mask,
397 uint32_t attr)
399 DIR *result;
401 START_PROFILE(syscall_fdopendir);
402 result = sys_fdopendir(fsp->fh->fd);
403 END_PROFILE(syscall_fdopendir);
404 return result;
408 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
409 DIR *dirp,
410 SMB_STRUCT_STAT *sbuf)
412 struct dirent *result;
414 START_PROFILE(syscall_readdir);
415 result = readdir(dirp);
416 END_PROFILE(syscall_readdir);
417 if (sbuf) {
418 /* Default Posix readdir() does not give us stat info.
419 * Set to invalid to indicate we didn't return this info. */
420 SET_STAT_INVALID(*sbuf);
421 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
422 if (result != NULL) {
423 /* See if we can efficiently return this. */
424 struct stat st;
425 int flags = AT_SYMLINK_NOFOLLOW;
426 int ret = fstatat(dirfd(dirp),
427 result->d_name,
428 &st,
429 flags);
431 * As this is an optimization,
432 * ignore it if we stat'ed a
433 * symlink. Make the caller
434 * do it again as we don't
435 * know if they wanted the link
436 * info, or its target info.
438 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
439 init_stat_ex_from_stat(sbuf,
440 &st,
441 lp_fake_directory_create_times(
442 SNUM(handle->conn)));
445 #endif
447 return result;
450 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
451 const struct smb_filename *fname,
452 TALLOC_CTX *mem_ctx,
453 struct readdir_attr_data **attr_data)
455 return NT_STATUS_NOT_SUPPORTED;
458 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
460 START_PROFILE(syscall_seekdir);
461 seekdir(dirp, offset);
462 END_PROFILE(syscall_seekdir);
465 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
467 long result;
468 START_PROFILE(syscall_telldir);
469 result = telldir(dirp);
470 END_PROFILE(syscall_telldir);
471 return result;
474 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
476 START_PROFILE(syscall_rewinddir);
477 rewinddir(dirp);
478 END_PROFILE(syscall_rewinddir);
481 static int vfswrap_mkdir(vfs_handle_struct *handle,
482 const struct smb_filename *smb_fname,
483 mode_t mode)
485 int result;
486 bool has_dacl = False;
487 const char *path = smb_fname->base_name;
488 char *parent = NULL;
490 START_PROFILE(syscall_mkdir);
492 if (lp_inherit_acls(SNUM(handle->conn))
493 && parent_dirname(talloc_tos(), path, &parent, NULL)
494 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
495 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
498 TALLOC_FREE(parent);
500 result = mkdir(path, mode);
502 if (result == 0 && !has_dacl) {
504 * We need to do this as the default behavior of POSIX ACLs
505 * is to set the mask to be the requested group permission
506 * bits, not the group permission bits to be the requested
507 * group permission bits. This is not what we want, as it will
508 * mess up any inherited ACL bits that were set. JRA.
510 int saved_errno = errno; /* We may get ENOSYS */
511 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
512 (errno == ENOSYS)) {
513 errno = saved_errno;
517 END_PROFILE(syscall_mkdir);
518 return result;
521 static int vfswrap_rmdir(vfs_handle_struct *handle,
522 const struct smb_filename *smb_fname)
524 int result;
526 START_PROFILE(syscall_rmdir);
527 result = rmdir(smb_fname->base_name);
528 END_PROFILE(syscall_rmdir);
529 return result;
532 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
534 int result;
536 START_PROFILE(syscall_closedir);
537 result = closedir(dirp);
538 END_PROFILE(syscall_closedir);
539 return result;
542 static void vfswrap_init_search_op(vfs_handle_struct *handle,
543 DIR *dirp)
545 /* Default behavior is a NOOP */
548 /* File operations */
550 static int vfswrap_open(vfs_handle_struct *handle,
551 struct smb_filename *smb_fname,
552 files_struct *fsp, int flags, mode_t mode)
554 int result = -1;
556 START_PROFILE(syscall_open);
558 if (smb_fname->stream_name) {
559 errno = ENOENT;
560 goto out;
563 result = open(smb_fname->base_name, flags, mode);
564 out:
565 END_PROFILE(syscall_open);
566 return result;
569 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
570 struct smb_request *req,
571 uint16_t root_dir_fid,
572 struct smb_filename *smb_fname,
573 uint32_t access_mask,
574 uint32_t share_access,
575 uint32_t create_disposition,
576 uint32_t create_options,
577 uint32_t file_attributes,
578 uint32_t oplock_request,
579 struct smb2_lease *lease,
580 uint64_t allocation_size,
581 uint32_t private_flags,
582 struct security_descriptor *sd,
583 struct ea_list *ea_list,
584 files_struct **result,
585 int *pinfo,
586 const struct smb2_create_blobs *in_context_blobs,
587 struct smb2_create_blobs *out_context_blobs)
589 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
590 access_mask, share_access,
591 create_disposition, create_options,
592 file_attributes, oplock_request, lease,
593 allocation_size, private_flags,
594 sd, ea_list, result,
595 pinfo, in_context_blobs, out_context_blobs);
598 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
600 int result;
602 START_PROFILE(syscall_close);
603 result = fd_close_posix(fsp);
604 END_PROFILE(syscall_close);
605 return result;
608 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
610 ssize_t result;
612 START_PROFILE_BYTES(syscall_read, n);
613 result = sys_read(fsp->fh->fd, data, n);
614 END_PROFILE_BYTES(syscall_read);
615 return result;
618 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
619 size_t n, off_t offset)
621 ssize_t result;
623 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
624 START_PROFILE_BYTES(syscall_pread, n);
625 result = sys_pread(fsp->fh->fd, data, n, offset);
626 END_PROFILE_BYTES(syscall_pread);
628 if (result == -1 && errno == ESPIPE) {
629 /* Maintain the fiction that pipes can be seeked (sought?) on. */
630 result = SMB_VFS_READ(fsp, data, n);
631 fsp->fh->pos = 0;
634 #else /* HAVE_PREAD */
635 off_t curr;
636 int lerrno;
638 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
639 if (curr == -1 && errno == ESPIPE) {
640 /* Maintain the fiction that pipes can be seeked (sought?) on. */
641 result = SMB_VFS_READ(fsp, data, n);
642 fsp->fh->pos = 0;
643 return result;
646 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
647 return -1;
650 errno = 0;
651 result = SMB_VFS_READ(fsp, data, n);
652 lerrno = errno;
654 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
655 errno = lerrno;
657 #endif /* HAVE_PREAD */
659 return result;
662 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
664 ssize_t result;
666 START_PROFILE_BYTES(syscall_write, n);
667 result = sys_write(fsp->fh->fd, data, n);
668 END_PROFILE_BYTES(syscall_write);
669 return result;
672 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
673 size_t n, off_t offset)
675 ssize_t result;
677 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
678 START_PROFILE_BYTES(syscall_pwrite, n);
679 result = sys_pwrite(fsp->fh->fd, data, n, offset);
680 END_PROFILE_BYTES(syscall_pwrite);
682 if (result == -1 && errno == ESPIPE) {
683 /* Maintain the fiction that pipes can be sought on. */
684 result = SMB_VFS_WRITE(fsp, data, n);
687 #else /* HAVE_PWRITE */
688 off_t curr;
689 int lerrno;
691 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
692 if (curr == -1) {
693 return -1;
696 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
697 return -1;
700 result = SMB_VFS_WRITE(fsp, data, n);
701 lerrno = errno;
703 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
704 errno = lerrno;
706 #endif /* HAVE_PWRITE */
708 return result;
711 static int vfswrap_init_pool(struct smbd_server_connection *conn)
713 int ret;
715 if (conn->pool != NULL) {
716 return 0;
719 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
720 &conn->pool);
721 return ret;
724 struct vfswrap_pread_state {
725 ssize_t ret;
726 int err;
727 int fd;
728 void *buf;
729 size_t count;
730 off_t offset;
732 struct vfs_aio_state vfs_aio_state;
733 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
736 static void vfs_pread_do(void *private_data);
737 static void vfs_pread_done(struct tevent_req *subreq);
739 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
740 TALLOC_CTX *mem_ctx,
741 struct tevent_context *ev,
742 struct files_struct *fsp,
743 void *data,
744 size_t n, off_t offset)
746 struct tevent_req *req, *subreq;
747 struct vfswrap_pread_state *state;
748 int ret;
750 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
751 if (req == NULL) {
752 return NULL;
755 ret = vfswrap_init_pool(handle->conn->sconn);
756 if (tevent_req_error(req, ret)) {
757 return tevent_req_post(req, ev);
760 state->ret = -1;
761 state->fd = fsp->fh->fd;
762 state->buf = data;
763 state->count = n;
764 state->offset = offset;
766 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
767 state->profile_bytes, n);
768 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
770 subreq = pthreadpool_tevent_job_send(
771 state, ev, handle->conn->sconn->pool,
772 vfs_pread_do, state);
773 if (tevent_req_nomem(subreq, req)) {
774 return tevent_req_post(req, ev);
776 tevent_req_set_callback(subreq, vfs_pread_done, req);
778 return req;
781 static void vfs_pread_do(void *private_data)
783 struct vfswrap_pread_state *state = talloc_get_type_abort(
784 private_data, struct vfswrap_pread_state);
785 struct timespec start_time;
786 struct timespec end_time;
788 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
790 PROFILE_TIMESTAMP(&start_time);
792 do {
793 state->ret = pread(state->fd, state->buf, state->count,
794 state->offset);
795 } while ((state->ret == -1) && (errno == EINTR));
797 state->err = errno;
799 PROFILE_TIMESTAMP(&end_time);
801 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
803 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
806 static void vfs_pread_done(struct tevent_req *subreq)
808 struct tevent_req *req = tevent_req_callback_data(
809 subreq, struct tevent_req);
810 #ifdef WITH_PROFILE
811 struct vfswrap_pread_state *state = tevent_req_data(
812 req, struct vfswrap_pread_state);
813 #endif
814 int ret;
816 ret = pthreadpool_tevent_job_recv(subreq);
817 TALLOC_FREE(subreq);
818 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
819 if (tevent_req_error(req, ret)) {
820 return;
823 tevent_req_done(req);
826 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
827 struct vfs_aio_state *vfs_aio_state)
829 struct vfswrap_pread_state *state = tevent_req_data(
830 req, struct vfswrap_pread_state);
832 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
833 return -1;
836 *vfs_aio_state = state->vfs_aio_state;
837 return state->ret;
840 struct vfswrap_pwrite_state {
841 ssize_t ret;
842 int err;
843 int fd;
844 const void *buf;
845 size_t count;
846 off_t offset;
848 struct vfs_aio_state vfs_aio_state;
849 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
852 static void vfs_pwrite_do(void *private_data);
853 static void vfs_pwrite_done(struct tevent_req *subreq);
855 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
856 TALLOC_CTX *mem_ctx,
857 struct tevent_context *ev,
858 struct files_struct *fsp,
859 const void *data,
860 size_t n, off_t offset)
862 struct tevent_req *req, *subreq;
863 struct vfswrap_pwrite_state *state;
864 int ret;
866 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
867 if (req == NULL) {
868 return NULL;
871 ret = vfswrap_init_pool(handle->conn->sconn);
872 if (tevent_req_error(req, ret)) {
873 return tevent_req_post(req, ev);
876 state->ret = -1;
877 state->fd = fsp->fh->fd;
878 state->buf = data;
879 state->count = n;
880 state->offset = offset;
882 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
883 state->profile_bytes, n);
884 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
886 subreq = pthreadpool_tevent_job_send(
887 state, ev, handle->conn->sconn->pool,
888 vfs_pwrite_do, state);
889 if (tevent_req_nomem(subreq, req)) {
890 return tevent_req_post(req, ev);
892 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
894 return req;
897 static void vfs_pwrite_do(void *private_data)
899 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
900 private_data, struct vfswrap_pwrite_state);
901 struct timespec start_time;
902 struct timespec end_time;
904 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
906 PROFILE_TIMESTAMP(&start_time);
908 do {
909 state->ret = pwrite(state->fd, state->buf, state->count,
910 state->offset);
911 } while ((state->ret == -1) && (errno == EINTR));
913 state->err = errno;
915 PROFILE_TIMESTAMP(&end_time);
917 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
919 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
922 static void vfs_pwrite_done(struct tevent_req *subreq)
924 struct tevent_req *req = tevent_req_callback_data(
925 subreq, struct tevent_req);
926 #ifdef WITH_PROFILE
927 struct vfswrap_pwrite_state *state = tevent_req_data(
928 req, struct vfswrap_pwrite_state);
929 #endif
930 int ret;
932 ret = pthreadpool_tevent_job_recv(subreq);
933 TALLOC_FREE(subreq);
934 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
935 if (tevent_req_error(req, ret)) {
936 return;
939 tevent_req_done(req);
942 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
943 struct vfs_aio_state *vfs_aio_state)
945 struct vfswrap_pwrite_state *state = tevent_req_data(
946 req, struct vfswrap_pwrite_state);
948 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
949 return -1;
952 *vfs_aio_state = state->vfs_aio_state;
953 return state->ret;
956 struct vfswrap_fsync_state {
957 ssize_t ret;
958 int err;
959 int fd;
961 struct vfs_aio_state vfs_aio_state;
962 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
965 static void vfs_fsync_do(void *private_data);
966 static void vfs_fsync_done(struct tevent_req *subreq);
968 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
969 TALLOC_CTX *mem_ctx,
970 struct tevent_context *ev,
971 struct files_struct *fsp)
973 struct tevent_req *req, *subreq;
974 struct vfswrap_fsync_state *state;
975 int ret;
977 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
978 if (req == NULL) {
979 return NULL;
982 ret = vfswrap_init_pool(handle->conn->sconn);
983 if (tevent_req_error(req, ret)) {
984 return tevent_req_post(req, ev);
987 state->ret = -1;
988 state->fd = fsp->fh->fd;
990 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
991 state->profile_basic);
993 subreq = pthreadpool_tevent_job_send(
994 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
995 if (tevent_req_nomem(subreq, req)) {
996 return tevent_req_post(req, ev);
998 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1000 return req;
1003 static void vfs_fsync_do(void *private_data)
1005 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1006 private_data, struct vfswrap_fsync_state);
1007 struct timespec start_time;
1008 struct timespec end_time;
1010 PROFILE_TIMESTAMP(&start_time);
1012 do {
1013 state->ret = fsync(state->fd);
1014 } while ((state->ret == -1) && (errno == EINTR));
1016 state->err = errno;
1018 PROFILE_TIMESTAMP(&end_time);
1020 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1023 static void vfs_fsync_done(struct tevent_req *subreq)
1025 struct tevent_req *req = tevent_req_callback_data(
1026 subreq, struct tevent_req);
1027 #ifdef WITH_PROFILE
1028 struct vfswrap_fsync_state *state = tevent_req_data(
1029 req, struct vfswrap_fsync_state);
1030 #endif
1031 int ret;
1033 ret = pthreadpool_tevent_job_recv(subreq);
1034 TALLOC_FREE(subreq);
1035 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1036 if (tevent_req_error(req, ret)) {
1037 return;
1040 tevent_req_done(req);
1043 static int vfswrap_fsync_recv(struct tevent_req *req,
1044 struct vfs_aio_state *vfs_aio_state)
1046 struct vfswrap_fsync_state *state = tevent_req_data(
1047 req, struct vfswrap_fsync_state);
1049 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1050 return -1;
1053 *vfs_aio_state = state->vfs_aio_state;
1054 return state->ret;
1057 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1059 off_t result = 0;
1061 START_PROFILE(syscall_lseek);
1063 /* Cope with 'stat' file opens. */
1064 if (fsp->fh->fd != -1)
1065 result = lseek(fsp->fh->fd, offset, whence);
1068 * We want to maintain the fiction that we can seek
1069 * on a fifo for file system purposes. This allows
1070 * people to set up UNIX fifo's that feed data to Windows
1071 * applications. JRA.
1074 if((result == -1) && (errno == ESPIPE)) {
1075 result = 0;
1076 errno = 0;
1079 END_PROFILE(syscall_lseek);
1080 return result;
1083 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1084 off_t offset, size_t n)
1086 ssize_t result;
1088 START_PROFILE_BYTES(syscall_sendfile, n);
1089 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1090 END_PROFILE_BYTES(syscall_sendfile);
1091 return result;
1094 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1095 int fromfd,
1096 files_struct *tofsp,
1097 off_t offset,
1098 size_t n)
1100 ssize_t result;
1102 START_PROFILE_BYTES(syscall_recvfile, n);
1103 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1104 END_PROFILE_BYTES(syscall_recvfile);
1105 return result;
1108 static int vfswrap_rename(vfs_handle_struct *handle,
1109 const struct smb_filename *smb_fname_src,
1110 const struct smb_filename *smb_fname_dst)
1112 int result = -1;
1114 START_PROFILE(syscall_rename);
1116 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1117 errno = ENOENT;
1118 goto out;
1121 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1123 out:
1124 END_PROFILE(syscall_rename);
1125 return result;
1128 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1130 #ifdef HAVE_FSYNC
1131 int result;
1133 START_PROFILE(syscall_fsync);
1134 result = fsync(fsp->fh->fd);
1135 END_PROFILE(syscall_fsync);
1136 return result;
1137 #else
1138 return 0;
1139 #endif
1142 static int vfswrap_stat(vfs_handle_struct *handle,
1143 struct smb_filename *smb_fname)
1145 int result = -1;
1147 START_PROFILE(syscall_stat);
1149 if (smb_fname->stream_name) {
1150 errno = ENOENT;
1151 goto out;
1154 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1155 lp_fake_directory_create_times(SNUM(handle->conn)));
1156 out:
1157 END_PROFILE(syscall_stat);
1158 return result;
1161 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1163 int result;
1165 START_PROFILE(syscall_fstat);
1166 result = sys_fstat(fsp->fh->fd,
1167 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1168 END_PROFILE(syscall_fstat);
1169 return result;
1172 static int vfswrap_lstat(vfs_handle_struct *handle,
1173 struct smb_filename *smb_fname)
1175 int result = -1;
1177 START_PROFILE(syscall_lstat);
1179 if (smb_fname->stream_name) {
1180 errno = ENOENT;
1181 goto out;
1184 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1185 lp_fake_directory_create_times(SNUM(handle->conn)));
1186 out:
1187 END_PROFILE(syscall_lstat);
1188 return result;
1191 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1192 const char *name,
1193 enum vfs_translate_direction direction,
1194 TALLOC_CTX *mem_ctx,
1195 char **mapped_name)
1197 return NT_STATUS_NONE_MAPPED;
1201 * Implement the default fsctl operation.
1203 static bool vfswrap_logged_ioctl_message = false;
1205 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1206 struct files_struct *fsp,
1207 TALLOC_CTX *ctx,
1208 uint32_t function,
1209 uint16_t req_flags, /* Needed for UNICODE ... */
1210 const uint8_t *_in_data,
1211 uint32_t in_len,
1212 uint8_t **_out_data,
1213 uint32_t max_out_len,
1214 uint32_t *out_len)
1216 const char *in_data = (const char *)_in_data;
1217 char **out_data = (char **)_out_data;
1218 NTSTATUS status;
1220 switch (function) {
1221 case FSCTL_SET_SPARSE:
1223 bool set_sparse = true;
1225 if (in_len >= 1 && in_data[0] == 0) {
1226 set_sparse = false;
1229 status = file_set_sparse(handle->conn, fsp, set_sparse);
1231 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1232 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1233 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1234 nt_errstr(status)));
1236 return status;
1239 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1241 unsigned char objid[16];
1242 char *return_data = NULL;
1244 /* This should return the object-id on this file.
1245 * I think I'll make this be the inode+dev. JRA.
1248 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1249 fsp_fnum_dbg(fsp)));
1251 *out_len = MIN(max_out_len, 64);
1253 /* Hmmm, will this cause problems if less data asked for? */
1254 return_data = talloc_array(ctx, char, 64);
1255 if (return_data == NULL) {
1256 return NT_STATUS_NO_MEMORY;
1259 /* For backwards compatibility only store the dev/inode. */
1260 push_file_id_16(return_data, &fsp->file_id);
1261 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1262 push_file_id_16(return_data+32, &fsp->file_id);
1263 memset(return_data+48, 0, 16);
1264 *out_data = return_data;
1265 return NT_STATUS_OK;
1268 case FSCTL_GET_REPARSE_POINT:
1270 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1271 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1272 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1273 return NT_STATUS_NOT_A_REPARSE_POINT;
1276 case FSCTL_SET_REPARSE_POINT:
1278 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1279 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1280 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1281 return NT_STATUS_NOT_A_REPARSE_POINT;
1284 case FSCTL_GET_SHADOW_COPY_DATA:
1287 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1288 * and return their volume names. If max_data_count is 16, then it is just
1289 * asking for the number of volumes and length of the combined names.
1291 * pdata is the data allocated by our caller, but that uses
1292 * total_data_count (which is 0 in our case) rather than max_data_count.
1293 * Allocate the correct amount and return the pointer to let
1294 * it be deallocated when we return.
1296 struct shadow_copy_data *shadow_data = NULL;
1297 bool labels = False;
1298 uint32_t labels_data_count = 0;
1299 uint32_t i;
1300 char *cur_pdata = NULL;
1302 if (max_out_len < 16) {
1303 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1304 max_out_len));
1305 return NT_STATUS_INVALID_PARAMETER;
1308 if (max_out_len > 16) {
1309 labels = True;
1312 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1313 if (shadow_data == NULL) {
1314 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1315 return NT_STATUS_NO_MEMORY;
1319 * Call the VFS routine to actually do the work.
1321 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1322 int log_lev = 0;
1323 if (errno == 0) {
1324 /* broken module didn't set errno on error */
1325 status = NT_STATUS_UNSUCCESSFUL;
1326 } else {
1327 status = map_nt_error_from_unix(errno);
1328 if (NT_STATUS_EQUAL(status,
1329 NT_STATUS_NOT_SUPPORTED)) {
1330 log_lev = 5;
1333 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1334 "connectpath %s, failed - %s.\n",
1335 fsp->conn->connectpath,
1336 nt_errstr(status)));
1337 TALLOC_FREE(shadow_data);
1338 return status;
1341 labels_data_count = (shadow_data->num_volumes * 2 *
1342 sizeof(SHADOW_COPY_LABEL)) + 2;
1344 if (!labels) {
1345 *out_len = 16;
1346 } else {
1347 *out_len = 12 + labels_data_count;
1350 if (max_out_len < *out_len) {
1351 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1352 max_out_len, *out_len));
1353 TALLOC_FREE(shadow_data);
1354 return NT_STATUS_BUFFER_TOO_SMALL;
1357 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1358 if (cur_pdata == NULL) {
1359 TALLOC_FREE(shadow_data);
1360 return NT_STATUS_NO_MEMORY;
1363 *out_data = cur_pdata;
1365 /* num_volumes 4 bytes */
1366 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1368 if (labels) {
1369 /* num_labels 4 bytes */
1370 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1373 /* needed_data_count 4 bytes */
1374 SIVAL(cur_pdata, 8, labels_data_count);
1376 cur_pdata += 12;
1378 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1379 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1380 if (labels && shadow_data->labels) {
1381 for (i=0; i<shadow_data->num_volumes; i++) {
1382 size_t len = 0;
1383 status = srvstr_push(cur_pdata, req_flags,
1384 cur_pdata, shadow_data->labels[i],
1385 2 * sizeof(SHADOW_COPY_LABEL),
1386 STR_UNICODE|STR_TERMINATE, &len);
1387 if (!NT_STATUS_IS_OK(status)) {
1388 TALLOC_FREE(*out_data);
1389 TALLOC_FREE(shadow_data);
1390 return status;
1392 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1393 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1397 TALLOC_FREE(shadow_data);
1399 return NT_STATUS_OK;
1402 case FSCTL_FIND_FILES_BY_SID:
1404 /* pretend this succeeded -
1406 * we have to send back a list with all files owned by this SID
1408 * but I have to check that --metze
1410 struct dom_sid sid;
1411 uid_t uid;
1412 size_t sid_len;
1414 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1415 fsp_fnum_dbg(fsp)));
1417 if (in_len < 8) {
1418 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1419 return NT_STATUS_INVALID_PARAMETER;
1422 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1424 /* unknown 4 bytes: this is not the length of the sid :-( */
1425 /*unknown = IVAL(pdata,0);*/
1427 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1428 return NT_STATUS_INVALID_PARAMETER;
1430 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1432 if (!sid_to_uid(&sid, &uid)) {
1433 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1434 sid_string_dbg(&sid),
1435 (unsigned long)sid_len));
1436 uid = (-1);
1439 /* we can take a look at the find source :-)
1441 * find ./ -uid $uid -name '*' is what we need here
1444 * and send 4bytes len and then NULL terminated unicode strings
1445 * for each file
1447 * but I don't know how to deal with the paged results
1448 * (maybe we can hang the result anywhere in the fsp struct)
1450 * but I don't know how to deal with the paged results
1451 * (maybe we can hang the result anywhere in the fsp struct)
1453 * we don't send all files at once
1454 * and at the next we should *not* start from the beginning,
1455 * so we have to cache the result
1457 * --metze
1460 /* this works for now... */
1461 return NT_STATUS_OK;
1464 case FSCTL_QUERY_ALLOCATED_RANGES:
1466 /* FIXME: This is just a dummy reply, telling that all of the
1467 * file is allocated. MKS cp needs that.
1468 * Adding the real allocated ranges via FIEMAP on Linux
1469 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1470 * this FSCTL correct for sparse files.
1472 uint64_t offset, length;
1473 char *out_data_tmp = NULL;
1475 if (in_len != 16) {
1476 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1477 in_len));
1478 return NT_STATUS_INVALID_PARAMETER;
1481 if (max_out_len < 16) {
1482 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1483 max_out_len));
1484 return NT_STATUS_INVALID_PARAMETER;
1487 offset = BVAL(in_data,0);
1488 length = BVAL(in_data,8);
1490 if (offset + length < offset) {
1491 /* No 64-bit integer wrap. */
1492 return NT_STATUS_INVALID_PARAMETER;
1495 /* Shouldn't this be SMB_VFS_STAT ... ? */
1496 status = vfs_stat_fsp(fsp);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 return status;
1501 *out_len = 16;
1502 out_data_tmp = talloc_array(ctx, char, *out_len);
1503 if (out_data_tmp == NULL) {
1504 DEBUG(10, ("unable to allocate memory for response\n"));
1505 return NT_STATUS_NO_MEMORY;
1508 if (offset > fsp->fsp_name->st.st_ex_size ||
1509 fsp->fsp_name->st.st_ex_size == 0 ||
1510 length == 0) {
1511 memset(out_data_tmp, 0, *out_len);
1512 } else {
1513 uint64_t end = offset + length;
1514 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1515 SBVAL(out_data_tmp, 0, 0);
1516 SBVAL(out_data_tmp, 8, end);
1519 *out_data = out_data_tmp;
1521 return NT_STATUS_OK;
1524 case FSCTL_IS_VOLUME_DIRTY:
1526 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1527 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1529 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1530 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1532 return NT_STATUS_INVALID_PARAMETER;
1535 default:
1537 * Only print once ... unfortunately there could be lots of
1538 * different FSCTLs that are called.
1540 if (!vfswrap_logged_ioctl_message) {
1541 vfswrap_logged_ioctl_message = true;
1542 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1543 __func__, function));
1547 return NT_STATUS_NOT_SUPPORTED;
1550 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1551 const struct smb_filename *fname,
1552 SMB_STRUCT_STAT *sbuf);
1554 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1555 struct smb_filename *smb_fname,
1556 uint32_t *dosmode)
1558 bool offline;
1560 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1561 if (offline) {
1562 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1565 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1568 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1569 struct files_struct *fsp,
1570 uint32_t *dosmode)
1572 bool offline;
1574 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1575 if (offline) {
1576 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1579 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1582 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1583 const struct smb_filename *smb_fname,
1584 uint32_t dosmode)
1586 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1589 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1590 struct files_struct *fsp,
1591 uint32_t dosmode)
1593 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1596 struct vfs_cc_state {
1597 struct tevent_context *ev;
1598 uint8_t *buf;
1599 bool read_lck_locked;
1600 struct lock_struct read_lck;
1601 bool write_lck_locked;
1602 struct lock_struct write_lck;
1603 struct files_struct *src_fsp;
1604 off_t src_off;
1605 struct files_struct *dst_fsp;
1606 off_t dst_off;
1607 off_t to_copy;
1608 off_t remaining;
1609 size_t next_io_size;
1610 uint32_t flags;
1613 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1615 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1616 TALLOC_CTX *mem_ctx,
1617 struct tevent_context *ev,
1618 struct files_struct *src_fsp,
1619 off_t src_off,
1620 struct files_struct *dest_fsp,
1621 off_t dest_off,
1622 off_t to_copy,
1623 uint32_t flags)
1625 struct tevent_req *req;
1626 struct vfs_cc_state *state = NULL;
1627 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1628 NTSTATUS status;
1630 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1632 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1633 if (req == NULL) {
1634 return NULL;
1637 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1638 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1639 return tevent_req_post(req, ev);
1642 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1643 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1644 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1645 return tevent_req_post(req, ev);
1648 *state = (struct vfs_cc_state) {
1649 .ev = ev,
1650 .src_fsp = src_fsp,
1651 .src_off = src_off,
1652 .dst_fsp = dest_fsp,
1653 .dst_off = dest_off,
1654 .to_copy = to_copy,
1655 .remaining = to_copy,
1656 .flags = flags,
1658 state->buf = talloc_array(state, uint8_t, num);
1659 if (tevent_req_nomem(state->buf, req)) {
1660 return tevent_req_post(req, ev);
1663 status = vfs_stat_fsp(src_fsp);
1664 if (tevent_req_nterror(req, status)) {
1665 return tevent_req_post(req, ev);
1668 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1670 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1671 * If the SourceOffset or SourceOffset + Length extends beyond
1672 * the end of file, the server SHOULD<240> treat this as a
1673 * STATUS_END_OF_FILE error.
1674 * ...
1675 * <240> Section 3.3.5.15.6: Windows servers will return
1676 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1678 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1679 return tevent_req_post(req, ev);
1682 if (src_fsp->op == NULL) {
1683 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1684 return tevent_req_post(req, ev);
1687 if (dest_fsp->op == NULL) {
1688 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1689 return tevent_req_post(req, ev);
1692 status = copy_chunk_loop(req);
1693 if (!NT_STATUS_IS_OK(status)) {
1694 tevent_req_nterror(req, status);
1695 return tevent_req_post(req, ev);
1698 return req;
1701 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1703 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1705 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1706 struct tevent_req *subreq = NULL;
1707 bool ok;
1709 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1711 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1712 init_strict_lock_struct(state->src_fsp,
1713 state->src_fsp->op->global->open_persistent_id,
1714 state->src_off,
1715 state->next_io_size,
1716 READ_LOCK,
1717 &state->read_lck);
1719 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1720 state->src_fsp,
1721 &state->read_lck);
1722 if (!ok) {
1723 return NT_STATUS_FILE_LOCK_CONFLICT;
1727 subreq = SMB_VFS_PREAD_SEND(state,
1728 state->src_fsp->conn->sconn->ev_ctx,
1729 state->src_fsp,
1730 state->buf,
1731 state->next_io_size,
1732 state->src_off);
1733 if (subreq == NULL) {
1734 return NT_STATUS_NO_MEMORY;
1736 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1738 return NT_STATUS_OK;
1741 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1743 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1745 struct tevent_req *req = tevent_req_callback_data(
1746 subreq, struct tevent_req);
1747 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1748 struct vfs_aio_state aio_state;
1749 ssize_t nread;
1750 bool ok;
1752 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1753 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1754 state->src_fsp,
1755 &state->read_lck);
1756 ZERO_STRUCT(state->read_lck);
1759 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1760 TALLOC_FREE(subreq);
1761 if (nread == -1) {
1762 DBG_ERR("read failed: %s\n", strerror(errno));
1763 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1764 return;
1766 if (nread != state->next_io_size) {
1767 DBG_ERR("Short read, only %zd of %zu\n",
1768 nread, state->next_io_size);
1769 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1770 return;
1773 state->src_off += nread;
1775 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1776 init_strict_lock_struct(state->dst_fsp,
1777 state->dst_fsp->op->global->open_persistent_id,
1778 state->dst_off,
1779 state->next_io_size,
1780 WRITE_LOCK,
1781 &state->write_lck);
1783 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1784 state->dst_fsp,
1785 &state->write_lck);
1786 if (!ok) {
1787 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1788 return;
1792 subreq = SMB_VFS_PWRITE_SEND(state,
1793 state->ev,
1794 state->dst_fsp,
1795 state->buf,
1796 state->next_io_size,
1797 state->dst_off);
1798 if (subreq == NULL) {
1799 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1800 return;
1802 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1805 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1807 struct tevent_req *req = tevent_req_callback_data(
1808 subreq, struct tevent_req);
1809 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1810 struct vfs_aio_state aio_state;
1811 ssize_t nwritten;
1812 NTSTATUS status;
1814 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1815 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1816 state->dst_fsp,
1817 &state->write_lck);
1818 ZERO_STRUCT(state->write_lck);
1821 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1822 TALLOC_FREE(subreq);
1823 if (nwritten == -1) {
1824 DBG_ERR("write failed: %s\n", strerror(errno));
1825 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1826 return;
1828 if (nwritten != state->next_io_size) {
1829 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1830 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1831 return;
1834 state->dst_off += nwritten;
1836 if (state->remaining < nwritten) {
1837 /* Paranoia check */
1838 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1839 return;
1841 state->remaining -= nwritten;
1842 if (state->remaining == 0) {
1843 tevent_req_done(req);
1844 return;
1847 status = copy_chunk_loop(req);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 tevent_req_nterror(req, status);
1850 return;
1853 return;
1856 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1857 struct tevent_req *req,
1858 off_t *copied)
1860 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1861 NTSTATUS status;
1863 if (tevent_req_is_nterror(req, &status)) {
1864 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1865 *copied = 0;
1866 tevent_req_received(req);
1867 return status;
1870 *copied = state->to_copy;
1871 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1872 tevent_req_received(req);
1874 return NT_STATUS_OK;
1877 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1878 TALLOC_CTX *mem_ctx,
1879 struct files_struct *fsp,
1880 struct smb_filename *smb_fname,
1881 uint16_t *_compression_fmt)
1883 return NT_STATUS_INVALID_DEVICE_REQUEST;
1886 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1887 TALLOC_CTX *mem_ctx,
1888 struct files_struct *fsp,
1889 uint16_t compression_fmt)
1891 return NT_STATUS_INVALID_DEVICE_REQUEST;
1894 /********************************************************************
1895 Given a stat buffer return the allocated size on disk, taking into
1896 account sparse files.
1897 ********************************************************************/
1898 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1899 struct files_struct *fsp,
1900 const SMB_STRUCT_STAT *sbuf)
1902 uint64_t result;
1904 START_PROFILE(syscall_get_alloc_size);
1906 if(S_ISDIR(sbuf->st_ex_mode)) {
1907 result = 0;
1908 goto out;
1911 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1912 /* The type of st_blocksize is blkcnt_t which *MUST* be
1913 signed (according to POSIX) and can be less than 64-bits.
1914 Ensure when we're converting to 64 bits wide we don't
1915 sign extend. */
1916 #if defined(SIZEOF_BLKCNT_T_8)
1917 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1918 #elif defined(SIZEOF_BLKCNT_T_4)
1920 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1921 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1923 #else
1924 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1925 #endif
1926 if (result == 0) {
1928 * Some file systems do not allocate a block for very
1929 * small files. But for non-empty file should report a
1930 * positive size.
1933 uint64_t filesize = get_file_size_stat(sbuf);
1934 if (filesize > 0) {
1935 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1938 #else
1939 result = get_file_size_stat(sbuf);
1940 #endif
1942 if (fsp && fsp->initial_allocation_size)
1943 result = MAX(result,fsp->initial_allocation_size);
1945 result = smb_roundup(handle->conn, result);
1947 out:
1948 END_PROFILE(syscall_get_alloc_size);
1949 return result;
1952 static int vfswrap_unlink(vfs_handle_struct *handle,
1953 const struct smb_filename *smb_fname)
1955 int result = -1;
1957 START_PROFILE(syscall_unlink);
1959 if (smb_fname->stream_name) {
1960 errno = ENOENT;
1961 goto out;
1963 result = unlink(smb_fname->base_name);
1965 out:
1966 END_PROFILE(syscall_unlink);
1967 return result;
1970 static int vfswrap_chmod(vfs_handle_struct *handle,
1971 const struct smb_filename *smb_fname,
1972 mode_t mode)
1974 int result;
1976 START_PROFILE(syscall_chmod);
1979 * We need to do this due to the fact that the default POSIX ACL
1980 * chmod modifies the ACL *mask* for the group owner, not the
1981 * group owner bits directly. JRA.
1986 int saved_errno = errno; /* We might get ENOSYS */
1987 result = SMB_VFS_CHMOD_ACL(handle->conn,
1988 smb_fname,
1989 mode);
1990 if (result == 0) {
1991 END_PROFILE(syscall_chmod);
1992 return result;
1994 /* Error - return the old errno. */
1995 errno = saved_errno;
1998 result = chmod(smb_fname->base_name, mode);
1999 END_PROFILE(syscall_chmod);
2000 return result;
2003 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2005 int result;
2007 START_PROFILE(syscall_fchmod);
2010 * We need to do this due to the fact that the default POSIX ACL
2011 * chmod modifies the ACL *mask* for the group owner, not the
2012 * group owner bits directly. JRA.
2016 int saved_errno = errno; /* We might get ENOSYS */
2017 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2018 END_PROFILE(syscall_fchmod);
2019 return result;
2021 /* Error - return the old errno. */
2022 errno = saved_errno;
2025 #if defined(HAVE_FCHMOD)
2026 result = fchmod(fsp->fh->fd, mode);
2027 #else
2028 result = -1;
2029 errno = ENOSYS;
2030 #endif
2032 END_PROFILE(syscall_fchmod);
2033 return result;
2036 static int vfswrap_chown(vfs_handle_struct *handle,
2037 const struct smb_filename *smb_fname,
2038 uid_t uid,
2039 gid_t gid)
2041 int result;
2043 START_PROFILE(syscall_chown);
2044 result = chown(smb_fname->base_name, uid, gid);
2045 END_PROFILE(syscall_chown);
2046 return result;
2049 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2051 #ifdef HAVE_FCHOWN
2052 int result;
2054 START_PROFILE(syscall_fchown);
2055 result = fchown(fsp->fh->fd, uid, gid);
2056 END_PROFILE(syscall_fchown);
2057 return result;
2058 #else
2059 errno = ENOSYS;
2060 return -1;
2061 #endif
2064 static int vfswrap_lchown(vfs_handle_struct *handle,
2065 const struct smb_filename *smb_fname,
2066 uid_t uid,
2067 gid_t gid)
2069 int result;
2071 START_PROFILE(syscall_lchown);
2072 result = lchown(smb_fname->base_name, uid, gid);
2073 END_PROFILE(syscall_lchown);
2074 return result;
2077 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2079 int result;
2081 START_PROFILE(syscall_chdir);
2082 result = chdir(path);
2083 END_PROFILE(syscall_chdir);
2084 return result;
2087 static char *vfswrap_getwd(vfs_handle_struct *handle)
2089 char *result;
2091 START_PROFILE(syscall_getwd);
2092 result = sys_getwd();
2093 END_PROFILE(syscall_getwd);
2094 return result;
2097 /*********************************************************************
2098 nsec timestamp resolution call. Convert down to whatever the underlying
2099 system will support.
2100 **********************************************************************/
2102 static int vfswrap_ntimes(vfs_handle_struct *handle,
2103 const struct smb_filename *smb_fname,
2104 struct smb_file_time *ft)
2106 int result = -1;
2108 START_PROFILE(syscall_ntimes);
2110 if (smb_fname->stream_name) {
2111 errno = ENOENT;
2112 goto out;
2115 if (ft != NULL) {
2116 if (null_timespec(ft->atime)) {
2117 ft->atime= smb_fname->st.st_ex_atime;
2120 if (null_timespec(ft->mtime)) {
2121 ft->mtime = smb_fname->st.st_ex_mtime;
2124 if (!null_timespec(ft->create_time)) {
2125 set_create_timespec_ea(handle->conn,
2126 smb_fname,
2127 ft->create_time);
2130 if ((timespec_compare(&ft->atime,
2131 &smb_fname->st.st_ex_atime) == 0) &&
2132 (timespec_compare(&ft->mtime,
2133 &smb_fname->st.st_ex_mtime) == 0)) {
2134 return 0;
2138 #if defined(HAVE_UTIMENSAT)
2139 if (ft != NULL) {
2140 struct timespec ts[2];
2141 ts[0] = ft->atime;
2142 ts[1] = ft->mtime;
2143 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2144 } else {
2145 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2147 if (!((result == -1) && (errno == ENOSYS))) {
2148 goto out;
2150 #endif
2151 #if defined(HAVE_UTIMES)
2152 if (ft != NULL) {
2153 struct timeval tv[2];
2154 tv[0] = convert_timespec_to_timeval(ft->atime);
2155 tv[1] = convert_timespec_to_timeval(ft->mtime);
2156 result = utimes(smb_fname->base_name, tv);
2157 } else {
2158 result = utimes(smb_fname->base_name, NULL);
2160 if (!((result == -1) && (errno == ENOSYS))) {
2161 goto out;
2163 #endif
2164 #if defined(HAVE_UTIME)
2165 if (ft != NULL) {
2166 struct utimbuf times;
2167 times.actime = convert_timespec_to_time_t(ft->atime);
2168 times.modtime = convert_timespec_to_time_t(ft->mtime);
2169 result = utime(smb_fname->base_name, &times);
2170 } else {
2171 result = utime(smb_fname->base_name, NULL);
2173 if (!((result == -1) && (errno == ENOSYS))) {
2174 goto out;
2176 #endif
2177 errno = ENOSYS;
2178 result = -1;
2180 out:
2181 END_PROFILE(syscall_ntimes);
2182 return result;
2185 /*********************************************************************
2186 A version of ftruncate that will write the space on disk if strict
2187 allocate is set.
2188 **********************************************************************/
2190 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2192 off_t space_to_write;
2193 uint64_t space_avail;
2194 uint64_t bsize,dfree,dsize;
2195 int ret;
2196 NTSTATUS status;
2197 SMB_STRUCT_STAT *pst;
2199 status = vfs_stat_fsp(fsp);
2200 if (!NT_STATUS_IS_OK(status)) {
2201 return -1;
2203 pst = &fsp->fsp_name->st;
2205 #ifdef S_ISFIFO
2206 if (S_ISFIFO(pst->st_ex_mode))
2207 return 0;
2208 #endif
2210 if (pst->st_ex_size == len)
2211 return 0;
2213 /* Shrink - just ftruncate. */
2214 if (pst->st_ex_size > len)
2215 return ftruncate(fsp->fh->fd, len);
2217 space_to_write = len - pst->st_ex_size;
2219 /* for allocation try fallocate first. This can fail on some
2220 platforms e.g. when the filesystem doesn't support it and no
2221 emulation is being done by the libc (like on AIX with JFS1). In that
2222 case we do our own emulation. fallocate implementations can
2223 return ENOTSUP or EINVAL in cases like that. */
2224 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2225 if (ret == -1 && errno == ENOSPC) {
2226 return -1;
2228 if (ret == 0) {
2229 return 0;
2231 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2232 "error %d. Falling back to slow manual allocation\n", errno));
2234 /* available disk space is enough or not? */
2235 space_avail =
2236 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2237 /* space_avail is 1k blocks */
2238 if (space_avail == (uint64_t)-1 ||
2239 ((uint64_t)space_to_write/1024 > space_avail) ) {
2240 errno = ENOSPC;
2241 return -1;
2244 /* Write out the real space on disk. */
2245 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2246 if (ret != 0) {
2247 return -1;
2250 return 0;
2253 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2255 int result = -1;
2256 SMB_STRUCT_STAT *pst;
2257 NTSTATUS status;
2258 char c = 0;
2260 START_PROFILE(syscall_ftruncate);
2262 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2263 result = strict_allocate_ftruncate(handle, fsp, len);
2264 END_PROFILE(syscall_ftruncate);
2265 return result;
2268 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2269 ftruncate if the system supports it. Then I discovered that
2270 you can have some filesystems that support ftruncate
2271 expansion and some that don't! On Linux fat can't do
2272 ftruncate extend but ext2 can. */
2274 result = ftruncate(fsp->fh->fd, len);
2276 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2277 extend a file with ftruncate. Provide alternate implementation
2278 for this */
2280 /* Do an fstat to see if the file is longer than the requested
2281 size in which case the ftruncate above should have
2282 succeeded or shorter, in which case seek to len - 1 and
2283 write 1 byte of zero */
2284 status = vfs_stat_fsp(fsp);
2285 if (!NT_STATUS_IS_OK(status)) {
2286 goto done;
2289 /* We need to update the files_struct after successful ftruncate */
2290 if (result == 0) {
2291 goto done;
2294 pst = &fsp->fsp_name->st;
2296 #ifdef S_ISFIFO
2297 if (S_ISFIFO(pst->st_ex_mode)) {
2298 result = 0;
2299 goto done;
2301 #endif
2303 if (pst->st_ex_size == len) {
2304 result = 0;
2305 goto done;
2308 if (pst->st_ex_size > len) {
2309 /* the ftruncate should have worked */
2310 goto done;
2313 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2314 goto done;
2317 result = 0;
2319 done:
2321 END_PROFILE(syscall_ftruncate);
2322 return result;
2325 static int vfswrap_fallocate(vfs_handle_struct *handle,
2326 files_struct *fsp,
2327 uint32_t mode,
2328 off_t offset,
2329 off_t len)
2331 int result;
2333 START_PROFILE(syscall_fallocate);
2334 if (mode == 0) {
2335 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2337 * posix_fallocate returns 0 on success, errno on error
2338 * and doesn't set errno. Make it behave like fallocate()
2339 * which returns -1, and sets errno on failure.
2341 if (result != 0) {
2342 errno = result;
2343 result = -1;
2345 } else {
2346 /* sys_fallocate handles filtering of unsupported mode flags */
2347 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2349 END_PROFILE(syscall_fallocate);
2350 return result;
2353 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2355 bool result;
2357 START_PROFILE(syscall_fcntl_lock);
2359 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2360 "smbd",
2361 "force process locks",
2362 false)) {
2363 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2366 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2367 END_PROFILE(syscall_fcntl_lock);
2368 return result;
2371 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2372 uint32_t share_mode, uint32_t access_mask)
2374 START_PROFILE(syscall_kernel_flock);
2375 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2376 END_PROFILE(syscall_kernel_flock);
2377 return 0;
2380 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2382 bool result;
2383 int op = F_GETLK;
2385 START_PROFILE(syscall_fcntl_getlock);
2387 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2388 "smbd",
2389 "force process locks",
2390 false)) {
2391 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2394 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2395 END_PROFILE(syscall_fcntl_getlock);
2396 return result;
2399 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2400 int leasetype)
2402 int result = -1;
2404 START_PROFILE(syscall_linux_setlease);
2406 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2407 result = linux_setlease(fsp->fh->fd, leasetype);
2408 #else
2409 errno = ENOSYS;
2410 #endif
2411 END_PROFILE(syscall_linux_setlease);
2412 return result;
2415 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2417 int result;
2419 START_PROFILE(syscall_symlink);
2420 result = symlink(oldpath, newpath);
2421 END_PROFILE(syscall_symlink);
2422 return result;
2425 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2427 int result;
2429 START_PROFILE(syscall_readlink);
2430 result = readlink(path, buf, bufsiz);
2431 END_PROFILE(syscall_readlink);
2432 return result;
2435 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2437 int result;
2439 START_PROFILE(syscall_link);
2440 result = link(oldpath, newpath);
2441 END_PROFILE(syscall_link);
2442 return result;
2445 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2447 int result;
2449 START_PROFILE(syscall_mknod);
2450 result = sys_mknod(pathname, mode, dev);
2451 END_PROFILE(syscall_mknod);
2452 return result;
2455 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2457 char *result;
2459 START_PROFILE(syscall_realpath);
2460 result = sys_realpath(path);
2461 END_PROFILE(syscall_realpath);
2462 return result;
2465 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2466 unsigned int flags)
2468 #ifdef HAVE_CHFLAGS
2469 return chflags(path, flags);
2470 #else
2471 errno = ENOSYS;
2472 return -1;
2473 #endif
2476 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2477 const SMB_STRUCT_STAT *sbuf)
2479 struct file_id key;
2481 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2482 * blob */
2483 ZERO_STRUCT(key);
2485 key.devid = sbuf->st_ex_dev;
2486 key.inode = sbuf->st_ex_ino;
2487 /* key.extid is unused by default. */
2489 return key;
2492 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2493 struct files_struct *fsp,
2494 const struct smb_filename *smb_fname,
2495 TALLOC_CTX *mem_ctx,
2496 unsigned int *pnum_streams,
2497 struct stream_struct **pstreams)
2499 SMB_STRUCT_STAT sbuf;
2500 struct stream_struct *tmp_streams = NULL;
2501 int ret;
2503 if ((fsp != NULL) && (fsp->is_directory)) {
2505 * No default streams on directories
2507 goto done;
2510 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2511 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2513 else {
2514 struct smb_filename smb_fname_cp;
2516 ZERO_STRUCT(smb_fname_cp);
2517 smb_fname_cp.base_name = discard_const_p(char,
2518 smb_fname->base_name);
2519 smb_fname_cp.flags = smb_fname->flags;
2521 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2522 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2523 } else {
2524 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2526 sbuf = smb_fname_cp.st;
2529 if (ret == -1) {
2530 return map_nt_error_from_unix(errno);
2533 if (S_ISDIR(sbuf.st_ex_mode)) {
2534 goto done;
2537 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2538 (*pnum_streams) + 1);
2539 if (tmp_streams == NULL) {
2540 return NT_STATUS_NO_MEMORY;
2542 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2543 if (tmp_streams[*pnum_streams].name == NULL) {
2544 return NT_STATUS_NO_MEMORY;
2546 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2547 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2549 *pnum_streams += 1;
2550 *pstreams = tmp_streams;
2551 done:
2552 return NT_STATUS_OK;
2555 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2556 const char *path,
2557 const char *name,
2558 TALLOC_CTX *mem_ctx,
2559 char **found_name)
2562 * Don't fall back to get_real_filename so callers can differentiate
2563 * between a full directory scan and an actual case-insensitive stat.
2565 errno = EOPNOTSUPP;
2566 return -1;
2569 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2570 const char *fname)
2572 return handle->conn->connectpath;
2575 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2576 struct byte_range_lock *br_lck,
2577 struct lock_struct *plock,
2578 bool blocking_lock)
2580 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2582 /* Note: blr is not used in the default implementation. */
2583 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2586 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2587 struct messaging_context *msg_ctx,
2588 struct byte_range_lock *br_lck,
2589 const struct lock_struct *plock)
2591 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2593 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2596 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2597 struct byte_range_lock *br_lck,
2598 struct lock_struct *plock)
2600 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2602 /* Note: blr is not used in the default implementation. */
2603 return brl_lock_cancel_default(br_lck, plock);
2606 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2607 files_struct *fsp,
2608 struct lock_struct *plock)
2610 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2611 plock->lock_type == WRITE_LOCK);
2613 return strict_lock_default(fsp, plock);
2616 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2617 files_struct *fsp,
2618 struct lock_struct *plock)
2620 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2621 plock->lock_type == WRITE_LOCK);
2623 strict_unlock_default(fsp, plock);
2626 /* NT ACL operations. */
2628 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2629 files_struct *fsp,
2630 uint32_t security_info,
2631 TALLOC_CTX *mem_ctx,
2632 struct security_descriptor **ppdesc)
2634 NTSTATUS result;
2636 START_PROFILE(fget_nt_acl);
2637 result = posix_fget_nt_acl(fsp, security_info,
2638 mem_ctx, ppdesc);
2639 END_PROFILE(fget_nt_acl);
2640 return result;
2643 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2644 const struct smb_filename *smb_fname,
2645 uint32_t security_info,
2646 TALLOC_CTX *mem_ctx,
2647 struct security_descriptor **ppdesc)
2649 NTSTATUS result;
2651 START_PROFILE(get_nt_acl);
2652 result = posix_get_nt_acl(handle->conn,
2653 smb_fname,
2654 security_info,
2655 mem_ctx,
2656 ppdesc);
2657 END_PROFILE(get_nt_acl);
2658 return result;
2661 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2663 NTSTATUS result;
2665 START_PROFILE(fset_nt_acl);
2666 result = set_nt_acl(fsp, security_info_sent, psd);
2667 END_PROFILE(fset_nt_acl);
2668 return result;
2671 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2672 struct smb_filename *file,
2673 struct security_acl *sacl,
2674 uint32_t access_requested,
2675 uint32_t access_denied)
2677 return NT_STATUS_OK; /* Nothing to do here ... */
2680 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2681 const struct smb_filename *smb_fname,
2682 mode_t mode)
2684 #ifdef HAVE_NO_ACL
2685 errno = ENOSYS;
2686 return -1;
2687 #else
2688 int result;
2690 START_PROFILE(chmod_acl);
2691 result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2692 END_PROFILE(chmod_acl);
2693 return result;
2694 #endif
2697 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2699 #ifdef HAVE_NO_ACL
2700 errno = ENOSYS;
2701 return -1;
2702 #else
2703 int result;
2705 START_PROFILE(fchmod_acl);
2706 result = fchmod_acl(fsp, mode);
2707 END_PROFILE(fchmod_acl);
2708 return result;
2709 #endif
2712 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2713 const char *path_p,
2714 SMB_ACL_TYPE_T type,
2715 TALLOC_CTX *mem_ctx)
2717 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2720 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2721 files_struct *fsp,
2722 TALLOC_CTX *mem_ctx)
2724 return sys_acl_get_fd(handle, fsp, mem_ctx);
2727 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2729 return sys_acl_set_file(handle, name, acltype, theacl);
2732 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2734 return sys_acl_set_fd(handle, fsp, theacl);
2737 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2738 const struct smb_filename *smb_fname)
2740 return sys_acl_delete_def_file(handle, smb_fname);
2743 /****************************************************************
2744 Extended attribute operations.
2745 *****************************************************************/
2747 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2749 return getxattr(path, name, value, size);
2752 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2754 return fgetxattr(fsp->fh->fd, name, value, size);
2757 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2759 return listxattr(path, list, size);
2762 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2764 return flistxattr(fsp->fh->fd, list, size);
2767 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2769 return removexattr(path, name);
2772 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2774 return fremovexattr(fsp->fh->fd, name);
2777 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2779 return setxattr(path, name, value, size, flags);
2782 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2784 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2787 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2789 return false;
2792 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2793 const struct smb_filename *fname,
2794 SMB_STRUCT_STAT *sbuf)
2796 NTSTATUS status;
2797 char *path;
2798 bool offline = false;
2800 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2801 return false;
2804 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2805 #if defined(ENOTSUP)
2806 errno = ENOTSUP;
2807 #endif
2808 return false;
2811 status = get_full_smb_filename(talloc_tos(), fname, &path);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 errno = map_errno_from_nt_status(status);
2814 return false;
2817 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2819 TALLOC_FREE(path);
2821 return offline;
2824 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2825 struct files_struct *fsp,
2826 TALLOC_CTX *mem_ctx,
2827 DATA_BLOB *cookie)
2829 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2832 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2833 struct files_struct *fsp,
2834 const DATA_BLOB old_cookie,
2835 TALLOC_CTX *mem_ctx,
2836 DATA_BLOB *new_cookie)
2838 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2839 new_cookie);
2842 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2843 struct smb_request *smb1req,
2844 struct smbXsrv_open *op,
2845 const DATA_BLOB old_cookie,
2846 TALLOC_CTX *mem_ctx,
2847 struct files_struct **fsp,
2848 DATA_BLOB *new_cookie)
2850 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2851 old_cookie, mem_ctx,
2852 fsp, new_cookie);
2855 static struct vfs_fn_pointers vfs_default_fns = {
2856 /* Disk operations */
2858 .connect_fn = vfswrap_connect,
2859 .disconnect_fn = vfswrap_disconnect,
2860 .disk_free_fn = vfswrap_disk_free,
2861 .get_quota_fn = vfswrap_get_quota,
2862 .set_quota_fn = vfswrap_set_quota,
2863 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2864 .statvfs_fn = vfswrap_statvfs,
2865 .fs_capabilities_fn = vfswrap_fs_capabilities,
2866 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2867 .snap_check_path_fn = vfswrap_snap_check_path,
2868 .snap_create_fn = vfswrap_snap_create,
2869 .snap_delete_fn = vfswrap_snap_delete,
2871 /* Directory operations */
2873 .opendir_fn = vfswrap_opendir,
2874 .fdopendir_fn = vfswrap_fdopendir,
2875 .readdir_fn = vfswrap_readdir,
2876 .readdir_attr_fn = vfswrap_readdir_attr,
2877 .seekdir_fn = vfswrap_seekdir,
2878 .telldir_fn = vfswrap_telldir,
2879 .rewind_dir_fn = vfswrap_rewinddir,
2880 .mkdir_fn = vfswrap_mkdir,
2881 .rmdir_fn = vfswrap_rmdir,
2882 .closedir_fn = vfswrap_closedir,
2883 .init_search_op_fn = vfswrap_init_search_op,
2885 /* File operations */
2887 .open_fn = vfswrap_open,
2888 .create_file_fn = vfswrap_create_file,
2889 .close_fn = vfswrap_close,
2890 .read_fn = vfswrap_read,
2891 .pread_fn = vfswrap_pread,
2892 .pread_send_fn = vfswrap_pread_send,
2893 .pread_recv_fn = vfswrap_pread_recv,
2894 .write_fn = vfswrap_write,
2895 .pwrite_fn = vfswrap_pwrite,
2896 .pwrite_send_fn = vfswrap_pwrite_send,
2897 .pwrite_recv_fn = vfswrap_pwrite_recv,
2898 .lseek_fn = vfswrap_lseek,
2899 .sendfile_fn = vfswrap_sendfile,
2900 .recvfile_fn = vfswrap_recvfile,
2901 .rename_fn = vfswrap_rename,
2902 .fsync_fn = vfswrap_fsync,
2903 .fsync_send_fn = vfswrap_fsync_send,
2904 .fsync_recv_fn = vfswrap_fsync_recv,
2905 .stat_fn = vfswrap_stat,
2906 .fstat_fn = vfswrap_fstat,
2907 .lstat_fn = vfswrap_lstat,
2908 .get_alloc_size_fn = vfswrap_get_alloc_size,
2909 .unlink_fn = vfswrap_unlink,
2910 .chmod_fn = vfswrap_chmod,
2911 .fchmod_fn = vfswrap_fchmod,
2912 .chown_fn = vfswrap_chown,
2913 .fchown_fn = vfswrap_fchown,
2914 .lchown_fn = vfswrap_lchown,
2915 .chdir_fn = vfswrap_chdir,
2916 .getwd_fn = vfswrap_getwd,
2917 .ntimes_fn = vfswrap_ntimes,
2918 .ftruncate_fn = vfswrap_ftruncate,
2919 .fallocate_fn = vfswrap_fallocate,
2920 .lock_fn = vfswrap_lock,
2921 .kernel_flock_fn = vfswrap_kernel_flock,
2922 .linux_setlease_fn = vfswrap_linux_setlease,
2923 .getlock_fn = vfswrap_getlock,
2924 .symlink_fn = vfswrap_symlink,
2925 .readlink_fn = vfswrap_readlink,
2926 .link_fn = vfswrap_link,
2927 .mknod_fn = vfswrap_mknod,
2928 .realpath_fn = vfswrap_realpath,
2929 .chflags_fn = vfswrap_chflags,
2930 .file_id_create_fn = vfswrap_file_id_create,
2931 .streaminfo_fn = vfswrap_streaminfo,
2932 .get_real_filename_fn = vfswrap_get_real_filename,
2933 .connectpath_fn = vfswrap_connectpath,
2934 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2935 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2936 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2937 .strict_lock_fn = vfswrap_strict_lock,
2938 .strict_unlock_fn = vfswrap_strict_unlock,
2939 .translate_name_fn = vfswrap_translate_name,
2940 .fsctl_fn = vfswrap_fsctl,
2941 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2942 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2943 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2944 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2945 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2946 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2947 .get_compression_fn = vfswrap_get_compression,
2948 .set_compression_fn = vfswrap_set_compression,
2950 /* NT ACL operations. */
2952 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2953 .get_nt_acl_fn = vfswrap_get_nt_acl,
2954 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2955 .audit_file_fn = vfswrap_audit_file,
2957 /* POSIX ACL operations. */
2959 .chmod_acl_fn = vfswrap_chmod_acl,
2960 .fchmod_acl_fn = vfswrap_fchmod_acl,
2962 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2963 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2964 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2965 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2966 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2967 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2968 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2970 /* EA operations. */
2971 .getxattr_fn = vfswrap_getxattr,
2972 .fgetxattr_fn = vfswrap_fgetxattr,
2973 .listxattr_fn = vfswrap_listxattr,
2974 .flistxattr_fn = vfswrap_flistxattr,
2975 .removexattr_fn = vfswrap_removexattr,
2976 .fremovexattr_fn = vfswrap_fremovexattr,
2977 .setxattr_fn = vfswrap_setxattr,
2978 .fsetxattr_fn = vfswrap_fsetxattr,
2980 /* aio operations */
2981 .aio_force_fn = vfswrap_aio_force,
2983 /* durable handle operations */
2984 .durable_cookie_fn = vfswrap_durable_cookie,
2985 .durable_disconnect_fn = vfswrap_durable_disconnect,
2986 .durable_reconnect_fn = vfswrap_durable_reconnect,
2989 NTSTATUS vfs_default_init(TALLOC_CTX *);
2990 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
2992 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2993 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);