s3: VFS: Change SMB_VFS_CHDIR to use const struct smb_filename * instead of const...
[Samba.git] / source3 / modules / vfs_default.c
blob7a2fae2156d91576cbd6923e388a7952bf6cd5bb
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,
59 const struct smb_filename *smb_fname,
60 uint64_t *bsize,
61 uint64_t *dfree,
62 uint64_t *dsize)
64 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
65 return (uint64_t)-1;
68 *bsize = 512;
69 return *dfree / 2;
72 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
73 const struct smb_filename *smb_fname,
74 enum SMB_QUOTA_TYPE qtype,
75 unid_t id,
76 SMB_DISK_QUOTA *qt)
78 #ifdef HAVE_SYS_QUOTAS
79 int result;
81 START_PROFILE(syscall_get_quota);
82 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
83 END_PROFILE(syscall_get_quota);
84 return result;
85 #else
86 errno = ENOSYS;
87 return -1;
88 #endif
91 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
93 #ifdef HAVE_SYS_QUOTAS
94 int result;
96 START_PROFILE(syscall_set_quota);
97 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
98 END_PROFILE(syscall_set_quota);
99 return result;
100 #else
101 errno = ENOSYS;
102 return -1;
103 #endif
106 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
107 struct files_struct *fsp,
108 struct shadow_copy_data *shadow_copy_data,
109 bool labels)
111 errno = ENOSYS;
112 return -1; /* Not implemented. */
115 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
116 const struct smb_filename *smb_fname,
117 vfs_statvfs_struct *statbuf)
119 return sys_statvfs(smb_fname->base_name, statbuf);
122 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
123 enum timestamp_set_resolution *p_ts_res)
125 connection_struct *conn = handle->conn;
126 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
127 struct smb_filename *smb_fname_cpath = NULL;
128 struct vfs_statvfs_struct statbuf;
129 int ret;
131 ZERO_STRUCT(statbuf);
132 ret = sys_statvfs(conn->connectpath, &statbuf);
133 if (ret == 0) {
134 caps = statbuf.FsCapabilities;
137 *p_ts_res = TIMESTAMP_SET_SECONDS;
139 /* Work out what timestamp resolution we can
140 * use when setting a timestamp. */
142 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
143 NULL, NULL, 0);
144 if (smb_fname_cpath == NULL) {
145 return caps;
148 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
149 if (ret == -1) {
150 TALLOC_FREE(smb_fname_cpath);
151 return caps;
154 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
155 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
157 /* If any of the normal UNIX directory timestamps
158 * have a non-zero tv_nsec component assume
159 * we might be able to set sub-second timestamps.
160 * See what filetime set primitives we have.
162 #if defined(HAVE_UTIMENSAT)
163 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
164 #elif defined(HAVE_UTIMES)
165 /* utimes allows msec timestamps to be set. */
166 *p_ts_res = TIMESTAMP_SET_MSEC;
167 #elif defined(HAVE_UTIME)
168 /* utime only allows sec timestamps to be set. */
169 *p_ts_res = TIMESTAMP_SET_SECONDS;
170 #endif
172 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
173 "resolution of %s "
174 "available on share %s, directory %s\n",
175 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
176 lp_servicename(talloc_tos(), conn->params->service),
177 conn->connectpath ));
179 TALLOC_FREE(smb_fname_cpath);
180 return caps;
183 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
184 struct dfs_GetDFSReferral *r)
186 struct junction_map *junction = NULL;
187 int consumedcnt = 0;
188 bool self_referral = false;
189 char *pathnamep = NULL;
190 char *local_dfs_path = NULL;
191 NTSTATUS status;
192 int i;
193 uint16_t max_referral_level = r->in.req.max_referral_level;
195 if (DEBUGLVL(10)) {
196 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
199 /* get the junction entry */
200 if (r->in.req.servername == NULL) {
201 return NT_STATUS_NOT_FOUND;
205 * Trim pathname sent by client so it begins with only one backslash.
206 * Two backslashes confuse some dfs clients
209 local_dfs_path = talloc_strdup(r, r->in.req.servername);
210 if (local_dfs_path == NULL) {
211 return NT_STATUS_NO_MEMORY;
213 pathnamep = local_dfs_path;
214 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
215 IS_DIRECTORY_SEP(pathnamep[1])) {
216 pathnamep++;
219 junction = talloc_zero(r, struct junction_map);
220 if (junction == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 /* The following call can change cwd. */
225 status = get_referred_path(r, pathnamep,
226 handle->conn->sconn->remote_address,
227 handle->conn->sconn->local_address,
228 !handle->conn->sconn->using_smb2,
229 junction, &consumedcnt, &self_referral);
230 if (!NT_STATUS_IS_OK(status)) {
231 struct smb_filename connectpath_fname = {
232 .base_name = handle->conn->connectpath
234 vfs_ChDir(handle->conn, &connectpath_fname);
235 return status;
238 struct smb_filename connectpath_fname = {
239 .base_name = handle->conn->connectpath
241 vfs_ChDir(handle->conn, &connectpath_fname);
244 if (!self_referral) {
245 pathnamep[consumedcnt] = '\0';
247 if (DEBUGLVL(3)) {
248 dbgtext("Path %s to alternate path(s):",
249 pathnamep);
250 for (i=0; i < junction->referral_count; i++) {
251 dbgtext(" %s",
252 junction->referral_list[i].alternate_path);
254 dbgtext(".\n");
258 if (r->in.req.max_referral_level <= 2) {
259 max_referral_level = 2;
261 if (r->in.req.max_referral_level >= 3) {
262 max_referral_level = 3;
265 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
266 if (r->out.resp == NULL) {
267 return NT_STATUS_NO_MEMORY;
270 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
271 r->out.resp->nb_referrals = junction->referral_count;
273 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
274 if (self_referral) {
275 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
278 r->out.resp->referral_entries = talloc_zero_array(r,
279 struct dfs_referral_type,
280 r->out.resp->nb_referrals);
281 if (r->out.resp->referral_entries == NULL) {
282 return NT_STATUS_NO_MEMORY;
285 switch (max_referral_level) {
286 case 2:
287 for(i=0; i < junction->referral_count; i++) {
288 struct referral *ref = &junction->referral_list[i];
289 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
290 struct dfs_referral_type *t =
291 &r->out.resp->referral_entries[i];
292 struct dfs_referral_v2 *v2 = &t->referral.v2;
294 t->version = 2;
295 v2->size = VERSION2_REFERRAL_SIZE;
296 if (self_referral) {
297 v2->server_type = DFS_SERVER_ROOT;
298 } else {
299 v2->server_type = DFS_SERVER_NON_ROOT;
301 v2->entry_flags = 0;
302 v2->proximity = ref->proximity;
303 v2->ttl = ref->ttl;
304 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
305 if (v2->DFS_path == NULL) {
306 return NT_STATUS_NO_MEMORY;
308 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
309 if (v2->DFS_alt_path == NULL) {
310 return NT_STATUS_NO_MEMORY;
312 v2->netw_address = talloc_strdup(mem_ctx,
313 ref->alternate_path);
314 if (v2->netw_address == NULL) {
315 return NT_STATUS_NO_MEMORY;
319 break;
320 case 3:
321 for(i=0; i < junction->referral_count; i++) {
322 struct referral *ref = &junction->referral_list[i];
323 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
324 struct dfs_referral_type *t =
325 &r->out.resp->referral_entries[i];
326 struct dfs_referral_v3 *v3 = &t->referral.v3;
327 struct dfs_normal_referral *r1 = &v3->referrals.r1;
329 t->version = 3;
330 v3->size = VERSION3_REFERRAL_SIZE;
331 if (self_referral) {
332 v3->server_type = DFS_SERVER_ROOT;
333 } else {
334 v3->server_type = DFS_SERVER_NON_ROOT;
336 v3->entry_flags = 0;
337 v3->ttl = ref->ttl;
338 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
339 if (r1->DFS_path == NULL) {
340 return NT_STATUS_NO_MEMORY;
342 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
343 if (r1->DFS_alt_path == NULL) {
344 return NT_STATUS_NO_MEMORY;
346 r1->netw_address = talloc_strdup(mem_ctx,
347 ref->alternate_path);
348 if (r1->netw_address == NULL) {
349 return NT_STATUS_NO_MEMORY;
352 break;
353 default:
354 DEBUG(0,("Invalid dfs referral version: %d\n",
355 max_referral_level));
356 return NT_STATUS_INVALID_LEVEL;
359 if (DEBUGLVL(10)) {
360 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
363 return NT_STATUS_OK;
366 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
367 TALLOC_CTX *mem_ctx,
368 const char *service_path,
369 char **base_volume)
371 return NT_STATUS_NOT_SUPPORTED;
374 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
375 TALLOC_CTX *mem_ctx,
376 const char *base_volume,
377 time_t *tstamp,
378 bool rw,
379 char **base_path,
380 char **snap_path)
382 return NT_STATUS_NOT_SUPPORTED;
385 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
386 TALLOC_CTX *mem_ctx,
387 char *base_path,
388 char *snap_path)
390 return NT_STATUS_NOT_SUPPORTED;
393 /* Directory operations */
395 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
396 const struct smb_filename *smb_fname,
397 const char *mask,
398 uint32_t attr)
400 DIR *result;
402 START_PROFILE(syscall_opendir);
403 result = opendir(smb_fname->base_name);
404 END_PROFILE(syscall_opendir);
405 return result;
408 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
409 files_struct *fsp,
410 const char *mask,
411 uint32_t attr)
413 DIR *result;
415 START_PROFILE(syscall_fdopendir);
416 result = sys_fdopendir(fsp->fh->fd);
417 END_PROFILE(syscall_fdopendir);
418 return result;
422 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
423 DIR *dirp,
424 SMB_STRUCT_STAT *sbuf)
426 struct dirent *result;
428 START_PROFILE(syscall_readdir);
429 result = readdir(dirp);
430 END_PROFILE(syscall_readdir);
431 if (sbuf) {
432 /* Default Posix readdir() does not give us stat info.
433 * Set to invalid to indicate we didn't return this info. */
434 SET_STAT_INVALID(*sbuf);
435 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
436 if (result != NULL) {
437 /* See if we can efficiently return this. */
438 struct stat st;
439 int flags = AT_SYMLINK_NOFOLLOW;
440 int ret = fstatat(dirfd(dirp),
441 result->d_name,
442 &st,
443 flags);
445 * As this is an optimization,
446 * ignore it if we stat'ed a
447 * symlink. Make the caller
448 * do it again as we don't
449 * know if they wanted the link
450 * info, or its target info.
452 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
453 init_stat_ex_from_stat(sbuf,
454 &st,
455 lp_fake_directory_create_times(
456 SNUM(handle->conn)));
459 #endif
461 return result;
464 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
465 const struct smb_filename *fname,
466 TALLOC_CTX *mem_ctx,
467 struct readdir_attr_data **attr_data)
469 return NT_STATUS_NOT_SUPPORTED;
472 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
474 START_PROFILE(syscall_seekdir);
475 seekdir(dirp, offset);
476 END_PROFILE(syscall_seekdir);
479 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
481 long result;
482 START_PROFILE(syscall_telldir);
483 result = telldir(dirp);
484 END_PROFILE(syscall_telldir);
485 return result;
488 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
490 START_PROFILE(syscall_rewinddir);
491 rewinddir(dirp);
492 END_PROFILE(syscall_rewinddir);
495 static int vfswrap_mkdir(vfs_handle_struct *handle,
496 const struct smb_filename *smb_fname,
497 mode_t mode)
499 int result;
500 bool has_dacl = False;
501 const char *path = smb_fname->base_name;
502 char *parent = NULL;
504 START_PROFILE(syscall_mkdir);
506 if (lp_inherit_acls(SNUM(handle->conn))
507 && parent_dirname(talloc_tos(), path, &parent, NULL)
508 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
509 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
512 TALLOC_FREE(parent);
514 result = mkdir(path, mode);
516 if (result == 0 && !has_dacl) {
518 * We need to do this as the default behavior of POSIX ACLs
519 * is to set the mask to be the requested group permission
520 * bits, not the group permission bits to be the requested
521 * group permission bits. This is not what we want, as it will
522 * mess up any inherited ACL bits that were set. JRA.
524 int saved_errno = errno; /* We may get ENOSYS */
525 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
526 (errno == ENOSYS)) {
527 errno = saved_errno;
531 END_PROFILE(syscall_mkdir);
532 return result;
535 static int vfswrap_rmdir(vfs_handle_struct *handle,
536 const struct smb_filename *smb_fname)
538 int result;
540 START_PROFILE(syscall_rmdir);
541 result = rmdir(smb_fname->base_name);
542 END_PROFILE(syscall_rmdir);
543 return result;
546 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
548 int result;
550 START_PROFILE(syscall_closedir);
551 result = closedir(dirp);
552 END_PROFILE(syscall_closedir);
553 return result;
556 static void vfswrap_init_search_op(vfs_handle_struct *handle,
557 DIR *dirp)
559 /* Default behavior is a NOOP */
562 /* File operations */
564 static int vfswrap_open(vfs_handle_struct *handle,
565 struct smb_filename *smb_fname,
566 files_struct *fsp, int flags, mode_t mode)
568 int result = -1;
570 START_PROFILE(syscall_open);
572 if (smb_fname->stream_name) {
573 errno = ENOENT;
574 goto out;
577 result = open(smb_fname->base_name, flags, mode);
578 out:
579 END_PROFILE(syscall_open);
580 return result;
583 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
584 struct smb_request *req,
585 uint16_t root_dir_fid,
586 struct smb_filename *smb_fname,
587 uint32_t access_mask,
588 uint32_t share_access,
589 uint32_t create_disposition,
590 uint32_t create_options,
591 uint32_t file_attributes,
592 uint32_t oplock_request,
593 struct smb2_lease *lease,
594 uint64_t allocation_size,
595 uint32_t private_flags,
596 struct security_descriptor *sd,
597 struct ea_list *ea_list,
598 files_struct **result,
599 int *pinfo,
600 const struct smb2_create_blobs *in_context_blobs,
601 struct smb2_create_blobs *out_context_blobs)
603 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
604 access_mask, share_access,
605 create_disposition, create_options,
606 file_attributes, oplock_request, lease,
607 allocation_size, private_flags,
608 sd, ea_list, result,
609 pinfo, in_context_blobs, out_context_blobs);
612 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
614 int result;
616 START_PROFILE(syscall_close);
617 result = fd_close_posix(fsp);
618 END_PROFILE(syscall_close);
619 return result;
622 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
624 ssize_t result;
626 START_PROFILE_BYTES(syscall_read, n);
627 result = sys_read(fsp->fh->fd, data, n);
628 END_PROFILE_BYTES(syscall_read);
629 return result;
632 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
633 size_t n, off_t offset)
635 ssize_t result;
637 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
638 START_PROFILE_BYTES(syscall_pread, n);
639 result = sys_pread(fsp->fh->fd, data, n, offset);
640 END_PROFILE_BYTES(syscall_pread);
642 if (result == -1 && errno == ESPIPE) {
643 /* Maintain the fiction that pipes can be seeked (sought?) on. */
644 result = SMB_VFS_READ(fsp, data, n);
645 fsp->fh->pos = 0;
648 #else /* HAVE_PREAD */
649 off_t curr;
650 int lerrno;
652 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
653 if (curr == -1 && errno == ESPIPE) {
654 /* Maintain the fiction that pipes can be seeked (sought?) on. */
655 result = SMB_VFS_READ(fsp, data, n);
656 fsp->fh->pos = 0;
657 return result;
660 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
661 return -1;
664 errno = 0;
665 result = SMB_VFS_READ(fsp, data, n);
666 lerrno = errno;
668 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
669 errno = lerrno;
671 #endif /* HAVE_PREAD */
673 return result;
676 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
678 ssize_t result;
680 START_PROFILE_BYTES(syscall_write, n);
681 result = sys_write(fsp->fh->fd, data, n);
682 END_PROFILE_BYTES(syscall_write);
683 return result;
686 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
687 size_t n, off_t offset)
689 ssize_t result;
691 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
692 START_PROFILE_BYTES(syscall_pwrite, n);
693 result = sys_pwrite(fsp->fh->fd, data, n, offset);
694 END_PROFILE_BYTES(syscall_pwrite);
696 if (result == -1 && errno == ESPIPE) {
697 /* Maintain the fiction that pipes can be sought on. */
698 result = SMB_VFS_WRITE(fsp, data, n);
701 #else /* HAVE_PWRITE */
702 off_t curr;
703 int lerrno;
705 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
706 if (curr == -1) {
707 return -1;
710 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
711 return -1;
714 result = SMB_VFS_WRITE(fsp, data, n);
715 lerrno = errno;
717 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
718 errno = lerrno;
720 #endif /* HAVE_PWRITE */
722 return result;
725 static int vfswrap_init_pool(struct smbd_server_connection *conn)
727 int ret;
729 if (conn->pool != NULL) {
730 return 0;
733 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
734 &conn->pool);
735 return ret;
738 struct vfswrap_pread_state {
739 ssize_t ret;
740 int err;
741 int fd;
742 void *buf;
743 size_t count;
744 off_t offset;
746 struct vfs_aio_state vfs_aio_state;
747 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
750 static void vfs_pread_do(void *private_data);
751 static void vfs_pread_done(struct tevent_req *subreq);
753 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
754 TALLOC_CTX *mem_ctx,
755 struct tevent_context *ev,
756 struct files_struct *fsp,
757 void *data,
758 size_t n, off_t offset)
760 struct tevent_req *req, *subreq;
761 struct vfswrap_pread_state *state;
762 int ret;
764 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
765 if (req == NULL) {
766 return NULL;
769 ret = vfswrap_init_pool(handle->conn->sconn);
770 if (tevent_req_error(req, ret)) {
771 return tevent_req_post(req, ev);
774 state->ret = -1;
775 state->fd = fsp->fh->fd;
776 state->buf = data;
777 state->count = n;
778 state->offset = offset;
780 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
781 state->profile_bytes, n);
782 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
784 subreq = pthreadpool_tevent_job_send(
785 state, ev, handle->conn->sconn->pool,
786 vfs_pread_do, state);
787 if (tevent_req_nomem(subreq, req)) {
788 return tevent_req_post(req, ev);
790 tevent_req_set_callback(subreq, vfs_pread_done, req);
792 return req;
795 static void vfs_pread_do(void *private_data)
797 struct vfswrap_pread_state *state = talloc_get_type_abort(
798 private_data, struct vfswrap_pread_state);
799 struct timespec start_time;
800 struct timespec end_time;
802 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
804 PROFILE_TIMESTAMP(&start_time);
806 do {
807 state->ret = pread(state->fd, state->buf, state->count,
808 state->offset);
809 } while ((state->ret == -1) && (errno == EINTR));
811 state->err = errno;
813 PROFILE_TIMESTAMP(&end_time);
815 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
817 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
820 static void vfs_pread_done(struct tevent_req *subreq)
822 struct tevent_req *req = tevent_req_callback_data(
823 subreq, struct tevent_req);
824 #ifdef WITH_PROFILE
825 struct vfswrap_pread_state *state = tevent_req_data(
826 req, struct vfswrap_pread_state);
827 #endif
828 int ret;
830 ret = pthreadpool_tevent_job_recv(subreq);
831 TALLOC_FREE(subreq);
832 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
833 if (tevent_req_error(req, ret)) {
834 return;
837 tevent_req_done(req);
840 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
841 struct vfs_aio_state *vfs_aio_state)
843 struct vfswrap_pread_state *state = tevent_req_data(
844 req, struct vfswrap_pread_state);
846 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
847 return -1;
850 *vfs_aio_state = state->vfs_aio_state;
851 return state->ret;
854 struct vfswrap_pwrite_state {
855 ssize_t ret;
856 int err;
857 int fd;
858 const void *buf;
859 size_t count;
860 off_t offset;
862 struct vfs_aio_state vfs_aio_state;
863 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
866 static void vfs_pwrite_do(void *private_data);
867 static void vfs_pwrite_done(struct tevent_req *subreq);
869 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
870 TALLOC_CTX *mem_ctx,
871 struct tevent_context *ev,
872 struct files_struct *fsp,
873 const void *data,
874 size_t n, off_t offset)
876 struct tevent_req *req, *subreq;
877 struct vfswrap_pwrite_state *state;
878 int ret;
880 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
881 if (req == NULL) {
882 return NULL;
885 ret = vfswrap_init_pool(handle->conn->sconn);
886 if (tevent_req_error(req, ret)) {
887 return tevent_req_post(req, ev);
890 state->ret = -1;
891 state->fd = fsp->fh->fd;
892 state->buf = data;
893 state->count = n;
894 state->offset = offset;
896 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
897 state->profile_bytes, n);
898 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
900 subreq = pthreadpool_tevent_job_send(
901 state, ev, handle->conn->sconn->pool,
902 vfs_pwrite_do, state);
903 if (tevent_req_nomem(subreq, req)) {
904 return tevent_req_post(req, ev);
906 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
908 return req;
911 static void vfs_pwrite_do(void *private_data)
913 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
914 private_data, struct vfswrap_pwrite_state);
915 struct timespec start_time;
916 struct timespec end_time;
918 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
920 PROFILE_TIMESTAMP(&start_time);
922 do {
923 state->ret = pwrite(state->fd, state->buf, state->count,
924 state->offset);
925 } while ((state->ret == -1) && (errno == EINTR));
927 state->err = errno;
929 PROFILE_TIMESTAMP(&end_time);
931 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
933 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
936 static void vfs_pwrite_done(struct tevent_req *subreq)
938 struct tevent_req *req = tevent_req_callback_data(
939 subreq, struct tevent_req);
940 #ifdef WITH_PROFILE
941 struct vfswrap_pwrite_state *state = tevent_req_data(
942 req, struct vfswrap_pwrite_state);
943 #endif
944 int ret;
946 ret = pthreadpool_tevent_job_recv(subreq);
947 TALLOC_FREE(subreq);
948 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
949 if (tevent_req_error(req, ret)) {
950 return;
953 tevent_req_done(req);
956 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
957 struct vfs_aio_state *vfs_aio_state)
959 struct vfswrap_pwrite_state *state = tevent_req_data(
960 req, struct vfswrap_pwrite_state);
962 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
963 return -1;
966 *vfs_aio_state = state->vfs_aio_state;
967 return state->ret;
970 struct vfswrap_fsync_state {
971 ssize_t ret;
972 int err;
973 int fd;
975 struct vfs_aio_state vfs_aio_state;
976 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
979 static void vfs_fsync_do(void *private_data);
980 static void vfs_fsync_done(struct tevent_req *subreq);
982 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
983 TALLOC_CTX *mem_ctx,
984 struct tevent_context *ev,
985 struct files_struct *fsp)
987 struct tevent_req *req, *subreq;
988 struct vfswrap_fsync_state *state;
989 int ret;
991 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
992 if (req == NULL) {
993 return NULL;
996 ret = vfswrap_init_pool(handle->conn->sconn);
997 if (tevent_req_error(req, ret)) {
998 return tevent_req_post(req, ev);
1001 state->ret = -1;
1002 state->fd = fsp->fh->fd;
1004 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1005 state->profile_basic);
1007 subreq = pthreadpool_tevent_job_send(
1008 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1009 if (tevent_req_nomem(subreq, req)) {
1010 return tevent_req_post(req, ev);
1012 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1014 return req;
1017 static void vfs_fsync_do(void *private_data)
1019 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1020 private_data, struct vfswrap_fsync_state);
1021 struct timespec start_time;
1022 struct timespec end_time;
1024 PROFILE_TIMESTAMP(&start_time);
1026 do {
1027 state->ret = fsync(state->fd);
1028 } while ((state->ret == -1) && (errno == EINTR));
1030 state->err = errno;
1032 PROFILE_TIMESTAMP(&end_time);
1034 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1037 static void vfs_fsync_done(struct tevent_req *subreq)
1039 struct tevent_req *req = tevent_req_callback_data(
1040 subreq, struct tevent_req);
1041 #ifdef WITH_PROFILE
1042 struct vfswrap_fsync_state *state = tevent_req_data(
1043 req, struct vfswrap_fsync_state);
1044 #endif
1045 int ret;
1047 ret = pthreadpool_tevent_job_recv(subreq);
1048 TALLOC_FREE(subreq);
1049 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1050 if (tevent_req_error(req, ret)) {
1051 return;
1054 tevent_req_done(req);
1057 static int vfswrap_fsync_recv(struct tevent_req *req,
1058 struct vfs_aio_state *vfs_aio_state)
1060 struct vfswrap_fsync_state *state = tevent_req_data(
1061 req, struct vfswrap_fsync_state);
1063 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1064 return -1;
1067 *vfs_aio_state = state->vfs_aio_state;
1068 return state->ret;
1071 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1073 off_t result = 0;
1075 START_PROFILE(syscall_lseek);
1077 /* Cope with 'stat' file opens. */
1078 if (fsp->fh->fd != -1)
1079 result = lseek(fsp->fh->fd, offset, whence);
1082 * We want to maintain the fiction that we can seek
1083 * on a fifo for file system purposes. This allows
1084 * people to set up UNIX fifo's that feed data to Windows
1085 * applications. JRA.
1088 if((result == -1) && (errno == ESPIPE)) {
1089 result = 0;
1090 errno = 0;
1093 END_PROFILE(syscall_lseek);
1094 return result;
1097 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1098 off_t offset, size_t n)
1100 ssize_t result;
1102 START_PROFILE_BYTES(syscall_sendfile, n);
1103 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1104 END_PROFILE_BYTES(syscall_sendfile);
1105 return result;
1108 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1109 int fromfd,
1110 files_struct *tofsp,
1111 off_t offset,
1112 size_t n)
1114 ssize_t result;
1116 START_PROFILE_BYTES(syscall_recvfile, n);
1117 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1118 END_PROFILE_BYTES(syscall_recvfile);
1119 return result;
1122 static int vfswrap_rename(vfs_handle_struct *handle,
1123 const struct smb_filename *smb_fname_src,
1124 const struct smb_filename *smb_fname_dst)
1126 int result = -1;
1128 START_PROFILE(syscall_rename);
1130 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1131 errno = ENOENT;
1132 goto out;
1135 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1137 out:
1138 END_PROFILE(syscall_rename);
1139 return result;
1142 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1144 #ifdef HAVE_FSYNC
1145 int result;
1147 START_PROFILE(syscall_fsync);
1148 result = fsync(fsp->fh->fd);
1149 END_PROFILE(syscall_fsync);
1150 return result;
1151 #else
1152 return 0;
1153 #endif
1156 static int vfswrap_stat(vfs_handle_struct *handle,
1157 struct smb_filename *smb_fname)
1159 int result = -1;
1161 START_PROFILE(syscall_stat);
1163 if (smb_fname->stream_name) {
1164 errno = ENOENT;
1165 goto out;
1168 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1169 lp_fake_directory_create_times(SNUM(handle->conn)));
1170 out:
1171 END_PROFILE(syscall_stat);
1172 return result;
1175 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1177 int result;
1179 START_PROFILE(syscall_fstat);
1180 result = sys_fstat(fsp->fh->fd,
1181 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1182 END_PROFILE(syscall_fstat);
1183 return result;
1186 static int vfswrap_lstat(vfs_handle_struct *handle,
1187 struct smb_filename *smb_fname)
1189 int result = -1;
1191 START_PROFILE(syscall_lstat);
1193 if (smb_fname->stream_name) {
1194 errno = ENOENT;
1195 goto out;
1198 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1199 lp_fake_directory_create_times(SNUM(handle->conn)));
1200 out:
1201 END_PROFILE(syscall_lstat);
1202 return result;
1205 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1206 const char *name,
1207 enum vfs_translate_direction direction,
1208 TALLOC_CTX *mem_ctx,
1209 char **mapped_name)
1211 return NT_STATUS_NONE_MAPPED;
1215 * Implement the default fsctl operation.
1217 static bool vfswrap_logged_ioctl_message = false;
1219 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1220 struct files_struct *fsp,
1221 TALLOC_CTX *ctx,
1222 uint32_t function,
1223 uint16_t req_flags, /* Needed for UNICODE ... */
1224 const uint8_t *_in_data,
1225 uint32_t in_len,
1226 uint8_t **_out_data,
1227 uint32_t max_out_len,
1228 uint32_t *out_len)
1230 const char *in_data = (const char *)_in_data;
1231 char **out_data = (char **)_out_data;
1232 NTSTATUS status;
1234 switch (function) {
1235 case FSCTL_SET_SPARSE:
1237 bool set_sparse = true;
1239 if (in_len >= 1 && in_data[0] == 0) {
1240 set_sparse = false;
1243 status = file_set_sparse(handle->conn, fsp, set_sparse);
1245 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1246 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1247 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1248 nt_errstr(status)));
1250 return status;
1253 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1255 unsigned char objid[16];
1256 char *return_data = NULL;
1258 /* This should return the object-id on this file.
1259 * I think I'll make this be the inode+dev. JRA.
1262 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1263 fsp_fnum_dbg(fsp)));
1265 *out_len = MIN(max_out_len, 64);
1267 /* Hmmm, will this cause problems if less data asked for? */
1268 return_data = talloc_array(ctx, char, 64);
1269 if (return_data == NULL) {
1270 return NT_STATUS_NO_MEMORY;
1273 /* For backwards compatibility only store the dev/inode. */
1274 push_file_id_16(return_data, &fsp->file_id);
1275 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1276 push_file_id_16(return_data+32, &fsp->file_id);
1277 memset(return_data+48, 0, 16);
1278 *out_data = return_data;
1279 return NT_STATUS_OK;
1282 case FSCTL_GET_REPARSE_POINT:
1284 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1285 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1286 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1287 return NT_STATUS_NOT_A_REPARSE_POINT;
1290 case FSCTL_SET_REPARSE_POINT:
1292 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1293 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1294 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1295 return NT_STATUS_NOT_A_REPARSE_POINT;
1298 case FSCTL_GET_SHADOW_COPY_DATA:
1301 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1302 * and return their volume names. If max_data_count is 16, then it is just
1303 * asking for the number of volumes and length of the combined names.
1305 * pdata is the data allocated by our caller, but that uses
1306 * total_data_count (which is 0 in our case) rather than max_data_count.
1307 * Allocate the correct amount and return the pointer to let
1308 * it be deallocated when we return.
1310 struct shadow_copy_data *shadow_data = NULL;
1311 bool labels = False;
1312 uint32_t labels_data_count = 0;
1313 uint32_t i;
1314 char *cur_pdata = NULL;
1316 if (max_out_len < 16) {
1317 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1318 max_out_len));
1319 return NT_STATUS_INVALID_PARAMETER;
1322 if (max_out_len > 16) {
1323 labels = True;
1326 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1327 if (shadow_data == NULL) {
1328 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1329 return NT_STATUS_NO_MEMORY;
1333 * Call the VFS routine to actually do the work.
1335 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1336 int log_lev = 0;
1337 if (errno == 0) {
1338 /* broken module didn't set errno on error */
1339 status = NT_STATUS_UNSUCCESSFUL;
1340 } else {
1341 status = map_nt_error_from_unix(errno);
1342 if (NT_STATUS_EQUAL(status,
1343 NT_STATUS_NOT_SUPPORTED)) {
1344 log_lev = 5;
1347 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1348 "connectpath %s, failed - %s.\n",
1349 fsp->conn->connectpath,
1350 nt_errstr(status)));
1351 TALLOC_FREE(shadow_data);
1352 return status;
1355 labels_data_count = (shadow_data->num_volumes * 2 *
1356 sizeof(SHADOW_COPY_LABEL)) + 2;
1358 if (!labels) {
1359 *out_len = 16;
1360 } else {
1361 *out_len = 12 + labels_data_count;
1364 if (max_out_len < *out_len) {
1365 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1366 max_out_len, *out_len));
1367 TALLOC_FREE(shadow_data);
1368 return NT_STATUS_BUFFER_TOO_SMALL;
1371 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1372 if (cur_pdata == NULL) {
1373 TALLOC_FREE(shadow_data);
1374 return NT_STATUS_NO_MEMORY;
1377 *out_data = cur_pdata;
1379 /* num_volumes 4 bytes */
1380 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1382 if (labels) {
1383 /* num_labels 4 bytes */
1384 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1387 /* needed_data_count 4 bytes */
1388 SIVAL(cur_pdata, 8, labels_data_count);
1390 cur_pdata += 12;
1392 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1393 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1394 if (labels && shadow_data->labels) {
1395 for (i=0; i<shadow_data->num_volumes; i++) {
1396 size_t len = 0;
1397 status = srvstr_push(cur_pdata, req_flags,
1398 cur_pdata, shadow_data->labels[i],
1399 2 * sizeof(SHADOW_COPY_LABEL),
1400 STR_UNICODE|STR_TERMINATE, &len);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 TALLOC_FREE(*out_data);
1403 TALLOC_FREE(shadow_data);
1404 return status;
1406 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1407 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1411 TALLOC_FREE(shadow_data);
1413 return NT_STATUS_OK;
1416 case FSCTL_FIND_FILES_BY_SID:
1418 /* pretend this succeeded -
1420 * we have to send back a list with all files owned by this SID
1422 * but I have to check that --metze
1424 struct dom_sid sid;
1425 uid_t uid;
1426 size_t sid_len;
1428 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1429 fsp_fnum_dbg(fsp)));
1431 if (in_len < 8) {
1432 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1433 return NT_STATUS_INVALID_PARAMETER;
1436 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1438 /* unknown 4 bytes: this is not the length of the sid :-( */
1439 /*unknown = IVAL(pdata,0);*/
1441 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1442 return NT_STATUS_INVALID_PARAMETER;
1444 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1446 if (!sid_to_uid(&sid, &uid)) {
1447 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1448 sid_string_dbg(&sid),
1449 (unsigned long)sid_len));
1450 uid = (-1);
1453 /* we can take a look at the find source :-)
1455 * find ./ -uid $uid -name '*' is what we need here
1458 * and send 4bytes len and then NULL terminated unicode strings
1459 * for each file
1461 * but I don't know how to deal with the paged results
1462 * (maybe we can hang the result anywhere in the fsp struct)
1464 * but I don't know how to deal with the paged results
1465 * (maybe we can hang the result anywhere in the fsp struct)
1467 * we don't send all files at once
1468 * and at the next we should *not* start from the beginning,
1469 * so we have to cache the result
1471 * --metze
1474 /* this works for now... */
1475 return NT_STATUS_OK;
1478 case FSCTL_QUERY_ALLOCATED_RANGES:
1480 /* FIXME: This is just a dummy reply, telling that all of the
1481 * file is allocated. MKS cp needs that.
1482 * Adding the real allocated ranges via FIEMAP on Linux
1483 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1484 * this FSCTL correct for sparse files.
1486 uint64_t offset, length;
1487 char *out_data_tmp = NULL;
1489 if (in_len != 16) {
1490 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1491 in_len));
1492 return NT_STATUS_INVALID_PARAMETER;
1495 if (max_out_len < 16) {
1496 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1497 max_out_len));
1498 return NT_STATUS_INVALID_PARAMETER;
1501 offset = BVAL(in_data,0);
1502 length = BVAL(in_data,8);
1504 if (offset + length < offset) {
1505 /* No 64-bit integer wrap. */
1506 return NT_STATUS_INVALID_PARAMETER;
1509 /* Shouldn't this be SMB_VFS_STAT ... ? */
1510 status = vfs_stat_fsp(fsp);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 return status;
1515 *out_len = 16;
1516 out_data_tmp = talloc_array(ctx, char, *out_len);
1517 if (out_data_tmp == NULL) {
1518 DEBUG(10, ("unable to allocate memory for response\n"));
1519 return NT_STATUS_NO_MEMORY;
1522 if (offset > fsp->fsp_name->st.st_ex_size ||
1523 fsp->fsp_name->st.st_ex_size == 0 ||
1524 length == 0) {
1525 memset(out_data_tmp, 0, *out_len);
1526 } else {
1527 uint64_t end = offset + length;
1528 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1529 SBVAL(out_data_tmp, 0, 0);
1530 SBVAL(out_data_tmp, 8, end);
1533 *out_data = out_data_tmp;
1535 return NT_STATUS_OK;
1538 case FSCTL_IS_VOLUME_DIRTY:
1540 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1541 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1543 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1544 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1546 return NT_STATUS_INVALID_PARAMETER;
1549 default:
1551 * Only print once ... unfortunately there could be lots of
1552 * different FSCTLs that are called.
1554 if (!vfswrap_logged_ioctl_message) {
1555 vfswrap_logged_ioctl_message = true;
1556 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1557 __func__, function));
1561 return NT_STATUS_NOT_SUPPORTED;
1564 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1565 const struct smb_filename *fname,
1566 SMB_STRUCT_STAT *sbuf);
1568 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1569 struct smb_filename *smb_fname,
1570 uint32_t *dosmode)
1572 bool offline;
1574 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1575 if (offline) {
1576 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1579 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1582 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1583 struct files_struct *fsp,
1584 uint32_t *dosmode)
1586 bool offline;
1588 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1589 if (offline) {
1590 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1593 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1596 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1597 const struct smb_filename *smb_fname,
1598 uint32_t dosmode)
1600 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1603 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1604 struct files_struct *fsp,
1605 uint32_t dosmode)
1607 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1610 struct vfs_cc_state {
1611 struct tevent_context *ev;
1612 uint8_t *buf;
1613 bool read_lck_locked;
1614 struct lock_struct read_lck;
1615 bool write_lck_locked;
1616 struct lock_struct write_lck;
1617 struct files_struct *src_fsp;
1618 off_t src_off;
1619 struct files_struct *dst_fsp;
1620 off_t dst_off;
1621 off_t to_copy;
1622 off_t remaining;
1623 size_t next_io_size;
1624 uint32_t flags;
1627 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1629 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1630 TALLOC_CTX *mem_ctx,
1631 struct tevent_context *ev,
1632 struct files_struct *src_fsp,
1633 off_t src_off,
1634 struct files_struct *dest_fsp,
1635 off_t dest_off,
1636 off_t to_copy,
1637 uint32_t flags)
1639 struct tevent_req *req;
1640 struct vfs_cc_state *state = NULL;
1641 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1642 NTSTATUS status;
1644 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1646 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1647 if (req == NULL) {
1648 return NULL;
1651 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1652 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1653 return tevent_req_post(req, ev);
1656 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1657 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1658 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1659 return tevent_req_post(req, ev);
1662 *state = (struct vfs_cc_state) {
1663 .ev = ev,
1664 .src_fsp = src_fsp,
1665 .src_off = src_off,
1666 .dst_fsp = dest_fsp,
1667 .dst_off = dest_off,
1668 .to_copy = to_copy,
1669 .remaining = to_copy,
1670 .flags = flags,
1672 state->buf = talloc_array(state, uint8_t, num);
1673 if (tevent_req_nomem(state->buf, req)) {
1674 return tevent_req_post(req, ev);
1677 status = vfs_stat_fsp(src_fsp);
1678 if (tevent_req_nterror(req, status)) {
1679 return tevent_req_post(req, ev);
1682 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1684 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1685 * If the SourceOffset or SourceOffset + Length extends beyond
1686 * the end of file, the server SHOULD<240> treat this as a
1687 * STATUS_END_OF_FILE error.
1688 * ...
1689 * <240> Section 3.3.5.15.6: Windows servers will return
1690 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1692 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1693 return tevent_req_post(req, ev);
1696 if (src_fsp->op == NULL) {
1697 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1698 return tevent_req_post(req, ev);
1701 if (dest_fsp->op == NULL) {
1702 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1703 return tevent_req_post(req, ev);
1706 status = copy_chunk_loop(req);
1707 if (!NT_STATUS_IS_OK(status)) {
1708 tevent_req_nterror(req, status);
1709 return tevent_req_post(req, ev);
1712 return req;
1715 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1717 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1719 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1720 struct tevent_req *subreq = NULL;
1721 bool ok;
1723 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1725 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1726 init_strict_lock_struct(state->src_fsp,
1727 state->src_fsp->op->global->open_persistent_id,
1728 state->src_off,
1729 state->next_io_size,
1730 READ_LOCK,
1731 &state->read_lck);
1733 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1734 state->src_fsp,
1735 &state->read_lck);
1736 if (!ok) {
1737 return NT_STATUS_FILE_LOCK_CONFLICT;
1741 subreq = SMB_VFS_PREAD_SEND(state,
1742 state->src_fsp->conn->sconn->ev_ctx,
1743 state->src_fsp,
1744 state->buf,
1745 state->next_io_size,
1746 state->src_off);
1747 if (subreq == NULL) {
1748 return NT_STATUS_NO_MEMORY;
1750 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1752 return NT_STATUS_OK;
1755 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1757 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1759 struct tevent_req *req = tevent_req_callback_data(
1760 subreq, struct tevent_req);
1761 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1762 struct vfs_aio_state aio_state;
1763 ssize_t nread;
1764 bool ok;
1766 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1767 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1768 state->src_fsp,
1769 &state->read_lck);
1770 ZERO_STRUCT(state->read_lck);
1773 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1774 TALLOC_FREE(subreq);
1775 if (nread == -1) {
1776 DBG_ERR("read failed: %s\n", strerror(errno));
1777 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1778 return;
1780 if (nread != state->next_io_size) {
1781 DBG_ERR("Short read, only %zd of %zu\n",
1782 nread, state->next_io_size);
1783 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1784 return;
1787 state->src_off += nread;
1789 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1790 init_strict_lock_struct(state->dst_fsp,
1791 state->dst_fsp->op->global->open_persistent_id,
1792 state->dst_off,
1793 state->next_io_size,
1794 WRITE_LOCK,
1795 &state->write_lck);
1797 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1798 state->dst_fsp,
1799 &state->write_lck);
1800 if (!ok) {
1801 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1802 return;
1806 subreq = SMB_VFS_PWRITE_SEND(state,
1807 state->ev,
1808 state->dst_fsp,
1809 state->buf,
1810 state->next_io_size,
1811 state->dst_off);
1812 if (subreq == NULL) {
1813 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1814 return;
1816 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1819 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1821 struct tevent_req *req = tevent_req_callback_data(
1822 subreq, struct tevent_req);
1823 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1824 struct vfs_aio_state aio_state;
1825 ssize_t nwritten;
1826 NTSTATUS status;
1828 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1829 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1830 state->dst_fsp,
1831 &state->write_lck);
1832 ZERO_STRUCT(state->write_lck);
1835 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1836 TALLOC_FREE(subreq);
1837 if (nwritten == -1) {
1838 DBG_ERR("write failed: %s\n", strerror(errno));
1839 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1840 return;
1842 if (nwritten != state->next_io_size) {
1843 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1844 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1845 return;
1848 state->dst_off += nwritten;
1850 if (state->remaining < nwritten) {
1851 /* Paranoia check */
1852 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1853 return;
1855 state->remaining -= nwritten;
1856 if (state->remaining == 0) {
1857 tevent_req_done(req);
1858 return;
1861 status = copy_chunk_loop(req);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 tevent_req_nterror(req, status);
1864 return;
1867 return;
1870 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1871 struct tevent_req *req,
1872 off_t *copied)
1874 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1875 NTSTATUS status;
1877 if (tevent_req_is_nterror(req, &status)) {
1878 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1879 *copied = 0;
1880 tevent_req_received(req);
1881 return status;
1884 *copied = state->to_copy;
1885 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1886 tevent_req_received(req);
1888 return NT_STATUS_OK;
1891 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1892 TALLOC_CTX *mem_ctx,
1893 struct files_struct *fsp,
1894 struct smb_filename *smb_fname,
1895 uint16_t *_compression_fmt)
1897 return NT_STATUS_INVALID_DEVICE_REQUEST;
1900 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1901 TALLOC_CTX *mem_ctx,
1902 struct files_struct *fsp,
1903 uint16_t compression_fmt)
1905 return NT_STATUS_INVALID_DEVICE_REQUEST;
1908 /********************************************************************
1909 Given a stat buffer return the allocated size on disk, taking into
1910 account sparse files.
1911 ********************************************************************/
1912 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1913 struct files_struct *fsp,
1914 const SMB_STRUCT_STAT *sbuf)
1916 uint64_t result;
1918 START_PROFILE(syscall_get_alloc_size);
1920 if(S_ISDIR(sbuf->st_ex_mode)) {
1921 result = 0;
1922 goto out;
1925 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1926 /* The type of st_blocksize is blkcnt_t which *MUST* be
1927 signed (according to POSIX) and can be less than 64-bits.
1928 Ensure when we're converting to 64 bits wide we don't
1929 sign extend. */
1930 #if defined(SIZEOF_BLKCNT_T_8)
1931 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1932 #elif defined(SIZEOF_BLKCNT_T_4)
1934 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1935 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1937 #else
1938 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1939 #endif
1940 if (result == 0) {
1942 * Some file systems do not allocate a block for very
1943 * small files. But for non-empty file should report a
1944 * positive size.
1947 uint64_t filesize = get_file_size_stat(sbuf);
1948 if (filesize > 0) {
1949 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1952 #else
1953 result = get_file_size_stat(sbuf);
1954 #endif
1956 if (fsp && fsp->initial_allocation_size)
1957 result = MAX(result,fsp->initial_allocation_size);
1959 result = smb_roundup(handle->conn, result);
1961 out:
1962 END_PROFILE(syscall_get_alloc_size);
1963 return result;
1966 static int vfswrap_unlink(vfs_handle_struct *handle,
1967 const struct smb_filename *smb_fname)
1969 int result = -1;
1971 START_PROFILE(syscall_unlink);
1973 if (smb_fname->stream_name) {
1974 errno = ENOENT;
1975 goto out;
1977 result = unlink(smb_fname->base_name);
1979 out:
1980 END_PROFILE(syscall_unlink);
1981 return result;
1984 static int vfswrap_chmod(vfs_handle_struct *handle,
1985 const struct smb_filename *smb_fname,
1986 mode_t mode)
1988 int result;
1990 START_PROFILE(syscall_chmod);
1993 * We need to do this due to the fact that the default POSIX ACL
1994 * chmod modifies the ACL *mask* for the group owner, not the
1995 * group owner bits directly. JRA.
2000 int saved_errno = errno; /* We might get ENOSYS */
2001 result = SMB_VFS_CHMOD_ACL(handle->conn,
2002 smb_fname,
2003 mode);
2004 if (result == 0) {
2005 END_PROFILE(syscall_chmod);
2006 return result;
2008 /* Error - return the old errno. */
2009 errno = saved_errno;
2012 result = chmod(smb_fname->base_name, mode);
2013 END_PROFILE(syscall_chmod);
2014 return result;
2017 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2019 int result;
2021 START_PROFILE(syscall_fchmod);
2024 * We need to do this due to the fact that the default POSIX ACL
2025 * chmod modifies the ACL *mask* for the group owner, not the
2026 * group owner bits directly. JRA.
2030 int saved_errno = errno; /* We might get ENOSYS */
2031 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2032 END_PROFILE(syscall_fchmod);
2033 return result;
2035 /* Error - return the old errno. */
2036 errno = saved_errno;
2039 #if defined(HAVE_FCHMOD)
2040 result = fchmod(fsp->fh->fd, mode);
2041 #else
2042 result = -1;
2043 errno = ENOSYS;
2044 #endif
2046 END_PROFILE(syscall_fchmod);
2047 return result;
2050 static int vfswrap_chown(vfs_handle_struct *handle,
2051 const struct smb_filename *smb_fname,
2052 uid_t uid,
2053 gid_t gid)
2055 int result;
2057 START_PROFILE(syscall_chown);
2058 result = chown(smb_fname->base_name, uid, gid);
2059 END_PROFILE(syscall_chown);
2060 return result;
2063 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2065 #ifdef HAVE_FCHOWN
2066 int result;
2068 START_PROFILE(syscall_fchown);
2069 result = fchown(fsp->fh->fd, uid, gid);
2070 END_PROFILE(syscall_fchown);
2071 return result;
2072 #else
2073 errno = ENOSYS;
2074 return -1;
2075 #endif
2078 static int vfswrap_lchown(vfs_handle_struct *handle,
2079 const struct smb_filename *smb_fname,
2080 uid_t uid,
2081 gid_t gid)
2083 int result;
2085 START_PROFILE(syscall_lchown);
2086 result = lchown(smb_fname->base_name, uid, gid);
2087 END_PROFILE(syscall_lchown);
2088 return result;
2091 static int vfswrap_chdir(vfs_handle_struct *handle,
2092 const struct smb_filename *smb_fname)
2094 int result;
2096 START_PROFILE(syscall_chdir);
2097 result = chdir(smb_fname->base_name);
2098 END_PROFILE(syscall_chdir);
2099 return result;
2102 static char *vfswrap_getwd(vfs_handle_struct *handle)
2104 char *result;
2106 START_PROFILE(syscall_getwd);
2107 result = sys_getwd();
2108 END_PROFILE(syscall_getwd);
2109 return result;
2112 /*********************************************************************
2113 nsec timestamp resolution call. Convert down to whatever the underlying
2114 system will support.
2115 **********************************************************************/
2117 static int vfswrap_ntimes(vfs_handle_struct *handle,
2118 const struct smb_filename *smb_fname,
2119 struct smb_file_time *ft)
2121 int result = -1;
2123 START_PROFILE(syscall_ntimes);
2125 if (smb_fname->stream_name) {
2126 errno = ENOENT;
2127 goto out;
2130 if (ft != NULL) {
2131 if (null_timespec(ft->atime)) {
2132 ft->atime= smb_fname->st.st_ex_atime;
2135 if (null_timespec(ft->mtime)) {
2136 ft->mtime = smb_fname->st.st_ex_mtime;
2139 if (!null_timespec(ft->create_time)) {
2140 set_create_timespec_ea(handle->conn,
2141 smb_fname,
2142 ft->create_time);
2145 if ((timespec_compare(&ft->atime,
2146 &smb_fname->st.st_ex_atime) == 0) &&
2147 (timespec_compare(&ft->mtime,
2148 &smb_fname->st.st_ex_mtime) == 0)) {
2149 return 0;
2153 #if defined(HAVE_UTIMENSAT)
2154 if (ft != NULL) {
2155 struct timespec ts[2];
2156 ts[0] = ft->atime;
2157 ts[1] = ft->mtime;
2158 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2159 } else {
2160 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2162 if (!((result == -1) && (errno == ENOSYS))) {
2163 goto out;
2165 #endif
2166 #if defined(HAVE_UTIMES)
2167 if (ft != NULL) {
2168 struct timeval tv[2];
2169 tv[0] = convert_timespec_to_timeval(ft->atime);
2170 tv[1] = convert_timespec_to_timeval(ft->mtime);
2171 result = utimes(smb_fname->base_name, tv);
2172 } else {
2173 result = utimes(smb_fname->base_name, NULL);
2175 if (!((result == -1) && (errno == ENOSYS))) {
2176 goto out;
2178 #endif
2179 #if defined(HAVE_UTIME)
2180 if (ft != NULL) {
2181 struct utimbuf times;
2182 times.actime = convert_timespec_to_time_t(ft->atime);
2183 times.modtime = convert_timespec_to_time_t(ft->mtime);
2184 result = utime(smb_fname->base_name, &times);
2185 } else {
2186 result = utime(smb_fname->base_name, NULL);
2188 if (!((result == -1) && (errno == ENOSYS))) {
2189 goto out;
2191 #endif
2192 errno = ENOSYS;
2193 result = -1;
2195 out:
2196 END_PROFILE(syscall_ntimes);
2197 return result;
2200 /*********************************************************************
2201 A version of ftruncate that will write the space on disk if strict
2202 allocate is set.
2203 **********************************************************************/
2205 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2207 off_t space_to_write;
2208 uint64_t space_avail;
2209 uint64_t bsize,dfree,dsize;
2210 int ret;
2211 NTSTATUS status;
2212 SMB_STRUCT_STAT *pst;
2214 status = vfs_stat_fsp(fsp);
2215 if (!NT_STATUS_IS_OK(status)) {
2216 return -1;
2218 pst = &fsp->fsp_name->st;
2220 #ifdef S_ISFIFO
2221 if (S_ISFIFO(pst->st_ex_mode))
2222 return 0;
2223 #endif
2225 if (pst->st_ex_size == len)
2226 return 0;
2228 /* Shrink - just ftruncate. */
2229 if (pst->st_ex_size > len)
2230 return ftruncate(fsp->fh->fd, len);
2232 space_to_write = len - pst->st_ex_size;
2234 /* for allocation try fallocate first. This can fail on some
2235 platforms e.g. when the filesystem doesn't support it and no
2236 emulation is being done by the libc (like on AIX with JFS1). In that
2237 case we do our own emulation. fallocate implementations can
2238 return ENOTSUP or EINVAL in cases like that. */
2239 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2240 if (ret == -1 && errno == ENOSPC) {
2241 return -1;
2243 if (ret == 0) {
2244 return 0;
2246 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2247 "error %d. Falling back to slow manual allocation\n", errno));
2249 /* available disk space is enough or not? */
2250 space_avail =
2251 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2252 /* space_avail is 1k blocks */
2253 if (space_avail == (uint64_t)-1 ||
2254 ((uint64_t)space_to_write/1024 > space_avail) ) {
2255 errno = ENOSPC;
2256 return -1;
2259 /* Write out the real space on disk. */
2260 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2261 if (ret != 0) {
2262 return -1;
2265 return 0;
2268 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2270 int result = -1;
2271 SMB_STRUCT_STAT *pst;
2272 NTSTATUS status;
2273 char c = 0;
2275 START_PROFILE(syscall_ftruncate);
2277 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2278 result = strict_allocate_ftruncate(handle, fsp, len);
2279 END_PROFILE(syscall_ftruncate);
2280 return result;
2283 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2284 ftruncate if the system supports it. Then I discovered that
2285 you can have some filesystems that support ftruncate
2286 expansion and some that don't! On Linux fat can't do
2287 ftruncate extend but ext2 can. */
2289 result = ftruncate(fsp->fh->fd, len);
2291 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2292 extend a file with ftruncate. Provide alternate implementation
2293 for this */
2295 /* Do an fstat to see if the file is longer than the requested
2296 size in which case the ftruncate above should have
2297 succeeded or shorter, in which case seek to len - 1 and
2298 write 1 byte of zero */
2299 status = vfs_stat_fsp(fsp);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 goto done;
2304 /* We need to update the files_struct after successful ftruncate */
2305 if (result == 0) {
2306 goto done;
2309 pst = &fsp->fsp_name->st;
2311 #ifdef S_ISFIFO
2312 if (S_ISFIFO(pst->st_ex_mode)) {
2313 result = 0;
2314 goto done;
2316 #endif
2318 if (pst->st_ex_size == len) {
2319 result = 0;
2320 goto done;
2323 if (pst->st_ex_size > len) {
2324 /* the ftruncate should have worked */
2325 goto done;
2328 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2329 goto done;
2332 result = 0;
2334 done:
2336 END_PROFILE(syscall_ftruncate);
2337 return result;
2340 static int vfswrap_fallocate(vfs_handle_struct *handle,
2341 files_struct *fsp,
2342 uint32_t mode,
2343 off_t offset,
2344 off_t len)
2346 int result;
2348 START_PROFILE(syscall_fallocate);
2349 if (mode == 0) {
2350 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2352 * posix_fallocate returns 0 on success, errno on error
2353 * and doesn't set errno. Make it behave like fallocate()
2354 * which returns -1, and sets errno on failure.
2356 if (result != 0) {
2357 errno = result;
2358 result = -1;
2360 } else {
2361 /* sys_fallocate handles filtering of unsupported mode flags */
2362 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2364 END_PROFILE(syscall_fallocate);
2365 return result;
2368 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2370 bool result;
2372 START_PROFILE(syscall_fcntl_lock);
2374 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2375 "smbd",
2376 "force process locks",
2377 false)) {
2378 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2381 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2382 END_PROFILE(syscall_fcntl_lock);
2383 return result;
2386 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2387 uint32_t share_mode, uint32_t access_mask)
2389 START_PROFILE(syscall_kernel_flock);
2390 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2391 END_PROFILE(syscall_kernel_flock);
2392 return 0;
2395 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2397 bool result;
2398 int op = F_GETLK;
2400 START_PROFILE(syscall_fcntl_getlock);
2402 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2403 "smbd",
2404 "force process locks",
2405 false)) {
2406 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2409 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2410 END_PROFILE(syscall_fcntl_getlock);
2411 return result;
2414 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2415 int leasetype)
2417 int result = -1;
2419 START_PROFILE(syscall_linux_setlease);
2421 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2422 result = linux_setlease(fsp->fh->fd, leasetype);
2423 #else
2424 errno = ENOSYS;
2425 #endif
2426 END_PROFILE(syscall_linux_setlease);
2427 return result;
2430 static int vfswrap_symlink(vfs_handle_struct *handle,
2431 const char *link_target,
2432 const struct smb_filename *new_smb_fname)
2434 int result;
2436 START_PROFILE(syscall_symlink);
2437 result = symlink(link_target, new_smb_fname->base_name);
2438 END_PROFILE(syscall_symlink);
2439 return result;
2442 static int vfswrap_readlink(vfs_handle_struct *handle,
2443 const struct smb_filename *smb_fname,
2444 char *buf,
2445 size_t bufsiz)
2447 int result;
2449 START_PROFILE(syscall_readlink);
2450 result = readlink(smb_fname->base_name, buf, bufsiz);
2451 END_PROFILE(syscall_readlink);
2452 return result;
2455 static int vfswrap_link(vfs_handle_struct *handle,
2456 const struct smb_filename *old_smb_fname,
2457 const struct smb_filename *new_smb_fname)
2459 int result;
2461 START_PROFILE(syscall_link);
2462 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2463 END_PROFILE(syscall_link);
2464 return result;
2467 static int vfswrap_mknod(vfs_handle_struct *handle,
2468 const struct smb_filename *smb_fname,
2469 mode_t mode,
2470 SMB_DEV_T dev)
2472 int result;
2474 START_PROFILE(syscall_mknod);
2475 result = sys_mknod(smb_fname->base_name, mode, dev);
2476 END_PROFILE(syscall_mknod);
2477 return result;
2480 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2482 char *result;
2484 START_PROFILE(syscall_realpath);
2485 result = sys_realpath(path);
2486 END_PROFILE(syscall_realpath);
2487 return result;
2490 static int vfswrap_chflags(vfs_handle_struct *handle,
2491 const struct smb_filename *smb_fname,
2492 unsigned int flags)
2494 #ifdef HAVE_CHFLAGS
2495 return chflags(smb_fname->base_name, flags);
2496 #else
2497 errno = ENOSYS;
2498 return -1;
2499 #endif
2502 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2503 const SMB_STRUCT_STAT *sbuf)
2505 struct file_id key;
2507 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2508 * blob */
2509 ZERO_STRUCT(key);
2511 key.devid = sbuf->st_ex_dev;
2512 key.inode = sbuf->st_ex_ino;
2513 /* key.extid is unused by default. */
2515 return key;
2518 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2519 struct files_struct *fsp,
2520 const struct smb_filename *smb_fname,
2521 TALLOC_CTX *mem_ctx,
2522 unsigned int *pnum_streams,
2523 struct stream_struct **pstreams)
2525 SMB_STRUCT_STAT sbuf;
2526 struct stream_struct *tmp_streams = NULL;
2527 int ret;
2529 if ((fsp != NULL) && (fsp->is_directory)) {
2531 * No default streams on directories
2533 goto done;
2536 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2537 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2539 else {
2540 struct smb_filename smb_fname_cp;
2542 ZERO_STRUCT(smb_fname_cp);
2543 smb_fname_cp.base_name = discard_const_p(char,
2544 smb_fname->base_name);
2545 smb_fname_cp.flags = smb_fname->flags;
2547 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2548 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2549 } else {
2550 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2552 sbuf = smb_fname_cp.st;
2555 if (ret == -1) {
2556 return map_nt_error_from_unix(errno);
2559 if (S_ISDIR(sbuf.st_ex_mode)) {
2560 goto done;
2563 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2564 (*pnum_streams) + 1);
2565 if (tmp_streams == NULL) {
2566 return NT_STATUS_NO_MEMORY;
2568 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2569 if (tmp_streams[*pnum_streams].name == NULL) {
2570 return NT_STATUS_NO_MEMORY;
2572 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2573 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2575 *pnum_streams += 1;
2576 *pstreams = tmp_streams;
2577 done:
2578 return NT_STATUS_OK;
2581 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2582 const char *path,
2583 const char *name,
2584 TALLOC_CTX *mem_ctx,
2585 char **found_name)
2588 * Don't fall back to get_real_filename so callers can differentiate
2589 * between a full directory scan and an actual case-insensitive stat.
2591 errno = EOPNOTSUPP;
2592 return -1;
2595 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2596 const char *fname)
2598 return handle->conn->connectpath;
2601 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2602 struct byte_range_lock *br_lck,
2603 struct lock_struct *plock,
2604 bool blocking_lock)
2606 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2608 /* Note: blr is not used in the default implementation. */
2609 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2612 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2613 struct messaging_context *msg_ctx,
2614 struct byte_range_lock *br_lck,
2615 const struct lock_struct *plock)
2617 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2619 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2622 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2623 struct byte_range_lock *br_lck,
2624 struct lock_struct *plock)
2626 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2628 /* Note: blr is not used in the default implementation. */
2629 return brl_lock_cancel_default(br_lck, plock);
2632 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2633 files_struct *fsp,
2634 struct lock_struct *plock)
2636 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2637 plock->lock_type == WRITE_LOCK);
2639 return strict_lock_default(fsp, plock);
2642 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2643 files_struct *fsp,
2644 struct lock_struct *plock)
2646 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2647 plock->lock_type == WRITE_LOCK);
2649 strict_unlock_default(fsp, plock);
2652 /* NT ACL operations. */
2654 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2655 files_struct *fsp,
2656 uint32_t security_info,
2657 TALLOC_CTX *mem_ctx,
2658 struct security_descriptor **ppdesc)
2660 NTSTATUS result;
2662 START_PROFILE(fget_nt_acl);
2663 result = posix_fget_nt_acl(fsp, security_info,
2664 mem_ctx, ppdesc);
2665 END_PROFILE(fget_nt_acl);
2666 return result;
2669 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2670 const struct smb_filename *smb_fname,
2671 uint32_t security_info,
2672 TALLOC_CTX *mem_ctx,
2673 struct security_descriptor **ppdesc)
2675 NTSTATUS result;
2677 START_PROFILE(get_nt_acl);
2678 result = posix_get_nt_acl(handle->conn,
2679 smb_fname,
2680 security_info,
2681 mem_ctx,
2682 ppdesc);
2683 END_PROFILE(get_nt_acl);
2684 return result;
2687 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2689 NTSTATUS result;
2691 START_PROFILE(fset_nt_acl);
2692 result = set_nt_acl(fsp, security_info_sent, psd);
2693 END_PROFILE(fset_nt_acl);
2694 return result;
2697 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2698 struct smb_filename *file,
2699 struct security_acl *sacl,
2700 uint32_t access_requested,
2701 uint32_t access_denied)
2703 return NT_STATUS_OK; /* Nothing to do here ... */
2706 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2707 const struct smb_filename *smb_fname,
2708 mode_t mode)
2710 #ifdef HAVE_NO_ACL
2711 errno = ENOSYS;
2712 return -1;
2713 #else
2714 int result;
2716 START_PROFILE(chmod_acl);
2717 result = chmod_acl(handle->conn, smb_fname, mode);
2718 END_PROFILE(chmod_acl);
2719 return result;
2720 #endif
2723 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2725 #ifdef HAVE_NO_ACL
2726 errno = ENOSYS;
2727 return -1;
2728 #else
2729 int result;
2731 START_PROFILE(fchmod_acl);
2732 result = fchmod_acl(fsp, mode);
2733 END_PROFILE(fchmod_acl);
2734 return result;
2735 #endif
2738 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2739 const struct smb_filename *smb_fname,
2740 SMB_ACL_TYPE_T type,
2741 TALLOC_CTX *mem_ctx)
2743 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2746 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2747 files_struct *fsp,
2748 TALLOC_CTX *mem_ctx)
2750 return sys_acl_get_fd(handle, fsp, mem_ctx);
2753 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2754 const struct smb_filename *smb_fname,
2755 SMB_ACL_TYPE_T acltype,
2756 SMB_ACL_T theacl)
2758 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2761 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2763 return sys_acl_set_fd(handle, fsp, theacl);
2766 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2767 const struct smb_filename *smb_fname)
2769 return sys_acl_delete_def_file(handle, smb_fname);
2772 /****************************************************************
2773 Extended attribute operations.
2774 *****************************************************************/
2776 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2777 const struct smb_filename *smb_fname,
2778 const char *name,
2779 void *value,
2780 size_t size)
2782 return getxattr(smb_fname->base_name, name, value, size);
2785 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2787 return fgetxattr(fsp->fh->fd, name, value, size);
2790 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2791 const struct smb_filename *smb_fname,
2792 char *list,
2793 size_t size)
2795 return listxattr(smb_fname->base_name, list, size);
2798 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2800 return flistxattr(fsp->fh->fd, list, size);
2803 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2804 const struct smb_filename *smb_fname,
2805 const char *name)
2807 return removexattr(smb_fname->base_name, name);
2810 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2812 return fremovexattr(fsp->fh->fd, name);
2815 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2816 const struct smb_filename *smb_fname,
2817 const char *name,
2818 const void *value,
2819 size_t size,
2820 int flags)
2822 return setxattr(smb_fname->base_name, name, value, size, flags);
2825 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2827 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2830 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2832 return false;
2835 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2836 const struct smb_filename *fname,
2837 SMB_STRUCT_STAT *sbuf)
2839 NTSTATUS status;
2840 char *path;
2841 bool offline = false;
2843 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2844 return false;
2847 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2848 #if defined(ENOTSUP)
2849 errno = ENOTSUP;
2850 #endif
2851 return false;
2854 status = get_full_smb_filename(talloc_tos(), fname, &path);
2855 if (!NT_STATUS_IS_OK(status)) {
2856 errno = map_errno_from_nt_status(status);
2857 return false;
2860 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2862 TALLOC_FREE(path);
2864 return offline;
2867 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2868 struct files_struct *fsp,
2869 TALLOC_CTX *mem_ctx,
2870 DATA_BLOB *cookie)
2872 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2875 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2876 struct files_struct *fsp,
2877 const DATA_BLOB old_cookie,
2878 TALLOC_CTX *mem_ctx,
2879 DATA_BLOB *new_cookie)
2881 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2882 new_cookie);
2885 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2886 struct smb_request *smb1req,
2887 struct smbXsrv_open *op,
2888 const DATA_BLOB old_cookie,
2889 TALLOC_CTX *mem_ctx,
2890 struct files_struct **fsp,
2891 DATA_BLOB *new_cookie)
2893 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2894 old_cookie, mem_ctx,
2895 fsp, new_cookie);
2898 static struct vfs_fn_pointers vfs_default_fns = {
2899 /* Disk operations */
2901 .connect_fn = vfswrap_connect,
2902 .disconnect_fn = vfswrap_disconnect,
2903 .disk_free_fn = vfswrap_disk_free,
2904 .get_quota_fn = vfswrap_get_quota,
2905 .set_quota_fn = vfswrap_set_quota,
2906 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2907 .statvfs_fn = vfswrap_statvfs,
2908 .fs_capabilities_fn = vfswrap_fs_capabilities,
2909 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2910 .snap_check_path_fn = vfswrap_snap_check_path,
2911 .snap_create_fn = vfswrap_snap_create,
2912 .snap_delete_fn = vfswrap_snap_delete,
2914 /* Directory operations */
2916 .opendir_fn = vfswrap_opendir,
2917 .fdopendir_fn = vfswrap_fdopendir,
2918 .readdir_fn = vfswrap_readdir,
2919 .readdir_attr_fn = vfswrap_readdir_attr,
2920 .seekdir_fn = vfswrap_seekdir,
2921 .telldir_fn = vfswrap_telldir,
2922 .rewind_dir_fn = vfswrap_rewinddir,
2923 .mkdir_fn = vfswrap_mkdir,
2924 .rmdir_fn = vfswrap_rmdir,
2925 .closedir_fn = vfswrap_closedir,
2926 .init_search_op_fn = vfswrap_init_search_op,
2928 /* File operations */
2930 .open_fn = vfswrap_open,
2931 .create_file_fn = vfswrap_create_file,
2932 .close_fn = vfswrap_close,
2933 .read_fn = vfswrap_read,
2934 .pread_fn = vfswrap_pread,
2935 .pread_send_fn = vfswrap_pread_send,
2936 .pread_recv_fn = vfswrap_pread_recv,
2937 .write_fn = vfswrap_write,
2938 .pwrite_fn = vfswrap_pwrite,
2939 .pwrite_send_fn = vfswrap_pwrite_send,
2940 .pwrite_recv_fn = vfswrap_pwrite_recv,
2941 .lseek_fn = vfswrap_lseek,
2942 .sendfile_fn = vfswrap_sendfile,
2943 .recvfile_fn = vfswrap_recvfile,
2944 .rename_fn = vfswrap_rename,
2945 .fsync_fn = vfswrap_fsync,
2946 .fsync_send_fn = vfswrap_fsync_send,
2947 .fsync_recv_fn = vfswrap_fsync_recv,
2948 .stat_fn = vfswrap_stat,
2949 .fstat_fn = vfswrap_fstat,
2950 .lstat_fn = vfswrap_lstat,
2951 .get_alloc_size_fn = vfswrap_get_alloc_size,
2952 .unlink_fn = vfswrap_unlink,
2953 .chmod_fn = vfswrap_chmod,
2954 .fchmod_fn = vfswrap_fchmod,
2955 .chown_fn = vfswrap_chown,
2956 .fchown_fn = vfswrap_fchown,
2957 .lchown_fn = vfswrap_lchown,
2958 .chdir_fn = vfswrap_chdir,
2959 .getwd_fn = vfswrap_getwd,
2960 .ntimes_fn = vfswrap_ntimes,
2961 .ftruncate_fn = vfswrap_ftruncate,
2962 .fallocate_fn = vfswrap_fallocate,
2963 .lock_fn = vfswrap_lock,
2964 .kernel_flock_fn = vfswrap_kernel_flock,
2965 .linux_setlease_fn = vfswrap_linux_setlease,
2966 .getlock_fn = vfswrap_getlock,
2967 .symlink_fn = vfswrap_symlink,
2968 .readlink_fn = vfswrap_readlink,
2969 .link_fn = vfswrap_link,
2970 .mknod_fn = vfswrap_mknod,
2971 .realpath_fn = vfswrap_realpath,
2972 .chflags_fn = vfswrap_chflags,
2973 .file_id_create_fn = vfswrap_file_id_create,
2974 .streaminfo_fn = vfswrap_streaminfo,
2975 .get_real_filename_fn = vfswrap_get_real_filename,
2976 .connectpath_fn = vfswrap_connectpath,
2977 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2978 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2979 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2980 .strict_lock_fn = vfswrap_strict_lock,
2981 .strict_unlock_fn = vfswrap_strict_unlock,
2982 .translate_name_fn = vfswrap_translate_name,
2983 .fsctl_fn = vfswrap_fsctl,
2984 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2985 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2986 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2987 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2988 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2989 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2990 .get_compression_fn = vfswrap_get_compression,
2991 .set_compression_fn = vfswrap_set_compression,
2993 /* NT ACL operations. */
2995 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2996 .get_nt_acl_fn = vfswrap_get_nt_acl,
2997 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2998 .audit_file_fn = vfswrap_audit_file,
3000 /* POSIX ACL operations. */
3002 .chmod_acl_fn = vfswrap_chmod_acl,
3003 .fchmod_acl_fn = vfswrap_fchmod_acl,
3005 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3006 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3007 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3008 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3009 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3010 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3011 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3013 /* EA operations. */
3014 .getxattr_fn = vfswrap_getxattr,
3015 .fgetxattr_fn = vfswrap_fgetxattr,
3016 .listxattr_fn = vfswrap_listxattr,
3017 .flistxattr_fn = vfswrap_flistxattr,
3018 .removexattr_fn = vfswrap_removexattr,
3019 .fremovexattr_fn = vfswrap_fremovexattr,
3020 .setxattr_fn = vfswrap_setxattr,
3021 .fsetxattr_fn = vfswrap_fsetxattr,
3023 /* aio operations */
3024 .aio_force_fn = vfswrap_aio_force,
3026 /* durable handle operations */
3027 .durable_cookie_fn = vfswrap_durable_cookie,
3028 .durable_disconnect_fn = vfswrap_durable_disconnect,
3029 .durable_reconnect_fn = vfswrap_durable_reconnect,
3032 NTSTATUS vfs_default_init(TALLOC_CTX *);
3033 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3035 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3036 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);