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/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
39 #define DBGC_CLASS DBGC_VFS
41 /* Check for NULL pointer parameters in vfswrap_* functions */
43 /* We don't want to have NULL function pointers lying around. Someone
44 is sure to try and execute them. These stubs are used to prevent
47 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 return 0; /* Return >= 0 for success */
52 static void vfswrap_disconnect(vfs_handle_struct *handle)
58 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
59 const struct smb_filename *smb_fname,
64 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
72 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
73 const struct smb_filename *smb_fname,
74 enum SMB_QUOTA_TYPE qtype,
78 #ifdef HAVE_SYS_QUOTAS
81 START_PROFILE(syscall_get_quota);
82 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
83 END_PROFILE(syscall_get_quota);
91 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
93 #ifdef HAVE_SYS_QUOTAS
96 START_PROFILE(syscall_set_quota);
97 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
98 END_PROFILE(syscall_set_quota);
106 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
107 struct files_struct *fsp,
108 struct shadow_copy_data *shadow_copy_data,
112 return -1; /* Not implemented. */
115 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
116 const struct smb_filename *smb_fname,
117 vfs_statvfs_struct *statbuf)
119 return sys_statvfs(smb_fname->base_name, statbuf);
122 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
123 enum timestamp_set_resolution *p_ts_res)
125 connection_struct *conn = handle->conn;
126 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
127 struct smb_filename *smb_fname_cpath = NULL;
128 struct vfs_statvfs_struct statbuf;
131 ZERO_STRUCT(statbuf);
132 ret = sys_statvfs(conn->connectpath, &statbuf);
134 caps = statbuf.FsCapabilities;
137 *p_ts_res = TIMESTAMP_SET_SECONDS;
139 /* Work out what timestamp resolution we can
140 * use when setting a timestamp. */
142 smb_fname_cpath = synthetic_smb_fname(talloc_tos(), conn->connectpath,
144 if (smb_fname_cpath == NULL) {
148 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
150 TALLOC_FREE(smb_fname_cpath);
154 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
155 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
156 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
157 /* If any of the normal UNIX directory timestamps
158 * have a non-zero tv_nsec component assume
159 * we might be able to set sub-second timestamps.
160 * See what filetime set primitives we have.
162 #if defined(HAVE_UTIMENSAT)
163 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
164 #elif defined(HAVE_UTIMES)
165 /* utimes allows msec timestamps to be set. */
166 *p_ts_res = TIMESTAMP_SET_MSEC;
167 #elif defined(HAVE_UTIME)
168 /* utime only allows sec timestamps to be set. */
169 *p_ts_res = TIMESTAMP_SET_SECONDS;
172 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
174 "available on share %s, directory %s\n",
175 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
176 lp_servicename(talloc_tos(), conn->params->service),
177 conn->connectpath ));
179 TALLOC_FREE(smb_fname_cpath);
183 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
184 struct dfs_GetDFSReferral *r)
186 struct junction_map *junction = NULL;
188 bool self_referral = false;
189 char *pathnamep = NULL;
190 char *local_dfs_path = NULL;
193 uint16_t max_referral_level = r->in.req.max_referral_level;
196 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
199 /* get the junction entry */
200 if (r->in.req.servername == NULL) {
201 return NT_STATUS_NOT_FOUND;
205 * Trim pathname sent by client so it begins with only one backslash.
206 * Two backslashes confuse some dfs clients
209 local_dfs_path = talloc_strdup(r, r->in.req.servername);
210 if (local_dfs_path == NULL) {
211 return NT_STATUS_NO_MEMORY;
213 pathnamep = local_dfs_path;
214 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
215 IS_DIRECTORY_SEP(pathnamep[1])) {
219 junction = talloc_zero(r, struct junction_map);
220 if (junction == NULL) {
221 return NT_STATUS_NO_MEMORY;
224 /* The following call can change cwd. */
225 status = get_referred_path(r, pathnamep,
226 handle->conn->sconn->remote_address,
227 handle->conn->sconn->local_address,
228 !handle->conn->sconn->using_smb2,
229 junction, &consumedcnt, &self_referral);
230 if (!NT_STATUS_IS_OK(status)) {
231 vfs_ChDir(handle->conn, handle->conn->connectpath);
234 vfs_ChDir(handle->conn, handle->conn->connectpath);
236 if (!self_referral) {
237 pathnamep[consumedcnt] = '\0';
240 dbgtext("Path %s to alternate path(s):",
242 for (i=0; i < junction->referral_count; i++) {
244 junction->referral_list[i].alternate_path);
250 if (r->in.req.max_referral_level <= 2) {
251 max_referral_level = 2;
253 if (r->in.req.max_referral_level >= 3) {
254 max_referral_level = 3;
257 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
258 if (r->out.resp == NULL) {
259 return NT_STATUS_NO_MEMORY;
262 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
263 r->out.resp->nb_referrals = junction->referral_count;
265 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
267 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
270 r->out.resp->referral_entries = talloc_zero_array(r,
271 struct dfs_referral_type,
272 r->out.resp->nb_referrals);
273 if (r->out.resp->referral_entries == NULL) {
274 return NT_STATUS_NO_MEMORY;
277 switch (max_referral_level) {
279 for(i=0; i < junction->referral_count; i++) {
280 struct referral *ref = &junction->referral_list[i];
281 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
282 struct dfs_referral_type *t =
283 &r->out.resp->referral_entries[i];
284 struct dfs_referral_v2 *v2 = &t->referral.v2;
287 v2->size = VERSION2_REFERRAL_SIZE;
289 v2->server_type = DFS_SERVER_ROOT;
291 v2->server_type = DFS_SERVER_NON_ROOT;
294 v2->proximity = ref->proximity;
296 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
297 if (v2->DFS_path == NULL) {
298 return NT_STATUS_NO_MEMORY;
300 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
301 if (v2->DFS_alt_path == NULL) {
302 return NT_STATUS_NO_MEMORY;
304 v2->netw_address = talloc_strdup(mem_ctx,
305 ref->alternate_path);
306 if (v2->netw_address == NULL) {
307 return NT_STATUS_NO_MEMORY;
313 for(i=0; i < junction->referral_count; i++) {
314 struct referral *ref = &junction->referral_list[i];
315 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
316 struct dfs_referral_type *t =
317 &r->out.resp->referral_entries[i];
318 struct dfs_referral_v3 *v3 = &t->referral.v3;
319 struct dfs_normal_referral *r1 = &v3->referrals.r1;
322 v3->size = VERSION3_REFERRAL_SIZE;
324 v3->server_type = DFS_SERVER_ROOT;
326 v3->server_type = DFS_SERVER_NON_ROOT;
330 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
331 if (r1->DFS_path == NULL) {
332 return NT_STATUS_NO_MEMORY;
334 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
335 if (r1->DFS_alt_path == NULL) {
336 return NT_STATUS_NO_MEMORY;
338 r1->netw_address = talloc_strdup(mem_ctx,
339 ref->alternate_path);
340 if (r1->netw_address == NULL) {
341 return NT_STATUS_NO_MEMORY;
346 DEBUG(0,("Invalid dfs referral version: %d\n",
347 max_referral_level));
348 return NT_STATUS_INVALID_LEVEL;
352 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
358 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
360 const char *service_path,
363 return NT_STATUS_NOT_SUPPORTED;
366 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
368 const char *base_volume,
374 return NT_STATUS_NOT_SUPPORTED;
377 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
382 return NT_STATUS_NOT_SUPPORTED;
385 /* Directory operations */
387 static DIR *vfswrap_opendir(vfs_handle_struct *handle,
388 const struct smb_filename *smb_fname,
394 START_PROFILE(syscall_opendir);
395 result = opendir(smb_fname->base_name);
396 END_PROFILE(syscall_opendir);
400 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
407 START_PROFILE(syscall_fdopendir);
408 result = sys_fdopendir(fsp->fh->fd);
409 END_PROFILE(syscall_fdopendir);
414 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
416 SMB_STRUCT_STAT *sbuf)
418 struct dirent *result;
420 START_PROFILE(syscall_readdir);
421 result = readdir(dirp);
422 END_PROFILE(syscall_readdir);
424 /* Default Posix readdir() does not give us stat info.
425 * Set to invalid to indicate we didn't return this info. */
426 SET_STAT_INVALID(*sbuf);
427 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
428 if (result != NULL) {
429 /* See if we can efficiently return this. */
431 int flags = AT_SYMLINK_NOFOLLOW;
432 int ret = fstatat(dirfd(dirp),
437 * As this is an optimization,
438 * ignore it if we stat'ed a
439 * symlink. Make the caller
440 * do it again as we don't
441 * know if they wanted the link
442 * info, or its target info.
444 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
445 init_stat_ex_from_stat(sbuf,
447 lp_fake_directory_create_times(
448 SNUM(handle->conn)));
456 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
457 const struct smb_filename *fname,
459 struct readdir_attr_data **attr_data)
461 return NT_STATUS_NOT_SUPPORTED;
464 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
466 START_PROFILE(syscall_seekdir);
467 seekdir(dirp, offset);
468 END_PROFILE(syscall_seekdir);
471 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
474 START_PROFILE(syscall_telldir);
475 result = telldir(dirp);
476 END_PROFILE(syscall_telldir);
480 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
482 START_PROFILE(syscall_rewinddir);
484 END_PROFILE(syscall_rewinddir);
487 static int vfswrap_mkdir(vfs_handle_struct *handle,
488 const struct smb_filename *smb_fname,
492 bool has_dacl = False;
493 const char *path = smb_fname->base_name;
496 START_PROFILE(syscall_mkdir);
498 if (lp_inherit_acls(SNUM(handle->conn))
499 && parent_dirname(talloc_tos(), path, &parent, NULL)
500 && (has_dacl = directory_has_default_acl(handle->conn, parent))) {
501 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
506 result = mkdir(path, mode);
508 if (result == 0 && !has_dacl) {
510 * We need to do this as the default behavior of POSIX ACLs
511 * is to set the mask to be the requested group permission
512 * bits, not the group permission bits to be the requested
513 * group permission bits. This is not what we want, as it will
514 * mess up any inherited ACL bits that were set. JRA.
516 int saved_errno = errno; /* We may get ENOSYS */
517 if ((SMB_VFS_CHMOD_ACL(handle->conn, smb_fname, mode) == -1) &&
523 END_PROFILE(syscall_mkdir);
527 static int vfswrap_rmdir(vfs_handle_struct *handle,
528 const struct smb_filename *smb_fname)
532 START_PROFILE(syscall_rmdir);
533 result = rmdir(smb_fname->base_name);
534 END_PROFILE(syscall_rmdir);
538 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
542 START_PROFILE(syscall_closedir);
543 result = closedir(dirp);
544 END_PROFILE(syscall_closedir);
548 static void vfswrap_init_search_op(vfs_handle_struct *handle,
551 /* Default behavior is a NOOP */
554 /* File operations */
556 static int vfswrap_open(vfs_handle_struct *handle,
557 struct smb_filename *smb_fname,
558 files_struct *fsp, int flags, mode_t mode)
562 START_PROFILE(syscall_open);
564 if (smb_fname->stream_name) {
569 result = open(smb_fname->base_name, flags, mode);
571 END_PROFILE(syscall_open);
575 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
576 struct smb_request *req,
577 uint16_t root_dir_fid,
578 struct smb_filename *smb_fname,
579 uint32_t access_mask,
580 uint32_t share_access,
581 uint32_t create_disposition,
582 uint32_t create_options,
583 uint32_t file_attributes,
584 uint32_t oplock_request,
585 struct smb2_lease *lease,
586 uint64_t allocation_size,
587 uint32_t private_flags,
588 struct security_descriptor *sd,
589 struct ea_list *ea_list,
590 files_struct **result,
592 const struct smb2_create_blobs *in_context_blobs,
593 struct smb2_create_blobs *out_context_blobs)
595 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
596 access_mask, share_access,
597 create_disposition, create_options,
598 file_attributes, oplock_request, lease,
599 allocation_size, private_flags,
601 pinfo, in_context_blobs, out_context_blobs);
604 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
608 START_PROFILE(syscall_close);
609 result = fd_close_posix(fsp);
610 END_PROFILE(syscall_close);
614 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
618 START_PROFILE_BYTES(syscall_read, n);
619 result = sys_read(fsp->fh->fd, data, n);
620 END_PROFILE_BYTES(syscall_read);
624 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
625 size_t n, off_t offset)
629 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
630 START_PROFILE_BYTES(syscall_pread, n);
631 result = sys_pread(fsp->fh->fd, data, n, offset);
632 END_PROFILE_BYTES(syscall_pread);
634 if (result == -1 && errno == ESPIPE) {
635 /* Maintain the fiction that pipes can be seeked (sought?) on. */
636 result = SMB_VFS_READ(fsp, data, n);
640 #else /* HAVE_PREAD */
644 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
645 if (curr == -1 && errno == ESPIPE) {
646 /* Maintain the fiction that pipes can be seeked (sought?) on. */
647 result = SMB_VFS_READ(fsp, data, n);
652 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
657 result = SMB_VFS_READ(fsp, data, n);
660 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
663 #endif /* HAVE_PREAD */
668 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
672 START_PROFILE_BYTES(syscall_write, n);
673 result = sys_write(fsp->fh->fd, data, n);
674 END_PROFILE_BYTES(syscall_write);
678 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
679 size_t n, off_t offset)
683 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
684 START_PROFILE_BYTES(syscall_pwrite, n);
685 result = sys_pwrite(fsp->fh->fd, data, n, offset);
686 END_PROFILE_BYTES(syscall_pwrite);
688 if (result == -1 && errno == ESPIPE) {
689 /* Maintain the fiction that pipes can be sought on. */
690 result = SMB_VFS_WRITE(fsp, data, n);
693 #else /* HAVE_PWRITE */
697 curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
702 if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
706 result = SMB_VFS_WRITE(fsp, data, n);
709 SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
712 #endif /* HAVE_PWRITE */
717 static int vfswrap_init_pool(struct smbd_server_connection *conn)
721 if (conn->pool != NULL) {
725 ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
730 struct vfswrap_pread_state {
738 struct vfs_aio_state vfs_aio_state;
739 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
742 static void vfs_pread_do(void *private_data);
743 static void vfs_pread_done(struct tevent_req *subreq);
745 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
747 struct tevent_context *ev,
748 struct files_struct *fsp,
750 size_t n, off_t offset)
752 struct tevent_req *req, *subreq;
753 struct vfswrap_pread_state *state;
756 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
761 ret = vfswrap_init_pool(handle->conn->sconn);
762 if (tevent_req_error(req, ret)) {
763 return tevent_req_post(req, ev);
767 state->fd = fsp->fh->fd;
770 state->offset = offset;
772 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
773 state->profile_bytes, n);
774 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
776 subreq = pthreadpool_tevent_job_send(
777 state, ev, handle->conn->sconn->pool,
778 vfs_pread_do, state);
779 if (tevent_req_nomem(subreq, req)) {
780 return tevent_req_post(req, ev);
782 tevent_req_set_callback(subreq, vfs_pread_done, req);
787 static void vfs_pread_do(void *private_data)
789 struct vfswrap_pread_state *state = talloc_get_type_abort(
790 private_data, struct vfswrap_pread_state);
791 struct timespec start_time;
792 struct timespec end_time;
794 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
796 PROFILE_TIMESTAMP(&start_time);
799 state->ret = pread(state->fd, state->buf, state->count,
801 } while ((state->ret == -1) && (errno == EINTR));
805 PROFILE_TIMESTAMP(&end_time);
807 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
809 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
812 static void vfs_pread_done(struct tevent_req *subreq)
814 struct tevent_req *req = tevent_req_callback_data(
815 subreq, struct tevent_req);
817 struct vfswrap_pread_state *state = tevent_req_data(
818 req, struct vfswrap_pread_state);
822 ret = pthreadpool_tevent_job_recv(subreq);
824 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
825 if (tevent_req_error(req, ret)) {
829 tevent_req_done(req);
832 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
833 struct vfs_aio_state *vfs_aio_state)
835 struct vfswrap_pread_state *state = tevent_req_data(
836 req, struct vfswrap_pread_state);
838 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
842 *vfs_aio_state = state->vfs_aio_state;
846 struct vfswrap_pwrite_state {
854 struct vfs_aio_state vfs_aio_state;
855 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
858 static void vfs_pwrite_do(void *private_data);
859 static void vfs_pwrite_done(struct tevent_req *subreq);
861 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
863 struct tevent_context *ev,
864 struct files_struct *fsp,
866 size_t n, off_t offset)
868 struct tevent_req *req, *subreq;
869 struct vfswrap_pwrite_state *state;
872 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
877 ret = vfswrap_init_pool(handle->conn->sconn);
878 if (tevent_req_error(req, ret)) {
879 return tevent_req_post(req, ev);
883 state->fd = fsp->fh->fd;
886 state->offset = offset;
888 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
889 state->profile_bytes, n);
890 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
892 subreq = pthreadpool_tevent_job_send(
893 state, ev, handle->conn->sconn->pool,
894 vfs_pwrite_do, state);
895 if (tevent_req_nomem(subreq, req)) {
896 return tevent_req_post(req, ev);
898 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
903 static void vfs_pwrite_do(void *private_data)
905 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
906 private_data, struct vfswrap_pwrite_state);
907 struct timespec start_time;
908 struct timespec end_time;
910 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
912 PROFILE_TIMESTAMP(&start_time);
915 state->ret = pwrite(state->fd, state->buf, state->count,
917 } while ((state->ret == -1) && (errno == EINTR));
921 PROFILE_TIMESTAMP(&end_time);
923 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
925 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
928 static void vfs_pwrite_done(struct tevent_req *subreq)
930 struct tevent_req *req = tevent_req_callback_data(
931 subreq, struct tevent_req);
933 struct vfswrap_pwrite_state *state = tevent_req_data(
934 req, struct vfswrap_pwrite_state);
938 ret = pthreadpool_tevent_job_recv(subreq);
940 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
941 if (tevent_req_error(req, ret)) {
945 tevent_req_done(req);
948 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
949 struct vfs_aio_state *vfs_aio_state)
951 struct vfswrap_pwrite_state *state = tevent_req_data(
952 req, struct vfswrap_pwrite_state);
954 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
958 *vfs_aio_state = state->vfs_aio_state;
962 struct vfswrap_fsync_state {
967 struct vfs_aio_state vfs_aio_state;
968 SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
971 static void vfs_fsync_do(void *private_data);
972 static void vfs_fsync_done(struct tevent_req *subreq);
974 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
976 struct tevent_context *ev,
977 struct files_struct *fsp)
979 struct tevent_req *req, *subreq;
980 struct vfswrap_fsync_state *state;
983 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
988 ret = vfswrap_init_pool(handle->conn->sconn);
989 if (tevent_req_error(req, ret)) {
990 return tevent_req_post(req, ev);
994 state->fd = fsp->fh->fd;
996 SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
997 state->profile_basic);
999 subreq = pthreadpool_tevent_job_send(
1000 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1001 if (tevent_req_nomem(subreq, req)) {
1002 return tevent_req_post(req, ev);
1004 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1009 static void vfs_fsync_do(void *private_data)
1011 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1012 private_data, struct vfswrap_fsync_state);
1013 struct timespec start_time;
1014 struct timespec end_time;
1016 PROFILE_TIMESTAMP(&start_time);
1019 state->ret = fsync(state->fd);
1020 } while ((state->ret == -1) && (errno == EINTR));
1024 PROFILE_TIMESTAMP(&end_time);
1026 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1029 static void vfs_fsync_done(struct tevent_req *subreq)
1031 struct tevent_req *req = tevent_req_callback_data(
1032 subreq, struct tevent_req);
1034 struct vfswrap_fsync_state *state = tevent_req_data(
1035 req, struct vfswrap_fsync_state);
1039 ret = pthreadpool_tevent_job_recv(subreq);
1040 TALLOC_FREE(subreq);
1041 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1042 if (tevent_req_error(req, ret)) {
1046 tevent_req_done(req);
1049 static int vfswrap_fsync_recv(struct tevent_req *req,
1050 struct vfs_aio_state *vfs_aio_state)
1052 struct vfswrap_fsync_state *state = tevent_req_data(
1053 req, struct vfswrap_fsync_state);
1055 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1059 *vfs_aio_state = state->vfs_aio_state;
1063 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1067 START_PROFILE(syscall_lseek);
1069 /* Cope with 'stat' file opens. */
1070 if (fsp->fh->fd != -1)
1071 result = lseek(fsp->fh->fd, offset, whence);
1074 * We want to maintain the fiction that we can seek
1075 * on a fifo for file system purposes. This allows
1076 * people to set up UNIX fifo's that feed data to Windows
1077 * applications. JRA.
1080 if((result == -1) && (errno == ESPIPE)) {
1085 END_PROFILE(syscall_lseek);
1089 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1090 off_t offset, size_t n)
1094 START_PROFILE_BYTES(syscall_sendfile, n);
1095 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1096 END_PROFILE_BYTES(syscall_sendfile);
1100 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1102 files_struct *tofsp,
1108 START_PROFILE_BYTES(syscall_recvfile, n);
1109 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1110 END_PROFILE_BYTES(syscall_recvfile);
1114 static int vfswrap_rename(vfs_handle_struct *handle,
1115 const struct smb_filename *smb_fname_src,
1116 const struct smb_filename *smb_fname_dst)
1120 START_PROFILE(syscall_rename);
1122 if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1127 result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1130 END_PROFILE(syscall_rename);
1134 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1139 START_PROFILE(syscall_fsync);
1140 result = fsync(fsp->fh->fd);
1141 END_PROFILE(syscall_fsync);
1148 static int vfswrap_stat(vfs_handle_struct *handle,
1149 struct smb_filename *smb_fname)
1153 START_PROFILE(syscall_stat);
1155 if (smb_fname->stream_name) {
1160 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1161 lp_fake_directory_create_times(SNUM(handle->conn)));
1163 END_PROFILE(syscall_stat);
1167 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1171 START_PROFILE(syscall_fstat);
1172 result = sys_fstat(fsp->fh->fd,
1173 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1174 END_PROFILE(syscall_fstat);
1178 static int vfswrap_lstat(vfs_handle_struct *handle,
1179 struct smb_filename *smb_fname)
1183 START_PROFILE(syscall_lstat);
1185 if (smb_fname->stream_name) {
1190 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1191 lp_fake_directory_create_times(SNUM(handle->conn)));
1193 END_PROFILE(syscall_lstat);
1197 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1199 enum vfs_translate_direction direction,
1200 TALLOC_CTX *mem_ctx,
1203 return NT_STATUS_NONE_MAPPED;
1207 * Implement the default fsctl operation.
1209 static bool vfswrap_logged_ioctl_message = false;
1211 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1212 struct files_struct *fsp,
1215 uint16_t req_flags, /* Needed for UNICODE ... */
1216 const uint8_t *_in_data,
1218 uint8_t **_out_data,
1219 uint32_t max_out_len,
1222 const char *in_data = (const char *)_in_data;
1223 char **out_data = (char **)_out_data;
1227 case FSCTL_SET_SPARSE:
1229 bool set_sparse = true;
1231 if (in_len >= 1 && in_data[0] == 0) {
1235 status = file_set_sparse(handle->conn, fsp, set_sparse);
1237 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1238 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1239 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1240 nt_errstr(status)));
1245 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1247 unsigned char objid[16];
1248 char *return_data = NULL;
1250 /* This should return the object-id on this file.
1251 * I think I'll make this be the inode+dev. JRA.
1254 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1255 fsp_fnum_dbg(fsp)));
1257 *out_len = MIN(max_out_len, 64);
1259 /* Hmmm, will this cause problems if less data asked for? */
1260 return_data = talloc_array(ctx, char, 64);
1261 if (return_data == NULL) {
1262 return NT_STATUS_NO_MEMORY;
1265 /* For backwards compatibility only store the dev/inode. */
1266 push_file_id_16(return_data, &fsp->file_id);
1267 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1268 push_file_id_16(return_data+32, &fsp->file_id);
1269 memset(return_data+48, 0, 16);
1270 *out_data = return_data;
1271 return NT_STATUS_OK;
1274 case FSCTL_GET_REPARSE_POINT:
1276 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1277 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1278 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1279 return NT_STATUS_NOT_A_REPARSE_POINT;
1282 case FSCTL_SET_REPARSE_POINT:
1284 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1285 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1286 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1287 return NT_STATUS_NOT_A_REPARSE_POINT;
1290 case FSCTL_GET_SHADOW_COPY_DATA:
1293 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1294 * and return their volume names. If max_data_count is 16, then it is just
1295 * asking for the number of volumes and length of the combined names.
1297 * pdata is the data allocated by our caller, but that uses
1298 * total_data_count (which is 0 in our case) rather than max_data_count.
1299 * Allocate the correct amount and return the pointer to let
1300 * it be deallocated when we return.
1302 struct shadow_copy_data *shadow_data = NULL;
1303 bool labels = False;
1304 uint32_t labels_data_count = 0;
1306 char *cur_pdata = NULL;
1308 if (max_out_len < 16) {
1309 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1311 return NT_STATUS_INVALID_PARAMETER;
1314 if (max_out_len > 16) {
1318 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1319 if (shadow_data == NULL) {
1320 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1321 return NT_STATUS_NO_MEMORY;
1325 * Call the VFS routine to actually do the work.
1327 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1330 /* broken module didn't set errno on error */
1331 status = NT_STATUS_UNSUCCESSFUL;
1333 status = map_nt_error_from_unix(errno);
1334 if (NT_STATUS_EQUAL(status,
1335 NT_STATUS_NOT_SUPPORTED)) {
1339 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1340 "connectpath %s, failed - %s.\n",
1341 fsp->conn->connectpath,
1342 nt_errstr(status)));
1343 TALLOC_FREE(shadow_data);
1347 labels_data_count = (shadow_data->num_volumes * 2 *
1348 sizeof(SHADOW_COPY_LABEL)) + 2;
1353 *out_len = 12 + labels_data_count;
1356 if (max_out_len < *out_len) {
1357 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1358 max_out_len, *out_len));
1359 TALLOC_FREE(shadow_data);
1360 return NT_STATUS_BUFFER_TOO_SMALL;
1363 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1364 if (cur_pdata == NULL) {
1365 TALLOC_FREE(shadow_data);
1366 return NT_STATUS_NO_MEMORY;
1369 *out_data = cur_pdata;
1371 /* num_volumes 4 bytes */
1372 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1375 /* num_labels 4 bytes */
1376 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1379 /* needed_data_count 4 bytes */
1380 SIVAL(cur_pdata, 8, labels_data_count);
1384 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1385 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1386 if (labels && shadow_data->labels) {
1387 for (i=0; i<shadow_data->num_volumes; i++) {
1389 status = srvstr_push(cur_pdata, req_flags,
1390 cur_pdata, shadow_data->labels[i],
1391 2 * sizeof(SHADOW_COPY_LABEL),
1392 STR_UNICODE|STR_TERMINATE, &len);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 TALLOC_FREE(*out_data);
1395 TALLOC_FREE(shadow_data);
1398 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1399 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1403 TALLOC_FREE(shadow_data);
1405 return NT_STATUS_OK;
1408 case FSCTL_FIND_FILES_BY_SID:
1410 /* pretend this succeeded -
1412 * we have to send back a list with all files owned by this SID
1414 * but I have to check that --metze
1420 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1421 fsp_fnum_dbg(fsp)));
1424 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1425 return NT_STATUS_INVALID_PARAMETER;
1428 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1430 /* unknown 4 bytes: this is not the length of the sid :-( */
1431 /*unknown = IVAL(pdata,0);*/
1433 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1434 return NT_STATUS_INVALID_PARAMETER;
1436 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1438 if (!sid_to_uid(&sid, &uid)) {
1439 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1440 sid_string_dbg(&sid),
1441 (unsigned long)sid_len));
1445 /* we can take a look at the find source :-)
1447 * find ./ -uid $uid -name '*' is what we need here
1450 * and send 4bytes len and then NULL terminated unicode strings
1453 * but I don't know how to deal with the paged results
1454 * (maybe we can hang the result anywhere in the fsp struct)
1456 * but I don't know how to deal with the paged results
1457 * (maybe we can hang the result anywhere in the fsp struct)
1459 * we don't send all files at once
1460 * and at the next we should *not* start from the beginning,
1461 * so we have to cache the result
1466 /* this works for now... */
1467 return NT_STATUS_OK;
1470 case FSCTL_QUERY_ALLOCATED_RANGES:
1472 /* FIXME: This is just a dummy reply, telling that all of the
1473 * file is allocated. MKS cp needs that.
1474 * Adding the real allocated ranges via FIEMAP on Linux
1475 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1476 * this FSCTL correct for sparse files.
1478 uint64_t offset, length;
1479 char *out_data_tmp = NULL;
1482 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1484 return NT_STATUS_INVALID_PARAMETER;
1487 if (max_out_len < 16) {
1488 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1490 return NT_STATUS_INVALID_PARAMETER;
1493 offset = BVAL(in_data,0);
1494 length = BVAL(in_data,8);
1496 if (offset + length < offset) {
1497 /* No 64-bit integer wrap. */
1498 return NT_STATUS_INVALID_PARAMETER;
1501 /* Shouldn't this be SMB_VFS_STAT ... ? */
1502 status = vfs_stat_fsp(fsp);
1503 if (!NT_STATUS_IS_OK(status)) {
1508 out_data_tmp = talloc_array(ctx, char, *out_len);
1509 if (out_data_tmp == NULL) {
1510 DEBUG(10, ("unable to allocate memory for response\n"));
1511 return NT_STATUS_NO_MEMORY;
1514 if (offset > fsp->fsp_name->st.st_ex_size ||
1515 fsp->fsp_name->st.st_ex_size == 0 ||
1517 memset(out_data_tmp, 0, *out_len);
1519 uint64_t end = offset + length;
1520 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1521 SBVAL(out_data_tmp, 0, 0);
1522 SBVAL(out_data_tmp, 8, end);
1525 *out_data = out_data_tmp;
1527 return NT_STATUS_OK;
1530 case FSCTL_IS_VOLUME_DIRTY:
1532 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1533 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1535 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1536 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1538 return NT_STATUS_INVALID_PARAMETER;
1543 * Only print once ... unfortunately there could be lots of
1544 * different FSCTLs that are called.
1546 if (!vfswrap_logged_ioctl_message) {
1547 vfswrap_logged_ioctl_message = true;
1548 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1549 __func__, function));
1553 return NT_STATUS_NOT_SUPPORTED;
1556 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1557 const struct smb_filename *fname,
1558 SMB_STRUCT_STAT *sbuf);
1560 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1561 struct smb_filename *smb_fname,
1566 offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1568 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1571 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1574 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1575 struct files_struct *fsp,
1580 offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1582 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1585 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1588 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1589 const struct smb_filename *smb_fname,
1592 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1595 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1596 struct files_struct *fsp,
1599 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1602 struct vfs_cc_state {
1603 struct tevent_context *ev;
1605 bool read_lck_locked;
1606 struct lock_struct read_lck;
1607 bool write_lck_locked;
1608 struct lock_struct write_lck;
1609 struct files_struct *src_fsp;
1611 struct files_struct *dst_fsp;
1615 size_t next_io_size;
1619 static NTSTATUS copy_chunk_loop(struct tevent_req *req);
1621 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1622 TALLOC_CTX *mem_ctx,
1623 struct tevent_context *ev,
1624 struct files_struct *src_fsp,
1626 struct files_struct *dest_fsp,
1631 struct tevent_req *req;
1632 struct vfs_cc_state *state = NULL;
1633 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1636 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1638 req = tevent_req_create(mem_ctx, &state, struct vfs_cc_state);
1643 if (flags & ~VFS_COPY_CHUNK_FL_MASK_ALL) {
1644 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1645 return tevent_req_post(req, ev);
1648 if (flags & VFS_COPY_CHUNK_FL_MUST_CLONE) {
1649 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1650 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1651 return tevent_req_post(req, ev);
1654 *state = (struct vfs_cc_state) {
1658 .dst_fsp = dest_fsp,
1659 .dst_off = dest_off,
1661 .remaining = to_copy,
1664 state->buf = talloc_array(state, uint8_t, num);
1665 if (tevent_req_nomem(state->buf, req)) {
1666 return tevent_req_post(req, ev);
1669 status = vfs_stat_fsp(src_fsp);
1670 if (tevent_req_nterror(req, status)) {
1671 return tevent_req_post(req, ev);
1674 if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1676 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1677 * If the SourceOffset or SourceOffset + Length extends beyond
1678 * the end of file, the server SHOULD<240> treat this as a
1679 * STATUS_END_OF_FILE error.
1681 * <240> Section 3.3.5.15.6: Windows servers will return
1682 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1684 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1685 return tevent_req_post(req, ev);
1688 if (src_fsp->op == NULL) {
1689 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1690 return tevent_req_post(req, ev);
1693 if (dest_fsp->op == NULL) {
1694 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1695 return tevent_req_post(req, ev);
1698 status = copy_chunk_loop(req);
1699 if (!NT_STATUS_IS_OK(status)) {
1700 tevent_req_nterror(req, status);
1701 return tevent_req_post(req, ev);
1707 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq);
1709 static NTSTATUS copy_chunk_loop(struct tevent_req *req)
1711 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1712 struct tevent_req *subreq = NULL;
1715 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1717 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1718 init_strict_lock_struct(state->src_fsp,
1719 state->src_fsp->op->global->open_persistent_id,
1721 state->next_io_size,
1725 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1729 return NT_STATUS_FILE_LOCK_CONFLICT;
1733 subreq = SMB_VFS_PREAD_SEND(state,
1734 state->src_fsp->conn->sconn->ev_ctx,
1737 state->next_io_size,
1739 if (subreq == NULL) {
1740 return NT_STATUS_NO_MEMORY;
1742 tevent_req_set_callback(subreq, vfswrap_copy_chunk_read_done, req);
1744 return NT_STATUS_OK;
1747 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq);
1749 static void vfswrap_copy_chunk_read_done(struct tevent_req *subreq)
1751 struct tevent_req *req = tevent_req_callback_data(
1752 subreq, struct tevent_req);
1753 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1754 struct vfs_aio_state aio_state;
1758 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1759 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1762 ZERO_STRUCT(state->read_lck);
1765 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1766 TALLOC_FREE(subreq);
1768 DBG_ERR("read failed: %s\n", strerror(errno));
1769 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1772 if (nread != state->next_io_size) {
1773 DBG_ERR("Short read, only %zd of %zu\n",
1774 nread, state->next_io_size);
1775 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1779 state->src_off += nread;
1781 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1782 init_strict_lock_struct(state->dst_fsp,
1783 state->dst_fsp->op->global->open_persistent_id,
1785 state->next_io_size,
1789 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1793 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1798 subreq = SMB_VFS_PWRITE_SEND(state,
1802 state->next_io_size,
1804 if (subreq == NULL) {
1805 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1808 tevent_req_set_callback(subreq, vfswrap_copy_chunk_write_done, req);
1811 static void vfswrap_copy_chunk_write_done(struct tevent_req *subreq)
1813 struct tevent_req *req = tevent_req_callback_data(
1814 subreq, struct tevent_req);
1815 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1816 struct vfs_aio_state aio_state;
1820 if (!(state->flags & VFS_COPY_CHUNK_FL_IGNORE_LOCKS)) {
1821 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1824 ZERO_STRUCT(state->write_lck);
1827 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1828 TALLOC_FREE(subreq);
1829 if (nwritten == -1) {
1830 DBG_ERR("write failed: %s\n", strerror(errno));
1831 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1834 if (nwritten != state->next_io_size) {
1835 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1836 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1840 state->dst_off += nwritten;
1842 if (state->remaining < nwritten) {
1843 /* Paranoia check */
1844 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1847 state->remaining -= nwritten;
1848 if (state->remaining == 0) {
1849 tevent_req_done(req);
1853 status = copy_chunk_loop(req);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 tevent_req_nterror(req, status);
1862 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1863 struct tevent_req *req,
1866 struct vfs_cc_state *state = tevent_req_data(req, struct vfs_cc_state);
1869 if (tevent_req_is_nterror(req, &status)) {
1870 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1872 tevent_req_received(req);
1876 *copied = state->to_copy;
1877 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1878 tevent_req_received(req);
1880 return NT_STATUS_OK;
1883 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1884 TALLOC_CTX *mem_ctx,
1885 struct files_struct *fsp,
1886 struct smb_filename *smb_fname,
1887 uint16_t *_compression_fmt)
1889 return NT_STATUS_INVALID_DEVICE_REQUEST;
1892 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1893 TALLOC_CTX *mem_ctx,
1894 struct files_struct *fsp,
1895 uint16_t compression_fmt)
1897 return NT_STATUS_INVALID_DEVICE_REQUEST;
1900 /********************************************************************
1901 Given a stat buffer return the allocated size on disk, taking into
1902 account sparse files.
1903 ********************************************************************/
1904 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1905 struct files_struct *fsp,
1906 const SMB_STRUCT_STAT *sbuf)
1910 START_PROFILE(syscall_get_alloc_size);
1912 if(S_ISDIR(sbuf->st_ex_mode)) {
1917 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1918 /* The type of st_blocksize is blkcnt_t which *MUST* be
1919 signed (according to POSIX) and can be less than 64-bits.
1920 Ensure when we're converting to 64 bits wide we don't
1922 #if defined(SIZEOF_BLKCNT_T_8)
1923 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1924 #elif defined(SIZEOF_BLKCNT_T_4)
1926 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1927 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1930 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1934 * Some file systems do not allocate a block for very
1935 * small files. But for non-empty file should report a
1939 uint64_t filesize = get_file_size_stat(sbuf);
1941 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1945 result = get_file_size_stat(sbuf);
1948 if (fsp && fsp->initial_allocation_size)
1949 result = MAX(result,fsp->initial_allocation_size);
1951 result = smb_roundup(handle->conn, result);
1954 END_PROFILE(syscall_get_alloc_size);
1958 static int vfswrap_unlink(vfs_handle_struct *handle,
1959 const struct smb_filename *smb_fname)
1963 START_PROFILE(syscall_unlink);
1965 if (smb_fname->stream_name) {
1969 result = unlink(smb_fname->base_name);
1972 END_PROFILE(syscall_unlink);
1976 static int vfswrap_chmod(vfs_handle_struct *handle,
1977 const struct smb_filename *smb_fname,
1982 START_PROFILE(syscall_chmod);
1985 * We need to do this due to the fact that the default POSIX ACL
1986 * chmod modifies the ACL *mask* for the group owner, not the
1987 * group owner bits directly. JRA.
1992 int saved_errno = errno; /* We might get ENOSYS */
1993 result = SMB_VFS_CHMOD_ACL(handle->conn,
1997 END_PROFILE(syscall_chmod);
2000 /* Error - return the old errno. */
2001 errno = saved_errno;
2004 result = chmod(smb_fname->base_name, mode);
2005 END_PROFILE(syscall_chmod);
2009 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2013 START_PROFILE(syscall_fchmod);
2016 * We need to do this due to the fact that the default POSIX ACL
2017 * chmod modifies the ACL *mask* for the group owner, not the
2018 * group owner bits directly. JRA.
2022 int saved_errno = errno; /* We might get ENOSYS */
2023 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2024 END_PROFILE(syscall_fchmod);
2027 /* Error - return the old errno. */
2028 errno = saved_errno;
2031 #if defined(HAVE_FCHMOD)
2032 result = fchmod(fsp->fh->fd, mode);
2038 END_PROFILE(syscall_fchmod);
2042 static int vfswrap_chown(vfs_handle_struct *handle,
2043 const struct smb_filename *smb_fname,
2049 START_PROFILE(syscall_chown);
2050 result = chown(smb_fname->base_name, uid, gid);
2051 END_PROFILE(syscall_chown);
2055 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2060 START_PROFILE(syscall_fchown);
2061 result = fchown(fsp->fh->fd, uid, gid);
2062 END_PROFILE(syscall_fchown);
2070 static int vfswrap_lchown(vfs_handle_struct *handle,
2071 const struct smb_filename *smb_fname,
2077 START_PROFILE(syscall_lchown);
2078 result = lchown(smb_fname->base_name, uid, gid);
2079 END_PROFILE(syscall_lchown);
2083 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
2087 START_PROFILE(syscall_chdir);
2088 result = chdir(path);
2089 END_PROFILE(syscall_chdir);
2093 static char *vfswrap_getwd(vfs_handle_struct *handle)
2097 START_PROFILE(syscall_getwd);
2098 result = sys_getwd();
2099 END_PROFILE(syscall_getwd);
2103 /*********************************************************************
2104 nsec timestamp resolution call. Convert down to whatever the underlying
2105 system will support.
2106 **********************************************************************/
2108 static int vfswrap_ntimes(vfs_handle_struct *handle,
2109 const struct smb_filename *smb_fname,
2110 struct smb_file_time *ft)
2114 START_PROFILE(syscall_ntimes);
2116 if (smb_fname->stream_name) {
2122 if (null_timespec(ft->atime)) {
2123 ft->atime= smb_fname->st.st_ex_atime;
2126 if (null_timespec(ft->mtime)) {
2127 ft->mtime = smb_fname->st.st_ex_mtime;
2130 if (!null_timespec(ft->create_time)) {
2131 set_create_timespec_ea(handle->conn,
2136 if ((timespec_compare(&ft->atime,
2137 &smb_fname->st.st_ex_atime) == 0) &&
2138 (timespec_compare(&ft->mtime,
2139 &smb_fname->st.st_ex_mtime) == 0)) {
2144 #if defined(HAVE_UTIMENSAT)
2146 struct timespec ts[2];
2149 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2151 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2153 if (!((result == -1) && (errno == ENOSYS))) {
2157 #if defined(HAVE_UTIMES)
2159 struct timeval tv[2];
2160 tv[0] = convert_timespec_to_timeval(ft->atime);
2161 tv[1] = convert_timespec_to_timeval(ft->mtime);
2162 result = utimes(smb_fname->base_name, tv);
2164 result = utimes(smb_fname->base_name, NULL);
2166 if (!((result == -1) && (errno == ENOSYS))) {
2170 #if defined(HAVE_UTIME)
2172 struct utimbuf times;
2173 times.actime = convert_timespec_to_time_t(ft->atime);
2174 times.modtime = convert_timespec_to_time_t(ft->mtime);
2175 result = utime(smb_fname->base_name, ×);
2177 result = utime(smb_fname->base_name, NULL);
2179 if (!((result == -1) && (errno == ENOSYS))) {
2187 END_PROFILE(syscall_ntimes);
2191 /*********************************************************************
2192 A version of ftruncate that will write the space on disk if strict
2194 **********************************************************************/
2196 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2198 off_t space_to_write;
2199 uint64_t space_avail;
2200 uint64_t bsize,dfree,dsize;
2203 SMB_STRUCT_STAT *pst;
2205 status = vfs_stat_fsp(fsp);
2206 if (!NT_STATUS_IS_OK(status)) {
2209 pst = &fsp->fsp_name->st;
2212 if (S_ISFIFO(pst->st_ex_mode))
2216 if (pst->st_ex_size == len)
2219 /* Shrink - just ftruncate. */
2220 if (pst->st_ex_size > len)
2221 return ftruncate(fsp->fh->fd, len);
2223 space_to_write = len - pst->st_ex_size;
2225 /* for allocation try fallocate first. This can fail on some
2226 platforms e.g. when the filesystem doesn't support it and no
2227 emulation is being done by the libc (like on AIX with JFS1). In that
2228 case we do our own emulation. fallocate implementations can
2229 return ENOTSUP or EINVAL in cases like that. */
2230 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2231 if (ret == -1 && errno == ENOSPC) {
2237 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2238 "error %d. Falling back to slow manual allocation\n", errno));
2240 /* available disk space is enough or not? */
2242 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2243 /* space_avail is 1k blocks */
2244 if (space_avail == (uint64_t)-1 ||
2245 ((uint64_t)space_to_write/1024 > space_avail) ) {
2250 /* Write out the real space on disk. */
2251 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2259 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2262 SMB_STRUCT_STAT *pst;
2266 START_PROFILE(syscall_ftruncate);
2268 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2269 result = strict_allocate_ftruncate(handle, fsp, len);
2270 END_PROFILE(syscall_ftruncate);
2274 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2275 ftruncate if the system supports it. Then I discovered that
2276 you can have some filesystems that support ftruncate
2277 expansion and some that don't! On Linux fat can't do
2278 ftruncate extend but ext2 can. */
2280 result = ftruncate(fsp->fh->fd, len);
2282 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2283 extend a file with ftruncate. Provide alternate implementation
2286 /* Do an fstat to see if the file is longer than the requested
2287 size in which case the ftruncate above should have
2288 succeeded or shorter, in which case seek to len - 1 and
2289 write 1 byte of zero */
2290 status = vfs_stat_fsp(fsp);
2291 if (!NT_STATUS_IS_OK(status)) {
2295 /* We need to update the files_struct after successful ftruncate */
2300 pst = &fsp->fsp_name->st;
2303 if (S_ISFIFO(pst->st_ex_mode)) {
2309 if (pst->st_ex_size == len) {
2314 if (pst->st_ex_size > len) {
2315 /* the ftruncate should have worked */
2319 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2327 END_PROFILE(syscall_ftruncate);
2331 static int vfswrap_fallocate(vfs_handle_struct *handle,
2339 START_PROFILE(syscall_fallocate);
2341 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2343 * posix_fallocate returns 0 on success, errno on error
2344 * and doesn't set errno. Make it behave like fallocate()
2345 * which returns -1, and sets errno on failure.
2352 /* sys_fallocate handles filtering of unsupported mode flags */
2353 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2355 END_PROFILE(syscall_fallocate);
2359 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2363 START_PROFILE(syscall_fcntl_lock);
2365 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2367 "force process locks",
2369 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2372 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2373 END_PROFILE(syscall_fcntl_lock);
2377 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2378 uint32_t share_mode, uint32_t access_mask)
2380 START_PROFILE(syscall_kernel_flock);
2381 kernel_flock(fsp->fh->fd, share_mode, access_mask);
2382 END_PROFILE(syscall_kernel_flock);
2386 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2391 START_PROFILE(syscall_fcntl_getlock);
2393 if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2395 "force process locks",
2397 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2400 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2401 END_PROFILE(syscall_fcntl_getlock);
2405 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2410 START_PROFILE(syscall_linux_setlease);
2412 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2413 result = linux_setlease(fsp->fh->fd, leasetype);
2417 END_PROFILE(syscall_linux_setlease);
2421 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2425 START_PROFILE(syscall_symlink);
2426 result = symlink(oldpath, newpath);
2427 END_PROFILE(syscall_symlink);
2431 static int vfswrap_readlink(vfs_handle_struct *handle,
2432 const struct smb_filename *smb_fname,
2438 START_PROFILE(syscall_readlink);
2439 result = readlink(smb_fname->base_name, buf, bufsiz);
2440 END_PROFILE(syscall_readlink);
2444 static int vfswrap_link(vfs_handle_struct *handle,
2445 const struct smb_filename *old_smb_fname,
2446 const struct smb_filename *new_smb_fname)
2450 START_PROFILE(syscall_link);
2451 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2452 END_PROFILE(syscall_link);
2456 static int vfswrap_mknod(vfs_handle_struct *handle,
2457 const struct smb_filename *smb_fname,
2463 START_PROFILE(syscall_mknod);
2464 result = sys_mknod(smb_fname->base_name, mode, dev);
2465 END_PROFILE(syscall_mknod);
2469 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2473 START_PROFILE(syscall_realpath);
2474 result = sys_realpath(path);
2475 END_PROFILE(syscall_realpath);
2479 static int vfswrap_chflags(vfs_handle_struct *handle,
2480 const struct smb_filename *smb_fname,
2484 return chflags(smb_fname->base_name, flags);
2491 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2492 const SMB_STRUCT_STAT *sbuf)
2496 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2500 key.devid = sbuf->st_ex_dev;
2501 key.inode = sbuf->st_ex_ino;
2502 /* key.extid is unused by default. */
2507 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2508 struct files_struct *fsp,
2509 const struct smb_filename *smb_fname,
2510 TALLOC_CTX *mem_ctx,
2511 unsigned int *pnum_streams,
2512 struct stream_struct **pstreams)
2514 SMB_STRUCT_STAT sbuf;
2515 struct stream_struct *tmp_streams = NULL;
2518 if ((fsp != NULL) && (fsp->is_directory)) {
2520 * No default streams on directories
2525 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2526 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2529 struct smb_filename smb_fname_cp;
2531 ZERO_STRUCT(smb_fname_cp);
2532 smb_fname_cp.base_name = discard_const_p(char,
2533 smb_fname->base_name);
2534 smb_fname_cp.flags = smb_fname->flags;
2536 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2537 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2539 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2541 sbuf = smb_fname_cp.st;
2545 return map_nt_error_from_unix(errno);
2548 if (S_ISDIR(sbuf.st_ex_mode)) {
2552 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2553 (*pnum_streams) + 1);
2554 if (tmp_streams == NULL) {
2555 return NT_STATUS_NO_MEMORY;
2557 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2558 if (tmp_streams[*pnum_streams].name == NULL) {
2559 return NT_STATUS_NO_MEMORY;
2561 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2562 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2565 *pstreams = tmp_streams;
2567 return NT_STATUS_OK;
2570 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2573 TALLOC_CTX *mem_ctx,
2577 * Don't fall back to get_real_filename so callers can differentiate
2578 * between a full directory scan and an actual case-insensitive stat.
2584 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2587 return handle->conn->connectpath;
2590 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2591 struct byte_range_lock *br_lck,
2592 struct lock_struct *plock,
2595 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2597 /* Note: blr is not used in the default implementation. */
2598 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2601 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2602 struct messaging_context *msg_ctx,
2603 struct byte_range_lock *br_lck,
2604 const struct lock_struct *plock)
2606 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2608 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2611 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2612 struct byte_range_lock *br_lck,
2613 struct lock_struct *plock)
2615 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2617 /* Note: blr is not used in the default implementation. */
2618 return brl_lock_cancel_default(br_lck, plock);
2621 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2623 struct lock_struct *plock)
2625 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2626 plock->lock_type == WRITE_LOCK);
2628 return strict_lock_default(fsp, plock);
2631 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2633 struct lock_struct *plock)
2635 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2636 plock->lock_type == WRITE_LOCK);
2638 strict_unlock_default(fsp, plock);
2641 /* NT ACL operations. */
2643 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2645 uint32_t security_info,
2646 TALLOC_CTX *mem_ctx,
2647 struct security_descriptor **ppdesc)
2651 START_PROFILE(fget_nt_acl);
2652 result = posix_fget_nt_acl(fsp, security_info,
2654 END_PROFILE(fget_nt_acl);
2658 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2659 const struct smb_filename *smb_fname,
2660 uint32_t security_info,
2661 TALLOC_CTX *mem_ctx,
2662 struct security_descriptor **ppdesc)
2666 START_PROFILE(get_nt_acl);
2667 result = posix_get_nt_acl(handle->conn,
2672 END_PROFILE(get_nt_acl);
2676 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2680 START_PROFILE(fset_nt_acl);
2681 result = set_nt_acl(fsp, security_info_sent, psd);
2682 END_PROFILE(fset_nt_acl);
2686 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2687 struct smb_filename *file,
2688 struct security_acl *sacl,
2689 uint32_t access_requested,
2690 uint32_t access_denied)
2692 return NT_STATUS_OK; /* Nothing to do here ... */
2695 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2696 const struct smb_filename *smb_fname,
2705 START_PROFILE(chmod_acl);
2706 result = chmod_acl(handle->conn, smb_fname, mode);
2707 END_PROFILE(chmod_acl);
2712 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2720 START_PROFILE(fchmod_acl);
2721 result = fchmod_acl(fsp, mode);
2722 END_PROFILE(fchmod_acl);
2727 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2728 const struct smb_filename *smb_fname,
2729 SMB_ACL_TYPE_T type,
2730 TALLOC_CTX *mem_ctx)
2732 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2735 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2737 TALLOC_CTX *mem_ctx)
2739 return sys_acl_get_fd(handle, fsp, mem_ctx);
2742 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2743 const struct smb_filename *smb_fname,
2744 SMB_ACL_TYPE_T acltype,
2747 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2750 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2752 return sys_acl_set_fd(handle, fsp, theacl);
2755 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2756 const struct smb_filename *smb_fname)
2758 return sys_acl_delete_def_file(handle, smb_fname);
2761 /****************************************************************
2762 Extended attribute operations.
2763 *****************************************************************/
2765 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2766 const struct smb_filename *smb_fname,
2771 return getxattr(smb_fname->base_name, name, value, size);
2774 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2776 return fgetxattr(fsp->fh->fd, name, value, size);
2779 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2780 const struct smb_filename *smb_fname,
2784 return listxattr(smb_fname->base_name, list, size);
2787 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2789 return flistxattr(fsp->fh->fd, list, size);
2792 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2793 const struct smb_filename *smb_fname,
2796 return removexattr(smb_fname->base_name, name);
2799 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2801 return fremovexattr(fsp->fh->fd, name);
2804 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2805 const struct smb_filename *smb_fname,
2811 return setxattr(smb_fname->base_name, name, value, size, flags);
2814 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2816 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2819 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2824 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2825 const struct smb_filename *fname,
2826 SMB_STRUCT_STAT *sbuf)
2830 bool offline = false;
2832 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2836 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2837 #if defined(ENOTSUP)
2843 status = get_full_smb_filename(talloc_tos(), fname, &path);
2844 if (!NT_STATUS_IS_OK(status)) {
2845 errno = map_errno_from_nt_status(status);
2849 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2856 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2857 struct files_struct *fsp,
2858 TALLOC_CTX *mem_ctx,
2861 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2864 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2865 struct files_struct *fsp,
2866 const DATA_BLOB old_cookie,
2867 TALLOC_CTX *mem_ctx,
2868 DATA_BLOB *new_cookie)
2870 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2874 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2875 struct smb_request *smb1req,
2876 struct smbXsrv_open *op,
2877 const DATA_BLOB old_cookie,
2878 TALLOC_CTX *mem_ctx,
2879 struct files_struct **fsp,
2880 DATA_BLOB *new_cookie)
2882 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2883 old_cookie, mem_ctx,
2887 static struct vfs_fn_pointers vfs_default_fns = {
2888 /* Disk operations */
2890 .connect_fn = vfswrap_connect,
2891 .disconnect_fn = vfswrap_disconnect,
2892 .disk_free_fn = vfswrap_disk_free,
2893 .get_quota_fn = vfswrap_get_quota,
2894 .set_quota_fn = vfswrap_set_quota,
2895 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2896 .statvfs_fn = vfswrap_statvfs,
2897 .fs_capabilities_fn = vfswrap_fs_capabilities,
2898 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2899 .snap_check_path_fn = vfswrap_snap_check_path,
2900 .snap_create_fn = vfswrap_snap_create,
2901 .snap_delete_fn = vfswrap_snap_delete,
2903 /* Directory operations */
2905 .opendir_fn = vfswrap_opendir,
2906 .fdopendir_fn = vfswrap_fdopendir,
2907 .readdir_fn = vfswrap_readdir,
2908 .readdir_attr_fn = vfswrap_readdir_attr,
2909 .seekdir_fn = vfswrap_seekdir,
2910 .telldir_fn = vfswrap_telldir,
2911 .rewind_dir_fn = vfswrap_rewinddir,
2912 .mkdir_fn = vfswrap_mkdir,
2913 .rmdir_fn = vfswrap_rmdir,
2914 .closedir_fn = vfswrap_closedir,
2915 .init_search_op_fn = vfswrap_init_search_op,
2917 /* File operations */
2919 .open_fn = vfswrap_open,
2920 .create_file_fn = vfswrap_create_file,
2921 .close_fn = vfswrap_close,
2922 .read_fn = vfswrap_read,
2923 .pread_fn = vfswrap_pread,
2924 .pread_send_fn = vfswrap_pread_send,
2925 .pread_recv_fn = vfswrap_pread_recv,
2926 .write_fn = vfswrap_write,
2927 .pwrite_fn = vfswrap_pwrite,
2928 .pwrite_send_fn = vfswrap_pwrite_send,
2929 .pwrite_recv_fn = vfswrap_pwrite_recv,
2930 .lseek_fn = vfswrap_lseek,
2931 .sendfile_fn = vfswrap_sendfile,
2932 .recvfile_fn = vfswrap_recvfile,
2933 .rename_fn = vfswrap_rename,
2934 .fsync_fn = vfswrap_fsync,
2935 .fsync_send_fn = vfswrap_fsync_send,
2936 .fsync_recv_fn = vfswrap_fsync_recv,
2937 .stat_fn = vfswrap_stat,
2938 .fstat_fn = vfswrap_fstat,
2939 .lstat_fn = vfswrap_lstat,
2940 .get_alloc_size_fn = vfswrap_get_alloc_size,
2941 .unlink_fn = vfswrap_unlink,
2942 .chmod_fn = vfswrap_chmod,
2943 .fchmod_fn = vfswrap_fchmod,
2944 .chown_fn = vfswrap_chown,
2945 .fchown_fn = vfswrap_fchown,
2946 .lchown_fn = vfswrap_lchown,
2947 .chdir_fn = vfswrap_chdir,
2948 .getwd_fn = vfswrap_getwd,
2949 .ntimes_fn = vfswrap_ntimes,
2950 .ftruncate_fn = vfswrap_ftruncate,
2951 .fallocate_fn = vfswrap_fallocate,
2952 .lock_fn = vfswrap_lock,
2953 .kernel_flock_fn = vfswrap_kernel_flock,
2954 .linux_setlease_fn = vfswrap_linux_setlease,
2955 .getlock_fn = vfswrap_getlock,
2956 .symlink_fn = vfswrap_symlink,
2957 .readlink_fn = vfswrap_readlink,
2958 .link_fn = vfswrap_link,
2959 .mknod_fn = vfswrap_mknod,
2960 .realpath_fn = vfswrap_realpath,
2961 .chflags_fn = vfswrap_chflags,
2962 .file_id_create_fn = vfswrap_file_id_create,
2963 .streaminfo_fn = vfswrap_streaminfo,
2964 .get_real_filename_fn = vfswrap_get_real_filename,
2965 .connectpath_fn = vfswrap_connectpath,
2966 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2967 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2968 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2969 .strict_lock_fn = vfswrap_strict_lock,
2970 .strict_unlock_fn = vfswrap_strict_unlock,
2971 .translate_name_fn = vfswrap_translate_name,
2972 .fsctl_fn = vfswrap_fsctl,
2973 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2974 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2975 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2976 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2977 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2978 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2979 .get_compression_fn = vfswrap_get_compression,
2980 .set_compression_fn = vfswrap_set_compression,
2982 /* NT ACL operations. */
2984 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2985 .get_nt_acl_fn = vfswrap_get_nt_acl,
2986 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2987 .audit_file_fn = vfswrap_audit_file,
2989 /* POSIX ACL operations. */
2991 .chmod_acl_fn = vfswrap_chmod_acl,
2992 .fchmod_acl_fn = vfswrap_fchmod_acl,
2994 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2995 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2996 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2997 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2998 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2999 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3000 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3002 /* EA operations. */
3003 .getxattr_fn = vfswrap_getxattr,
3004 .fgetxattr_fn = vfswrap_fgetxattr,
3005 .listxattr_fn = vfswrap_listxattr,
3006 .flistxattr_fn = vfswrap_flistxattr,
3007 .removexattr_fn = vfswrap_removexattr,
3008 .fremovexattr_fn = vfswrap_fremovexattr,
3009 .setxattr_fn = vfswrap_setxattr,
3010 .fsetxattr_fn = vfswrap_fsetxattr,
3012 /* aio operations */
3013 .aio_force_fn = vfswrap_aio_force,
3015 /* durable handle operations */
3016 .durable_cookie_fn = vfswrap_durable_cookie,
3017 .durable_disconnect_fn = vfswrap_durable_disconnect,
3018 .durable_reconnect_fn = vfswrap_durable_reconnect,
3021 NTSTATUS vfs_default_init(TALLOC_CTX *);
3022 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3024 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3025 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);