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"
37 #include "offload_token.h"
40 #define DBGC_CLASS DBGC_VFS
42 /* Check for NULL pointer parameters in vfswrap_* functions */
44 /* We don't want to have NULL function pointers lying around. Someone
45 is sure to try and execute them. These stubs are used to prevent
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
50 return 0; /* Return >= 0 for success */
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60 const struct smb_filename *smb_fname,
65 if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74 const struct smb_filename *smb_fname,
75 enum SMB_QUOTA_TYPE qtype,
79 #ifdef HAVE_SYS_QUOTAS
82 START_PROFILE(syscall_get_quota);
83 result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84 END_PROFILE(syscall_get_quota);
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
94 #ifdef HAVE_SYS_QUOTAS
97 START_PROFILE(syscall_set_quota);
98 result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99 END_PROFILE(syscall_set_quota);
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108 struct files_struct *fsp,
109 struct shadow_copy_data *shadow_copy_data,
113 return -1; /* Not implemented. */
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117 const struct smb_filename *smb_fname,
118 vfs_statvfs_struct *statbuf)
120 return sys_statvfs(smb_fname->base_name, statbuf);
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124 enum timestamp_set_resolution *p_ts_res)
126 const struct loadparm_substitution *lp_sub =
127 loadparm_s3_global_substitution();
128 connection_struct *conn = handle->conn;
129 uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
130 struct smb_filename *smb_fname_cpath = NULL;
131 struct vfs_statvfs_struct statbuf;
134 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
140 if (smb_fname_cpath == NULL) {
144 ZERO_STRUCT(statbuf);
145 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
147 caps = statbuf.FsCapabilities;
150 *p_ts_res = TIMESTAMP_SET_SECONDS;
152 /* Work out what timestamp resolution we can
153 * use when setting a timestamp. */
155 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
157 TALLOC_FREE(smb_fname_cpath);
161 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
162 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
163 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
164 /* If any of the normal UNIX directory timestamps
165 * have a non-zero tv_nsec component assume
166 * we might be able to set sub-second timestamps.
167 * See what filetime set primitives we have.
169 #if defined(HAVE_UTIMENSAT)
170 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
171 #elif defined(HAVE_UTIMES)
172 /* utimes allows msec timestamps to be set. */
173 *p_ts_res = TIMESTAMP_SET_MSEC;
174 #elif defined(HAVE_UTIME)
175 /* utime only allows sec timestamps to be set. */
176 *p_ts_res = TIMESTAMP_SET_SECONDS;
179 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
181 "available on share %s, directory %s\n",
182 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
183 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
184 conn->connectpath ));
186 TALLOC_FREE(smb_fname_cpath);
190 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
191 struct dfs_GetDFSReferral *r)
193 struct junction_map *junction = NULL;
195 bool self_referral = false;
196 char *pathnamep = NULL;
197 char *local_dfs_path = NULL;
200 uint16_t max_referral_level = r->in.req.max_referral_level;
203 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
206 /* get the junction entry */
207 if (r->in.req.servername == NULL) {
208 return NT_STATUS_NOT_FOUND;
212 * Trim pathname sent by client so it begins with only one backslash.
213 * Two backslashes confuse some dfs clients
216 local_dfs_path = talloc_strdup(r, r->in.req.servername);
217 if (local_dfs_path == NULL) {
218 return NT_STATUS_NO_MEMORY;
220 pathnamep = local_dfs_path;
221 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
222 IS_DIRECTORY_SEP(pathnamep[1])) {
226 junction = talloc_zero(r, struct junction_map);
227 if (junction == NULL) {
228 return NT_STATUS_NO_MEMORY;
231 /* The following call can change cwd. */
232 status = get_referred_path(r,
233 handle->conn->session_info,
235 handle->conn->sconn->remote_address,
236 handle->conn->sconn->local_address,
237 !handle->conn->sconn->using_smb2,
238 junction, &consumedcnt, &self_referral);
239 if (!NT_STATUS_IS_OK(status)) {
240 struct smb_filename connectpath_fname = {
241 .base_name = handle->conn->connectpath
243 vfs_ChDir(handle->conn, &connectpath_fname);
247 struct smb_filename connectpath_fname = {
248 .base_name = handle->conn->connectpath
250 vfs_ChDir(handle->conn, &connectpath_fname);
253 if (!self_referral) {
254 pathnamep[consumedcnt] = '\0';
257 dbgtext("Path %s to alternate path(s):",
259 for (i=0; i < junction->referral_count; i++) {
261 junction->referral_list[i].alternate_path);
267 if (r->in.req.max_referral_level <= 2) {
268 max_referral_level = 2;
270 if (r->in.req.max_referral_level >= 3) {
271 max_referral_level = 3;
274 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
275 if (r->out.resp == NULL) {
276 return NT_STATUS_NO_MEMORY;
279 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
280 r->out.resp->nb_referrals = junction->referral_count;
282 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
284 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
287 r->out.resp->referral_entries = talloc_zero_array(r,
288 struct dfs_referral_type,
289 r->out.resp->nb_referrals);
290 if (r->out.resp->referral_entries == NULL) {
291 return NT_STATUS_NO_MEMORY;
294 switch (max_referral_level) {
296 for(i=0; i < junction->referral_count; i++) {
297 struct referral *ref = &junction->referral_list[i];
298 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
299 struct dfs_referral_type *t =
300 &r->out.resp->referral_entries[i];
301 struct dfs_referral_v2 *v2 = &t->referral.v2;
304 v2->size = VERSION2_REFERRAL_SIZE;
306 v2->server_type = DFS_SERVER_ROOT;
308 v2->server_type = DFS_SERVER_NON_ROOT;
311 v2->proximity = ref->proximity;
313 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
314 if (v2->DFS_path == NULL) {
315 return NT_STATUS_NO_MEMORY;
317 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
318 if (v2->DFS_alt_path == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 v2->netw_address = talloc_strdup(mem_ctx,
322 ref->alternate_path);
323 if (v2->netw_address == NULL) {
324 return NT_STATUS_NO_MEMORY;
330 for(i=0; i < junction->referral_count; i++) {
331 struct referral *ref = &junction->referral_list[i];
332 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
333 struct dfs_referral_type *t =
334 &r->out.resp->referral_entries[i];
335 struct dfs_referral_v3 *v3 = &t->referral.v3;
336 struct dfs_normal_referral *r1 = &v3->referrals.r1;
339 v3->size = VERSION3_REFERRAL_SIZE;
341 v3->server_type = DFS_SERVER_ROOT;
343 v3->server_type = DFS_SERVER_NON_ROOT;
347 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
348 if (r1->DFS_path == NULL) {
349 return NT_STATUS_NO_MEMORY;
351 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
352 if (r1->DFS_alt_path == NULL) {
353 return NT_STATUS_NO_MEMORY;
355 r1->netw_address = talloc_strdup(mem_ctx,
356 ref->alternate_path);
357 if (r1->netw_address == NULL) {
358 return NT_STATUS_NO_MEMORY;
363 DEBUG(0,("Invalid dfs referral version: %d\n",
364 max_referral_level));
365 return NT_STATUS_INVALID_LEVEL;
369 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
375 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
376 struct files_struct *dirfsp,
377 const struct smb_filename *smb_fname,
378 const struct referral *reflist,
379 size_t referral_count)
381 TALLOC_CTX *frame = talloc_stackframe();
382 NTSTATUS status = NT_STATUS_NO_MEMORY;
384 char *msdfs_link = NULL;
386 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
388 /* Form the msdfs_link contents */
389 msdfs_link = msdfs_link_string(frame,
392 if (msdfs_link == NULL) {
396 ret = symlinkat(msdfs_link,
398 smb_fname->base_name);
400 status = NT_STATUS_OK;
402 status = map_nt_error_from_unix(errno);
412 * Read and return the contents of a DFS redirect given a
413 * pathname. A caller can pass in NULL for ppreflist and
414 * preferral_count but still determine if this was a
415 * DFS redirect point by getting NT_STATUS_OK back
416 * without incurring the overhead of reading and parsing
417 * the referral contents.
420 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
422 struct files_struct *dirfsp,
423 const struct smb_filename *smb_fname,
424 struct referral **ppreflist,
425 size_t *preferral_count)
427 NTSTATUS status = NT_STATUS_NO_MEMORY;
429 char *link_target = NULL;
432 #if defined(HAVE_BROKEN_READLINK)
433 char link_target_buf[PATH_MAX];
435 char link_target_buf[7];
438 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
440 if (ppreflist == NULL && preferral_count == NULL) {
442 * We're only checking if this is a DFS
443 * redirect. We don't need to return data.
445 bufsize = sizeof(link_target_buf);
446 link_target = link_target_buf;
449 link_target = talloc_array(mem_ctx, char, bufsize);
455 referral_len = readlinkat(dirfsp->fh->fd,
456 smb_fname->base_name,
459 if (referral_len == -1) {
460 if (errno == EINVAL) {
462 * If the path isn't a link, readlinkat
463 * returns EINVAL. Allow the caller to
466 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
467 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
469 status = map_nt_error_from_unix(errno);
470 DBG_ERR("Error reading "
471 "msdfs link %s: %s\n",
472 smb_fname->base_name,
477 link_target[referral_len] = '\0';
479 DBG_INFO("%s -> %s\n",
480 smb_fname->base_name,
483 if (!strnequal(link_target, "msdfs:", 6)) {
484 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
488 if (ppreflist == NULL && preferral_count == NULL) {
489 /* Early return for checking if this is a DFS link. */
493 ok = parse_msdfs_symlink(mem_ctx,
494 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
500 status = NT_STATUS_OK;
502 status = NT_STATUS_NO_MEMORY;
507 if (link_target != link_target_buf) {
508 TALLOC_FREE(link_target);
513 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
515 const char *service_path,
518 return NT_STATUS_NOT_SUPPORTED;
521 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
523 const char *base_volume,
529 return NT_STATUS_NOT_SUPPORTED;
532 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
537 return NT_STATUS_NOT_SUPPORTED;
540 /* Directory operations */
542 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
549 START_PROFILE(syscall_fdopendir);
550 result = sys_fdopendir(fsp->fh->fd);
551 END_PROFILE(syscall_fdopendir);
556 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
558 SMB_STRUCT_STAT *sbuf)
560 struct dirent *result;
562 START_PROFILE(syscall_readdir);
563 result = readdir(dirp);
564 END_PROFILE(syscall_readdir);
566 /* Default Posix readdir() does not give us stat info.
567 * Set to invalid to indicate we didn't return this info. */
568 SET_STAT_INVALID(*sbuf);
569 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
570 if (result != NULL) {
571 /* See if we can efficiently return this. */
573 int flags = AT_SYMLINK_NOFOLLOW;
574 int ret = fstatat(dirfd(dirp),
579 * As this is an optimization,
580 * ignore it if we stat'ed a
581 * symlink. Make the caller
582 * do it again as we don't
583 * know if they wanted the link
584 * info, or its target info.
586 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
587 init_stat_ex_from_stat(sbuf,
589 lp_fake_directory_create_times(
590 SNUM(handle->conn)));
598 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
599 const struct smb_filename *fname,
601 struct readdir_attr_data **attr_data)
603 return NT_STATUS_NOT_SUPPORTED;
606 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
608 START_PROFILE(syscall_seekdir);
609 seekdir(dirp, offset);
610 END_PROFILE(syscall_seekdir);
613 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
616 START_PROFILE(syscall_telldir);
617 result = telldir(dirp);
618 END_PROFILE(syscall_telldir);
622 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
624 START_PROFILE(syscall_rewinddir);
626 END_PROFILE(syscall_rewinddir);
629 static int vfswrap_mkdirat(vfs_handle_struct *handle,
630 struct files_struct *dirfsp,
631 const struct smb_filename *smb_fname,
635 struct smb_filename *parent = NULL;
638 START_PROFILE(syscall_mkdirat);
640 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
642 if (lp_inherit_acls(SNUM(handle->conn))) {
643 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
644 if (ok && directory_has_default_acl(handle->conn,
648 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
654 result = mkdirat(dirfsp->fh->fd, smb_fname->base_name, mode);
656 END_PROFILE(syscall_mkdirat);
660 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
664 START_PROFILE(syscall_closedir);
665 result = closedir(dirp);
666 END_PROFILE(syscall_closedir);
670 /* File operations */
672 static int vfswrap_open(vfs_handle_struct *handle,
673 struct smb_filename *smb_fname,
674 files_struct *fsp, int flags, mode_t mode)
678 START_PROFILE(syscall_open);
680 if (is_named_stream(smb_fname)) {
685 result = open(smb_fname->base_name, flags, mode);
687 END_PROFILE(syscall_open);
691 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
692 struct smb_request *req,
693 uint16_t root_dir_fid,
694 struct smb_filename *smb_fname,
695 uint32_t access_mask,
696 uint32_t share_access,
697 uint32_t create_disposition,
698 uint32_t create_options,
699 uint32_t file_attributes,
700 uint32_t oplock_request,
701 const struct smb2_lease *lease,
702 uint64_t allocation_size,
703 uint32_t private_flags,
704 struct security_descriptor *sd,
705 struct ea_list *ea_list,
706 files_struct **result,
708 const struct smb2_create_blobs *in_context_blobs,
709 struct smb2_create_blobs *out_context_blobs)
711 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
712 access_mask, share_access,
713 create_disposition, create_options,
714 file_attributes, oplock_request, lease,
715 allocation_size, private_flags,
717 pinfo, in_context_blobs, out_context_blobs);
720 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
724 START_PROFILE(syscall_close);
725 result = fd_close_posix(fsp);
726 END_PROFILE(syscall_close);
730 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
731 size_t n, off_t offset)
735 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
736 START_PROFILE_BYTES(syscall_pread, n);
737 result = sys_pread(fsp->fh->fd, data, n, offset);
738 END_PROFILE_BYTES(syscall_pread);
740 if (result == -1 && errno == ESPIPE) {
741 /* Maintain the fiction that pipes can be seeked (sought?) on. */
742 result = sys_read(fsp->fh->fd, data, n);
746 #else /* HAVE_PREAD */
749 #endif /* HAVE_PREAD */
754 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
755 size_t n, off_t offset)
759 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
760 START_PROFILE_BYTES(syscall_pwrite, n);
761 result = sys_pwrite(fsp->fh->fd, data, n, offset);
762 END_PROFILE_BYTES(syscall_pwrite);
764 if (result == -1 && errno == ESPIPE) {
765 /* Maintain the fiction that pipes can be sought on. */
766 result = sys_write(fsp->fh->fd, data, n);
769 #else /* HAVE_PWRITE */
772 #endif /* HAVE_PWRITE */
777 struct vfswrap_pread_state {
784 struct vfs_aio_state vfs_aio_state;
785 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
788 static void vfs_pread_do(void *private_data);
789 static void vfs_pread_done(struct tevent_req *subreq);
790 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
792 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
794 struct tevent_context *ev,
795 struct files_struct *fsp,
797 size_t n, off_t offset)
799 struct tevent_req *req, *subreq;
800 struct vfswrap_pread_state *state;
802 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
808 state->fd = fsp->fh->fd;
811 state->offset = offset;
813 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
814 state->profile_bytes, n);
815 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
817 subreq = pthreadpool_tevent_job_send(
818 state, ev, handle->conn->sconn->pool,
819 vfs_pread_do, state);
820 if (tevent_req_nomem(subreq, req)) {
821 return tevent_req_post(req, ev);
823 tevent_req_set_callback(subreq, vfs_pread_done, req);
825 talloc_set_destructor(state, vfs_pread_state_destructor);
830 static void vfs_pread_do(void *private_data)
832 struct vfswrap_pread_state *state = talloc_get_type_abort(
833 private_data, struct vfswrap_pread_state);
834 struct timespec start_time;
835 struct timespec end_time;
837 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
839 PROFILE_TIMESTAMP(&start_time);
842 state->ret = pread(state->fd, state->buf, state->count,
844 } while ((state->ret == -1) && (errno == EINTR));
846 if (state->ret == -1) {
847 state->vfs_aio_state.error = errno;
850 PROFILE_TIMESTAMP(&end_time);
852 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
854 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
857 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
862 static void vfs_pread_done(struct tevent_req *subreq)
864 struct tevent_req *req = tevent_req_callback_data(
865 subreq, struct tevent_req);
866 struct vfswrap_pread_state *state = tevent_req_data(
867 req, struct vfswrap_pread_state);
870 ret = pthreadpool_tevent_job_recv(subreq);
872 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
873 talloc_set_destructor(state, NULL);
876 tevent_req_error(req, ret);
880 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
881 * means the lower level pthreadpool failed to create a new
882 * thread. Fallback to sync processing in that case to allow
883 * some progress for the client.
888 tevent_req_done(req);
891 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
892 struct vfs_aio_state *vfs_aio_state)
894 struct vfswrap_pread_state *state = tevent_req_data(
895 req, struct vfswrap_pread_state);
897 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
901 *vfs_aio_state = state->vfs_aio_state;
905 struct vfswrap_pwrite_state {
912 struct vfs_aio_state vfs_aio_state;
913 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
916 static void vfs_pwrite_do(void *private_data);
917 static void vfs_pwrite_done(struct tevent_req *subreq);
918 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
920 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
922 struct tevent_context *ev,
923 struct files_struct *fsp,
925 size_t n, off_t offset)
927 struct tevent_req *req, *subreq;
928 struct vfswrap_pwrite_state *state;
930 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
936 state->fd = fsp->fh->fd;
939 state->offset = offset;
941 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
942 state->profile_bytes, n);
943 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
945 subreq = pthreadpool_tevent_job_send(
946 state, ev, handle->conn->sconn->pool,
947 vfs_pwrite_do, state);
948 if (tevent_req_nomem(subreq, req)) {
949 return tevent_req_post(req, ev);
951 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
953 talloc_set_destructor(state, vfs_pwrite_state_destructor);
958 static void vfs_pwrite_do(void *private_data)
960 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
961 private_data, struct vfswrap_pwrite_state);
962 struct timespec start_time;
963 struct timespec end_time;
965 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
967 PROFILE_TIMESTAMP(&start_time);
970 state->ret = pwrite(state->fd, state->buf, state->count,
972 } while ((state->ret == -1) && (errno == EINTR));
974 if (state->ret == -1) {
975 state->vfs_aio_state.error = errno;
978 PROFILE_TIMESTAMP(&end_time);
980 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
982 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
985 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
990 static void vfs_pwrite_done(struct tevent_req *subreq)
992 struct tevent_req *req = tevent_req_callback_data(
993 subreq, struct tevent_req);
994 struct vfswrap_pwrite_state *state = tevent_req_data(
995 req, struct vfswrap_pwrite_state);
998 ret = pthreadpool_tevent_job_recv(subreq);
1000 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1001 talloc_set_destructor(state, NULL);
1003 if (ret != EAGAIN) {
1004 tevent_req_error(req, ret);
1008 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1009 * means the lower level pthreadpool failed to create a new
1010 * thread. Fallback to sync processing in that case to allow
1011 * some progress for the client.
1013 vfs_pwrite_do(state);
1016 tevent_req_done(req);
1019 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1020 struct vfs_aio_state *vfs_aio_state)
1022 struct vfswrap_pwrite_state *state = tevent_req_data(
1023 req, struct vfswrap_pwrite_state);
1025 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1029 *vfs_aio_state = state->vfs_aio_state;
1033 struct vfswrap_fsync_state {
1037 struct vfs_aio_state vfs_aio_state;
1038 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1041 static void vfs_fsync_do(void *private_data);
1042 static void vfs_fsync_done(struct tevent_req *subreq);
1043 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1045 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1046 TALLOC_CTX *mem_ctx,
1047 struct tevent_context *ev,
1048 struct files_struct *fsp)
1050 struct tevent_req *req, *subreq;
1051 struct vfswrap_fsync_state *state;
1053 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1059 state->fd = fsp->fh->fd;
1061 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1062 state->profile_bytes, 0);
1063 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1065 subreq = pthreadpool_tevent_job_send(
1066 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1067 if (tevent_req_nomem(subreq, req)) {
1068 return tevent_req_post(req, ev);
1070 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1072 talloc_set_destructor(state, vfs_fsync_state_destructor);
1077 static void vfs_fsync_do(void *private_data)
1079 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1080 private_data, struct vfswrap_fsync_state);
1081 struct timespec start_time;
1082 struct timespec end_time;
1084 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1086 PROFILE_TIMESTAMP(&start_time);
1089 state->ret = fsync(state->fd);
1090 } while ((state->ret == -1) && (errno == EINTR));
1092 if (state->ret == -1) {
1093 state->vfs_aio_state.error = errno;
1096 PROFILE_TIMESTAMP(&end_time);
1098 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1100 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1103 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1108 static void vfs_fsync_done(struct tevent_req *subreq)
1110 struct tevent_req *req = tevent_req_callback_data(
1111 subreq, struct tevent_req);
1112 struct vfswrap_fsync_state *state = tevent_req_data(
1113 req, struct vfswrap_fsync_state);
1116 ret = pthreadpool_tevent_job_recv(subreq);
1117 TALLOC_FREE(subreq);
1118 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1119 talloc_set_destructor(state, NULL);
1121 if (ret != EAGAIN) {
1122 tevent_req_error(req, ret);
1126 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1127 * means the lower level pthreadpool failed to create a new
1128 * thread. Fallback to sync processing in that case to allow
1129 * some progress for the client.
1131 vfs_fsync_do(state);
1134 tevent_req_done(req);
1137 static int vfswrap_fsync_recv(struct tevent_req *req,
1138 struct vfs_aio_state *vfs_aio_state)
1140 struct vfswrap_fsync_state *state = tevent_req_data(
1141 req, struct vfswrap_fsync_state);
1143 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1147 *vfs_aio_state = state->vfs_aio_state;
1151 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1155 START_PROFILE(syscall_lseek);
1157 result = lseek(fsp->fh->fd, offset, whence);
1159 * We want to maintain the fiction that we can seek
1160 * on a fifo for file system purposes. This allows
1161 * people to set up UNIX fifo's that feed data to Windows
1162 * applications. JRA.
1165 if((result == -1) && (errno == ESPIPE)) {
1170 END_PROFILE(syscall_lseek);
1174 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1175 off_t offset, size_t n)
1179 START_PROFILE_BYTES(syscall_sendfile, n);
1180 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1181 END_PROFILE_BYTES(syscall_sendfile);
1185 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1187 files_struct *tofsp,
1193 START_PROFILE_BYTES(syscall_recvfile, n);
1194 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1195 END_PROFILE_BYTES(syscall_recvfile);
1199 static int vfswrap_renameat(vfs_handle_struct *handle,
1200 files_struct *srcfsp,
1201 const struct smb_filename *smb_fname_src,
1202 files_struct *dstfsp,
1203 const struct smb_filename *smb_fname_dst)
1207 START_PROFILE(syscall_renameat);
1209 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1214 result = renameat(srcfsp->fh->fd,
1215 smb_fname_src->base_name,
1217 smb_fname_dst->base_name);
1220 END_PROFILE(syscall_renameat);
1224 static int vfswrap_stat(vfs_handle_struct *handle,
1225 struct smb_filename *smb_fname)
1229 START_PROFILE(syscall_stat);
1231 if (is_named_stream(smb_fname)) {
1236 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1237 lp_fake_directory_create_times(SNUM(handle->conn)));
1239 END_PROFILE(syscall_stat);
1243 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1247 START_PROFILE(syscall_fstat);
1248 result = sys_fstat(fsp->fh->fd,
1249 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1250 END_PROFILE(syscall_fstat);
1254 static int vfswrap_lstat(vfs_handle_struct *handle,
1255 struct smb_filename *smb_fname)
1259 START_PROFILE(syscall_lstat);
1261 if (is_named_stream(smb_fname)) {
1266 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1267 lp_fake_directory_create_times(SNUM(handle->conn)));
1269 END_PROFILE(syscall_lstat);
1273 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1275 enum vfs_translate_direction direction,
1276 TALLOC_CTX *mem_ctx,
1279 return NT_STATUS_NONE_MAPPED;
1283 * Implement the default fsctl operation.
1285 static bool vfswrap_logged_ioctl_message = false;
1287 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1288 struct files_struct *fsp,
1291 uint16_t req_flags, /* Needed for UNICODE ... */
1292 const uint8_t *_in_data,
1294 uint8_t **_out_data,
1295 uint32_t max_out_len,
1298 const char *in_data = (const char *)_in_data;
1299 char **out_data = (char **)_out_data;
1303 case FSCTL_SET_SPARSE:
1305 bool set_sparse = true;
1307 if (in_len >= 1 && in_data[0] == 0) {
1311 status = file_set_sparse(handle->conn, fsp, set_sparse);
1313 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1314 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1315 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1316 nt_errstr(status)));
1321 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1323 unsigned char objid[16];
1324 char *return_data = NULL;
1326 /* This should return the object-id on this file.
1327 * I think I'll make this be the inode+dev. JRA.
1330 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1331 fsp_fnum_dbg(fsp)));
1333 *out_len = MIN(max_out_len, 64);
1335 /* Hmmm, will this cause problems if less data asked for? */
1336 return_data = talloc_array(ctx, char, 64);
1337 if (return_data == NULL) {
1338 return NT_STATUS_NO_MEMORY;
1341 /* For backwards compatibility only store the dev/inode. */
1342 push_file_id_16(return_data, &fsp->file_id);
1343 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1344 push_file_id_16(return_data+32, &fsp->file_id);
1345 memset(return_data+48, 0, 16);
1346 *out_data = return_data;
1347 return NT_STATUS_OK;
1350 case FSCTL_GET_REPARSE_POINT:
1352 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1353 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1354 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1355 return NT_STATUS_NOT_A_REPARSE_POINT;
1358 case FSCTL_SET_REPARSE_POINT:
1360 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1361 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1362 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1363 return NT_STATUS_NOT_A_REPARSE_POINT;
1366 case FSCTL_GET_SHADOW_COPY_DATA:
1369 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1370 * and return their volume names. If max_data_count is 16, then it is just
1371 * asking for the number of volumes and length of the combined names.
1373 * pdata is the data allocated by our caller, but that uses
1374 * total_data_count (which is 0 in our case) rather than max_data_count.
1375 * Allocate the correct amount and return the pointer to let
1376 * it be deallocated when we return.
1378 struct shadow_copy_data *shadow_data = NULL;
1379 bool labels = False;
1380 uint32_t labels_data_count = 0;
1382 char *cur_pdata = NULL;
1384 if (max_out_len < 16) {
1385 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1387 return NT_STATUS_INVALID_PARAMETER;
1390 if (max_out_len > 16) {
1394 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1395 if (shadow_data == NULL) {
1396 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1397 return NT_STATUS_NO_MEMORY;
1401 * Call the VFS routine to actually do the work.
1403 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1406 /* broken module didn't set errno on error */
1407 status = NT_STATUS_UNSUCCESSFUL;
1409 status = map_nt_error_from_unix(errno);
1410 if (NT_STATUS_EQUAL(status,
1411 NT_STATUS_NOT_SUPPORTED)) {
1415 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1416 "connectpath %s, failed - %s.\n",
1417 fsp->conn->connectpath,
1418 nt_errstr(status)));
1419 TALLOC_FREE(shadow_data);
1423 labels_data_count = (shadow_data->num_volumes * 2 *
1424 sizeof(SHADOW_COPY_LABEL)) + 2;
1429 *out_len = 12 + labels_data_count;
1432 if (max_out_len < *out_len) {
1433 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1434 max_out_len, *out_len));
1435 TALLOC_FREE(shadow_data);
1436 return NT_STATUS_BUFFER_TOO_SMALL;
1439 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1440 if (cur_pdata == NULL) {
1441 TALLOC_FREE(shadow_data);
1442 return NT_STATUS_NO_MEMORY;
1445 *out_data = cur_pdata;
1447 /* num_volumes 4 bytes */
1448 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1451 /* num_labels 4 bytes */
1452 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1455 /* needed_data_count 4 bytes */
1456 SIVAL(cur_pdata, 8, labels_data_count);
1460 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1461 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1462 if (labels && shadow_data->labels) {
1463 for (i=0; i<shadow_data->num_volumes; i++) {
1465 status = srvstr_push(cur_pdata, req_flags,
1466 cur_pdata, shadow_data->labels[i],
1467 2 * sizeof(SHADOW_COPY_LABEL),
1468 STR_UNICODE|STR_TERMINATE, &len);
1469 if (!NT_STATUS_IS_OK(status)) {
1470 TALLOC_FREE(*out_data);
1471 TALLOC_FREE(shadow_data);
1474 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1475 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1479 TALLOC_FREE(shadow_data);
1481 return NT_STATUS_OK;
1484 case FSCTL_FIND_FILES_BY_SID:
1486 /* pretend this succeeded -
1488 * we have to send back a list with all files owned by this SID
1490 * but I have to check that --metze
1494 struct dom_sid_buf buf;
1498 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1499 fsp_fnum_dbg(fsp)));
1502 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1503 return NT_STATUS_INVALID_PARAMETER;
1506 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1508 /* unknown 4 bytes: this is not the length of the sid :-( */
1509 /*unknown = IVAL(pdata,0);*/
1511 ret = sid_parse(_in_data + 4, sid_len, &sid);
1513 return NT_STATUS_INVALID_PARAMETER;
1515 DEBUGADD(10, ("for SID: %s\n",
1516 dom_sid_str_buf(&sid, &buf)));
1518 if (!sid_to_uid(&sid, &uid)) {
1519 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1520 dom_sid_str_buf(&sid, &buf),
1521 (unsigned long)sid_len));
1525 /* we can take a look at the find source :-)
1527 * find ./ -uid $uid -name '*' is what we need here
1530 * and send 4bytes len and then NULL terminated unicode strings
1533 * but I don't know how to deal with the paged results
1534 * (maybe we can hang the result anywhere in the fsp struct)
1536 * but I don't know how to deal with the paged results
1537 * (maybe we can hang the result anywhere in the fsp struct)
1539 * we don't send all files at once
1540 * and at the next we should *not* start from the beginning,
1541 * so we have to cache the result
1546 /* this works for now... */
1547 return NT_STATUS_OK;
1550 case FSCTL_QUERY_ALLOCATED_RANGES:
1552 /* FIXME: This is just a dummy reply, telling that all of the
1553 * file is allocated. MKS cp needs that.
1554 * Adding the real allocated ranges via FIEMAP on Linux
1555 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1556 * this FSCTL correct for sparse files.
1558 uint64_t offset, length;
1559 char *out_data_tmp = NULL;
1562 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1564 return NT_STATUS_INVALID_PARAMETER;
1567 if (max_out_len < 16) {
1568 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1570 return NT_STATUS_INVALID_PARAMETER;
1573 offset = BVAL(in_data,0);
1574 length = BVAL(in_data,8);
1576 if (offset + length < offset) {
1577 /* No 64-bit integer wrap. */
1578 return NT_STATUS_INVALID_PARAMETER;
1581 /* Shouldn't this be SMB_VFS_STAT ... ? */
1582 status = vfs_stat_fsp(fsp);
1583 if (!NT_STATUS_IS_OK(status)) {
1588 out_data_tmp = talloc_array(ctx, char, *out_len);
1589 if (out_data_tmp == NULL) {
1590 DEBUG(10, ("unable to allocate memory for response\n"));
1591 return NT_STATUS_NO_MEMORY;
1594 if (offset > fsp->fsp_name->st.st_ex_size ||
1595 fsp->fsp_name->st.st_ex_size == 0 ||
1597 memset(out_data_tmp, 0, *out_len);
1599 uint64_t end = offset + length;
1600 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1601 SBVAL(out_data_tmp, 0, 0);
1602 SBVAL(out_data_tmp, 8, end);
1605 *out_data = out_data_tmp;
1607 return NT_STATUS_OK;
1610 case FSCTL_IS_VOLUME_DIRTY:
1612 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1613 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1615 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1616 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1618 return NT_STATUS_INVALID_PARAMETER;
1623 * Only print once ... unfortunately there could be lots of
1624 * different FSCTLs that are called.
1626 if (!vfswrap_logged_ioctl_message) {
1627 vfswrap_logged_ioctl_message = true;
1628 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1629 __func__, function));
1633 return NT_STATUS_NOT_SUPPORTED;
1636 static bool vfswrap_is_offline(struct connection_struct *conn,
1637 const struct smb_filename *fname);
1639 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1640 struct smb_filename *smb_fname,
1645 offline = vfswrap_is_offline(handle->conn, smb_fname);
1647 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1650 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1653 struct vfswrap_get_dos_attributes_state {
1654 struct vfs_aio_state aio_state;
1655 connection_struct *conn;
1656 TALLOC_CTX *mem_ctx;
1657 struct tevent_context *ev;
1658 files_struct *dir_fsp;
1659 struct smb_filename *smb_fname;
1664 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1666 static struct tevent_req *vfswrap_get_dos_attributes_send(
1667 TALLOC_CTX *mem_ctx,
1668 struct tevent_context *ev,
1669 struct vfs_handle_struct *handle,
1670 files_struct *dir_fsp,
1671 struct smb_filename *smb_fname)
1673 struct tevent_req *req = NULL;
1674 struct tevent_req *subreq = NULL;
1675 struct vfswrap_get_dos_attributes_state *state = NULL;
1677 req = tevent_req_create(mem_ctx, &state,
1678 struct vfswrap_get_dos_attributes_state);
1683 *state = (struct vfswrap_get_dos_attributes_state) {
1684 .conn = dir_fsp->conn,
1688 .smb_fname = smb_fname,
1691 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1695 SAMBA_XATTR_DOS_ATTRIB,
1697 if (tevent_req_nomem(subreq, req)) {
1698 return tevent_req_post(req, ev);
1700 tevent_req_set_callback(subreq,
1701 vfswrap_get_dos_attributes_getxattr_done,
1707 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1709 struct tevent_req *req =
1710 tevent_req_callback_data(subreq,
1712 struct vfswrap_get_dos_attributes_state *state =
1713 tevent_req_data(req,
1714 struct vfswrap_get_dos_attributes_state);
1716 DATA_BLOB blob = {0};
1718 char *tofree = NULL;
1719 char pathbuf[PATH_MAX+1];
1721 struct smb_filename smb_fname;
1725 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1729 TALLOC_FREE(subreq);
1730 if (xattr_size == -1) {
1731 status = map_nt_error_from_unix(state->aio_state.error);
1733 if (state->as_root) {
1734 tevent_req_nterror(req, status);
1737 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1738 tevent_req_nterror(req, status);
1742 state->as_root = true;
1745 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1749 SAMBA_XATTR_DOS_ATTRIB,
1752 if (tevent_req_nomem(subreq, req)) {
1755 tevent_req_set_callback(subreq,
1756 vfswrap_get_dos_attributes_getxattr_done,
1761 blob.length = xattr_size;
1763 status = parse_dos_attribute_blob(state->smb_fname,
1766 if (!NT_STATUS_IS_OK(status)) {
1767 tevent_req_nterror(req, status);
1771 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1772 state->smb_fname->base_name,
1777 if (pathlen == -1) {
1778 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1782 smb_fname = (struct smb_filename) {
1784 .st = state->smb_fname->st,
1785 .flags = state->smb_fname->flags,
1786 .twrp = state->smb_fname->twrp,
1789 offline = vfswrap_is_offline(state->conn, &smb_fname);
1791 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1793 TALLOC_FREE(tofree);
1795 tevent_req_done(req);
1799 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1800 struct vfs_aio_state *aio_state,
1803 struct vfswrap_get_dos_attributes_state *state =
1804 tevent_req_data(req,
1805 struct vfswrap_get_dos_attributes_state);
1808 if (tevent_req_is_nterror(req, &status)) {
1809 tevent_req_received(req);
1813 *aio_state = state->aio_state;
1814 *dosmode = state->dosmode;
1815 tevent_req_received(req);
1816 return NT_STATUS_OK;
1819 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1820 struct files_struct *fsp,
1825 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1827 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1830 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1833 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1834 const struct smb_filename *smb_fname,
1837 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1840 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1841 struct files_struct *fsp,
1844 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1847 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1849 struct vfswrap_offload_read_state {
1853 static struct tevent_req *vfswrap_offload_read_send(
1854 TALLOC_CTX *mem_ctx,
1855 struct tevent_context *ev,
1856 struct vfs_handle_struct *handle,
1857 struct files_struct *fsp,
1863 struct tevent_req *req = NULL;
1864 struct vfswrap_offload_read_state *state = NULL;
1867 req = tevent_req_create(mem_ctx, &state,
1868 struct vfswrap_offload_read_state);
1873 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1874 &vfswrap_offload_ctx);
1875 if (tevent_req_nterror(req, status)) {
1876 return tevent_req_post(req, ev);
1879 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1880 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1881 return tevent_req_post(req, ev);
1884 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1886 if (tevent_req_nterror(req, status)) {
1887 return tevent_req_post(req, ev);
1890 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1892 if (tevent_req_nterror(req, status)) {
1893 return tevent_req_post(req, ev);
1896 tevent_req_done(req);
1897 return tevent_req_post(req, ev);
1900 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1901 struct vfs_handle_struct *handle,
1902 TALLOC_CTX *mem_ctx,
1905 struct vfswrap_offload_read_state *state = tevent_req_data(
1906 req, struct vfswrap_offload_read_state);
1909 if (tevent_req_is_nterror(req, &status)) {
1910 tevent_req_received(req);
1914 token->length = state->token.length;
1915 token->data = talloc_move(mem_ctx, &state->token.data);
1917 tevent_req_received(req);
1918 return NT_STATUS_OK;
1921 struct vfswrap_offload_write_state {
1923 bool read_lck_locked;
1924 bool write_lck_locked;
1926 struct tevent_context *src_ev;
1927 struct files_struct *src_fsp;
1929 struct tevent_context *dst_ev;
1930 struct files_struct *dst_fsp;
1934 size_t next_io_size;
1937 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1938 enum tevent_req_state req_state)
1940 struct vfswrap_offload_write_state *state = tevent_req_data(
1941 req, struct vfswrap_offload_write_state);
1944 if (state->dst_fsp == NULL) {
1948 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1950 state->dst_fsp = NULL;
1953 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1955 static struct tevent_req *vfswrap_offload_write_send(
1956 struct vfs_handle_struct *handle,
1957 TALLOC_CTX *mem_ctx,
1958 struct tevent_context *ev,
1961 off_t transfer_offset,
1962 struct files_struct *dest_fsp,
1966 struct tevent_req *req;
1967 struct vfswrap_offload_write_state *state = NULL;
1968 /* off_t is signed! */
1969 off_t max_offset = INT64_MAX - to_copy;
1970 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1971 files_struct *src_fsp = NULL;
1975 req = tevent_req_create(mem_ctx, &state,
1976 struct vfswrap_offload_write_state);
1981 *state = (struct vfswrap_offload_write_state) {
1983 .src_off = transfer_offset,
1985 .dst_fsp = dest_fsp,
1986 .dst_off = dest_off,
1988 .remaining = to_copy,
1991 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1994 case FSCTL_SRV_COPYCHUNK:
1995 case FSCTL_SRV_COPYCHUNK_WRITE:
1998 case FSCTL_OFFLOAD_WRITE:
1999 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2000 return tevent_req_post(req, ev);
2002 case FSCTL_DUP_EXTENTS_TO_FILE:
2003 DBG_DEBUG("COW clones not supported by vfs_default\n");
2004 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2005 return tevent_req_post(req, ev);
2008 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2009 return tevent_req_post(req, ev);
2013 * From here on we assume a copy-chunk fsctl
2017 tevent_req_done(req);
2018 return tevent_req_post(req, ev);
2021 if (state->src_off > max_offset) {
2023 * Protect integer checks below.
2025 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2026 return tevent_req_post(req, ev);
2028 if (state->src_off < 0) {
2030 * Protect integer checks below.
2032 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 return tevent_req_post(req, ev);
2035 if (state->dst_off > max_offset) {
2037 * Protect integer checks below.
2039 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 return tevent_req_post(req, ev);
2042 if (state->dst_off < 0) {
2044 * Protect integer checks below.
2046 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2047 return tevent_req_post(req, ev);
2050 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2052 if (tevent_req_nterror(req, status)) {
2053 return tevent_req_post(req, ev);
2056 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2058 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2059 if (!NT_STATUS_IS_OK(status)) {
2060 tevent_req_nterror(req, status);
2061 return tevent_req_post(req, ev);
2064 ok = change_to_user_and_service_by_fsp(src_fsp);
2066 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2067 return tevent_req_post(req, ev);
2070 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2071 state->src_fsp = src_fsp;
2073 status = vfs_stat_fsp(src_fsp);
2074 if (tevent_req_nterror(req, status)) {
2075 return tevent_req_post(req, ev);
2078 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2080 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2081 * If the SourceOffset or SourceOffset + Length extends beyond
2082 * the end of file, the server SHOULD<240> treat this as a
2083 * STATUS_END_OF_FILE error.
2085 * <240> Section 3.3.5.15.6: Windows servers will return
2086 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2088 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2089 return tevent_req_post(req, ev);
2092 state->buf = talloc_array(state, uint8_t, num);
2093 if (tevent_req_nomem(state->buf, req)) {
2094 return tevent_req_post(req, ev);
2097 status = vfswrap_offload_write_loop(req);
2098 if (!NT_STATUS_IS_OK(status)) {
2099 tevent_req_nterror(req, status);
2100 return tevent_req_post(req, ev);
2106 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2108 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2110 struct vfswrap_offload_write_state *state = tevent_req_data(
2111 req, struct vfswrap_offload_write_state);
2112 struct tevent_req *subreq = NULL;
2113 struct lock_struct read_lck;
2117 * This is called under the context of state->src_fsp.
2120 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2122 init_strict_lock_struct(state->src_fsp,
2123 state->src_fsp->op->global->open_persistent_id,
2125 state->next_io_size,
2129 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2133 return NT_STATUS_FILE_LOCK_CONFLICT;
2136 subreq = SMB_VFS_PREAD_SEND(state,
2140 state->next_io_size,
2142 if (subreq == NULL) {
2143 return NT_STATUS_NO_MEMORY;
2145 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2147 return NT_STATUS_OK;
2150 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2152 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2154 struct tevent_req *req = tevent_req_callback_data(
2155 subreq, struct tevent_req);
2156 struct vfswrap_offload_write_state *state = tevent_req_data(
2157 req, struct vfswrap_offload_write_state);
2158 struct vfs_aio_state aio_state;
2159 struct lock_struct write_lck;
2163 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2164 TALLOC_FREE(subreq);
2166 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2167 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2170 if (nread != state->next_io_size) {
2171 DBG_ERR("Short read, only %zd of %zu\n",
2172 nread, state->next_io_size);
2173 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2177 state->src_off += nread;
2179 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2181 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2185 init_strict_lock_struct(state->dst_fsp,
2186 state->dst_fsp->op->global->open_persistent_id,
2188 state->next_io_size,
2192 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2196 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2200 subreq = SMB_VFS_PWRITE_SEND(state,
2204 state->next_io_size,
2206 if (subreq == NULL) {
2207 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2210 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2213 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2215 struct tevent_req *req = tevent_req_callback_data(
2216 subreq, struct tevent_req);
2217 struct vfswrap_offload_write_state *state = tevent_req_data(
2218 req, struct vfswrap_offload_write_state);
2219 struct vfs_aio_state aio_state;
2224 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2225 TALLOC_FREE(subreq);
2226 if (nwritten == -1) {
2227 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2228 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2231 if (nwritten != state->next_io_size) {
2232 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2233 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2237 state->dst_off += nwritten;
2239 if (state->remaining < nwritten) {
2240 /* Paranoia check */
2241 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2244 state->remaining -= nwritten;
2245 if (state->remaining == 0) {
2246 tevent_req_done(req);
2250 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2252 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2256 status = vfswrap_offload_write_loop(req);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 tevent_req_nterror(req, status);
2265 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2266 struct tevent_req *req,
2269 struct vfswrap_offload_write_state *state = tevent_req_data(
2270 req, struct vfswrap_offload_write_state);
2273 if (tevent_req_is_nterror(req, &status)) {
2274 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2276 tevent_req_received(req);
2280 *copied = state->to_copy;
2281 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2282 tevent_req_received(req);
2284 return NT_STATUS_OK;
2287 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2288 TALLOC_CTX *mem_ctx,
2289 struct files_struct *fsp,
2290 struct smb_filename *smb_fname,
2291 uint16_t *_compression_fmt)
2293 return NT_STATUS_INVALID_DEVICE_REQUEST;
2296 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2297 TALLOC_CTX *mem_ctx,
2298 struct files_struct *fsp,
2299 uint16_t compression_fmt)
2301 return NT_STATUS_INVALID_DEVICE_REQUEST;
2304 /********************************************************************
2305 Given a stat buffer return the allocated size on disk, taking into
2306 account sparse files.
2307 ********************************************************************/
2308 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2309 struct files_struct *fsp,
2310 const SMB_STRUCT_STAT *sbuf)
2314 START_PROFILE(syscall_get_alloc_size);
2316 if(S_ISDIR(sbuf->st_ex_mode)) {
2321 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2322 /* The type of st_blocksize is blkcnt_t which *MUST* be
2323 signed (according to POSIX) and can be less than 64-bits.
2324 Ensure when we're converting to 64 bits wide we don't
2326 #if defined(SIZEOF_BLKCNT_T_8)
2327 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2328 #elif defined(SIZEOF_BLKCNT_T_4)
2330 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2331 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2334 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2338 * Some file systems do not allocate a block for very
2339 * small files. But for non-empty file should report a
2343 uint64_t filesize = get_file_size_stat(sbuf);
2345 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2349 result = get_file_size_stat(sbuf);
2352 if (fsp && fsp->initial_allocation_size)
2353 result = MAX(result,fsp->initial_allocation_size);
2355 result = smb_roundup(handle->conn, result);
2358 END_PROFILE(syscall_get_alloc_size);
2362 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2363 struct files_struct *dirfsp,
2364 const struct smb_filename *smb_fname,
2369 START_PROFILE(syscall_unlinkat);
2371 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2373 if (is_named_stream(smb_fname)) {
2377 result = unlinkat(dirfsp->fh->fd,
2378 smb_fname->base_name,
2382 END_PROFILE(syscall_unlinkat);
2386 static int vfswrap_chmod(vfs_handle_struct *handle,
2387 const struct smb_filename *smb_fname,
2392 START_PROFILE(syscall_chmod);
2393 result = chmod(smb_fname->base_name, mode);
2394 END_PROFILE(syscall_chmod);
2398 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2402 START_PROFILE(syscall_fchmod);
2403 #if defined(HAVE_FCHMOD)
2404 result = fchmod(fsp->fh->fd, mode);
2410 END_PROFILE(syscall_fchmod);
2414 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2419 START_PROFILE(syscall_fchown);
2420 result = fchown(fsp->fh->fd, uid, gid);
2421 END_PROFILE(syscall_fchown);
2429 static int vfswrap_lchown(vfs_handle_struct *handle,
2430 const struct smb_filename *smb_fname,
2436 START_PROFILE(syscall_lchown);
2437 result = lchown(smb_fname->base_name, uid, gid);
2438 END_PROFILE(syscall_lchown);
2442 static int vfswrap_chdir(vfs_handle_struct *handle,
2443 const struct smb_filename *smb_fname)
2447 START_PROFILE(syscall_chdir);
2448 result = chdir(smb_fname->base_name);
2449 END_PROFILE(syscall_chdir);
2453 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2457 struct smb_filename *smb_fname = NULL;
2459 START_PROFILE(syscall_getwd);
2460 result = sys_getwd();
2461 END_PROFILE(syscall_getwd);
2463 if (result == NULL) {
2466 smb_fname = synthetic_smb_fname(ctx,
2473 * sys_getwd() *always* returns malloced memory.
2474 * We must free here to avoid leaks:
2475 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2481 /*********************************************************************
2482 nsec timestamp resolution call. Convert down to whatever the underlying
2483 system will support.
2484 **********************************************************************/
2486 static int vfswrap_ntimes(vfs_handle_struct *handle,
2487 const struct smb_filename *smb_fname,
2488 struct smb_file_time *ft)
2492 START_PROFILE(syscall_ntimes);
2494 if (is_named_stream(smb_fname)) {
2500 if (is_omit_timespec(&ft->atime)) {
2501 ft->atime= smb_fname->st.st_ex_atime;
2504 if (is_omit_timespec(&ft->mtime)) {
2505 ft->mtime = smb_fname->st.st_ex_mtime;
2508 if (!is_omit_timespec(&ft->create_time)) {
2509 set_create_timespec_ea(handle->conn,
2514 if ((timespec_compare(&ft->atime,
2515 &smb_fname->st.st_ex_atime) == 0) &&
2516 (timespec_compare(&ft->mtime,
2517 &smb_fname->st.st_ex_mtime) == 0)) {
2522 #if defined(HAVE_UTIMENSAT)
2524 struct timespec ts[2];
2527 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2529 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2531 if (!((result == -1) && (errno == ENOSYS))) {
2535 #if defined(HAVE_UTIMES)
2537 struct timeval tv[2];
2538 tv[0] = convert_timespec_to_timeval(ft->atime);
2539 tv[1] = convert_timespec_to_timeval(ft->mtime);
2540 result = utimes(smb_fname->base_name, tv);
2542 result = utimes(smb_fname->base_name, NULL);
2544 if (!((result == -1) && (errno == ENOSYS))) {
2548 #if defined(HAVE_UTIME)
2550 struct utimbuf times;
2551 times.actime = convert_timespec_to_time_t(ft->atime);
2552 times.modtime = convert_timespec_to_time_t(ft->mtime);
2553 result = utime(smb_fname->base_name, ×);
2555 result = utime(smb_fname->base_name, NULL);
2557 if (!((result == -1) && (errno == ENOSYS))) {
2565 END_PROFILE(syscall_ntimes);
2569 /*********************************************************************
2570 A version of ftruncate that will write the space on disk if strict
2572 **********************************************************************/
2574 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2576 off_t space_to_write;
2577 uint64_t space_avail;
2578 uint64_t bsize,dfree,dsize;
2581 SMB_STRUCT_STAT *pst;
2583 status = vfs_stat_fsp(fsp);
2584 if (!NT_STATUS_IS_OK(status)) {
2587 pst = &fsp->fsp_name->st;
2590 if (S_ISFIFO(pst->st_ex_mode))
2594 if (pst->st_ex_size == len)
2597 /* Shrink - just ftruncate. */
2598 if (pst->st_ex_size > len)
2599 return ftruncate(fsp->fh->fd, len);
2601 space_to_write = len - pst->st_ex_size;
2603 /* for allocation try fallocate first. This can fail on some
2604 platforms e.g. when the filesystem doesn't support it and no
2605 emulation is being done by the libc (like on AIX with JFS1). In that
2606 case we do our own emulation. fallocate implementations can
2607 return ENOTSUP or EINVAL in cases like that. */
2608 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2609 if (ret == -1 && errno == ENOSPC) {
2615 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2616 "error %d. Falling back to slow manual allocation\n", errno));
2618 /* available disk space is enough or not? */
2620 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2621 /* space_avail is 1k blocks */
2622 if (space_avail == (uint64_t)-1 ||
2623 ((uint64_t)space_to_write/1024 > space_avail) ) {
2628 /* Write out the real space on disk. */
2629 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2637 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2640 SMB_STRUCT_STAT *pst;
2644 START_PROFILE(syscall_ftruncate);
2646 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2647 result = strict_allocate_ftruncate(handle, fsp, len);
2648 END_PROFILE(syscall_ftruncate);
2652 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2653 ftruncate if the system supports it. Then I discovered that
2654 you can have some filesystems that support ftruncate
2655 expansion and some that don't! On Linux fat can't do
2656 ftruncate extend but ext2 can. */
2658 result = ftruncate(fsp->fh->fd, len);
2660 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2661 extend a file with ftruncate. Provide alternate implementation
2664 /* Do an fstat to see if the file is longer than the requested
2665 size in which case the ftruncate above should have
2666 succeeded or shorter, in which case seek to len - 1 and
2667 write 1 byte of zero */
2668 status = vfs_stat_fsp(fsp);
2669 if (!NT_STATUS_IS_OK(status)) {
2673 /* We need to update the files_struct after successful ftruncate */
2678 pst = &fsp->fsp_name->st;
2681 if (S_ISFIFO(pst->st_ex_mode)) {
2687 if (pst->st_ex_size == len) {
2692 if (pst->st_ex_size > len) {
2693 /* the ftruncate should have worked */
2697 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2705 END_PROFILE(syscall_ftruncate);
2709 static int vfswrap_fallocate(vfs_handle_struct *handle,
2717 START_PROFILE(syscall_fallocate);
2719 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2721 * posix_fallocate returns 0 on success, errno on error
2722 * and doesn't set errno. Make it behave like fallocate()
2723 * which returns -1, and sets errno on failure.
2730 /* sys_fallocate handles filtering of unsupported mode flags */
2731 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2733 END_PROFILE(syscall_fallocate);
2737 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2741 START_PROFILE(syscall_fcntl_lock);
2743 if (fsp->fsp_flags.use_ofd_locks) {
2744 op = map_process_lock_to_ofd_lock(op);
2747 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2748 END_PROFILE(syscall_fcntl_lock);
2752 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2753 uint32_t share_access, uint32_t access_mask)
2755 START_PROFILE(syscall_kernel_flock);
2756 kernel_flock(fsp->fh->fd, share_access, access_mask);
2757 END_PROFILE(syscall_kernel_flock);
2761 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2765 va_list dup_cmd_arg;
2769 START_PROFILE(syscall_fcntl);
2771 va_copy(dup_cmd_arg, cmd_arg);
2777 #if defined(HAVE_OFD_LOCKS)
2782 #if defined(HAVE_F_OWNER_EX)
2786 #if defined(HAVE_RW_HINTS)
2789 case F_GET_FILE_RW_HINT:
2790 case F_SET_FILE_RW_HINT:
2792 argp = va_arg(dup_cmd_arg, void *);
2793 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2796 val = va_arg(dup_cmd_arg, int);
2797 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2800 va_end(dup_cmd_arg);
2802 END_PROFILE(syscall_fcntl);
2806 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2811 START_PROFILE(syscall_fcntl_getlock);
2813 if (fsp->fsp_flags.use_ofd_locks) {
2814 op = map_process_lock_to_ofd_lock(op);
2817 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2818 END_PROFILE(syscall_fcntl_getlock);
2822 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2827 START_PROFILE(syscall_linux_setlease);
2829 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2830 result = linux_setlease(fsp->fh->fd, leasetype);
2834 END_PROFILE(syscall_linux_setlease);
2838 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2839 const struct smb_filename *link_target,
2840 struct files_struct *dirfsp,
2841 const struct smb_filename *new_smb_fname)
2845 START_PROFILE(syscall_symlinkat);
2847 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2849 result = symlinkat(link_target->base_name,
2851 new_smb_fname->base_name);
2852 END_PROFILE(syscall_symlinkat);
2856 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2857 files_struct *dirfsp,
2858 const struct smb_filename *smb_fname,
2864 START_PROFILE(syscall_readlinkat);
2866 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2868 result = readlinkat(dirfsp->fh->fd,
2869 smb_fname->base_name,
2873 END_PROFILE(syscall_readlinkat);
2877 static int vfswrap_linkat(vfs_handle_struct *handle,
2878 files_struct *srcfsp,
2879 const struct smb_filename *old_smb_fname,
2880 files_struct *dstfsp,
2881 const struct smb_filename *new_smb_fname,
2886 START_PROFILE(syscall_linkat);
2888 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2889 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2891 result = linkat(srcfsp->fh->fd,
2892 old_smb_fname->base_name,
2894 new_smb_fname->base_name,
2897 END_PROFILE(syscall_linkat);
2901 static int vfswrap_mknodat(vfs_handle_struct *handle,
2902 files_struct *dirfsp,
2903 const struct smb_filename *smb_fname,
2909 START_PROFILE(syscall_mknodat);
2911 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2913 result = sys_mknodat(dirfsp->fh->fd,
2914 smb_fname->base_name,
2918 END_PROFILE(syscall_mknodat);
2922 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2924 const struct smb_filename *smb_fname)
2927 struct smb_filename *result_fname = NULL;
2929 START_PROFILE(syscall_realpath);
2930 result = sys_realpath(smb_fname->base_name);
2931 END_PROFILE(syscall_realpath);
2933 result_fname = synthetic_smb_fname(ctx,
2941 return result_fname;
2944 static int vfswrap_chflags(vfs_handle_struct *handle,
2945 const struct smb_filename *smb_fname,
2949 return chflags(smb_fname->base_name, flags);
2956 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2957 const SMB_STRUCT_STAT *sbuf)
2961 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2965 key.devid = sbuf->st_ex_dev;
2966 key.inode = sbuf->st_ex_ino;
2967 /* key.extid is unused by default. */
2972 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2973 const SMB_STRUCT_STAT *psbuf)
2977 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2978 return psbuf->st_ex_file_id;
2981 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2982 return (uint64_t)psbuf->st_ex_ino;
2986 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2989 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
2994 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2995 struct files_struct *fsp,
2996 const struct smb_filename *smb_fname,
2997 TALLOC_CTX *mem_ctx,
2998 unsigned int *pnum_streams,
2999 struct stream_struct **pstreams)
3001 SMB_STRUCT_STAT sbuf;
3002 struct stream_struct *tmp_streams = NULL;
3005 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3007 * No default streams on directories
3012 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3013 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3016 struct smb_filename *smb_fname_cp = NULL;
3018 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3019 if (smb_fname_cp == NULL) {
3020 return NT_STATUS_NO_MEMORY;
3023 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3024 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3026 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3028 sbuf = smb_fname_cp->st;
3029 TALLOC_FREE(smb_fname_cp);
3033 return map_nt_error_from_unix(errno);
3036 if (S_ISDIR(sbuf.st_ex_mode)) {
3040 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3041 (*pnum_streams) + 1);
3042 if (tmp_streams == NULL) {
3043 return NT_STATUS_NO_MEMORY;
3045 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3046 if (tmp_streams[*pnum_streams].name == NULL) {
3047 return NT_STATUS_NO_MEMORY;
3049 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3050 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3053 *pstreams = tmp_streams;
3055 return NT_STATUS_OK;
3058 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3059 const struct smb_filename *path,
3061 TALLOC_CTX *mem_ctx,
3065 * Don't fall back to get_real_filename so callers can differentiate
3066 * between a full directory scan and an actual case-insensitive stat.
3072 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3073 const struct smb_filename *smb_fname)
3075 return handle->conn->connectpath;
3078 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3079 struct byte_range_lock *br_lck,
3080 struct lock_struct *plock)
3082 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3084 /* Note: blr is not used in the default implementation. */
3085 return brl_lock_windows_default(br_lck, plock);
3088 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3089 struct byte_range_lock *br_lck,
3090 const struct lock_struct *plock)
3092 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3094 return brl_unlock_windows_default(br_lck, plock);
3097 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3099 struct lock_struct *plock)
3101 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3102 plock->lock_type == WRITE_LOCK);
3104 return strict_lock_check_default(fsp, plock);
3107 /* NT ACL operations. */
3109 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3111 uint32_t security_info,
3112 TALLOC_CTX *mem_ctx,
3113 struct security_descriptor **ppdesc)
3117 START_PROFILE(fget_nt_acl);
3118 result = posix_fget_nt_acl(fsp, security_info,
3120 END_PROFILE(fget_nt_acl);
3124 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3125 const struct smb_filename *smb_fname,
3126 uint32_t security_info,
3127 TALLOC_CTX *mem_ctx,
3128 struct security_descriptor **ppdesc)
3132 START_PROFILE(get_nt_acl);
3133 result = posix_get_nt_acl(handle->conn,
3138 END_PROFILE(get_nt_acl);
3142 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3146 START_PROFILE(fset_nt_acl);
3147 result = set_nt_acl(fsp, security_info_sent, psd);
3148 END_PROFILE(fset_nt_acl);
3152 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3153 struct smb_filename *file,
3154 struct security_acl *sacl,
3155 uint32_t access_requested,
3156 uint32_t access_denied)
3158 return NT_STATUS_OK; /* Nothing to do here ... */
3161 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3162 const struct smb_filename *smb_fname,
3163 SMB_ACL_TYPE_T type,
3164 TALLOC_CTX *mem_ctx)
3166 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3169 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3171 TALLOC_CTX *mem_ctx)
3173 return sys_acl_get_fd(handle, fsp, mem_ctx);
3176 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3177 const struct smb_filename *smb_fname,
3178 SMB_ACL_TYPE_T acltype,
3181 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3184 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3186 return sys_acl_set_fd(handle, fsp, theacl);
3189 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3190 const struct smb_filename *smb_fname)
3192 return sys_acl_delete_def_file(handle, smb_fname);
3195 /****************************************************************
3196 Extended attribute operations.
3197 *****************************************************************/
3199 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3200 const struct smb_filename *smb_fname,
3205 return getxattr(smb_fname->base_name, name, value, size);
3208 struct vfswrap_getxattrat_state {
3209 struct tevent_context *ev;
3210 files_struct *dir_fsp;
3211 const struct smb_filename *smb_fname;
3212 struct tevent_req *req;
3215 * The following variables are talloced off "state" which is protected
3216 * by a destructor and thus are guaranteed to be safe to be used in the
3217 * job function in the worker thread.
3220 const char *xattr_name;
3221 uint8_t *xattr_value;
3222 struct security_unix_token *token;
3225 struct vfs_aio_state vfs_aio_state;
3226 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3229 static int vfswrap_getxattrat_state_destructor(
3230 struct vfswrap_getxattrat_state *state)
3235 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3236 static void vfswrap_getxattrat_do_async(void *private_data);
3237 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3239 static struct tevent_req *vfswrap_getxattrat_send(
3240 TALLOC_CTX *mem_ctx,
3241 struct tevent_context *ev,
3242 struct vfs_handle_struct *handle,
3243 files_struct *dir_fsp,
3244 const struct smb_filename *smb_fname,
3245 const char *xattr_name,
3248 struct tevent_req *req = NULL;
3249 struct tevent_req *subreq = NULL;
3250 struct vfswrap_getxattrat_state *state = NULL;
3251 size_t max_threads = 0;
3252 bool have_per_thread_cwd = false;
3253 bool have_per_thread_creds = false;
3254 bool do_async = false;
3256 req = tevent_req_create(mem_ctx, &state,
3257 struct vfswrap_getxattrat_state);
3261 *state = (struct vfswrap_getxattrat_state) {
3264 .smb_fname = smb_fname,
3268 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3269 if (max_threads >= 1) {
3271 * We need a non sync threadpool!
3273 have_per_thread_cwd = per_thread_cwd_supported();
3275 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3276 have_per_thread_creds = true;
3278 if (have_per_thread_cwd && have_per_thread_creds) {
3282 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3283 state->profile_bytes, 0);
3285 if (dir_fsp->fh->fd == -1) {
3286 DBG_ERR("Need a valid directory fd\n");
3287 tevent_req_error(req, EINVAL);
3288 return tevent_req_post(req, ev);
3291 if (alloc_hint > 0) {
3292 state->xattr_value = talloc_zero_array(state,
3295 if (tevent_req_nomem(state->xattr_value, req)) {
3296 return tevent_req_post(req, ev);
3301 vfswrap_getxattrat_do_sync(req);
3302 return tevent_req_post(req, ev);
3306 * Now allocate all parameters from a memory context that won't go away
3307 * no matter what. These paremeters will get used in threads and we
3308 * can't reliably cancel threads, so all buffers passed to the threads
3309 * must not be freed before all referencing threads terminate.
3312 state->name = talloc_strdup(state, smb_fname->base_name);
3313 if (tevent_req_nomem(state->name, req)) {
3314 return tevent_req_post(req, ev);
3317 state->xattr_name = talloc_strdup(state, xattr_name);
3318 if (tevent_req_nomem(state->xattr_name, req)) {
3319 return tevent_req_post(req, ev);
3323 * This is a hot codepath so at first glance one might think we should
3324 * somehow optimize away the token allocation and do a
3325 * talloc_reference() or similar black magic instead. But due to the
3326 * talloc_stackframe pool per SMB2 request this should be a simple copy
3327 * without a malloc in most cases.
3329 if (geteuid() == sec_initial_uid()) {
3330 state->token = root_unix_token(state);
3332 state->token = copy_unix_token(
3334 dir_fsp->conn->session_info->unix_token);
3336 if (tevent_req_nomem(state->token, req)) {
3337 return tevent_req_post(req, ev);
3340 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3342 subreq = pthreadpool_tevent_job_send(
3345 dir_fsp->conn->sconn->pool,
3346 vfswrap_getxattrat_do_async,
3348 if (tevent_req_nomem(subreq, req)) {
3349 return tevent_req_post(req, ev);
3351 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3353 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3358 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3360 struct vfswrap_getxattrat_state *state = tevent_req_data(
3361 req, struct vfswrap_getxattrat_state);
3363 char *tofree = NULL;
3364 char pathbuf[PATH_MAX+1];
3368 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3369 state->smb_fname->base_name,
3374 if (pathlen == -1) {
3375 tevent_req_error(req, ENOMEM);
3379 state->xattr_size = getxattr(path,
3382 talloc_array_length(state->xattr_value));
3384 TALLOC_FREE(tofree);
3385 if (state->xattr_size == -1) {
3386 tevent_req_error(req, err);
3390 tevent_req_done(req);
3394 static void vfswrap_getxattrat_do_async(void *private_data)
3396 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3397 private_data, struct vfswrap_getxattrat_state);
3398 struct timespec start_time;
3399 struct timespec end_time;
3402 PROFILE_TIMESTAMP(&start_time);
3403 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3406 * Here we simulate a getxattrat()
3407 * call using fchdir();getxattr()
3410 per_thread_cwd_activate();
3412 /* Become the correct credential on this thread. */
3413 ret = set_thread_credentials(state->token->uid,
3415 (size_t)state->token->ngroups,
3416 state->token->groups);
3418 state->xattr_size = -1;
3419 state->vfs_aio_state.error = errno;
3423 ret = fchdir(state->dir_fsp->fh->fd);
3425 state->xattr_size = -1;
3426 state->vfs_aio_state.error = errno;
3430 state->xattr_size = getxattr(state->name,
3433 talloc_array_length(state->xattr_value));
3434 if (state->xattr_size == -1) {
3435 state->vfs_aio_state.error = errno;
3439 PROFILE_TIMESTAMP(&end_time);
3440 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3441 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3444 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3446 struct tevent_req *req = tevent_req_callback_data(
3447 subreq, struct tevent_req);
3448 struct vfswrap_getxattrat_state *state = tevent_req_data(
3449 req, struct vfswrap_getxattrat_state);
3454 * Make sure we run as the user again
3456 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3459 ret = pthreadpool_tevent_job_recv(subreq);
3460 TALLOC_FREE(subreq);
3461 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3462 talloc_set_destructor(state, NULL);
3464 if (ret != EAGAIN) {
3465 tevent_req_error(req, ret);
3469 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3470 * means the lower level pthreadpool failed to create a new
3471 * thread. Fallback to sync processing in that case to allow
3472 * some progress for the client.
3474 vfswrap_getxattrat_do_sync(req);
3478 if (state->xattr_size == -1) {
3479 tevent_req_error(req, state->vfs_aio_state.error);
3483 if (state->xattr_value == NULL) {
3485 * The caller only wanted the size.
3487 tevent_req_done(req);
3492 * shrink the buffer to the returned size.
3493 * (can't fail). It means NULL if size is 0.
3495 state->xattr_value = talloc_realloc(state,
3500 tevent_req_done(req);
3503 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3504 struct vfs_aio_state *aio_state,
3505 TALLOC_CTX *mem_ctx,
3506 uint8_t **xattr_value)
3508 struct vfswrap_getxattrat_state *state = tevent_req_data(
3509 req, struct vfswrap_getxattrat_state);
3512 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3513 tevent_req_received(req);
3517 *aio_state = state->vfs_aio_state;
3518 xattr_size = state->xattr_size;
3519 if (xattr_value != NULL) {
3520 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3523 tevent_req_received(req);
3527 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3529 return fgetxattr(fsp->fh->fd, name, value, size);
3532 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3533 const struct smb_filename *smb_fname,
3537 return listxattr(smb_fname->base_name, list, size);
3540 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3542 return flistxattr(fsp->fh->fd, list, size);
3545 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3546 const struct smb_filename *smb_fname,
3549 return removexattr(smb_fname->base_name, name);
3552 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3554 return fremovexattr(fsp->fh->fd, name);
3557 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3558 const struct smb_filename *smb_fname,
3564 return setxattr(smb_fname->base_name, name, value, size, flags);
3567 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3569 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3572 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3577 static bool vfswrap_is_offline(struct connection_struct *conn,
3578 const struct smb_filename *fname)
3582 bool offline = false;
3584 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3588 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3589 #if defined(ENOTSUP)
3595 status = get_full_smb_filename(talloc_tos(), fname, &path);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 errno = map_errno_from_nt_status(status);
3601 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3608 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3609 struct files_struct *fsp,
3610 TALLOC_CTX *mem_ctx,
3613 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3616 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3617 struct files_struct *fsp,
3618 const DATA_BLOB old_cookie,
3619 TALLOC_CTX *mem_ctx,
3620 DATA_BLOB *new_cookie)
3622 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3626 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3627 struct smb_request *smb1req,
3628 struct smbXsrv_open *op,
3629 const DATA_BLOB old_cookie,
3630 TALLOC_CTX *mem_ctx,
3631 struct files_struct **fsp,
3632 DATA_BLOB *new_cookie)
3634 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3635 old_cookie, mem_ctx,
3639 static struct vfs_fn_pointers vfs_default_fns = {
3640 /* Disk operations */
3642 .connect_fn = vfswrap_connect,
3643 .disconnect_fn = vfswrap_disconnect,
3644 .disk_free_fn = vfswrap_disk_free,
3645 .get_quota_fn = vfswrap_get_quota,
3646 .set_quota_fn = vfswrap_set_quota,
3647 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3648 .statvfs_fn = vfswrap_statvfs,
3649 .fs_capabilities_fn = vfswrap_fs_capabilities,
3650 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3651 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3652 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3653 .snap_check_path_fn = vfswrap_snap_check_path,
3654 .snap_create_fn = vfswrap_snap_create,
3655 .snap_delete_fn = vfswrap_snap_delete,
3657 /* Directory operations */
3659 .fdopendir_fn = vfswrap_fdopendir,
3660 .readdir_fn = vfswrap_readdir,
3661 .readdir_attr_fn = vfswrap_readdir_attr,
3662 .seekdir_fn = vfswrap_seekdir,
3663 .telldir_fn = vfswrap_telldir,
3664 .rewind_dir_fn = vfswrap_rewinddir,
3665 .mkdirat_fn = vfswrap_mkdirat,
3666 .closedir_fn = vfswrap_closedir,
3668 /* File operations */
3670 .open_fn = vfswrap_open,
3671 .create_file_fn = vfswrap_create_file,
3672 .close_fn = vfswrap_close,
3673 .pread_fn = vfswrap_pread,
3674 .pread_send_fn = vfswrap_pread_send,
3675 .pread_recv_fn = vfswrap_pread_recv,
3676 .pwrite_fn = vfswrap_pwrite,
3677 .pwrite_send_fn = vfswrap_pwrite_send,
3678 .pwrite_recv_fn = vfswrap_pwrite_recv,
3679 .lseek_fn = vfswrap_lseek,
3680 .sendfile_fn = vfswrap_sendfile,
3681 .recvfile_fn = vfswrap_recvfile,
3682 .renameat_fn = vfswrap_renameat,
3683 .fsync_send_fn = vfswrap_fsync_send,
3684 .fsync_recv_fn = vfswrap_fsync_recv,
3685 .stat_fn = vfswrap_stat,
3686 .fstat_fn = vfswrap_fstat,
3687 .lstat_fn = vfswrap_lstat,
3688 .get_alloc_size_fn = vfswrap_get_alloc_size,
3689 .unlinkat_fn = vfswrap_unlinkat,
3690 .chmod_fn = vfswrap_chmod,
3691 .fchmod_fn = vfswrap_fchmod,
3692 .fchown_fn = vfswrap_fchown,
3693 .lchown_fn = vfswrap_lchown,
3694 .chdir_fn = vfswrap_chdir,
3695 .getwd_fn = vfswrap_getwd,
3696 .ntimes_fn = vfswrap_ntimes,
3697 .ftruncate_fn = vfswrap_ftruncate,
3698 .fallocate_fn = vfswrap_fallocate,
3699 .lock_fn = vfswrap_lock,
3700 .kernel_flock_fn = vfswrap_kernel_flock,
3701 .fcntl_fn = vfswrap_fcntl,
3702 .linux_setlease_fn = vfswrap_linux_setlease,
3703 .getlock_fn = vfswrap_getlock,
3704 .symlinkat_fn = vfswrap_symlinkat,
3705 .readlinkat_fn = vfswrap_readlinkat,
3706 .linkat_fn = vfswrap_linkat,
3707 .mknodat_fn = vfswrap_mknodat,
3708 .realpath_fn = vfswrap_realpath,
3709 .chflags_fn = vfswrap_chflags,
3710 .file_id_create_fn = vfswrap_file_id_create,
3711 .fs_file_id_fn = vfswrap_fs_file_id,
3712 .streaminfo_fn = vfswrap_streaminfo,
3713 .get_real_filename_fn = vfswrap_get_real_filename,
3714 .connectpath_fn = vfswrap_connectpath,
3715 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3716 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3717 .strict_lock_check_fn = vfswrap_strict_lock_check,
3718 .translate_name_fn = vfswrap_translate_name,
3719 .fsctl_fn = vfswrap_fsctl,
3720 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3721 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3722 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3723 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3724 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3725 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3726 .offload_read_send_fn = vfswrap_offload_read_send,
3727 .offload_read_recv_fn = vfswrap_offload_read_recv,
3728 .offload_write_send_fn = vfswrap_offload_write_send,
3729 .offload_write_recv_fn = vfswrap_offload_write_recv,
3730 .get_compression_fn = vfswrap_get_compression,
3731 .set_compression_fn = vfswrap_set_compression,
3733 /* NT ACL operations. */
3735 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3736 .get_nt_acl_fn = vfswrap_get_nt_acl,
3737 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3738 .audit_file_fn = vfswrap_audit_file,
3740 /* POSIX ACL operations. */
3742 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3743 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3744 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3745 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3746 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3747 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3748 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3750 /* EA operations. */
3751 .getxattr_fn = vfswrap_getxattr,
3752 .getxattrat_send_fn = vfswrap_getxattrat_send,
3753 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3754 .fgetxattr_fn = vfswrap_fgetxattr,
3755 .listxattr_fn = vfswrap_listxattr,
3756 .flistxattr_fn = vfswrap_flistxattr,
3757 .removexattr_fn = vfswrap_removexattr,
3758 .fremovexattr_fn = vfswrap_fremovexattr,
3759 .setxattr_fn = vfswrap_setxattr,
3760 .fsetxattr_fn = vfswrap_fsetxattr,
3762 /* aio operations */
3763 .aio_force_fn = vfswrap_aio_force,
3765 /* durable handle operations */
3766 .durable_cookie_fn = vfswrap_durable_cookie,
3767 .durable_disconnect_fn = vfswrap_durable_disconnect,
3768 .durable_reconnect_fn = vfswrap_durable_reconnect,
3772 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3775 * Here we need to implement every call!
3777 * As this is the end of the vfs module chain.
3779 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3780 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3781 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);