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(),
139 if (smb_fname_cpath == NULL) {
143 ZERO_STRUCT(statbuf);
144 ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
146 caps = statbuf.FsCapabilities;
149 *p_ts_res = TIMESTAMP_SET_SECONDS;
151 /* Work out what timestamp resolution we can
152 * use when setting a timestamp. */
154 ret = SMB_VFS_STAT(conn, smb_fname_cpath);
156 TALLOC_FREE(smb_fname_cpath);
160 if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
161 smb_fname_cpath->st.st_ex_atime.tv_nsec ||
162 smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
163 /* If any of the normal UNIX directory timestamps
164 * have a non-zero tv_nsec component assume
165 * we might be able to set sub-second timestamps.
166 * See what filetime set primitives we have.
168 #if defined(HAVE_UTIMENSAT)
169 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
170 #elif defined(HAVE_UTIMES)
171 /* utimes allows msec timestamps to be set. */
172 *p_ts_res = TIMESTAMP_SET_MSEC;
173 #elif defined(HAVE_UTIME)
174 /* utime only allows sec timestamps to be set. */
175 *p_ts_res = TIMESTAMP_SET_SECONDS;
178 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
180 "available on share %s, directory %s\n",
181 *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
182 lp_servicename(talloc_tos(), lp_sub, conn->params->service),
183 conn->connectpath ));
185 TALLOC_FREE(smb_fname_cpath);
189 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
190 struct dfs_GetDFSReferral *r)
192 struct junction_map *junction = NULL;
194 bool self_referral = false;
195 char *pathnamep = NULL;
196 char *local_dfs_path = NULL;
199 uint16_t max_referral_level = r->in.req.max_referral_level;
202 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
205 /* get the junction entry */
206 if (r->in.req.servername == NULL) {
207 return NT_STATUS_NOT_FOUND;
211 * Trim pathname sent by client so it begins with only one backslash.
212 * Two backslashes confuse some dfs clients
215 local_dfs_path = talloc_strdup(r, r->in.req.servername);
216 if (local_dfs_path == NULL) {
217 return NT_STATUS_NO_MEMORY;
219 pathnamep = local_dfs_path;
220 while (IS_DIRECTORY_SEP(pathnamep[0]) &&
221 IS_DIRECTORY_SEP(pathnamep[1])) {
225 junction = talloc_zero(r, struct junction_map);
226 if (junction == NULL) {
227 return NT_STATUS_NO_MEMORY;
230 /* The following call can change cwd. */
231 status = get_referred_path(r,
232 handle->conn->session_info,
234 handle->conn->sconn->remote_address,
235 handle->conn->sconn->local_address,
236 !handle->conn->sconn->using_smb2,
237 junction, &consumedcnt, &self_referral);
238 if (!NT_STATUS_IS_OK(status)) {
239 struct smb_filename connectpath_fname = {
240 .base_name = handle->conn->connectpath
242 vfs_ChDir(handle->conn, &connectpath_fname);
246 struct smb_filename connectpath_fname = {
247 .base_name = handle->conn->connectpath
249 vfs_ChDir(handle->conn, &connectpath_fname);
252 if (!self_referral) {
253 pathnamep[consumedcnt] = '\0';
256 dbgtext("Path %s to alternate path(s):",
258 for (i=0; i < junction->referral_count; i++) {
260 junction->referral_list[i].alternate_path);
266 if (r->in.req.max_referral_level <= 2) {
267 max_referral_level = 2;
269 if (r->in.req.max_referral_level >= 3) {
270 max_referral_level = 3;
273 r->out.resp = talloc_zero(r, struct dfs_referral_resp);
274 if (r->out.resp == NULL) {
275 return NT_STATUS_NO_MEMORY;
278 r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
279 r->out.resp->nb_referrals = junction->referral_count;
281 r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
283 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
286 r->out.resp->referral_entries = talloc_zero_array(r,
287 struct dfs_referral_type,
288 r->out.resp->nb_referrals);
289 if (r->out.resp->referral_entries == NULL) {
290 return NT_STATUS_NO_MEMORY;
293 switch (max_referral_level) {
295 for(i=0; i < junction->referral_count; i++) {
296 struct referral *ref = &junction->referral_list[i];
297 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
298 struct dfs_referral_type *t =
299 &r->out.resp->referral_entries[i];
300 struct dfs_referral_v2 *v2 = &t->referral.v2;
303 v2->size = VERSION2_REFERRAL_SIZE;
305 v2->server_type = DFS_SERVER_ROOT;
307 v2->server_type = DFS_SERVER_NON_ROOT;
310 v2->proximity = ref->proximity;
312 v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
313 if (v2->DFS_path == NULL) {
314 return NT_STATUS_NO_MEMORY;
316 v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
317 if (v2->DFS_alt_path == NULL) {
318 return NT_STATUS_NO_MEMORY;
320 v2->netw_address = talloc_strdup(mem_ctx,
321 ref->alternate_path);
322 if (v2->netw_address == NULL) {
323 return NT_STATUS_NO_MEMORY;
329 for(i=0; i < junction->referral_count; i++) {
330 struct referral *ref = &junction->referral_list[i];
331 TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
332 struct dfs_referral_type *t =
333 &r->out.resp->referral_entries[i];
334 struct dfs_referral_v3 *v3 = &t->referral.v3;
335 struct dfs_normal_referral *r1 = &v3->referrals.r1;
338 v3->size = VERSION3_REFERRAL_SIZE;
340 v3->server_type = DFS_SERVER_ROOT;
342 v3->server_type = DFS_SERVER_NON_ROOT;
346 r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
347 if (r1->DFS_path == NULL) {
348 return NT_STATUS_NO_MEMORY;
350 r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
351 if (r1->DFS_alt_path == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 r1->netw_address = talloc_strdup(mem_ctx,
355 ref->alternate_path);
356 if (r1->netw_address == NULL) {
357 return NT_STATUS_NO_MEMORY;
362 DEBUG(0,("Invalid dfs referral version: %d\n",
363 max_referral_level));
364 return NT_STATUS_INVALID_LEVEL;
368 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
374 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
375 struct files_struct *dirfsp,
376 const struct smb_filename *smb_fname,
377 const struct referral *reflist,
378 size_t referral_count)
380 TALLOC_CTX *frame = talloc_stackframe();
381 NTSTATUS status = NT_STATUS_NO_MEMORY;
383 char *msdfs_link = NULL;
385 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
387 /* Form the msdfs_link contents */
388 msdfs_link = msdfs_link_string(frame,
391 if (msdfs_link == NULL) {
395 ret = symlinkat(msdfs_link,
397 smb_fname->base_name);
399 status = NT_STATUS_OK;
401 status = map_nt_error_from_unix(errno);
411 * Read and return the contents of a DFS redirect given a
412 * pathname. A caller can pass in NULL for ppreflist and
413 * preferral_count but still determine if this was a
414 * DFS redirect point by getting NT_STATUS_OK back
415 * without incurring the overhead of reading and parsing
416 * the referral contents.
419 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
421 struct files_struct *dirfsp,
422 const struct smb_filename *smb_fname,
423 struct referral **ppreflist,
424 size_t *preferral_count)
426 NTSTATUS status = NT_STATUS_NO_MEMORY;
428 char *link_target = NULL;
431 #if defined(HAVE_BROKEN_READLINK)
432 char link_target_buf[PATH_MAX];
434 char link_target_buf[7];
437 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
439 if (ppreflist == NULL && preferral_count == NULL) {
441 * We're only checking if this is a DFS
442 * redirect. We don't need to return data.
444 bufsize = sizeof(link_target_buf);
445 link_target = link_target_buf;
448 link_target = talloc_array(mem_ctx, char, bufsize);
454 referral_len = readlinkat(dirfsp->fh->fd,
455 smb_fname->base_name,
458 if (referral_len == -1) {
459 if (errno == EINVAL) {
461 * If the path isn't a link, readlinkat
462 * returns EINVAL. Allow the caller to
465 DBG_INFO("%s is not a link.\n", smb_fname->base_name);
466 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
468 status = map_nt_error_from_unix(errno);
469 DBG_ERR("Error reading "
470 "msdfs link %s: %s\n",
471 smb_fname->base_name,
476 link_target[referral_len] = '\0';
478 DBG_INFO("%s -> %s\n",
479 smb_fname->base_name,
482 if (!strnequal(link_target, "msdfs:", 6)) {
483 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
487 if (ppreflist == NULL && preferral_count == NULL) {
488 /* Early return for checking if this is a DFS link. */
492 ok = parse_msdfs_symlink(mem_ctx,
493 lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
499 status = NT_STATUS_OK;
501 status = NT_STATUS_NO_MEMORY;
506 if (link_target != link_target_buf) {
507 TALLOC_FREE(link_target);
512 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
514 const char *service_path,
517 return NT_STATUS_NOT_SUPPORTED;
520 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
522 const char *base_volume,
528 return NT_STATUS_NOT_SUPPORTED;
531 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
536 return NT_STATUS_NOT_SUPPORTED;
539 /* Directory operations */
541 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
548 START_PROFILE(syscall_fdopendir);
549 result = sys_fdopendir(fsp->fh->fd);
550 END_PROFILE(syscall_fdopendir);
555 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
557 SMB_STRUCT_STAT *sbuf)
559 struct dirent *result;
561 START_PROFILE(syscall_readdir);
562 result = readdir(dirp);
563 END_PROFILE(syscall_readdir);
565 /* Default Posix readdir() does not give us stat info.
566 * Set to invalid to indicate we didn't return this info. */
567 SET_STAT_INVALID(*sbuf);
568 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
569 if (result != NULL) {
570 /* See if we can efficiently return this. */
572 int flags = AT_SYMLINK_NOFOLLOW;
573 int ret = fstatat(dirfd(dirp),
578 * As this is an optimization,
579 * ignore it if we stat'ed a
580 * symlink. Make the caller
581 * do it again as we don't
582 * know if they wanted the link
583 * info, or its target info.
585 if ((ret == 0) && (!S_ISLNK(st.st_mode))) {
586 init_stat_ex_from_stat(sbuf,
588 lp_fake_directory_create_times(
589 SNUM(handle->conn)));
597 static NTSTATUS vfswrap_readdir_attr(struct vfs_handle_struct *handle,
598 const struct smb_filename *fname,
600 struct readdir_attr_data **attr_data)
602 return NT_STATUS_NOT_SUPPORTED;
605 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
607 START_PROFILE(syscall_seekdir);
608 seekdir(dirp, offset);
609 END_PROFILE(syscall_seekdir);
612 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
615 START_PROFILE(syscall_telldir);
616 result = telldir(dirp);
617 END_PROFILE(syscall_telldir);
621 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
623 START_PROFILE(syscall_rewinddir);
625 END_PROFILE(syscall_rewinddir);
628 static int vfswrap_mkdirat(vfs_handle_struct *handle,
629 struct files_struct *dirfsp,
630 const struct smb_filename *smb_fname,
634 struct smb_filename *parent = NULL;
637 START_PROFILE(syscall_mkdirat);
639 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
641 if (lp_inherit_acls(SNUM(handle->conn))) {
642 ok = parent_smb_fname(talloc_tos(), smb_fname, &parent, NULL);
643 if (ok && directory_has_default_acl(handle->conn,
647 mode = (0777 & lp_directory_mask(SNUM(handle->conn)));
653 result = mkdirat(dirfsp->fh->fd, smb_fname->base_name, mode);
655 END_PROFILE(syscall_mkdirat);
659 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
663 START_PROFILE(syscall_closedir);
664 result = closedir(dirp);
665 END_PROFILE(syscall_closedir);
669 /* File operations */
671 static int vfswrap_open(vfs_handle_struct *handle,
672 struct smb_filename *smb_fname,
673 files_struct *fsp, int flags, mode_t mode)
677 START_PROFILE(syscall_open);
679 if (is_named_stream(smb_fname)) {
684 result = open(smb_fname->base_name, flags, mode);
686 END_PROFILE(syscall_open);
690 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
691 struct smb_request *req,
692 uint16_t root_dir_fid,
693 struct smb_filename *smb_fname,
694 uint32_t access_mask,
695 uint32_t share_access,
696 uint32_t create_disposition,
697 uint32_t create_options,
698 uint32_t file_attributes,
699 uint32_t oplock_request,
700 const struct smb2_lease *lease,
701 uint64_t allocation_size,
702 uint32_t private_flags,
703 struct security_descriptor *sd,
704 struct ea_list *ea_list,
705 files_struct **result,
707 const struct smb2_create_blobs *in_context_blobs,
708 struct smb2_create_blobs *out_context_blobs)
710 return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
711 access_mask, share_access,
712 create_disposition, create_options,
713 file_attributes, oplock_request, lease,
714 allocation_size, private_flags,
716 pinfo, in_context_blobs, out_context_blobs);
719 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
723 START_PROFILE(syscall_close);
724 result = fd_close_posix(fsp);
725 END_PROFILE(syscall_close);
729 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
730 size_t n, off_t offset)
734 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
735 START_PROFILE_BYTES(syscall_pread, n);
736 result = sys_pread(fsp->fh->fd, data, n, offset);
737 END_PROFILE_BYTES(syscall_pread);
739 if (result == -1 && errno == ESPIPE) {
740 /* Maintain the fiction that pipes can be seeked (sought?) on. */
741 result = sys_read(fsp->fh->fd, data, n);
745 #else /* HAVE_PREAD */
748 #endif /* HAVE_PREAD */
753 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
754 size_t n, off_t offset)
758 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
759 START_PROFILE_BYTES(syscall_pwrite, n);
760 result = sys_pwrite(fsp->fh->fd, data, n, offset);
761 END_PROFILE_BYTES(syscall_pwrite);
763 if (result == -1 && errno == ESPIPE) {
764 /* Maintain the fiction that pipes can be sought on. */
765 result = sys_write(fsp->fh->fd, data, n);
768 #else /* HAVE_PWRITE */
771 #endif /* HAVE_PWRITE */
776 struct vfswrap_pread_state {
783 struct vfs_aio_state vfs_aio_state;
784 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
787 static void vfs_pread_do(void *private_data);
788 static void vfs_pread_done(struct tevent_req *subreq);
789 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
791 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
793 struct tevent_context *ev,
794 struct files_struct *fsp,
796 size_t n, off_t offset)
798 struct tevent_req *req, *subreq;
799 struct vfswrap_pread_state *state;
801 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
807 state->fd = fsp->fh->fd;
810 state->offset = offset;
812 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
813 state->profile_bytes, n);
814 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
816 subreq = pthreadpool_tevent_job_send(
817 state, ev, handle->conn->sconn->pool,
818 vfs_pread_do, state);
819 if (tevent_req_nomem(subreq, req)) {
820 return tevent_req_post(req, ev);
822 tevent_req_set_callback(subreq, vfs_pread_done, req);
824 talloc_set_destructor(state, vfs_pread_state_destructor);
829 static void vfs_pread_do(void *private_data)
831 struct vfswrap_pread_state *state = talloc_get_type_abort(
832 private_data, struct vfswrap_pread_state);
833 struct timespec start_time;
834 struct timespec end_time;
836 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
838 PROFILE_TIMESTAMP(&start_time);
841 state->ret = pread(state->fd, state->buf, state->count,
843 } while ((state->ret == -1) && (errno == EINTR));
845 if (state->ret == -1) {
846 state->vfs_aio_state.error = errno;
849 PROFILE_TIMESTAMP(&end_time);
851 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
853 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
856 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
861 static void vfs_pread_done(struct tevent_req *subreq)
863 struct tevent_req *req = tevent_req_callback_data(
864 subreq, struct tevent_req);
865 struct vfswrap_pread_state *state = tevent_req_data(
866 req, struct vfswrap_pread_state);
869 ret = pthreadpool_tevent_job_recv(subreq);
871 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
872 talloc_set_destructor(state, NULL);
875 tevent_req_error(req, ret);
879 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
880 * means the lower level pthreadpool failed to create a new
881 * thread. Fallback to sync processing in that case to allow
882 * some progress for the client.
887 tevent_req_done(req);
890 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
891 struct vfs_aio_state *vfs_aio_state)
893 struct vfswrap_pread_state *state = tevent_req_data(
894 req, struct vfswrap_pread_state);
896 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
900 *vfs_aio_state = state->vfs_aio_state;
904 struct vfswrap_pwrite_state {
911 struct vfs_aio_state vfs_aio_state;
912 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
915 static void vfs_pwrite_do(void *private_data);
916 static void vfs_pwrite_done(struct tevent_req *subreq);
917 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
919 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
921 struct tevent_context *ev,
922 struct files_struct *fsp,
924 size_t n, off_t offset)
926 struct tevent_req *req, *subreq;
927 struct vfswrap_pwrite_state *state;
929 req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
935 state->fd = fsp->fh->fd;
938 state->offset = offset;
940 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
941 state->profile_bytes, n);
942 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
944 subreq = pthreadpool_tevent_job_send(
945 state, ev, handle->conn->sconn->pool,
946 vfs_pwrite_do, state);
947 if (tevent_req_nomem(subreq, req)) {
948 return tevent_req_post(req, ev);
950 tevent_req_set_callback(subreq, vfs_pwrite_done, req);
952 talloc_set_destructor(state, vfs_pwrite_state_destructor);
957 static void vfs_pwrite_do(void *private_data)
959 struct vfswrap_pwrite_state *state = talloc_get_type_abort(
960 private_data, struct vfswrap_pwrite_state);
961 struct timespec start_time;
962 struct timespec end_time;
964 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
966 PROFILE_TIMESTAMP(&start_time);
969 state->ret = pwrite(state->fd, state->buf, state->count,
971 } while ((state->ret == -1) && (errno == EINTR));
973 if (state->ret == -1) {
974 state->vfs_aio_state.error = errno;
977 PROFILE_TIMESTAMP(&end_time);
979 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
981 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
984 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
989 static void vfs_pwrite_done(struct tevent_req *subreq)
991 struct tevent_req *req = tevent_req_callback_data(
992 subreq, struct tevent_req);
993 struct vfswrap_pwrite_state *state = tevent_req_data(
994 req, struct vfswrap_pwrite_state);
997 ret = pthreadpool_tevent_job_recv(subreq);
999 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1000 talloc_set_destructor(state, NULL);
1002 if (ret != EAGAIN) {
1003 tevent_req_error(req, ret);
1007 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1008 * means the lower level pthreadpool failed to create a new
1009 * thread. Fallback to sync processing in that case to allow
1010 * some progress for the client.
1012 vfs_pwrite_do(state);
1015 tevent_req_done(req);
1018 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1019 struct vfs_aio_state *vfs_aio_state)
1021 struct vfswrap_pwrite_state *state = tevent_req_data(
1022 req, struct vfswrap_pwrite_state);
1024 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1028 *vfs_aio_state = state->vfs_aio_state;
1032 struct vfswrap_fsync_state {
1036 struct vfs_aio_state vfs_aio_state;
1037 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1040 static void vfs_fsync_do(void *private_data);
1041 static void vfs_fsync_done(struct tevent_req *subreq);
1042 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1044 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1045 TALLOC_CTX *mem_ctx,
1046 struct tevent_context *ev,
1047 struct files_struct *fsp)
1049 struct tevent_req *req, *subreq;
1050 struct vfswrap_fsync_state *state;
1052 req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1058 state->fd = fsp->fh->fd;
1060 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1061 state->profile_bytes, 0);
1062 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1064 subreq = pthreadpool_tevent_job_send(
1065 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1066 if (tevent_req_nomem(subreq, req)) {
1067 return tevent_req_post(req, ev);
1069 tevent_req_set_callback(subreq, vfs_fsync_done, req);
1071 talloc_set_destructor(state, vfs_fsync_state_destructor);
1076 static void vfs_fsync_do(void *private_data)
1078 struct vfswrap_fsync_state *state = talloc_get_type_abort(
1079 private_data, struct vfswrap_fsync_state);
1080 struct timespec start_time;
1081 struct timespec end_time;
1083 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1085 PROFILE_TIMESTAMP(&start_time);
1088 state->ret = fsync(state->fd);
1089 } while ((state->ret == -1) && (errno == EINTR));
1091 if (state->ret == -1) {
1092 state->vfs_aio_state.error = errno;
1095 PROFILE_TIMESTAMP(&end_time);
1097 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1099 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1102 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1107 static void vfs_fsync_done(struct tevent_req *subreq)
1109 struct tevent_req *req = tevent_req_callback_data(
1110 subreq, struct tevent_req);
1111 struct vfswrap_fsync_state *state = tevent_req_data(
1112 req, struct vfswrap_fsync_state);
1115 ret = pthreadpool_tevent_job_recv(subreq);
1116 TALLOC_FREE(subreq);
1117 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1118 talloc_set_destructor(state, NULL);
1120 if (ret != EAGAIN) {
1121 tevent_req_error(req, ret);
1125 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1126 * means the lower level pthreadpool failed to create a new
1127 * thread. Fallback to sync processing in that case to allow
1128 * some progress for the client.
1130 vfs_fsync_do(state);
1133 tevent_req_done(req);
1136 static int vfswrap_fsync_recv(struct tevent_req *req,
1137 struct vfs_aio_state *vfs_aio_state)
1139 struct vfswrap_fsync_state *state = tevent_req_data(
1140 req, struct vfswrap_fsync_state);
1142 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1146 *vfs_aio_state = state->vfs_aio_state;
1150 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1154 START_PROFILE(syscall_lseek);
1156 result = lseek(fsp->fh->fd, offset, whence);
1158 * We want to maintain the fiction that we can seek
1159 * on a fifo for file system purposes. This allows
1160 * people to set up UNIX fifo's that feed data to Windows
1161 * applications. JRA.
1164 if((result == -1) && (errno == ESPIPE)) {
1169 END_PROFILE(syscall_lseek);
1173 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1174 off_t offset, size_t n)
1178 START_PROFILE_BYTES(syscall_sendfile, n);
1179 result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1180 END_PROFILE_BYTES(syscall_sendfile);
1184 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1186 files_struct *tofsp,
1192 START_PROFILE_BYTES(syscall_recvfile, n);
1193 result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1194 END_PROFILE_BYTES(syscall_recvfile);
1198 static int vfswrap_renameat(vfs_handle_struct *handle,
1199 files_struct *srcfsp,
1200 const struct smb_filename *smb_fname_src,
1201 files_struct *dstfsp,
1202 const struct smb_filename *smb_fname_dst)
1206 START_PROFILE(syscall_renameat);
1208 if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1213 result = renameat(srcfsp->fh->fd,
1214 smb_fname_src->base_name,
1216 smb_fname_dst->base_name);
1219 END_PROFILE(syscall_renameat);
1223 static int vfswrap_stat(vfs_handle_struct *handle,
1224 struct smb_filename *smb_fname)
1228 START_PROFILE(syscall_stat);
1230 if (is_named_stream(smb_fname)) {
1235 result = sys_stat(smb_fname->base_name, &smb_fname->st,
1236 lp_fake_directory_create_times(SNUM(handle->conn)));
1238 END_PROFILE(syscall_stat);
1242 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1246 START_PROFILE(syscall_fstat);
1247 result = sys_fstat(fsp->fh->fd,
1248 sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1249 END_PROFILE(syscall_fstat);
1253 static int vfswrap_lstat(vfs_handle_struct *handle,
1254 struct smb_filename *smb_fname)
1258 START_PROFILE(syscall_lstat);
1260 if (is_named_stream(smb_fname)) {
1265 result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1266 lp_fake_directory_create_times(SNUM(handle->conn)));
1268 END_PROFILE(syscall_lstat);
1272 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1274 enum vfs_translate_direction direction,
1275 TALLOC_CTX *mem_ctx,
1278 return NT_STATUS_NONE_MAPPED;
1282 * Implement the default fsctl operation.
1284 static bool vfswrap_logged_ioctl_message = false;
1286 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1287 struct files_struct *fsp,
1290 uint16_t req_flags, /* Needed for UNICODE ... */
1291 const uint8_t *_in_data,
1293 uint8_t **_out_data,
1294 uint32_t max_out_len,
1297 const char *in_data = (const char *)_in_data;
1298 char **out_data = (char **)_out_data;
1302 case FSCTL_SET_SPARSE:
1304 bool set_sparse = true;
1306 if (in_len >= 1 && in_data[0] == 0) {
1310 status = file_set_sparse(handle->conn, fsp, set_sparse);
1312 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1313 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1314 smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1315 nt_errstr(status)));
1320 case FSCTL_CREATE_OR_GET_OBJECT_ID:
1322 unsigned char objid[16];
1323 char *return_data = NULL;
1325 /* This should return the object-id on this file.
1326 * I think I'll make this be the inode+dev. JRA.
1329 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1330 fsp_fnum_dbg(fsp)));
1332 *out_len = MIN(max_out_len, 64);
1334 /* Hmmm, will this cause problems if less data asked for? */
1335 return_data = talloc_array(ctx, char, 64);
1336 if (return_data == NULL) {
1337 return NT_STATUS_NO_MEMORY;
1340 /* For backwards compatibility only store the dev/inode. */
1341 push_file_id_16(return_data, &fsp->file_id);
1342 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1343 push_file_id_16(return_data+32, &fsp->file_id);
1344 memset(return_data+48, 0, 16);
1345 *out_data = return_data;
1346 return NT_STATUS_OK;
1349 case FSCTL_GET_REPARSE_POINT:
1351 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1352 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1353 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1354 return NT_STATUS_NOT_A_REPARSE_POINT;
1357 case FSCTL_SET_REPARSE_POINT:
1359 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1360 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1361 "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1362 return NT_STATUS_NOT_A_REPARSE_POINT;
1365 case FSCTL_GET_SHADOW_COPY_DATA:
1368 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1369 * and return their volume names. If max_data_count is 16, then it is just
1370 * asking for the number of volumes and length of the combined names.
1372 * pdata is the data allocated by our caller, but that uses
1373 * total_data_count (which is 0 in our case) rather than max_data_count.
1374 * Allocate the correct amount and return the pointer to let
1375 * it be deallocated when we return.
1377 struct shadow_copy_data *shadow_data = NULL;
1378 bool labels = False;
1379 uint32_t labels_data_count = 0;
1381 char *cur_pdata = NULL;
1383 if (max_out_len < 16) {
1384 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1386 return NT_STATUS_INVALID_PARAMETER;
1389 if (max_out_len > 16) {
1393 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1394 if (shadow_data == NULL) {
1395 DEBUG(0,("TALLOC_ZERO() failed!\n"));
1396 return NT_STATUS_NO_MEMORY;
1400 * Call the VFS routine to actually do the work.
1402 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1405 /* broken module didn't set errno on error */
1406 status = NT_STATUS_UNSUCCESSFUL;
1408 status = map_nt_error_from_unix(errno);
1409 if (NT_STATUS_EQUAL(status,
1410 NT_STATUS_NOT_SUPPORTED)) {
1414 DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1415 "connectpath %s, failed - %s.\n",
1416 fsp->conn->connectpath,
1417 nt_errstr(status)));
1418 TALLOC_FREE(shadow_data);
1422 labels_data_count = (shadow_data->num_volumes * 2 *
1423 sizeof(SHADOW_COPY_LABEL)) + 2;
1428 *out_len = 12 + labels_data_count;
1431 if (max_out_len < *out_len) {
1432 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1433 max_out_len, *out_len));
1434 TALLOC_FREE(shadow_data);
1435 return NT_STATUS_BUFFER_TOO_SMALL;
1438 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1439 if (cur_pdata == NULL) {
1440 TALLOC_FREE(shadow_data);
1441 return NT_STATUS_NO_MEMORY;
1444 *out_data = cur_pdata;
1446 /* num_volumes 4 bytes */
1447 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1450 /* num_labels 4 bytes */
1451 SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1454 /* needed_data_count 4 bytes */
1455 SIVAL(cur_pdata, 8, labels_data_count);
1459 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1460 shadow_data->num_volumes, fsp_str_dbg(fsp)));
1461 if (labels && shadow_data->labels) {
1462 for (i=0; i<shadow_data->num_volumes; i++) {
1464 status = srvstr_push(cur_pdata, req_flags,
1465 cur_pdata, shadow_data->labels[i],
1466 2 * sizeof(SHADOW_COPY_LABEL),
1467 STR_UNICODE|STR_TERMINATE, &len);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 TALLOC_FREE(*out_data);
1470 TALLOC_FREE(shadow_data);
1473 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1474 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1478 TALLOC_FREE(shadow_data);
1480 return NT_STATUS_OK;
1483 case FSCTL_FIND_FILES_BY_SID:
1485 /* pretend this succeeded -
1487 * we have to send back a list with all files owned by this SID
1489 * but I have to check that --metze
1493 struct dom_sid_buf buf;
1497 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1498 fsp_fnum_dbg(fsp)));
1501 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1502 return NT_STATUS_INVALID_PARAMETER;
1505 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1507 /* unknown 4 bytes: this is not the length of the sid :-( */
1508 /*unknown = IVAL(pdata,0);*/
1510 ret = sid_parse(_in_data + 4, sid_len, &sid);
1512 return NT_STATUS_INVALID_PARAMETER;
1514 DEBUGADD(10, ("for SID: %s\n",
1515 dom_sid_str_buf(&sid, &buf)));
1517 if (!sid_to_uid(&sid, &uid)) {
1518 DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1519 dom_sid_str_buf(&sid, &buf),
1520 (unsigned long)sid_len));
1524 /* we can take a look at the find source :-)
1526 * find ./ -uid $uid -name '*' is what we need here
1529 * and send 4bytes len and then NULL terminated unicode strings
1532 * but I don't know how to deal with the paged results
1533 * (maybe we can hang the result anywhere in the fsp struct)
1535 * but I don't know how to deal with the paged results
1536 * (maybe we can hang the result anywhere in the fsp struct)
1538 * we don't send all files at once
1539 * and at the next we should *not* start from the beginning,
1540 * so we have to cache the result
1545 /* this works for now... */
1546 return NT_STATUS_OK;
1549 case FSCTL_QUERY_ALLOCATED_RANGES:
1551 /* FIXME: This is just a dummy reply, telling that all of the
1552 * file is allocated. MKS cp needs that.
1553 * Adding the real allocated ranges via FIEMAP on Linux
1554 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1555 * this FSCTL correct for sparse files.
1557 uint64_t offset, length;
1558 char *out_data_tmp = NULL;
1561 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1563 return NT_STATUS_INVALID_PARAMETER;
1566 if (max_out_len < 16) {
1567 DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1569 return NT_STATUS_INVALID_PARAMETER;
1572 offset = BVAL(in_data,0);
1573 length = BVAL(in_data,8);
1575 if (offset + length < offset) {
1576 /* No 64-bit integer wrap. */
1577 return NT_STATUS_INVALID_PARAMETER;
1580 /* Shouldn't this be SMB_VFS_STAT ... ? */
1581 status = vfs_stat_fsp(fsp);
1582 if (!NT_STATUS_IS_OK(status)) {
1587 out_data_tmp = talloc_array(ctx, char, *out_len);
1588 if (out_data_tmp == NULL) {
1589 DEBUG(10, ("unable to allocate memory for response\n"));
1590 return NT_STATUS_NO_MEMORY;
1593 if (offset > fsp->fsp_name->st.st_ex_size ||
1594 fsp->fsp_name->st.st_ex_size == 0 ||
1596 memset(out_data_tmp, 0, *out_len);
1598 uint64_t end = offset + length;
1599 end = MIN(end, fsp->fsp_name->st.st_ex_size);
1600 SBVAL(out_data_tmp, 0, 0);
1601 SBVAL(out_data_tmp, 8, end);
1604 *out_data = out_data_tmp;
1606 return NT_STATUS_OK;
1609 case FSCTL_IS_VOLUME_DIRTY:
1611 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1612 "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1614 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1615 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1617 return NT_STATUS_INVALID_PARAMETER;
1622 * Only print once ... unfortunately there could be lots of
1623 * different FSCTLs that are called.
1625 if (!vfswrap_logged_ioctl_message) {
1626 vfswrap_logged_ioctl_message = true;
1627 DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1628 __func__, function));
1632 return NT_STATUS_NOT_SUPPORTED;
1635 static bool vfswrap_is_offline(struct connection_struct *conn,
1636 const struct smb_filename *fname);
1638 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1639 struct smb_filename *smb_fname,
1644 offline = vfswrap_is_offline(handle->conn, smb_fname);
1646 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1649 return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1652 struct vfswrap_get_dos_attributes_state {
1653 struct vfs_aio_state aio_state;
1654 connection_struct *conn;
1655 TALLOC_CTX *mem_ctx;
1656 struct tevent_context *ev;
1657 files_struct *dir_fsp;
1658 struct smb_filename *smb_fname;
1663 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1665 static struct tevent_req *vfswrap_get_dos_attributes_send(
1666 TALLOC_CTX *mem_ctx,
1667 struct tevent_context *ev,
1668 struct vfs_handle_struct *handle,
1669 files_struct *dir_fsp,
1670 struct smb_filename *smb_fname)
1672 struct tevent_req *req = NULL;
1673 struct tevent_req *subreq = NULL;
1674 struct vfswrap_get_dos_attributes_state *state = NULL;
1676 req = tevent_req_create(mem_ctx, &state,
1677 struct vfswrap_get_dos_attributes_state);
1682 *state = (struct vfswrap_get_dos_attributes_state) {
1683 .conn = dir_fsp->conn,
1687 .smb_fname = smb_fname,
1690 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1694 SAMBA_XATTR_DOS_ATTRIB,
1696 if (tevent_req_nomem(subreq, req)) {
1697 return tevent_req_post(req, ev);
1699 tevent_req_set_callback(subreq,
1700 vfswrap_get_dos_attributes_getxattr_done,
1706 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1708 struct tevent_req *req =
1709 tevent_req_callback_data(subreq,
1711 struct vfswrap_get_dos_attributes_state *state =
1712 tevent_req_data(req,
1713 struct vfswrap_get_dos_attributes_state);
1715 DATA_BLOB blob = {0};
1717 char *tofree = NULL;
1718 char pathbuf[PATH_MAX+1];
1720 struct smb_filename smb_fname;
1724 xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1728 TALLOC_FREE(subreq);
1729 if (xattr_size == -1) {
1730 status = map_nt_error_from_unix(state->aio_state.error);
1732 if (state->as_root) {
1733 tevent_req_nterror(req, status);
1736 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1737 tevent_req_nterror(req, status);
1741 state->as_root = true;
1744 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1748 SAMBA_XATTR_DOS_ATTRIB,
1751 if (tevent_req_nomem(subreq, req)) {
1754 tevent_req_set_callback(subreq,
1755 vfswrap_get_dos_attributes_getxattr_done,
1760 blob.length = xattr_size;
1762 status = parse_dos_attribute_blob(state->smb_fname,
1765 if (!NT_STATUS_IS_OK(status)) {
1766 tevent_req_nterror(req, status);
1770 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1771 state->smb_fname->base_name,
1776 if (pathlen == -1) {
1777 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1781 smb_fname = (struct smb_filename) {
1783 .st = state->smb_fname->st,
1784 .flags = state->smb_fname->flags,
1787 offline = vfswrap_is_offline(state->conn, &smb_fname);
1789 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1791 TALLOC_FREE(tofree);
1793 tevent_req_done(req);
1797 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1798 struct vfs_aio_state *aio_state,
1801 struct vfswrap_get_dos_attributes_state *state =
1802 tevent_req_data(req,
1803 struct vfswrap_get_dos_attributes_state);
1806 if (tevent_req_is_nterror(req, &status)) {
1807 tevent_req_received(req);
1811 *aio_state = state->aio_state;
1812 *dosmode = state->dosmode;
1813 tevent_req_received(req);
1814 return NT_STATUS_OK;
1817 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1818 struct files_struct *fsp,
1823 offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1825 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1828 return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1831 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1832 const struct smb_filename *smb_fname,
1835 return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1838 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1839 struct files_struct *fsp,
1842 return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1845 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1847 struct vfswrap_offload_read_state {
1851 static struct tevent_req *vfswrap_offload_read_send(
1852 TALLOC_CTX *mem_ctx,
1853 struct tevent_context *ev,
1854 struct vfs_handle_struct *handle,
1855 struct files_struct *fsp,
1861 struct tevent_req *req = NULL;
1862 struct vfswrap_offload_read_state *state = NULL;
1865 req = tevent_req_create(mem_ctx, &state,
1866 struct vfswrap_offload_read_state);
1871 status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1872 &vfswrap_offload_ctx);
1873 if (tevent_req_nterror(req, status)) {
1874 return tevent_req_post(req, ev);
1877 if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1878 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1879 return tevent_req_post(req, ev);
1882 status = vfs_offload_token_create_blob(state, fsp, fsctl,
1884 if (tevent_req_nterror(req, status)) {
1885 return tevent_req_post(req, ev);
1888 status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1890 if (tevent_req_nterror(req, status)) {
1891 return tevent_req_post(req, ev);
1894 tevent_req_done(req);
1895 return tevent_req_post(req, ev);
1898 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1899 struct vfs_handle_struct *handle,
1900 TALLOC_CTX *mem_ctx,
1903 struct vfswrap_offload_read_state *state = tevent_req_data(
1904 req, struct vfswrap_offload_read_state);
1907 if (tevent_req_is_nterror(req, &status)) {
1908 tevent_req_received(req);
1912 token->length = state->token.length;
1913 token->data = talloc_move(mem_ctx, &state->token.data);
1915 tevent_req_received(req);
1916 return NT_STATUS_OK;
1919 struct vfswrap_offload_write_state {
1921 bool read_lck_locked;
1922 bool write_lck_locked;
1924 struct tevent_context *src_ev;
1925 struct files_struct *src_fsp;
1927 struct tevent_context *dst_ev;
1928 struct files_struct *dst_fsp;
1932 size_t next_io_size;
1935 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
1936 enum tevent_req_state req_state)
1938 struct vfswrap_offload_write_state *state = tevent_req_data(
1939 req, struct vfswrap_offload_write_state);
1942 if (state->dst_fsp == NULL) {
1946 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
1948 state->dst_fsp = NULL;
1951 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1953 static struct tevent_req *vfswrap_offload_write_send(
1954 struct vfs_handle_struct *handle,
1955 TALLOC_CTX *mem_ctx,
1956 struct tevent_context *ev,
1959 off_t transfer_offset,
1960 struct files_struct *dest_fsp,
1964 struct tevent_req *req;
1965 struct vfswrap_offload_write_state *state = NULL;
1966 /* off_t is signed! */
1967 off_t max_offset = INT64_MAX - to_copy;
1968 size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1969 files_struct *src_fsp = NULL;
1973 req = tevent_req_create(mem_ctx, &state,
1974 struct vfswrap_offload_write_state);
1979 *state = (struct vfswrap_offload_write_state) {
1981 .src_off = transfer_offset,
1983 .dst_fsp = dest_fsp,
1984 .dst_off = dest_off,
1986 .remaining = to_copy,
1989 tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
1992 case FSCTL_SRV_COPYCHUNK:
1993 case FSCTL_SRV_COPYCHUNK_WRITE:
1996 case FSCTL_OFFLOAD_WRITE:
1997 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1998 return tevent_req_post(req, ev);
2000 case FSCTL_DUP_EXTENTS_TO_FILE:
2001 DBG_DEBUG("COW clones not supported by vfs_default\n");
2002 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2003 return tevent_req_post(req, ev);
2006 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2007 return tevent_req_post(req, ev);
2011 * From here on we assume a copy-chunk fsctl
2015 tevent_req_done(req);
2016 return tevent_req_post(req, ev);
2019 if (state->src_off > max_offset) {
2021 * Protect integer checks below.
2023 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2024 return tevent_req_post(req, ev);
2026 if (state->src_off < 0) {
2028 * Protect integer checks below.
2030 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031 return tevent_req_post(req, ev);
2033 if (state->dst_off > max_offset) {
2035 * Protect integer checks below.
2037 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2038 return tevent_req_post(req, ev);
2040 if (state->dst_off < 0) {
2042 * Protect integer checks below.
2044 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 return tevent_req_post(req, ev);
2048 status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2050 if (tevent_req_nterror(req, status)) {
2051 return tevent_req_post(req, ev);
2054 DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2056 status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2057 if (!NT_STATUS_IS_OK(status)) {
2058 tevent_req_nterror(req, status);
2059 return tevent_req_post(req, ev);
2062 ok = change_to_user_and_service_by_fsp(src_fsp);
2064 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2065 return tevent_req_post(req, ev);
2068 state->src_ev = src_fsp->conn->sconn->ev_ctx;
2069 state->src_fsp = src_fsp;
2071 status = vfs_stat_fsp(src_fsp);
2072 if (tevent_req_nterror(req, status)) {
2073 return tevent_req_post(req, ev);
2076 if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2078 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2079 * If the SourceOffset or SourceOffset + Length extends beyond
2080 * the end of file, the server SHOULD<240> treat this as a
2081 * STATUS_END_OF_FILE error.
2083 * <240> Section 3.3.5.15.6: Windows servers will return
2084 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2086 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2087 return tevent_req_post(req, ev);
2090 state->buf = talloc_array(state, uint8_t, num);
2091 if (tevent_req_nomem(state->buf, req)) {
2092 return tevent_req_post(req, ev);
2095 status = vfswrap_offload_write_loop(req);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 tevent_req_nterror(req, status);
2098 return tevent_req_post(req, ev);
2104 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2106 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2108 struct vfswrap_offload_write_state *state = tevent_req_data(
2109 req, struct vfswrap_offload_write_state);
2110 struct tevent_req *subreq = NULL;
2111 struct lock_struct read_lck;
2115 * This is called under the context of state->src_fsp.
2118 state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2120 init_strict_lock_struct(state->src_fsp,
2121 state->src_fsp->op->global->open_persistent_id,
2123 state->next_io_size,
2127 ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2131 return NT_STATUS_FILE_LOCK_CONFLICT;
2134 subreq = SMB_VFS_PREAD_SEND(state,
2138 state->next_io_size,
2140 if (subreq == NULL) {
2141 return NT_STATUS_NO_MEMORY;
2143 tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2145 return NT_STATUS_OK;
2148 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2150 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2152 struct tevent_req *req = tevent_req_callback_data(
2153 subreq, struct tevent_req);
2154 struct vfswrap_offload_write_state *state = tevent_req_data(
2155 req, struct vfswrap_offload_write_state);
2156 struct vfs_aio_state aio_state;
2157 struct lock_struct write_lck;
2161 nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2162 TALLOC_FREE(subreq);
2164 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2165 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2168 if (nread != state->next_io_size) {
2169 DBG_ERR("Short read, only %zd of %zu\n",
2170 nread, state->next_io_size);
2171 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2175 state->src_off += nread;
2177 ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2179 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2183 init_strict_lock_struct(state->dst_fsp,
2184 state->dst_fsp->op->global->open_persistent_id,
2186 state->next_io_size,
2190 ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2194 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2198 subreq = SMB_VFS_PWRITE_SEND(state,
2202 state->next_io_size,
2204 if (subreq == NULL) {
2205 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2208 tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2211 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2213 struct tevent_req *req = tevent_req_callback_data(
2214 subreq, struct tevent_req);
2215 struct vfswrap_offload_write_state *state = tevent_req_data(
2216 req, struct vfswrap_offload_write_state);
2217 struct vfs_aio_state aio_state;
2222 nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2223 TALLOC_FREE(subreq);
2224 if (nwritten == -1) {
2225 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2226 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2229 if (nwritten != state->next_io_size) {
2230 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2231 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2235 state->dst_off += nwritten;
2237 if (state->remaining < nwritten) {
2238 /* Paranoia check */
2239 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2242 state->remaining -= nwritten;
2243 if (state->remaining == 0) {
2244 tevent_req_done(req);
2248 ok = change_to_user_and_service_by_fsp(state->src_fsp);
2250 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2254 status = vfswrap_offload_write_loop(req);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 tevent_req_nterror(req, status);
2263 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2264 struct tevent_req *req,
2267 struct vfswrap_offload_write_state *state = tevent_req_data(
2268 req, struct vfswrap_offload_write_state);
2271 if (tevent_req_is_nterror(req, &status)) {
2272 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2274 tevent_req_received(req);
2278 *copied = state->to_copy;
2279 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2280 tevent_req_received(req);
2282 return NT_STATUS_OK;
2285 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2286 TALLOC_CTX *mem_ctx,
2287 struct files_struct *fsp,
2288 struct smb_filename *smb_fname,
2289 uint16_t *_compression_fmt)
2291 return NT_STATUS_INVALID_DEVICE_REQUEST;
2294 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2295 TALLOC_CTX *mem_ctx,
2296 struct files_struct *fsp,
2297 uint16_t compression_fmt)
2299 return NT_STATUS_INVALID_DEVICE_REQUEST;
2302 /********************************************************************
2303 Given a stat buffer return the allocated size on disk, taking into
2304 account sparse files.
2305 ********************************************************************/
2306 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2307 struct files_struct *fsp,
2308 const SMB_STRUCT_STAT *sbuf)
2312 START_PROFILE(syscall_get_alloc_size);
2314 if(S_ISDIR(sbuf->st_ex_mode)) {
2319 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2320 /* The type of st_blocksize is blkcnt_t which *MUST* be
2321 signed (according to POSIX) and can be less than 64-bits.
2322 Ensure when we're converting to 64 bits wide we don't
2324 #if defined(SIZEOF_BLKCNT_T_8)
2325 result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2326 #elif defined(SIZEOF_BLKCNT_T_4)
2328 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2329 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2332 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2336 * Some file systems do not allocate a block for very
2337 * small files. But for non-empty file should report a
2341 uint64_t filesize = get_file_size_stat(sbuf);
2343 result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2347 result = get_file_size_stat(sbuf);
2350 if (fsp && fsp->initial_allocation_size)
2351 result = MAX(result,fsp->initial_allocation_size);
2353 result = smb_roundup(handle->conn, result);
2356 END_PROFILE(syscall_get_alloc_size);
2360 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2361 struct files_struct *dirfsp,
2362 const struct smb_filename *smb_fname,
2367 START_PROFILE(syscall_unlinkat);
2369 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2371 if (is_named_stream(smb_fname)) {
2375 result = unlinkat(dirfsp->fh->fd,
2376 smb_fname->base_name,
2380 END_PROFILE(syscall_unlinkat);
2384 static int vfswrap_chmod(vfs_handle_struct *handle,
2385 const struct smb_filename *smb_fname,
2390 START_PROFILE(syscall_chmod);
2391 result = chmod(smb_fname->base_name, mode);
2392 END_PROFILE(syscall_chmod);
2396 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2400 START_PROFILE(syscall_fchmod);
2401 #if defined(HAVE_FCHMOD)
2402 result = fchmod(fsp->fh->fd, mode);
2408 END_PROFILE(syscall_fchmod);
2412 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2417 START_PROFILE(syscall_fchown);
2418 result = fchown(fsp->fh->fd, uid, gid);
2419 END_PROFILE(syscall_fchown);
2427 static int vfswrap_lchown(vfs_handle_struct *handle,
2428 const struct smb_filename *smb_fname,
2434 START_PROFILE(syscall_lchown);
2435 result = lchown(smb_fname->base_name, uid, gid);
2436 END_PROFILE(syscall_lchown);
2440 static int vfswrap_chdir(vfs_handle_struct *handle,
2441 const struct smb_filename *smb_fname)
2445 START_PROFILE(syscall_chdir);
2446 result = chdir(smb_fname->base_name);
2447 END_PROFILE(syscall_chdir);
2451 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2455 struct smb_filename *smb_fname = NULL;
2457 START_PROFILE(syscall_getwd);
2458 result = sys_getwd();
2459 END_PROFILE(syscall_getwd);
2461 if (result == NULL) {
2464 smb_fname = synthetic_smb_fname(ctx,
2470 * sys_getwd() *always* returns malloced memory.
2471 * We must free here to avoid leaks:
2472 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2478 /*********************************************************************
2479 nsec timestamp resolution call. Convert down to whatever the underlying
2480 system will support.
2481 **********************************************************************/
2483 static int vfswrap_ntimes(vfs_handle_struct *handle,
2484 const struct smb_filename *smb_fname,
2485 struct smb_file_time *ft)
2489 START_PROFILE(syscall_ntimes);
2491 if (is_named_stream(smb_fname)) {
2497 if (is_omit_timespec(&ft->atime)) {
2498 ft->atime= smb_fname->st.st_ex_atime;
2501 if (is_omit_timespec(&ft->mtime)) {
2502 ft->mtime = smb_fname->st.st_ex_mtime;
2505 if (!is_omit_timespec(&ft->create_time)) {
2506 set_create_timespec_ea(handle->conn,
2511 if ((timespec_compare(&ft->atime,
2512 &smb_fname->st.st_ex_atime) == 0) &&
2513 (timespec_compare(&ft->mtime,
2514 &smb_fname->st.st_ex_mtime) == 0)) {
2519 #if defined(HAVE_UTIMENSAT)
2521 struct timespec ts[2];
2524 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2526 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2528 if (!((result == -1) && (errno == ENOSYS))) {
2532 #if defined(HAVE_UTIMES)
2534 struct timeval tv[2];
2535 tv[0] = convert_timespec_to_timeval(ft->atime);
2536 tv[1] = convert_timespec_to_timeval(ft->mtime);
2537 result = utimes(smb_fname->base_name, tv);
2539 result = utimes(smb_fname->base_name, NULL);
2541 if (!((result == -1) && (errno == ENOSYS))) {
2545 #if defined(HAVE_UTIME)
2547 struct utimbuf times;
2548 times.actime = convert_timespec_to_time_t(ft->atime);
2549 times.modtime = convert_timespec_to_time_t(ft->mtime);
2550 result = utime(smb_fname->base_name, ×);
2552 result = utime(smb_fname->base_name, NULL);
2554 if (!((result == -1) && (errno == ENOSYS))) {
2562 END_PROFILE(syscall_ntimes);
2566 /*********************************************************************
2567 A version of ftruncate that will write the space on disk if strict
2569 **********************************************************************/
2571 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2573 off_t space_to_write;
2574 uint64_t space_avail;
2575 uint64_t bsize,dfree,dsize;
2578 SMB_STRUCT_STAT *pst;
2580 status = vfs_stat_fsp(fsp);
2581 if (!NT_STATUS_IS_OK(status)) {
2584 pst = &fsp->fsp_name->st;
2587 if (S_ISFIFO(pst->st_ex_mode))
2591 if (pst->st_ex_size == len)
2594 /* Shrink - just ftruncate. */
2595 if (pst->st_ex_size > len)
2596 return ftruncate(fsp->fh->fd, len);
2598 space_to_write = len - pst->st_ex_size;
2600 /* for allocation try fallocate first. This can fail on some
2601 platforms e.g. when the filesystem doesn't support it and no
2602 emulation is being done by the libc (like on AIX with JFS1). In that
2603 case we do our own emulation. fallocate implementations can
2604 return ENOTSUP or EINVAL in cases like that. */
2605 ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2606 if (ret == -1 && errno == ENOSPC) {
2612 DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2613 "error %d. Falling back to slow manual allocation\n", errno));
2615 /* available disk space is enough or not? */
2617 get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2618 /* space_avail is 1k blocks */
2619 if (space_avail == (uint64_t)-1 ||
2620 ((uint64_t)space_to_write/1024 > space_avail) ) {
2625 /* Write out the real space on disk. */
2626 ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2634 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2637 SMB_STRUCT_STAT *pst;
2641 START_PROFILE(syscall_ftruncate);
2643 if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2644 result = strict_allocate_ftruncate(handle, fsp, len);
2645 END_PROFILE(syscall_ftruncate);
2649 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2650 ftruncate if the system supports it. Then I discovered that
2651 you can have some filesystems that support ftruncate
2652 expansion and some that don't! On Linux fat can't do
2653 ftruncate extend but ext2 can. */
2655 result = ftruncate(fsp->fh->fd, len);
2657 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2658 extend a file with ftruncate. Provide alternate implementation
2661 /* Do an fstat to see if the file is longer than the requested
2662 size in which case the ftruncate above should have
2663 succeeded or shorter, in which case seek to len - 1 and
2664 write 1 byte of zero */
2665 status = vfs_stat_fsp(fsp);
2666 if (!NT_STATUS_IS_OK(status)) {
2670 /* We need to update the files_struct after successful ftruncate */
2675 pst = &fsp->fsp_name->st;
2678 if (S_ISFIFO(pst->st_ex_mode)) {
2684 if (pst->st_ex_size == len) {
2689 if (pst->st_ex_size > len) {
2690 /* the ftruncate should have worked */
2694 if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2702 END_PROFILE(syscall_ftruncate);
2706 static int vfswrap_fallocate(vfs_handle_struct *handle,
2714 START_PROFILE(syscall_fallocate);
2716 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2718 * posix_fallocate returns 0 on success, errno on error
2719 * and doesn't set errno. Make it behave like fallocate()
2720 * which returns -1, and sets errno on failure.
2727 /* sys_fallocate handles filtering of unsupported mode flags */
2728 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2730 END_PROFILE(syscall_fallocate);
2734 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2738 START_PROFILE(syscall_fcntl_lock);
2740 if (fsp->fsp_flags.use_ofd_locks) {
2741 op = map_process_lock_to_ofd_lock(op);
2744 result = fcntl_lock(fsp->fh->fd, op, offset, count, type);
2745 END_PROFILE(syscall_fcntl_lock);
2749 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2750 uint32_t share_access, uint32_t access_mask)
2752 START_PROFILE(syscall_kernel_flock);
2753 kernel_flock(fsp->fh->fd, share_access, access_mask);
2754 END_PROFILE(syscall_kernel_flock);
2758 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2762 va_list dup_cmd_arg;
2766 START_PROFILE(syscall_fcntl);
2768 va_copy(dup_cmd_arg, cmd_arg);
2774 #if defined(HAVE_OFD_LOCKS)
2779 #if defined(HAVE_F_OWNER_EX)
2783 #if defined(HAVE_RW_HINTS)
2786 case F_GET_FILE_RW_HINT:
2787 case F_SET_FILE_RW_HINT:
2789 argp = va_arg(dup_cmd_arg, void *);
2790 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2793 val = va_arg(dup_cmd_arg, int);
2794 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2797 va_end(dup_cmd_arg);
2799 END_PROFILE(syscall_fcntl);
2803 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2808 START_PROFILE(syscall_fcntl_getlock);
2810 if (fsp->fsp_flags.use_ofd_locks) {
2811 op = map_process_lock_to_ofd_lock(op);
2814 result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2815 END_PROFILE(syscall_fcntl_getlock);
2819 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2824 START_PROFILE(syscall_linux_setlease);
2826 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2827 result = linux_setlease(fsp->fh->fd, leasetype);
2831 END_PROFILE(syscall_linux_setlease);
2835 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2836 const char *link_target,
2837 struct files_struct *dirfsp,
2838 const struct smb_filename *new_smb_fname)
2842 START_PROFILE(syscall_symlinkat);
2844 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2846 result = symlinkat(link_target,
2848 new_smb_fname->base_name);
2849 END_PROFILE(syscall_symlinkat);
2853 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2854 files_struct *dirfsp,
2855 const struct smb_filename *smb_fname,
2861 START_PROFILE(syscall_readlinkat);
2863 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2865 result = readlinkat(dirfsp->fh->fd,
2866 smb_fname->base_name,
2870 END_PROFILE(syscall_readlinkat);
2874 static int vfswrap_linkat(vfs_handle_struct *handle,
2875 files_struct *srcfsp,
2876 const struct smb_filename *old_smb_fname,
2877 files_struct *dstfsp,
2878 const struct smb_filename *new_smb_fname,
2883 START_PROFILE(syscall_linkat);
2885 SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2886 SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2888 result = linkat(srcfsp->fh->fd,
2889 old_smb_fname->base_name,
2891 new_smb_fname->base_name,
2894 END_PROFILE(syscall_linkat);
2898 static int vfswrap_mknodat(vfs_handle_struct *handle,
2899 files_struct *dirfsp,
2900 const struct smb_filename *smb_fname,
2906 START_PROFILE(syscall_mknodat);
2908 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2910 result = sys_mknodat(dirfsp->fh->fd,
2911 smb_fname->base_name,
2915 END_PROFILE(syscall_mknodat);
2919 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2921 const struct smb_filename *smb_fname)
2924 struct smb_filename *result_fname = NULL;
2926 START_PROFILE(syscall_realpath);
2927 result = sys_realpath(smb_fname->base_name);
2928 END_PROFILE(syscall_realpath);
2930 result_fname = synthetic_smb_fname(ctx,
2937 return result_fname;
2940 static int vfswrap_chflags(vfs_handle_struct *handle,
2941 const struct smb_filename *smb_fname,
2945 return chflags(smb_fname->base_name, flags);
2952 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2953 const SMB_STRUCT_STAT *sbuf)
2957 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2961 key.devid = sbuf->st_ex_dev;
2962 key.inode = sbuf->st_ex_ino;
2963 /* key.extid is unused by default. */
2968 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
2969 const SMB_STRUCT_STAT *psbuf)
2973 if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
2974 return psbuf->st_ex_file_id;
2977 if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
2978 return (uint64_t)psbuf->st_ex_ino;
2982 file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
2985 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
2990 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2991 struct files_struct *fsp,
2992 const struct smb_filename *smb_fname,
2993 TALLOC_CTX *mem_ctx,
2994 unsigned int *pnum_streams,
2995 struct stream_struct **pstreams)
2997 SMB_STRUCT_STAT sbuf;
2998 struct stream_struct *tmp_streams = NULL;
3001 if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3003 * No default streams on directories
3008 if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3009 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3012 struct smb_filename smb_fname_cp;
3014 ZERO_STRUCT(smb_fname_cp);
3015 smb_fname_cp.base_name = discard_const_p(char,
3016 smb_fname->base_name);
3017 smb_fname_cp.flags = smb_fname->flags;
3019 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
3020 ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
3022 ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
3024 sbuf = smb_fname_cp.st;
3028 return map_nt_error_from_unix(errno);
3031 if (S_ISDIR(sbuf.st_ex_mode)) {
3035 tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3036 (*pnum_streams) + 1);
3037 if (tmp_streams == NULL) {
3038 return NT_STATUS_NO_MEMORY;
3040 tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3041 if (tmp_streams[*pnum_streams].name == NULL) {
3042 return NT_STATUS_NO_MEMORY;
3044 tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3045 tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3048 *pstreams = tmp_streams;
3050 return NT_STATUS_OK;
3053 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3056 TALLOC_CTX *mem_ctx,
3060 * Don't fall back to get_real_filename so callers can differentiate
3061 * between a full directory scan and an actual case-insensitive stat.
3067 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3068 const struct smb_filename *smb_fname)
3070 return handle->conn->connectpath;
3073 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3074 struct byte_range_lock *br_lck,
3075 struct lock_struct *plock)
3077 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3079 /* Note: blr is not used in the default implementation. */
3080 return brl_lock_windows_default(br_lck, plock);
3083 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3084 struct byte_range_lock *br_lck,
3085 const struct lock_struct *plock)
3087 SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3089 return brl_unlock_windows_default(br_lck, plock);
3092 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3094 struct lock_struct *plock)
3096 SMB_ASSERT(plock->lock_type == READ_LOCK ||
3097 plock->lock_type == WRITE_LOCK);
3099 return strict_lock_check_default(fsp, plock);
3102 /* NT ACL operations. */
3104 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3106 uint32_t security_info,
3107 TALLOC_CTX *mem_ctx,
3108 struct security_descriptor **ppdesc)
3112 START_PROFILE(fget_nt_acl);
3113 result = posix_fget_nt_acl(fsp, security_info,
3115 END_PROFILE(fget_nt_acl);
3119 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3120 const struct smb_filename *smb_fname,
3121 uint32_t security_info,
3122 TALLOC_CTX *mem_ctx,
3123 struct security_descriptor **ppdesc)
3127 START_PROFILE(get_nt_acl);
3128 result = posix_get_nt_acl(handle->conn,
3133 END_PROFILE(get_nt_acl);
3137 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3141 START_PROFILE(fset_nt_acl);
3142 result = set_nt_acl(fsp, security_info_sent, psd);
3143 END_PROFILE(fset_nt_acl);
3147 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3148 struct smb_filename *file,
3149 struct security_acl *sacl,
3150 uint32_t access_requested,
3151 uint32_t access_denied)
3153 return NT_STATUS_OK; /* Nothing to do here ... */
3156 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3157 const struct smb_filename *smb_fname,
3158 SMB_ACL_TYPE_T type,
3159 TALLOC_CTX *mem_ctx)
3161 return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3164 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3166 TALLOC_CTX *mem_ctx)
3168 return sys_acl_get_fd(handle, fsp, mem_ctx);
3171 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3172 const struct smb_filename *smb_fname,
3173 SMB_ACL_TYPE_T acltype,
3176 return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3179 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3181 return sys_acl_set_fd(handle, fsp, theacl);
3184 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3185 const struct smb_filename *smb_fname)
3187 return sys_acl_delete_def_file(handle, smb_fname);
3190 /****************************************************************
3191 Extended attribute operations.
3192 *****************************************************************/
3194 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3195 const struct smb_filename *smb_fname,
3200 return getxattr(smb_fname->base_name, name, value, size);
3203 struct vfswrap_getxattrat_state {
3204 struct tevent_context *ev;
3205 files_struct *dir_fsp;
3206 const struct smb_filename *smb_fname;
3207 struct tevent_req *req;
3210 * The following variables are talloced off "state" which is protected
3211 * by a destructor and thus are guaranteed to be safe to be used in the
3212 * job function in the worker thread.
3215 const char *xattr_name;
3216 uint8_t *xattr_value;
3217 struct security_unix_token *token;
3220 struct vfs_aio_state vfs_aio_state;
3221 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3224 static int vfswrap_getxattrat_state_destructor(
3225 struct vfswrap_getxattrat_state *state)
3230 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3231 static void vfswrap_getxattrat_do_async(void *private_data);
3232 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3234 static struct tevent_req *vfswrap_getxattrat_send(
3235 TALLOC_CTX *mem_ctx,
3236 struct tevent_context *ev,
3237 struct vfs_handle_struct *handle,
3238 files_struct *dir_fsp,
3239 const struct smb_filename *smb_fname,
3240 const char *xattr_name,
3243 struct tevent_req *req = NULL;
3244 struct tevent_req *subreq = NULL;
3245 struct vfswrap_getxattrat_state *state = NULL;
3246 size_t max_threads = 0;
3247 bool have_per_thread_cwd = false;
3248 bool have_per_thread_creds = false;
3249 bool do_async = false;
3251 req = tevent_req_create(mem_ctx, &state,
3252 struct vfswrap_getxattrat_state);
3256 *state = (struct vfswrap_getxattrat_state) {
3259 .smb_fname = smb_fname,
3263 max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3264 if (max_threads >= 1) {
3266 * We need a non sync threadpool!
3268 have_per_thread_cwd = per_thread_cwd_supported();
3270 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3271 have_per_thread_creds = true;
3273 if (have_per_thread_cwd && have_per_thread_creds) {
3277 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3278 state->profile_bytes, 0);
3280 if (dir_fsp->fh->fd == -1) {
3281 DBG_ERR("Need a valid directory fd\n");
3282 tevent_req_error(req, EINVAL);
3283 return tevent_req_post(req, ev);
3286 if (alloc_hint > 0) {
3287 state->xattr_value = talloc_zero_array(state,
3290 if (tevent_req_nomem(state->xattr_value, req)) {
3291 return tevent_req_post(req, ev);
3296 vfswrap_getxattrat_do_sync(req);
3297 return tevent_req_post(req, ev);
3301 * Now allocate all parameters from a memory context that won't go away
3302 * no matter what. These paremeters will get used in threads and we
3303 * can't reliably cancel threads, so all buffers passed to the threads
3304 * must not be freed before all referencing threads terminate.
3307 state->name = talloc_strdup(state, smb_fname->base_name);
3308 if (tevent_req_nomem(state->name, req)) {
3309 return tevent_req_post(req, ev);
3312 state->xattr_name = talloc_strdup(state, xattr_name);
3313 if (tevent_req_nomem(state->xattr_name, req)) {
3314 return tevent_req_post(req, ev);
3318 * This is a hot codepath so at first glance one might think we should
3319 * somehow optimize away the token allocation and do a
3320 * talloc_reference() or similar black magic instead. But due to the
3321 * talloc_stackframe pool per SMB2 request this should be a simple copy
3322 * without a malloc in most cases.
3324 if (geteuid() == sec_initial_uid()) {
3325 state->token = root_unix_token(state);
3327 state->token = copy_unix_token(
3329 dir_fsp->conn->session_info->unix_token);
3331 if (tevent_req_nomem(state->token, req)) {
3332 return tevent_req_post(req, ev);
3335 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3337 subreq = pthreadpool_tevent_job_send(
3340 dir_fsp->conn->sconn->pool,
3341 vfswrap_getxattrat_do_async,
3343 if (tevent_req_nomem(subreq, req)) {
3344 return tevent_req_post(req, ev);
3346 tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3348 talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3353 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3355 struct vfswrap_getxattrat_state *state = tevent_req_data(
3356 req, struct vfswrap_getxattrat_state);
3358 char *tofree = NULL;
3359 char pathbuf[PATH_MAX+1];
3363 pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3364 state->smb_fname->base_name,
3369 if (pathlen == -1) {
3370 tevent_req_error(req, ENOMEM);
3374 state->xattr_size = getxattr(path,
3377 talloc_array_length(state->xattr_value));
3379 TALLOC_FREE(tofree);
3380 if (state->xattr_size == -1) {
3381 tevent_req_error(req, err);
3385 tevent_req_done(req);
3389 static void vfswrap_getxattrat_do_async(void *private_data)
3391 struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3392 private_data, struct vfswrap_getxattrat_state);
3393 struct timespec start_time;
3394 struct timespec end_time;
3397 PROFILE_TIMESTAMP(&start_time);
3398 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3401 * Here we simulate a getxattrat()
3402 * call using fchdir();getxattr()
3405 per_thread_cwd_activate();
3407 /* Become the correct credential on this thread. */
3408 ret = set_thread_credentials(state->token->uid,
3410 (size_t)state->token->ngroups,
3411 state->token->groups);
3413 state->xattr_size = -1;
3414 state->vfs_aio_state.error = errno;
3418 ret = fchdir(state->dir_fsp->fh->fd);
3420 state->xattr_size = -1;
3421 state->vfs_aio_state.error = errno;
3425 state->xattr_size = getxattr(state->name,
3428 talloc_array_length(state->xattr_value));
3429 if (state->xattr_size == -1) {
3430 state->vfs_aio_state.error = errno;
3434 PROFILE_TIMESTAMP(&end_time);
3435 state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3436 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3439 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3441 struct tevent_req *req = tevent_req_callback_data(
3442 subreq, struct tevent_req);
3443 struct vfswrap_getxattrat_state *state = tevent_req_data(
3444 req, struct vfswrap_getxattrat_state);
3449 * Make sure we run as the user again
3451 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3454 ret = pthreadpool_tevent_job_recv(subreq);
3455 TALLOC_FREE(subreq);
3456 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3457 talloc_set_destructor(state, NULL);
3459 if (ret != EAGAIN) {
3460 tevent_req_error(req, ret);
3464 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3465 * means the lower level pthreadpool failed to create a new
3466 * thread. Fallback to sync processing in that case to allow
3467 * some progress for the client.
3469 vfswrap_getxattrat_do_sync(req);
3473 if (state->xattr_size == -1) {
3474 tevent_req_error(req, state->vfs_aio_state.error);
3478 if (state->xattr_value == NULL) {
3480 * The caller only wanted the size.
3482 tevent_req_done(req);
3487 * shrink the buffer to the returned size.
3488 * (can't fail). It means NULL if size is 0.
3490 state->xattr_value = talloc_realloc(state,
3495 tevent_req_done(req);
3498 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3499 struct vfs_aio_state *aio_state,
3500 TALLOC_CTX *mem_ctx,
3501 uint8_t **xattr_value)
3503 struct vfswrap_getxattrat_state *state = tevent_req_data(
3504 req, struct vfswrap_getxattrat_state);
3507 if (tevent_req_is_unix_error(req, &aio_state->error)) {
3508 tevent_req_received(req);
3512 *aio_state = state->vfs_aio_state;
3513 xattr_size = state->xattr_size;
3514 if (xattr_value != NULL) {
3515 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3518 tevent_req_received(req);
3522 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3524 return fgetxattr(fsp->fh->fd, name, value, size);
3527 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3528 const struct smb_filename *smb_fname,
3532 return listxattr(smb_fname->base_name, list, size);
3535 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3537 return flistxattr(fsp->fh->fd, list, size);
3540 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3541 const struct smb_filename *smb_fname,
3544 return removexattr(smb_fname->base_name, name);
3547 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3549 return fremovexattr(fsp->fh->fd, name);
3552 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3553 const struct smb_filename *smb_fname,
3559 return setxattr(smb_fname->base_name, name, value, size, flags);
3562 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3564 return fsetxattr(fsp->fh->fd, name, value, size, flags);
3567 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3572 static bool vfswrap_is_offline(struct connection_struct *conn,
3573 const struct smb_filename *fname)
3577 bool offline = false;
3579 if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3583 if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3584 #if defined(ENOTSUP)
3590 status = get_full_smb_filename(talloc_tos(), fname, &path);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 errno = map_errno_from_nt_status(status);
3596 offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3603 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3604 struct files_struct *fsp,
3605 TALLOC_CTX *mem_ctx,
3608 return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3611 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3612 struct files_struct *fsp,
3613 const DATA_BLOB old_cookie,
3614 TALLOC_CTX *mem_ctx,
3615 DATA_BLOB *new_cookie)
3617 return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3621 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3622 struct smb_request *smb1req,
3623 struct smbXsrv_open *op,
3624 const DATA_BLOB old_cookie,
3625 TALLOC_CTX *mem_ctx,
3626 struct files_struct **fsp,
3627 DATA_BLOB *new_cookie)
3629 return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3630 old_cookie, mem_ctx,
3634 static struct vfs_fn_pointers vfs_default_fns = {
3635 /* Disk operations */
3637 .connect_fn = vfswrap_connect,
3638 .disconnect_fn = vfswrap_disconnect,
3639 .disk_free_fn = vfswrap_disk_free,
3640 .get_quota_fn = vfswrap_get_quota,
3641 .set_quota_fn = vfswrap_set_quota,
3642 .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3643 .statvfs_fn = vfswrap_statvfs,
3644 .fs_capabilities_fn = vfswrap_fs_capabilities,
3645 .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3646 .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3647 .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3648 .snap_check_path_fn = vfswrap_snap_check_path,
3649 .snap_create_fn = vfswrap_snap_create,
3650 .snap_delete_fn = vfswrap_snap_delete,
3652 /* Directory operations */
3654 .fdopendir_fn = vfswrap_fdopendir,
3655 .readdir_fn = vfswrap_readdir,
3656 .readdir_attr_fn = vfswrap_readdir_attr,
3657 .seekdir_fn = vfswrap_seekdir,
3658 .telldir_fn = vfswrap_telldir,
3659 .rewind_dir_fn = vfswrap_rewinddir,
3660 .mkdirat_fn = vfswrap_mkdirat,
3661 .closedir_fn = vfswrap_closedir,
3663 /* File operations */
3665 .open_fn = vfswrap_open,
3666 .create_file_fn = vfswrap_create_file,
3667 .close_fn = vfswrap_close,
3668 .pread_fn = vfswrap_pread,
3669 .pread_send_fn = vfswrap_pread_send,
3670 .pread_recv_fn = vfswrap_pread_recv,
3671 .pwrite_fn = vfswrap_pwrite,
3672 .pwrite_send_fn = vfswrap_pwrite_send,
3673 .pwrite_recv_fn = vfswrap_pwrite_recv,
3674 .lseek_fn = vfswrap_lseek,
3675 .sendfile_fn = vfswrap_sendfile,
3676 .recvfile_fn = vfswrap_recvfile,
3677 .renameat_fn = vfswrap_renameat,
3678 .fsync_send_fn = vfswrap_fsync_send,
3679 .fsync_recv_fn = vfswrap_fsync_recv,
3680 .stat_fn = vfswrap_stat,
3681 .fstat_fn = vfswrap_fstat,
3682 .lstat_fn = vfswrap_lstat,
3683 .get_alloc_size_fn = vfswrap_get_alloc_size,
3684 .unlinkat_fn = vfswrap_unlinkat,
3685 .chmod_fn = vfswrap_chmod,
3686 .fchmod_fn = vfswrap_fchmod,
3687 .fchown_fn = vfswrap_fchown,
3688 .lchown_fn = vfswrap_lchown,
3689 .chdir_fn = vfswrap_chdir,
3690 .getwd_fn = vfswrap_getwd,
3691 .ntimes_fn = vfswrap_ntimes,
3692 .ftruncate_fn = vfswrap_ftruncate,
3693 .fallocate_fn = vfswrap_fallocate,
3694 .lock_fn = vfswrap_lock,
3695 .kernel_flock_fn = vfswrap_kernel_flock,
3696 .fcntl_fn = vfswrap_fcntl,
3697 .linux_setlease_fn = vfswrap_linux_setlease,
3698 .getlock_fn = vfswrap_getlock,
3699 .symlinkat_fn = vfswrap_symlinkat,
3700 .readlinkat_fn = vfswrap_readlinkat,
3701 .linkat_fn = vfswrap_linkat,
3702 .mknodat_fn = vfswrap_mknodat,
3703 .realpath_fn = vfswrap_realpath,
3704 .chflags_fn = vfswrap_chflags,
3705 .file_id_create_fn = vfswrap_file_id_create,
3706 .fs_file_id_fn = vfswrap_fs_file_id,
3707 .streaminfo_fn = vfswrap_streaminfo,
3708 .get_real_filename_fn = vfswrap_get_real_filename,
3709 .connectpath_fn = vfswrap_connectpath,
3710 .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3711 .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3712 .strict_lock_check_fn = vfswrap_strict_lock_check,
3713 .translate_name_fn = vfswrap_translate_name,
3714 .fsctl_fn = vfswrap_fsctl,
3715 .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3716 .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3717 .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3718 .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3719 .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3720 .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3721 .offload_read_send_fn = vfswrap_offload_read_send,
3722 .offload_read_recv_fn = vfswrap_offload_read_recv,
3723 .offload_write_send_fn = vfswrap_offload_write_send,
3724 .offload_write_recv_fn = vfswrap_offload_write_recv,
3725 .get_compression_fn = vfswrap_get_compression,
3726 .set_compression_fn = vfswrap_set_compression,
3728 /* NT ACL operations. */
3730 .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3731 .get_nt_acl_fn = vfswrap_get_nt_acl,
3732 .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3733 .audit_file_fn = vfswrap_audit_file,
3735 /* POSIX ACL operations. */
3737 .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3738 .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3739 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3740 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3741 .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3742 .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3743 .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3745 /* EA operations. */
3746 .getxattr_fn = vfswrap_getxattr,
3747 .getxattrat_send_fn = vfswrap_getxattrat_send,
3748 .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3749 .fgetxattr_fn = vfswrap_fgetxattr,
3750 .listxattr_fn = vfswrap_listxattr,
3751 .flistxattr_fn = vfswrap_flistxattr,
3752 .removexattr_fn = vfswrap_removexattr,
3753 .fremovexattr_fn = vfswrap_fremovexattr,
3754 .setxattr_fn = vfswrap_setxattr,
3755 .fsetxattr_fn = vfswrap_fsetxattr,
3757 /* aio operations */
3758 .aio_force_fn = vfswrap_aio_force,
3760 /* durable handle operations */
3761 .durable_cookie_fn = vfswrap_durable_cookie,
3762 .durable_disconnect_fn = vfswrap_durable_disconnect,
3763 .durable_reconnect_fn = vfswrap_durable_reconnect,
3767 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3770 * Here we need to implement every call!
3772 * As this is the end of the vfs module chain.
3774 smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3775 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3776 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);