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/>.
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.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/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
63 result = sys_disk_free(handle->conn, path, bsize, dfree, dsize);
67 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
69 #ifdef HAVE_SYS_QUOTAS
72 START_PROFILE(syscall_get_quota);
73 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
74 END_PROFILE(syscall_get_quota);
82 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
84 #ifdef HAVE_SYS_QUOTAS
87 START_PROFILE(syscall_set_quota);
88 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
89 END_PROFILE(syscall_set_quota);
97 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
98 struct files_struct *fsp,
99 struct shadow_copy_data *shadow_copy_data,
103 return -1; /* Not implemented. */
106 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
108 return sys_statvfs(path, statbuf);
111 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
112 enum timestamp_set_resolution *p_ts_res)
114 connection_struct *conn = handle->conn;
115 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
116 struct smb_filename *smb_fname_cpath = NULL;
117 struct vfs_statvfs_struct statbuf;
120 ZERO_STRUCT(statbuf);
121 ret = sys_statvfs(conn->connectpath, &statbuf);
123 caps = statbuf.FsCapabilities;
126 *p_ts_res = TIMESTAMP_SET_SECONDS;
128 /* Work out what timestamp resolution we can
129 * use when setting a timestamp. */
131 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
133 if (smb_fname_cpath == NULL) {
137 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
139 TALLOC_FREE(smb_fname_cpath);
143 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
145 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
146 /* If any of the normal UNIX directory timestamps
147 * have a non-zero tv_nsec component assume
148 * we might be able to set sub-second timestamps.
149 * See what filetime set primitives we have.
151 #if defined(HAVE_UTIMENSAT)
152 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
153 #elif defined(HAVE_UTIMES)
154 /* utimes allows msec timestamps to be set. */
155 *p_ts_res = TIMESTAMP_SET_MSEC;
156 #elif defined(HAVE_UTIME)
157 /* utime only allows sec timestamps to be set. */
158 *p_ts_res = TIMESTAMP_SET_SECONDS;
161 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
163 "available on share %s, directory %s\n",
164 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
165 lp_servicename(talloc_tos(), conn->params->service),
166 conn->connectpath ));
168 TALLOC_FREE(smb_fname_cpath);
172 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
173 struct dfs_GetDFSReferral *r)
175 struct junction_map *junction = NULL;
177 bool self_referral = false;
178 char *pathnamep = NULL;
179 char *local_dfs_path = NULL;
182 uint16_t max_referral_level = r->in.req.max_referral_level;
185 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
188 /* get the junction entry */
189 if (r->in.req.servername == NULL) {
190 return NT_STATUS_NOT_FOUND;
194 * Trim pathname sent by client so it begins with only one backslash.
195 * Two backslashes confuse some dfs clients
198 local_dfs_path = talloc_strdup(r, r->in.req.servername);
199 if (local_dfs_path == NULL) {
200 return NT_STATUS_NO_MEMORY;
202 pathnamep = local_dfs_path;
203 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
204 IS_DIRECTORY_SEP(pathnamep[1])) {
208 junction = talloc_zero(r, struct junction_map);
209 if (junction == NULL) {
210 return NT_STATUS_NO_MEMORY;
213 /* The following call can change cwd. */
214 status = get_referred_path(r, pathnamep,
215 !handle->conn->sconn->using_smb2,
216 junction, &consumedcnt, &self_referral);
217 if (!NT_STATUS_IS_OK(status)) {
218 vfs_ChDir(handle->conn, handle->conn->connectpath);
221 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 if (!self_referral) {
224 pathnamep[consumedcnt] = '\0';
227 dbgtext("Path %s to alternate path(s):",
229 for (i=0; i < junction->referral_count; i++) {
231 junction->referral_list[i].alternate_path);
237 if (r->in.req.max_referral_level <= 2) {
238 max_referral_level = 2;
240 if (r->in.req.max_referral_level >= 3) {
241 max_referral_level = 3;
244 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
245 if (r->out.resp == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
250 r->out.resp->nb_referrals = junction->referral_count;
252 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
254 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
257 r->out.resp->referral_entries = talloc_zero_array(r,
258 struct dfs_referral_type,
259 r->out.resp->nb_referrals);
260 if (r->out.resp->referral_entries == NULL) {
261 return NT_STATUS_NO_MEMORY;
264 switch (max_referral_level) {
266 for(i=0; i < junction->referral_count; i++) {
267 struct referral *ref = &junction->referral_list[i];
268 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
269 struct dfs_referral_type *t =
270 &r->out.resp->referral_entries[i];
271 struct dfs_referral_v2 *v2 = &t->referral.v2;
274 v2->size = VERSION2_REFERRAL_SIZE;
276 v2->server_type = DFS_SERVER_ROOT;
278 v2->server_type = DFS_SERVER_NON_ROOT;
281 v2->proximity = ref->proximity;
283 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
284 if (v2->DFS_path == NULL) {
285 return NT_STATUS_NO_MEMORY;
287 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_alt_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->netw_address = talloc_strdup(mem_ctx,
292 ref->alternate_path);
293 if (v2->netw_address == NULL) {
294 return NT_STATUS_NO_MEMORY;
300 for(i=0; i < junction->referral_count; i++) {
301 struct referral *ref = &junction->referral_list[i];
302 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
303 struct dfs_referral_type *t =
304 &r->out.resp->referral_entries[i];
305 struct dfs_referral_v3 *v3 = &t->referral.v3;
306 struct dfs_normal_referral *r1 = &v3->referrals.r1;
309 v3->size = VERSION3_REFERRAL_SIZE;
311 v3->server_type = DFS_SERVER_ROOT;
313 v3->server_type = DFS_SERVER_NON_ROOT;
317 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
318 if (r1->DFS_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_alt_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->netw_address = talloc_strdup(mem_ctx,
326 ref->alternate_path);
327 if (r1->netw_address == NULL) {
328 return NT_STATUS_NO_MEMORY;
333 DEBUG(0,("Invalid dfs referral version: %d\n",
334 max_referral_level));
335 return NT_STATUS_INVALID_LEVEL;
339 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
345 /* Directory operations */
347 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
351 START_PROFILE(syscall_opendir);
352 result = opendir(fname);
353 END_PROFILE(syscall_opendir);
357 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
364 START_PROFILE(syscall_fdopendir);
365 result = sys_fdopendir(fsp->fh->fd);
366 END_PROFILE(syscall_fdopendir);
371 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
373 SMB_STRUCT_STAT *sbuf)
375 struct dirent *result;
377 START_PROFILE(syscall_readdir);
378 result = readdir(dirp);
379 END_PROFILE(syscall_readdir);
381 /* Default Posix readdir() does not give us stat info.
382 * Set to invalid to indicate we didn't return this info. */
383 SET_STAT_INVALID(*sbuf);
384 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
385 if (result != NULL) {
386 /* See if we can efficiently return this. */
388 int flags = (lp_posix_pathnames() ?
389 AT_SYMLINK_NOFOLLOW : 0);
390 int ret = fstatat(dirfd(dirp),
395 init_stat_ex_from_stat(sbuf,
397 lp_fake_directory_create_times(
398 SNUM(handle->conn)));
406 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
407 const struct smb_filename *fname,
409 struct readdir_attr_data **attr_data)
411 return NT_STATUS_NOT_SUPPORTED;
414 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
416 START_PROFILE(syscall_seekdir);
417 seekdir(dirp, offset);
418 END_PROFILE(syscall_seekdir);
421 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
424 START_PROFILE(syscall_telldir);
425 result = telldir(dirp);
426 END_PROFILE(syscall_telldir);
430 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
432 START_PROFILE(syscall_rewinddir);
434 END_PROFILE(syscall_rewinddir);
437 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
440 bool has_dacl = False;
443 START_PROFILE(syscall_mkdir);
445 if (lp_inherit_acls(SNUM(handle->conn))
446 && parent_dirname(talloc_tos(), path, &parent, NULL)
447 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
448 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
452 result = mkdir(path, mode);
454 if (result == 0 && !has_dacl) {
456 * We need to do this as the default behavior of POSIX ACLs
457 * is to set the mask to be the requested group permission
458 * bits, not the group permission bits to be the requested
459 * group permission bits. This is not what we want, as it will
460 * mess up any inherited ACL bits that were set. JRA.
462 int saved_errno = errno; /* We may get ENOSYS */
463 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
467 END_PROFILE(syscall_mkdir);
471 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
475 START_PROFILE(syscall_rmdir);
476 result = rmdir(path);
477 END_PROFILE(syscall_rmdir);
481 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
485 START_PROFILE(syscall_closedir);
486 result = closedir(dirp);
487 END_PROFILE(syscall_closedir);
491 static void vfswrap_init_search_op(vfs_handle_struct *handle,
494 /* Default behavior is a NOOP */
497 /* File operations */
499 static int vfswrap_open(vfs_handle_struct *handle,
500 struct smb_filename *smb_fname,
501 files_struct *fsp, int flags, mode_t mode)
505 START_PROFILE(syscall_open);
507 if (smb_fname->stream_name) {
512 result = open(smb_fname->base_name, flags, mode);
514 END_PROFILE(syscall_open);
518 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
519 struct smb_request *req,
520 uint16_t root_dir_fid,
521 struct smb_filename *smb_fname,
522 uint32_t access_mask,
523 uint32_t share_access,
524 uint32_t create_disposition,
525 uint32_t create_options,
526 uint32_t file_attributes,
527 uint32_t oplock_request,
528 struct smb2_lease *lease,
529 uint64_t allocation_size,
530 uint32_t private_flags,
531 struct security_descriptor *sd,
532 struct ea_list *ea_list,
533 files_struct **result,
535 const struct smb2_create_blobs *in_context_blobs,
536 struct smb2_create_blobs *out_context_blobs)
538 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
539 access_mask, share_access,
540 create_disposition, create_options,
541 file_attributes, oplock_request, lease,
542 allocation_size, private_flags,
544 pinfo, in_context_blobs, out_context_blobs);
547 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
551 START_PROFILE(syscall_close);
552 result = fd_close_posix(fsp);
553 END_PROFILE(syscall_close);
557 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
561 START_PROFILE_BYTES(syscall_read, n);
562 result = sys_read(fsp->fh->fd, data, n);
563 END_PROFILE_BYTES(syscall_read);
567 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
568 size_t n, off_t offset)
572 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
573 START_PROFILE_BYTES(syscall_pread, n);
574 result = sys_pread(fsp->fh->fd, data, n, offset);
575 END_PROFILE_BYTES(syscall_pread);
577 if (result == -1 && errno == ESPIPE) {
578 /* Maintain the fiction that pipes can be seeked (sought?) on. */
579 result = SMB_VFS_READ(fsp, data, n);
583 #else /* HAVE_PREAD */
587 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
588 if (curr == -1 && errno == ESPIPE) {
589 /* Maintain the fiction that pipes can be seeked (sought?) on. */
590 result = SMB_VFS_READ(fsp, data, n);
595 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
600 result = SMB_VFS_READ(fsp, data, n);
603 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
606 #endif /* HAVE_PREAD */
611 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
615 START_PROFILE_BYTES(syscall_write, n);
616 result = sys_write(fsp->fh->fd, data, n);
617 END_PROFILE_BYTES(syscall_write);
621 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
622 size_t n, off_t offset)
626 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
627 START_PROFILE_BYTES(syscall_pwrite, n);
628 result = sys_pwrite(fsp->fh->fd, data, n, offset);
629 END_PROFILE_BYTES(syscall_pwrite);
631 if (result == -1 && errno == ESPIPE) {
632 /* Maintain the fiction that pipes can be sought on. */
633 result = SMB_VFS_WRITE(fsp, data, n);
636 #else /* HAVE_PWRITE */
640 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
645 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
649 result = SMB_VFS_WRITE(fsp, data, n);
652 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
655 #endif /* HAVE_PWRITE */
660 static void vfswrap_asys_finished(struct tevent_context *ev,
661 struct tevent_fd *fde,
662 uint16_t flags, void *p);
664 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
669 if (conn->asys_ctx != NULL) {
672 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
674 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
678 fd = asys_signalfd(conn->asys_ctx);
680 set_blocking(fd, false);
682 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
684 vfswrap_asys_finished,
686 if (conn->asys_fde == NULL) {
687 DEBUG(1, ("tevent_add_fd failed\n"));
688 asys_context_destroy(conn->asys_ctx);
689 conn->asys_ctx = NULL;
695 struct vfswrap_asys_state {
696 struct asys_context *asys_ctx;
697 struct tevent_req *req;
700 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
701 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
704 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
706 asys_cancel(s->asys_ctx, s->req);
710 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
712 struct tevent_context *ev,
713 struct files_struct *fsp,
715 size_t n, off_t offset)
717 struct tevent_req *req;
718 struct vfswrap_asys_state *state;
721 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
725 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
727 return tevent_req_post(req, ev);
729 state->asys_ctx = handle->conn->sconn->asys_ctx;
732 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
733 state->profile_bytes, n);
734 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
736 tevent_req_error(req, ret);
737 return tevent_req_post(req, ev);
739 talloc_set_destructor(state, vfswrap_asys_state_destructor);
744 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
746 struct tevent_context *ev,
747 struct files_struct *fsp,
749 size_t n, off_t offset)
751 struct tevent_req *req;
752 struct vfswrap_asys_state *state;
755 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
759 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
761 return tevent_req_post(req, ev);
763 state->asys_ctx = handle->conn->sconn->asys_ctx;
766 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
767 state->profile_bytes, n);
768 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
770 tevent_req_error(req, ret);
771 return tevent_req_post(req, ev);
773 talloc_set_destructor(state, vfswrap_asys_state_destructor);
778 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
780 struct tevent_context *ev,
781 struct files_struct *fsp)
783 struct tevent_req *req;
784 struct vfswrap_asys_state *state;
787 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
791 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
793 return tevent_req_post(req, ev);
795 state->asys_ctx = handle->conn->sconn->asys_ctx;
798 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
799 state->profile_basic);
800 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
802 tevent_req_error(req, ret);
803 return tevent_req_post(req, ev);
805 talloc_set_destructor(state, vfswrap_asys_state_destructor);
810 static void vfswrap_asys_finished(struct tevent_context *ev,
811 struct tevent_fd *fde,
812 uint16_t flags, void *p)
814 struct asys_context *asys_ctx = (struct asys_context *)p;
815 struct asys_result results[outstanding_aio_calls];
818 if ((flags & TEVENT_FD_READ) == 0) {
822 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
824 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
828 for (i=0; i<ret; i++) {
829 struct asys_result *result = &results[i];
830 struct tevent_req *req;
831 struct vfswrap_asys_state *state;
833 if ((result->ret == -1) && (result->err == ECANCELED)) {
837 req = talloc_get_type_abort(result->private_data,
839 state = tevent_req_data(req, struct vfswrap_asys_state);
841 talloc_set_destructor(state, NULL);
843 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
844 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
845 state->ret = result->ret;
846 state->err = result->err;
847 tevent_req_defer_callback(req, ev);
848 tevent_req_done(req);
852 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
854 struct vfswrap_asys_state *state = tevent_req_data(
855 req, struct vfswrap_asys_state);
857 if (tevent_req_is_unix_error(req, err)) {
864 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
866 struct vfswrap_asys_state *state = tevent_req_data(
867 req, struct vfswrap_asys_state);
869 if (tevent_req_is_unix_error(req, err)) {
876 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
880 START_PROFILE(syscall_lseek);
882 /* Cope with 'stat' file opens. */
883 if (fsp->fh->fd != -1)
884 result = lseek(fsp->fh->fd, offset, whence);
887 * We want to maintain the fiction that we can seek
888 * on a fifo for file system purposes. This allows
889 * people to set up UNIX fifo's that feed data to Windows
893 if((result == -1) && (errno == ESPIPE)) {
898 END_PROFILE(syscall_lseek);
902 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
903 off_t offset, size_t n)
907 START_PROFILE_BYTES(syscall_sendfile, n);
908 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
909 END_PROFILE_BYTES(syscall_sendfile);
913 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
921 START_PROFILE_BYTES(syscall_recvfile, n);
922 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
923 END_PROFILE_BYTES(syscall_recvfile);
927 static int vfswrap_rename(vfs_handle_struct *handle,
928 const struct smb_filename *smb_fname_src,
929 const struct smb_filename *smb_fname_dst)
933 START_PROFILE(syscall_rename);
935 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
940 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
943 END_PROFILE(syscall_rename);
947 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
952 START_PROFILE(syscall_fsync);
953 result = fsync(fsp->fh->fd);
954 END_PROFILE(syscall_fsync);
961 static int vfswrap_stat(vfs_handle_struct *handle,
962 struct smb_filename *smb_fname)
966 START_PROFILE(syscall_stat);
968 if (smb_fname->stream_name) {
973 result = sys_stat(smb_fname->base_name, &smb_fname->st,
974 lp_fake_directory_create_times(SNUM(handle->conn)));
976 END_PROFILE(syscall_stat);
980 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
984 START_PROFILE(syscall_fstat);
985 result = sys_fstat(fsp->fh->fd,
986 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
987 END_PROFILE(syscall_fstat);
991 static int vfswrap_lstat(vfs_handle_struct *handle,
992 struct smb_filename *smb_fname)
996 START_PROFILE(syscall_lstat);
998 if (smb_fname->stream_name) {
1003 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1004 lp_fake_directory_create_times(SNUM(handle->conn)));
1006 END_PROFILE(syscall_lstat);
1010 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1012 enum vfs_translate_direction direction,
1013 TALLOC_CTX *mem_ctx,
1016 return NT_STATUS_NONE_MAPPED;
1020 * Implement the default fsctl operation.
1022 static bool vfswrap_logged_ioctl_message = false;
1024 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1025 struct files_struct *fsp,
1028 uint16_t req_flags, /* Needed for UNICODE ... */
1029 const uint8_t *_in_data,
1031 uint8_t **_out_data,
1032 uint32_t max_out_len,
1035 const char *in_data = (const char *)_in_data;
1036 char **out_data = (char **)_out_data;
1040 case FSCTL_SET_SPARSE:
1042 bool set_sparse = true;
1044 if (in_len >= 1 && in_data[0] == 0) {
1048 status = file_set_sparse(handle->conn, fsp, set_sparse);
1050 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1051 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1052 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1053 nt_errstr(status)));
1058 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1060 unsigned char objid[16];
1061 char *return_data = NULL;
1063 /* This should return the object-id on this file.
1064 * I think I'll make this be the inode+dev. JRA.
1067 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1068 fsp_fnum_dbg(fsp)));
1070 *out_len = MIN(max_out_len, 64);
1072 /* Hmmm, will this cause problems if less data asked for? */
1073 return_data = talloc_array(ctx, char, 64);
1074 if (return_data == NULL) {
1075 return NT_STATUS_NO_MEMORY;
1078 /* For backwards compatibility only store the dev/inode. */
1079 push_file_id_16(return_data, &fsp->file_id);
1080 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1081 push_file_id_16(return_data+32, &fsp->file_id);
1082 memset(return_data+48, 0, 16);
1083 *out_data = return_data;
1084 return NT_STATUS_OK;
1087 case FSCTL_GET_REPARSE_POINT:
1089 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1090 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1091 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1092 return NT_STATUS_NOT_A_REPARSE_POINT;
1095 case FSCTL_SET_REPARSE_POINT:
1097 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1098 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1099 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1100 return NT_STATUS_NOT_A_REPARSE_POINT;
1103 case FSCTL_GET_SHADOW_COPY_DATA:
1106 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1107 * and return their volume names. If max_data_count is 16, then it is just
1108 * asking for the number of volumes and length of the combined names.
1110 * pdata is the data allocated by our caller, but that uses
1111 * total_data_count (which is 0 in our case) rather than max_data_count.
1112 * Allocate the correct amount and return the pointer to let
1113 * it be deallocated when we return.
1115 struct shadow_copy_data *shadow_data = NULL;
1116 bool labels = False;
1117 uint32 labels_data_count = 0;
1119 char *cur_pdata = NULL;
1121 if (max_out_len < 16) {
1122 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1124 return NT_STATUS_INVALID_PARAMETER;
1127 if (max_out_len > 16) {
1131 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1132 if (shadow_data == NULL) {
1133 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1134 return NT_STATUS_NO_MEMORY;
1138 * Call the VFS routine to actually do the work.
1140 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1143 /* broken module didn't set errno on error */
1144 status = NT_STATUS_UNSUCCESSFUL;
1146 status = map_nt_error_from_unix(errno);
1147 if (NT_STATUS_EQUAL(status,
1148 NT_STATUS_NOT_SUPPORTED)) {
1152 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1153 "connectpath %s, failed - %s.\n",
1154 fsp->conn->connectpath,
1155 nt_errstr(status)));
1156 TALLOC_FREE(shadow_data);
1160 labels_data_count = (shadow_data->num_volumes * 2 *
1161 sizeof(SHADOW_COPY_LABEL)) + 2;
1166 *out_len = 12 + labels_data_count;
1169 if (max_out_len < *out_len) {
1170 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1171 max_out_len, *out_len));
1172 TALLOC_FREE(shadow_data);
1173 return NT_STATUS_BUFFER_TOO_SMALL;
1176 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1177 if (cur_pdata == NULL) {
1178 TALLOC_FREE(shadow_data);
1179 return NT_STATUS_NO_MEMORY;
1182 *out_data = cur_pdata;
1184 /* num_volumes 4 bytes */
1185 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1188 /* num_labels 4 bytes */
1189 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1192 /* needed_data_count 4 bytes */
1193 SIVAL(cur_pdata, 8, labels_data_count);
1197 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1198 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1199 if (labels && shadow_data->labels) {
1200 for (i=0; i<shadow_data->num_volumes; i++) {
1202 status = srvstr_push(cur_pdata, req_flags,
1203 cur_pdata, shadow_data->labels[i],
1204 2 * sizeof(SHADOW_COPY_LABEL),
1205 STR_UNICODE|STR_TERMINATE, &len);
1206 if (!NT_STATUS_IS_OK(status)) {
1207 TALLOC_FREE(*out_data);
1208 TALLOC_FREE(shadow_data);
1211 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1212 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1216 TALLOC_FREE(shadow_data);
1218 return NT_STATUS_OK;
1221 case FSCTL_FIND_FILES_BY_SID:
1223 /* pretend this succeeded -
1225 * we have to send back a list with all files owned by this SID
1227 * but I have to check that --metze
1233 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1234 fsp_fnum_dbg(fsp)));
1237 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1238 return NT_STATUS_INVALID_PARAMETER;
1241 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1243 /* unknown 4 bytes: this is not the length of the sid :-( */
1244 /*unknown = IVAL(pdata,0);*/
1246 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1249 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1251 if (!sid_to_uid(&sid, &uid)) {
1252 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1253 sid_string_dbg(&sid),
1254 (unsigned long)sid_len));
1258 /* we can take a look at the find source :-)
1260 * find ./ -uid $uid -name '*' is what we need here
1263 * and send 4bytes len and then NULL terminated unicode strings
1266 * but I don't know how to deal with the paged results
1267 * (maybe we can hang the result anywhere in the fsp struct)
1269 * but I don't know how to deal with the paged results
1270 * (maybe we can hang the result anywhere in the fsp struct)
1272 * we don't send all files at once
1273 * and at the next we should *not* start from the beginning,
1274 * so we have to cache the result
1279 /* this works for now... */
1280 return NT_STATUS_OK;
1283 case FSCTL_QUERY_ALLOCATED_RANGES:
1285 /* FIXME: This is just a dummy reply, telling that all of the
1286 * file is allocated. MKS cp needs that.
1287 * Adding the real allocated ranges via FIEMAP on Linux
1288 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1289 * this FSCTL correct for sparse files.
1291 uint64_t offset, length;
1292 char *out_data_tmp = NULL;
1295 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1297 return NT_STATUS_INVALID_PARAMETER;
1300 if (max_out_len < 16) {
1301 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1303 return NT_STATUS_INVALID_PARAMETER;
1306 offset = BVAL(in_data,0);
1307 length = BVAL(in_data,8);
1309 if (offset + length < offset) {
1310 /* No 64-bit integer wrap. */
1311 return NT_STATUS_INVALID_PARAMETER;
1314 /* Shouldn't this be SMB_VFS_STAT ... ? */
1315 status = vfs_stat_fsp(fsp);
1316 if (!NT_STATUS_IS_OK(status)) {
1321 out_data_tmp = talloc_array(ctx, char, *out_len);
1322 if (out_data_tmp == NULL) {
1323 DEBUG(10, ("unable to allocate memory for response\n"));
1324 return NT_STATUS_NO_MEMORY;
1327 if (offset > fsp->fsp_name->st.st_ex_size ||
1328 fsp->fsp_name->st.st_ex_size == 0 ||
1330 memset(out_data_tmp, 0, *out_len);
1332 uint64_t end = offset + length;
1333 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1334 SBVAL(out_data_tmp, 0, 0);
1335 SBVAL(out_data_tmp, 8, end);
1338 *out_data = out_data_tmp;
1340 return NT_STATUS_OK;
1343 case FSCTL_IS_VOLUME_DIRTY:
1345 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1346 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1348 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1349 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1351 return NT_STATUS_INVALID_PARAMETER;
1356 * Only print once ... unfortunately there could be lots of
1357 * different FSCTLs that are called.
1359 if (!vfswrap_logged_ioctl_message) {
1360 vfswrap_logged_ioctl_message = true;
1361 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1362 __func__, function));
1366 return NT_STATUS_NOT_SUPPORTED;
1369 struct vfs_cc_state {
1374 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1375 TALLOC_CTX *mem_ctx,
1376 struct tevent_context *ev,
1377 struct files_struct *src_fsp,
1379 struct files_struct *dest_fsp,
1383 struct tevent_req *req;
1384 struct vfs_cc_state *vfs_cc_state;
1387 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1388 (unsigned long)num));
1390 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1395 status = vfs_stat_fsp(src_fsp);
1396 if (tevent_req_nterror(req, status)) {
1397 return tevent_req_post(req, ev);
1400 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1402 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1403 * If the SourceOffset or SourceOffset + Length extends beyond
1404 * the end of file, the server SHOULD<240> treat this as a
1405 * STATUS_END_OF_FILE error.
1407 * <240> Section 3.3.5.15.6: Windows servers will return
1408 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1410 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1411 return tevent_req_post(req, ev);
1414 /* could use 2.6.33+ sendfile here to do this in kernel */
1415 while (vfs_cc_state->copied < num) {
1417 struct lock_struct lck;
1420 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1421 num - vfs_cc_state->copied);
1423 if (src_fsp->op == NULL) {
1424 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1425 return tevent_req_post(req, ev);
1427 init_strict_lock_struct(src_fsp,
1428 src_fsp->op->global->open_persistent_id,
1434 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1435 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1436 return tevent_req_post(req, ev);
1439 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1442 saved_errno = errno;
1445 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1448 errno = saved_errno;
1449 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1450 return tevent_req_post(req, ev);
1452 if (ret != this_num) {
1453 /* zero tolerance for short reads */
1454 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1455 return tevent_req_post(req, ev);
1460 if (dest_fsp->op == NULL) {
1461 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1462 return tevent_req_post(req, ev);
1465 init_strict_lock_struct(dest_fsp,
1466 dest_fsp->op->global->open_persistent_id,
1472 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1473 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1474 return tevent_req_post(req, ev);
1477 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1478 this_num, dest_off);
1480 saved_errno = errno;
1483 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1486 errno = saved_errno;
1487 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1488 return tevent_req_post(req, ev);
1490 if (ret != this_num) {
1491 /* zero tolerance for short writes */
1492 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1493 return tevent_req_post(req, ev);
1497 vfs_cc_state->copied += this_num;
1500 tevent_req_done(req);
1501 return tevent_req_post(req, ev);
1504 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1505 struct tevent_req *req,
1508 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1509 struct vfs_cc_state);
1512 if (tevent_req_is_nterror(req, &status)) {
1513 DEBUG(2, ("server side copy chunk failed: %s\n",
1514 nt_errstr(status)));
1516 tevent_req_received(req);
1520 *copied = vfs_cc_state->copied;
1521 DEBUG(10, ("server side copy chunk copied %lu\n",
1522 (unsigned long)*copied));
1523 tevent_req_received(req);
1525 return NT_STATUS_OK;
1528 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1529 TALLOC_CTX *mem_ctx,
1530 struct files_struct *fsp,
1531 struct smb_filename *smb_fname,
1532 uint16_t *_compression_fmt)
1534 return NT_STATUS_INVALID_DEVICE_REQUEST;
1537 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1538 TALLOC_CTX *mem_ctx,
1539 struct files_struct *fsp,
1540 uint16_t compression_fmt)
1542 return NT_STATUS_INVALID_DEVICE_REQUEST;
1545 /********************************************************************
1546 Given a stat buffer return the allocated size on disk, taking into
1547 account sparse files.
1548 ********************************************************************/
1549 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1550 struct files_struct *fsp,
1551 const SMB_STRUCT_STAT *sbuf)
1555 START_PROFILE(syscall_get_alloc_size);
1557 if(S_ISDIR(sbuf->st_ex_mode)) {
1562 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1563 /* The type of st_blocksize is blkcnt_t which *MUST* be
1564 signed (according to POSIX) and can be less than 64-bits.
1565 Ensure when we're converting to 64 bits wide we don't
1567 #if defined(SIZEOF_BLKCNT_T_8)
1568 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1569 #elif defined(SIZEOF_BLKCNT_T_4)
1571 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1572 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1575 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1579 * Some file systems do not allocate a block for very
1580 * small files. But for non-empty file should report a
1584 uint64_t filesize = get_file_size_stat(sbuf);
1586 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1590 result = get_file_size_stat(sbuf);
1593 if (fsp && fsp->initial_allocation_size)
1594 result = MAX(result,fsp->initial_allocation_size);
1596 result = smb_roundup(handle->conn, result);
1599 END_PROFILE(syscall_get_alloc_size);
1603 static int vfswrap_unlink(vfs_handle_struct *handle,
1604 const struct smb_filename *smb_fname)
1608 START_PROFILE(syscall_unlink);
1610 if (smb_fname->stream_name) {
1614 result = unlink(smb_fname->base_name);
1617 END_PROFILE(syscall_unlink);
1621 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1625 START_PROFILE(syscall_chmod);
1628 * We need to do this due to the fact that the default POSIX ACL
1629 * chmod modifies the ACL *mask* for the group owner, not the
1630 * group owner bits directly. JRA.
1635 int saved_errno = errno; /* We might get ENOSYS */
1636 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1637 END_PROFILE(syscall_chmod);
1640 /* Error - return the old errno. */
1641 errno = saved_errno;
1644 result = chmod(path, mode);
1645 END_PROFILE(syscall_chmod);
1649 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1653 START_PROFILE(syscall_fchmod);
1656 * We need to do this due to the fact that the default POSIX ACL
1657 * chmod modifies the ACL *mask* for the group owner, not the
1658 * group owner bits directly. JRA.
1662 int saved_errno = errno; /* We might get ENOSYS */
1663 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1664 END_PROFILE(syscall_fchmod);
1667 /* Error - return the old errno. */
1668 errno = saved_errno;
1671 #if defined(HAVE_FCHMOD)
1672 result = fchmod(fsp->fh->fd, mode);
1678 END_PROFILE(syscall_fchmod);
1682 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1686 START_PROFILE(syscall_chown);
1687 result = chown(path, uid, gid);
1688 END_PROFILE(syscall_chown);
1692 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1697 START_PROFILE(syscall_fchown);
1698 result = fchown(fsp->fh->fd, uid, gid);
1699 END_PROFILE(syscall_fchown);
1707 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1711 START_PROFILE(syscall_lchown);
1712 result = lchown(path, uid, gid);
1713 END_PROFILE(syscall_lchown);
1717 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1721 START_PROFILE(syscall_chdir);
1722 result = chdir(path);
1723 END_PROFILE(syscall_chdir);
1727 static char *vfswrap_getwd(vfs_handle_struct *handle)
1731 START_PROFILE(syscall_getwd);
1732 result = sys_getwd();
1733 END_PROFILE(syscall_getwd);
1737 /*********************************************************************
1738 nsec timestamp resolution call. Convert down to whatever the underlying
1739 system will support.
1740 **********************************************************************/
1742 static int vfswrap_ntimes(vfs_handle_struct *handle,
1743 const struct smb_filename *smb_fname,
1744 struct smb_file_time *ft)
1748 START_PROFILE(syscall_ntimes);
1750 if (smb_fname->stream_name) {
1756 if (null_timespec(ft->atime)) {
1757 ft->atime= smb_fname->st.st_ex_atime;
1760 if (null_timespec(ft->mtime)) {
1761 ft->mtime = smb_fname->st.st_ex_mtime;
1764 if (!null_timespec(ft->create_time)) {
1765 set_create_timespec_ea(handle->conn,
1770 if ((timespec_compare(&ft->atime,
1771 &smb_fname->st.st_ex_atime) == 0) &&
1772 (timespec_compare(&ft->mtime,
1773 &smb_fname->st.st_ex_mtime) == 0)) {
1778 #if defined(HAVE_UTIMENSAT)
1780 struct timespec ts[2];
1783 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1785 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1787 if (!((result == -1) && (errno == ENOSYS))) {
1791 #if defined(HAVE_UTIMES)
1793 struct timeval tv[2];
1794 tv[0] = convert_timespec_to_timeval(ft->atime);
1795 tv[1] = convert_timespec_to_timeval(ft->mtime);
1796 result = utimes(smb_fname->base_name, tv);
1798 result = utimes(smb_fname->base_name, NULL);
1800 if (!((result == -1) && (errno == ENOSYS))) {
1804 #if defined(HAVE_UTIME)
1806 struct utimbuf times;
1807 times.actime = convert_timespec_to_time_t(ft->atime);
1808 times.modtime = convert_timespec_to_time_t(ft->mtime);
1809 result = utime(smb_fname->base_name, ×);
1811 result = utime(smb_fname->base_name, NULL);
1813 if (!((result == -1) && (errno == ENOSYS))) {
1821 END_PROFILE(syscall_ntimes);
1825 /*********************************************************************
1826 A version of ftruncate that will write the space on disk if strict
1828 **********************************************************************/
1830 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1832 off_t space_to_write;
1833 uint64_t space_avail;
1834 uint64_t bsize,dfree,dsize;
1837 SMB_STRUCT_STAT *pst;
1839 status = vfs_stat_fsp(fsp);
1840 if (!NT_STATUS_IS_OK(status)) {
1843 pst = &fsp->fsp_name->st;
1846 if (S_ISFIFO(pst->st_ex_mode))
1850 if (pst->st_ex_size == len)
1853 /* Shrink - just ftruncate. */
1854 if (pst->st_ex_size > len)
1855 return ftruncate(fsp->fh->fd, len);
1857 space_to_write = len - pst->st_ex_size;
1859 /* for allocation try fallocate first. This can fail on some
1860 platforms e.g. when the filesystem doesn't support it and no
1861 emulation is being done by the libc (like on AIX with JFS1). In that
1862 case we do our own emulation. fallocate implementations can
1863 return ENOTSUP or EINVAL in cases like that. */
1864 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1865 if (ret == -1 && errno == ENOSPC) {
1871 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1872 "error %d. Falling back to slow manual allocation\n", errno));
1874 /* available disk space is enough or not? */
1875 space_avail = get_dfree_info(fsp->conn,
1876 fsp->fsp_name->base_name,
1877 &bsize, &dfree, &dsize);
1878 /* space_avail is 1k blocks */
1879 if (space_avail == (uint64_t)-1 ||
1880 ((uint64_t)space_to_write/1024 > space_avail) ) {
1885 /* Write out the real space on disk. */
1886 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1894 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1897 SMB_STRUCT_STAT *pst;
1901 START_PROFILE(syscall_ftruncate);
1903 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1904 result = strict_allocate_ftruncate(handle, fsp, len);
1905 END_PROFILE(syscall_ftruncate);
1909 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1910 ftruncate if the system supports it. Then I discovered that
1911 you can have some filesystems that support ftruncate
1912 expansion and some that don't! On Linux fat can't do
1913 ftruncate extend but ext2 can. */
1915 result = ftruncate(fsp->fh->fd, len);
1919 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1920 extend a file with ftruncate. Provide alternate implementation
1923 /* Do an fstat to see if the file is longer than the requested
1924 size in which case the ftruncate above should have
1925 succeeded or shorter, in which case seek to len - 1 and
1926 write 1 byte of zero */
1927 status = vfs_stat_fsp(fsp);
1928 if (!NT_STATUS_IS_OK(status)) {
1931 pst = &fsp->fsp_name->st;
1934 if (S_ISFIFO(pst->st_ex_mode)) {
1940 if (pst->st_ex_size == len) {
1945 if (pst->st_ex_size > len) {
1946 /* the ftruncate should have worked */
1950 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1958 END_PROFILE(syscall_ftruncate);
1962 static int vfswrap_fallocate(vfs_handle_struct *handle,
1970 START_PROFILE(syscall_fallocate);
1972 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1974 * posix_fallocate returns 0 on success, errno on error
1975 * and doesn't set errno. Make it behave like fallocate()
1976 * which returns -1, and sets errno on failure.
1983 /* sys_fallocate handles filtering of unsupported mode flags */
1984 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1986 END_PROFILE(syscall_fallocate);
1990 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1994 START_PROFILE(syscall_fcntl_lock);
1995 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1996 END_PROFILE(syscall_fcntl_lock);
2000 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2001 uint32 share_mode, uint32 access_mask)
2003 START_PROFILE(syscall_kernel_flock);
2004 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2005 END_PROFILE(syscall_kernel_flock);
2009 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2013 START_PROFILE(syscall_fcntl_getlock);
2014 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2015 END_PROFILE(syscall_fcntl_getlock);
2019 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2024 START_PROFILE(syscall_linux_setlease);
2026 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2027 result = linux_setlease(fsp->fh->fd, leasetype);
2031 END_PROFILE(syscall_linux_setlease);
2035 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2039 START_PROFILE(syscall_symlink);
2040 result = symlink(oldpath, newpath);
2041 END_PROFILE(syscall_symlink);
2045 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2049 START_PROFILE(syscall_readlink);
2050 result = readlink(path, buf, bufsiz);
2051 END_PROFILE(syscall_readlink);
2055 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2059 START_PROFILE(syscall_link);
2060 result = link(oldpath, newpath);
2061 END_PROFILE(syscall_link);
2065 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2069 START_PROFILE(syscall_mknod);
2070 result = sys_mknod(pathname, mode, dev);
2071 END_PROFILE(syscall_mknod);
2075 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2079 START_PROFILE(syscall_realpath);
2080 #ifdef REALPATH_TAKES_NULL
2081 result = realpath(path, NULL);
2083 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2085 char *resolved_path = realpath(path, result);
2086 if (!resolved_path) {
2089 /* SMB_ASSERT(result == resolved_path) ? */
2090 result = resolved_path;
2094 END_PROFILE(syscall_realpath);
2098 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2099 struct sys_notify_context *ctx,
2102 uint32_t *subdir_filter,
2103 void (*callback)(struct sys_notify_context *ctx,
2105 struct notify_event *ev),
2106 void *private_data, void *handle)
2109 * So far inotify is the only supported default notify mechanism. If
2110 * another platform like the the BSD's or a proprietary Unix comes
2111 * along and wants another default, we can play the same trick we
2112 * played with Posix ACLs.
2114 * Until that is the case, hard-code inotify here.
2117 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2119 if (!lp_parm_bool(-1, "notify", "inotify", True)) {
2120 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2123 * "ctx->private_data" is not obvious as a talloc context
2124 * here. Without modifying the VFS we don't have a mem_ctx
2125 * available here, and ctx->private_data was used by
2126 * inotify_watch before it got a real talloc parent.
2128 ret = inotify_watch(ctx->private_data, ctx,
2129 path, filter, subdir_filter,
2130 callback, private_data, handle);
2132 return map_nt_error_from_unix(ret);
2134 return NT_STATUS_OK;
2138 * Do nothing, leave everything to notify_internal.c
2140 return NT_STATUS_OK;
2143 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2147 return chflags(path, flags);
2154 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2155 const SMB_STRUCT_STAT *sbuf)
2159 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2163 key.devid = sbuf->st_ex_dev;
2164 key.inode = sbuf->st_ex_ino;
2165 /* key.extid is unused by default. */
2170 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2171 struct files_struct *fsp,
2173 TALLOC_CTX *mem_ctx,
2174 unsigned int *pnum_streams,
2175 struct stream_struct **pstreams)
2177 SMB_STRUCT_STAT sbuf;
2178 struct stream_struct *tmp_streams = NULL;
2181 if ((fsp != NULL) && (fsp->is_directory)) {
2183 * No default streams on directories
2188 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2189 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2192 struct smb_filename smb_fname;
2194 ZERO_STRUCT(smb_fname);
2195 smb_fname.base_name = discard_const_p(char, fname);
2197 if (lp_posix_pathnames()) {
2198 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2200 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2202 sbuf = smb_fname.st;
2206 return map_nt_error_from_unix(errno);
2209 if (S_ISDIR(sbuf.st_ex_mode)) {
2213 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2214 (*pnum_streams) + 1);
2215 if (tmp_streams == NULL) {
2216 return NT_STATUS_NO_MEMORY;
2218 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2219 if (tmp_streams[*pnum_streams].name == NULL) {
2220 return NT_STATUS_NO_MEMORY;
2222 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2223 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2226 *pstreams = tmp_streams;
2228 return NT_STATUS_OK;
2231 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2234 TALLOC_CTX *mem_ctx,
2238 * Don't fall back to get_real_filename so callers can differentiate
2239 * between a full directory scan and an actual case-insensitive stat.
2245 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2248 return handle->conn->connectpath;
2251 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2252 struct byte_range_lock *br_lck,
2253 struct lock_struct *plock,
2256 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2258 /* Note: blr is not used in the default implementation. */
2259 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2262 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2263 struct messaging_context *msg_ctx,
2264 struct byte_range_lock *br_lck,
2265 const struct lock_struct *plock)
2267 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2269 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2272 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2273 struct byte_range_lock *br_lck,
2274 struct lock_struct *plock)
2276 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2278 /* Note: blr is not used in the default implementation. */
2279 return brl_lock_cancel_default(br_lck, plock);
2282 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2284 struct lock_struct *plock)
2286 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2287 plock->lock_type == WRITE_LOCK);
2289 return strict_lock_default(fsp, plock);
2292 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2294 struct lock_struct *plock)
2296 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2297 plock->lock_type == WRITE_LOCK);
2299 strict_unlock_default(fsp, plock);
2302 /* NT ACL operations. */
2304 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2306 uint32 security_info,
2307 TALLOC_CTX *mem_ctx,
2308 struct security_descriptor **ppdesc)
2312 START_PROFILE(fget_nt_acl);
2313 result = posix_fget_nt_acl(fsp, security_info,
2315 END_PROFILE(fget_nt_acl);
2319 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2321 uint32 security_info,
2322 TALLOC_CTX *mem_ctx,
2323 struct security_descriptor **ppdesc)
2327 START_PROFILE(get_nt_acl);
2328 result = posix_get_nt_acl(handle->conn, name, security_info,
2330 END_PROFILE(get_nt_acl);
2334 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2338 START_PROFILE(fset_nt_acl);
2339 result = set_nt_acl(fsp, security_info_sent, psd);
2340 END_PROFILE(fset_nt_acl);
2344 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2345 struct smb_filename *file,
2346 struct security_acl *sacl,
2347 uint32_t access_requested,
2348 uint32_t access_denied)
2350 return NT_STATUS_OK; /* Nothing to do here ... */
2353 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2361 START_PROFILE(chmod_acl);
2362 result = chmod_acl(handle->conn, name, mode);
2363 END_PROFILE(chmod_acl);
2368 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2376 START_PROFILE(fchmod_acl);
2377 result = fchmod_acl(fsp, mode);
2378 END_PROFILE(fchmod_acl);
2383 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2385 SMB_ACL_TYPE_T type,
2386 TALLOC_CTX *mem_ctx)
2388 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2391 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2393 TALLOC_CTX *mem_ctx)
2395 return sys_acl_get_fd(handle, fsp, mem_ctx);
2398 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2400 return sys_acl_set_file(handle, name, acltype, theacl);
2403 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2405 return sys_acl_set_fd(handle, fsp, theacl);
2408 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2410 return sys_acl_delete_def_file(handle, path);
2413 /****************************************************************
2414 Extended attribute operations.
2415 *****************************************************************/
2417 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2419 return getxattr(path, name, value, size);
2422 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2424 return fgetxattr(fsp->fh->fd, name, value, size);
2427 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2429 return listxattr(path, list, size);
2432 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2434 return flistxattr(fsp->fh->fd, list, size);
2437 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2439 return removexattr(path, name);
2442 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2444 return fremovexattr(fsp->fh->fd, name);
2447 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2449 return setxattr(path, name, value, size, flags);
2452 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2454 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2457 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2462 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2463 const struct smb_filename *fname,
2464 SMB_STRUCT_STAT *sbuf)
2468 bool offline = false;
2470 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2474 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2475 #if defined(ENOTSUP)
2481 status = get_full_smb_filename(talloc_tos(), fname, &path);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 errno = map_errno_from_nt_status(status);
2487 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2494 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2495 const struct smb_filename *fname)
2497 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2498 #if defined(ENOTSUP)
2504 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2505 struct files_struct *fsp,
2506 TALLOC_CTX *mem_ctx,
2509 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2512 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2513 struct files_struct *fsp,
2514 const DATA_BLOB old_cookie,
2515 TALLOC_CTX *mem_ctx,
2516 DATA_BLOB *new_cookie)
2518 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2522 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2523 struct smb_request *smb1req,
2524 struct smbXsrv_open *op,
2525 const DATA_BLOB old_cookie,
2526 TALLOC_CTX *mem_ctx,
2527 struct files_struct **fsp,
2528 DATA_BLOB *new_cookie)
2530 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2531 old_cookie, mem_ctx,
2535 static struct vfs_fn_pointers vfs_default_fns = {
2536 /* Disk operations */
2538 .connect_fn = vfswrap_connect,
2539 .disconnect_fn = vfswrap_disconnect,
2540 .disk_free_fn = vfswrap_disk_free,
2541 .get_quota_fn = vfswrap_get_quota,
2542 .set_quota_fn = vfswrap_set_quota,
2543 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2544 .statvfs_fn = vfswrap_statvfs,
2545 .fs_capabilities_fn = vfswrap_fs_capabilities,
2546 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2548 /* Directory operations */
2550 .opendir_fn = vfswrap_opendir,
2551 .fdopendir_fn = vfswrap_fdopendir,
2552 .readdir_fn = vfswrap_readdir,
2553 .readdir_attr_fn = vfswrap_readdir_attr,
2554 .seekdir_fn = vfswrap_seekdir,
2555 .telldir_fn = vfswrap_telldir,
2556 .rewind_dir_fn = vfswrap_rewinddir,
2557 .mkdir_fn = vfswrap_mkdir,
2558 .rmdir_fn = vfswrap_rmdir,
2559 .closedir_fn = vfswrap_closedir,
2560 .init_search_op_fn = vfswrap_init_search_op,
2562 /* File operations */
2564 .open_fn = vfswrap_open,
2565 .create_file_fn = vfswrap_create_file,
2566 .close_fn = vfswrap_close,
2567 .read_fn = vfswrap_read,
2568 .pread_fn = vfswrap_pread,
2569 .pread_send_fn = vfswrap_pread_send,
2570 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2571 .write_fn = vfswrap_write,
2572 .pwrite_fn = vfswrap_pwrite,
2573 .pwrite_send_fn = vfswrap_pwrite_send,
2574 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2575 .lseek_fn = vfswrap_lseek,
2576 .sendfile_fn = vfswrap_sendfile,
2577 .recvfile_fn = vfswrap_recvfile,
2578 .rename_fn = vfswrap_rename,
2579 .fsync_fn = vfswrap_fsync,
2580 .fsync_send_fn = vfswrap_fsync_send,
2581 .fsync_recv_fn = vfswrap_asys_int_recv,
2582 .stat_fn = vfswrap_stat,
2583 .fstat_fn = vfswrap_fstat,
2584 .lstat_fn = vfswrap_lstat,
2585 .get_alloc_size_fn = vfswrap_get_alloc_size,
2586 .unlink_fn = vfswrap_unlink,
2587 .chmod_fn = vfswrap_chmod,
2588 .fchmod_fn = vfswrap_fchmod,
2589 .chown_fn = vfswrap_chown,
2590 .fchown_fn = vfswrap_fchown,
2591 .lchown_fn = vfswrap_lchown,
2592 .chdir_fn = vfswrap_chdir,
2593 .getwd_fn = vfswrap_getwd,
2594 .ntimes_fn = vfswrap_ntimes,
2595 .ftruncate_fn = vfswrap_ftruncate,
2596 .fallocate_fn = vfswrap_fallocate,
2597 .lock_fn = vfswrap_lock,
2598 .kernel_flock_fn = vfswrap_kernel_flock,
2599 .linux_setlease_fn = vfswrap_linux_setlease,
2600 .getlock_fn = vfswrap_getlock,
2601 .symlink_fn = vfswrap_symlink,
2602 .readlink_fn = vfswrap_readlink,
2603 .link_fn = vfswrap_link,
2604 .mknod_fn = vfswrap_mknod,
2605 .realpath_fn = vfswrap_realpath,
2606 .notify_watch_fn = vfswrap_notify_watch,
2607 .chflags_fn = vfswrap_chflags,
2608 .file_id_create_fn = vfswrap_file_id_create,
2609 .streaminfo_fn = vfswrap_streaminfo,
2610 .get_real_filename_fn = vfswrap_get_real_filename,
2611 .connectpath_fn = vfswrap_connectpath,
2612 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2613 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2614 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2615 .strict_lock_fn = vfswrap_strict_lock,
2616 .strict_unlock_fn = vfswrap_strict_unlock,
2617 .translate_name_fn = vfswrap_translate_name,
2618 .fsctl_fn = vfswrap_fsctl,
2619 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2620 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2621 .get_compression_fn = vfswrap_get_compression,
2622 .set_compression_fn = vfswrap_set_compression,
2624 /* NT ACL operations. */
2626 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2627 .get_nt_acl_fn = vfswrap_get_nt_acl,
2628 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2629 .audit_file_fn = vfswrap_audit_file,
2631 /* POSIX ACL operations. */
2633 .chmod_acl_fn = vfswrap_chmod_acl,
2634 .fchmod_acl_fn = vfswrap_fchmod_acl,
2636 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2637 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2638 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2639 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2640 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2641 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2642 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2644 /* EA operations. */
2645 .getxattr_fn = vfswrap_getxattr,
2646 .fgetxattr_fn = vfswrap_fgetxattr,
2647 .listxattr_fn = vfswrap_listxattr,
2648 .flistxattr_fn = vfswrap_flistxattr,
2649 .removexattr_fn = vfswrap_removexattr,
2650 .fremovexattr_fn = vfswrap_fremovexattr,
2651 .setxattr_fn = vfswrap_setxattr,
2652 .fsetxattr_fn = vfswrap_fsetxattr,
2654 /* aio operations */
2655 .aio_force_fn = vfswrap_aio_force,
2657 /* offline operations */
2658 .is_offline_fn = vfswrap_is_offline,
2659 .set_offline_fn = vfswrap_set_offline,
2661 /* durable handle operations */
2662 .durable_cookie_fn = vfswrap_durable_cookie,
2663 .durable_disconnect_fn = vfswrap_durable_disconnect,
2664 .durable_reconnect_fn = vfswrap_durable_reconnect,
2667 NTSTATUS vfs_default_init(void);
2668 NTSTATUS vfs_default_init(void)
2670 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2671 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);