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;
2584 ok = vfs_valid_pwrite_range(len, 0);
2590 status = vfs_stat_fsp(fsp);
2591 if (!NT_STATUS_IS_OK(status)) {
2594 pst = &fsp->fsp_name->st;
2597 if (S_ISFIFO(pst->st_ex_mode))
2601 if (pst->st_ex_size == len)
2604 /* Shrink - just ftruncate. */
2605 if (pst->st_ex_size > len)
2606 return ftruncate(fsp->fh->fd, len);
2608 space_to_write = len - pst->st_ex_size;
2610 /* for allocation try fallocate first. This can fail on some
2611 platforms e.g. when the filesystem doesn't support it and no
2612 emulation is being done by the libc (like on AIX with JFS1). In that
2613 case we do our own emulation. fallocate implementations can
2614 return ENOTSUP or EINVAL in cases like that. */
2615 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2616 if (ret == -1 && errno == ENOSPC) {
2622 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2623 "error %d. Falling back to slow manual allocation\n", errno));
2625 /* available disk space is enough or not? */
2627 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2628 /* space_avail is 1k blocks */
2629 if (space_avail == (uint64_t)-1 ||
2630 ((uint64_t)space_to_write/1024 > space_avail) ) {
2635 /* Write out the real space on disk. */
2636 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2644 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2647 SMB_STRUCT_STAT *pst;
2651 START_PROFILE(syscall_ftruncate);
2653 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2654 result = strict_allocate_ftruncate(handle, fsp, len);
2655 END_PROFILE(syscall_ftruncate);
2659 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2660 ftruncate if the system supports it. Then I discovered that
2661 you can have some filesystems that support ftruncate
2662 expansion and some that don't! On Linux fat can't do
2663 ftruncate extend but ext2 can. */
2665 result = ftruncate(fsp->fh->fd, len);
2667 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2668 extend a file with ftruncate. Provide alternate implementation
2671 /* Do an fstat to see if the file is longer than the requested
2672 size in which case the ftruncate above should have
2673 succeeded or shorter, in which case seek to len - 1 and
2674 write 1 byte of zero */
2675 status = vfs_stat_fsp(fsp);
2676 if (!NT_STATUS_IS_OK(status)) {
2680 /* We need to update the files_struct after successful ftruncate */
2685 pst = &fsp->fsp_name->st;
2688 if (S_ISFIFO(pst->st_ex_mode)) {
2694 if (pst->st_ex_size == len) {
2699 if (pst->st_ex_size > len) {
2700 /* the ftruncate should have worked */
2704 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2712 END_PROFILE(syscall_ftruncate);
2716 static int vfswrap_fallocate(vfs_handle_struct *handle,
2724 START_PROFILE(syscall_fallocate);
2726 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2728 * posix_fallocate returns 0 on success, errno on error
2729 * and doesn't set errno. Make it behave like fallocate()
2730 * which returns -1, and sets errno on failure.
2737 /* sys_fallocate handles filtering of unsupported mode flags */
2738 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2740 END_PROFILE(syscall_fallocate);
2744 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2748 START_PROFILE(syscall_fcntl_lock);
2750 if (fsp->fsp_flags.use_ofd_locks) {
2751 op = map_process_lock_to_ofd_lock(op);
2754 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2755 END_PROFILE(syscall_fcntl_lock);
2759 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2760 uint32_t share_access, uint32_t access_mask)
2762 START_PROFILE(syscall_kernel_flock);
2763 kernel_flock(fsp->fh->fd, share_access, access_mask);
2764 END_PROFILE(syscall_kernel_flock);
2768 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2772 va_list dup_cmd_arg;
2776 START_PROFILE(syscall_fcntl);
2778 va_copy(dup_cmd_arg, cmd_arg);
2784 #if defined(HAVE_OFD_LOCKS)
2789 #if defined(HAVE_F_OWNER_EX)
2793 #if defined(HAVE_RW_HINTS)
2796 case F_GET_FILE_RW_HINT:
2797 case F_SET_FILE_RW_HINT:
2799 argp = va_arg(dup_cmd_arg, void *);
2800 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2803 val = va_arg(dup_cmd_arg, int);
2804 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2807 va_end(dup_cmd_arg);
2809 END_PROFILE(syscall_fcntl);
2813 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2818 START_PROFILE(syscall_fcntl_getlock);
2820 if (fsp->fsp_flags.use_ofd_locks) {
2821 op = map_process_lock_to_ofd_lock(op);
2824 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2825 END_PROFILE(syscall_fcntl_getlock);
2829 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2834 START_PROFILE(syscall_linux_setlease);
2836 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2837 result = linux_setlease(fsp->fh->fd, leasetype);
2841 END_PROFILE(syscall_linux_setlease);
2845 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2846 const struct smb_filename *link_target,
2847 struct files_struct *dirfsp,
2848 const struct smb_filename *new_smb_fname)
2852 START_PROFILE(syscall_symlinkat);
2854 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2856 result = symlinkat(link_target->base_name,
2858 new_smb_fname->base_name);
2859 END_PROFILE(syscall_symlinkat);
2863 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2864 files_struct *dirfsp,
2865 const struct smb_filename *smb_fname,
2871 START_PROFILE(syscall_readlinkat);
2873 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2875 result = readlinkat(dirfsp->fh->fd,
2876 smb_fname->base_name,
2880 END_PROFILE(syscall_readlinkat);
2884 static int vfswrap_linkat(vfs_handle_struct *handle,
2885 files_struct *srcfsp,
2886 const struct smb_filename *old_smb_fname,
2887 files_struct *dstfsp,
2888 const struct smb_filename *new_smb_fname,
2893 START_PROFILE(syscall_linkat);
2895 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2896 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2898 result = linkat(srcfsp->fh->fd,
2899 old_smb_fname->base_name,
2901 new_smb_fname->base_name,
2904 END_PROFILE(syscall_linkat);
2908 static int vfswrap_mknodat(vfs_handle_struct *handle,
2909 files_struct *dirfsp,
2910 const struct smb_filename *smb_fname,
2916 START_PROFILE(syscall_mknodat);
2918 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2920 result = sys_mknodat(dirfsp->fh->fd,
2921 smb_fname->base_name,
2925 END_PROFILE(syscall_mknodat);
2929 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2931 const struct smb_filename *smb_fname)
2934 struct smb_filename *result_fname = NULL;
2936 START_PROFILE(syscall_realpath);
2937 result = sys_realpath(smb_fname->base_name);
2938 END_PROFILE(syscall_realpath);
2940 result_fname = synthetic_smb_fname(ctx,
2948 return result_fname;
2951 static int vfswrap_chflags(vfs_handle_struct *handle,
2952 const struct smb_filename *smb_fname,
2956 return chflags(smb_fname->base_name, flags);
2963 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2964 const SMB_STRUCT_STAT *sbuf)
2968 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2972 key.devid = sbuf->st_ex_dev;
2973 key.inode = sbuf->st_ex_ino;
2974 /* key.extid is unused by default. */
2979 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2980 const SMB_STRUCT_STAT *psbuf)
2984 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2985 return psbuf->st_ex_file_id;
2988 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2989 return (uint64_t)psbuf->st_ex_ino;
2993 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2996 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3001 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3002 struct files_struct *fsp,
3003 const struct smb_filename *smb_fname,
3004 TALLOC_CTX *mem_ctx,
3005 unsigned int *pnum_streams,
3006 struct stream_struct **pstreams)
3008 SMB_STRUCT_STAT sbuf;
3009 struct stream_struct *tmp_streams = NULL;
3012 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3014 * No default streams on directories
3019 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3020 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3023 struct smb_filename *smb_fname_cp = NULL;
3025 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3026 if (smb_fname_cp == NULL) {
3027 return NT_STATUS_NO_MEMORY;
3030 if (smb_fname_cp->flags & SMB_FILENAME_POSIX_PATH) {
3031 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_cp);
3033 ret = SMB_VFS_STAT(handle->conn, smb_fname_cp);
3035 sbuf = smb_fname_cp->st;
3036 TALLOC_FREE(smb_fname_cp);
3040 return map_nt_error_from_unix(errno);
3043 if (S_ISDIR(sbuf.st_ex_mode)) {
3047 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3048 (*pnum_streams) + 1);
3049 if (tmp_streams == NULL) {
3050 return NT_STATUS_NO_MEMORY;
3052 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3053 if (tmp_streams[*pnum_streams].name == NULL) {
3054 return NT_STATUS_NO_MEMORY;
3056 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3057 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3060 *pstreams = tmp_streams;
3062 return NT_STATUS_OK;
3065 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3066 const struct smb_filename *path,
3068 TALLOC_CTX *mem_ctx,
3072 * Don't fall back to get_real_filename so callers can differentiate
3073 * between a full directory scan and an actual case-insensitive stat.
3079 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3080 const struct smb_filename *smb_fname)
3082 return handle->conn->connectpath;
3085 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3086 struct byte_range_lock *br_lck,
3087 struct lock_struct *plock)
3089 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3091 /* Note: blr is not used in the default implementation. */
3092 return brl_lock_windows_default(br_lck, plock);
3095 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3096 struct byte_range_lock *br_lck,
3097 const struct lock_struct *plock)
3099 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3101 return brl_unlock_windows_default(br_lck, plock);
3104 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3106 struct lock_struct *plock)
3108 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3109 plock->lock_type == WRITE_LOCK);
3111 return strict_lock_check_default(fsp, plock);
3114 /* NT ACL operations. */
3116 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3118 uint32_t security_info,
3119 TALLOC_CTX *mem_ctx,
3120 struct security_descriptor **ppdesc)
3124 START_PROFILE(fget_nt_acl);
3125 result = posix_fget_nt_acl(fsp, security_info,
3127 END_PROFILE(fget_nt_acl);
3131 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3132 struct files_struct *dirfsp,
3133 const struct smb_filename *smb_fname,
3134 uint32_t security_info,
3135 TALLOC_CTX *mem_ctx,
3136 struct security_descriptor **ppdesc)
3140 START_PROFILE(get_nt_acl_at);
3142 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3144 result = posix_get_nt_acl(handle->conn,
3149 END_PROFILE(get_nt_acl_at);
3153 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3157 START_PROFILE(fset_nt_acl);
3158 result = set_nt_acl(fsp, security_info_sent, psd);
3159 END_PROFILE(fset_nt_acl);
3163 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3164 struct smb_filename *file,
3165 struct security_acl *sacl,
3166 uint32_t access_requested,
3167 uint32_t access_denied)
3169 return NT_STATUS_OK; /* Nothing to do here ... */
3172 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3173 const struct smb_filename *smb_fname,
3174 SMB_ACL_TYPE_T type,
3175 TALLOC_CTX *mem_ctx)
3177 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3180 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3182 TALLOC_CTX *mem_ctx)
3184 return sys_acl_get_fd(handle, fsp, mem_ctx);
3187 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3188 const struct smb_filename *smb_fname,
3189 SMB_ACL_TYPE_T acltype,
3192 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3195 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3197 return sys_acl_set_fd(handle, fsp, theacl);
3200 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3201 const struct smb_filename *smb_fname)
3203 return sys_acl_delete_def_file(handle, smb_fname);
3206 /****************************************************************
3207 Extended attribute operations.
3208 *****************************************************************/
3210 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3211 const struct smb_filename *smb_fname,
3216 return getxattr(smb_fname->base_name, name, value, size);
3219 struct vfswrap_getxattrat_state {
3220 struct tevent_context *ev;
3221 files_struct *dir_fsp;
3222 const struct smb_filename *smb_fname;
3223 struct tevent_req *req;
3226 * The following variables are talloced off "state" which is protected
3227 * by a destructor and thus are guaranteed to be safe to be used in the
3228 * job function in the worker thread.
3231 const char *xattr_name;
3232 uint8_t *xattr_value;
3233 struct security_unix_token *token;
3236 struct vfs_aio_state vfs_aio_state;
3237 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3240 static int vfswrap_getxattrat_state_destructor(
3241 struct vfswrap_getxattrat_state *state)
3246 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3247 static void vfswrap_getxattrat_do_async(void *private_data);
3248 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3250 static struct tevent_req *vfswrap_getxattrat_send(
3251 TALLOC_CTX *mem_ctx,
3252 struct tevent_context *ev,
3253 struct vfs_handle_struct *handle,
3254 files_struct *dir_fsp,
3255 const struct smb_filename *smb_fname,
3256 const char *xattr_name,
3259 struct tevent_req *req = NULL;
3260 struct tevent_req *subreq = NULL;
3261 struct vfswrap_getxattrat_state *state = NULL;
3262 size_t max_threads = 0;
3263 bool have_per_thread_cwd = false;
3264 bool have_per_thread_creds = false;
3265 bool do_async = false;
3267 req = tevent_req_create(mem_ctx, &state,
3268 struct vfswrap_getxattrat_state);
3272 *state = (struct vfswrap_getxattrat_state) {
3275 .smb_fname = smb_fname,
3279 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3280 if (max_threads >= 1) {
3282 * We need a non sync threadpool!
3284 have_per_thread_cwd = per_thread_cwd_supported();
3286 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3287 have_per_thread_creds = true;
3289 if (have_per_thread_cwd && have_per_thread_creds) {
3293 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3294 state->profile_bytes, 0);
3296 if (dir_fsp->fh->fd == -1) {
3297 DBG_ERR("Need a valid directory fd\n");
3298 tevent_req_error(req, EINVAL);
3299 return tevent_req_post(req, ev);
3302 if (alloc_hint > 0) {
3303 state->xattr_value = talloc_zero_array(state,
3306 if (tevent_req_nomem(state->xattr_value, req)) {
3307 return tevent_req_post(req, ev);
3312 vfswrap_getxattrat_do_sync(req);
3313 return tevent_req_post(req, ev);
3317 * Now allocate all parameters from a memory context that won't go away
3318 * no matter what. These paremeters will get used in threads and we
3319 * can't reliably cancel threads, so all buffers passed to the threads
3320 * must not be freed before all referencing threads terminate.
3323 state->name = talloc_strdup(state, smb_fname->base_name);
3324 if (tevent_req_nomem(state->name, req)) {
3325 return tevent_req_post(req, ev);
3328 state->xattr_name = talloc_strdup(state, xattr_name);
3329 if (tevent_req_nomem(state->xattr_name, req)) {
3330 return tevent_req_post(req, ev);
3334 * This is a hot codepath so at first glance one might think we should
3335 * somehow optimize away the token allocation and do a
3336 * talloc_reference() or similar black magic instead. But due to the
3337 * talloc_stackframe pool per SMB2 request this should be a simple copy
3338 * without a malloc in most cases.
3340 if (geteuid() == sec_initial_uid()) {
3341 state->token = root_unix_token(state);
3343 state->token = copy_unix_token(
3345 dir_fsp->conn->session_info->unix_token);
3347 if (tevent_req_nomem(state->token, req)) {
3348 return tevent_req_post(req, ev);
3351 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3353 subreq = pthreadpool_tevent_job_send(
3356 dir_fsp->conn->sconn->pool,
3357 vfswrap_getxattrat_do_async,
3359 if (tevent_req_nomem(subreq, req)) {
3360 return tevent_req_post(req, ev);
3362 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3364 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3369 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3371 struct vfswrap_getxattrat_state *state = tevent_req_data(
3372 req, struct vfswrap_getxattrat_state);
3374 char *tofree = NULL;
3375 char pathbuf[PATH_MAX+1];
3379 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3380 state->smb_fname->base_name,
3385 if (pathlen == -1) {
3386 tevent_req_error(req, ENOMEM);
3390 state->xattr_size = getxattr(path,
3393 talloc_array_length(state->xattr_value));
3395 TALLOC_FREE(tofree);
3396 if (state->xattr_size == -1) {
3397 tevent_req_error(req, err);
3401 tevent_req_done(req);
3405 static void vfswrap_getxattrat_do_async(void *private_data)
3407 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3408 private_data, struct vfswrap_getxattrat_state);
3409 struct timespec start_time;
3410 struct timespec end_time;
3413 PROFILE_TIMESTAMP(&start_time);
3414 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3417 * Here we simulate a getxattrat()
3418 * call using fchdir();getxattr()
3421 per_thread_cwd_activate();
3423 /* Become the correct credential on this thread. */
3424 ret = set_thread_credentials(state->token->uid,
3426 (size_t)state->token->ngroups,
3427 state->token->groups);
3429 state->xattr_size = -1;
3430 state->vfs_aio_state.error = errno;
3434 ret = fchdir(state->dir_fsp->fh->fd);
3436 state->xattr_size = -1;
3437 state->vfs_aio_state.error = errno;
3441 state->xattr_size = getxattr(state->name,
3444 talloc_array_length(state->xattr_value));
3445 if (state->xattr_size == -1) {
3446 state->vfs_aio_state.error = errno;
3450 PROFILE_TIMESTAMP(&end_time);
3451 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3452 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3455 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3457 struct tevent_req *req = tevent_req_callback_data(
3458 subreq, struct tevent_req);
3459 struct vfswrap_getxattrat_state *state = tevent_req_data(
3460 req, struct vfswrap_getxattrat_state);
3465 * Make sure we run as the user again
3467 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3470 ret = pthreadpool_tevent_job_recv(subreq);
3471 TALLOC_FREE(subreq);
3472 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3473 talloc_set_destructor(state, NULL);
3475 if (ret != EAGAIN) {
3476 tevent_req_error(req, ret);
3480 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3481 * means the lower level pthreadpool failed to create a new
3482 * thread. Fallback to sync processing in that case to allow
3483 * some progress for the client.
3485 vfswrap_getxattrat_do_sync(req);
3489 if (state->xattr_size == -1) {
3490 tevent_req_error(req, state->vfs_aio_state.error);
3494 if (state->xattr_value == NULL) {
3496 * The caller only wanted the size.
3498 tevent_req_done(req);
3503 * shrink the buffer to the returned size.
3504 * (can't fail). It means NULL if size is 0.
3506 state->xattr_value = talloc_realloc(state,
3511 tevent_req_done(req);
3514 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3515 struct vfs_aio_state *aio_state,
3516 TALLOC_CTX *mem_ctx,
3517 uint8_t **xattr_value)
3519 struct vfswrap_getxattrat_state *state = tevent_req_data(
3520 req, struct vfswrap_getxattrat_state);
3523 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3524 tevent_req_received(req);
3528 *aio_state = state->vfs_aio_state;
3529 xattr_size = state->xattr_size;
3530 if (xattr_value != NULL) {
3531 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3534 tevent_req_received(req);
3538 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3540 return fgetxattr(fsp->fh->fd, name, value, size);
3543 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3544 const struct smb_filename *smb_fname,
3548 return listxattr(smb_fname->base_name, list, size);
3551 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3553 return flistxattr(fsp->fh->fd, list, size);
3556 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3557 const struct smb_filename *smb_fname,
3560 return removexattr(smb_fname->base_name, name);
3563 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3565 return fremovexattr(fsp->fh->fd, name);
3568 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3569 const struct smb_filename *smb_fname,
3575 return setxattr(smb_fname->base_name, name, value, size, flags);
3578 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3580 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3583 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3588 static bool vfswrap_is_offline(struct connection_struct *conn,
3589 const struct smb_filename *fname)
3593 bool offline = false;
3595 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3599 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3600 #if defined(ENOTSUP)
3606 status = get_full_smb_filename(talloc_tos(), fname, &path);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 errno = map_errno_from_nt_status(status);
3612 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3619 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3620 struct files_struct *fsp,
3621 TALLOC_CTX *mem_ctx,
3624 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3627 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3628 struct files_struct *fsp,
3629 const DATA_BLOB old_cookie,
3630 TALLOC_CTX *mem_ctx,
3631 DATA_BLOB *new_cookie)
3633 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3637 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3638 struct smb_request *smb1req,
3639 struct smbXsrv_open *op,
3640 const DATA_BLOB old_cookie,
3641 TALLOC_CTX *mem_ctx,
3642 struct files_struct **fsp,
3643 DATA_BLOB *new_cookie)
3645 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3646 old_cookie, mem_ctx,
3650 static struct vfs_fn_pointers vfs_default_fns = {
3651 /* Disk operations */
3653 .connect_fn = vfswrap_connect,
3654 .disconnect_fn = vfswrap_disconnect,
3655 .disk_free_fn = vfswrap_disk_free,
3656 .get_quota_fn = vfswrap_get_quota,
3657 .set_quota_fn = vfswrap_set_quota,
3658 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3659 .statvfs_fn = vfswrap_statvfs,
3660 .fs_capabilities_fn = vfswrap_fs_capabilities,
3661 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3662 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3663 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3664 .snap_check_path_fn = vfswrap_snap_check_path,
3665 .snap_create_fn = vfswrap_snap_create,
3666 .snap_delete_fn = vfswrap_snap_delete,
3668 /* Directory operations */
3670 .fdopendir_fn = vfswrap_fdopendir,
3671 .readdir_fn = vfswrap_readdir,
3672 .readdir_attr_fn = vfswrap_readdir_attr,
3673 .seekdir_fn = vfswrap_seekdir,
3674 .telldir_fn = vfswrap_telldir,
3675 .rewind_dir_fn = vfswrap_rewinddir,
3676 .mkdirat_fn = vfswrap_mkdirat,
3677 .closedir_fn = vfswrap_closedir,
3679 /* File operations */
3681 .open_fn = vfswrap_open,
3682 .create_file_fn = vfswrap_create_file,
3683 .close_fn = vfswrap_close,
3684 .pread_fn = vfswrap_pread,
3685 .pread_send_fn = vfswrap_pread_send,
3686 .pread_recv_fn = vfswrap_pread_recv,
3687 .pwrite_fn = vfswrap_pwrite,
3688 .pwrite_send_fn = vfswrap_pwrite_send,
3689 .pwrite_recv_fn = vfswrap_pwrite_recv,
3690 .lseek_fn = vfswrap_lseek,
3691 .sendfile_fn = vfswrap_sendfile,
3692 .recvfile_fn = vfswrap_recvfile,
3693 .renameat_fn = vfswrap_renameat,
3694 .fsync_send_fn = vfswrap_fsync_send,
3695 .fsync_recv_fn = vfswrap_fsync_recv,
3696 .stat_fn = vfswrap_stat,
3697 .fstat_fn = vfswrap_fstat,
3698 .lstat_fn = vfswrap_lstat,
3699 .get_alloc_size_fn = vfswrap_get_alloc_size,
3700 .unlinkat_fn = vfswrap_unlinkat,
3701 .chmod_fn = vfswrap_chmod,
3702 .fchmod_fn = vfswrap_fchmod,
3703 .fchown_fn = vfswrap_fchown,
3704 .lchown_fn = vfswrap_lchown,
3705 .chdir_fn = vfswrap_chdir,
3706 .getwd_fn = vfswrap_getwd,
3707 .ntimes_fn = vfswrap_ntimes,
3708 .ftruncate_fn = vfswrap_ftruncate,
3709 .fallocate_fn = vfswrap_fallocate,
3710 .lock_fn = vfswrap_lock,
3711 .kernel_flock_fn = vfswrap_kernel_flock,
3712 .fcntl_fn = vfswrap_fcntl,
3713 .linux_setlease_fn = vfswrap_linux_setlease,
3714 .getlock_fn = vfswrap_getlock,
3715 .symlinkat_fn = vfswrap_symlinkat,
3716 .readlinkat_fn = vfswrap_readlinkat,
3717 .linkat_fn = vfswrap_linkat,
3718 .mknodat_fn = vfswrap_mknodat,
3719 .realpath_fn = vfswrap_realpath,
3720 .chflags_fn = vfswrap_chflags,
3721 .file_id_create_fn = vfswrap_file_id_create,
3722 .fs_file_id_fn = vfswrap_fs_file_id,
3723 .streaminfo_fn = vfswrap_streaminfo,
3724 .get_real_filename_fn = vfswrap_get_real_filename,
3725 .connectpath_fn = vfswrap_connectpath,
3726 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3727 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3728 .strict_lock_check_fn = vfswrap_strict_lock_check,
3729 .translate_name_fn = vfswrap_translate_name,
3730 .fsctl_fn = vfswrap_fsctl,
3731 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3732 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3733 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3734 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3735 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3736 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3737 .offload_read_send_fn = vfswrap_offload_read_send,
3738 .offload_read_recv_fn = vfswrap_offload_read_recv,
3739 .offload_write_send_fn = vfswrap_offload_write_send,
3740 .offload_write_recv_fn = vfswrap_offload_write_recv,
3741 .get_compression_fn = vfswrap_get_compression,
3742 .set_compression_fn = vfswrap_set_compression,
3744 /* NT ACL operations. */
3746 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3747 .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3748 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3749 .audit_file_fn = vfswrap_audit_file,
3751 /* POSIX ACL operations. */
3753 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3754 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3755 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3756 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3757 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3758 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3759 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3761 /* EA operations. */
3762 .getxattr_fn = vfswrap_getxattr,
3763 .getxattrat_send_fn = vfswrap_getxattrat_send,
3764 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3765 .fgetxattr_fn = vfswrap_fgetxattr,
3766 .listxattr_fn = vfswrap_listxattr,
3767 .flistxattr_fn = vfswrap_flistxattr,
3768 .removexattr_fn = vfswrap_removexattr,
3769 .fremovexattr_fn = vfswrap_fremovexattr,
3770 .setxattr_fn = vfswrap_setxattr,
3771 .fsetxattr_fn = vfswrap_fsetxattr,
3773 /* aio operations */
3774 .aio_force_fn = vfswrap_aio_force,
3776 /* durable handle operations */
3777 .durable_cookie_fn = vfswrap_durable_cookie,
3778 .durable_disconnect_fn = vfswrap_durable_disconnect,
3779 .durable_reconnect_fn = vfswrap_durable_reconnect,
3783 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3786 * Here we need to implement every call!
3788 * As this is the end of the vfs module chain.
3790 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3791 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3792 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);