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 == ENOSPC) {
1874 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1875 "error %d. Falling back to slow manual allocation\n", ret));
1877 /* available disk space is enough or not? */
1878 space_avail = get_dfree_info(fsp->conn,
1879 fsp->fsp_name->base_name, false,
1880 &bsize,&dfree,&dsize);
1881 /* space_avail is 1k blocks */
1882 if (space_avail == (uint64_t)-1 ||
1883 ((uint64_t)space_to_write/1024 > space_avail) ) {
1888 /* Write out the real space on disk. */
1889 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1898 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1901 SMB_STRUCT_STAT *pst;
1905 START_PROFILE(syscall_ftruncate);
1907 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1908 result = strict_allocate_ftruncate(handle, fsp, len);
1909 END_PROFILE(syscall_ftruncate);
1913 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1914 ftruncate if the system supports it. Then I discovered that
1915 you can have some filesystems that support ftruncate
1916 expansion and some that don't! On Linux fat can't do
1917 ftruncate extend but ext2 can. */
1919 result = ftruncate(fsp->fh->fd, len);
1923 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1924 extend a file with ftruncate. Provide alternate implementation
1927 /* Do an fstat to see if the file is longer than the requested
1928 size in which case the ftruncate above should have
1929 succeeded or shorter, in which case seek to len - 1 and
1930 write 1 byte of zero */
1931 status = vfs_stat_fsp(fsp);
1932 if (!NT_STATUS_IS_OK(status)) {
1935 pst = &fsp->fsp_name->st;
1938 if (S_ISFIFO(pst->st_ex_mode)) {
1944 if (pst->st_ex_size == len) {
1949 if (pst->st_ex_size > len) {
1950 /* the ftruncate should have worked */
1954 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1962 END_PROFILE(syscall_ftruncate);
1966 static int vfswrap_fallocate(vfs_handle_struct *handle,
1968 enum vfs_fallocate_mode mode,
1974 START_PROFILE(syscall_fallocate);
1975 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1976 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1977 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1978 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1983 END_PROFILE(syscall_fallocate);
1987 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1991 START_PROFILE(syscall_fcntl_lock);
1992 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1993 END_PROFILE(syscall_fcntl_lock);
1997 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1998 uint32 share_mode, uint32 access_mask)
2000 START_PROFILE(syscall_kernel_flock);
2001 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2002 END_PROFILE(syscall_kernel_flock);
2006 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2010 START_PROFILE(syscall_fcntl_getlock);
2011 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2012 END_PROFILE(syscall_fcntl_getlock);
2016 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2021 START_PROFILE(syscall_linux_setlease);
2023 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2024 result = linux_setlease(fsp->fh->fd, leasetype);
2028 END_PROFILE(syscall_linux_setlease);
2032 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2036 START_PROFILE(syscall_symlink);
2037 result = symlink(oldpath, newpath);
2038 END_PROFILE(syscall_symlink);
2042 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2046 START_PROFILE(syscall_readlink);
2047 result = readlink(path, buf, bufsiz);
2048 END_PROFILE(syscall_readlink);
2052 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2056 START_PROFILE(syscall_link);
2057 result = link(oldpath, newpath);
2058 END_PROFILE(syscall_link);
2062 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2066 START_PROFILE(syscall_mknod);
2067 result = sys_mknod(pathname, mode, dev);
2068 END_PROFILE(syscall_mknod);
2072 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2076 START_PROFILE(syscall_realpath);
2077 #ifdef REALPATH_TAKES_NULL
2078 result = realpath(path, NULL);
2080 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
2082 char *resolved_path = realpath(path, result);
2083 if (!resolved_path) {
2086 /* SMB_ASSERT(result == resolved_path) ? */
2087 result = resolved_path;
2091 END_PROFILE(syscall_realpath);
2095 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
2096 struct sys_notify_context *ctx,
2099 uint32_t *subdir_filter,
2100 void (*callback)(struct sys_notify_context *ctx,
2102 struct notify_event *ev),
2103 void *private_data, void *handle)
2106 * So far inotify is the only supported default notify mechanism. If
2107 * another platform like the the BSD's or a proprietary Unix comes
2108 * along and wants another default, we can play the same trick we
2109 * played with Posix ACLs.
2111 * Until that is the case, hard-code inotify here.
2114 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
2115 return inotify_watch(ctx, path, filter, subdir_filter,
2116 callback, private_data, handle);
2120 * Do nothing, leave everything to notify_internal.c
2122 return NT_STATUS_OK;
2125 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2129 return chflags(path, flags);
2136 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2137 const SMB_STRUCT_STAT *sbuf)
2141 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2145 key.devid = sbuf->st_ex_dev;
2146 key.inode = sbuf->st_ex_ino;
2147 /* key.extid is unused by default. */
2152 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2153 struct files_struct *fsp,
2155 TALLOC_CTX *mem_ctx,
2156 unsigned int *pnum_streams,
2157 struct stream_struct **pstreams)
2159 SMB_STRUCT_STAT sbuf;
2160 struct stream_struct *tmp_streams = NULL;
2163 if ((fsp != NULL) && (fsp->is_directory)) {
2165 * No default streams on directories
2170 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2171 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2174 struct smb_filename smb_fname;
2176 ZERO_STRUCT(smb_fname);
2177 smb_fname.base_name = discard_const_p(char, fname);
2179 if (lp_posix_pathnames()) {
2180 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2182 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2184 sbuf = smb_fname.st;
2188 return map_nt_error_from_unix(errno);
2191 if (S_ISDIR(sbuf.st_ex_mode)) {
2195 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2196 (*pnum_streams) + 1);
2197 if (tmp_streams == NULL) {
2198 return NT_STATUS_NO_MEMORY;
2200 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2201 if (tmp_streams[*pnum_streams].name == NULL) {
2202 return NT_STATUS_NO_MEMORY;
2204 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2205 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2208 *pstreams = tmp_streams;
2210 return NT_STATUS_OK;
2213 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2216 TALLOC_CTX *mem_ctx,
2220 * Don't fall back to get_real_filename so callers can differentiate
2221 * between a full directory scan and an actual case-insensitive stat.
2227 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2230 return handle->conn->connectpath;
2233 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2234 struct byte_range_lock *br_lck,
2235 struct lock_struct *plock,
2238 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2240 /* Note: blr is not used in the default implementation. */
2241 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2244 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2245 struct messaging_context *msg_ctx,
2246 struct byte_range_lock *br_lck,
2247 const struct lock_struct *plock)
2249 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2251 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2254 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2255 struct byte_range_lock *br_lck,
2256 struct lock_struct *plock)
2258 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2260 /* Note: blr is not used in the default implementation. */
2261 return brl_lock_cancel_default(br_lck, plock);
2264 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2266 struct lock_struct *plock)
2268 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2269 plock->lock_type == WRITE_LOCK);
2271 return strict_lock_default(fsp, plock);
2274 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2276 struct lock_struct *plock)
2278 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2279 plock->lock_type == WRITE_LOCK);
2281 strict_unlock_default(fsp, plock);
2284 /* NT ACL operations. */
2286 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2288 uint32 security_info,
2289 TALLOC_CTX *mem_ctx,
2290 struct security_descriptor **ppdesc)
2294 START_PROFILE(fget_nt_acl);
2295 result = posix_fget_nt_acl(fsp, security_info,
2297 END_PROFILE(fget_nt_acl);
2301 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2303 uint32 security_info,
2304 TALLOC_CTX *mem_ctx,
2305 struct security_descriptor **ppdesc)
2309 START_PROFILE(get_nt_acl);
2310 result = posix_get_nt_acl(handle->conn, name, security_info,
2312 END_PROFILE(get_nt_acl);
2316 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2320 START_PROFILE(fset_nt_acl);
2321 result = set_nt_acl(fsp, security_info_sent, psd);
2322 END_PROFILE(fset_nt_acl);
2326 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2327 struct smb_filename *file,
2328 struct security_acl *sacl,
2329 uint32_t access_requested,
2330 uint32_t access_denied)
2332 return NT_STATUS_OK; /* Nothing to do here ... */
2335 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2343 START_PROFILE(chmod_acl);
2344 result = chmod_acl(handle->conn, name, mode);
2345 END_PROFILE(chmod_acl);
2350 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2358 START_PROFILE(fchmod_acl);
2359 result = fchmod_acl(fsp, mode);
2360 END_PROFILE(fchmod_acl);
2365 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2367 SMB_ACL_TYPE_T type,
2368 TALLOC_CTX *mem_ctx)
2370 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2373 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2375 TALLOC_CTX *mem_ctx)
2377 return sys_acl_get_fd(handle, fsp, mem_ctx);
2380 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2382 return sys_acl_set_file(handle, name, acltype, theacl);
2385 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2387 return sys_acl_set_fd(handle, fsp, theacl);
2390 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2392 return sys_acl_delete_def_file(handle, path);
2395 /****************************************************************
2396 Extended attribute operations.
2397 *****************************************************************/
2399 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2401 return getxattr(path, name, value, size);
2404 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2406 return fgetxattr(fsp->fh->fd, name, value, size);
2409 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2411 return listxattr(path, list, size);
2414 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2416 return flistxattr(fsp->fh->fd, list, size);
2419 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2421 return removexattr(path, name);
2424 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2426 return fremovexattr(fsp->fh->fd, name);
2429 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2431 return setxattr(path, name, value, size, flags);
2434 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2436 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2439 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2444 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2445 const struct smb_filename *fname,
2446 SMB_STRUCT_STAT *sbuf)
2450 bool offline = false;
2452 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2456 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2457 #if defined(ENOTSUP)
2463 status = get_full_smb_filename(talloc_tos(), fname, &path);
2464 if (!NT_STATUS_IS_OK(status)) {
2465 errno = map_errno_from_nt_status(status);
2469 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2476 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2477 const struct smb_filename *fname)
2479 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2480 #if defined(ENOTSUP)
2486 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2487 struct files_struct *fsp,
2488 TALLOC_CTX *mem_ctx,
2491 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2494 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2495 struct files_struct *fsp,
2496 const DATA_BLOB old_cookie,
2497 TALLOC_CTX *mem_ctx,
2498 DATA_BLOB *new_cookie)
2500 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2504 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2505 struct smb_request *smb1req,
2506 struct smbXsrv_open *op,
2507 const DATA_BLOB old_cookie,
2508 TALLOC_CTX *mem_ctx,
2509 struct files_struct **fsp,
2510 DATA_BLOB *new_cookie)
2512 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2513 old_cookie, mem_ctx,
2517 static struct vfs_fn_pointers vfs_default_fns = {
2518 /* Disk operations */
2520 .connect_fn = vfswrap_connect,
2521 .disconnect_fn = vfswrap_disconnect,
2522 .disk_free_fn = vfswrap_disk_free,
2523 .get_quota_fn = vfswrap_get_quota,
2524 .set_quota_fn = vfswrap_set_quota,
2525 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2526 .statvfs_fn = vfswrap_statvfs,
2527 .fs_capabilities_fn = vfswrap_fs_capabilities,
2528 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2530 /* Directory operations */
2532 .opendir_fn = vfswrap_opendir,
2533 .fdopendir_fn = vfswrap_fdopendir,
2534 .readdir_fn = vfswrap_readdir,
2535 .readdir_attr_fn = vfswrap_readdir_attr,
2536 .seekdir_fn = vfswrap_seekdir,
2537 .telldir_fn = vfswrap_telldir,
2538 .rewind_dir_fn = vfswrap_rewinddir,
2539 .mkdir_fn = vfswrap_mkdir,
2540 .rmdir_fn = vfswrap_rmdir,
2541 .closedir_fn = vfswrap_closedir,
2542 .init_search_op_fn = vfswrap_init_search_op,
2544 /* File operations */
2546 .open_fn = vfswrap_open,
2547 .create_file_fn = vfswrap_create_file,
2548 .close_fn = vfswrap_close,
2549 .read_fn = vfswrap_read,
2550 .pread_fn = vfswrap_pread,
2551 .pread_send_fn = vfswrap_pread_send,
2552 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2553 .write_fn = vfswrap_write,
2554 .pwrite_fn = vfswrap_pwrite,
2555 .pwrite_send_fn = vfswrap_pwrite_send,
2556 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2557 .lseek_fn = vfswrap_lseek,
2558 .sendfile_fn = vfswrap_sendfile,
2559 .recvfile_fn = vfswrap_recvfile,
2560 .rename_fn = vfswrap_rename,
2561 .fsync_fn = vfswrap_fsync,
2562 .fsync_send_fn = vfswrap_fsync_send,
2563 .fsync_recv_fn = vfswrap_asys_int_recv,
2564 .stat_fn = vfswrap_stat,
2565 .fstat_fn = vfswrap_fstat,
2566 .lstat_fn = vfswrap_lstat,
2567 .get_alloc_size_fn = vfswrap_get_alloc_size,
2568 .unlink_fn = vfswrap_unlink,
2569 .chmod_fn = vfswrap_chmod,
2570 .fchmod_fn = vfswrap_fchmod,
2571 .chown_fn = vfswrap_chown,
2572 .fchown_fn = vfswrap_fchown,
2573 .lchown_fn = vfswrap_lchown,
2574 .chdir_fn = vfswrap_chdir,
2575 .getwd_fn = vfswrap_getwd,
2576 .ntimes_fn = vfswrap_ntimes,
2577 .ftruncate_fn = vfswrap_ftruncate,
2578 .fallocate_fn = vfswrap_fallocate,
2579 .lock_fn = vfswrap_lock,
2580 .kernel_flock_fn = vfswrap_kernel_flock,
2581 .linux_setlease_fn = vfswrap_linux_setlease,
2582 .getlock_fn = vfswrap_getlock,
2583 .symlink_fn = vfswrap_symlink,
2584 .readlink_fn = vfswrap_readlink,
2585 .link_fn = vfswrap_link,
2586 .mknod_fn = vfswrap_mknod,
2587 .realpath_fn = vfswrap_realpath,
2588 .notify_watch_fn = vfswrap_notify_watch,
2589 .chflags_fn = vfswrap_chflags,
2590 .file_id_create_fn = vfswrap_file_id_create,
2591 .streaminfo_fn = vfswrap_streaminfo,
2592 .get_real_filename_fn = vfswrap_get_real_filename,
2593 .connectpath_fn = vfswrap_connectpath,
2594 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2595 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2596 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2597 .strict_lock_fn = vfswrap_strict_lock,
2598 .strict_unlock_fn = vfswrap_strict_unlock,
2599 .translate_name_fn = vfswrap_translate_name,
2600 .fsctl_fn = vfswrap_fsctl,
2601 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2602 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2603 .get_compression_fn = vfswrap_get_compression,
2604 .set_compression_fn = vfswrap_set_compression,
2606 /* NT ACL operations. */
2608 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2609 .get_nt_acl_fn = vfswrap_get_nt_acl,
2610 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2611 .audit_file_fn = vfswrap_audit_file,
2613 /* POSIX ACL operations. */
2615 .chmod_acl_fn = vfswrap_chmod_acl,
2616 .fchmod_acl_fn = vfswrap_fchmod_acl,
2618 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2619 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2620 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2621 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2622 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2623 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2624 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2626 /* EA operations. */
2627 .getxattr_fn = vfswrap_getxattr,
2628 .fgetxattr_fn = vfswrap_fgetxattr,
2629 .listxattr_fn = vfswrap_listxattr,
2630 .flistxattr_fn = vfswrap_flistxattr,
2631 .removexattr_fn = vfswrap_removexattr,
2632 .fremovexattr_fn = vfswrap_fremovexattr,
2633 .setxattr_fn = vfswrap_setxattr,
2634 .fsetxattr_fn = vfswrap_fsetxattr,
2636 /* aio operations */
2637 .aio_force_fn = vfswrap_aio_force,
2639 /* offline operations */
2640 .is_offline_fn = vfswrap_is_offline,
2641 .set_offline_fn = vfswrap_set_offline,
2643 /* durable handle operations */
2644 .durable_cookie_fn = vfswrap_durable_cookie,
2645 .durable_disconnect_fn = vfswrap_durable_disconnect,
2646 .durable_reconnect_fn = vfswrap_durable_reconnect,
2649 NTSTATUS vfs_default_init(void);
2650 NTSTATUS vfs_default_init(void)
2652 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2653 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);