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, const char *path, char *buf, size_t bufsiz)
2435 START_PROFILE(syscall_readlink);
2436 result = readlink(path, buf, bufsiz);
2437 END_PROFILE(syscall_readlink);
2441 static int vfswrap_link(vfs_handle_struct *handle,
2442 const struct smb_filename *old_smb_fname,
2443 const struct smb_filename *new_smb_fname)
2447 START_PROFILE(syscall_link);
2448 result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2449 END_PROFILE(syscall_link);
2453 static int vfswrap_mknod(vfs_handle_struct *handle,
2454 const struct smb_filename *smb_fname,
2460 START_PROFILE(syscall_mknod);
2461 result = sys_mknod(smb_fname->base_name, mode, dev);
2462 END_PROFILE(syscall_mknod);
2466 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2470 START_PROFILE(syscall_realpath);
2471 result = sys_realpath(path);
2472 END_PROFILE(syscall_realpath);
2476 static int vfswrap_chflags(vfs_handle_struct *handle,
2477 const struct smb_filename *smb_fname,
2481 return chflags(smb_fname->base_name, flags);
2488 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2489 const SMB_STRUCT_STAT *sbuf)
2493 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2497 key.devid = sbuf->st_ex_dev;
2498 key.inode = sbuf->st_ex_ino;
2499 /* key.extid is unused by default. */
2504 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2505 struct files_struct *fsp,
2506 const struct smb_filename *smb_fname,
2507 TALLOC_CTX *mem_ctx,
2508 unsigned int *pnum_streams,
2509 struct stream_struct **pstreams)
2511 SMB_STRUCT_STAT sbuf;
2512 struct stream_struct *tmp_streams = NULL;
2515 if ((fsp != NULL) && (fsp->is_directory)) {
2517 * No default streams on directories
2522 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2523 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2526 struct smb_filename smb_fname_cp;
2528 ZERO_STRUCT(smb_fname_cp);
2529 smb_fname_cp.base_name = discard_const_p(char,
2530 smb_fname->base_name);
2531 smb_fname_cp.flags = smb_fname->flags;
2533 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2534 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2536 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2538 sbuf = smb_fname_cp.st;
2542 return map_nt_error_from_unix(errno);
2545 if (S_ISDIR(sbuf.st_ex_mode)) {
2549 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2550 (*pnum_streams) + 1);
2551 if (tmp_streams == NULL) {
2552 return NT_STATUS_NO_MEMORY;
2554 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2555 if (tmp_streams[*pnum_streams].name == NULL) {
2556 return NT_STATUS_NO_MEMORY;
2558 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2559 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2562 *pstreams = tmp_streams;
2564 return NT_STATUS_OK;
2567 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2570 TALLOC_CTX *mem_ctx,
2574 * Don't fall back to get_real_filename so callers can differentiate
2575 * between a full directory scan and an actual case-insensitive stat.
2581 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2584 return handle->conn->connectpath;
2587 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2588 struct byte_range_lock *br_lck,
2589 struct lock_struct *plock,
2592 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2594 /* Note: blr is not used in the default implementation. */
2595 return brl_lock_windows_default(br_lck, plock, blocking_lock);
2598 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2599 struct messaging_context *msg_ctx,
2600 struct byte_range_lock *br_lck,
2601 const struct lock_struct *plock)
2603 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2605 return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2608 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2609 struct byte_range_lock *br_lck,
2610 struct lock_struct *plock)
2612 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2614 /* Note: blr is not used in the default implementation. */
2615 return brl_lock_cancel_default(br_lck, plock);
2618 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2620 struct lock_struct *plock)
2622 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2623 plock->lock_type == WRITE_LOCK);
2625 return strict_lock_default(fsp, plock);
2628 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2630 struct lock_struct *plock)
2632 SMB_ASSERT(plock->lock_type == READ_LOCK ||
2633 plock->lock_type == WRITE_LOCK);
2635 strict_unlock_default(fsp, plock);
2638 /* NT ACL operations. */
2640 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2642 uint32_t security_info,
2643 TALLOC_CTX *mem_ctx,
2644 struct security_descriptor **ppdesc)
2648 START_PROFILE(fget_nt_acl);
2649 result = posix_fget_nt_acl(fsp, security_info,
2651 END_PROFILE(fget_nt_acl);
2655 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2656 const struct smb_filename *smb_fname,
2657 uint32_t security_info,
2658 TALLOC_CTX *mem_ctx,
2659 struct security_descriptor **ppdesc)
2663 START_PROFILE(get_nt_acl);
2664 result = posix_get_nt_acl(handle->conn,
2669 END_PROFILE(get_nt_acl);
2673 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2677 START_PROFILE(fset_nt_acl);
2678 result = set_nt_acl(fsp, security_info_sent, psd);
2679 END_PROFILE(fset_nt_acl);
2683 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2684 struct smb_filename *file,
2685 struct security_acl *sacl,
2686 uint32_t access_requested,
2687 uint32_t access_denied)
2689 return NT_STATUS_OK; /* Nothing to do here ... */
2692 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2693 const struct smb_filename *smb_fname,
2702 START_PROFILE(chmod_acl);
2703 result = chmod_acl(handle->conn, smb_fname, mode);
2704 END_PROFILE(chmod_acl);
2709 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2717 START_PROFILE(fchmod_acl);
2718 result = fchmod_acl(fsp, mode);
2719 END_PROFILE(fchmod_acl);
2724 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2725 const struct smb_filename *smb_fname,
2726 SMB_ACL_TYPE_T type,
2727 TALLOC_CTX *mem_ctx)
2729 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2732 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2734 TALLOC_CTX *mem_ctx)
2736 return sys_acl_get_fd(handle, fsp, mem_ctx);
2739 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2740 const struct smb_filename *smb_fname,
2741 SMB_ACL_TYPE_T acltype,
2744 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2747 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2749 return sys_acl_set_fd(handle, fsp, theacl);
2752 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2753 const struct smb_filename *smb_fname)
2755 return sys_acl_delete_def_file(handle, smb_fname);
2758 /****************************************************************
2759 Extended attribute operations.
2760 *****************************************************************/
2762 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2763 const struct smb_filename *smb_fname,
2768 return getxattr(smb_fname->base_name, name, value, size);
2771 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2773 return fgetxattr(fsp->fh->fd, name, value, size);
2776 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2777 const struct smb_filename *smb_fname,
2781 return listxattr(smb_fname->base_name, list, size);
2784 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2786 return flistxattr(fsp->fh->fd, list, size);
2789 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2790 const struct smb_filename *smb_fname,
2793 return removexattr(smb_fname->base_name, name);
2796 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2798 return fremovexattr(fsp->fh->fd, name);
2801 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2802 const struct smb_filename *smb_fname,
2808 return setxattr(smb_fname->base_name, name, value, size, flags);
2811 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2813 return fsetxattr(fsp->fh->fd, name, value, size, flags);
2816 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2821 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2822 const struct smb_filename *fname,
2823 SMB_STRUCT_STAT *sbuf)
2827 bool offline = false;
2829 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2833 if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2834 #if defined(ENOTSUP)
2840 status = get_full_smb_filename(talloc_tos(), fname, &path);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 errno = map_errno_from_nt_status(status);
2846 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2853 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2854 struct files_struct *fsp,
2855 TALLOC_CTX *mem_ctx,
2858 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2861 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2862 struct files_struct *fsp,
2863 const DATA_BLOB old_cookie,
2864 TALLOC_CTX *mem_ctx,
2865 DATA_BLOB *new_cookie)
2867 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2871 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2872 struct smb_request *smb1req,
2873 struct smbXsrv_open *op,
2874 const DATA_BLOB old_cookie,
2875 TALLOC_CTX *mem_ctx,
2876 struct files_struct **fsp,
2877 DATA_BLOB *new_cookie)
2879 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2880 old_cookie, mem_ctx,
2884 static struct vfs_fn_pointers vfs_default_fns = {
2885 /* Disk operations */
2887 .connect_fn = vfswrap_connect,
2888 .disconnect_fn = vfswrap_disconnect,
2889 .disk_free_fn = vfswrap_disk_free,
2890 .get_quota_fn = vfswrap_get_quota,
2891 .set_quota_fn = vfswrap_set_quota,
2892 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2893 .statvfs_fn = vfswrap_statvfs,
2894 .fs_capabilities_fn = vfswrap_fs_capabilities,
2895 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2896 .snap_check_path_fn = vfswrap_snap_check_path,
2897 .snap_create_fn = vfswrap_snap_create,
2898 .snap_delete_fn = vfswrap_snap_delete,
2900 /* Directory operations */
2902 .opendir_fn = vfswrap_opendir,
2903 .fdopendir_fn = vfswrap_fdopendir,
2904 .readdir_fn = vfswrap_readdir,
2905 .readdir_attr_fn = vfswrap_readdir_attr,
2906 .seekdir_fn = vfswrap_seekdir,
2907 .telldir_fn = vfswrap_telldir,
2908 .rewind_dir_fn = vfswrap_rewinddir,
2909 .mkdir_fn = vfswrap_mkdir,
2910 .rmdir_fn = vfswrap_rmdir,
2911 .closedir_fn = vfswrap_closedir,
2912 .init_search_op_fn = vfswrap_init_search_op,
2914 /* File operations */
2916 .open_fn = vfswrap_open,
2917 .create_file_fn = vfswrap_create_file,
2918 .close_fn = vfswrap_close,
2919 .read_fn = vfswrap_read,
2920 .pread_fn = vfswrap_pread,
2921 .pread_send_fn = vfswrap_pread_send,
2922 .pread_recv_fn = vfswrap_pread_recv,
2923 .write_fn = vfswrap_write,
2924 .pwrite_fn = vfswrap_pwrite,
2925 .pwrite_send_fn = vfswrap_pwrite_send,
2926 .pwrite_recv_fn = vfswrap_pwrite_recv,
2927 .lseek_fn = vfswrap_lseek,
2928 .sendfile_fn = vfswrap_sendfile,
2929 .recvfile_fn = vfswrap_recvfile,
2930 .rename_fn = vfswrap_rename,
2931 .fsync_fn = vfswrap_fsync,
2932 .fsync_send_fn = vfswrap_fsync_send,
2933 .fsync_recv_fn = vfswrap_fsync_recv,
2934 .stat_fn = vfswrap_stat,
2935 .fstat_fn = vfswrap_fstat,
2936 .lstat_fn = vfswrap_lstat,
2937 .get_alloc_size_fn = vfswrap_get_alloc_size,
2938 .unlink_fn = vfswrap_unlink,
2939 .chmod_fn = vfswrap_chmod,
2940 .fchmod_fn = vfswrap_fchmod,
2941 .chown_fn = vfswrap_chown,
2942 .fchown_fn = vfswrap_fchown,
2943 .lchown_fn = vfswrap_lchown,
2944 .chdir_fn = vfswrap_chdir,
2945 .getwd_fn = vfswrap_getwd,
2946 .ntimes_fn = vfswrap_ntimes,
2947 .ftruncate_fn = vfswrap_ftruncate,
2948 .fallocate_fn = vfswrap_fallocate,
2949 .lock_fn = vfswrap_lock,
2950 .kernel_flock_fn = vfswrap_kernel_flock,
2951 .linux_setlease_fn = vfswrap_linux_setlease,
2952 .getlock_fn = vfswrap_getlock,
2953 .symlink_fn = vfswrap_symlink,
2954 .readlink_fn = vfswrap_readlink,
2955 .link_fn = vfswrap_link,
2956 .mknod_fn = vfswrap_mknod,
2957 .realpath_fn = vfswrap_realpath,
2958 .chflags_fn = vfswrap_chflags,
2959 .file_id_create_fn = vfswrap_file_id_create,
2960 .streaminfo_fn = vfswrap_streaminfo,
2961 .get_real_filename_fn = vfswrap_get_real_filename,
2962 .connectpath_fn = vfswrap_connectpath,
2963 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2964 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2965 .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2966 .strict_lock_fn = vfswrap_strict_lock,
2967 .strict_unlock_fn = vfswrap_strict_unlock,
2968 .translate_name_fn = vfswrap_translate_name,
2969 .fsctl_fn = vfswrap_fsctl,
2970 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2971 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2972 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2973 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2974 .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2975 .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2976 .get_compression_fn = vfswrap_get_compression,
2977 .set_compression_fn = vfswrap_set_compression,
2979 /* NT ACL operations. */
2981 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2982 .get_nt_acl_fn = vfswrap_get_nt_acl,
2983 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2984 .audit_file_fn = vfswrap_audit_file,
2986 /* POSIX ACL operations. */
2988 .chmod_acl_fn = vfswrap_chmod_acl,
2989 .fchmod_acl_fn = vfswrap_fchmod_acl,
2991 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2992 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2993 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2994 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2995 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2996 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2997 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2999 /* EA operations. */
3000 .getxattr_fn = vfswrap_getxattr,
3001 .fgetxattr_fn = vfswrap_fgetxattr,
3002 .listxattr_fn = vfswrap_listxattr,
3003 .flistxattr_fn = vfswrap_flistxattr,
3004 .removexattr_fn = vfswrap_removexattr,
3005 .fremovexattr_fn = vfswrap_fremovexattr,
3006 .setxattr_fn = vfswrap_setxattr,
3007 .fsetxattr_fn = vfswrap_fsetxattr,
3009 /* aio operations */
3010 .aio_force_fn = vfswrap_aio_force,
3012 /* durable handle operations */
3013 .durable_cookie_fn = vfswrap_durable_cookie,
3014 .durable_disconnect_fn = vfswrap_durable_disconnect,
3015 .durable_reconnect_fn = vfswrap_durable_reconnect,
3018 NTSTATUS vfs_default_init(TALLOC_CTX *);
3019 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3021 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3022 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);