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/util/sys_rw.h"
38 #define DBGC_CLASS DBGC_VFS
40 /* Check for NULL pointer parameters in vfswrap_* functions */
42 /* We don't want to have NULL function pointers lying around. Someone
43 is sure to try and execute them. These stubs are used to prevent
46 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
48 return 0; /* Return >= 0 for success */
51 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path,
58 uint64_t *bsize, uint64_t *dfree,
61 if (sys_fsusage(path, dfree, dsize) != 0) {
69 static int vfswrap_get_quota(struct vfs_handle_struct *handle, const char *path,
70 enum SMB_QUOTA_TYPE qtype, unid_t id,
73 #ifdef HAVE_SYS_QUOTAS
76 START_PROFILE(syscall_get_quota);
77 result = sys_get_quota(path, qtype, id, qt);
78 END_PROFILE(syscall_get_quota);
86 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
88 #ifdef HAVE_SYS_QUOTAS
91 START_PROFILE(syscall_set_quota);
92 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
93 END_PROFILE(syscall_set_quota);
101 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
102 struct files_struct *fsp,
103 struct shadow_copy_data *shadow_copy_data,
107 return -1; /* Not implemented. */
110 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
112 return sys_statvfs(path, statbuf);
115 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
116 enum timestamp_set_resolution *p_ts_res)
118 connection_struct *conn = handle->conn;
119 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
120 struct smb_filename *smb_fname_cpath = NULL;
121 struct vfs_statvfs_struct statbuf;
124 ZERO_STRUCT(statbuf);
125 ret = sys_statvfs(conn->connectpath, &statbuf);
127 caps = statbuf.FsCapabilities;
130 *p_ts_res = TIMESTAMP_SET_SECONDS;
132 /* Work out what timestamp resolution we can
133 * use when setting a timestamp. */
135 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
137 if (smb_fname_cpath == NULL) {
141 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
143 TALLOC_FREE(smb_fname_cpath);
147 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
148 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
149 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
150 /* If any of the normal UNIX directory timestamps
151 * have a non-zero tv_nsec component assume
152 * we might be able to set sub-second timestamps.
153 * See what filetime set primitives we have.
155 #if defined(HAVE_UTIMENSAT)
156 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
157 #elif defined(HAVE_UTIMES)
158 /* utimes allows msec timestamps to be set. */
159 *p_ts_res = TIMESTAMP_SET_MSEC;
160 #elif defined(HAVE_UTIME)
161 /* utime only allows sec timestamps to be set. */
162 *p_ts_res = TIMESTAMP_SET_SECONDS;
165 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
167 "available on share %s, directory %s\n",
168 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
169 lp_servicename(talloc_tos(), conn->params->service),
170 conn->connectpath ));
172 TALLOC_FREE(smb_fname_cpath);
176 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
177 struct dfs_GetDFSReferral *r)
179 struct junction_map *junction = NULL;
181 bool self_referral = false;
182 char *pathnamep = NULL;
183 char *local_dfs_path = NULL;
186 uint16_t max_referral_level = r->in.req.max_referral_level;
189 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
192 /* get the junction entry */
193 if (r->in.req.servername == NULL) {
194 return NT_STATUS_NOT_FOUND;
198 * Trim pathname sent by client so it begins with only one backslash.
199 * Two backslashes confuse some dfs clients
202 local_dfs_path = talloc_strdup(r, r->in.req.servername);
203 if (local_dfs_path == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 pathnamep = local_dfs_path;
207 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
208 IS_DIRECTORY_SEP(pathnamep[1])) {
212 junction = talloc_zero(r, struct junction_map);
213 if (junction == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 /* The following call can change cwd. */
218 status = get_referred_path(r, pathnamep,
219 !handle->conn->sconn->using_smb2,
220 junction, &consumedcnt, &self_referral);
221 if (!NT_STATUS_IS_OK(status)) {
222 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 vfs_ChDir(handle->conn, handle->conn->connectpath);
227 if (!self_referral) {
228 pathnamep[consumedcnt] = '\0';
231 dbgtext("Path %s to alternate path(s):",
233 for (i=0; i < junction->referral_count; i++) {
235 junction->referral_list[i].alternate_path);
241 if (r->in.req.max_referral_level <= 2) {
242 max_referral_level = 2;
244 if (r->in.req.max_referral_level >= 3) {
245 max_referral_level = 3;
248 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
249 if (r->out.resp == NULL) {
250 return NT_STATUS_NO_MEMORY;
253 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
254 r->out.resp->nb_referrals = junction->referral_count;
256 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
258 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
261 r->out.resp->referral_entries = talloc_zero_array(r,
262 struct dfs_referral_type,
263 r->out.resp->nb_referrals);
264 if (r->out.resp->referral_entries == NULL) {
265 return NT_STATUS_NO_MEMORY;
268 switch (max_referral_level) {
270 for(i=0; i < junction->referral_count; i++) {
271 struct referral *ref = &junction->referral_list[i];
272 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
273 struct dfs_referral_type *t =
274 &r->out.resp->referral_entries[i];
275 struct dfs_referral_v2 *v2 = &t->referral.v2;
278 v2->size = VERSION2_REFERRAL_SIZE;
280 v2->server_type = DFS_SERVER_ROOT;
282 v2->server_type = DFS_SERVER_NON_ROOT;
285 v2->proximity = ref->proximity;
287 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
288 if (v2->DFS_path == NULL) {
289 return NT_STATUS_NO_MEMORY;
291 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
292 if (v2->DFS_alt_path == NULL) {
293 return NT_STATUS_NO_MEMORY;
295 v2->netw_address = talloc_strdup(mem_ctx,
296 ref->alternate_path);
297 if (v2->netw_address == NULL) {
298 return NT_STATUS_NO_MEMORY;
304 for(i=0; i < junction->referral_count; i++) {
305 struct referral *ref = &junction->referral_list[i];
306 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
307 struct dfs_referral_type *t =
308 &r->out.resp->referral_entries[i];
309 struct dfs_referral_v3 *v3 = &t->referral.v3;
310 struct dfs_normal_referral *r1 = &v3->referrals.r1;
313 v3->size = VERSION3_REFERRAL_SIZE;
315 v3->server_type = DFS_SERVER_ROOT;
317 v3->server_type = DFS_SERVER_NON_ROOT;
321 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
322 if (r1->DFS_path == NULL) {
323 return NT_STATUS_NO_MEMORY;
325 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
326 if (r1->DFS_alt_path == NULL) {
327 return NT_STATUS_NO_MEMORY;
329 r1->netw_address = talloc_strdup(mem_ctx,
330 ref->alternate_path);
331 if (r1->netw_address == NULL) {
332 return NT_STATUS_NO_MEMORY;
337 DEBUG(0,("Invalid dfs referral version: %d\n",
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
351 const char *service_path,
354 return NT_STATUS_NOT_SUPPORTED;
357 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
359 const char *base_volume,
365 return NT_STATUS_NOT_SUPPORTED;
368 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
373 return NT_STATUS_NOT_SUPPORTED;
376 /* Directory operations */
378 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32_t attr)
382 START_PROFILE(syscall_opendir);
383 result = opendir(fname);
384 END_PROFILE(syscall_opendir);
388 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
395 START_PROFILE(syscall_fdopendir);
396 result = sys_fdopendir(fsp->fh->fd);
397 END_PROFILE(syscall_fdopendir);
402 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
404 SMB_STRUCT_STAT *sbuf)
406 struct dirent *result;
408 START_PROFILE(syscall_readdir);
409 result = readdir(dirp);
410 END_PROFILE(syscall_readdir);
412 /* Default Posix readdir() does not give us stat info.
413 * Set to invalid to indicate we didn't return this info. */
414 SET_STAT_INVALID(*sbuf);
415 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
416 if (result != NULL) {
417 /* See if we can efficiently return this. */
419 int flags = (lp_posix_pathnames() ?
420 AT_SYMLINK_NOFOLLOW : 0);
421 int ret = fstatat(dirfd(dirp),
426 init_stat_ex_from_stat(sbuf,
428 lp_fake_directory_create_times(
429 SNUM(handle->conn)));
437 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
438 const struct smb_filename *fname,
440 struct readdir_attr_data **attr_data)
442 return NT_STATUS_NOT_SUPPORTED;
445 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
447 START_PROFILE(syscall_seekdir);
448 seekdir(dirp, offset);
449 END_PROFILE(syscall_seekdir);
452 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
455 START_PROFILE(syscall_telldir);
456 result = telldir(dirp);
457 END_PROFILE(syscall_telldir);
461 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
463 START_PROFILE(syscall_rewinddir);
465 END_PROFILE(syscall_rewinddir);
468 static int vfswrap_mkdir(vfs_handle_struct *handle,
469 const struct smb_filename *smb_fname,
473 bool has_dacl = False;
474 const char *path = smb_fname->base_name;
477 START_PROFILE(syscall_mkdir);
479 if (lp_inherit_acls(SNUM(handle->conn))
480 && parent_dirname(talloc_tos(), path, &parent, NULL)
481 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
482 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
487 result = mkdir(path, mode);
489 if (result == 0 && !has_dacl) {
491 * We need to do this as the default behavior of POSIX ACLs
492 * is to set the mask to be the requested group permission
493 * bits, not the group permission bits to be the requested
494 * group permission bits. This is not what we want, as it will
495 * mess up any inherited ACL bits that were set. JRA.
497 int saved_errno = errno; /* We may get ENOSYS */
498 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
502 END_PROFILE(syscall_mkdir);
506 static int vfswrap_rmdir(vfs_handle_struct *handle,
507 const struct smb_filename *smb_fname)
511 START_PROFILE(syscall_rmdir);
512 result = rmdir(smb_fname->base_name);
513 END_PROFILE(syscall_rmdir);
517 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
521 START_PROFILE(syscall_closedir);
522 result = closedir(dirp);
523 END_PROFILE(syscall_closedir);
527 static void vfswrap_init_search_op(vfs_handle_struct *handle,
530 /* Default behavior is a NOOP */
533 /* File operations */
535 static int vfswrap_open(vfs_handle_struct *handle,
536 struct smb_filename *smb_fname,
537 files_struct *fsp, int flags, mode_t mode)
541 START_PROFILE(syscall_open);
543 if (smb_fname->stream_name) {
548 result = open(smb_fname->base_name, flags, mode);
550 END_PROFILE(syscall_open);
554 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
555 struct smb_request *req,
556 uint16_t root_dir_fid,
557 struct smb_filename *smb_fname,
558 uint32_t access_mask,
559 uint32_t share_access,
560 uint32_t create_disposition,
561 uint32_t create_options,
562 uint32_t file_attributes,
563 uint32_t oplock_request,
564 struct smb2_lease *lease,
565 uint64_t allocation_size,
566 uint32_t private_flags,
567 struct security_descriptor *sd,
568 struct ea_list *ea_list,
569 files_struct **result,
571 const struct smb2_create_blobs *in_context_blobs,
572 struct smb2_create_blobs *out_context_blobs)
574 struct smb2_create_blob *svhdx = NULL;
577 * It might be empty ... and smb2_create_blob_find does not handle that
579 if (in_context_blobs) {
580 svhdx = smb2_create_blob_find(in_context_blobs,
581 SVHDX_OPEN_DEVICE_CONTEXT);
585 /* SharedVHD is not yet supported */
586 DEBUG(10, ("Shared VHD not yet supported, INVALID_DEVICE_REQUEST\n"));
587 return NT_STATUS_INVALID_DEVICE_REQUEST;
590 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
591 access_mask, share_access,
592 create_disposition, create_options,
593 file_attributes, oplock_request, lease,
594 allocation_size, private_flags,
596 pinfo, in_context_blobs, out_context_blobs);
599 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
603 START_PROFILE(syscall_close);
604 result = fd_close_posix(fsp);
605 END_PROFILE(syscall_close);
609 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
613 START_PROFILE_BYTES(syscall_read, n);
614 result = sys_read(fsp->fh->fd, data, n);
615 END_PROFILE_BYTES(syscall_read);
619 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
620 size_t n, off_t offset)
624 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
625 START_PROFILE_BYTES(syscall_pread, n);
626 result = sys_pread(fsp->fh->fd, data, n, offset);
627 END_PROFILE_BYTES(syscall_pread);
629 if (result == -1 && errno == ESPIPE) {
630 /* Maintain the fiction that pipes can be seeked (sought?) on. */
631 result = SMB_VFS_READ(fsp, data, n);
635 #else /* HAVE_PREAD */
639 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
640 if (curr == -1 && errno == ESPIPE) {
641 /* Maintain the fiction that pipes can be seeked (sought?) on. */
642 result = SMB_VFS_READ(fsp, data, n);
647 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
652 result = SMB_VFS_READ(fsp, data, n);
655 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
658 #endif /* HAVE_PREAD */
663 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
667 START_PROFILE_BYTES(syscall_write, n);
668 result = sys_write(fsp->fh->fd, data, n);
669 END_PROFILE_BYTES(syscall_write);
673 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
674 size_t n, off_t offset)
678 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
679 START_PROFILE_BYTES(syscall_pwrite, n);
680 result = sys_pwrite(fsp->fh->fd, data, n, offset);
681 END_PROFILE_BYTES(syscall_pwrite);
683 if (result == -1 && errno == ESPIPE) {
684 /* Maintain the fiction that pipes can be sought on. */
685 result = SMB_VFS_WRITE(fsp, data, n);
688 #else /* HAVE_PWRITE */
692 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
697 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
701 result = SMB_VFS_WRITE(fsp, data, n);
704 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
707 #endif /* HAVE_PWRITE */
712 static void vfswrap_asys_finished(struct tevent_context *ev,
713 struct tevent_fd *fde,
714 uint16_t flags, void *p);
716 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
718 struct asys_context *ctx;
719 struct tevent_fd *fde;
723 if (conn->asys_ctx != NULL) {
727 ret = asys_context_init(&ctx, lp_aio_max_threads());
729 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
733 fd = asys_signalfd(ctx);
735 ret = set_blocking(fd, false);
737 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
741 fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
742 vfswrap_asys_finished, ctx);
744 DEBUG(1, ("tevent_add_fd failed\n"));
748 conn->asys_ctx = ctx;
749 conn->asys_fde = fde;
753 asys_context_destroy(ctx);
757 struct vfswrap_asys_state {
758 struct asys_context *asys_ctx;
759 struct tevent_req *req;
762 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
763 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
766 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
768 asys_cancel(s->asys_ctx, s->req);
772 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
774 struct tevent_context *ev,
775 struct files_struct *fsp,
777 size_t n, off_t offset)
779 struct tevent_req *req;
780 struct vfswrap_asys_state *state;
783 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
787 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
789 return tevent_req_post(req, ev);
791 state->asys_ctx = handle->conn->sconn->asys_ctx;
794 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
795 state->profile_bytes, n);
796 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
798 tevent_req_error(req, ret);
799 return tevent_req_post(req, ev);
801 talloc_set_destructor(state, vfswrap_asys_state_destructor);
806 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
808 struct tevent_context *ev,
809 struct files_struct *fsp,
811 size_t n, off_t offset)
813 struct tevent_req *req;
814 struct vfswrap_asys_state *state;
817 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
821 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
823 return tevent_req_post(req, ev);
825 state->asys_ctx = handle->conn->sconn->asys_ctx;
828 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
829 state->profile_bytes, n);
830 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
832 tevent_req_error(req, ret);
833 return tevent_req_post(req, ev);
835 talloc_set_destructor(state, vfswrap_asys_state_destructor);
840 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
842 struct tevent_context *ev,
843 struct files_struct *fsp)
845 struct tevent_req *req;
846 struct vfswrap_asys_state *state;
849 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
853 if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
855 return tevent_req_post(req, ev);
857 state->asys_ctx = handle->conn->sconn->asys_ctx;
860 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
861 state->profile_basic);
862 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
864 tevent_req_error(req, ret);
865 return tevent_req_post(req, ev);
867 talloc_set_destructor(state, vfswrap_asys_state_destructor);
872 static void vfswrap_asys_finished(struct tevent_context *ev,
873 struct tevent_fd *fde,
874 uint16_t flags, void *p)
876 struct asys_context *asys_ctx = (struct asys_context *)p;
877 struct asys_result results[get_outstanding_aio_calls()];
880 if ((flags & TEVENT_FD_READ) == 0) {
884 ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
886 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
890 for (i=0; i<ret; i++) {
891 struct asys_result *result = &results[i];
892 struct tevent_req *req;
893 struct vfswrap_asys_state *state;
895 if ((result->ret == -1) && (result->err == ECANCELED)) {
899 req = talloc_get_type_abort(result->private_data,
901 state = tevent_req_data(req, struct vfswrap_asys_state);
903 talloc_set_destructor(state, NULL);
905 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
906 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
907 state->ret = result->ret;
908 state->err = result->err;
909 tevent_req_defer_callback(req, ev);
910 tevent_req_done(req);
914 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
916 struct vfswrap_asys_state *state = tevent_req_data(
917 req, struct vfswrap_asys_state);
919 if (tevent_req_is_unix_error(req, err)) {
926 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
928 struct vfswrap_asys_state *state = tevent_req_data(
929 req, struct vfswrap_asys_state);
931 if (tevent_req_is_unix_error(req, err)) {
938 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
942 START_PROFILE(syscall_lseek);
944 /* Cope with 'stat' file opens. */
945 if (fsp->fh->fd != -1)
946 result = lseek(fsp->fh->fd, offset, whence);
949 * We want to maintain the fiction that we can seek
950 * on a fifo for file system purposes. This allows
951 * people to set up UNIX fifo's that feed data to Windows
955 if((result == -1) && (errno == ESPIPE)) {
960 END_PROFILE(syscall_lseek);
964 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
965 off_t offset, size_t n)
969 START_PROFILE_BYTES(syscall_sendfile, n);
970 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
971 END_PROFILE_BYTES(syscall_sendfile);
975 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
983 START_PROFILE_BYTES(syscall_recvfile, n);
984 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
985 END_PROFILE_BYTES(syscall_recvfile);
989 static int vfswrap_rename(vfs_handle_struct *handle,
990 const struct smb_filename *smb_fname_src,
991 const struct smb_filename *smb_fname_dst)
995 START_PROFILE(syscall_rename);
997 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1002 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1005 END_PROFILE(syscall_rename);
1009 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1014 START_PROFILE(syscall_fsync);
1015 result = fsync(fsp->fh->fd);
1016 END_PROFILE(syscall_fsync);
1023 static int vfswrap_stat(vfs_handle_struct *handle,
1024 struct smb_filename *smb_fname)
1028 START_PROFILE(syscall_stat);
1030 if (smb_fname->stream_name) {
1035 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1036 lp_fake_directory_create_times(SNUM(handle->conn)));
1038 END_PROFILE(syscall_stat);
1042 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1046 START_PROFILE(syscall_fstat);
1047 result = sys_fstat(fsp->fh->fd,
1048 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1049 END_PROFILE(syscall_fstat);
1053 static int vfswrap_lstat(vfs_handle_struct *handle,
1054 struct smb_filename *smb_fname)
1058 START_PROFILE(syscall_lstat);
1060 if (smb_fname->stream_name) {
1065 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1066 lp_fake_directory_create_times(SNUM(handle->conn)));
1068 END_PROFILE(syscall_lstat);
1072 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1074 enum vfs_translate_direction direction,
1075 TALLOC_CTX *mem_ctx,
1078 return NT_STATUS_NONE_MAPPED;
1082 * Implement the default fsctl operation.
1084 static bool vfswrap_logged_ioctl_message = false;
1086 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1087 struct files_struct *fsp,
1090 uint16_t req_flags, /* Needed for UNICODE ... */
1091 const uint8_t *_in_data,
1093 uint8_t **_out_data,
1094 uint32_t max_out_len,
1097 const char *in_data = (const char *)_in_data;
1098 char **out_data = (char **)_out_data;
1102 case FSCTL_SET_SPARSE:
1104 bool set_sparse = true;
1106 if (in_len >= 1 && in_data[0] == 0) {
1110 status = file_set_sparse(handle->conn, fsp, set_sparse);
1112 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1113 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1114 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1115 nt_errstr(status)));
1120 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1122 unsigned char objid[16];
1123 char *return_data = NULL;
1125 /* This should return the object-id on this file.
1126 * I think I'll make this be the inode+dev. JRA.
1129 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1130 fsp_fnum_dbg(fsp)));
1132 *out_len = MIN(max_out_len, 64);
1134 /* Hmmm, will this cause problems if less data asked for? */
1135 return_data = talloc_array(ctx, char, 64);
1136 if (return_data == NULL) {
1137 return NT_STATUS_NO_MEMORY;
1140 /* For backwards compatibility only store the dev/inode. */
1141 push_file_id_16(return_data, &fsp->file_id);
1142 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1143 push_file_id_16(return_data+32, &fsp->file_id);
1144 memset(return_data+48, 0, 16);
1145 *out_data = return_data;
1146 return NT_STATUS_OK;
1149 case FSCTL_GET_REPARSE_POINT:
1151 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1152 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1153 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1154 return NT_STATUS_NOT_A_REPARSE_POINT;
1157 case FSCTL_SET_REPARSE_POINT:
1159 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1160 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1161 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1162 return NT_STATUS_NOT_A_REPARSE_POINT;
1165 case FSCTL_GET_SHADOW_COPY_DATA:
1168 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1169 * and return their volume names. If max_data_count is 16, then it is just
1170 * asking for the number of volumes and length of the combined names.
1172 * pdata is the data allocated by our caller, but that uses
1173 * total_data_count (which is 0 in our case) rather than max_data_count.
1174 * Allocate the correct amount and return the pointer to let
1175 * it be deallocated when we return.
1177 struct shadow_copy_data *shadow_data = NULL;
1178 bool labels = False;
1179 uint32_t labels_data_count = 0;
1181 char *cur_pdata = NULL;
1183 if (max_out_len < 16) {
1184 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1186 return NT_STATUS_INVALID_PARAMETER;
1189 if (max_out_len > 16) {
1193 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1194 if (shadow_data == NULL) {
1195 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1196 return NT_STATUS_NO_MEMORY;
1200 * Call the VFS routine to actually do the work.
1202 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1205 /* broken module didn't set errno on error */
1206 status = NT_STATUS_UNSUCCESSFUL;
1208 status = map_nt_error_from_unix(errno);
1209 if (NT_STATUS_EQUAL(status,
1210 NT_STATUS_NOT_SUPPORTED)) {
1214 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1215 "connectpath %s, failed - %s.\n",
1216 fsp->conn->connectpath,
1217 nt_errstr(status)));
1218 TALLOC_FREE(shadow_data);
1222 labels_data_count = (shadow_data->num_volumes * 2 *
1223 sizeof(SHADOW_COPY_LABEL)) + 2;
1228 *out_len = 12 + labels_data_count;
1231 if (max_out_len < *out_len) {
1232 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1233 max_out_len, *out_len));
1234 TALLOC_FREE(shadow_data);
1235 return NT_STATUS_BUFFER_TOO_SMALL;
1238 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1239 if (cur_pdata == NULL) {
1240 TALLOC_FREE(shadow_data);
1241 return NT_STATUS_NO_MEMORY;
1244 *out_data = cur_pdata;
1246 /* num_volumes 4 bytes */
1247 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1250 /* num_labels 4 bytes */
1251 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1254 /* needed_data_count 4 bytes */
1255 SIVAL(cur_pdata, 8, labels_data_count);
1259 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1260 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1261 if (labels && shadow_data->labels) {
1262 for (i=0; i<shadow_data->num_volumes; i++) {
1264 status = srvstr_push(cur_pdata, req_flags,
1265 cur_pdata, shadow_data->labels[i],
1266 2 * sizeof(SHADOW_COPY_LABEL),
1267 STR_UNICODE|STR_TERMINATE, &len);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 TALLOC_FREE(*out_data);
1270 TALLOC_FREE(shadow_data);
1273 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1274 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1278 TALLOC_FREE(shadow_data);
1280 return NT_STATUS_OK;
1283 case FSCTL_FIND_FILES_BY_SID:
1285 /* pretend this succeeded -
1287 * we have to send back a list with all files owned by this SID
1289 * but I have to check that --metze
1295 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1296 fsp_fnum_dbg(fsp)));
1299 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1300 return NT_STATUS_INVALID_PARAMETER;
1303 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1305 /* unknown 4 bytes: this is not the length of the sid :-( */
1306 /*unknown = IVAL(pdata,0);*/
1308 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1309 return NT_STATUS_INVALID_PARAMETER;
1311 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1313 if (!sid_to_uid(&sid, &uid)) {
1314 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1315 sid_string_dbg(&sid),
1316 (unsigned long)sid_len));
1320 /* we can take a look at the find source :-)
1322 * find ./ -uid $uid -name '*' is what we need here
1325 * and send 4bytes len and then NULL terminated unicode strings
1328 * but I don't know how to deal with the paged results
1329 * (maybe we can hang the result anywhere in the fsp struct)
1331 * but I don't know how to deal with the paged results
1332 * (maybe we can hang the result anywhere in the fsp struct)
1334 * we don't send all files at once
1335 * and at the next we should *not* start from the beginning,
1336 * so we have to cache the result
1341 /* this works for now... */
1342 return NT_STATUS_OK;
1345 case FSCTL_QUERY_ALLOCATED_RANGES:
1347 /* FIXME: This is just a dummy reply, telling that all of the
1348 * file is allocated. MKS cp needs that.
1349 * Adding the real allocated ranges via FIEMAP on Linux
1350 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1351 * this FSCTL correct for sparse files.
1353 uint64_t offset, length;
1354 char *out_data_tmp = NULL;
1357 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1359 return NT_STATUS_INVALID_PARAMETER;
1362 if (max_out_len < 16) {
1363 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1365 return NT_STATUS_INVALID_PARAMETER;
1368 offset = BVAL(in_data,0);
1369 length = BVAL(in_data,8);
1371 if (offset + length < offset) {
1372 /* No 64-bit integer wrap. */
1373 return NT_STATUS_INVALID_PARAMETER;
1376 /* Shouldn't this be SMB_VFS_STAT ... ? */
1377 status = vfs_stat_fsp(fsp);
1378 if (!NT_STATUS_IS_OK(status)) {
1383 out_data_tmp = talloc_array(ctx, char, *out_len);
1384 if (out_data_tmp == NULL) {
1385 DEBUG(10, ("unable to allocate memory for response\n"));
1386 return NT_STATUS_NO_MEMORY;
1389 if (offset > fsp->fsp_name->st.st_ex_size ||
1390 fsp->fsp_name->st.st_ex_size == 0 ||
1392 memset(out_data_tmp, 0, *out_len);
1394 uint64_t end = offset + length;
1395 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1396 SBVAL(out_data_tmp, 0, 0);
1397 SBVAL(out_data_tmp, 8, end);
1400 *out_data = out_data_tmp;
1402 return NT_STATUS_OK;
1405 case FSCTL_IS_VOLUME_DIRTY:
1407 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1408 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1410 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1411 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1413 return NT_STATUS_INVALID_PARAMETER;
1418 * Only print once ... unfortunately there could be lots of
1419 * different FSCTLs that are called.
1421 if (!vfswrap_logged_ioctl_message) {
1422 vfswrap_logged_ioctl_message = true;
1423 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1424 __func__, function));
1428 return NT_STATUS_NOT_SUPPORTED;
1431 struct vfs_cc_state {
1436 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1437 TALLOC_CTX *mem_ctx,
1438 struct tevent_context *ev,
1439 struct files_struct *src_fsp,
1441 struct files_struct *dest_fsp,
1445 struct tevent_req *req;
1446 struct vfs_cc_state *vfs_cc_state;
1449 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1450 (unsigned long)num));
1452 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1457 vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1458 MIN(num, 8*1024*1024));
1459 if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1460 return tevent_req_post(req, ev);
1463 status = vfs_stat_fsp(src_fsp);
1464 if (tevent_req_nterror(req, status)) {
1465 return tevent_req_post(req, ev);
1468 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1470 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1471 * If the SourceOffset or SourceOffset + Length extends beyond
1472 * the end of file, the server SHOULD<240> treat this as a
1473 * STATUS_END_OF_FILE error.
1475 * <240> Section 3.3.5.15.6: Windows servers will return
1476 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1478 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1479 return tevent_req_post(req, ev);
1482 /* could use 2.6.33+ sendfile here to do this in kernel */
1483 while (vfs_cc_state->copied < num) {
1485 struct lock_struct lck;
1488 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1489 num - vfs_cc_state->copied);
1491 if (src_fsp->op == NULL) {
1492 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1493 return tevent_req_post(req, ev);
1495 init_strict_lock_struct(src_fsp,
1496 src_fsp->op->global->open_persistent_id,
1502 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1503 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1504 return tevent_req_post(req, ev);
1507 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1510 saved_errno = errno;
1513 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1516 errno = saved_errno;
1517 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1518 return tevent_req_post(req, ev);
1520 if (ret != this_num) {
1521 /* zero tolerance for short reads */
1522 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1523 return tevent_req_post(req, ev);
1528 if (dest_fsp->op == NULL) {
1529 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1530 return tevent_req_post(req, ev);
1533 init_strict_lock_struct(dest_fsp,
1534 dest_fsp->op->global->open_persistent_id,
1540 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1541 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1542 return tevent_req_post(req, ev);
1545 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1546 this_num, dest_off);
1548 saved_errno = errno;
1551 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1554 errno = saved_errno;
1555 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1556 return tevent_req_post(req, ev);
1558 if (ret != this_num) {
1559 /* zero tolerance for short writes */
1560 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1561 return tevent_req_post(req, ev);
1565 vfs_cc_state->copied += this_num;
1568 tevent_req_done(req);
1569 return tevent_req_post(req, ev);
1572 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1573 struct tevent_req *req,
1576 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1577 struct vfs_cc_state);
1580 if (tevent_req_is_nterror(req, &status)) {
1581 DEBUG(2, ("server side copy chunk failed: %s\n",
1582 nt_errstr(status)));
1584 tevent_req_received(req);
1588 *copied = vfs_cc_state->copied;
1589 DEBUG(10, ("server side copy chunk copied %lu\n",
1590 (unsigned long)*copied));
1591 tevent_req_received(req);
1593 return NT_STATUS_OK;
1596 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1597 TALLOC_CTX *mem_ctx,
1598 struct files_struct *fsp,
1599 struct smb_filename *smb_fname,
1600 uint16_t *_compression_fmt)
1602 return NT_STATUS_INVALID_DEVICE_REQUEST;
1605 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1606 TALLOC_CTX *mem_ctx,
1607 struct files_struct *fsp,
1608 uint16_t compression_fmt)
1610 return NT_STATUS_INVALID_DEVICE_REQUEST;
1613 /********************************************************************
1614 Given a stat buffer return the allocated size on disk, taking into
1615 account sparse files.
1616 ********************************************************************/
1617 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1618 struct files_struct *fsp,
1619 const SMB_STRUCT_STAT *sbuf)
1623 START_PROFILE(syscall_get_alloc_size);
1625 if(S_ISDIR(sbuf->st_ex_mode)) {
1630 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1631 /* The type of st_blocksize is blkcnt_t which *MUST* be
1632 signed (according to POSIX) and can be less than 64-bits.
1633 Ensure when we're converting to 64 bits wide we don't
1635 #if defined(SIZEOF_BLKCNT_T_8)
1636 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1637 #elif defined(SIZEOF_BLKCNT_T_4)
1639 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1640 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1643 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1647 * Some file systems do not allocate a block for very
1648 * small files. But for non-empty file should report a
1652 uint64_t filesize = get_file_size_stat(sbuf);
1654 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1658 result = get_file_size_stat(sbuf);
1661 if (fsp && fsp->initial_allocation_size)
1662 result = MAX(result,fsp->initial_allocation_size);
1664 result = smb_roundup(handle->conn, result);
1667 END_PROFILE(syscall_get_alloc_size);
1671 static int vfswrap_unlink(vfs_handle_struct *handle,
1672 const struct smb_filename *smb_fname)
1676 START_PROFILE(syscall_unlink);
1678 if (smb_fname->stream_name) {
1682 result = unlink(smb_fname->base_name);
1685 END_PROFILE(syscall_unlink);
1689 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1693 START_PROFILE(syscall_chmod);
1696 * We need to do this due to the fact that the default POSIX ACL
1697 * chmod modifies the ACL *mask* for the group owner, not the
1698 * group owner bits directly. JRA.
1703 int saved_errno = errno; /* We might get ENOSYS */
1704 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1705 END_PROFILE(syscall_chmod);
1708 /* Error - return the old errno. */
1709 errno = saved_errno;
1712 result = chmod(path, mode);
1713 END_PROFILE(syscall_chmod);
1717 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1721 START_PROFILE(syscall_fchmod);
1724 * We need to do this due to the fact that the default POSIX ACL
1725 * chmod modifies the ACL *mask* for the group owner, not the
1726 * group owner bits directly. JRA.
1730 int saved_errno = errno; /* We might get ENOSYS */
1731 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1732 END_PROFILE(syscall_fchmod);
1735 /* Error - return the old errno. */
1736 errno = saved_errno;
1739 #if defined(HAVE_FCHMOD)
1740 result = fchmod(fsp->fh->fd, mode);
1746 END_PROFILE(syscall_fchmod);
1750 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1754 START_PROFILE(syscall_chown);
1755 result = chown(path, uid, gid);
1756 END_PROFILE(syscall_chown);
1760 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1765 START_PROFILE(syscall_fchown);
1766 result = fchown(fsp->fh->fd, uid, gid);
1767 END_PROFILE(syscall_fchown);
1775 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1779 START_PROFILE(syscall_lchown);
1780 result = lchown(path, uid, gid);
1781 END_PROFILE(syscall_lchown);
1785 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1789 START_PROFILE(syscall_chdir);
1790 result = chdir(path);
1791 END_PROFILE(syscall_chdir);
1795 static char *vfswrap_getwd(vfs_handle_struct *handle)
1799 START_PROFILE(syscall_getwd);
1800 result = sys_getwd();
1801 END_PROFILE(syscall_getwd);
1805 /*********************************************************************
1806 nsec timestamp resolution call. Convert down to whatever the underlying
1807 system will support.
1808 **********************************************************************/
1810 static int vfswrap_ntimes(vfs_handle_struct *handle,
1811 const struct smb_filename *smb_fname,
1812 struct smb_file_time *ft)
1816 START_PROFILE(syscall_ntimes);
1818 if (smb_fname->stream_name) {
1824 if (null_timespec(ft->atime)) {
1825 ft->atime= smb_fname->st.st_ex_atime;
1828 if (null_timespec(ft->mtime)) {
1829 ft->mtime = smb_fname->st.st_ex_mtime;
1832 if (!null_timespec(ft->create_time)) {
1833 set_create_timespec_ea(handle->conn,
1838 if ((timespec_compare(&ft->atime,
1839 &smb_fname->st.st_ex_atime) == 0) &&
1840 (timespec_compare(&ft->mtime,
1841 &smb_fname->st.st_ex_mtime) == 0)) {
1846 #if defined(HAVE_UTIMENSAT)
1848 struct timespec ts[2];
1851 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1853 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1855 if (!((result == -1) && (errno == ENOSYS))) {
1859 #if defined(HAVE_UTIMES)
1861 struct timeval tv[2];
1862 tv[0] = convert_timespec_to_timeval(ft->atime);
1863 tv[1] = convert_timespec_to_timeval(ft->mtime);
1864 result = utimes(smb_fname->base_name, tv);
1866 result = utimes(smb_fname->base_name, NULL);
1868 if (!((result == -1) && (errno == ENOSYS))) {
1872 #if defined(HAVE_UTIME)
1874 struct utimbuf times;
1875 times.actime = convert_timespec_to_time_t(ft->atime);
1876 times.modtime = convert_timespec_to_time_t(ft->mtime);
1877 result = utime(smb_fname->base_name, ×);
1879 result = utime(smb_fname->base_name, NULL);
1881 if (!((result == -1) && (errno == ENOSYS))) {
1889 END_PROFILE(syscall_ntimes);
1893 /*********************************************************************
1894 A version of ftruncate that will write the space on disk if strict
1896 **********************************************************************/
1898 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1900 off_t space_to_write;
1901 uint64_t space_avail;
1902 uint64_t bsize,dfree,dsize;
1905 SMB_STRUCT_STAT *pst;
1907 status = vfs_stat_fsp(fsp);
1908 if (!NT_STATUS_IS_OK(status)) {
1911 pst = &fsp->fsp_name->st;
1914 if (S_ISFIFO(pst->st_ex_mode))
1918 if (pst->st_ex_size == len)
1921 /* Shrink - just ftruncate. */
1922 if (pst->st_ex_size > len)
1923 return ftruncate(fsp->fh->fd, len);
1925 space_to_write = len - pst->st_ex_size;
1927 /* for allocation try fallocate first. This can fail on some
1928 platforms e.g. when the filesystem doesn't support it and no
1929 emulation is being done by the libc (like on AIX with JFS1). In that
1930 case we do our own emulation. fallocate implementations can
1931 return ENOTSUP or EINVAL in cases like that. */
1932 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
1933 if (ret == -1 && errno == ENOSPC) {
1939 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1940 "error %d. Falling back to slow manual allocation\n", errno));
1942 /* available disk space is enough or not? */
1943 space_avail = get_dfree_info(fsp->conn,
1944 fsp->fsp_name->base_name,
1945 &bsize, &dfree, &dsize);
1946 /* space_avail is 1k blocks */
1947 if (space_avail == (uint64_t)-1 ||
1948 ((uint64_t)space_to_write/1024 > space_avail) ) {
1953 /* Write out the real space on disk. */
1954 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1962 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1965 SMB_STRUCT_STAT *pst;
1969 START_PROFILE(syscall_ftruncate);
1971 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1972 result = strict_allocate_ftruncate(handle, fsp, len);
1973 END_PROFILE(syscall_ftruncate);
1977 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1978 ftruncate if the system supports it. Then I discovered that
1979 you can have some filesystems that support ftruncate
1980 expansion and some that don't! On Linux fat can't do
1981 ftruncate extend but ext2 can. */
1983 result = ftruncate(fsp->fh->fd, len);
1985 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1986 extend a file with ftruncate. Provide alternate implementation
1989 /* Do an fstat to see if the file is longer than the requested
1990 size in which case the ftruncate above should have
1991 succeeded or shorter, in which case seek to len - 1 and
1992 write 1 byte of zero */
1993 status = vfs_stat_fsp(fsp);
1994 if (!NT_STATUS_IS_OK(status)) {
1998 /* We need to update the files_struct after successful ftruncate */
2003 pst = &fsp->fsp_name->st;
2006 if (S_ISFIFO(pst->st_ex_mode)) {
2012 if (pst->st_ex_size == len) {
2017 if (pst->st_ex_size > len) {
2018 /* the ftruncate should have worked */
2022 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2030 END_PROFILE(syscall_ftruncate);
2034 static int vfswrap_fallocate(vfs_handle_struct *handle,
2042 START_PROFILE(syscall_fallocate);
2044 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2046 * posix_fallocate returns 0 on success, errno on error
2047 * and doesn't set errno. Make it behave like fallocate()
2048 * which returns -1, and sets errno on failure.
2055 /* sys_fallocate handles filtering of unsupported mode flags */
2056 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2058 END_PROFILE(syscall_fallocate);
2062 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2066 START_PROFILE(syscall_fcntl_lock);
2067 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2068 END_PROFILE(syscall_fcntl_lock);
2072 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2073 uint32_t share_mode, uint32_t access_mask)
2075 START_PROFILE(syscall_kernel_flock);
2076 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2077 END_PROFILE(syscall_kernel_flock);
2081 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2085 START_PROFILE(syscall_fcntl_getlock);
2086 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
2087 END_PROFILE(syscall_fcntl_getlock);
2091 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2096 START_PROFILE(syscall_linux_setlease);
2098 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2099 result = linux_setlease(fsp->fh->fd, leasetype);
2103 END_PROFILE(syscall_linux_setlease);
2107 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2111 START_PROFILE(syscall_symlink);
2112 result = symlink(oldpath, newpath);
2113 END_PROFILE(syscall_symlink);
2117 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2121 START_PROFILE(syscall_readlink);
2122 result = readlink(path, buf, bufsiz);
2123 END_PROFILE(syscall_readlink);
2127 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2131 START_PROFILE(syscall_link);
2132 result = link(oldpath, newpath);
2133 END_PROFILE(syscall_link);
2137 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2141 START_PROFILE(syscall_mknod);
2142 result = sys_mknod(pathname, mode, dev);
2143 END_PROFILE(syscall_mknod);
2147 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2151 START_PROFILE(syscall_realpath);
2152 result = sys_realpath(path);
2153 END_PROFILE(syscall_realpath);
2157 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2161 return chflags(path, flags);
2168 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2169 const SMB_STRUCT_STAT *sbuf)
2173 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2177 key.devid = sbuf->st_ex_dev;
2178 key.inode = sbuf->st_ex_ino;
2179 /* key.extid is unused by default. */
2184 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2185 struct files_struct *fsp,
2187 TALLOC_CTX *mem_ctx,
2188 unsigned int *pnum_streams,
2189 struct stream_struct **pstreams)
2191 SMB_STRUCT_STAT sbuf;
2192 struct stream_struct *tmp_streams = NULL;
2195 if ((fsp != NULL) && (fsp->is_directory)) {
2197 * No default streams on directories
2202 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2203 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2206 struct smb_filename smb_fname;
2208 ZERO_STRUCT(smb_fname);
2209 smb_fname.base_name = discard_const_p(char, fname);
2211 if (lp_posix_pathnames()) {
2212 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2214 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2216 sbuf = smb_fname.st;
2220 return map_nt_error_from_unix(errno);
2223 if (S_ISDIR(sbuf.st_ex_mode)) {
2227 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2228 (*pnum_streams) + 1);
2229 if (tmp_streams == NULL) {
2230 return NT_STATUS_NO_MEMORY;
2232 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2233 if (tmp_streams[*pnum_streams].name == NULL) {
2234 return NT_STATUS_NO_MEMORY;
2236 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2237 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2240 *pstreams = tmp_streams;
2242 return NT_STATUS_OK;
2245 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2248 TALLOC_CTX *mem_ctx,
2252 * Don't fall back to get_real_filename so callers can differentiate
2253 * between a full directory scan and an actual case-insensitive stat.
2259 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2262 return handle->conn->connectpath;
2265 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2266 struct byte_range_lock *br_lck,
2267 struct lock_struct *plock,
2270 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2272 /* Note: blr is not used in the default implementation. */
2273 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2276 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2277 struct messaging_context *msg_ctx,
2278 struct byte_range_lock *br_lck,
2279 const struct lock_struct *plock)
2281 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2283 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2286 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2287 struct byte_range_lock *br_lck,
2288 struct lock_struct *plock)
2290 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2292 /* Note: blr is not used in the default implementation. */
2293 return brl_lock_cancel_default(br_lck, plock);
2296 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2298 struct lock_struct *plock)
2300 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2301 plock->lock_type == WRITE_LOCK);
2303 return strict_lock_default(fsp, plock);
2306 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2308 struct lock_struct *plock)
2310 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2311 plock->lock_type == WRITE_LOCK);
2313 strict_unlock_default(fsp, plock);
2316 /* NT ACL operations. */
2318 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2320 uint32_t security_info,
2321 TALLOC_CTX *mem_ctx,
2322 struct security_descriptor **ppdesc)
2326 START_PROFILE(fget_nt_acl);
2327 result = posix_fget_nt_acl(fsp, security_info,
2329 END_PROFILE(fget_nt_acl);
2333 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2334 const struct smb_filename *smb_fname,
2335 uint32_t security_info,
2336 TALLOC_CTX *mem_ctx,
2337 struct security_descriptor **ppdesc)
2341 START_PROFILE(get_nt_acl);
2342 result = posix_get_nt_acl(handle->conn,
2343 smb_fname->base_name,
2347 END_PROFILE(get_nt_acl);
2351 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2355 START_PROFILE(fset_nt_acl);
2356 result = set_nt_acl(fsp, security_info_sent, psd);
2357 END_PROFILE(fset_nt_acl);
2361 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2362 struct smb_filename *file,
2363 struct security_acl *sacl,
2364 uint32_t access_requested,
2365 uint32_t access_denied)
2367 return NT_STATUS_OK; /* Nothing to do here ... */
2370 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2378 START_PROFILE(chmod_acl);
2379 result = chmod_acl(handle->conn, name, mode);
2380 END_PROFILE(chmod_acl);
2385 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2393 START_PROFILE(fchmod_acl);
2394 result = fchmod_acl(fsp, mode);
2395 END_PROFILE(fchmod_acl);
2400 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2402 SMB_ACL_TYPE_T type,
2403 TALLOC_CTX *mem_ctx)
2405 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2408 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2410 TALLOC_CTX *mem_ctx)
2412 return sys_acl_get_fd(handle, fsp, mem_ctx);
2415 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2417 return sys_acl_set_file(handle, name, acltype, theacl);
2420 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2422 return sys_acl_set_fd(handle, fsp, theacl);
2425 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2427 return sys_acl_delete_def_file(handle, path);
2430 /****************************************************************
2431 Extended attribute operations.
2432 *****************************************************************/
2434 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2436 return getxattr(path, name, value, size);
2439 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2441 return fgetxattr(fsp->fh->fd, name, value, size);
2444 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2446 return listxattr(path, list, size);
2449 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2451 return flistxattr(fsp->fh->fd, list, size);
2454 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2456 return removexattr(path, name);
2459 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2461 return fremovexattr(fsp->fh->fd, name);
2464 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2466 return setxattr(path, name, value, size, flags);
2469 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2471 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2474 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2479 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2480 const struct smb_filename *fname,
2481 SMB_STRUCT_STAT *sbuf)
2485 bool offline = false;
2487 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2491 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2492 #if defined(ENOTSUP)
2498 status = get_full_smb_filename(talloc_tos(), fname, &path);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 errno = map_errno_from_nt_status(status);
2504 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2511 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2512 const struct smb_filename *fname)
2514 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2515 #if defined(ENOTSUP)
2521 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2522 struct files_struct *fsp,
2523 TALLOC_CTX *mem_ctx,
2526 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2529 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2530 struct files_struct *fsp,
2531 const DATA_BLOB old_cookie,
2532 TALLOC_CTX *mem_ctx,
2533 DATA_BLOB *new_cookie)
2535 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2539 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2540 struct smb_request *smb1req,
2541 struct smbXsrv_open *op,
2542 const DATA_BLOB old_cookie,
2543 TALLOC_CTX *mem_ctx,
2544 struct files_struct **fsp,
2545 DATA_BLOB *new_cookie)
2547 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2548 old_cookie, mem_ctx,
2552 static struct vfs_fn_pointers vfs_default_fns = {
2553 /* Disk operations */
2555 .connect_fn = vfswrap_connect,
2556 .disconnect_fn = vfswrap_disconnect,
2557 .disk_free_fn = vfswrap_disk_free,
2558 .get_quota_fn = vfswrap_get_quota,
2559 .set_quota_fn = vfswrap_set_quota,
2560 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2561 .statvfs_fn = vfswrap_statvfs,
2562 .fs_capabilities_fn = vfswrap_fs_capabilities,
2563 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2564 .snap_check_path_fn = vfswrap_snap_check_path,
2565 .snap_create_fn = vfswrap_snap_create,
2566 .snap_delete_fn = vfswrap_snap_delete,
2568 /* Directory operations */
2570 .opendir_fn = vfswrap_opendir,
2571 .fdopendir_fn = vfswrap_fdopendir,
2572 .readdir_fn = vfswrap_readdir,
2573 .readdir_attr_fn = vfswrap_readdir_attr,
2574 .seekdir_fn = vfswrap_seekdir,
2575 .telldir_fn = vfswrap_telldir,
2576 .rewind_dir_fn = vfswrap_rewinddir,
2577 .mkdir_fn = vfswrap_mkdir,
2578 .rmdir_fn = vfswrap_rmdir,
2579 .closedir_fn = vfswrap_closedir,
2580 .init_search_op_fn = vfswrap_init_search_op,
2582 /* File operations */
2584 .open_fn = vfswrap_open,
2585 .create_file_fn = vfswrap_create_file,
2586 .close_fn = vfswrap_close,
2587 .read_fn = vfswrap_read,
2588 .pread_fn = vfswrap_pread,
2589 .pread_send_fn = vfswrap_pread_send,
2590 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2591 .write_fn = vfswrap_write,
2592 .pwrite_fn = vfswrap_pwrite,
2593 .pwrite_send_fn = vfswrap_pwrite_send,
2594 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2595 .lseek_fn = vfswrap_lseek,
2596 .sendfile_fn = vfswrap_sendfile,
2597 .recvfile_fn = vfswrap_recvfile,
2598 .rename_fn = vfswrap_rename,
2599 .fsync_fn = vfswrap_fsync,
2600 .fsync_send_fn = vfswrap_fsync_send,
2601 .fsync_recv_fn = vfswrap_asys_int_recv,
2602 .stat_fn = vfswrap_stat,
2603 .fstat_fn = vfswrap_fstat,
2604 .lstat_fn = vfswrap_lstat,
2605 .get_alloc_size_fn = vfswrap_get_alloc_size,
2606 .unlink_fn = vfswrap_unlink,
2607 .chmod_fn = vfswrap_chmod,
2608 .fchmod_fn = vfswrap_fchmod,
2609 .chown_fn = vfswrap_chown,
2610 .fchown_fn = vfswrap_fchown,
2611 .lchown_fn = vfswrap_lchown,
2612 .chdir_fn = vfswrap_chdir,
2613 .getwd_fn = vfswrap_getwd,
2614 .ntimes_fn = vfswrap_ntimes,
2615 .ftruncate_fn = vfswrap_ftruncate,
2616 .fallocate_fn = vfswrap_fallocate,
2617 .lock_fn = vfswrap_lock,
2618 .kernel_flock_fn = vfswrap_kernel_flock,
2619 .linux_setlease_fn = vfswrap_linux_setlease,
2620 .getlock_fn = vfswrap_getlock,
2621 .symlink_fn = vfswrap_symlink,
2622 .readlink_fn = vfswrap_readlink,
2623 .link_fn = vfswrap_link,
2624 .mknod_fn = vfswrap_mknod,
2625 .realpath_fn = vfswrap_realpath,
2626 .chflags_fn = vfswrap_chflags,
2627 .file_id_create_fn = vfswrap_file_id_create,
2628 .streaminfo_fn = vfswrap_streaminfo,
2629 .get_real_filename_fn = vfswrap_get_real_filename,
2630 .connectpath_fn = vfswrap_connectpath,
2631 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2632 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2633 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2634 .strict_lock_fn = vfswrap_strict_lock,
2635 .strict_unlock_fn = vfswrap_strict_unlock,
2636 .translate_name_fn = vfswrap_translate_name,
2637 .fsctl_fn = vfswrap_fsctl,
2638 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2639 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2640 .get_compression_fn = vfswrap_get_compression,
2641 .set_compression_fn = vfswrap_set_compression,
2643 /* NT ACL operations. */
2645 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2646 .get_nt_acl_fn = vfswrap_get_nt_acl,
2647 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2648 .audit_file_fn = vfswrap_audit_file,
2650 /* POSIX ACL operations. */
2652 .chmod_acl_fn = vfswrap_chmod_acl,
2653 .fchmod_acl_fn = vfswrap_fchmod_acl,
2655 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2656 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2657 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2658 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2659 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2660 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2661 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2663 /* EA operations. */
2664 .getxattr_fn = vfswrap_getxattr,
2665 .fgetxattr_fn = vfswrap_fgetxattr,
2666 .listxattr_fn = vfswrap_listxattr,
2667 .flistxattr_fn = vfswrap_flistxattr,
2668 .removexattr_fn = vfswrap_removexattr,
2669 .fremovexattr_fn = vfswrap_fremovexattr,
2670 .setxattr_fn = vfswrap_setxattr,
2671 .fsetxattr_fn = vfswrap_fsetxattr,
2673 /* aio operations */
2674 .aio_force_fn = vfswrap_aio_force,
2676 /* offline operations */
2677 .is_offline_fn = vfswrap_is_offline,
2678 .set_offline_fn = vfswrap_set_offline,
2680 /* durable handle operations */
2681 .durable_cookie_fn = vfswrap_durable_cookie,
2682 .durable_disconnect_fn = vfswrap_durable_disconnect,
2683 .durable_reconnect_fn = vfswrap_durable_reconnect,
2686 NTSTATUS vfs_default_init(void);
2687 NTSTATUS vfs_default_init(void)
2689 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2690 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);