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"
37 #define DBGC_CLASS DBGC_VFS
39 /* Check for NULL pointer parameters in vfswrap_* functions */
41 /* We don't want to have NULL function pointers lying around. Someone
42 is sure to try and execute them. These stubs are used to prevent
45 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
47 return 0; /* Return >= 0 for success */
50 static void vfswrap_disconnect(vfs_handle_struct *handle)
56 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle, const char *path, bool small_query, uint64_t *bsize,
57 uint64_t *dfree, uint64_t *dsize)
61 result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
65 static int vfswrap_get_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
67 #ifdef HAVE_SYS_QUOTAS
70 START_PROFILE(syscall_get_quota);
71 result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
72 END_PROFILE(syscall_get_quota);
80 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
82 #ifdef HAVE_SYS_QUOTAS
85 START_PROFILE(syscall_set_quota);
86 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
87 END_PROFILE(syscall_set_quota);
95 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
96 struct files_struct *fsp,
97 struct shadow_copy_data *shadow_copy_data,
101 return -1; /* Not implemented. */
104 static int vfswrap_statvfs(struct vfs_handle_struct *handle, const char *path, vfs_statvfs_struct *statbuf)
106 return sys_statvfs(path, statbuf);
109 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
110 enum timestamp_set_resolution *p_ts_res)
112 connection_struct *conn = handle->conn;
113 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
114 struct smb_filename *smb_fname_cpath = NULL;
115 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 status = create_synthetic_smb_fname(talloc_tos(),
135 if (!NT_STATUS_IS_OK(status)) {
139 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
141 TALLOC_FREE(smb_fname_cpath);
145 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
146 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
147 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
148 /* If any of the normal UNIX directory timestamps
149 * have a non-zero tv_nsec component assume
150 * we might be able to set sub-second timestamps.
151 * See what filetime set primitives we have.
153 #if defined(HAVE_UTIMENSAT)
154 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
155 #elif defined(HAVE_UTIMES)
156 /* utimes allows msec timestamps to be set. */
157 *p_ts_res = TIMESTAMP_SET_MSEC;
158 #elif defined(HAVE_UTIME)
159 /* utime only allows sec timestamps to be set. */
160 *p_ts_res = TIMESTAMP_SET_SECONDS;
163 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
165 "available on share %s, directory %s\n",
166 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
167 lp_servicename(talloc_tos(), conn->params->service),
168 conn->connectpath ));
170 TALLOC_FREE(smb_fname_cpath);
174 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
175 struct dfs_GetDFSReferral *r)
177 struct junction_map *junction = NULL;
179 bool self_referral = false;
180 char *pathnamep = NULL;
181 char *local_dfs_path = NULL;
184 uint16_t max_referral_level = r->in.req.max_referral_level;
187 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
190 /* get the junction entry */
191 if (r->in.req.servername == NULL) {
192 return NT_STATUS_NOT_FOUND;
196 * Trim pathname sent by client so it begins with only one backslash.
197 * Two backslashes confuse some dfs clients
200 local_dfs_path = talloc_strdup(r, r->in.req.servername);
201 if (local_dfs_path == NULL) {
202 return NT_STATUS_NO_MEMORY;
204 pathnamep = local_dfs_path;
205 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
206 IS_DIRECTORY_SEP(pathnamep[1])) {
210 junction = talloc_zero(r, struct junction_map);
211 if (junction == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 /* The following call can change cwd. */
216 status = get_referred_path(r, pathnamep,
217 !handle->conn->sconn->using_smb2,
218 junction, &consumedcnt, &self_referral);
219 if (!NT_STATUS_IS_OK(status)) {
220 vfs_ChDir(handle->conn, handle->conn->connectpath);
223 vfs_ChDir(handle->conn, handle->conn->connectpath);
225 if (!self_referral) {
226 pathnamep[consumedcnt] = '\0';
229 dbgtext("setup_dfs_referral: Path %s to "
230 "alternate path(s):",
232 for (i=0; i < junction->referral_count; i++) {
234 junction->referral_list[i].alternate_path);
240 if (r->in.req.max_referral_level <= 2) {
241 max_referral_level = 2;
243 if (r->in.req.max_referral_level >= 3) {
244 max_referral_level = 3;
247 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
248 if (r->out.resp == NULL) {
249 return NT_STATUS_NO_MEMORY;
252 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
253 r->out.resp->nb_referrals = junction->referral_count;
255 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
257 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
260 r->out.resp->referral_entries = talloc_zero_array(r,
261 struct dfs_referral_type,
262 r->out.resp->nb_referrals);
263 if (r->out.resp->referral_entries == NULL) {
264 return NT_STATUS_NO_MEMORY;
267 switch (max_referral_level) {
269 for(i=0; i < junction->referral_count; i++) {
270 struct referral *ref = &junction->referral_list[i];
271 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
272 struct dfs_referral_type *t =
273 &r->out.resp->referral_entries[i];
274 struct dfs_referral_v2 *v2 = &t->referral.v2;
277 v2->size = VERSION2_REFERRAL_SIZE;
279 v2->server_type = DFS_SERVER_ROOT;
281 v2->server_type = DFS_SERVER_NON_ROOT;
284 v2->proximity = ref->proximity;
286 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
287 if (v2->DFS_path == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
291 if (v2->DFS_alt_path == NULL) {
292 return NT_STATUS_NO_MEMORY;
294 v2->netw_address = talloc_strdup(mem_ctx,
295 ref->alternate_path);
296 if (v2->netw_address == NULL) {
297 return NT_STATUS_NO_MEMORY;
303 for(i=0; i < junction->referral_count; i++) {
304 struct referral *ref = &junction->referral_list[i];
305 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
306 struct dfs_referral_type *t =
307 &r->out.resp->referral_entries[i];
308 struct dfs_referral_v3 *v3 = &t->referral.v3;
309 struct dfs_normal_referral *r1 = &v3->referrals.r1;
312 v3->size = VERSION3_REFERRAL_SIZE;
314 v3->server_type = DFS_SERVER_ROOT;
316 v3->server_type = DFS_SERVER_NON_ROOT;
320 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
321 if (r1->DFS_path == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
325 if (r1->DFS_alt_path == NULL) {
326 return NT_STATUS_NO_MEMORY;
328 r1->netw_address = talloc_strdup(mem_ctx,
329 ref->alternate_path);
330 if (r1->netw_address == NULL) {
331 return NT_STATUS_NO_MEMORY;
336 DEBUG(0,("setup_dfs_referral: Invalid dfs referral "
338 max_referral_level));
339 return NT_STATUS_INVALID_LEVEL;
343 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
349 /* Directory operations */
351 static DIR *vfswrap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
355 START_PROFILE(syscall_opendir);
356 result = opendir(fname);
357 END_PROFILE(syscall_opendir);
361 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
368 START_PROFILE(syscall_fdopendir);
369 result = sys_fdopendir(fsp->fh->fd);
370 END_PROFILE(syscall_fdopendir);
375 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
377 SMB_STRUCT_STAT *sbuf)
379 struct dirent *result;
381 START_PROFILE(syscall_readdir);
382 result = readdir(dirp);
383 /* Default Posix readdir() does not give us stat info.
384 * Set to invalid to indicate we didn't return this info. */
386 SET_STAT_INVALID(*sbuf);
387 END_PROFILE(syscall_readdir);
391 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
393 START_PROFILE(syscall_seekdir);
394 seekdir(dirp, offset);
395 END_PROFILE(syscall_seekdir);
398 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
401 START_PROFILE(syscall_telldir);
402 result = telldir(dirp);
403 END_PROFILE(syscall_telldir);
407 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
409 START_PROFILE(syscall_rewinddir);
411 END_PROFILE(syscall_rewinddir);
414 static int vfswrap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
417 bool has_dacl = False;
420 START_PROFILE(syscall_mkdir);
422 if (lp_inherit_acls(SNUM(handle->conn))
423 && parent_dirname(talloc_tos(), path, &parent, NULL)
424 && (has_dacl = directory_has_default_acl(handle->conn, parent)))
425 mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
429 result = mkdir(path, mode);
431 if (result == 0 && !has_dacl) {
433 * We need to do this as the default behavior of POSIX ACLs
434 * is to set the mask to be the requested group permission
435 * bits, not the group permission bits to be the requested
436 * group permission bits. This is not what we want, as it will
437 * mess up any inherited ACL bits that were set. JRA.
439 int saved_errno = errno; /* We may get ENOSYS */
440 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
444 END_PROFILE(syscall_mkdir);
448 static int vfswrap_rmdir(vfs_handle_struct *handle, const char *path)
452 START_PROFILE(syscall_rmdir);
453 result = rmdir(path);
454 END_PROFILE(syscall_rmdir);
458 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
462 START_PROFILE(syscall_closedir);
463 result = closedir(dirp);
464 END_PROFILE(syscall_closedir);
468 static void vfswrap_init_search_op(vfs_handle_struct *handle,
471 /* Default behavior is a NOOP */
474 /* File operations */
476 static int vfswrap_open(vfs_handle_struct *handle,
477 struct smb_filename *smb_fname,
478 files_struct *fsp, int flags, mode_t mode)
482 START_PROFILE(syscall_open);
484 if (smb_fname->stream_name) {
489 result = open(smb_fname->base_name, flags, mode);
491 END_PROFILE(syscall_open);
495 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
496 struct smb_request *req,
497 uint16_t root_dir_fid,
498 struct smb_filename *smb_fname,
499 uint32_t access_mask,
500 uint32_t share_access,
501 uint32_t create_disposition,
502 uint32_t create_options,
503 uint32_t file_attributes,
504 uint32_t oplock_request,
505 uint64_t allocation_size,
506 uint32_t private_flags,
507 struct security_descriptor *sd,
508 struct ea_list *ea_list,
509 files_struct **result,
512 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
513 access_mask, share_access,
514 create_disposition, create_options,
515 file_attributes, oplock_request,
516 allocation_size, private_flags,
521 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
525 START_PROFILE(syscall_close);
526 result = fd_close_posix(fsp);
527 END_PROFILE(syscall_close);
531 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
535 START_PROFILE_BYTES(syscall_read, n);
536 result = sys_read(fsp->fh->fd, data, n);
537 END_PROFILE(syscall_read);
541 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
542 size_t n, off_t offset)
546 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
547 START_PROFILE_BYTES(syscall_pread, n);
548 result = sys_pread(fsp->fh->fd, data, n, offset);
549 END_PROFILE(syscall_pread);
551 if (result == -1 && errno == ESPIPE) {
552 /* Maintain the fiction that pipes can be seeked (sought?) on. */
553 result = SMB_VFS_READ(fsp, data, n);
557 #else /* HAVE_PREAD */
561 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
562 if (curr == -1 && errno == ESPIPE) {
563 /* Maintain the fiction that pipes can be seeked (sought?) on. */
564 result = SMB_VFS_READ(fsp, data, n);
569 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
574 result = SMB_VFS_READ(fsp, data, n);
577 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
580 #endif /* HAVE_PREAD */
585 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
589 START_PROFILE_BYTES(syscall_write, n);
590 result = sys_write(fsp->fh->fd, data, n);
591 END_PROFILE(syscall_write);
595 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
596 size_t n, off_t offset)
600 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
601 START_PROFILE_BYTES(syscall_pwrite, n);
602 result = sys_pwrite(fsp->fh->fd, data, n, offset);
603 END_PROFILE(syscall_pwrite);
605 if (result == -1 && errno == ESPIPE) {
606 /* Maintain the fiction that pipes can be sought on. */
607 result = SMB_VFS_WRITE(fsp, data, n);
610 #else /* HAVE_PWRITE */
614 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
619 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
623 result = SMB_VFS_WRITE(fsp, data, n);
626 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
629 #endif /* HAVE_PWRITE */
634 static void vfswrap_asys_finished(struct tevent_context *ev,
635 struct tevent_fd *fde,
636 uint16_t flags, void *p);
638 static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn)
643 if (conn->asys_ctx != NULL) {
646 ret = asys_context_init(&conn->asys_ctx, aio_pending_size);
648 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
652 fd = asys_signalfd(conn->asys_ctx);
654 set_blocking(fd, false);
656 conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, fd,
658 vfswrap_asys_finished,
660 if (conn->asys_fde == NULL) {
661 DEBUG(1, ("tevent_add_fd failed\n"));
662 asys_context_destroy(conn->asys_ctx);
663 conn->asys_ctx = NULL;
669 struct vfswrap_asys_state {
670 struct asys_context *asys_ctx;
671 struct tevent_req *req;
676 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
678 asys_cancel(s->asys_ctx, s->req);
682 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
684 struct tevent_context *ev,
685 struct files_struct *fsp,
687 size_t n, off_t offset)
689 struct tevent_req *req;
690 struct vfswrap_asys_state *state;
693 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
697 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
699 return tevent_req_post(req, ev);
701 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
704 ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
706 tevent_req_error(req, ret);
707 return tevent_req_post(req, ev);
709 talloc_set_destructor(state, vfswrap_asys_state_destructor);
714 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
716 struct tevent_context *ev,
717 struct files_struct *fsp,
719 size_t n, off_t offset)
721 struct tevent_req *req;
722 struct vfswrap_asys_state *state;
725 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
729 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
731 return tevent_req_post(req, ev);
733 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
736 ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
738 tevent_req_error(req, ret);
739 return tevent_req_post(req, ev);
741 talloc_set_destructor(state, vfswrap_asys_state_destructor);
746 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
748 struct tevent_context *ev,
749 struct files_struct *fsp)
751 struct tevent_req *req;
752 struct vfswrap_asys_state *state;
755 req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
759 if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) {
761 return tevent_req_post(req, ev);
763 state->asys_ctx = handle->conn->sconn->conn->asys_ctx;
766 ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
768 tevent_req_error(req, ret);
769 return tevent_req_post(req, ev);
771 talloc_set_destructor(state, vfswrap_asys_state_destructor);
776 static void vfswrap_asys_finished(struct tevent_context *ev,
777 struct tevent_fd *fde,
778 uint16_t flags, void *p)
780 struct asys_context *asys_ctx = (struct asys_context *)p;
781 struct tevent_req *req;
782 struct vfswrap_asys_state *state;
788 if ((flags & TEVENT_FD_READ) == 0) {
793 res = asys_result(asys_ctx, &ret, &err, &private_data);
794 if (res == EINTR || res == EAGAIN) {
798 if (res == EWOULDBLOCK) {
803 if (res == ECANCELED) {
808 DEBUG(1, ("asys_result returned %s\n", strerror(res)));
812 req = talloc_get_type_abort(private_data, struct tevent_req);
813 state = tevent_req_data(req, struct vfswrap_asys_state);
815 talloc_set_destructor(state, NULL);
819 tevent_req_defer_callback(req, ev);
820 tevent_req_done(req);
824 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
826 struct vfswrap_asys_state *state = tevent_req_data(
827 req, struct vfswrap_asys_state);
829 if (tevent_req_is_unix_error(req, err)) {
836 static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
838 struct vfswrap_asys_state *state = tevent_req_data(
839 req, struct vfswrap_asys_state);
841 if (tevent_req_is_unix_error(req, err)) {
848 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
852 START_PROFILE(syscall_lseek);
854 /* Cope with 'stat' file opens. */
855 if (fsp->fh->fd != -1)
856 result = lseek(fsp->fh->fd, offset, whence);
859 * We want to maintain the fiction that we can seek
860 * on a fifo for file system purposes. This allows
861 * people to set up UNIX fifo's that feed data to Windows
865 if((result == -1) && (errno == ESPIPE)) {
870 END_PROFILE(syscall_lseek);
874 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
875 off_t offset, size_t n)
879 START_PROFILE_BYTES(syscall_sendfile, n);
880 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
881 END_PROFILE(syscall_sendfile);
885 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
893 START_PROFILE_BYTES(syscall_recvfile, n);
894 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
895 END_PROFILE(syscall_recvfile);
899 static int vfswrap_rename(vfs_handle_struct *handle,
900 const struct smb_filename *smb_fname_src,
901 const struct smb_filename *smb_fname_dst)
905 START_PROFILE(syscall_rename);
907 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
912 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
915 END_PROFILE(syscall_rename);
919 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
924 START_PROFILE(syscall_fsync);
925 result = fsync(fsp->fh->fd);
926 END_PROFILE(syscall_fsync);
933 static int vfswrap_stat(vfs_handle_struct *handle,
934 struct smb_filename *smb_fname)
938 START_PROFILE(syscall_stat);
940 if (smb_fname->stream_name) {
945 result = sys_stat(smb_fname->base_name, &smb_fname->st,
946 lp_fake_dir_create_times(SNUM(handle->conn)));
948 END_PROFILE(syscall_stat);
952 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
956 START_PROFILE(syscall_fstat);
957 result = sys_fstat(fsp->fh->fd,
958 sbuf, lp_fake_dir_create_times(SNUM(handle->conn)));
959 END_PROFILE(syscall_fstat);
963 static int vfswrap_lstat(vfs_handle_struct *handle,
964 struct smb_filename *smb_fname)
968 START_PROFILE(syscall_lstat);
970 if (smb_fname->stream_name) {
975 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
976 lp_fake_dir_create_times(SNUM(handle->conn)));
978 END_PROFILE(syscall_lstat);
982 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
984 enum vfs_translate_direction direction,
988 return NT_STATUS_NONE_MAPPED;
992 * Implement the default fsctl operation.
994 static bool vfswrap_logged_ioctl_message = false;
996 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
997 struct files_struct *fsp,
1000 uint16_t req_flags, /* Needed for UNICODE ... */
1001 const uint8_t *_in_data,
1003 uint8_t **_out_data,
1004 uint32_t max_out_len,
1007 const char *in_data = (const char *)_in_data;
1008 char **out_data = (char **)_out_data;
1011 case FSCTL_SET_SPARSE:
1013 bool set_sparse = true;
1016 if (in_len >= 1 && in_data[0] == 0) {
1020 status = file_set_sparse(handle->conn, fsp, set_sparse);
1022 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1023 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1024 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1025 nt_errstr(status)));
1030 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1032 unsigned char objid[16];
1033 char *return_data = NULL;
1035 /* This should return the object-id on this file.
1036 * I think I'll make this be the inode+dev. JRA.
1039 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1040 fsp_fnum_dbg(fsp)));
1042 *out_len = (max_out_len >= 64) ? 64 : max_out_len;
1043 /* Hmmm, will this cause problems if less data asked for? */
1044 return_data = talloc_array(ctx, char, 64);
1045 if (return_data == NULL) {
1046 return NT_STATUS_NO_MEMORY;
1049 /* For backwards compatibility only store the dev/inode. */
1050 push_file_id_16(return_data, &fsp->file_id);
1051 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1052 push_file_id_16(return_data+32, &fsp->file_id);
1053 *out_data = return_data;
1054 return NT_STATUS_OK;
1057 case FSCTL_GET_REPARSE_POINT:
1059 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1060 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1061 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1062 return NT_STATUS_NOT_A_REPARSE_POINT;
1065 case FSCTL_SET_REPARSE_POINT:
1067 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1068 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1069 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1070 return NT_STATUS_NOT_A_REPARSE_POINT;
1073 case FSCTL_GET_SHADOW_COPY_DATA:
1076 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1077 * and return their volume names. If max_data_count is 16, then it is just
1078 * asking for the number of volumes and length of the combined names.
1080 * pdata is the data allocated by our caller, but that uses
1081 * total_data_count (which is 0 in our case) rather than max_data_count.
1082 * Allocate the correct amount and return the pointer to let
1083 * it be deallocated when we return.
1085 struct shadow_copy_data *shadow_data = NULL;
1086 bool labels = False;
1087 uint32 labels_data_count = 0;
1089 char *cur_pdata = NULL;
1091 if (max_out_len < 16) {
1092 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1094 return NT_STATUS_INVALID_PARAMETER;
1097 if (max_out_len > 16) {
1101 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1102 if (shadow_data == NULL) {
1103 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1104 return NT_STATUS_NO_MEMORY;
1108 * Call the VFS routine to actually do the work.
1110 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1111 TALLOC_FREE(shadow_data);
1112 if (errno == ENOSYS) {
1113 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n",
1114 fsp->conn->connectpath));
1115 return NT_STATUS_NOT_SUPPORTED;
1117 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n",
1118 fsp->conn->connectpath));
1119 return NT_STATUS_UNSUCCESSFUL;
1123 labels_data_count = (shadow_data->num_volumes * 2 *
1124 sizeof(SHADOW_COPY_LABEL)) + 2;
1129 *out_len = 12 + labels_data_count + 4;
1132 if (max_out_len < *out_len) {
1133 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1134 max_out_len, *out_len));
1135 TALLOC_FREE(shadow_data);
1136 return NT_STATUS_BUFFER_TOO_SMALL;
1139 cur_pdata = talloc_array(ctx, char, *out_len);
1140 if (cur_pdata == NULL) {
1141 TALLOC_FREE(shadow_data);
1142 return NT_STATUS_NO_MEMORY;
1145 *out_data = cur_pdata;
1147 /* num_volumes 4 bytes */
1148 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1151 /* num_labels 4 bytes */
1152 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1155 /* needed_data_count 4 bytes */
1156 SIVAL(cur_pdata, 8, labels_data_count + 4);
1160 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1161 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1162 if (labels && shadow_data->labels) {
1163 for (i=0; i<shadow_data->num_volumes; i++) {
1164 srvstr_push(cur_pdata, req_flags,
1165 cur_pdata, shadow_data->labels[i],
1166 2 * sizeof(SHADOW_COPY_LABEL),
1167 STR_UNICODE|STR_TERMINATE);
1168 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1169 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1173 TALLOC_FREE(shadow_data);
1175 return NT_STATUS_OK;
1178 case FSCTL_FIND_FILES_BY_SID:
1180 /* pretend this succeeded -
1182 * we have to send back a list with all files owned by this SID
1184 * but I have to check that --metze
1190 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1191 fsp_fnum_dbg(fsp)));
1194 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1195 return NT_STATUS_INVALID_PARAMETER;
1198 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1200 /* unknown 4 bytes: this is not the length of the sid :-( */
1201 /*unknown = IVAL(pdata,0);*/
1203 if (!sid_parse(in_data + 4, sid_len, &sid)) {
1204 return NT_STATUS_INVALID_PARAMETER;
1206 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1208 if (!sid_to_uid(&sid, &uid)) {
1209 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1210 sid_string_dbg(&sid),
1211 (unsigned long)sid_len));
1215 /* we can take a look at the find source :-)
1217 * find ./ -uid $uid -name '*' is what we need here
1220 * and send 4bytes len and then NULL terminated unicode strings
1223 * but I don't know how to deal with the paged results
1224 * (maybe we can hang the result anywhere in the fsp struct)
1226 * but I don't know how to deal with the paged results
1227 * (maybe we can hang the result anywhere in the fsp struct)
1229 * we don't send all files at once
1230 * and at the next we should *not* start from the beginning,
1231 * so we have to cache the result
1236 /* this works for now... */
1237 return NT_STATUS_OK;
1240 case FSCTL_QUERY_ALLOCATED_RANGES:
1242 /* FIXME: This is just a dummy reply, telling that all of the
1243 * file is allocated. MKS cp needs that.
1244 * Adding the real allocated ranges via FIEMAP on Linux
1245 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1246 * this FSCTL correct for sparse files.
1249 uint64_t offset, length;
1250 char *out_data_tmp = NULL;
1253 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1255 return NT_STATUS_INVALID_PARAMETER;
1258 if (max_out_len < 16) {
1259 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1261 return NT_STATUS_INVALID_PARAMETER;
1264 offset = BVAL(in_data,0);
1265 length = BVAL(in_data,8);
1267 if (offset + length < offset) {
1268 /* No 64-bit integer wrap. */
1269 return NT_STATUS_INVALID_PARAMETER;
1272 /* Shouldn't this be SMB_VFS_STAT ... ? */
1273 status = vfs_stat_fsp(fsp);
1274 if (!NT_STATUS_IS_OK(status)) {
1279 out_data_tmp = talloc_array(ctx, char, *out_len);
1280 if (out_data_tmp == NULL) {
1281 DEBUG(10, ("unable to allocate memory for response\n"));
1282 return NT_STATUS_NO_MEMORY;
1285 if (offset > fsp->fsp_name->st.st_ex_size ||
1286 fsp->fsp_name->st.st_ex_size == 0 ||
1288 memset(out_data_tmp, 0, *out_len);
1290 uint64_t end = offset + length;
1291 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1292 SBVAL(out_data_tmp, 0, 0);
1293 SBVAL(out_data_tmp, 8, end);
1296 *out_data = out_data_tmp;
1298 return NT_STATUS_OK;
1301 case FSCTL_IS_VOLUME_DIRTY:
1303 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1304 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1306 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1307 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1309 return NT_STATUS_INVALID_PARAMETER;
1314 * Only print once ... unfortunately there could be lots of
1315 * different FSCTLs that are called.
1317 if (!vfswrap_logged_ioctl_message) {
1318 vfswrap_logged_ioctl_message = true;
1319 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1320 __func__, function));
1324 return NT_STATUS_NOT_SUPPORTED;
1327 struct vfs_cc_state {
1332 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1333 TALLOC_CTX *mem_ctx,
1334 struct tevent_context *ev,
1335 struct files_struct *src_fsp,
1337 struct files_struct *dest_fsp,
1341 struct tevent_req *req;
1342 struct vfs_cc_state *vfs_cc_state;
1345 DEBUG(10, ("performing server side copy chunk of length %lu\n",
1346 (unsigned long)num));
1348 req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1353 status = vfs_stat_fsp(src_fsp);
1354 if (tevent_req_nterror(req, status)) {
1355 return tevent_req_post(req, ev);
1358 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1360 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1361 * If the SourceOffset or SourceOffset + Length extends beyond
1362 * the end of file, the server SHOULD<240> treat this as a
1363 * STATUS_END_OF_FILE error.
1365 * <240> Section 3.3.5.15.6: Windows servers will return
1366 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1368 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1369 return tevent_req_post(req, ev);
1372 /* could use 2.6.33+ sendfile here to do this in kernel */
1373 while (vfs_cc_state->copied < num) {
1375 off_t this_num = MIN(sizeof(vfs_cc_state->buf),
1376 num - vfs_cc_state->copied);
1378 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1381 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1382 return tevent_req_post(req, ev);
1384 if (ret != this_num) {
1385 /* zero tolerance for short reads */
1386 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1387 return tevent_req_post(req, ev);
1391 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1392 this_num, dest_off);
1394 tevent_req_nterror(req, map_nt_error_from_unix(errno));
1395 return tevent_req_post(req, ev);
1397 if (ret != this_num) {
1398 /* zero tolerance for short writes */
1399 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1400 return tevent_req_post(req, ev);
1404 vfs_cc_state->copied += this_num;
1407 tevent_req_done(req);
1408 return tevent_req_post(req, ev);
1411 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1412 struct tevent_req *req,
1415 struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1416 struct vfs_cc_state);
1419 if (tevent_req_is_nterror(req, &status)) {
1420 DEBUG(2, ("server side copy chunk failed: %s\n",
1421 nt_errstr(status)));
1423 tevent_req_received(req);
1427 *copied = vfs_cc_state->copied;
1428 DEBUG(10, ("server side copy chunk copied %lu\n",
1429 (unsigned long)*copied));
1430 tevent_req_received(req);
1432 return NT_STATUS_OK;
1435 /********************************************************************
1436 Given a stat buffer return the allocated size on disk, taking into
1437 account sparse files.
1438 ********************************************************************/
1439 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1440 struct files_struct *fsp,
1441 const SMB_STRUCT_STAT *sbuf)
1445 START_PROFILE(syscall_get_alloc_size);
1447 if(S_ISDIR(sbuf->st_ex_mode)) {
1452 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1453 /* The type of st_blocksize is blkcnt_t which *MUST* be
1454 signed (according to POSIX) and can be less than 64-bits.
1455 Ensure when we're converting to 64 bits wide we don't
1457 #if defined(SIZEOF_BLKCNT_T_8)
1458 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1459 #elif defined(SIZEOF_BLKCNT_T_4)
1461 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1462 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1465 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1468 result = get_file_size_stat(sbuf);
1471 if (fsp && fsp->initial_allocation_size)
1472 result = MAX(result,fsp->initial_allocation_size);
1474 result = smb_roundup(handle->conn, result);
1477 END_PROFILE(syscall_get_alloc_size);
1481 static int vfswrap_unlink(vfs_handle_struct *handle,
1482 const struct smb_filename *smb_fname)
1486 START_PROFILE(syscall_unlink);
1488 if (smb_fname->stream_name) {
1492 result = unlink(smb_fname->base_name);
1495 END_PROFILE(syscall_unlink);
1499 static int vfswrap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1503 START_PROFILE(syscall_chmod);
1506 * We need to do this due to the fact that the default POSIX ACL
1507 * chmod modifies the ACL *mask* for the group owner, not the
1508 * group owner bits directly. JRA.
1513 int saved_errno = errno; /* We might get ENOSYS */
1514 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
1515 END_PROFILE(syscall_chmod);
1518 /* Error - return the old errno. */
1519 errno = saved_errno;
1522 result = chmod(path, mode);
1523 END_PROFILE(syscall_chmod);
1527 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1531 START_PROFILE(syscall_fchmod);
1534 * We need to do this due to the fact that the default POSIX ACL
1535 * chmod modifies the ACL *mask* for the group owner, not the
1536 * group owner bits directly. JRA.
1540 int saved_errno = errno; /* We might get ENOSYS */
1541 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1542 END_PROFILE(syscall_fchmod);
1545 /* Error - return the old errno. */
1546 errno = saved_errno;
1549 #if defined(HAVE_FCHMOD)
1550 result = fchmod(fsp->fh->fd, mode);
1556 END_PROFILE(syscall_fchmod);
1560 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1564 START_PROFILE(syscall_chown);
1565 result = chown(path, uid, gid);
1566 END_PROFILE(syscall_chown);
1570 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1575 START_PROFILE(syscall_fchown);
1576 result = fchown(fsp->fh->fd, uid, gid);
1577 END_PROFILE(syscall_fchown);
1585 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
1589 START_PROFILE(syscall_lchown);
1590 result = lchown(path, uid, gid);
1591 END_PROFILE(syscall_lchown);
1595 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1599 START_PROFILE(syscall_chdir);
1600 result = chdir(path);
1601 END_PROFILE(syscall_chdir);
1605 static char *vfswrap_getwd(vfs_handle_struct *handle)
1609 START_PROFILE(syscall_getwd);
1610 result = sys_getwd();
1611 END_PROFILE(syscall_getwd);
1615 /*********************************************************************
1616 nsec timestamp resolution call. Convert down to whatever the underlying
1617 system will support.
1618 **********************************************************************/
1620 static int vfswrap_ntimes(vfs_handle_struct *handle,
1621 const struct smb_filename *smb_fname,
1622 struct smb_file_time *ft)
1626 START_PROFILE(syscall_ntimes);
1628 if (smb_fname->stream_name) {
1634 if (null_timespec(ft->atime)) {
1635 ft->atime= smb_fname->st.st_ex_atime;
1638 if (null_timespec(ft->mtime)) {
1639 ft->mtime = smb_fname->st.st_ex_mtime;
1642 if (!null_timespec(ft->create_time)) {
1643 set_create_timespec_ea(handle->conn,
1648 if ((timespec_compare(&ft->atime,
1649 &smb_fname->st.st_ex_atime) == 0) &&
1650 (timespec_compare(&ft->mtime,
1651 &smb_fname->st.st_ex_mtime) == 0)) {
1656 #if defined(HAVE_UTIMENSAT)
1658 struct timespec ts[2];
1661 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1663 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1665 if (!((result == -1) && (errno == ENOSYS))) {
1669 #if defined(HAVE_UTIMES)
1671 struct timeval tv[2];
1672 tv[0] = convert_timespec_to_timeval(ft->atime);
1673 tv[1] = convert_timespec_to_timeval(ft->mtime);
1674 result = utimes(smb_fname->base_name, tv);
1676 result = utimes(smb_fname->base_name, NULL);
1678 if (!((result == -1) && (errno == ENOSYS))) {
1682 #if defined(HAVE_UTIME)
1684 struct utimbuf times;
1685 times.actime = convert_timespec_to_time_t(ft->atime);
1686 times.modtime = convert_timespec_to_time_t(ft->mtime);
1687 result = utime(smb_fname->base_name, ×);
1689 result = utime(smb_fname->base_name, NULL);
1691 if (!((result == -1) && (errno == ENOSYS))) {
1699 END_PROFILE(syscall_ntimes);
1703 /*********************************************************************
1704 A version of ftruncate that will write the space on disk if strict
1706 **********************************************************************/
1708 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1710 off_t space_to_write;
1711 uint64_t space_avail;
1712 uint64_t bsize,dfree,dsize;
1715 SMB_STRUCT_STAT *pst;
1717 status = vfs_stat_fsp(fsp);
1718 if (!NT_STATUS_IS_OK(status)) {
1721 pst = &fsp->fsp_name->st;
1724 if (S_ISFIFO(pst->st_ex_mode))
1728 if (pst->st_ex_size == len)
1731 /* Shrink - just ftruncate. */
1732 if (pst->st_ex_size > len)
1733 return ftruncate(fsp->fh->fd, len);
1735 space_to_write = len - pst->st_ex_size;
1737 /* for allocation try fallocate first. This can fail on some
1738 platforms e.g. when the filesystem doesn't support it and no
1739 emulation is being done by the libc (like on AIX with JFS1). In that
1740 case we do our own emulation. fallocate implementations can
1741 return ENOTSUP or EINVAL in cases like that. */
1742 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
1743 pst->st_ex_size, space_to_write);
1744 if (ret == ENOSPC) {
1751 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
1752 "error %d. Falling back to slow manual allocation\n", ret));
1754 /* available disk space is enough or not? */
1755 space_avail = get_dfree_info(fsp->conn,
1756 fsp->fsp_name->base_name, false,
1757 &bsize,&dfree,&dsize);
1758 /* space_avail is 1k blocks */
1759 if (space_avail == (uint64_t)-1 ||
1760 ((uint64_t)space_to_write/1024 > space_avail) ) {
1765 /* Write out the real space on disk. */
1766 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
1775 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
1778 SMB_STRUCT_STAT *pst;
1782 START_PROFILE(syscall_ftruncate);
1784 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
1785 result = strict_allocate_ftruncate(handle, fsp, len);
1786 END_PROFILE(syscall_ftruncate);
1790 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1791 ftruncate if the system supports it. Then I discovered that
1792 you can have some filesystems that support ftruncate
1793 expansion and some that don't! On Linux fat can't do
1794 ftruncate extend but ext2 can. */
1796 result = ftruncate(fsp->fh->fd, len);
1800 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1801 extend a file with ftruncate. Provide alternate implementation
1804 /* Do an fstat to see if the file is longer than the requested
1805 size in which case the ftruncate above should have
1806 succeeded or shorter, in which case seek to len - 1 and
1807 write 1 byte of zero */
1808 status = vfs_stat_fsp(fsp);
1809 if (!NT_STATUS_IS_OK(status)) {
1812 pst = &fsp->fsp_name->st;
1815 if (S_ISFIFO(pst->st_ex_mode)) {
1821 if (pst->st_ex_size == len) {
1826 if (pst->st_ex_size > len) {
1827 /* the ftruncate should have worked */
1831 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
1839 END_PROFILE(syscall_ftruncate);
1843 static int vfswrap_fallocate(vfs_handle_struct *handle,
1845 enum vfs_fallocate_mode mode,
1851 START_PROFILE(syscall_fallocate);
1852 if (mode == VFS_FALLOCATE_EXTEND_SIZE) {
1853 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
1854 } else if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1855 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
1860 END_PROFILE(syscall_fallocate);
1864 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
1868 START_PROFILE(syscall_fcntl_lock);
1869 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
1870 END_PROFILE(syscall_fcntl_lock);
1874 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1875 uint32 share_mode, uint32 access_mask)
1877 START_PROFILE(syscall_kernel_flock);
1878 kernel_flock(fsp->fh->fd, share_mode, access_mask);
1879 END_PROFILE(syscall_kernel_flock);
1883 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1887 START_PROFILE(syscall_fcntl_getlock);
1888 result = fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1889 END_PROFILE(syscall_fcntl_getlock);
1893 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1898 START_PROFILE(syscall_linux_setlease);
1900 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1901 result = linux_setlease(fsp->fh->fd, leasetype);
1905 END_PROFILE(syscall_linux_setlease);
1909 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1913 START_PROFILE(syscall_symlink);
1914 result = symlink(oldpath, newpath);
1915 END_PROFILE(syscall_symlink);
1919 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
1923 START_PROFILE(syscall_readlink);
1924 result = readlink(path, buf, bufsiz);
1925 END_PROFILE(syscall_readlink);
1929 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
1933 START_PROFILE(syscall_link);
1934 result = link(oldpath, newpath);
1935 END_PROFILE(syscall_link);
1939 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
1943 START_PROFILE(syscall_mknod);
1944 result = sys_mknod(pathname, mode, dev);
1945 END_PROFILE(syscall_mknod);
1949 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
1953 START_PROFILE(syscall_realpath);
1954 #ifdef REALPATH_TAKES_NULL
1955 result = realpath(path, NULL);
1957 result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
1959 char *resolved_path = realpath(path, result);
1960 if (!resolved_path) {
1963 /* SMB_ASSERT(result == resolved_path) ? */
1964 result = resolved_path;
1968 END_PROFILE(syscall_realpath);
1972 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
1973 struct sys_notify_context *ctx,
1976 uint32_t *subdir_filter,
1977 void (*callback)(struct sys_notify_context *ctx,
1979 struct notify_event *ev),
1980 void *private_data, void *handle)
1983 * So far inotify is the only supported default notify mechanism. If
1984 * another platform like the the BSD's or a proprietary Unix comes
1985 * along and wants another default, we can play the same trick we
1986 * played with Posix ACLs.
1988 * Until that is the case, hard-code inotify here.
1991 if (lp_kernel_change_notify(vfs_handle->conn->params)) {
1992 return inotify_watch(ctx, path, filter, subdir_filter,
1993 callback, private_data, handle);
1997 * Do nothing, leave everything to notify_internal.c
1999 return NT_STATUS_OK;
2002 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2006 return chflags(path, flags);
2013 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2014 const SMB_STRUCT_STAT *sbuf)
2018 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2022 key.devid = sbuf->st_ex_dev;
2023 key.inode = sbuf->st_ex_ino;
2024 /* key.extid is unused by default. */
2029 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2030 struct files_struct *fsp,
2032 TALLOC_CTX *mem_ctx,
2033 unsigned int *pnum_streams,
2034 struct stream_struct **pstreams)
2036 SMB_STRUCT_STAT sbuf;
2037 struct stream_struct *tmp_streams = NULL;
2040 if ((fsp != NULL) && (fsp->is_directory)) {
2042 * No default streams on directories
2047 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2048 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2051 struct smb_filename smb_fname;
2053 ZERO_STRUCT(smb_fname);
2054 smb_fname.base_name = discard_const_p(char, fname);
2056 if (lp_posix_pathnames()) {
2057 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
2059 ret = SMB_VFS_STAT(handle->conn, &smb_fname);
2061 sbuf = smb_fname.st;
2065 return map_nt_error_from_unix(errno);
2068 if (S_ISDIR(sbuf.st_ex_mode)) {
2072 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2073 (*pnum_streams) + 1);
2074 if (tmp_streams == NULL) {
2075 return NT_STATUS_NO_MEMORY;
2077 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2078 if (tmp_streams[*pnum_streams].name == NULL) {
2079 return NT_STATUS_NO_MEMORY;
2081 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2082 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2085 *pstreams = tmp_streams;
2087 return NT_STATUS_OK;
2090 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2093 TALLOC_CTX *mem_ctx,
2097 * Don't fall back to get_real_filename so callers can differentiate
2098 * between a full directory scan and an actual case-insensitive stat.
2104 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2107 return handle->conn->connectpath;
2110 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2111 struct byte_range_lock *br_lck,
2112 struct lock_struct *plock,
2114 struct blocking_lock_record *blr)
2116 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2118 /* Note: blr is not used in the default implementation. */
2119 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2122 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2123 struct messaging_context *msg_ctx,
2124 struct byte_range_lock *br_lck,
2125 const struct lock_struct *plock)
2127 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2129 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2132 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2133 struct byte_range_lock *br_lck,
2134 struct lock_struct *plock,
2135 struct blocking_lock_record *blr)
2137 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2139 /* Note: blr is not used in the default implementation. */
2140 return brl_lock_cancel_default(br_lck, plock);
2143 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2145 struct lock_struct *plock)
2147 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2148 plock->lock_type == WRITE_LOCK);
2150 return strict_lock_default(fsp, plock);
2153 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2155 struct lock_struct *plock)
2157 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2158 plock->lock_type == WRITE_LOCK);
2160 strict_unlock_default(fsp, plock);
2163 /* NT ACL operations. */
2165 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2167 uint32 security_info,
2168 TALLOC_CTX *mem_ctx,
2169 struct security_descriptor **ppdesc)
2173 START_PROFILE(fget_nt_acl);
2174 result = posix_fget_nt_acl(fsp, security_info,
2176 END_PROFILE(fget_nt_acl);
2180 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2182 uint32 security_info,
2183 TALLOC_CTX *mem_ctx,
2184 struct security_descriptor **ppdesc)
2188 START_PROFILE(get_nt_acl);
2189 result = posix_get_nt_acl(handle->conn, name, security_info,
2191 END_PROFILE(get_nt_acl);
2195 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
2199 START_PROFILE(fset_nt_acl);
2200 result = set_nt_acl(fsp, security_info_sent, psd);
2201 END_PROFILE(fset_nt_acl);
2205 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2206 struct smb_filename *file,
2207 struct security_acl *sacl,
2208 uint32_t access_requested,
2209 uint32_t access_denied)
2211 return NT_STATUS_OK; /* Nothing to do here ... */
2214 static int vfswrap_chmod_acl(vfs_handle_struct *handle, const char *name, mode_t mode)
2222 START_PROFILE(chmod_acl);
2223 result = chmod_acl(handle->conn, name, mode);
2224 END_PROFILE(chmod_acl);
2229 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2237 START_PROFILE(fchmod_acl);
2238 result = fchmod_acl(fsp, mode);
2239 END_PROFILE(fchmod_acl);
2244 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2246 SMB_ACL_TYPE_T type,
2247 TALLOC_CTX *mem_ctx)
2249 return sys_acl_get_file(handle, path_p, type, mem_ctx);
2252 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2254 TALLOC_CTX *mem_ctx)
2256 return sys_acl_get_fd(handle, fsp, mem_ctx);
2259 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2261 return sys_acl_set_file(handle, name, acltype, theacl);
2264 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2266 return sys_acl_set_fd(handle, fsp, theacl);
2269 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2271 return sys_acl_delete_def_file(handle, path);
2274 /****************************************************************
2275 Extended attribute operations.
2276 *****************************************************************/
2278 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2280 return getxattr(path, name, value, size);
2283 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2285 return fgetxattr(fsp->fh->fd, name, value, size);
2288 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2290 return listxattr(path, list, size);
2293 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2295 return flistxattr(fsp->fh->fd, list, size);
2298 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2300 return removexattr(path, name);
2303 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2305 return fremovexattr(fsp->fh->fd, name);
2308 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2310 return setxattr(path, name, value, size, flags);
2313 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2315 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2318 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2323 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2324 const struct smb_filename *fname,
2325 SMB_STRUCT_STAT *sbuf)
2329 bool offline = false;
2331 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2335 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2336 #if defined(ENOTSUP)
2342 status = get_full_smb_filename(talloc_tos(), fname, &path);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 errno = map_errno_from_nt_status(status);
2348 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2355 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2356 const struct smb_filename *fname)
2358 /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2359 #if defined(ENOTSUP)
2365 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2366 struct files_struct *fsp,
2367 TALLOC_CTX *mem_ctx,
2370 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2373 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2374 struct files_struct *fsp,
2375 const DATA_BLOB old_cookie,
2376 TALLOC_CTX *mem_ctx,
2377 DATA_BLOB *new_cookie)
2379 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2383 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2384 struct smb_request *smb1req,
2385 struct smbXsrv_open *op,
2386 const DATA_BLOB old_cookie,
2387 TALLOC_CTX *mem_ctx,
2388 struct files_struct **fsp,
2389 DATA_BLOB *new_cookie)
2391 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2392 old_cookie, mem_ctx,
2396 static struct vfs_fn_pointers vfs_default_fns = {
2397 /* Disk operations */
2399 .connect_fn = vfswrap_connect,
2400 .disconnect_fn = vfswrap_disconnect,
2401 .disk_free_fn = vfswrap_disk_free,
2402 .get_quota_fn = vfswrap_get_quota,
2403 .set_quota_fn = vfswrap_set_quota,
2404 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2405 .statvfs_fn = vfswrap_statvfs,
2406 .fs_capabilities_fn = vfswrap_fs_capabilities,
2407 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2409 /* Directory operations */
2411 .opendir_fn = vfswrap_opendir,
2412 .fdopendir_fn = vfswrap_fdopendir,
2413 .readdir_fn = vfswrap_readdir,
2414 .seekdir_fn = vfswrap_seekdir,
2415 .telldir_fn = vfswrap_telldir,
2416 .rewind_dir_fn = vfswrap_rewinddir,
2417 .mkdir_fn = vfswrap_mkdir,
2418 .rmdir_fn = vfswrap_rmdir,
2419 .closedir_fn = vfswrap_closedir,
2420 .init_search_op_fn = vfswrap_init_search_op,
2422 /* File operations */
2424 .open_fn = vfswrap_open,
2425 .create_file_fn = vfswrap_create_file,
2426 .close_fn = vfswrap_close,
2427 .read_fn = vfswrap_read,
2428 .pread_fn = vfswrap_pread,
2429 .pread_send_fn = vfswrap_pread_send,
2430 .pread_recv_fn = vfswrap_asys_ssize_t_recv,
2431 .write_fn = vfswrap_write,
2432 .pwrite_fn = vfswrap_pwrite,
2433 .pwrite_send_fn = vfswrap_pwrite_send,
2434 .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2435 .lseek_fn = vfswrap_lseek,
2436 .sendfile_fn = vfswrap_sendfile,
2437 .recvfile_fn = vfswrap_recvfile,
2438 .rename_fn = vfswrap_rename,
2439 .fsync_fn = vfswrap_fsync,
2440 .fsync_send_fn = vfswrap_fsync_send,
2441 .fsync_recv_fn = vfswrap_asys_int_recv,
2442 .stat_fn = vfswrap_stat,
2443 .fstat_fn = vfswrap_fstat,
2444 .lstat_fn = vfswrap_lstat,
2445 .get_alloc_size_fn = vfswrap_get_alloc_size,
2446 .unlink_fn = vfswrap_unlink,
2447 .chmod_fn = vfswrap_chmod,
2448 .fchmod_fn = vfswrap_fchmod,
2449 .chown_fn = vfswrap_chown,
2450 .fchown_fn = vfswrap_fchown,
2451 .lchown_fn = vfswrap_lchown,
2452 .chdir_fn = vfswrap_chdir,
2453 .getwd_fn = vfswrap_getwd,
2454 .ntimes_fn = vfswrap_ntimes,
2455 .ftruncate_fn = vfswrap_ftruncate,
2456 .fallocate_fn = vfswrap_fallocate,
2457 .lock_fn = vfswrap_lock,
2458 .kernel_flock_fn = vfswrap_kernel_flock,
2459 .linux_setlease_fn = vfswrap_linux_setlease,
2460 .getlock_fn = vfswrap_getlock,
2461 .symlink_fn = vfswrap_symlink,
2462 .readlink_fn = vfswrap_readlink,
2463 .link_fn = vfswrap_link,
2464 .mknod_fn = vfswrap_mknod,
2465 .realpath_fn = vfswrap_realpath,
2466 .notify_watch_fn = vfswrap_notify_watch,
2467 .chflags_fn = vfswrap_chflags,
2468 .file_id_create_fn = vfswrap_file_id_create,
2469 .streaminfo_fn = vfswrap_streaminfo,
2470 .get_real_filename_fn = vfswrap_get_real_filename,
2471 .connectpath_fn = vfswrap_connectpath,
2472 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2473 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2474 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2475 .strict_lock_fn = vfswrap_strict_lock,
2476 .strict_unlock_fn = vfswrap_strict_unlock,
2477 .translate_name_fn = vfswrap_translate_name,
2478 .fsctl_fn = vfswrap_fsctl,
2479 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2480 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2482 /* NT ACL operations. */
2484 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2485 .get_nt_acl_fn = vfswrap_get_nt_acl,
2486 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2487 .audit_file_fn = vfswrap_audit_file,
2489 /* POSIX ACL operations. */
2491 .chmod_acl_fn = vfswrap_chmod_acl,
2492 .fchmod_acl_fn = vfswrap_fchmod_acl,
2494 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2495 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2496 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2497 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2498 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2499 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2500 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2502 /* EA operations. */
2503 .getxattr_fn = vfswrap_getxattr,
2504 .fgetxattr_fn = vfswrap_fgetxattr,
2505 .listxattr_fn = vfswrap_listxattr,
2506 .flistxattr_fn = vfswrap_flistxattr,
2507 .removexattr_fn = vfswrap_removexattr,
2508 .fremovexattr_fn = vfswrap_fremovexattr,
2509 .setxattr_fn = vfswrap_setxattr,
2510 .fsetxattr_fn = vfswrap_fsetxattr,
2512 /* aio operations */
2513 .aio_force_fn = vfswrap_aio_force,
2515 /* offline operations */
2516 .is_offline_fn = vfswrap_is_offline,
2517 .set_offline_fn = vfswrap_set_offline,
2519 /* durable handle operations */
2520 .durable_cookie_fn = vfswrap_durable_cookie,
2521 .durable_disconnect_fn = vfswrap_durable_disconnect,
2522 .durable_reconnect_fn = vfswrap_durable_reconnect,
2525 NTSTATUS vfs_default_init(void);
2526 NTSTATUS vfs_default_init(void)
2528 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2529 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);