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"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
42 #define DBGC_CLASS DBGC_VFS
44 /* Check for NULL pointer parameters in vfswrap_* functions */
46 /* We don't want to have NULL function pointers lying around. Someone
47 is sure to try and execute them. These stubs are used to prevent
50 static int vfswrap_connect(vfs_handle_struct
*handle
, const char *service
, const char *user
)
54 handle
->conn
->have_proc_fds
= sys_have_proc_fds();
55 #ifdef DISABLE_PROC_FDS
56 handle
->conn
->have_proc_fds
= false;
60 * assume the kernel will support openat2(),
61 * it will be reset on the first ENOSYS.
63 * Note that libreplace will always provide openat2(),
64 * but return -1/errno = ENOSYS...
66 * The option is only there to test the fallback code.
68 bval
= lp_parm_bool(SNUM(handle
->conn
),
70 "VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS",
73 handle
->conn
->open_how_resolve
|=
74 VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
;
76 #ifdef DISABLE_VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
77 handle
->conn
->open_how_resolve
&= ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
;
80 return 0; /* Return >= 0 for success */
83 static void vfswrap_disconnect(vfs_handle_struct
*handle
)
89 static uint64_t vfswrap_disk_free(vfs_handle_struct
*handle
,
90 const struct smb_filename
*smb_fname
,
95 if (sys_fsusage(smb_fname
->base_name
, dfree
, dsize
) != 0) {
103 static int vfswrap_get_quota(struct vfs_handle_struct
*handle
,
104 const struct smb_filename
*smb_fname
,
105 enum SMB_QUOTA_TYPE qtype
,
109 #ifdef HAVE_SYS_QUOTAS
112 START_PROFILE(syscall_get_quota
);
113 result
= sys_get_quota(smb_fname
->base_name
, qtype
, id
, qt
);
114 END_PROFILE(syscall_get_quota
);
122 static int vfswrap_set_quota(struct vfs_handle_struct
*handle
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*qt
)
124 #ifdef HAVE_SYS_QUOTAS
127 START_PROFILE(syscall_set_quota
);
128 result
= sys_set_quota(handle
->conn
->connectpath
, qtype
, id
, qt
);
129 END_PROFILE(syscall_set_quota
);
137 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
138 struct files_struct
*fsp
,
139 struct shadow_copy_data
*shadow_copy_data
,
143 return -1; /* Not implemented. */
146 static int vfswrap_statvfs(struct vfs_handle_struct
*handle
,
147 const struct smb_filename
*smb_fname
,
148 struct vfs_statvfs_struct
*statbuf
)
150 return sys_statvfs(smb_fname
->base_name
, statbuf
);
153 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct
*handle
,
154 enum timestamp_set_resolution
*p_ts_res
)
156 const struct loadparm_substitution
*lp_sub
=
157 loadparm_s3_global_substitution();
158 connection_struct
*conn
= handle
->conn
;
159 uint32_t caps
= FILE_CASE_SENSITIVE_SEARCH
| FILE_CASE_PRESERVED_NAMES
;
160 struct smb_filename
*smb_fname_cpath
= NULL
;
161 struct vfs_statvfs_struct statbuf
;
164 smb_fname_cpath
= synthetic_smb_fname(talloc_tos(),
170 if (smb_fname_cpath
== NULL
) {
174 ZERO_STRUCT(statbuf
);
175 ret
= SMB_VFS_STATVFS(conn
, smb_fname_cpath
, &statbuf
);
177 caps
= statbuf
.FsCapabilities
;
180 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
182 /* Work out what timestamp resolution we can
183 * use when setting a timestamp. */
185 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
187 TALLOC_FREE(smb_fname_cpath
);
191 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
192 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
193 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
194 /* If any of the normal UNIX directory timestamps
195 * have a non-zero tv_nsec component assume
196 * we might be able to set sub-second timestamps.
197 * See what filetime set primitives we have.
199 #if defined(HAVE_UTIMENSAT)
200 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
201 #elif defined(HAVE_UTIMES)
202 /* utimes allows msec timestamps to be set. */
203 *p_ts_res
= TIMESTAMP_SET_MSEC
;
204 #elif defined(HAVE_UTIME)
205 /* utime only allows sec timestamps to be set. */
206 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
209 DBG_DEBUG("vfswrap_fs_capabilities: timestamp "
211 "available on share %s, directory %s\n",
212 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
213 lp_servicename(talloc_tos(), lp_sub
, conn
->params
->service
),
216 TALLOC_FREE(smb_fname_cpath
);
220 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
221 struct dfs_GetDFSReferral
*r
)
223 struct junction_map
*junction
= NULL
;
224 size_t consumedcnt
= 0;
225 bool self_referral
= false;
226 char *pathnamep
= NULL
;
227 char *local_dfs_path
= NULL
;
230 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
232 if (DEBUGLVL(DBGLVL_DEBUG
)) {
233 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
236 /* get the junction entry */
237 if (r
->in
.req
.servername
== NULL
) {
238 return NT_STATUS_NOT_FOUND
;
242 * Trim pathname sent by client so it begins with only one backslash.
243 * Two backslashes confuse some dfs clients
246 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
247 if (local_dfs_path
== NULL
) {
248 return NT_STATUS_NO_MEMORY
;
250 pathnamep
= local_dfs_path
;
251 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
252 IS_DIRECTORY_SEP(pathnamep
[1])) {
256 junction
= talloc_zero(r
, struct junction_map
);
257 if (junction
== NULL
) {
258 return NT_STATUS_NO_MEMORY
;
261 /* The following call can change cwd. */
262 status
= get_referred_path(r
,
263 handle
->conn
->session_info
,
265 handle
->conn
->sconn
->remote_address
,
266 handle
->conn
->sconn
->local_address
,
267 junction
, &consumedcnt
, &self_referral
);
268 if (!NT_STATUS_IS_OK(status
)) {
269 struct smb_filename connectpath_fname
= {
270 .base_name
= handle
->conn
->connectpath
272 vfs_ChDir(handle
->conn
, &connectpath_fname
);
276 struct smb_filename connectpath_fname
= {
277 .base_name
= handle
->conn
->connectpath
279 vfs_ChDir(handle
->conn
, &connectpath_fname
);
282 if (!self_referral
) {
283 pathnamep
[consumedcnt
] = '\0';
285 if (DEBUGLVL(DBGLVL_INFO
)) {
286 dbgtext("Path %s to alternate path(s):",
288 for (i
=0; i
< junction
->referral_count
; i
++) {
290 junction
->referral_list
[i
].alternate_path
);
296 if (r
->in
.req
.max_referral_level
<= 2) {
297 max_referral_level
= 2;
299 if (r
->in
.req
.max_referral_level
>= 3) {
300 max_referral_level
= 3;
303 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
304 if (r
->out
.resp
== NULL
) {
305 return NT_STATUS_NO_MEMORY
;
308 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
309 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
311 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
313 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
316 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
317 struct dfs_referral_type
,
318 r
->out
.resp
->nb_referrals
);
319 if (r
->out
.resp
->referral_entries
== NULL
) {
320 return NT_STATUS_NO_MEMORY
;
323 switch (max_referral_level
) {
325 for(i
=0; i
< junction
->referral_count
; i
++) {
326 struct referral
*ref
= &junction
->referral_list
[i
];
327 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
328 struct dfs_referral_type
*t
=
329 &r
->out
.resp
->referral_entries
[i
];
330 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
333 v2
->size
= VERSION2_REFERRAL_SIZE
;
335 v2
->server_type
= DFS_SERVER_ROOT
;
337 v2
->server_type
= DFS_SERVER_NON_ROOT
;
340 v2
->proximity
= ref
->proximity
;
342 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
343 if (v2
->DFS_path
== NULL
) {
344 return NT_STATUS_NO_MEMORY
;
346 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
347 if (v2
->DFS_alt_path
== NULL
) {
348 return NT_STATUS_NO_MEMORY
;
350 v2
->netw_address
= talloc_strdup(mem_ctx
,
351 ref
->alternate_path
);
352 if (v2
->netw_address
== NULL
) {
353 return NT_STATUS_NO_MEMORY
;
359 for(i
=0; i
< junction
->referral_count
; i
++) {
360 struct referral
*ref
= &junction
->referral_list
[i
];
361 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
362 struct dfs_referral_type
*t
=
363 &r
->out
.resp
->referral_entries
[i
];
364 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
365 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
368 v3
->size
= VERSION3_REFERRAL_SIZE
;
370 v3
->server_type
= DFS_SERVER_ROOT
;
372 v3
->server_type
= DFS_SERVER_NON_ROOT
;
376 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
377 if (r1
->DFS_path
== NULL
) {
378 return NT_STATUS_NO_MEMORY
;
380 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
381 if (r1
->DFS_alt_path
== NULL
) {
382 return NT_STATUS_NO_MEMORY
;
384 r1
->netw_address
= talloc_strdup(mem_ctx
,
385 ref
->alternate_path
);
386 if (r1
->netw_address
== NULL
) {
387 return NT_STATUS_NO_MEMORY
;
392 DBG_ERR("Invalid dfs referral version: %d\n",
394 return NT_STATUS_INVALID_LEVEL
;
397 if (DEBUGLVL(DBGLVL_DEBUG
)) {
398 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
404 static NTSTATUS
vfswrap_create_dfs_pathat(struct vfs_handle_struct
*handle
,
405 struct files_struct
*dirfsp
,
406 const struct smb_filename
*smb_fname
,
407 const struct referral
*reflist
,
408 size_t referral_count
)
410 TALLOC_CTX
*frame
= talloc_stackframe();
411 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
413 char *msdfs_link
= NULL
;
415 /* Form the msdfs_link contents */
416 msdfs_link
= msdfs_link_string(frame
,
419 if (msdfs_link
== NULL
) {
423 ret
= symlinkat(msdfs_link
,
424 fsp_get_pathref_fd(dirfsp
),
425 smb_fname
->base_name
);
427 status
= NT_STATUS_OK
;
429 status
= map_nt_error_from_unix(errno
);
439 * Read and return the contents of a DFS redirect given a
440 * pathname. A caller can pass in NULL for ppreflist and
441 * preferral_count but still determine if this was a
442 * DFS redirect point by getting NT_STATUS_OK back
443 * without incurring the overhead of reading and parsing
444 * the referral contents.
447 static NTSTATUS
vfswrap_read_dfs_pathat(struct vfs_handle_struct
*handle
,
449 struct files_struct
*dirfsp
,
450 struct smb_filename
*smb_fname
,
451 struct referral
**ppreflist
,
452 size_t *preferral_count
)
454 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
456 char *link_target
= NULL
;
459 #if defined(HAVE_BROKEN_READLINK)
460 char link_target_buf
[PATH_MAX
];
462 char link_target_buf
[7];
466 if (is_named_stream(smb_fname
)) {
467 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
471 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
473 * We're only checking if this is a DFS
474 * redirect. We don't need to return data.
476 bufsize
= sizeof(link_target_buf
);
477 link_target
= link_target_buf
;
480 link_target
= talloc_array(mem_ctx
, char, bufsize
);
486 referral_len
= readlinkat(fsp_get_pathref_fd(dirfsp
),
487 smb_fname
->base_name
,
490 if (referral_len
== -1) {
491 if (errno
== EINVAL
) {
493 * If the path isn't a link, readlinkat
494 * returns EINVAL. Allow the caller to
497 DBG_INFO("%s is not a link.\n", smb_fname
->base_name
);
498 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
500 status
= map_nt_error_from_unix(errno
);
501 if (errno
== ENOENT
) {
502 DBG_NOTICE("Error reading "
503 "msdfs link %s: %s\n",
504 smb_fname
->base_name
,
507 DBG_ERR("Error reading "
508 "msdfs link %s: %s\n",
509 smb_fname
->base_name
,
515 link_target
[referral_len
] = '\0';
517 DBG_INFO("%s -> %s\n",
518 smb_fname
->base_name
,
521 if (!strnequal(link_target
, "msdfs:", 6)) {
522 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
526 ret
= sys_fstatat(fsp_get_pathref_fd(dirfsp
),
527 smb_fname
->base_name
,
530 lp_fake_directory_create_times(SNUM(handle
->conn
)));
532 status
= map_nt_error_from_unix(errno
);
536 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
537 /* Early return for checking if this is a DFS link. */
541 ok
= parse_msdfs_symlink(mem_ctx
,
542 lp_msdfs_shuffle_referrals(SNUM(handle
->conn
)),
548 status
= NT_STATUS_OK
;
550 status
= NT_STATUS_NO_MEMORY
;
555 if (link_target
!= link_target_buf
) {
556 TALLOC_FREE(link_target
);
561 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
563 const char *service_path
,
566 return NT_STATUS_NOT_SUPPORTED
;
569 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
571 const char *base_volume
,
577 return NT_STATUS_NOT_SUPPORTED
;
580 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
585 return NT_STATUS_NOT_SUPPORTED
;
588 /* Directory operations */
590 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
597 START_PROFILE(syscall_fdopendir
);
598 result
= sys_fdopendir(fsp_get_io_fd(fsp
));
599 END_PROFILE(syscall_fdopendir
);
603 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
604 struct files_struct
*dirfsp
,
607 struct dirent
*result
;
609 START_PROFILE(syscall_readdir
);
611 result
= readdir(dirp
);
612 END_PROFILE(syscall_readdir
);
617 static NTSTATUS
vfswrap_freaddir_attr(struct vfs_handle_struct
*handle
,
618 struct files_struct
*fsp
,
620 struct readdir_attr_data
**attr_data
)
622 return NT_STATUS_NOT_SUPPORTED
;
625 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
627 START_PROFILE(syscall_rewinddir
);
629 END_PROFILE(syscall_rewinddir
);
632 static int vfswrap_mkdirat(vfs_handle_struct
*handle
,
633 struct files_struct
*dirfsp
,
634 const struct smb_filename
*smb_fname
,
639 START_PROFILE(syscall_mkdirat
);
641 result
= mkdirat(fsp_get_pathref_fd(dirfsp
), smb_fname
->base_name
, mode
);
643 END_PROFILE(syscall_mkdirat
);
647 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
651 START_PROFILE(syscall_closedir
);
652 result
= closedir(dirp
);
653 END_PROFILE(syscall_closedir
);
657 /* File operations */
659 static int vfswrap_openat(vfs_handle_struct
*handle
,
660 const struct files_struct
*dirfsp
,
661 const struct smb_filename
*smb_fname
,
663 const struct vfs_open_how
*how
)
665 int flags
= how
->flags
;
666 mode_t mode
= how
->mode
;
667 bool have_opath
= false;
668 bool became_root
= false;
671 START_PROFILE(syscall_openat
);
673 if (how
->resolve
& ~(VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
|
674 VFS_OPEN_HOW_WITH_BACKUP_INTENT
)) {
680 SMB_ASSERT(!is_named_stream(smb_fname
));
684 if (fsp
->fsp_flags
.is_pathref
) {
687 if (flags
& O_PATH
) {
689 * From "man 2 openat":
691 * When O_PATH is specified in flags, flag bits other than
692 * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored.
694 * From "man 2 openat2":
696 * Whereas openat(2) ignores unknown bits in its flags
697 * argument, openat2() returns an error if unknown or
698 * conflicting flags are specified in how.flags.
700 * So we better clear ignored/invalid flags
701 * and only keep the expected ones.
703 flags
&= (O_PATH
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
707 if (how
->resolve
& VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
) {
708 struct open_how linux_how
= {
711 .resolve
= RESOLVE_NO_SYMLINKS
,
714 result
= openat2(fsp_get_pathref_fd(dirfsp
),
715 smb_fname
->base_name
,
719 if (errno
== ENOSYS
) {
721 * The kernel doesn't support
722 * openat2(), so indicate to
724 * VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
725 * would just be a waste of time.
727 fsp
->conn
->open_how_resolve
&=
728 ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
;
736 if (fsp
->fsp_flags
.is_pathref
&& !have_opath
) {
741 result
= openat(fsp_get_pathref_fd(dirfsp
),
742 smb_fname
->base_name
,
754 fsp
->fsp_flags
.have_proc_fds
= fsp
->conn
->have_proc_fds
;
757 * "/proc/self/fd/-1" never exists. Indicate to upper
758 * layers that for this fsp a possible name-based
759 * fallback is the only way to go.
761 fsp
->fsp_flags
.have_proc_fds
= false;
765 END_PROFILE(syscall_openat
);
768 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
769 struct smb_request
*req
,
770 struct files_struct
*dirfsp
,
771 struct smb_filename
*smb_fname
,
772 uint32_t access_mask
,
773 uint32_t share_access
,
774 uint32_t create_disposition
,
775 uint32_t create_options
,
776 uint32_t file_attributes
,
777 uint32_t oplock_request
,
778 const struct smb2_lease
*lease
,
779 uint64_t allocation_size
,
780 uint32_t private_flags
,
781 struct security_descriptor
*sd
,
782 struct ea_list
*ea_list
,
783 files_struct
**result
,
785 const struct smb2_create_blobs
*in_context_blobs
,
786 struct smb2_create_blobs
*out_context_blobs
)
788 return create_file_default(handle
->conn
, req
, dirfsp
, smb_fname
,
789 access_mask
, share_access
,
790 create_disposition
, create_options
,
791 file_attributes
, oplock_request
, lease
,
792 allocation_size
, private_flags
,
794 pinfo
, in_context_blobs
, out_context_blobs
);
797 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
801 START_PROFILE(syscall_close
);
802 result
= fd_close_posix(fsp
);
803 END_PROFILE(syscall_close
);
807 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
808 size_t n
, off_t offset
)
812 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
813 START_PROFILE_BYTES(syscall_pread
, n
);
814 result
= sys_pread_full(fsp_get_io_fd(fsp
), data
, n
, offset
);
815 END_PROFILE_BYTES(syscall_pread
);
817 if (result
== -1 && errno
== ESPIPE
) {
818 /* Maintain the fiction that pipes can be seeked (sought?) on. */
819 result
= sys_read(fsp_get_io_fd(fsp
), data
, n
);
820 fh_set_pos(fsp
->fh
, 0);
823 #else /* HAVE_PREAD */
826 #endif /* HAVE_PREAD */
831 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
832 size_t n
, off_t offset
)
836 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
837 START_PROFILE_BYTES(syscall_pwrite
, n
);
838 result
= sys_pwrite_full(fsp_get_io_fd(fsp
), data
, n
, offset
);
839 END_PROFILE_BYTES(syscall_pwrite
);
841 if (result
== -1 && errno
== ESPIPE
) {
842 /* Maintain the fiction that pipes can be sought on. */
843 result
= sys_write(fsp_get_io_fd(fsp
), data
, n
);
846 #else /* HAVE_PWRITE */
849 #endif /* HAVE_PWRITE */
854 struct vfswrap_pread_state
{
861 struct vfs_aio_state vfs_aio_state
;
862 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
865 static void vfs_pread_do(void *private_data
);
866 static void vfs_pread_done(struct tevent_req
*subreq
);
867 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
869 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
871 struct tevent_context
*ev
,
872 struct files_struct
*fsp
,
874 size_t n
, off_t offset
)
876 struct tevent_req
*req
, *subreq
;
877 struct vfswrap_pread_state
*state
;
879 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
885 state
->fd
= fsp_get_io_fd(fsp
);
888 state
->offset
= offset
;
890 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
891 state
->profile_bytes
, n
);
892 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
894 subreq
= pthreadpool_tevent_job_send(
895 state
, ev
, handle
->conn
->sconn
->pool
,
896 vfs_pread_do
, state
);
897 if (tevent_req_nomem(subreq
, req
)) {
898 return tevent_req_post(req
, ev
);
900 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
902 talloc_set_destructor(state
, vfs_pread_state_destructor
);
907 static void vfs_pread_do(void *private_data
)
909 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
910 private_data
, struct vfswrap_pread_state
);
911 struct timespec start_time
;
912 struct timespec end_time
;
914 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
916 PROFILE_TIMESTAMP(&start_time
);
918 state
->ret
= sys_pread_full(state
->fd
,
923 if (state
->ret
== -1) {
924 state
->vfs_aio_state
.error
= errno
;
927 PROFILE_TIMESTAMP(&end_time
);
929 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
931 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
934 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
939 static void vfs_pread_done(struct tevent_req
*subreq
)
941 struct tevent_req
*req
= tevent_req_callback_data(
942 subreq
, struct tevent_req
);
943 struct vfswrap_pread_state
*state
= tevent_req_data(
944 req
, struct vfswrap_pread_state
);
947 ret
= pthreadpool_tevent_job_recv(subreq
);
949 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
950 talloc_set_destructor(state
, NULL
);
953 tevent_req_error(req
, ret
);
957 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
958 * means the lower level pthreadpool failed to create a new
959 * thread. Fallback to sync processing in that case to allow
960 * some progress for the client.
965 tevent_req_done(req
);
968 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
969 struct vfs_aio_state
*vfs_aio_state
)
971 struct vfswrap_pread_state
*state
= tevent_req_data(
972 req
, struct vfswrap_pread_state
);
974 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
978 *vfs_aio_state
= state
->vfs_aio_state
;
982 struct vfswrap_pwrite_state
{
989 struct vfs_aio_state vfs_aio_state
;
990 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
993 static void vfs_pwrite_do(void *private_data
);
994 static void vfs_pwrite_done(struct tevent_req
*subreq
);
995 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
997 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
999 struct tevent_context
*ev
,
1000 struct files_struct
*fsp
,
1002 size_t n
, off_t offset
)
1004 struct tevent_req
*req
, *subreq
;
1005 struct vfswrap_pwrite_state
*state
;
1007 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
1013 state
->fd
= fsp_get_io_fd(fsp
);
1016 state
->offset
= offset
;
1018 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
1019 state
->profile_bytes
, n
);
1020 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1022 subreq
= pthreadpool_tevent_job_send(
1023 state
, ev
, handle
->conn
->sconn
->pool
,
1024 vfs_pwrite_do
, state
);
1025 if (tevent_req_nomem(subreq
, req
)) {
1026 return tevent_req_post(req
, ev
);
1028 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
1030 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
1035 static void vfs_pwrite_do(void *private_data
)
1037 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
1038 private_data
, struct vfswrap_pwrite_state
);
1039 struct timespec start_time
;
1040 struct timespec end_time
;
1042 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
1044 PROFILE_TIMESTAMP(&start_time
);
1046 state
->ret
= sys_pwrite_full(state
->fd
,
1051 if (state
->ret
== -1) {
1052 state
->vfs_aio_state
.error
= errno
;
1055 PROFILE_TIMESTAMP(&end_time
);
1057 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1059 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1062 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
1067 static void vfs_pwrite_done(struct tevent_req
*subreq
)
1069 struct tevent_req
*req
= tevent_req_callback_data(
1070 subreq
, struct tevent_req
);
1071 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1072 req
, struct vfswrap_pwrite_state
);
1075 ret
= pthreadpool_tevent_job_recv(subreq
);
1076 TALLOC_FREE(subreq
);
1077 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1078 talloc_set_destructor(state
, NULL
);
1080 if (ret
!= EAGAIN
) {
1081 tevent_req_error(req
, ret
);
1085 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1086 * means the lower level pthreadpool failed to create a new
1087 * thread. Fallback to sync processing in that case to allow
1088 * some progress for the client.
1090 vfs_pwrite_do(state
);
1093 tevent_req_done(req
);
1096 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
1097 struct vfs_aio_state
*vfs_aio_state
)
1099 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1100 req
, struct vfswrap_pwrite_state
);
1102 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1106 *vfs_aio_state
= state
->vfs_aio_state
;
1110 struct vfswrap_fsync_state
{
1114 struct vfs_aio_state vfs_aio_state
;
1115 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
1118 static void vfs_fsync_do(void *private_data
);
1119 static void vfs_fsync_done(struct tevent_req
*subreq
);
1120 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
1122 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
1123 TALLOC_CTX
*mem_ctx
,
1124 struct tevent_context
*ev
,
1125 struct files_struct
*fsp
)
1127 struct tevent_req
*req
, *subreq
;
1128 struct vfswrap_fsync_state
*state
;
1130 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
1136 state
->fd
= fsp_get_io_fd(fsp
);
1138 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync
, profile_p
,
1139 state
->profile_bytes
, 0);
1140 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1142 subreq
= pthreadpool_tevent_job_send(
1143 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1144 if (tevent_req_nomem(subreq
, req
)) {
1145 return tevent_req_post(req
, ev
);
1147 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1149 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1154 static void vfs_fsync_do(void *private_data
)
1156 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1157 private_data
, struct vfswrap_fsync_state
);
1158 struct timespec start_time
;
1159 struct timespec end_time
;
1161 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
1163 PROFILE_TIMESTAMP(&start_time
);
1166 state
->ret
= fsync(state
->fd
);
1167 } while ((state
->ret
== -1) && (errno
== EINTR
));
1169 if (state
->ret
== -1) {
1170 state
->vfs_aio_state
.error
= errno
;
1173 PROFILE_TIMESTAMP(&end_time
);
1175 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1177 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1180 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1185 static void vfs_fsync_done(struct tevent_req
*subreq
)
1187 struct tevent_req
*req
= tevent_req_callback_data(
1188 subreq
, struct tevent_req
);
1189 struct vfswrap_fsync_state
*state
= tevent_req_data(
1190 req
, struct vfswrap_fsync_state
);
1193 ret
= pthreadpool_tevent_job_recv(subreq
);
1194 TALLOC_FREE(subreq
);
1195 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1196 talloc_set_destructor(state
, NULL
);
1198 if (ret
!= EAGAIN
) {
1199 tevent_req_error(req
, ret
);
1203 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1204 * means the lower level pthreadpool failed to create a new
1205 * thread. Fallback to sync processing in that case to allow
1206 * some progress for the client.
1208 vfs_fsync_do(state
);
1211 tevent_req_done(req
);
1214 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1215 struct vfs_aio_state
*vfs_aio_state
)
1217 struct vfswrap_fsync_state
*state
= tevent_req_data(
1218 req
, struct vfswrap_fsync_state
);
1220 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1224 *vfs_aio_state
= state
->vfs_aio_state
;
1228 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1232 START_PROFILE(syscall_lseek
);
1234 result
= lseek(fsp_get_io_fd(fsp
), offset
, whence
);
1236 * We want to maintain the fiction that we can seek
1237 * on a fifo for file system purposes. This allows
1238 * people to set up UNIX fifo's that feed data to Windows
1239 * applications. JRA.
1242 if((result
== -1) && (errno
== ESPIPE
)) {
1247 END_PROFILE(syscall_lseek
);
1251 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1252 off_t offset
, size_t n
)
1256 START_PROFILE_BYTES(syscall_sendfile
, n
);
1257 result
= sys_sendfile(tofd
, fsp_get_io_fd(fromfsp
), hdr
, offset
, n
);
1258 END_PROFILE_BYTES(syscall_sendfile
);
1262 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1264 files_struct
*tofsp
,
1270 START_PROFILE_BYTES(syscall_recvfile
, n
);
1271 result
= sys_recvfile(fromfd
, fsp_get_io_fd(tofsp
), offset
, n
);
1272 END_PROFILE_BYTES(syscall_recvfile
);
1276 static int vfswrap_renameat(vfs_handle_struct
*handle
,
1277 files_struct
*srcfsp
,
1278 const struct smb_filename
*smb_fname_src
,
1279 files_struct
*dstfsp
,
1280 const struct smb_filename
*smb_fname_dst
)
1284 START_PROFILE(syscall_renameat
);
1286 SMB_ASSERT(!is_named_stream(smb_fname_src
));
1287 SMB_ASSERT(!is_named_stream(smb_fname_dst
));
1289 result
= renameat(fsp_get_pathref_fd(srcfsp
),
1290 smb_fname_src
->base_name
,
1291 fsp_get_pathref_fd(dstfsp
),
1292 smb_fname_dst
->base_name
);
1294 END_PROFILE(syscall_renameat
);
1298 static int vfswrap_stat(vfs_handle_struct
*handle
,
1299 struct smb_filename
*smb_fname
)
1303 START_PROFILE(syscall_stat
);
1305 SMB_ASSERT(!is_named_stream(smb_fname
));
1307 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1308 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1310 END_PROFILE(syscall_stat
);
1314 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1318 START_PROFILE(syscall_fstat
);
1319 result
= sys_fstat(fsp_get_pathref_fd(fsp
),
1320 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1321 END_PROFILE(syscall_fstat
);
1325 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1326 struct smb_filename
*smb_fname
)
1330 START_PROFILE(syscall_lstat
);
1332 SMB_ASSERT(!is_named_stream(smb_fname
));
1334 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1335 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1337 END_PROFILE(syscall_lstat
);
1341 static int vfswrap_fstatat(
1342 struct vfs_handle_struct
*handle
,
1343 const struct files_struct
*dirfsp
,
1344 const struct smb_filename
*smb_fname
,
1345 SMB_STRUCT_STAT
*sbuf
,
1350 START_PROFILE(syscall_fstatat
);
1352 SMB_ASSERT(!is_named_stream(smb_fname
));
1354 result
= sys_fstatat(
1355 fsp_get_pathref_fd(dirfsp
),
1356 smb_fname
->base_name
,
1359 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1361 END_PROFILE(syscall_fstatat
);
1365 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1367 enum vfs_translate_direction direction
,
1368 TALLOC_CTX
*mem_ctx
,
1371 return NT_STATUS_NONE_MAPPED
;
1375 * Return allocated parent directory and basename of path
1377 * Note: if requesting atname, it is returned as talloc child of the
1378 * parent. Freeing the parent is thus sufficient to free both.
1380 static NTSTATUS
vfswrap_parent_pathname(struct vfs_handle_struct
*handle
,
1381 TALLOC_CTX
*mem_ctx
,
1382 const struct smb_filename
*smb_fname_in
,
1383 struct smb_filename
**parent_dir_out
,
1384 struct smb_filename
**atname_out
)
1386 struct smb_filename
*parent
= NULL
;
1387 struct smb_filename
*name
= NULL
;
1390 parent
= cp_smb_filename_nostream(mem_ctx
, smb_fname_in
);
1391 if (parent
== NULL
) {
1392 return NT_STATUS_NO_MEMORY
;
1394 SET_STAT_INVALID(parent
->st
);
1396 p
= strrchr_m(parent
->base_name
, '/'); /* Find final '/', if any */
1398 TALLOC_FREE(parent
->base_name
);
1399 parent
->base_name
= talloc_strdup(parent
, ".");
1400 if (parent
->base_name
== NULL
) {
1401 TALLOC_FREE(parent
);
1402 return NT_STATUS_NO_MEMORY
;
1404 p
= smb_fname_in
->base_name
;
1410 if (atname_out
== NULL
) {
1411 *parent_dir_out
= parent
;
1412 return NT_STATUS_OK
;
1415 name
= synthetic_smb_fname(
1418 smb_fname_in
->stream_name
,
1421 smb_fname_in
->flags
);
1423 return NT_STATUS_NO_MEMORY
;
1426 *parent_dir_out
= parent
;
1428 return NT_STATUS_OK
;
1432 * Implement the default fsctl operation.
1434 static bool vfswrap_logged_ioctl_message
= false;
1436 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1437 struct files_struct
*fsp
,
1440 uint16_t req_flags
, /* Needed for UNICODE ... */
1441 const uint8_t *_in_data
,
1443 uint8_t **_out_data
,
1444 uint32_t max_out_len
,
1447 const char *in_data
= (const char *)_in_data
;
1448 char **out_data
= (char **)_out_data
;
1452 * Currently all fsctls operate on the base
1453 * file if given an alternate data stream.
1454 * Revisit this if we implement fsctls later
1455 * that need access to the ADS handle.
1457 fsp
= metadata_fsp(fsp
);
1460 case FSCTL_SET_SPARSE
:
1462 bool set_sparse
= true;
1464 if (in_len
>= 1 && in_data
[0] == 0) {
1468 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1470 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1471 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1472 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1473 nt_errstr(status
)));
1478 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1480 unsigned char objid
[16];
1481 uint8_t *return_data
= NULL
;
1483 /* This should return the object-id on this file.
1484 * I think I'll make this be the inode+dev. JRA.
1487 DBG_DEBUG("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1490 *out_len
= MIN(max_out_len
, 64);
1492 /* Hmmm, will this cause problems if less data asked for? */
1493 return_data
= talloc_array(ctx
, uint8_t, 64);
1494 if (return_data
== NULL
) {
1495 return NT_STATUS_NO_MEMORY
;
1498 /* For backwards compatibility only store the dev/inode. */
1499 push_file_id_16(return_data
, &fsp
->file_id
);
1500 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1501 push_file_id_16(return_data
+ 32, &fsp
->file_id
);
1502 memset(return_data
+48, 0, 16);
1503 *_out_data
= return_data
;
1504 return NT_STATUS_OK
;
1507 case FSCTL_GET_REPARSE_POINT
:
1510 status
= fsctl_get_reparse_point(
1511 fsp
, ctx
, &tag
, _out_data
, max_out_len
, out_len
);
1515 case FSCTL_SET_REPARSE_POINT
:
1517 status
= fsctl_set_reparse_point(fsp
, ctx
, _in_data
, in_len
);
1521 case FSCTL_DELETE_REPARSE_POINT
:
1523 status
= fsctl_del_reparse_point(fsp
, ctx
, _in_data
, in_len
);
1527 case FSCTL_GET_SHADOW_COPY_DATA
:
1530 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1531 * and return their volume names. If max_data_count is 16, then it is just
1532 * asking for the number of volumes and length of the combined names.
1534 * pdata is the data allocated by our caller, but that uses
1535 * total_data_count (which is 0 in our case) rather than max_data_count.
1536 * Allocate the correct amount and return the pointer to let
1537 * it be deallocated when we return.
1539 struct shadow_copy_data
*shadow_data
= NULL
;
1540 bool labels
= False
;
1541 uint32_t labels_data_count
= 0;
1543 char *cur_pdata
= NULL
;
1545 if (max_out_len
< 16) {
1546 DBG_ERR("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1548 return NT_STATUS_INVALID_PARAMETER
;
1551 if (max_out_len
> 16) {
1555 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1556 if (shadow_data
== NULL
) {
1557 DBG_ERR("TALLOC_ZERO() failed!\n");
1558 return NT_STATUS_NO_MEMORY
;
1562 * Call the VFS routine to actually do the work.
1564 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1565 int log_lev
= DBGLVL_ERR
;
1567 /* broken module didn't set errno on error */
1568 status
= NT_STATUS_UNSUCCESSFUL
;
1570 status
= map_nt_error_from_unix(errno
);
1571 if (NT_STATUS_EQUAL(status
,
1572 NT_STATUS_NOT_SUPPORTED
)) {
1573 log_lev
= DBGLVL_INFO
;
1576 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1577 "connectpath %s, failed - %s.\n",
1578 fsp
->conn
->connectpath
,
1579 nt_errstr(status
)));
1580 TALLOC_FREE(shadow_data
);
1584 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1585 sizeof(SHADOW_COPY_LABEL
)) + 2;
1590 *out_len
= 12 + labels_data_count
;
1593 if (max_out_len
< *out_len
) {
1594 DBG_ERR("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1595 max_out_len
, *out_len
);
1596 TALLOC_FREE(shadow_data
);
1597 return NT_STATUS_BUFFER_TOO_SMALL
;
1600 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1601 if (cur_pdata
== NULL
) {
1602 TALLOC_FREE(shadow_data
);
1603 return NT_STATUS_NO_MEMORY
;
1606 *out_data
= cur_pdata
;
1608 /* num_volumes 4 bytes */
1609 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1612 /* num_labels 4 bytes */
1613 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1616 /* needed_data_count 4 bytes */
1617 SIVAL(cur_pdata
, 8, labels_data_count
);
1621 DBG_DEBUG("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1622 shadow_data
->num_volumes
, fsp_str_dbg(fsp
));
1623 if (labels
&& shadow_data
->labels
) {
1624 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1626 status
= srvstr_push(cur_pdata
, req_flags
,
1627 cur_pdata
, shadow_data
->labels
[i
],
1628 2 * sizeof(SHADOW_COPY_LABEL
),
1629 STR_UNICODE
|STR_TERMINATE
, &len
);
1630 if (!NT_STATUS_IS_OK(status
)) {
1631 TALLOC_FREE(*out_data
);
1632 TALLOC_FREE(shadow_data
);
1635 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1636 DEBUGADD(DBGLVL_DEBUG
,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1640 TALLOC_FREE(shadow_data
);
1642 return NT_STATUS_OK
;
1645 case FSCTL_FIND_FILES_BY_SID
:
1647 /* pretend this succeeded -
1649 * we have to send back a list with all files owned by this SID
1651 * but I have to check that --metze
1655 struct dom_sid_buf buf
;
1659 DBG_DEBUG("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1663 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1664 return NT_STATUS_INVALID_PARAMETER
;
1667 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1669 /* unknown 4 bytes: this is not the length of the sid :-( */
1670 /*unknown = IVAL(pdata,0);*/
1672 ret
= sid_parse(_in_data
+ 4, sid_len
, &sid
);
1674 return NT_STATUS_INVALID_PARAMETER
;
1676 DEBUGADD(DBGLVL_DEBUG
, ("for SID: %s\n",
1677 dom_sid_str_buf(&sid
, &buf
)));
1679 if (!sid_to_uid(&sid
, &uid
)) {
1680 DBG_ERR("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1681 dom_sid_str_buf(&sid
, &buf
),
1682 (unsigned long)sid_len
);
1686 /* we can take a look at the find source :-)
1688 * find ./ -uid $uid -name '*' is what we need here
1691 * and send 4bytes len and then NULL terminated unicode strings
1694 * but I don't know how to deal with the paged results
1695 * (maybe we can hang the result anywhere in the fsp struct)
1697 * but I don't know how to deal with the paged results
1698 * (maybe we can hang the result anywhere in the fsp struct)
1700 * we don't send all files at once
1701 * and at the next we should *not* start from the beginning,
1702 * so we have to cache the result
1707 /* this works for now... */
1708 return NT_STATUS_OK
;
1711 case FSCTL_QUERY_ALLOCATED_RANGES
:
1713 /* FIXME: This is just a dummy reply, telling that all of the
1714 * file is allocated. MKS cp needs that.
1715 * Adding the real allocated ranges via FIEMAP on Linux
1716 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1717 * this FSCTL correct for sparse files.
1719 uint64_t offset
, length
;
1720 char *out_data_tmp
= NULL
;
1723 DBG_ERR("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1725 return NT_STATUS_INVALID_PARAMETER
;
1728 if (max_out_len
< 16) {
1729 DBG_ERR("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1731 return NT_STATUS_INVALID_PARAMETER
;
1734 offset
= BVAL(in_data
,0);
1735 length
= BVAL(in_data
,8);
1737 if (offset
+ length
< offset
) {
1738 /* No 64-bit integer wrap. */
1739 return NT_STATUS_INVALID_PARAMETER
;
1742 /* Shouldn't this be SMB_VFS_STAT ... ? */
1743 status
= vfs_stat_fsp(fsp
);
1744 if (!NT_STATUS_IS_OK(status
)) {
1749 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1750 if (out_data_tmp
== NULL
) {
1751 DBG_DEBUG("unable to allocate memory for response\n");
1752 return NT_STATUS_NO_MEMORY
;
1755 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1756 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1758 memset(out_data_tmp
, 0, *out_len
);
1760 uint64_t end
= offset
+ length
;
1761 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1762 SBVAL(out_data_tmp
, 0, 0);
1763 SBVAL(out_data_tmp
, 8, end
);
1766 *out_data
= out_data_tmp
;
1768 return NT_STATUS_OK
;
1771 case FSCTL_IS_VOLUME_DIRTY
:
1773 DBG_DEBUG("FSCTL_IS_VOLUME_DIRTY: called on %s "
1774 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
));
1776 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1777 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1779 return NT_STATUS_INVALID_PARAMETER
;
1784 * Only print once ... unfortunately there could be lots of
1785 * different FSCTLs that are called.
1787 if (!vfswrap_logged_ioctl_message
) {
1788 vfswrap_logged_ioctl_message
= true;
1789 DBG_NOTICE("%s (0x%x): Currently not implemented.\n",
1790 __func__
, function
);
1794 return NT_STATUS_NOT_SUPPORTED
;
1797 static bool vfswrap_is_offline(struct connection_struct
*conn
,
1798 const struct smb_filename
*fname
);
1800 struct vfswrap_get_dos_attributes_state
{
1801 struct vfs_aio_state aio_state
;
1802 connection_struct
*conn
;
1803 TALLOC_CTX
*mem_ctx
;
1804 struct tevent_context
*ev
;
1805 files_struct
*dir_fsp
;
1806 struct smb_filename
*smb_fname
;
1811 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
);
1813 static struct tevent_req
*vfswrap_get_dos_attributes_send(
1814 TALLOC_CTX
*mem_ctx
,
1815 struct tevent_context
*ev
,
1816 struct vfs_handle_struct
*handle
,
1817 files_struct
*dir_fsp
,
1818 struct smb_filename
*smb_fname
)
1820 struct tevent_req
*req
= NULL
;
1821 struct tevent_req
*subreq
= NULL
;
1822 struct vfswrap_get_dos_attributes_state
*state
= NULL
;
1824 SMB_ASSERT(!is_named_stream(smb_fname
));
1826 req
= tevent_req_create(mem_ctx
, &state
,
1827 struct vfswrap_get_dos_attributes_state
);
1832 *state
= (struct vfswrap_get_dos_attributes_state
) {
1833 .conn
= dir_fsp
->conn
,
1837 .smb_fname
= smb_fname
,
1840 if (!lp_store_dos_attributes(SNUM(dir_fsp
->conn
))) {
1841 DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
1842 "\"store dos attributes\" is disabled\n",
1843 dir_fsp
->conn
->connectpath
);
1844 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1845 return tevent_req_post(req
, ev
);
1848 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1852 SAMBA_XATTR_DOS_ATTRIB
,
1854 if (tevent_req_nomem(subreq
, req
)) {
1855 return tevent_req_post(req
, ev
);
1857 tevent_req_set_callback(subreq
,
1858 vfswrap_get_dos_attributes_getxattr_done
,
1864 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
)
1866 struct tevent_req
*req
=
1867 tevent_req_callback_data(subreq
,
1869 struct vfswrap_get_dos_attributes_state
*state
=
1870 tevent_req_data(req
,
1871 struct vfswrap_get_dos_attributes_state
);
1873 DATA_BLOB blob
= {0};
1875 char *tofree
= NULL
;
1876 char pathbuf
[PATH_MAX
+1];
1878 struct smb_filename smb_fname
;
1882 xattr_size
= SMB_VFS_GETXATTRAT_RECV(subreq
,
1886 TALLOC_FREE(subreq
);
1887 if (xattr_size
== -1) {
1888 status
= map_nt_error_from_unix(state
->aio_state
.error
);
1890 if (state
->as_root
) {
1891 tevent_req_nterror(req
, status
);
1894 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1895 tevent_req_nterror(req
, status
);
1899 state
->as_root
= true;
1902 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1906 SAMBA_XATTR_DOS_ATTRIB
,
1909 if (tevent_req_nomem(subreq
, req
)) {
1912 tevent_req_set_callback(subreq
,
1913 vfswrap_get_dos_attributes_getxattr_done
,
1918 blob
.length
= xattr_size
;
1920 status
= parse_dos_attribute_blob(state
->smb_fname
,
1923 if (!NT_STATUS_IS_OK(status
)) {
1924 tevent_req_nterror(req
, status
);
1928 pathlen
= full_path_tos(state
->dir_fsp
->fsp_name
->base_name
,
1929 state
->smb_fname
->base_name
,
1934 if (pathlen
== -1) {
1935 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1939 smb_fname
= (struct smb_filename
) {
1941 .st
= state
->smb_fname
->st
,
1942 .flags
= state
->smb_fname
->flags
,
1943 .twrp
= state
->smb_fname
->twrp
,
1946 offline
= vfswrap_is_offline(state
->conn
, &smb_fname
);
1948 state
->dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1950 TALLOC_FREE(tofree
);
1952 tevent_req_done(req
);
1956 static NTSTATUS
vfswrap_get_dos_attributes_recv(struct tevent_req
*req
,
1957 struct vfs_aio_state
*aio_state
,
1960 struct vfswrap_get_dos_attributes_state
*state
=
1961 tevent_req_data(req
,
1962 struct vfswrap_get_dos_attributes_state
);
1965 if (tevent_req_is_nterror(req
, &status
)) {
1966 tevent_req_received(req
);
1970 *aio_state
= state
->aio_state
;
1971 *dosmode
= state
->dosmode
;
1972 tevent_req_received(req
);
1973 return NT_STATUS_OK
;
1976 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
1977 struct files_struct
*fsp
,
1982 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
1984 offline
= vfswrap_is_offline(handle
->conn
, fsp
->fsp_name
);
1986 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1989 return fget_ea_dos_attribute(fsp
, dosmode
);
1992 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
1993 struct files_struct
*fsp
,
1996 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
1998 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
2001 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
2003 struct vfswrap_offload_read_state
{
2007 static struct tevent_req
*vfswrap_offload_read_send(
2008 TALLOC_CTX
*mem_ctx
,
2009 struct tevent_context
*ev
,
2010 struct vfs_handle_struct
*handle
,
2011 struct files_struct
*fsp
,
2017 struct tevent_req
*req
= NULL
;
2018 struct vfswrap_offload_read_state
*state
= NULL
;
2021 req
= tevent_req_create(mem_ctx
, &state
,
2022 struct vfswrap_offload_read_state
);
2027 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
2028 &vfswrap_offload_ctx
);
2029 if (tevent_req_nterror(req
, status
)) {
2030 return tevent_req_post(req
, ev
);
2033 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
) {
2034 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
2035 return tevent_req_post(req
, ev
);
2038 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
2040 if (tevent_req_nterror(req
, status
)) {
2041 return tevent_req_post(req
, ev
);
2044 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
2046 if (tevent_req_nterror(req
, status
)) {
2047 return tevent_req_post(req
, ev
);
2050 tevent_req_done(req
);
2051 return tevent_req_post(req
, ev
);
2054 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
2055 struct vfs_handle_struct
*handle
,
2056 TALLOC_CTX
*mem_ctx
,
2061 struct vfswrap_offload_read_state
*state
= tevent_req_data(
2062 req
, struct vfswrap_offload_read_state
);
2065 if (tevent_req_is_nterror(req
, &status
)) {
2066 tevent_req_received(req
);
2072 token
->length
= state
->token
.length
;
2073 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
2075 tevent_req_received(req
);
2076 return NT_STATUS_OK
;
2079 struct vfswrap_offload_write_state
{
2081 bool read_lck_locked
;
2082 bool write_lck_locked
;
2084 struct tevent_context
*src_ev
;
2085 struct files_struct
*src_fsp
;
2087 struct tevent_context
*dst_ev
;
2088 struct files_struct
*dst_fsp
;
2093 size_t next_io_size
;
2096 static void vfswrap_offload_write_cleanup(struct tevent_req
*req
,
2097 enum tevent_req_state req_state
)
2099 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2100 req
, struct vfswrap_offload_write_state
);
2103 if (state
->dst_fsp
== NULL
) {
2107 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2109 state
->dst_fsp
= NULL
;
2112 static NTSTATUS
vfswrap_offload_copy_file_range(struct tevent_req
*req
);
2113 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
2115 static struct tevent_req
*vfswrap_offload_write_send(
2116 struct vfs_handle_struct
*handle
,
2117 TALLOC_CTX
*mem_ctx
,
2118 struct tevent_context
*ev
,
2121 off_t transfer_offset
,
2122 struct files_struct
*dest_fsp
,
2126 struct tevent_req
*req
;
2127 struct vfswrap_offload_write_state
*state
= NULL
;
2128 /* off_t is signed! */
2129 off_t max_offset
= INT64_MAX
- to_copy
;
2130 size_t num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
2131 files_struct
*src_fsp
= NULL
;
2135 req
= tevent_req_create(mem_ctx
, &state
,
2136 struct vfswrap_offload_write_state
);
2141 *state
= (struct vfswrap_offload_write_state
) {
2143 .src_off
= transfer_offset
,
2145 .dst_fsp
= dest_fsp
,
2146 .dst_off
= dest_off
,
2148 .remaining
= to_copy
,
2151 tevent_req_set_cleanup_fn(req
, vfswrap_offload_write_cleanup
);
2154 case FSCTL_SRV_COPYCHUNK
:
2155 case FSCTL_SRV_COPYCHUNK_WRITE
:
2158 case FSCTL_OFFLOAD_WRITE
:
2159 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2160 return tevent_req_post(req
, ev
);
2162 case FSCTL_DUP_EXTENTS_TO_FILE
:
2163 DBG_DEBUG("COW clones not supported by vfs_default\n");
2164 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2165 return tevent_req_post(req
, ev
);
2168 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2169 return tevent_req_post(req
, ev
);
2173 * From here on we assume a copy-chunk fsctl
2177 tevent_req_done(req
);
2178 return tevent_req_post(req
, ev
);
2181 if (state
->src_off
> max_offset
) {
2183 * Protect integer checks below.
2185 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2186 return tevent_req_post(req
, ev
);
2188 if (state
->src_off
< 0) {
2190 * Protect integer checks below.
2192 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2193 return tevent_req_post(req
, ev
);
2195 if (state
->dst_off
> max_offset
) {
2197 * Protect integer checks below.
2199 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2200 return tevent_req_post(req
, ev
);
2202 if (state
->dst_off
< 0) {
2204 * Protect integer checks below.
2206 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2207 return tevent_req_post(req
, ev
);
2210 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
2212 if (tevent_req_nterror(req
, status
)) {
2213 return tevent_req_post(req
, ev
);
2216 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
2218 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
2219 if (!NT_STATUS_IS_OK(status
)) {
2220 tevent_req_nterror(req
, status
);
2221 return tevent_req_post(req
, ev
);
2224 ok
= change_to_user_and_service_by_fsp(src_fsp
);
2226 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2227 return tevent_req_post(req
, ev
);
2230 state
->src_ev
= src_fsp
->conn
->sconn
->ev_ctx
;
2231 state
->src_fsp
= src_fsp
;
2233 status
= vfs_stat_fsp(src_fsp
);
2234 if (tevent_req_nterror(req
, status
)) {
2235 return tevent_req_post(req
, ev
);
2238 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ to_copy
) {
2240 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2241 * If the SourceOffset or SourceOffset + Length extends beyond
2242 * the end of file, the server SHOULD<240> treat this as a
2243 * STATUS_END_OF_FILE error.
2245 * <240> Section 3.3.5.15.6: Windows servers will return
2246 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2248 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
2249 return tevent_req_post(req
, ev
);
2252 status
= vfswrap_offload_copy_file_range(req
);
2253 if (NT_STATUS_IS_OK(status
)) {
2254 tevent_req_done(req
);
2255 return tevent_req_post(req
, ev
);
2257 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
2258 tevent_req_nterror(req
, status
);
2259 return tevent_req_post(req
, ev
);
2262 state
->buf
= talloc_array(state
, uint8_t, num
);
2263 if (tevent_req_nomem(state
->buf
, req
)) {
2264 return tevent_req_post(req
, ev
);
2267 status
= vfswrap_offload_write_loop(req
);
2268 if (!NT_STATUS_IS_OK(status
)) {
2269 tevent_req_nterror(req
, status
);
2270 return tevent_req_post(req
, ev
);
2276 static NTSTATUS
vfswrap_offload_copy_file_range(struct tevent_req
*req
)
2278 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2279 req
, struct vfswrap_offload_write_state
);
2280 struct lock_struct lck
;
2285 static bool try_copy_file_range
= true;
2287 if (!try_copy_file_range
) {
2288 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2291 same_file
= file_id_equal(&state
->src_fsp
->file_id
,
2292 &state
->dst_fsp
->file_id
);
2294 sys_io_ranges_overlap(state
->remaining
,
2299 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2302 if (fsp_is_alternate_stream(state
->src_fsp
) ||
2303 fsp_is_alternate_stream(state
->dst_fsp
))
2305 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2308 init_strict_lock_struct(state
->src_fsp
,
2309 state
->src_fsp
->op
->global
->open_persistent_id
,
2313 lp_posix_cifsu_locktype(state
->src_fsp
),
2316 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2320 return NT_STATUS_FILE_LOCK_CONFLICT
;
2323 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2325 return NT_STATUS_INTERNAL_ERROR
;
2328 init_strict_lock_struct(state
->dst_fsp
,
2329 state
->dst_fsp
->op
->global
->open_persistent_id
,
2333 lp_posix_cifsu_locktype(state
->dst_fsp
),
2336 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2340 return NT_STATUS_FILE_LOCK_CONFLICT
;
2343 while (state
->remaining
> 0) {
2344 nwritten
= copy_file_range(fsp_get_io_fd(state
->src_fsp
),
2346 fsp_get_io_fd(state
->dst_fsp
),
2350 if (nwritten
== -1) {
2351 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2352 "n [%jd] failed: %s\n",
2353 fsp_str_dbg(state
->src_fsp
),
2354 (intmax_t)state
->src_off
,
2355 fsp_str_dbg(state
->dst_fsp
),
2356 (intmax_t)state
->dst_off
,
2357 (intmax_t)state
->remaining
,
2362 try_copy_file_range
= false;
2363 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2366 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2369 status
= map_nt_error_from_unix(errno
);
2370 if (NT_STATUS_EQUAL(
2372 NT_STATUS_MORE_PROCESSING_REQUIRED
))
2374 /* Avoid triggering the fallback */
2375 status
= NT_STATUS_INTERNAL_ERROR
;
2382 if (state
->remaining
< nwritten
) {
2383 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2384 "n [%jd] remaining [%jd]\n",
2385 fsp_str_dbg(state
->src_fsp
),
2386 fsp_str_dbg(state
->dst_fsp
),
2388 (intmax_t)state
->remaining
);
2389 return NT_STATUS_INTERNAL_ERROR
;
2392 if (nwritten
== 0) {
2395 state
->copied
+= nwritten
;
2396 state
->remaining
-= nwritten
;
2400 * Tell the req cleanup function there's no need to call
2401 * change_to_user_and_service_by_fsp() on the dst handle.
2403 state
->dst_fsp
= NULL
;
2404 return NT_STATUS_OK
;
2407 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
2409 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
2411 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2412 req
, struct vfswrap_offload_write_state
);
2413 struct tevent_req
*subreq
= NULL
;
2414 struct lock_struct read_lck
;
2418 * This is called under the context of state->src_fsp.
2421 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
2423 init_strict_lock_struct(state
->src_fsp
,
2424 state
->src_fsp
->op
->global
->open_persistent_id
,
2426 state
->next_io_size
,
2428 lp_posix_cifsu_locktype(state
->src_fsp
),
2431 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2435 return NT_STATUS_FILE_LOCK_CONFLICT
;
2438 subreq
= SMB_VFS_PREAD_SEND(state
,
2442 state
->next_io_size
,
2444 if (subreq
== NULL
) {
2445 return NT_STATUS_NO_MEMORY
;
2447 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
2449 return NT_STATUS_OK
;
2452 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
2454 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
2456 struct tevent_req
*req
= tevent_req_callback_data(
2457 subreq
, struct tevent_req
);
2458 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2459 req
, struct vfswrap_offload_write_state
);
2460 struct vfs_aio_state aio_state
;
2461 struct lock_struct write_lck
;
2465 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
2466 TALLOC_FREE(subreq
);
2468 DBG_ERR("read failed: %s\n", strerror(aio_state
.error
));
2469 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2472 if (nread
!= state
->next_io_size
) {
2473 DBG_ERR("Short read, only %zd of %zu\n",
2474 nread
, state
->next_io_size
);
2475 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2479 state
->src_off
+= nread
;
2481 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2483 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2487 init_strict_lock_struct(state
->dst_fsp
,
2488 state
->dst_fsp
->op
->global
->open_persistent_id
,
2490 state
->next_io_size
,
2492 lp_posix_cifsu_locktype(state
->dst_fsp
),
2495 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2499 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
2503 subreq
= SMB_VFS_PWRITE_SEND(state
,
2507 state
->next_io_size
,
2509 if (subreq
== NULL
) {
2510 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2513 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
2516 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
2518 struct tevent_req
*req
= tevent_req_callback_data(
2519 subreq
, struct tevent_req
);
2520 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2521 req
, struct vfswrap_offload_write_state
);
2522 struct vfs_aio_state aio_state
;
2527 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
2528 TALLOC_FREE(subreq
);
2529 if (nwritten
== -1) {
2530 DBG_ERR("write failed: %s\n", strerror(aio_state
.error
));
2531 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2534 if (nwritten
!= state
->next_io_size
) {
2535 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
2536 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2540 state
->dst_off
+= nwritten
;
2542 if (state
->remaining
< nwritten
) {
2543 /* Paranoia check */
2544 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2547 state
->copied
+= nwritten
;
2548 state
->remaining
-= nwritten
;
2549 if (state
->remaining
== 0) {
2550 tevent_req_done(req
);
2554 ok
= change_to_user_and_service_by_fsp(state
->src_fsp
);
2556 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2560 status
= vfswrap_offload_write_loop(req
);
2561 if (!NT_STATUS_IS_OK(status
)) {
2562 tevent_req_nterror(req
, status
);
2569 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
2570 struct tevent_req
*req
,
2573 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2574 req
, struct vfswrap_offload_write_state
);
2577 if (tevent_req_is_nterror(req
, &status
)) {
2578 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
2580 tevent_req_received(req
);
2584 *copied
= state
->copied
;
2585 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2586 tevent_req_received(req
);
2588 return NT_STATUS_OK
;
2591 static NTSTATUS
vfswrap_fget_compression(struct vfs_handle_struct
*handle
,
2592 TALLOC_CTX
*mem_ctx
,
2593 struct files_struct
*fsp
,
2594 uint16_t *_compression_fmt
)
2596 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2599 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2600 TALLOC_CTX
*mem_ctx
,
2601 struct files_struct
*fsp
,
2602 uint16_t compression_fmt
)
2604 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2607 /********************************************************************
2608 Given a stat buffer return the allocated size on disk, taking into
2609 account sparse files.
2610 ********************************************************************/
2611 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2612 struct files_struct
*fsp
,
2613 const SMB_STRUCT_STAT
*sbuf
)
2617 START_PROFILE(syscall_get_alloc_size
);
2619 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2624 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2625 /* The type of st_blocksize is blkcnt_t which *MUST* be
2626 signed (according to POSIX) and can be less than 64-bits.
2627 Ensure when we're converting to 64 bits wide we don't
2629 #if defined(SIZEOF_BLKCNT_T_8)
2630 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2631 #elif defined(SIZEOF_BLKCNT_T_4)
2633 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2634 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2637 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2641 * Some file systems do not allocate a block for very
2642 * small files. But for non-empty file should report a
2646 uint64_t filesize
= get_file_size_stat(sbuf
);
2648 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2652 result
= get_file_size_stat(sbuf
);
2655 if (fsp
&& fsp
->initial_allocation_size
)
2656 result
= MAX(result
,fsp
->initial_allocation_size
);
2658 result
= smb_roundup(handle
->conn
, result
);
2661 END_PROFILE(syscall_get_alloc_size
);
2665 static int vfswrap_unlinkat(vfs_handle_struct
*handle
,
2666 struct files_struct
*dirfsp
,
2667 const struct smb_filename
*smb_fname
,
2672 START_PROFILE(syscall_unlinkat
);
2674 SMB_ASSERT(!is_named_stream(smb_fname
));
2676 result
= unlinkat(fsp_get_pathref_fd(dirfsp
),
2677 smb_fname
->base_name
,
2680 END_PROFILE(syscall_unlinkat
);
2684 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2688 START_PROFILE(syscall_fchmod
);
2690 if (!fsp
->fsp_flags
.is_pathref
) {
2691 result
= fchmod(fsp_get_io_fd(fsp
), mode
);
2692 END_PROFILE(syscall_fchmod
);
2696 if (fsp
->fsp_flags
.have_proc_fds
) {
2697 int fd
= fsp_get_pathref_fd(fsp
);
2698 struct sys_proc_fd_path_buf buf
;
2700 result
= chmod(sys_proc_fd_path(fd
, &buf
), mode
);
2702 END_PROFILE(syscall_fchmod
);
2707 * This is no longer a handle based call.
2709 result
= chmod(fsp
->fsp_name
->base_name
, mode
);
2711 END_PROFILE(syscall_fchmod
);
2715 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2720 START_PROFILE(syscall_fchown
);
2721 if (!fsp
->fsp_flags
.is_pathref
) {
2722 result
= fchown(fsp_get_io_fd(fsp
), uid
, gid
);
2723 END_PROFILE(syscall_fchown
);
2727 if (fsp
->fsp_flags
.have_proc_fds
) {
2728 int fd
= fsp_get_pathref_fd(fsp
);
2729 struct sys_proc_fd_path_buf buf
;
2731 result
= chown(sys_proc_fd_path(fd
, &buf
), uid
, gid
);
2733 END_PROFILE(syscall_fchown
);
2738 * This is no longer a handle based call.
2740 result
= chown(fsp
->fsp_name
->base_name
, uid
, gid
);
2741 END_PROFILE(syscall_fchown
);
2749 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2750 const struct smb_filename
*smb_fname
,
2756 START_PROFILE(syscall_lchown
);
2757 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2758 END_PROFILE(syscall_lchown
);
2762 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2763 const struct smb_filename
*smb_fname
)
2767 START_PROFILE(syscall_chdir
);
2768 result
= chdir(smb_fname
->base_name
);
2769 END_PROFILE(syscall_chdir
);
2773 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2777 struct smb_filename
*smb_fname
= NULL
;
2779 START_PROFILE(syscall_getwd
);
2780 result
= sys_getwd();
2781 END_PROFILE(syscall_getwd
);
2783 if (result
== NULL
) {
2786 smb_fname
= synthetic_smb_fname(ctx
,
2793 * sys_getwd() *always* returns malloced memory.
2794 * We must free here to avoid leaks:
2795 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2801 /*********************************************************************
2802 nsec timestamp resolution call. Convert down to whatever the underlying
2803 system will support.
2804 **********************************************************************/
2806 static int vfswrap_fntimes(vfs_handle_struct
*handle
,
2808 struct smb_file_time
*ft
)
2811 struct timespec ts
[2];
2812 struct timespec
*times
= NULL
;
2814 START_PROFILE(syscall_fntimes
);
2816 if (fsp_is_alternate_stream(fsp
)) {
2822 if (is_omit_timespec(&ft
->atime
)) {
2823 ft
->atime
= fsp
->fsp_name
->st
.st_ex_atime
;
2826 if (is_omit_timespec(&ft
->mtime
)) {
2827 ft
->mtime
= fsp
->fsp_name
->st
.st_ex_mtime
;
2830 if (!is_omit_timespec(&ft
->create_time
)) {
2831 set_create_timespec_ea(fsp
,
2835 if ((timespec_compare(&ft
->atime
,
2836 &fsp
->fsp_name
->st
.st_ex_atime
) == 0) &&
2837 (timespec_compare(&ft
->mtime
,
2838 &fsp
->fsp_name
->st
.st_ex_mtime
) == 0)) {
2850 if (!fsp
->fsp_flags
.is_pathref
) {
2851 result
= futimens(fsp_get_io_fd(fsp
), times
);
2855 if (fsp
->fsp_flags
.have_proc_fds
) {
2856 int fd
= fsp_get_pathref_fd(fsp
);
2857 struct sys_proc_fd_path_buf buf
;
2859 result
= utimensat(AT_FDCWD
,
2860 sys_proc_fd_path(fd
, &buf
),
2868 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2869 * path translation mechanism. Fallback to path based call.
2871 result
= utimensat(AT_FDCWD
, fsp
->fsp_name
->base_name
, times
, 0);
2874 END_PROFILE(syscall_fntimes
);
2880 /*********************************************************************
2881 A version of ftruncate that will write the space on disk if strict
2883 **********************************************************************/
2885 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2887 off_t space_to_write
;
2888 uint64_t space_avail
;
2889 uint64_t bsize
,dfree
,dsize
;
2892 SMB_STRUCT_STAT
*pst
;
2895 ok
= vfs_valid_pwrite_range(len
, 0);
2901 status
= vfs_stat_fsp(fsp
);
2902 if (!NT_STATUS_IS_OK(status
)) {
2905 pst
= &fsp
->fsp_name
->st
;
2908 if (S_ISFIFO(pst
->st_ex_mode
))
2912 if (pst
->st_ex_size
== len
)
2915 /* Shrink - just ftruncate. */
2916 if (pst
->st_ex_size
> len
)
2917 return ftruncate(fsp_get_io_fd(fsp
), len
);
2919 space_to_write
= len
- pst
->st_ex_size
;
2921 /* for allocation try fallocate first. This can fail on some
2922 platforms e.g. when the filesystem doesn't support it and no
2923 emulation is being done by the libc (like on AIX with JFS1). In that
2924 case we do our own emulation. fallocate implementations can
2925 return ENOTSUP or EINVAL in cases like that. */
2926 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2927 if (ret
== -1 && errno
== ENOSPC
) {
2933 DBG_DEBUG("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2934 "error %d. Falling back to slow manual allocation\n", errno
);
2936 /* available disk space is enough or not? */
2938 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2939 /* space_avail is 1k blocks */
2940 if (space_avail
== (uint64_t)-1 ||
2941 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2946 /* Write out the real space on disk. */
2947 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2955 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2958 SMB_STRUCT_STAT
*pst
;
2962 START_PROFILE(syscall_ftruncate
);
2964 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->fsp_flags
.is_sparse
) {
2965 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2966 END_PROFILE(syscall_ftruncate
);
2970 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2971 ftruncate if the system supports it. Then I discovered that
2972 you can have some filesystems that support ftruncate
2973 expansion and some that don't! On Linux fat can't do
2974 ftruncate extend but ext2 can. */
2976 result
= ftruncate(fsp_get_io_fd(fsp
), len
);
2978 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2979 extend a file with ftruncate. Provide alternate implementation
2982 /* Do an fstat to see if the file is longer than the requested
2983 size in which case the ftruncate above should have
2984 succeeded or shorter, in which case seek to len - 1 and
2985 write 1 byte of zero */
2986 status
= vfs_stat_fsp(fsp
);
2987 if (!NT_STATUS_IS_OK(status
)) {
2991 /* We need to update the files_struct after successful ftruncate */
2996 pst
= &fsp
->fsp_name
->st
;
2999 if (S_ISFIFO(pst
->st_ex_mode
)) {
3005 if (pst
->st_ex_size
== len
) {
3010 if (pst
->st_ex_size
> len
) {
3011 /* the ftruncate should have worked */
3015 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
3023 END_PROFILE(syscall_ftruncate
);
3027 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
3035 START_PROFILE(syscall_fallocate
);
3037 result
= sys_posix_fallocate(fsp_get_io_fd(fsp
), offset
, len
);
3039 * posix_fallocate returns 0 on success, errno on error
3040 * and doesn't set errno. Make it behave like fallocate()
3041 * which returns -1, and sets errno on failure.
3048 /* sys_fallocate handles filtering of unsupported mode flags */
3049 result
= sys_fallocate(fsp_get_io_fd(fsp
), mode
, offset
, len
);
3051 END_PROFILE(syscall_fallocate
);
3055 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
3059 START_PROFILE(syscall_fcntl_lock
);
3061 if (fsp
->fsp_flags
.use_ofd_locks
) {
3062 op
= map_process_lock_to_ofd_lock(op
);
3065 result
= fcntl_lock(fsp_get_io_fd(fsp
), op
, offset
, count
, type
);
3066 END_PROFILE(syscall_fcntl_lock
);
3070 static int vfswrap_filesystem_sharemode(vfs_handle_struct
*handle
,
3072 uint32_t share_access
,
3073 uint32_t access_mask
)
3079 static int vfswrap_fcntl(vfs_handle_struct
*handle
, files_struct
*fsp
, int cmd
,
3083 va_list dup_cmd_arg
;
3087 START_PROFILE(syscall_fcntl
);
3089 va_copy(dup_cmd_arg
, cmd_arg
);
3095 #if defined(HAVE_OFD_LOCKS)
3100 #if defined(HAVE_F_OWNER_EX)
3104 #if defined(HAVE_RW_HINTS)
3107 case F_GET_FILE_RW_HINT
:
3108 case F_SET_FILE_RW_HINT
:
3110 argp
= va_arg(dup_cmd_arg
, void *);
3111 result
= sys_fcntl_ptr(fsp_get_io_fd(fsp
), cmd
, argp
);
3114 val
= va_arg(dup_cmd_arg
, int);
3115 result
= sys_fcntl_int(fsp_get_io_fd(fsp
), cmd
, val
);
3118 va_end(dup_cmd_arg
);
3120 END_PROFILE(syscall_fcntl
);
3124 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
3129 START_PROFILE(syscall_fcntl_getlock
);
3131 if (fsp
->fsp_flags
.use_ofd_locks
) {
3132 op
= map_process_lock_to_ofd_lock(op
);
3135 result
= fcntl_getlock(fsp_get_io_fd(fsp
), op
, poffset
, pcount
, ptype
, ppid
);
3136 END_PROFILE(syscall_fcntl_getlock
);
3140 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
3145 START_PROFILE(syscall_linux_setlease
);
3147 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3149 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3150 result
= linux_setlease(fsp_get_io_fd(fsp
), leasetype
);
3154 END_PROFILE(syscall_linux_setlease
);
3158 static int vfswrap_symlinkat(vfs_handle_struct
*handle
,
3159 const struct smb_filename
*link_target
,
3160 struct files_struct
*dirfsp
,
3161 const struct smb_filename
*new_smb_fname
)
3165 START_PROFILE(syscall_symlinkat
);
3167 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3169 result
= symlinkat(link_target
->base_name
,
3170 fsp_get_pathref_fd(dirfsp
),
3171 new_smb_fname
->base_name
);
3172 END_PROFILE(syscall_symlinkat
);
3176 static int vfswrap_readlinkat(vfs_handle_struct
*handle
,
3177 const struct files_struct
*dirfsp
,
3178 const struct smb_filename
*smb_fname
,
3184 START_PROFILE(syscall_readlinkat
);
3186 SMB_ASSERT(!is_named_stream(smb_fname
));
3188 result
= readlinkat(fsp_get_pathref_fd(dirfsp
),
3189 smb_fname
->base_name
,
3193 END_PROFILE(syscall_readlinkat
);
3197 static int vfswrap_linkat(vfs_handle_struct
*handle
,
3198 files_struct
*srcfsp
,
3199 const struct smb_filename
*old_smb_fname
,
3200 files_struct
*dstfsp
,
3201 const struct smb_filename
*new_smb_fname
,
3206 START_PROFILE(syscall_linkat
);
3208 SMB_ASSERT(!is_named_stream(old_smb_fname
));
3209 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3211 result
= linkat(fsp_get_pathref_fd(srcfsp
),
3212 old_smb_fname
->base_name
,
3213 fsp_get_pathref_fd(dstfsp
),
3214 new_smb_fname
->base_name
,
3217 END_PROFILE(syscall_linkat
);
3221 static int vfswrap_mknodat(vfs_handle_struct
*handle
,
3222 files_struct
*dirfsp
,
3223 const struct smb_filename
*smb_fname
,
3229 START_PROFILE(syscall_mknodat
);
3231 SMB_ASSERT(!is_named_stream(smb_fname
));
3233 result
= sys_mknodat(fsp_get_pathref_fd(dirfsp
),
3234 smb_fname
->base_name
,
3238 END_PROFILE(syscall_mknodat
);
3242 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
3244 const struct smb_filename
*smb_fname
)
3247 struct smb_filename
*result_fname
= NULL
;
3249 START_PROFILE(syscall_realpath
);
3250 result
= sys_realpath(smb_fname
->base_name
);
3251 END_PROFILE(syscall_realpath
);
3253 result_fname
= synthetic_smb_fname(ctx
,
3261 return result_fname
;
3264 static int vfswrap_fchflags(vfs_handle_struct
*handle
,
3265 struct files_struct
*fsp
,
3268 #ifdef HAVE_FCHFLAGS
3269 int fd
= fsp_get_pathref_fd(fsp
);
3271 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3273 if (!fsp
->fsp_flags
.is_pathref
) {
3274 return fchflags(fd
, flags
);
3277 if (fsp
->fsp_flags
.have_proc_fds
) {
3278 struct sys_proc_fd_path_buf buf
;
3280 return chflags(sys_proc_fd_path(fd
, &buf
), flags
);
3284 * This is no longer a handle based call.
3286 return chflags(fsp
->fsp_name
->base_name
, flags
);
3293 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
3294 const SMB_STRUCT_STAT
*sbuf
)
3298 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3302 key
.devid
= sbuf
->st_ex_dev
;
3303 key
.inode
= sbuf
->st_ex_ino
;
3304 /* key.extid is unused by default. */
3309 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct
*handle
,
3310 const SMB_STRUCT_STAT
*psbuf
)
3314 if (handle
->conn
->base_share_dev
== psbuf
->st_ex_dev
) {
3315 return (uint64_t)psbuf
->st_ex_ino
;
3319 file_id
= ((psbuf
->st_ex_ino
) & UINT32_MAX
);
3322 file_id
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32;
3327 static NTSTATUS
vfswrap_fstreaminfo(vfs_handle_struct
*handle
,
3328 struct files_struct
*fsp
,
3329 TALLOC_CTX
*mem_ctx
,
3330 unsigned int *pnum_streams
,
3331 struct stream_struct
**pstreams
)
3333 struct stream_struct
*tmp_streams
= NULL
;
3334 unsigned int num_streams
= *pnum_streams
;
3335 struct stream_struct
*streams
= *pstreams
;
3338 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3340 if (fsp
->fsp_flags
.is_directory
) {
3342 * No default streams on directories
3346 status
= vfs_stat_fsp(fsp
);
3347 if (!NT_STATUS_IS_OK(status
)) {
3351 if (num_streams
+ 1 < 1) {
3353 return NT_STATUS_INVALID_PARAMETER
;
3356 tmp_streams
= talloc_realloc(mem_ctx
,
3358 struct stream_struct
,
3360 if (tmp_streams
== NULL
) {
3361 return NT_STATUS_NO_MEMORY
;
3363 tmp_streams
[num_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
3364 if (tmp_streams
[num_streams
].name
== NULL
) {
3365 return NT_STATUS_NO_MEMORY
;
3367 tmp_streams
[num_streams
].size
= fsp
->fsp_name
->st
.st_ex_size
;
3368 tmp_streams
[num_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(
3371 &fsp
->fsp_name
->st
);
3374 *pnum_streams
= num_streams
;
3375 *pstreams
= tmp_streams
;
3377 return NT_STATUS_OK
;
3380 static NTSTATUS
vfswrap_get_real_filename_at(
3381 struct vfs_handle_struct
*handle
,
3382 struct files_struct
*dirfsp
,
3384 TALLOC_CTX
*mem_ctx
,
3388 * Don't fall back to get_real_filename so callers can differentiate
3389 * between a full directory scan and an actual case-insensitive stat.
3391 return NT_STATUS_NOT_SUPPORTED
;
3394 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
3395 const struct files_struct
*dirfsp
,
3396 const struct smb_filename
*smb_fname
)
3398 return handle
->conn
->connectpath
;
3401 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
3402 struct byte_range_lock
*br_lck
,
3403 struct lock_struct
*plock
)
3405 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3407 /* Note: blr is not used in the default implementation. */
3408 return brl_lock_windows_default(br_lck
, plock
);
3411 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
3412 struct byte_range_lock
*br_lck
,
3413 const struct lock_struct
*plock
)
3415 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3417 return brl_unlock_windows_default(br_lck
, plock
);
3420 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
3422 struct lock_struct
*plock
)
3424 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
3425 plock
->lock_type
== WRITE_LOCK
);
3427 return strict_lock_check_default(fsp
, plock
);
3430 /* NT ACL operations. */
3432 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
3434 uint32_t security_info
,
3435 TALLOC_CTX
*mem_ctx
,
3436 struct security_descriptor
**ppdesc
)
3440 START_PROFILE(fget_nt_acl
);
3442 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3444 result
= posix_fget_nt_acl(fsp
, security_info
,
3446 END_PROFILE(fget_nt_acl
);
3450 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
3454 START_PROFILE(fset_nt_acl
);
3456 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3458 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
3459 END_PROFILE(fset_nt_acl
);
3463 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
3464 struct smb_filename
*file
,
3465 struct security_acl
*sacl
,
3466 uint32_t access_requested
,
3467 uint32_t access_denied
)
3469 return NT_STATUS_OK
; /* Nothing to do here ... */
3472 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
3474 SMB_ACL_TYPE_T type
,
3475 TALLOC_CTX
*mem_ctx
)
3477 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3479 return sys_acl_get_fd(handle
, fsp
, type
, mem_ctx
);
3482 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
,
3484 SMB_ACL_TYPE_T type
,
3487 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3489 return sys_acl_set_fd(handle
, fsp
, type
, theacl
);
3492 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct
*handle
,
3495 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3497 return sys_acl_delete_def_fd(handle
, fsp
);
3500 /****************************************************************
3501 Extended attribute operations.
3502 *****************************************************************/
3504 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
,
3505 struct files_struct
*fsp
,
3510 int fd
= fsp_get_pathref_fd(fsp
);
3512 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3514 if (!fsp
->fsp_flags
.is_pathref
) {
3515 return fgetxattr(fd
, name
, value
, size
);
3518 if (fsp
->fsp_flags
.have_proc_fds
) {
3519 struct sys_proc_fd_path_buf buf
;
3521 return getxattr(sys_proc_fd_path(fd
, &buf
), name
, value
, size
);
3525 * This is no longer a handle based call.
3527 return getxattr(fsp
->fsp_name
->base_name
, name
, value
, size
);
3530 struct vfswrap_getxattrat_state
{
3531 struct tevent_context
*ev
;
3532 struct vfs_handle_struct
*handle
;
3533 files_struct
*dir_fsp
;
3534 const struct smb_filename
*smb_fname
;
3537 * The following variables are talloced off "state" which is protected
3538 * by a destructor and thus are guaranteed to be safe to be used in the
3539 * job function in the worker thread.
3542 const char *xattr_name
;
3543 uint8_t *xattr_value
;
3544 struct security_unix_token
*token
;
3547 struct vfs_aio_state vfs_aio_state
;
3548 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
3551 static int vfswrap_getxattrat_state_destructor(
3552 struct vfswrap_getxattrat_state
*state
)
3557 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
);
3558 static void vfswrap_getxattrat_do_async(void *private_data
);
3559 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
);
3561 static struct tevent_req
*vfswrap_getxattrat_send(
3562 TALLOC_CTX
*mem_ctx
,
3563 struct tevent_context
*ev
,
3564 struct vfs_handle_struct
*handle
,
3565 files_struct
*dir_fsp
,
3566 const struct smb_filename
*smb_fname
,
3567 const char *xattr_name
,
3570 struct tevent_req
*req
= NULL
;
3571 struct tevent_req
*subreq
= NULL
;
3572 struct vfswrap_getxattrat_state
*state
= NULL
;
3573 size_t max_threads
= 0;
3574 bool have_per_thread_cwd
= false;
3575 bool have_per_thread_creds
= false;
3576 bool do_async
= false;
3578 SMB_ASSERT(!is_named_stream(smb_fname
));
3580 req
= tevent_req_create(mem_ctx
, &state
,
3581 struct vfswrap_getxattrat_state
);
3585 *state
= (struct vfswrap_getxattrat_state
) {
3589 .smb_fname
= smb_fname
,
3592 max_threads
= pthreadpool_tevent_max_threads(dir_fsp
->conn
->sconn
->pool
);
3593 if (max_threads
>= 1) {
3595 * We need a non sync threadpool!
3597 have_per_thread_cwd
= per_thread_cwd_supported();
3599 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3600 have_per_thread_creds
= true;
3602 if (have_per_thread_cwd
&& have_per_thread_creds
) {
3606 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat
, profile_p
,
3607 state
->profile_bytes
, 0);
3609 if (fsp_get_pathref_fd(dir_fsp
) == -1) {
3610 DBG_ERR("Need a valid directory fd\n");
3611 tevent_req_error(req
, EINVAL
);
3612 return tevent_req_post(req
, ev
);
3615 if (alloc_hint
> 0) {
3616 state
->xattr_value
= talloc_zero_array(state
,
3619 if (tevent_req_nomem(state
->xattr_value
, req
)) {
3620 return tevent_req_post(req
, ev
);
3625 vfswrap_getxattrat_do_sync(req
);
3626 return tevent_req_post(req
, ev
);
3630 * Now allocate all parameters from a memory context that won't go away
3631 * no matter what. These parameters will get used in threads and we
3632 * can't reliably cancel threads, so all buffers passed to the threads
3633 * must not be freed before all referencing threads terminate.
3636 state
->name
= talloc_strdup(state
, smb_fname
->base_name
);
3637 if (tevent_req_nomem(state
->name
, req
)) {
3638 return tevent_req_post(req
, ev
);
3641 state
->xattr_name
= talloc_strdup(state
, xattr_name
);
3642 if (tevent_req_nomem(state
->xattr_name
, req
)) {
3643 return tevent_req_post(req
, ev
);
3647 * This is a hot codepath so at first glance one might think we should
3648 * somehow optimize away the token allocation and do a
3649 * talloc_reference() or similar black magic instead. But due to the
3650 * talloc_stackframe pool per SMB2 request this should be a simple copy
3651 * without a malloc in most cases.
3653 if (geteuid() == sec_initial_uid()) {
3654 state
->token
= root_unix_token(state
);
3656 state
->token
= copy_unix_token(
3658 dir_fsp
->conn
->session_info
->unix_token
);
3660 if (tevent_req_nomem(state
->token
, req
)) {
3661 return tevent_req_post(req
, ev
);
3664 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3666 subreq
= pthreadpool_tevent_job_send(
3669 dir_fsp
->conn
->sconn
->pool
,
3670 vfswrap_getxattrat_do_async
,
3672 if (tevent_req_nomem(subreq
, req
)) {
3673 return tevent_req_post(req
, ev
);
3675 tevent_req_set_callback(subreq
, vfswrap_getxattrat_done
, req
);
3677 talloc_set_destructor(state
, vfswrap_getxattrat_state_destructor
);
3682 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
)
3684 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3685 req
, struct vfswrap_getxattrat_state
);
3687 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3688 state
->smb_fname
->fsp
,
3691 talloc_array_length(state
->xattr_value
));
3692 if (state
->xattr_size
== -1) {
3693 tevent_req_error(req
, errno
);
3697 tevent_req_done(req
);
3701 static void vfswrap_getxattrat_do_async(void *private_data
)
3703 struct vfswrap_getxattrat_state
*state
= talloc_get_type_abort(
3704 private_data
, struct vfswrap_getxattrat_state
);
3705 struct timespec start_time
;
3706 struct timespec end_time
;
3709 PROFILE_TIMESTAMP(&start_time
);
3710 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
3713 * Here we simulate a getxattrat()
3714 * call using fchdir();getxattr()
3717 per_thread_cwd_activate();
3719 /* Become the correct credential on this thread. */
3720 ret
= set_thread_credentials(state
->token
->uid
,
3722 (size_t)state
->token
->ngroups
,
3723 state
->token
->groups
);
3725 state
->xattr_size
= -1;
3726 state
->vfs_aio_state
.error
= errno
;
3730 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3731 state
->smb_fname
->fsp
,
3734 talloc_array_length(state
->xattr_value
));
3735 if (state
->xattr_size
== -1) {
3736 state
->vfs_aio_state
.error
= errno
;
3740 PROFILE_TIMESTAMP(&end_time
);
3741 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
3742 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3745 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
)
3747 struct tevent_req
*req
= tevent_req_callback_data(
3748 subreq
, struct tevent_req
);
3749 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3750 req
, struct vfswrap_getxattrat_state
);
3755 * Make sure we run as the user again
3757 ok
= change_to_user_and_service_by_fsp(state
->dir_fsp
);
3760 ret
= pthreadpool_tevent_job_recv(subreq
);
3761 TALLOC_FREE(subreq
);
3762 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
3763 talloc_set_destructor(state
, NULL
);
3765 if (ret
!= EAGAIN
) {
3766 tevent_req_error(req
, ret
);
3770 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3771 * means the lower level pthreadpool failed to create a new
3772 * thread. Fallback to sync processing in that case to allow
3773 * some progress for the client.
3775 vfswrap_getxattrat_do_sync(req
);
3779 if (state
->xattr_size
== -1) {
3780 tevent_req_error(req
, state
->vfs_aio_state
.error
);
3784 if (state
->xattr_value
== NULL
) {
3786 * The caller only wanted the size.
3788 tevent_req_done(req
);
3793 * shrink the buffer to the returned size.
3794 * (can't fail). It means NULL if size is 0.
3796 state
->xattr_value
= talloc_realloc(state
,
3801 tevent_req_done(req
);
3804 static ssize_t
vfswrap_getxattrat_recv(struct tevent_req
*req
,
3805 struct vfs_aio_state
*aio_state
,
3806 TALLOC_CTX
*mem_ctx
,
3807 uint8_t **xattr_value
)
3809 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3810 req
, struct vfswrap_getxattrat_state
);
3813 if (tevent_req_is_unix_error(req
, &aio_state
->error
)) {
3814 tevent_req_received(req
);
3818 *aio_state
= state
->vfs_aio_state
;
3819 xattr_size
= state
->xattr_size
;
3820 if (xattr_value
!= NULL
) {
3821 *xattr_value
= talloc_move(mem_ctx
, &state
->xattr_value
);
3824 tevent_req_received(req
);
3828 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
3830 int fd
= fsp_get_pathref_fd(fsp
);
3832 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3834 if (!fsp
->fsp_flags
.is_pathref
) {
3835 return flistxattr(fd
, list
, size
);
3838 if (fsp
->fsp_flags
.have_proc_fds
) {
3839 struct sys_proc_fd_path_buf buf
;
3841 return listxattr(sys_proc_fd_path(fd
, &buf
), list
, size
);
3845 * This is no longer a handle based call.
3847 return listxattr(fsp
->fsp_name
->base_name
, list
, size
);
3850 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
3852 int fd
= fsp_get_pathref_fd(fsp
);
3854 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3856 if (!fsp
->fsp_flags
.is_pathref
) {
3857 return fremovexattr(fd
, name
);
3860 if (fsp
->fsp_flags
.have_proc_fds
) {
3861 struct sys_proc_fd_path_buf buf
;
3863 return removexattr(sys_proc_fd_path(fd
, &buf
), name
);
3867 * This is no longer a handle based call.
3869 return removexattr(fsp
->fsp_name
->base_name
, name
);
3872 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
3874 int fd
= fsp_get_pathref_fd(fsp
);
3876 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3878 if (!fsp
->fsp_flags
.is_pathref
) {
3879 return fsetxattr(fd
, name
, value
, size
, flags
);
3882 if (fsp
->fsp_flags
.have_proc_fds
) {
3883 struct sys_proc_fd_path_buf buf
;
3885 return setxattr(sys_proc_fd_path(fd
, &buf
),
3893 * This is no longer a handle based call.
3895 return setxattr(fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
3898 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
3903 static bool vfswrap_is_offline(struct connection_struct
*conn
,
3904 const struct smb_filename
*fname
)
3908 bool offline
= false;
3910 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
3914 if (!lp_dmapi_support(SNUM(conn
)) || !dmapi_have_session()) {
3915 #if defined(ENOTSUP)
3921 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
3922 if (!NT_STATUS_IS_OK(status
)) {
3923 errno
= map_errno_from_nt_status(status
);
3927 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
3934 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
3935 struct files_struct
*fsp
,
3936 TALLOC_CTX
*mem_ctx
,
3939 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
3942 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
3943 struct files_struct
*fsp
,
3944 const DATA_BLOB old_cookie
,
3945 TALLOC_CTX
*mem_ctx
,
3946 DATA_BLOB
*new_cookie
)
3948 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
3952 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
3953 struct smb_request
*smb1req
,
3954 struct smbXsrv_open
*op
,
3955 const DATA_BLOB old_cookie
,
3956 TALLOC_CTX
*mem_ctx
,
3957 struct files_struct
**fsp
,
3958 DATA_BLOB
*new_cookie
)
3960 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
3961 old_cookie
, mem_ctx
,
3965 static struct vfs_fn_pointers vfs_default_fns
= {
3966 /* Disk operations */
3968 .connect_fn
= vfswrap_connect
,
3969 .disconnect_fn
= vfswrap_disconnect
,
3970 .disk_free_fn
= vfswrap_disk_free
,
3971 .get_quota_fn
= vfswrap_get_quota
,
3972 .set_quota_fn
= vfswrap_set_quota
,
3973 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
3974 .statvfs_fn
= vfswrap_statvfs
,
3975 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
3976 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
3977 .create_dfs_pathat_fn
= vfswrap_create_dfs_pathat
,
3978 .read_dfs_pathat_fn
= vfswrap_read_dfs_pathat
,
3979 .snap_check_path_fn
= vfswrap_snap_check_path
,
3980 .snap_create_fn
= vfswrap_snap_create
,
3981 .snap_delete_fn
= vfswrap_snap_delete
,
3983 /* Directory operations */
3985 .fdopendir_fn
= vfswrap_fdopendir
,
3986 .readdir_fn
= vfswrap_readdir
,
3987 .freaddir_attr_fn
= vfswrap_freaddir_attr
,
3988 .rewind_dir_fn
= vfswrap_rewinddir
,
3989 .mkdirat_fn
= vfswrap_mkdirat
,
3990 .closedir_fn
= vfswrap_closedir
,
3992 /* File operations */
3994 .openat_fn
= vfswrap_openat
,
3995 .create_file_fn
= vfswrap_create_file
,
3996 .close_fn
= vfswrap_close
,
3997 .pread_fn
= vfswrap_pread
,
3998 .pread_send_fn
= vfswrap_pread_send
,
3999 .pread_recv_fn
= vfswrap_pread_recv
,
4000 .pwrite_fn
= vfswrap_pwrite
,
4001 .pwrite_send_fn
= vfswrap_pwrite_send
,
4002 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
4003 .lseek_fn
= vfswrap_lseek
,
4004 .sendfile_fn
= vfswrap_sendfile
,
4005 .recvfile_fn
= vfswrap_recvfile
,
4006 .renameat_fn
= vfswrap_renameat
,
4007 .fsync_send_fn
= vfswrap_fsync_send
,
4008 .fsync_recv_fn
= vfswrap_fsync_recv
,
4009 .stat_fn
= vfswrap_stat
,
4010 .fstat_fn
= vfswrap_fstat
,
4011 .lstat_fn
= vfswrap_lstat
,
4012 .fstatat_fn
= vfswrap_fstatat
,
4013 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
4014 .unlinkat_fn
= vfswrap_unlinkat
,
4015 .fchmod_fn
= vfswrap_fchmod
,
4016 .fchown_fn
= vfswrap_fchown
,
4017 .lchown_fn
= vfswrap_lchown
,
4018 .chdir_fn
= vfswrap_chdir
,
4019 .getwd_fn
= vfswrap_getwd
,
4020 .fntimes_fn
= vfswrap_fntimes
,
4021 .ftruncate_fn
= vfswrap_ftruncate
,
4022 .fallocate_fn
= vfswrap_fallocate
,
4023 .lock_fn
= vfswrap_lock
,
4024 .filesystem_sharemode_fn
= vfswrap_filesystem_sharemode
,
4025 .fcntl_fn
= vfswrap_fcntl
,
4026 .linux_setlease_fn
= vfswrap_linux_setlease
,
4027 .getlock_fn
= vfswrap_getlock
,
4028 .symlinkat_fn
= vfswrap_symlinkat
,
4029 .readlinkat_fn
= vfswrap_readlinkat
,
4030 .linkat_fn
= vfswrap_linkat
,
4031 .mknodat_fn
= vfswrap_mknodat
,
4032 .realpath_fn
= vfswrap_realpath
,
4033 .fchflags_fn
= vfswrap_fchflags
,
4034 .file_id_create_fn
= vfswrap_file_id_create
,
4035 .fs_file_id_fn
= vfswrap_fs_file_id
,
4036 .fstreaminfo_fn
= vfswrap_fstreaminfo
,
4037 .get_real_filename_at_fn
= vfswrap_get_real_filename_at
,
4038 .connectpath_fn
= vfswrap_connectpath
,
4039 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
4040 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
4041 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
4042 .translate_name_fn
= vfswrap_translate_name
,
4043 .parent_pathname_fn
= vfswrap_parent_pathname
,
4044 .fsctl_fn
= vfswrap_fsctl
,
4045 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
4046 .get_dos_attributes_send_fn
= vfswrap_get_dos_attributes_send
,
4047 .get_dos_attributes_recv_fn
= vfswrap_get_dos_attributes_recv
,
4048 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
4049 .offload_read_send_fn
= vfswrap_offload_read_send
,
4050 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
4051 .offload_write_send_fn
= vfswrap_offload_write_send
,
4052 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
4053 .fget_compression_fn
= vfswrap_fget_compression
,
4054 .set_compression_fn
= vfswrap_set_compression
,
4056 /* NT ACL operations. */
4058 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
4059 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
4060 .audit_file_fn
= vfswrap_audit_file
,
4062 /* POSIX ACL operations. */
4064 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
4065 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
4066 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
4067 .sys_acl_delete_def_fd_fn
= vfswrap_sys_acl_delete_def_fd
,
4069 /* EA operations. */
4070 .getxattrat_send_fn
= vfswrap_getxattrat_send
,
4071 .getxattrat_recv_fn
= vfswrap_getxattrat_recv
,
4072 .fgetxattr_fn
= vfswrap_fgetxattr
,
4073 .flistxattr_fn
= vfswrap_flistxattr
,
4074 .fremovexattr_fn
= vfswrap_fremovexattr
,
4075 .fsetxattr_fn
= vfswrap_fsetxattr
,
4077 /* aio operations */
4078 .aio_force_fn
= vfswrap_aio_force
,
4080 /* durable handle operations */
4081 .durable_cookie_fn
= vfswrap_durable_cookie
,
4082 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
4083 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
4087 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
4090 * Here we need to implement every call!
4092 * As this is the end of the vfs module chain.
4094 smb_vfs_assert_all_fns(&vfs_default_fns
, DEFAULT_VFS_MODULE_NAME
);
4095 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
4096 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);