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, bool small_query, uint64_t *bsize,
58 uint64_t *dfree, uint64_t *dsize)
62 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
66 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
68 #ifdef HAVE_SYS_QUOTAS
71 START_PROFILE(syscall_get_quota);
72 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
73 END_PROFILE(syscall_get_quota);
81 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
83 #ifdef HAVE_SYS_QUOTAS
86 START_PROFILE(syscall_set_quota);
87 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
88 END_PROFILE(syscall_set_quota);
96 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
97 struct files_struct *fsp,
98 struct shadow_copy_data *shadow_copy_data,
102 return -1; /* Not implemented. */
105 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
107 return sys_statvfs(path, statbuf);
110 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
111 enum timestamp_set_resolution *p_ts_res)
113 connection_struct *conn = handle->conn;
114 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
115 struct smb_filename *smb_fname_cpath = NULL;
116 struct vfs_statvfs_struct statbuf;
119 ZERO_STRUCT(statbuf);
120 ret = sys_statvfs(conn->connectpath, &statbuf);
122 caps = statbuf.FsCapabilities;
125 *p_ts_res = TIMESTAMP_SET_SECONDS;
127 /* Work out what timestamp resolution we can
128 * use when setting a timestamp. */
130 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
132 if (smb_fname_cpath == NULL) {
136 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
138 TALLOC_FREE(smb_fname_cpath);
142 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
143 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
144 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
145 /* If any of the normal UNIX directory timestamps
146 * have a non-zero tv_nsec component assume
147 * we might be able to set sub-second timestamps.
148 * See what filetime set primitives we have.
150 #if defined(HAVE_UTIMENSAT)
151 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
152 #elif defined(HAVE_UTIMES)
153 /* utimes allows msec timestamps to be set. */
154 *p_ts_res = TIMESTAMP_SET_MSEC;
155 #elif defined(HAVE_UTIME)
156 /* utime only allows sec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_SECONDS;
160 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
162 "available on share %s, directory %s\n",
163 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
164 lp_servicename(talloc_tos(), conn->params->service),
165 conn->connectpath ));
167 TALLOC_FREE(smb_fname_cpath);
171 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
172 struct dfs_GetDFSReferral *r)
174 struct junction_map *junction = NULL;
176 bool self_referral = false;
177 char *pathnamep = NULL;
178 char *local_dfs_path = NULL;
181 uint16_t max_referral_level = r->in.req.max_referral_level;
184 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
187 /* get the junction entry */
188 if (r->in.req.servername == NULL) {
189 return NT_STATUS_NOT_FOUND;
193 * Trim pathname sent by client so it begins with only one backslash.
194 * Two backslashes confuse some dfs clients
197 local_dfs_path = talloc_strdup(r, r->in.req.servername);
198 if (local_dfs_path == NULL) {
199 return NT_STATUS_NO_MEMORY;
201 pathnamep = local_dfs_path;
202 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
203 IS_DIRECTORY_SEP(pathnamep[1])) {
207 junction = talloc_zero(r, struct junction_map);
208 if (junction == NULL) {
209 return NT_STATUS_NO_MEMORY;
212 /* The following call can change cwd. */
213 status = get_referred_path(r, pathnamep,
214 !handle->conn->sconn->using_smb2,
215 junction, &consumedcnt, &self_referral);
216 if (!NT_STATUS_IS_OK(status)) {
217 vfs_ChDir(handle->conn, handle->conn->connectpath);
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
222 if (!self_referral) {
223 pathnamep[consumedcnt] = '\0';
226 dbgtext("setup_dfs_referral: Path %s to "
227 "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,("setup_dfs_referral: Invalid dfs referral "
335 max_referral_level));
336 return NT_STATUS_INVALID_LEVEL;
340 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
346 /* Directory operations */
348 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
352 START_PROFILE(syscall_opendir);
353 result = opendir(fname);
354 END_PROFILE(syscall_opendir);
358 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
365 START_PROFILE(syscall_fdopendir);
366 result = sys_fdopendir(fsp->fh->fd);
367 END_PROFILE(syscall_fdopendir);
372 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
374 SMB_STRUCT_STAT *sbuf)
376 struct dirent *result;
378 START_PROFILE(syscall_readdir);
379 result = readdir(dirp);
380 END_PROFILE(syscall_readdir);
382 /* Default Posix readdir() does not give us stat info.
383 * Set to invalid to indicate we didn't return this info. */
384 SET_STAT_INVALID(*sbuf);
385 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
386 if (result != NULL) {
387 /* See if we can efficiently return this. */
389 int flags = (lp_posix_pathnames() ?
390 AT_SYMLINK_NOFOLLOW : 0);
391 int ret = fstatat(dirfd(dirp),
396 init_stat_ex_from_stat(sbuf,
398 lp_fake_directory_create_times(
399 SNUM(handle->conn)));
407 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
408 const struct smb_filename *fname,
410 struct readdir_attr_data **attr_data)
412 return NT_STATUS_NOT_SUPPORTED;
415 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
417 START_PROFILE(syscall_seekdir);
418 seekdir(dirp, offset);
419 END_PROFILE(syscall_seekdir);
422 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
425 START_PROFILE(syscall_telldir);
426 result = telldir(dirp);
427 END_PROFILE(syscall_telldir);
431 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
433 START_PROFILE(syscall_rewinddir);
435 END_PROFILE(syscall_rewinddir);
438 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
441 bool has_dacl = False;
444 START_PROFILE(syscall_mkdir);
446 if (lp_inherit_acls(SNUM(handle->conn))
447 && parent_dirname(talloc_tos(), path, &parent, NULL)
448 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
449 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
453 result = mkdir(path, mode);
455 if (result == 0 && !has_dacl) {
457 * We need to do this as the default behavior of POSIX ACLs
458 * is to set the mask to be the requested group permission
459 * bits, not the group permission bits to be the requested
460 * group permission bits. This is not what we want, as it will
461 * mess up any inherited ACL bits that were set. JRA.
463 int saved_errno = errno; /* We may get ENOSYS */
464 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
468 END_PROFILE(syscall_mkdir);
472 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
476 START_PROFILE(syscall_rmdir);
477 result = rmdir(path);
478 END_PROFILE(syscall_rmdir);
482 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
486 START_PROFILE(syscall_closedir);
487 result = closedir(dirp);
488 END_PROFILE(syscall_closedir);
492 static void vfswrap_init_search_op(vfs_handle_struct *handle,
495 /* Default behavior is a NOOP */
498 /* File operations */
500 static int vfswrap_open(vfs_handle_struct *handle,
501 struct smb_filename *smb_fname,
502 files_struct *fsp, int flags, mode_t mode)
506 START_PROFILE(syscall_open);
508 if (smb_fname->stream_name) {
513 result = open(smb_fname->base_name, flags, mode);
515 END_PROFILE(syscall_open);
519 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
520 struct smb_request *req,
521 uint16_t root_dir_fid,
522 struct smb_filename *smb_fname,
523 uint32_t access_mask,
524 uint32_t share_access,
525 uint32_t create_disposition,
526 uint32_t create_options,
527 uint32_t file_attributes,
528 uint32_t oplock_request,
529 struct smb2_lease *lease,
530 uint64_t allocation_size,
531 uint32_t private_flags,
532 struct security_descriptor *sd,
533 struct ea_list *ea_list,
534 files_struct **result,
536 const struct smb2_create_blobs *in_context_blobs,
537 struct smb2_create_blobs *out_context_blobs)
539 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
540 access_mask, share_access,
541 create_disposition, create_options,
542 file_attributes, oplock_request, lease,
543 allocation_size, private_flags,
545 pinfo, in_context_blobs, out_context_blobs);
548 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
552 START_PROFILE(syscall_close);
553 result = fd_close_posix(fsp);
554 END_PROFILE(syscall_close);
558 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
562 START_PROFILE_BYTES(syscall_read, n);
563 result = sys_read(fsp->fh->fd, data, n);
564 END_PROFILE_BYTES(syscall_read);
568 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
569 size_t n, off_t offset)
573 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
574 START_PROFILE_BYTES(syscall_pread, n);
575 result = sys_pread(fsp->fh->fd, data, n, offset);
576 END_PROFILE_BYTES(syscall_pread);
578 if (result == -1 && errno == ESPIPE) {
579 /* Maintain the fiction that pipes can be seeked (sought?) on. */
580 result = SMB_VFS_READ(fsp, data, n);
584 #else /* HAVE_PREAD */
588 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
589 if (curr == -1 && errno == ESPIPE) {
590 /* Maintain the fiction that pipes can be seeked (sought?) on. */
591 result = SMB_VFS_READ(fsp, data, n);
596 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
601 result = SMB_VFS_READ(fsp, data, n);
604 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
607 #endif /* HAVE_PREAD */
612 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
616 START_PROFILE_BYTES(syscall_write, n);
617 result = sys_write(fsp->fh->fd, data, n);
618 END_PROFILE_BYTES(syscall_write);
622 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
623 size_t n, off_t offset)
627 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
628 START_PROFILE_BYTES(syscall_pwrite, n);
629 result = sys_pwrite(fsp->fh->fd, data, n, offset);
630 END_PROFILE_BYTES(syscall_pwrite);
632 if (result == -1 && errno == ESPIPE) {
633 /* Maintain the fiction that pipes can be sought on. */
634 result = SMB_VFS_WRITE(fsp, data, n);
637 #else /* HAVE_PWRITE */
641 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
646 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
650 result = SMB_VFS_WRITE(fsp, data, n);
653 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
656 #endif /* HAVE_PWRITE */
661 static void vfswrap_asys_finished(struct tevent_context *ev,
662 struct tevent_fd *fde,
663 uint16_t flags, void *p);
665 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
670 if (conn->asys_ctx != NULL) {
673 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
675 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
679 fd = asys_signalfd(conn->asys_ctx);
681 set_blocking(fd, false);
683 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
685 vfswrap_asys_finished,
687 if (conn->asys_fde == NULL) {
688 DEBUG(1, ("tevent_add_fd failed\n"));
689 asys_context_destroy(conn->asys_ctx);
690 conn->asys_ctx = NULL;
696 struct vfswrap_asys_state {
697 struct asys_context *asys_ctx;
698 struct tevent_req *req;
701 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
702 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
705 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
707 asys_cancel(s->asys_ctx, s->req);
711 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
713 struct tevent_context *ev,
714 struct files_struct *fsp,
716 size_t n, off_t offset)
718 struct tevent_req *req;
719 struct vfswrap_asys_state *state;
722 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
726 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
728 return tevent_req_post(req, ev);
730 state->asys_ctx = handle->conn->sconn->asys_ctx;
733 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
734 state->profile_bytes, n);
735 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
737 tevent_req_error(req, ret);
738 return tevent_req_post(req, ev);
740 talloc_set_destructor(state, vfswrap_asys_state_destructor);
745 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
747 struct tevent_context *ev,
748 struct files_struct *fsp,
750 size_t n, off_t offset)
752 struct tevent_req *req;
753 struct vfswrap_asys_state *state;
756 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
760 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
762 return tevent_req_post(req, ev);
764 state->asys_ctx = handle->conn->sconn->asys_ctx;
767 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
768 state->profile_bytes, n);
769 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
771 tevent_req_error(req, ret);
772 return tevent_req_post(req, ev);
774 talloc_set_destructor(state, vfswrap_asys_state_destructor);
779 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
781 struct tevent_context *ev,
782 struct files_struct *fsp)
784 struct tevent_req *req;
785 struct vfswrap_asys_state *state;
788 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
792 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
794 return tevent_req_post(req, ev);
796 state->asys_ctx = handle->conn->sconn->asys_ctx;
799 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
800 state->profile_basic);
801 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
803 tevent_req_error(req, ret);
804 return tevent_req_post(req, ev);
806 talloc_set_destructor(state, vfswrap_asys_state_destructor);
811 static void vfswrap_asys_finished(struct tevent_context *ev,
812 struct tevent_fd *fde,
813 uint16_t flags, void *p)
815 struct asys_context *asys_ctx = (struct asys_context *)p;
816 struct asys_result results[outstanding_aio_calls];
819 if ((flags & TEVENT_FD_READ) == 0) {
823 ret = asys_results(asys_ctx, results, outstanding_aio_calls);
825 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
829 for (i=0; i<ret; i++) {
830 struct asys_result *result = &results[i];
831 struct tevent_req *req;
832 struct vfswrap_asys_state *state;
834 if ((result->ret == -1) && (result->err == ECANCELED)) {
838 req = talloc_get_type_abort(result->private_data,
840 state = tevent_req_data(req, struct vfswrap_asys_state);
842 talloc_set_destructor(state, NULL);
844 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
845 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
846 state->ret = result->ret;
847 state->err = result->err;
848 tevent_req_defer_callback(req, ev);
849 tevent_req_done(req);
853 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
855 struct vfswrap_asys_state *state = tevent_req_data(
856 req, struct vfswrap_asys_state);
858 if (tevent_req_is_unix_error(req, err)) {
865 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
867 struct vfswrap_asys_state *state = tevent_req_data(
868 req, struct vfswrap_asys_state);
870 if (tevent_req_is_unix_error(req, err)) {
877 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
881 START_PROFILE(syscall_lseek);
883 /* Cope with 'stat' file opens. */
884 if (fsp->fh->fd != -1)
885 result = lseek(fsp->fh->fd, offset, whence);
888 * We want to maintain the fiction that we can seek
889 * on a fifo for file system purposes. This allows
890 * people to set up UNIX fifo's that feed data to Windows
894 if((result == -1) && (errno == ESPIPE)) {
899 END_PROFILE(syscall_lseek);
903 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
904 off_t offset, size_t n)
908 START_PROFILE_BYTES(syscall_sendfile, n);
909 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
910 END_PROFILE_BYTES(syscall_sendfile);
914 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
922 START_PROFILE_BYTES(syscall_recvfile, n);
923 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
924 END_PROFILE_BYTES(syscall_recvfile);
928 static int vfswrap_rename(vfs_handle_struct *handle,
929 const struct smb_filename *smb_fname_src,
930 const struct smb_filename *smb_fname_dst)
934 START_PROFILE(syscall_rename);
936 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
941 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
944 END_PROFILE(syscall_rename);
948 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
953 START_PROFILE(syscall_fsync);
954 result = fsync(fsp->fh->fd);
955 END_PROFILE(syscall_fsync);
962 static int vfswrap_stat(vfs_handle_struct *handle,
963 struct smb_filename *smb_fname)
967 START_PROFILE(syscall_stat);
969 if (smb_fname->stream_name) {
974 result = sys_stat(smb_fname->base_name, &smb_fname->st,
975 lp_fake_directory_create_times(SNUM(handle->conn)));
977 END_PROFILE(syscall_stat);
981 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
985 START_PROFILE(syscall_fstat);
986 result = sys_fstat(fsp->fh->fd,
987 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
988 END_PROFILE(syscall_fstat);
992 static int vfswrap_lstat(vfs_handle_struct *handle,
993 struct smb_filename *smb_fname)
997 START_PROFILE(syscall_lstat);
999 if (smb_fname->stream_name) {
1004 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1005 lp_fake_directory_create_times(SNUM(handle->conn)));
1007 END_PROFILE(syscall_lstat);
1011 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1013 enum vfs_translate_direction direction,
1014 TALLOC_CTX *mem_ctx,
1017 return NT_STATUS_NONE_MAPPED;
1021 * Implement the default fsctl operation.
1023 static bool vfswrap_logged_ioctl_message = false;
1025 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1026 struct files_struct *fsp,
1029 uint16_t req_flags, /* Needed for UNICODE ... */
1030 const uint8_t *_in_data,
1032 uint8_t **_out_data,
1033 uint32_t max_out_len,
1036 const char *in_data = (const char *)_in_data;
1037 char **out_data = (char **)_out_data;
1041 case FSCTL_SET_SPARSE:
1043 bool set_sparse = true;
1045 if (in_len >= 1 && in_data[0] == 0) {
1049 status = file_set_sparse(handle->conn, fsp, set_sparse);
1051 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1052 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1053 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1054 nt_errstr(status)));
1059 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1061 unsigned char objid[16];
1062 char *return_data = NULL;
1064 /* This should return the object-id on this file.
1065 * I think I'll make this be the inode+dev. JRA.
1068 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1069 fsp_fnum_dbg(fsp)));
1071 *out_len = MIN(max_out_len, 64);
1073 /* Hmmm, will this cause problems if less data asked for? */
1074 return_data = talloc_array(ctx, char, 64);
1075 if (return_data == NULL) {
1076 return NT_STATUS_NO_MEMORY;
1079 /* For backwards compatibility only store the dev/inode. */
1080 push_file_id_16(return_data, &fsp->file_id);
1081 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1082 push_file_id_16(return_data+32, &fsp->file_id);
1083 memset(return_data+48, 0, 16);
1084 *out_data = return_data;
1085 return NT_STATUS_OK;
1088 case FSCTL_GET_REPARSE_POINT:
1090 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1091 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1092 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1093 return NT_STATUS_NOT_A_REPARSE_POINT;
1096 case FSCTL_SET_REPARSE_POINT:
1098 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1099 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1100 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1101 return NT_STATUS_NOT_A_REPARSE_POINT;
1104 case FSCTL_GET_SHADOW_COPY_DATA:
1107 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1108 * and return their volume names. If max_data_count is 16, then it is just
1109 * asking for the number of volumes and length of the combined names.
1111 * pdata is the data allocated by our caller, but that uses
1112 * total_data_count (which is 0 in our case) rather than max_data_count.
1113 * Allocate the correct amount and return the pointer to let
1114 * it be deallocated when we return.
1116 struct shadow_copy_data *shadow_data = NULL;
1117 bool labels = False;
1118 uint32 labels_data_count = 0;
1120 char *cur_pdata = NULL;
1122 if (max_out_len < 16) {
1123 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1125 return NT_STATUS_INVALID_PARAMETER;
1128 if (max_out_len > 16) {
1132 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1133 if (shadow_data == NULL) {
1134 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1135 return NT_STATUS_NO_MEMORY;
1139 * Call the VFS routine to actually do the work.
1141 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1144 /* broken module didn't set errno on error */
1145 status = NT_STATUS_UNSUCCESSFUL;
1147 status = map_nt_error_from_unix(errno);
1148 if (NT_STATUS_EQUAL(status,
1149 NT_STATUS_NOT_SUPPORTED)) {
1153 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1154 "connectpath %s, failed - %s.\n",
1155 fsp->conn->connectpath,
1156 nt_errstr(status)));
1157 TALLOC_FREE(shadow_data);
1161 labels_data_count = (shadow_data->num_volumes * 2 *
1162 sizeof(SHADOW_COPY_LABEL)) + 2;
1167 *out_len = 12 + labels_data_count;
1170 if (max_out_len < *out_len) {
1171 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1172 max_out_len, *out_len));
1173 TALLOC_FREE(shadow_data);
1174 return NT_STATUS_BUFFER_TOO_SMALL;
1177 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1178 if (cur_pdata == NULL) {
1179 TALLOC_FREE(shadow_data);
1180 return NT_STATUS_NO_MEMORY;
1183 *out_data = cur_pdata;
1185 /* num_volumes 4 bytes */
1186 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1189 /* num_labels 4 bytes */
1190 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1193 /* needed_data_count 4 bytes */
1194 SIVAL(cur_pdata, 8, labels_data_count);
1198 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1199 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1200 if (labels && shadow_data->labels) {
1201 for (i=0; i<shadow_data->num_volumes; i++) {
1203 status = srvstr_push(cur_pdata, req_flags,
1204 cur_pdata, shadow_data->labels[i],
1205 2 * sizeof(SHADOW_COPY_LABEL),
1206 STR_UNICODE|STR_TERMINATE, &len);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 TALLOC_FREE(*out_data);
1209 TALLOC_FREE(shadow_data);
1212 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1213 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1217 TALLOC_FREE(shadow_data);
1219 return NT_STATUS_OK;
1222 case FSCTL_FIND_FILES_BY_SID:
1224 /* pretend this succeeded -
1226 * we have to send back a list with all files owned by this SID
1228 * but I have to check that --metze
1234 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1235 fsp_fnum_dbg(fsp)));
1238 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1239 return NT_STATUS_INVALID_PARAMETER;
1242 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1244 /* unknown 4 bytes: this is not the length of the sid :-( */
1245 /*unknown = IVAL(pdata,0);*/
1247 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1248 return NT_STATUS_INVALID_PARAMETER;
1250 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1252 if (!sid_to_uid(&sid, &uid)) {
1253 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1254 sid_string_dbg(&sid),
1255 (unsigned long)sid_len));
1259 /* we can take a look at the find source :-)
1261 * find ./ -uid $uid -name '*' is what we need here
1264 * and send 4bytes len and then NULL terminated unicode strings
1267 * but I don't know how to deal with the paged results
1268 * (maybe we can hang the result anywhere in the fsp struct)
1270 * but I don't know how to deal with the paged results
1271 * (maybe we can hang the result anywhere in the fsp struct)
1273 * we don't send all files at once
1274 * and at the next we should *not* start from the beginning,
1275 * so we have to cache the result
1280 /* this works for now... */
1281 return NT_STATUS_OK;
1284 case FSCTL_QUERY_ALLOCATED_RANGES:
1286 /* FIXME: This is just a dummy reply, telling that all of the
1287 * file is allocated. MKS cp needs that.
1288 * Adding the real allocated ranges via FIEMAP on Linux
1289 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1290 * this FSCTL correct for sparse files.
1292 uint64_t offset, length;
1293 char *out_data_tmp = NULL;
1296 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1298 return NT_STATUS_INVALID_PARAMETER;
1301 if (max_out_len < 16) {
1302 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1304 return NT_STATUS_INVALID_PARAMETER;
1307 offset = BVAL(in_data,0);
1308 length = BVAL(in_data,8);
1310 if (offset + length < offset) {
1311 /* No 64-bit integer wrap. */
1312 return NT_STATUS_INVALID_PARAMETER;
1315 /* Shouldn't this be SMB_VFS_STAT ... ? */
1316 status = vfs_stat_fsp(fsp);
1317 if (!NT_STATUS_IS_OK(status)) {
1322 out_data_tmp = talloc_array(ctx, char, *out_len);
1323 if (out_data_tmp == NULL) {
1324 DEBUG(10, ("unable to allocate memory for response\n"));
1325 return NT_STATUS_NO_MEMORY;
1328 if (offset > fsp->fsp_name->st.st_ex_size ||
1329 fsp->fsp_name->st.st_ex_size == 0 ||
1331 memset(out_data_tmp, 0, *out_len);
1333 uint64_t end = offset + length;
1334 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1335 SBVAL(out_data_tmp, 0, 0);
1336 SBVAL(out_data_tmp, 8, end);
1339 *out_data = out_data_tmp;
1341 return NT_STATUS_OK;
1344 case FSCTL_IS_VOLUME_DIRTY:
1346 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1347 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1349 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1350 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1352 return NT_STATUS_INVALID_PARAMETER;
1357 * Only print once ... unfortunately there could be lots of
1358 * different FSCTLs that are called.
1360 if (!vfswrap_logged_ioctl_message) {
1361 vfswrap_logged_ioctl_message = true;
1362 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1363 __func__, function));
1367 return NT_STATUS_NOT_SUPPORTED;
1370 struct vfs_cc_state {
1375 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1376 TALLOC_CTX *mem_ctx,
1377 struct tevent_context *ev,
1378 struct files_struct *src_fsp,
1380 struct files_struct *dest_fsp,
1384 struct tevent_req *req;
1385 struct vfs_cc_state *vfs_cc_state;
1388 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1389 (unsigned long)num));
1391 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1396 status = vfs_stat_fsp(src_fsp);
1397 if (tevent_req_nterror(req, status)) {
1398 return tevent_req_post(req, ev);
1401 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1403 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1404 * If the SourceOffset or SourceOffset + Length extends beyond
1405 * the end of file, the server SHOULD<240> treat this as a
1406 * STATUS_END_OF_FILE error.
1408 * <240> Section 3.3.5.15.6: Windows servers will return
1409 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1411 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1412 return tevent_req_post(req, ev);
1415 /* could use 2.6.33+ sendfile here to do this in kernel */
1416 while (vfs_cc_state->copied < num) {
1418 struct lock_struct lck;
1421 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1422 num - vfs_cc_state->copied);
1424 if (src_fsp->op == NULL) {
1425 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1426 return tevent_req_post(req, ev);
1428 init_strict_lock_struct(src_fsp,
1429 src_fsp->op->global->open_persistent_id,
1435 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1436 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1437 return tevent_req_post(req, ev);
1440 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1443 saved_errno = errno;
1446 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1449 errno = saved_errno;
1450 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1451 return tevent_req_post(req, ev);
1453 if (ret != this_num) {
1454 /* zero tolerance for short reads */
1455 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1456 return tevent_req_post(req, ev);
1461 if (dest_fsp->op == NULL) {
1462 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1463 return tevent_req_post(req, ev);
1466 init_strict_lock_struct(dest_fsp,
1467 dest_fsp->op->global->open_persistent_id,
1473 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1474 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1475 return tevent_req_post(req, ev);
1478 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1479 this_num, dest_off);
1481 saved_errno = errno;
1484 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1487 errno = saved_errno;
1488 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1489 return tevent_req_post(req, ev);
1491 if (ret != this_num) {
1492 /* zero tolerance for short writes */
1493 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1494 return tevent_req_post(req, ev);
1498 vfs_cc_state->copied += this_num;
1501 tevent_req_done(req);
1502 return tevent_req_post(req, ev);
1505 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1506 struct tevent_req *req,
1509 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1510 struct vfs_cc_state);
1513 if (tevent_req_is_nterror(req, &status)) {
1514 DEBUG(2, ("server side copy chunk failed: %s\n",
1515 nt_errstr(status)));
1517 tevent_req_received(req);
1521 *copied = vfs_cc_state->copied;
1522 DEBUG(10, ("server side copy chunk copied %lu\n",
1523 (unsigned long)*copied));
1524 tevent_req_received(req);
1526 return NT_STATUS_OK;
1529 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1530 TALLOC_CTX *mem_ctx,
1531 struct files_struct *fsp,
1532 struct smb_filename *smb_fname,
1533 uint16_t *_compression_fmt)
1535 return NT_STATUS_INVALID_DEVICE_REQUEST;
1538 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1539 TALLOC_CTX *mem_ctx,
1540 struct files_struct *fsp,
1541 uint16_t compression_fmt)
1543 return NT_STATUS_INVALID_DEVICE_REQUEST;
1546 /********************************************************************
1547 Given a stat buffer return the allocated size on disk, taking into
1548 account sparse files.
1549 ********************************************************************/
1550 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1551 struct files_struct *fsp,
1552 const SMB_STRUCT_STAT *sbuf)
1556 START_PROFILE(syscall_get_alloc_size);
1558 if(S_ISDIR(sbuf->st_ex_mode)) {
1563 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1564 /* The type of st_blocksize is blkcnt_t which *MUST* be
1565 signed (according to POSIX) and can be less than 64-bits.
1566 Ensure when we're converting to 64 bits wide we don't
1568 #if defined(SIZEOF_BLKCNT_T_8)
1569 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1570 #elif defined(SIZEOF_BLKCNT_T_4)
1572 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1573 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1576 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1580 * Some file systems do not allocate a block for very
1581 * small files. But for non-empty file should report a
1585 uint64_t filesize = get_file_size_stat(sbuf);
1587 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1591 result = get_file_size_stat(sbuf);
1594 if (fsp && fsp->initial_allocation_size)
1595 result = MAX(result,fsp->initial_allocation_size);
1597 result = smb_roundup(handle->conn, result);
1600 END_PROFILE(syscall_get_alloc_size);
1604 static int vfswrap_unlink(vfs_handle_struct *handle,
1605 const struct smb_filename *smb_fname)
1609 START_PROFILE(syscall_unlink);
1611 if (smb_fname->stream_name) {
1615 result = unlink(smb_fname->base_name);
1618 END_PROFILE(syscall_unlink);
1622 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1626 START_PROFILE(syscall_chmod);
1629 * We need to do this due to the fact that the default POSIX ACL
1630 * chmod modifies the ACL *mask* for the group owner, not the
1631 * group owner bits directly. JRA.
1636 int saved_errno = errno; /* We might get ENOSYS */
1637 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1638 END_PROFILE(syscall_chmod);
1641 /* Error - return the old errno. */
1642 errno = saved_errno;
1645 result = chmod(path, mode);
1646 END_PROFILE(syscall_chmod);
1650 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1654 START_PROFILE(syscall_fchmod);
1657 * We need to do this due to the fact that the default POSIX ACL
1658 * chmod modifies the ACL *mask* for the group owner, not the
1659 * group owner bits directly. JRA.
1663 int saved_errno = errno; /* We might get ENOSYS */
1664 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1665 END_PROFILE(syscall_fchmod);
1668 /* Error - return the old errno. */
1669 errno = saved_errno;
1672 #if defined(HAVE_FCHMOD)
1673 result = fchmod(fsp->fh->fd, mode);
1679 END_PROFILE(syscall_fchmod);
1683 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1687 START_PROFILE(syscall_chown);
1688 result = chown(path, uid, gid);
1689 END_PROFILE(syscall_chown);
1693 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1698 START_PROFILE(syscall_fchown);
1699 result = fchown(fsp->fh->fd, uid, gid);
1700 END_PROFILE(syscall_fchown);
1708 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1712 START_PROFILE(syscall_lchown);
1713 result = lchown(path, uid, gid);
1714 END_PROFILE(syscall_lchown);
1718 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1722 START_PROFILE(syscall_chdir);
1723 result = chdir(path);
1724 END_PROFILE(syscall_chdir);
1728 static char *vfswrap_getwd(vfs_handle_struct *handle)
1732 START_PROFILE(syscall_getwd);
1733 result = sys_getwd();
1734 END_PROFILE(syscall_getwd);
1738 /*********************************************************************
1739 nsec timestamp resolution call. Convert down to whatever the underlying
1740 system will support.
1741 **********************************************************************/
1743 static int vfswrap_ntimes(vfs_handle_struct *handle,
1744 const struct smb_filename *smb_fname,
1745 struct smb_file_time *ft)
1749 START_PROFILE(syscall_ntimes);
1751 if (smb_fname->stream_name) {
1757 if (null_timespec(ft->atime)) {
1758 ft->atime= smb_fname->st.st_ex_atime;
1761 if (null_timespec(ft->mtime)) {
1762 ft->mtime = smb_fname->st.st_ex_mtime;
1765 if (!null_timespec(ft->create_time)) {
1766 set_create_timespec_ea(handle->conn,
1771 if ((timespec_compare(&ft->atime,
1772 &smb_fname->st.st_ex_atime) == 0) &&
1773 (timespec_compare(&ft->mtime,
1774 &smb_fname->st.st_ex_mtime) == 0)) {
1779 #if defined(HAVE_UTIMENSAT)
1781 struct timespec ts[2];
1784 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1786 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1788 if (!((result == -1) && (errno == ENOSYS))) {
1792 #if defined(HAVE_UTIMES)
1794 struct timeval tv[2];
1795 tv[0] = convert_timespec_to_timeval(ft->atime);
1796 tv[1] = convert_timespec_to_timeval(ft->mtime);
1797 result = utimes(smb_fname->base_name, tv);
1799 result = utimes(smb_fname->base_name, NULL);
1801 if (!((result == -1) && (errno == ENOSYS))) {
1805 #if defined(HAVE_UTIME)
1807 struct utimbuf times;
1808 times.actime = convert_timespec_to_time_t(ft->atime);
1809 times.modtime = convert_timespec_to_time_t(ft->mtime);
1810 result = utime(smb_fname->base_name, ×);
1812 result = utime(smb_fname->base_name, NULL);
1814 if (!((result == -1) && (errno == ENOSYS))) {
1822 END_PROFILE(syscall_ntimes);
1826 /*********************************************************************
1827 A version of ftruncate that will write the space on disk if strict
1829 **********************************************************************/
1831 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1833 off_t space_to_write;
1834 uint64_t space_avail;
1835 uint64_t bsize,dfree,dsize;
1838 SMB_STRUCT_STAT *pst;
1840 status = vfs_stat_fsp(fsp);
1841 if (!NT_STATUS_IS_OK(status)) {
1844 pst = &fsp->fsp_name->st;
1847 if (S_ISFIFO(pst->st_ex_mode))
1851 if (pst->st_ex_size == len)
1854 /* Shrink - just ftruncate. */
1855 if (pst->st_ex_size > len)
1856 return ftruncate(fsp->fh->fd, len);
1858 space_to_write = len - pst->st_ex_size;
1860 /* for allocation try fallocate first. This can fail on some
1861 platforms e.g. when the filesystem doesn't support it and no
1862 emulation is being done by the libc (like on AIX with JFS1). In that
1863 case we do our own emulation. fallocate implementations can
1864 return ENOTSUP or EINVAL in cases like that. */
1865 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1866 pst->st_ex_size, space_to_write);
1867 if (ret == -1 && errno == ENOSPC) {
1873 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1874 "error %d. Falling back to slow manual allocation\n", errno));
1876 /* available disk space is enough or not? */
1877 space_avail = get_dfree_info(fsp->conn,
1878 fsp->fsp_name->base_name, false,
1879 &bsize,&dfree,&dsize);
1880 /* space_avail is 1k blocks */
1881 if (space_avail == (uint64_t)-1 ||
1882 ((uint64_t)space_to_write/1024 > space_avail) ) {
1887 /* Write out the real space on disk. */
1888 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1896 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1899 SMB_STRUCT_STAT *pst;
1903 START_PROFILE(syscall_ftruncate);
1905 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1906 result = strict_allocate_ftruncate(handle, fsp, len);
1907 END_PROFILE(syscall_ftruncate);
1911 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1912 ftruncate if the system supports it. Then I discovered that
1913 you can have some filesystems that support ftruncate
1914 expansion and some that don't! On Linux fat can't do
1915 ftruncate extend but ext2 can. */
1917 result = ftruncate(fsp->fh->fd, len);
1921 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1922 extend a file with ftruncate. Provide alternate implementation
1925 /* Do an fstat to see if the file is longer than the requested
1926 size in which case the ftruncate above should have
1927 succeeded or shorter, in which case seek to len - 1 and
1928 write 1 byte of zero */
1929 status = vfs_stat_fsp(fsp);
1930 if (!NT_STATUS_IS_OK(status)) {
1933 pst = &fsp->fsp_name->st;
1936 if (S_ISFIFO(pst->st_ex_mode)) {
1942 if (pst->st_ex_size == len) {
1947 if (pst->st_ex_size > len) {
1948 /* the ftruncate should have worked */
1952 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1960 END_PROFILE(syscall_ftruncate);
1964 static int vfswrap_fallocate(vfs_handle_struct *handle,
1966 enum vfs_fallocate_mode mode,
1972 START_PROFILE(syscall_fallocate);
1973 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1974 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1976 * posix_fallocate returns 0 on success, errno on error
1977 * and doesn't set errno. Make it behave like fallocate()
1978 * which returns -1, and sets errno on failure.
1984 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1985 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1990 END_PROFILE(syscall_fallocate);
1994 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1998 START_PROFILE(syscall_fcntl_lock);
1999 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2000 END_PROFILE(syscall_fcntl_lock);
2004 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2005 uint32 share_mode, uint32 access_mask)
2007 START_PROFILE(syscall_kernel_flock);
2008 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2009 END_PROFILE(syscall_kernel_flock);
2013 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2017 START_PROFILE(syscall_fcntl_getlock);
2018 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2019 END_PROFILE(syscall_fcntl_getlock);
2023 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2028 START_PROFILE(syscall_linux_setlease);
2030 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2031 result = linux_setlease(fsp->fh->fd, leasetype);
2035 END_PROFILE(syscall_linux_setlease);
2039 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2043 START_PROFILE(syscall_symlink);
2044 result = symlink(oldpath, newpath);
2045 END_PROFILE(syscall_symlink);
2049 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2053 START_PROFILE(syscall_readlink);
2054 result = readlink(path, buf, bufsiz);
2055 END_PROFILE(syscall_readlink);
2059 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2063 START_PROFILE(syscall_link);
2064 result = link(oldpath, newpath);
2065 END_PROFILE(syscall_link);
2069 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2073 START_PROFILE(syscall_mknod);
2074 result = sys_mknod(pathname, mode, dev);
2075 END_PROFILE(syscall_mknod);
2079 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2083 START_PROFILE(syscall_realpath);
2084 #ifdef REALPATH_TAKES_NULL
2085 result = realpath(path, NULL);
2087 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2089 char *resolved_path = realpath(path, result);
2090 if (!resolved_path) {
2093 /* SMB_ASSERT(result == resolved_path) ? */
2094 result = resolved_path;
2098 END_PROFILE(syscall_realpath);
2102 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2103 struct sys_notify_context *ctx,
2106 uint32_t *subdir_filter,
2107 void (*callback)(struct sys_notify_context *ctx,
2109 struct notify_event *ev),
2110 void *private_data, void *handle)
2113 * So far inotify is the only supported default notify mechanism. If
2114 * another platform like the the BSD's or a proprietary Unix comes
2115 * along and wants another default, we can play the same trick we
2116 * played with Posix ACLs.
2118 * Until that is the case, hard-code inotify here.
2121 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2123 if (!lp_parm_bool(-1, "notify", "inotify", True)) {
2124 return NT_STATUS_INVALID_SYSTEM_SERVICE;
2126 ret = inotify_watch(ctx, path, filter, subdir_filter,
2127 callback, private_data, handle);
2129 return map_nt_error_from_unix(ret);
2131 return NT_STATUS_OK;
2135 * Do nothing, leave everything to notify_internal.c
2137 return NT_STATUS_OK;
2140 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2144 return chflags(path, flags);
2151 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2152 const SMB_STRUCT_STAT *sbuf)
2156 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2160 key.devid = sbuf->st_ex_dev;
2161 key.inode = sbuf->st_ex_ino;
2162 /* key.extid is unused by default. */
2167 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2168 struct files_struct *fsp,
2170 TALLOC_CTX *mem_ctx,
2171 unsigned int *pnum_streams,
2172 struct stream_struct **pstreams)
2174 SMB_STRUCT_STAT sbuf;
2175 struct stream_struct *tmp_streams = NULL;
2178 if ((fsp != NULL) && (fsp->is_directory)) {
2180 * No default streams on directories
2185 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2186 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2189 struct smb_filename smb_fname;
2191 ZERO_STRUCT(smb_fname);
2192 smb_fname.base_name = discard_const_p(char, fname);
2194 if (lp_posix_pathnames()) {
2195 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2197 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2199 sbuf = smb_fname.st;
2203 return map_nt_error_from_unix(errno);
2206 if (S_ISDIR(sbuf.st_ex_mode)) {
2210 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2211 (*pnum_streams) + 1);
2212 if (tmp_streams == NULL) {
2213 return NT_STATUS_NO_MEMORY;
2215 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2216 if (tmp_streams[*pnum_streams].name == NULL) {
2217 return NT_STATUS_NO_MEMORY;
2219 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2220 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2223 *pstreams = tmp_streams;
2225 return NT_STATUS_OK;
2228 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2231 TALLOC_CTX *mem_ctx,
2235 * Don't fall back to get_real_filename so callers can differentiate
2236 * between a full directory scan and an actual case-insensitive stat.
2242 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2245 return handle->conn->connectpath;
2248 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2249 struct byte_range_lock *br_lck,
2250 struct lock_struct *plock,
2253 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2255 /* Note: blr is not used in the default implementation. */
2256 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2259 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2260 struct messaging_context *msg_ctx,
2261 struct byte_range_lock *br_lck,
2262 const struct lock_struct *plock)
2264 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2266 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2269 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2270 struct byte_range_lock *br_lck,
2271 struct lock_struct *plock)
2273 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2275 /* Note: blr is not used in the default implementation. */
2276 return brl_lock_cancel_default(br_lck, plock);
2279 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2281 struct lock_struct *plock)
2283 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2284 plock->lock_type == WRITE_LOCK);
2286 return strict_lock_default(fsp, plock);
2289 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2291 struct lock_struct *plock)
2293 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2294 plock->lock_type == WRITE_LOCK);
2296 strict_unlock_default(fsp, plock);
2299 /* NT ACL operations. */
2301 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2303 uint32 security_info,
2304 TALLOC_CTX *mem_ctx,
2305 struct security_descriptor **ppdesc)
2309 START_PROFILE(fget_nt_acl);
2310 result = posix_fget_nt_acl(fsp, security_info,
2312 END_PROFILE(fget_nt_acl);
2316 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2318 uint32 security_info,
2319 TALLOC_CTX *mem_ctx,
2320 struct security_descriptor **ppdesc)
2324 START_PROFILE(get_nt_acl);
2325 result = posix_get_nt_acl(handle->conn, name, security_info,
2327 END_PROFILE(get_nt_acl);
2331 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2335 START_PROFILE(fset_nt_acl);
2336 result = set_nt_acl(fsp, security_info_sent, psd);
2337 END_PROFILE(fset_nt_acl);
2341 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2342 struct smb_filename *file,
2343 struct security_acl *sacl,
2344 uint32_t access_requested,
2345 uint32_t access_denied)
2347 return NT_STATUS_OK; /* Nothing to do here ... */
2350 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2358 START_PROFILE(chmod_acl);
2359 result = chmod_acl(handle->conn, name, mode);
2360 END_PROFILE(chmod_acl);
2365 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2373 START_PROFILE(fchmod_acl);
2374 result = fchmod_acl(fsp, mode);
2375 END_PROFILE(fchmod_acl);
2380 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2382 SMB_ACL_TYPE_T type,
2383 TALLOC_CTX *mem_ctx)
2385 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2388 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2390 TALLOC_CTX *mem_ctx)
2392 return sys_acl_get_fd(handle, fsp, mem_ctx);
2395 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2397 return sys_acl_set_file(handle, name, acltype, theacl);
2400 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2402 return sys_acl_set_fd(handle, fsp, theacl);
2405 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2407 return sys_acl_delete_def_file(handle, path);
2410 /****************************************************************
2411 Extended attribute operations.
2412 *****************************************************************/
2414 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2416 return getxattr(path, name, value, size);
2419 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2421 return fgetxattr(fsp->fh->fd, name, value, size);
2424 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2426 return listxattr(path, list, size);
2429 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2431 return flistxattr(fsp->fh->fd, list, size);
2434 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2436 return removexattr(path, name);
2439 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2441 return fremovexattr(fsp->fh->fd, name);
2444 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2446 return setxattr(path, name, value, size, flags);
2449 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2451 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2454 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2459 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2460 const struct smb_filename *fname,
2461 SMB_STRUCT_STAT *sbuf)
2465 bool offline = false;
2467 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2471 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2472 #if defined(ENOTSUP)
2478 status = get_full_smb_filename(talloc_tos(), fname, &path);
2479 if (!NT_STATUS_IS_OK(status)) {
2480 errno = map_errno_from_nt_status(status);
2484 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2491 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2492 const struct smb_filename *fname)
2494 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2495 #if defined(ENOTSUP)
2501 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2502 struct files_struct *fsp,
2503 TALLOC_CTX *mem_ctx,
2506 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2509 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2510 struct files_struct *fsp,
2511 const DATA_BLOB old_cookie,
2512 TALLOC_CTX *mem_ctx,
2513 DATA_BLOB *new_cookie)
2515 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2519 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2520 struct smb_request *smb1req,
2521 struct smbXsrv_open *op,
2522 const DATA_BLOB old_cookie,
2523 TALLOC_CTX *mem_ctx,
2524 struct files_struct **fsp,
2525 DATA_BLOB *new_cookie)
2527 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2528 old_cookie, mem_ctx,
2532 static struct vfs_fn_pointers vfs_default_fns = {
2533 /* Disk operations */
2535 .connect_fn = vfswrap_connect,
2536 .disconnect_fn = vfswrap_disconnect,
2537 .disk_free_fn = vfswrap_disk_free,
2538 .get_quota_fn = vfswrap_get_quota,
2539 .set_quota_fn = vfswrap_set_quota,
2540 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2541 .statvfs_fn = vfswrap_statvfs,
2542 .fs_capabilities_fn = vfswrap_fs_capabilities,
2543 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2545 /* Directory operations */
2547 .opendir_fn = vfswrap_opendir,
2548 .fdopendir_fn = vfswrap_fdopendir,
2549 .readdir_fn = vfswrap_readdir,
2550 .readdir_attr_fn = vfswrap_readdir_attr,
2551 .seekdir_fn = vfswrap_seekdir,
2552 .telldir_fn = vfswrap_telldir,
2553 .rewind_dir_fn = vfswrap_rewinddir,
2554 .mkdir_fn = vfswrap_mkdir,
2555 .rmdir_fn = vfswrap_rmdir,
2556 .closedir_fn = vfswrap_closedir,
2557 .init_search_op_fn = vfswrap_init_search_op,
2559 /* File operations */
2561 .open_fn = vfswrap_open,
2562 .create_file_fn = vfswrap_create_file,
2563 .close_fn = vfswrap_close,
2564 .read_fn = vfswrap_read,
2565 .pread_fn = vfswrap_pread,
2566 .pread_send_fn = vfswrap_pread_send,
2567 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2568 .write_fn = vfswrap_write,
2569 .pwrite_fn = vfswrap_pwrite,
2570 .pwrite_send_fn = vfswrap_pwrite_send,
2571 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2572 .lseek_fn = vfswrap_lseek,
2573 .sendfile_fn = vfswrap_sendfile,
2574 .recvfile_fn = vfswrap_recvfile,
2575 .rename_fn = vfswrap_rename,
2576 .fsync_fn = vfswrap_fsync,
2577 .fsync_send_fn = vfswrap_fsync_send,
2578 .fsync_recv_fn = vfswrap_asys_int_recv,
2579 .stat_fn = vfswrap_stat,
2580 .fstat_fn = vfswrap_fstat,
2581 .lstat_fn = vfswrap_lstat,
2582 .get_alloc_size_fn = vfswrap_get_alloc_size,
2583 .unlink_fn = vfswrap_unlink,
2584 .chmod_fn = vfswrap_chmod,
2585 .fchmod_fn = vfswrap_fchmod,
2586 .chown_fn = vfswrap_chown,
2587 .fchown_fn = vfswrap_fchown,
2588 .lchown_fn = vfswrap_lchown,
2589 .chdir_fn = vfswrap_chdir,
2590 .getwd_fn = vfswrap_getwd,
2591 .ntimes_fn = vfswrap_ntimes,
2592 .ftruncate_fn = vfswrap_ftruncate,
2593 .fallocate_fn = vfswrap_fallocate,
2594 .lock_fn = vfswrap_lock,
2595 .kernel_flock_fn = vfswrap_kernel_flock,
2596 .linux_setlease_fn = vfswrap_linux_setlease,
2597 .getlock_fn = vfswrap_getlock,
2598 .symlink_fn = vfswrap_symlink,
2599 .readlink_fn = vfswrap_readlink,
2600 .link_fn = vfswrap_link,
2601 .mknod_fn = vfswrap_mknod,
2602 .realpath_fn = vfswrap_realpath,
2603 .notify_watch_fn = vfswrap_notify_watch,
2604 .chflags_fn = vfswrap_chflags,
2605 .file_id_create_fn = vfswrap_file_id_create,
2606 .streaminfo_fn = vfswrap_streaminfo,
2607 .get_real_filename_fn = vfswrap_get_real_filename,
2608 .connectpath_fn = vfswrap_connectpath,
2609 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2610 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2611 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2612 .strict_lock_fn = vfswrap_strict_lock,
2613 .strict_unlock_fn = vfswrap_strict_unlock,
2614 .translate_name_fn = vfswrap_translate_name,
2615 .fsctl_fn = vfswrap_fsctl,
2616 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2617 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2618 .get_compression_fn = vfswrap_get_compression,
2619 .set_compression_fn = vfswrap_set_compression,
2621 /* NT ACL operations. */
2623 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2624 .get_nt_acl_fn = vfswrap_get_nt_acl,
2625 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2626 .audit_file_fn = vfswrap_audit_file,
2628 /* POSIX ACL operations. */
2630 .chmod_acl_fn = vfswrap_chmod_acl,
2631 .fchmod_acl_fn = vfswrap_fchmod_acl,
2633 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2634 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2635 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2636 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2637 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2638 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2639 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2641 /* EA operations. */
2642 .getxattr_fn = vfswrap_getxattr,
2643 .fgetxattr_fn = vfswrap_fgetxattr,
2644 .listxattr_fn = vfswrap_listxattr,
2645 .flistxattr_fn = vfswrap_flistxattr,
2646 .removexattr_fn = vfswrap_removexattr,
2647 .fremovexattr_fn = vfswrap_fremovexattr,
2648 .setxattr_fn = vfswrap_setxattr,
2649 .fsetxattr_fn = vfswrap_fsetxattr,
2651 /* aio operations */
2652 .aio_force_fn = vfswrap_aio_force,
2654 /* offline operations */
2655 .is_offline_fn = vfswrap_is_offline,
2656 .set_offline_fn = vfswrap_set_offline,
2658 /* durable handle operations */
2659 .durable_cookie_fn = vfswrap_durable_cookie,
2660 .durable_disconnect_fn = vfswrap_durable_disconnect,
2661 .durable_reconnect_fn = vfswrap_durable_reconnect,
2664 NTSTATUS vfs_default_init(void);
2665 NTSTATUS vfs_default_init(void)
2667 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2668 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);