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 status
= vfs_offload_token_ctx_init(handle
->conn
->sconn
->client
,
2152 &vfswrap_offload_ctx
);
2153 if (tevent_req_nterror(req
, status
)) {
2154 return tevent_req_post(req
, ev
);
2157 tevent_req_set_cleanup_fn(req
, vfswrap_offload_write_cleanup
);
2160 case FSCTL_SRV_COPYCHUNK
:
2161 case FSCTL_SRV_COPYCHUNK_WRITE
:
2164 case FSCTL_OFFLOAD_WRITE
:
2165 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2166 return tevent_req_post(req
, ev
);
2168 case FSCTL_DUP_EXTENTS_TO_FILE
:
2169 DBG_DEBUG("COW clones not supported by vfs_default\n");
2170 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2171 return tevent_req_post(req
, ev
);
2174 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2175 return tevent_req_post(req
, ev
);
2179 * From here on we assume a copy-chunk fsctl
2183 tevent_req_done(req
);
2184 return tevent_req_post(req
, ev
);
2187 if (state
->src_off
> max_offset
) {
2189 * Protect integer checks below.
2191 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2192 return tevent_req_post(req
, ev
);
2194 if (state
->src_off
< 0) {
2196 * Protect integer checks below.
2198 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2199 return tevent_req_post(req
, ev
);
2201 if (state
->dst_off
> max_offset
) {
2203 * Protect integer checks below.
2205 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2206 return tevent_req_post(req
, ev
);
2208 if (state
->dst_off
< 0) {
2210 * Protect integer checks below.
2212 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2213 return tevent_req_post(req
, ev
);
2216 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
2218 if (tevent_req_nterror(req
, status
)) {
2219 return tevent_req_post(req
, ev
);
2222 DBG_DEBUG("server side copy chunk of length %" PRIu64
"\n", to_copy
);
2224 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
2225 if (!NT_STATUS_IS_OK(status
)) {
2226 tevent_req_nterror(req
, status
);
2227 return tevent_req_post(req
, ev
);
2230 ok
= change_to_user_and_service_by_fsp(src_fsp
);
2232 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2233 return tevent_req_post(req
, ev
);
2236 state
->src_ev
= src_fsp
->conn
->sconn
->ev_ctx
;
2237 state
->src_fsp
= src_fsp
;
2239 status
= vfs_stat_fsp(src_fsp
);
2240 if (tevent_req_nterror(req
, status
)) {
2241 return tevent_req_post(req
, ev
);
2244 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ to_copy
) {
2246 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2247 * If the SourceOffset or SourceOffset + Length extends beyond
2248 * the end of file, the server SHOULD<240> treat this as a
2249 * STATUS_END_OF_FILE error.
2251 * <240> Section 3.3.5.15.6: Windows servers will return
2252 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2254 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
2255 return tevent_req_post(req
, ev
);
2258 status
= vfswrap_offload_copy_file_range(req
);
2259 if (NT_STATUS_IS_OK(status
)) {
2260 tevent_req_done(req
);
2261 return tevent_req_post(req
, ev
);
2263 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
2264 tevent_req_nterror(req
, status
);
2265 return tevent_req_post(req
, ev
);
2268 state
->buf
= talloc_array(state
, uint8_t, num
);
2269 if (tevent_req_nomem(state
->buf
, req
)) {
2270 return tevent_req_post(req
, ev
);
2273 status
= vfswrap_offload_write_loop(req
);
2274 if (!NT_STATUS_IS_OK(status
)) {
2275 tevent_req_nterror(req
, status
);
2276 return tevent_req_post(req
, ev
);
2282 static NTSTATUS
vfswrap_offload_copy_file_range(struct tevent_req
*req
)
2284 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2285 req
, struct vfswrap_offload_write_state
);
2286 struct lock_struct lck
;
2291 static bool try_copy_file_range
= true;
2293 if (!try_copy_file_range
) {
2294 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2297 same_file
= file_id_equal(&state
->src_fsp
->file_id
,
2298 &state
->dst_fsp
->file_id
);
2300 sys_io_ranges_overlap(state
->remaining
,
2305 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2308 if (fsp_is_alternate_stream(state
->src_fsp
) ||
2309 fsp_is_alternate_stream(state
->dst_fsp
))
2311 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2314 init_strict_lock_struct(state
->src_fsp
,
2315 state
->src_fsp
->op
->global
->open_persistent_id
,
2319 lp_posix_cifsu_locktype(state
->src_fsp
),
2322 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2326 return NT_STATUS_FILE_LOCK_CONFLICT
;
2329 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2331 return NT_STATUS_INTERNAL_ERROR
;
2334 init_strict_lock_struct(state
->dst_fsp
,
2335 state
->dst_fsp
->op
->global
->open_persistent_id
,
2339 lp_posix_cifsu_locktype(state
->dst_fsp
),
2342 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2346 return NT_STATUS_FILE_LOCK_CONFLICT
;
2349 while (state
->remaining
> 0) {
2350 nwritten
= copy_file_range(fsp_get_io_fd(state
->src_fsp
),
2352 fsp_get_io_fd(state
->dst_fsp
),
2356 if (nwritten
== -1) {
2357 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2358 "n [%jd] failed: %s\n",
2359 fsp_str_dbg(state
->src_fsp
),
2360 (intmax_t)state
->src_off
,
2361 fsp_str_dbg(state
->dst_fsp
),
2362 (intmax_t)state
->dst_off
,
2363 (intmax_t)state
->remaining
,
2368 try_copy_file_range
= false;
2369 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2372 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2375 status
= map_nt_error_from_unix(errno
);
2376 if (NT_STATUS_EQUAL(
2378 NT_STATUS_MORE_PROCESSING_REQUIRED
))
2380 /* Avoid triggering the fallback */
2381 status
= NT_STATUS_INTERNAL_ERROR
;
2388 if (state
->remaining
< nwritten
) {
2389 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2390 "n [%jd] remaining [%jd]\n",
2391 fsp_str_dbg(state
->src_fsp
),
2392 fsp_str_dbg(state
->dst_fsp
),
2394 (intmax_t)state
->remaining
);
2395 return NT_STATUS_INTERNAL_ERROR
;
2398 if (nwritten
== 0) {
2401 state
->copied
+= nwritten
;
2402 state
->remaining
-= nwritten
;
2406 * Tell the req cleanup function there's no need to call
2407 * change_to_user_and_service_by_fsp() on the dst handle.
2409 state
->dst_fsp
= NULL
;
2410 return NT_STATUS_OK
;
2413 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
2415 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
2417 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2418 req
, struct vfswrap_offload_write_state
);
2419 struct tevent_req
*subreq
= NULL
;
2420 struct lock_struct read_lck
;
2424 * This is called under the context of state->src_fsp.
2427 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
2429 init_strict_lock_struct(state
->src_fsp
,
2430 state
->src_fsp
->op
->global
->open_persistent_id
,
2432 state
->next_io_size
,
2434 lp_posix_cifsu_locktype(state
->src_fsp
),
2437 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2441 return NT_STATUS_FILE_LOCK_CONFLICT
;
2444 subreq
= SMB_VFS_PREAD_SEND(state
,
2448 state
->next_io_size
,
2450 if (subreq
== NULL
) {
2451 return NT_STATUS_NO_MEMORY
;
2453 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
2455 return NT_STATUS_OK
;
2458 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
2460 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
2462 struct tevent_req
*req
= tevent_req_callback_data(
2463 subreq
, struct tevent_req
);
2464 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2465 req
, struct vfswrap_offload_write_state
);
2466 struct vfs_aio_state aio_state
;
2467 struct lock_struct write_lck
;
2471 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
2472 TALLOC_FREE(subreq
);
2474 DBG_ERR("read failed: %s\n", strerror(aio_state
.error
));
2475 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2478 if (nread
!= state
->next_io_size
) {
2479 DBG_ERR("Short read, only %zd of %zu\n",
2480 nread
, state
->next_io_size
);
2481 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2485 state
->src_off
+= nread
;
2487 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2489 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2493 init_strict_lock_struct(state
->dst_fsp
,
2494 state
->dst_fsp
->op
->global
->open_persistent_id
,
2496 state
->next_io_size
,
2498 lp_posix_cifsu_locktype(state
->dst_fsp
),
2501 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2505 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
2509 subreq
= SMB_VFS_PWRITE_SEND(state
,
2513 state
->next_io_size
,
2515 if (subreq
== NULL
) {
2516 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2519 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
2522 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
2524 struct tevent_req
*req
= tevent_req_callback_data(
2525 subreq
, struct tevent_req
);
2526 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2527 req
, struct vfswrap_offload_write_state
);
2528 struct vfs_aio_state aio_state
;
2533 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
2534 TALLOC_FREE(subreq
);
2535 if (nwritten
== -1) {
2536 DBG_ERR("write failed: %s\n", strerror(aio_state
.error
));
2537 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2540 if (nwritten
!= state
->next_io_size
) {
2541 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
2542 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2546 state
->dst_off
+= nwritten
;
2548 if (state
->remaining
< nwritten
) {
2549 /* Paranoia check */
2550 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2553 state
->copied
+= nwritten
;
2554 state
->remaining
-= nwritten
;
2555 if (state
->remaining
== 0) {
2556 tevent_req_done(req
);
2560 ok
= change_to_user_and_service_by_fsp(state
->src_fsp
);
2562 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2566 status
= vfswrap_offload_write_loop(req
);
2567 if (!NT_STATUS_IS_OK(status
)) {
2568 tevent_req_nterror(req
, status
);
2575 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
2576 struct tevent_req
*req
,
2579 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2580 req
, struct vfswrap_offload_write_state
);
2583 if (tevent_req_is_nterror(req
, &status
)) {
2584 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
2586 tevent_req_received(req
);
2590 *copied
= state
->copied
;
2591 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2592 tevent_req_received(req
);
2594 return NT_STATUS_OK
;
2597 static NTSTATUS
vfswrap_fget_compression(struct vfs_handle_struct
*handle
,
2598 TALLOC_CTX
*mem_ctx
,
2599 struct files_struct
*fsp
,
2600 uint16_t *_compression_fmt
)
2602 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2605 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2606 TALLOC_CTX
*mem_ctx
,
2607 struct files_struct
*fsp
,
2608 uint16_t compression_fmt
)
2610 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2613 /********************************************************************
2614 Given a stat buffer return the allocated size on disk, taking into
2615 account sparse files.
2616 ********************************************************************/
2617 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2618 struct files_struct
*fsp
,
2619 const SMB_STRUCT_STAT
*sbuf
)
2623 START_PROFILE(syscall_get_alloc_size
);
2625 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2630 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2631 /* The type of st_blocksize is blkcnt_t which *MUST* be
2632 signed (according to POSIX) and can be less than 64-bits.
2633 Ensure when we're converting to 64 bits wide we don't
2635 #if defined(SIZEOF_BLKCNT_T_8)
2636 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2637 #elif defined(SIZEOF_BLKCNT_T_4)
2639 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2640 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2643 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2647 * Some file systems do not allocate a block for very
2648 * small files. But for non-empty file should report a
2652 uint64_t filesize
= get_file_size_stat(sbuf
);
2654 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2658 result
= get_file_size_stat(sbuf
);
2661 if (fsp
&& fsp
->initial_allocation_size
)
2662 result
= MAX(result
,fsp
->initial_allocation_size
);
2664 result
= smb_roundup(handle
->conn
, result
);
2667 END_PROFILE(syscall_get_alloc_size
);
2671 static int vfswrap_unlinkat(vfs_handle_struct
*handle
,
2672 struct files_struct
*dirfsp
,
2673 const struct smb_filename
*smb_fname
,
2678 START_PROFILE(syscall_unlinkat
);
2680 SMB_ASSERT(!is_named_stream(smb_fname
));
2682 result
= unlinkat(fsp_get_pathref_fd(dirfsp
),
2683 smb_fname
->base_name
,
2686 END_PROFILE(syscall_unlinkat
);
2690 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2694 START_PROFILE(syscall_fchmod
);
2696 if (!fsp
->fsp_flags
.is_pathref
) {
2697 result
= fchmod(fsp_get_io_fd(fsp
), mode
);
2698 END_PROFILE(syscall_fchmod
);
2702 if (fsp
->fsp_flags
.have_proc_fds
) {
2703 int fd
= fsp_get_pathref_fd(fsp
);
2704 struct sys_proc_fd_path_buf buf
;
2706 result
= chmod(sys_proc_fd_path(fd
, &buf
), mode
);
2708 END_PROFILE(syscall_fchmod
);
2713 * This is no longer a handle based call.
2715 result
= chmod(fsp
->fsp_name
->base_name
, mode
);
2717 END_PROFILE(syscall_fchmod
);
2721 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2726 START_PROFILE(syscall_fchown
);
2727 if (!fsp
->fsp_flags
.is_pathref
) {
2728 result
= fchown(fsp_get_io_fd(fsp
), uid
, gid
);
2729 END_PROFILE(syscall_fchown
);
2733 if (fsp
->fsp_flags
.have_proc_fds
) {
2734 int fd
= fsp_get_pathref_fd(fsp
);
2735 struct sys_proc_fd_path_buf buf
;
2737 result
= chown(sys_proc_fd_path(fd
, &buf
), uid
, gid
);
2739 END_PROFILE(syscall_fchown
);
2744 * This is no longer a handle based call.
2746 result
= chown(fsp
->fsp_name
->base_name
, uid
, gid
);
2747 END_PROFILE(syscall_fchown
);
2755 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2756 const struct smb_filename
*smb_fname
,
2762 START_PROFILE(syscall_lchown
);
2763 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2764 END_PROFILE(syscall_lchown
);
2768 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2769 const struct smb_filename
*smb_fname
)
2773 START_PROFILE(syscall_chdir
);
2774 result
= chdir(smb_fname
->base_name
);
2775 END_PROFILE(syscall_chdir
);
2779 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2783 struct smb_filename
*smb_fname
= NULL
;
2785 START_PROFILE(syscall_getwd
);
2786 result
= sys_getwd();
2787 END_PROFILE(syscall_getwd
);
2789 if (result
== NULL
) {
2792 smb_fname
= synthetic_smb_fname(ctx
,
2799 * sys_getwd() *always* returns malloced memory.
2800 * We must free here to avoid leaks:
2801 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2807 /*********************************************************************
2808 nsec timestamp resolution call. Convert down to whatever the underlying
2809 system will support.
2810 **********************************************************************/
2812 static int vfswrap_fntimes(vfs_handle_struct
*handle
,
2814 struct smb_file_time
*ft
)
2817 struct timespec ts
[2];
2818 struct timespec
*times
= NULL
;
2820 START_PROFILE(syscall_fntimes
);
2822 if (fsp_is_alternate_stream(fsp
)) {
2828 if (is_omit_timespec(&ft
->atime
)) {
2829 ft
->atime
= fsp
->fsp_name
->st
.st_ex_atime
;
2832 if (is_omit_timespec(&ft
->mtime
)) {
2833 ft
->mtime
= fsp
->fsp_name
->st
.st_ex_mtime
;
2836 if (!is_omit_timespec(&ft
->create_time
)) {
2837 set_create_timespec_ea(fsp
,
2841 if ((timespec_compare(&ft
->atime
,
2842 &fsp
->fsp_name
->st
.st_ex_atime
) == 0) &&
2843 (timespec_compare(&ft
->mtime
,
2844 &fsp
->fsp_name
->st
.st_ex_mtime
) == 0)) {
2856 if (!fsp
->fsp_flags
.is_pathref
) {
2857 result
= futimens(fsp_get_io_fd(fsp
), times
);
2861 if (fsp
->fsp_flags
.have_proc_fds
) {
2862 int fd
= fsp_get_pathref_fd(fsp
);
2863 struct sys_proc_fd_path_buf buf
;
2865 result
= utimensat(AT_FDCWD
,
2866 sys_proc_fd_path(fd
, &buf
),
2874 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2875 * path translation mechanism. Fallback to path based call.
2877 result
= utimensat(AT_FDCWD
, fsp
->fsp_name
->base_name
, times
, 0);
2880 END_PROFILE(syscall_fntimes
);
2886 /*********************************************************************
2887 A version of ftruncate that will write the space on disk if strict
2889 **********************************************************************/
2891 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2893 off_t space_to_write
;
2894 uint64_t space_avail
;
2895 uint64_t bsize
,dfree
,dsize
;
2898 SMB_STRUCT_STAT
*pst
;
2901 ok
= vfs_valid_pwrite_range(len
, 0);
2907 status
= vfs_stat_fsp(fsp
);
2908 if (!NT_STATUS_IS_OK(status
)) {
2911 pst
= &fsp
->fsp_name
->st
;
2914 if (S_ISFIFO(pst
->st_ex_mode
))
2918 if (pst
->st_ex_size
== len
)
2921 /* Shrink - just ftruncate. */
2922 if (pst
->st_ex_size
> len
)
2923 return ftruncate(fsp_get_io_fd(fsp
), len
);
2925 space_to_write
= len
- pst
->st_ex_size
;
2927 /* for allocation try fallocate first. This can fail on some
2928 platforms e.g. when the filesystem doesn't support it and no
2929 emulation is being done by the libc (like on AIX with JFS1). In that
2930 case we do our own emulation. fallocate implementations can
2931 return ENOTSUP or EINVAL in cases like that. */
2932 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2933 if (ret
== -1 && errno
== ENOSPC
) {
2939 DBG_DEBUG("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2940 "error %d. Falling back to slow manual allocation\n", errno
);
2942 /* available disk space is enough or not? */
2944 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
2945 /* space_avail is 1k blocks */
2946 if (space_avail
== (uint64_t)-1 ||
2947 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
2952 /* Write out the real space on disk. */
2953 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
2961 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2964 SMB_STRUCT_STAT
*pst
;
2968 START_PROFILE(syscall_ftruncate
);
2970 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->fsp_flags
.is_sparse
) {
2971 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
2972 END_PROFILE(syscall_ftruncate
);
2976 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2977 ftruncate if the system supports it. Then I discovered that
2978 you can have some filesystems that support ftruncate
2979 expansion and some that don't! On Linux fat can't do
2980 ftruncate extend but ext2 can. */
2982 result
= ftruncate(fsp_get_io_fd(fsp
), len
);
2984 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2985 extend a file with ftruncate. Provide alternate implementation
2988 /* Do an fstat to see if the file is longer than the requested
2989 size in which case the ftruncate above should have
2990 succeeded or shorter, in which case seek to len - 1 and
2991 write 1 byte of zero */
2992 status
= vfs_stat_fsp(fsp
);
2993 if (!NT_STATUS_IS_OK(status
)) {
2997 /* We need to update the files_struct after successful ftruncate */
3002 pst
= &fsp
->fsp_name
->st
;
3005 if (S_ISFIFO(pst
->st_ex_mode
)) {
3011 if (pst
->st_ex_size
== len
) {
3016 if (pst
->st_ex_size
> len
) {
3017 /* the ftruncate should have worked */
3021 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
3029 END_PROFILE(syscall_ftruncate
);
3033 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
3041 START_PROFILE(syscall_fallocate
);
3043 result
= sys_posix_fallocate(fsp_get_io_fd(fsp
), offset
, len
);
3045 * posix_fallocate returns 0 on success, errno on error
3046 * and doesn't set errno. Make it behave like fallocate()
3047 * which returns -1, and sets errno on failure.
3054 /* sys_fallocate handles filtering of unsupported mode flags */
3055 result
= sys_fallocate(fsp_get_io_fd(fsp
), mode
, offset
, len
);
3057 END_PROFILE(syscall_fallocate
);
3061 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
3065 START_PROFILE(syscall_fcntl_lock
);
3067 if (fsp
->fsp_flags
.use_ofd_locks
) {
3068 op
= map_process_lock_to_ofd_lock(op
);
3071 result
= fcntl_lock(fsp_get_io_fd(fsp
), op
, offset
, count
, type
);
3072 END_PROFILE(syscall_fcntl_lock
);
3076 static int vfswrap_filesystem_sharemode(vfs_handle_struct
*handle
,
3078 uint32_t share_access
,
3079 uint32_t access_mask
)
3085 static int vfswrap_fcntl(vfs_handle_struct
*handle
, files_struct
*fsp
, int cmd
,
3089 va_list dup_cmd_arg
;
3093 START_PROFILE(syscall_fcntl
);
3095 va_copy(dup_cmd_arg
, cmd_arg
);
3101 #if defined(HAVE_OFD_LOCKS)
3106 #if defined(HAVE_F_OWNER_EX)
3110 #if defined(HAVE_RW_HINTS)
3113 case F_GET_FILE_RW_HINT
:
3114 case F_SET_FILE_RW_HINT
:
3116 argp
= va_arg(dup_cmd_arg
, void *);
3117 result
= sys_fcntl_ptr(fsp_get_io_fd(fsp
), cmd
, argp
);
3120 val
= va_arg(dup_cmd_arg
, int);
3121 result
= sys_fcntl_int(fsp_get_io_fd(fsp
), cmd
, val
);
3124 va_end(dup_cmd_arg
);
3126 END_PROFILE(syscall_fcntl
);
3130 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
3135 START_PROFILE(syscall_fcntl_getlock
);
3137 if (fsp
->fsp_flags
.use_ofd_locks
) {
3138 op
= map_process_lock_to_ofd_lock(op
);
3141 result
= fcntl_getlock(fsp_get_io_fd(fsp
), op
, poffset
, pcount
, ptype
, ppid
);
3142 END_PROFILE(syscall_fcntl_getlock
);
3146 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
3151 START_PROFILE(syscall_linux_setlease
);
3153 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3155 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3156 result
= linux_setlease(fsp_get_io_fd(fsp
), leasetype
);
3160 END_PROFILE(syscall_linux_setlease
);
3164 static int vfswrap_symlinkat(vfs_handle_struct
*handle
,
3165 const struct smb_filename
*link_target
,
3166 struct files_struct
*dirfsp
,
3167 const struct smb_filename
*new_smb_fname
)
3171 START_PROFILE(syscall_symlinkat
);
3173 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3175 result
= symlinkat(link_target
->base_name
,
3176 fsp_get_pathref_fd(dirfsp
),
3177 new_smb_fname
->base_name
);
3178 END_PROFILE(syscall_symlinkat
);
3182 static int vfswrap_readlinkat(vfs_handle_struct
*handle
,
3183 const struct files_struct
*dirfsp
,
3184 const struct smb_filename
*smb_fname
,
3190 START_PROFILE(syscall_readlinkat
);
3192 SMB_ASSERT(!is_named_stream(smb_fname
));
3194 result
= readlinkat(fsp_get_pathref_fd(dirfsp
),
3195 smb_fname
->base_name
,
3199 END_PROFILE(syscall_readlinkat
);
3203 static int vfswrap_linkat(vfs_handle_struct
*handle
,
3204 files_struct
*srcfsp
,
3205 const struct smb_filename
*old_smb_fname
,
3206 files_struct
*dstfsp
,
3207 const struct smb_filename
*new_smb_fname
,
3212 START_PROFILE(syscall_linkat
);
3214 SMB_ASSERT(!is_named_stream(old_smb_fname
));
3215 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3217 result
= linkat(fsp_get_pathref_fd(srcfsp
),
3218 old_smb_fname
->base_name
,
3219 fsp_get_pathref_fd(dstfsp
),
3220 new_smb_fname
->base_name
,
3223 END_PROFILE(syscall_linkat
);
3227 static int vfswrap_mknodat(vfs_handle_struct
*handle
,
3228 files_struct
*dirfsp
,
3229 const struct smb_filename
*smb_fname
,
3235 START_PROFILE(syscall_mknodat
);
3237 SMB_ASSERT(!is_named_stream(smb_fname
));
3239 result
= sys_mknodat(fsp_get_pathref_fd(dirfsp
),
3240 smb_fname
->base_name
,
3244 END_PROFILE(syscall_mknodat
);
3248 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
3250 const struct smb_filename
*smb_fname
)
3253 struct smb_filename
*result_fname
= NULL
;
3255 START_PROFILE(syscall_realpath
);
3256 result
= sys_realpath(smb_fname
->base_name
);
3257 END_PROFILE(syscall_realpath
);
3259 result_fname
= synthetic_smb_fname(ctx
,
3267 return result_fname
;
3270 static int vfswrap_fchflags(vfs_handle_struct
*handle
,
3271 struct files_struct
*fsp
,
3274 #ifdef HAVE_FCHFLAGS
3275 int fd
= fsp_get_pathref_fd(fsp
);
3277 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3279 if (!fsp
->fsp_flags
.is_pathref
) {
3280 return fchflags(fd
, flags
);
3283 if (fsp
->fsp_flags
.have_proc_fds
) {
3284 struct sys_proc_fd_path_buf buf
;
3286 return chflags(sys_proc_fd_path(fd
, &buf
), flags
);
3290 * This is no longer a handle based call.
3292 return chflags(fsp
->fsp_name
->base_name
, flags
);
3299 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
3300 const SMB_STRUCT_STAT
*sbuf
)
3304 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3308 key
.devid
= sbuf
->st_ex_dev
;
3309 key
.inode
= sbuf
->st_ex_ino
;
3310 /* key.extid is unused by default. */
3315 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct
*handle
,
3316 const SMB_STRUCT_STAT
*psbuf
)
3320 if (handle
->conn
->base_share_dev
== psbuf
->st_ex_dev
) {
3321 return (uint64_t)psbuf
->st_ex_ino
;
3325 file_id
= ((psbuf
->st_ex_ino
) & UINT32_MAX
);
3328 file_id
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32;
3333 static NTSTATUS
vfswrap_fstreaminfo(vfs_handle_struct
*handle
,
3334 struct files_struct
*fsp
,
3335 TALLOC_CTX
*mem_ctx
,
3336 unsigned int *pnum_streams
,
3337 struct stream_struct
**pstreams
)
3339 struct stream_struct
*tmp_streams
= NULL
;
3340 unsigned int num_streams
= *pnum_streams
;
3341 struct stream_struct
*streams
= *pstreams
;
3344 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3346 if (fsp
->fsp_flags
.is_directory
) {
3348 * No default streams on directories
3352 status
= vfs_stat_fsp(fsp
);
3353 if (!NT_STATUS_IS_OK(status
)) {
3357 if (num_streams
+ 1 < 1) {
3359 return NT_STATUS_INVALID_PARAMETER
;
3362 tmp_streams
= talloc_realloc(mem_ctx
,
3364 struct stream_struct
,
3366 if (tmp_streams
== NULL
) {
3367 return NT_STATUS_NO_MEMORY
;
3369 tmp_streams
[num_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
3370 if (tmp_streams
[num_streams
].name
== NULL
) {
3371 return NT_STATUS_NO_MEMORY
;
3373 tmp_streams
[num_streams
].size
= fsp
->fsp_name
->st
.st_ex_size
;
3374 tmp_streams
[num_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(
3377 &fsp
->fsp_name
->st
);
3380 *pnum_streams
= num_streams
;
3381 *pstreams
= tmp_streams
;
3383 return NT_STATUS_OK
;
3386 static NTSTATUS
vfswrap_get_real_filename_at(
3387 struct vfs_handle_struct
*handle
,
3388 struct files_struct
*dirfsp
,
3390 TALLOC_CTX
*mem_ctx
,
3394 * Don't fall back to get_real_filename so callers can differentiate
3395 * between a full directory scan and an actual case-insensitive stat.
3397 return NT_STATUS_NOT_SUPPORTED
;
3400 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
3401 const struct files_struct
*dirfsp
,
3402 const struct smb_filename
*smb_fname
)
3404 return handle
->conn
->connectpath
;
3407 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
3408 struct byte_range_lock
*br_lck
,
3409 struct lock_struct
*plock
)
3411 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3413 /* Note: blr is not used in the default implementation. */
3414 return brl_lock_windows_default(br_lck
, plock
);
3417 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
3418 struct byte_range_lock
*br_lck
,
3419 const struct lock_struct
*plock
)
3421 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3423 return brl_unlock_windows_default(br_lck
, plock
);
3426 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
3428 struct lock_struct
*plock
)
3430 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
3431 plock
->lock_type
== WRITE_LOCK
);
3433 return strict_lock_check_default(fsp
, plock
);
3436 /* NT ACL operations. */
3438 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
3440 uint32_t security_info
,
3441 TALLOC_CTX
*mem_ctx
,
3442 struct security_descriptor
**ppdesc
)
3446 START_PROFILE(fget_nt_acl
);
3448 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3450 result
= posix_fget_nt_acl(fsp
, security_info
,
3452 END_PROFILE(fget_nt_acl
);
3456 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
3460 START_PROFILE(fset_nt_acl
);
3462 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3464 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
3465 END_PROFILE(fset_nt_acl
);
3469 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
3470 struct smb_filename
*file
,
3471 struct security_acl
*sacl
,
3472 uint32_t access_requested
,
3473 uint32_t access_denied
)
3475 return NT_STATUS_OK
; /* Nothing to do here ... */
3478 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
3480 SMB_ACL_TYPE_T type
,
3481 TALLOC_CTX
*mem_ctx
)
3483 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3485 return sys_acl_get_fd(handle
, fsp
, type
, mem_ctx
);
3488 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
,
3490 SMB_ACL_TYPE_T type
,
3493 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3495 return sys_acl_set_fd(handle
, fsp
, type
, theacl
);
3498 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct
*handle
,
3501 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3503 return sys_acl_delete_def_fd(handle
, fsp
);
3506 /****************************************************************
3507 Extended attribute operations.
3508 *****************************************************************/
3510 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
,
3511 struct files_struct
*fsp
,
3516 int fd
= fsp_get_pathref_fd(fsp
);
3518 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3520 if (!fsp
->fsp_flags
.is_pathref
) {
3521 return fgetxattr(fd
, name
, value
, size
);
3524 if (fsp
->fsp_flags
.have_proc_fds
) {
3525 struct sys_proc_fd_path_buf buf
;
3527 return getxattr(sys_proc_fd_path(fd
, &buf
), name
, value
, size
);
3531 * This is no longer a handle based call.
3533 return getxattr(fsp
->fsp_name
->base_name
, name
, value
, size
);
3536 struct vfswrap_getxattrat_state
{
3537 struct tevent_context
*ev
;
3538 struct vfs_handle_struct
*handle
;
3539 files_struct
*dir_fsp
;
3540 const struct smb_filename
*smb_fname
;
3543 * The following variables are talloced off "state" which is protected
3544 * by a destructor and thus are guaranteed to be safe to be used in the
3545 * job function in the worker thread.
3548 const char *xattr_name
;
3549 uint8_t *xattr_value
;
3550 struct security_unix_token
*token
;
3553 struct vfs_aio_state vfs_aio_state
;
3554 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
3557 static int vfswrap_getxattrat_state_destructor(
3558 struct vfswrap_getxattrat_state
*state
)
3563 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
);
3564 static void vfswrap_getxattrat_do_async(void *private_data
);
3565 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
);
3567 static struct tevent_req
*vfswrap_getxattrat_send(
3568 TALLOC_CTX
*mem_ctx
,
3569 struct tevent_context
*ev
,
3570 struct vfs_handle_struct
*handle
,
3571 files_struct
*dir_fsp
,
3572 const struct smb_filename
*smb_fname
,
3573 const char *xattr_name
,
3576 struct tevent_req
*req
= NULL
;
3577 struct tevent_req
*subreq
= NULL
;
3578 struct vfswrap_getxattrat_state
*state
= NULL
;
3579 size_t max_threads
= 0;
3580 bool have_per_thread_cwd
= false;
3581 bool have_per_thread_creds
= false;
3582 bool do_async
= false;
3584 SMB_ASSERT(!is_named_stream(smb_fname
));
3586 req
= tevent_req_create(mem_ctx
, &state
,
3587 struct vfswrap_getxattrat_state
);
3591 *state
= (struct vfswrap_getxattrat_state
) {
3595 .smb_fname
= smb_fname
,
3598 max_threads
= pthreadpool_tevent_max_threads(dir_fsp
->conn
->sconn
->pool
);
3599 if (max_threads
>= 1) {
3601 * We need a non sync threadpool!
3603 have_per_thread_cwd
= per_thread_cwd_supported();
3605 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3606 have_per_thread_creds
= true;
3608 if (have_per_thread_cwd
&& have_per_thread_creds
) {
3612 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat
, profile_p
,
3613 state
->profile_bytes
, 0);
3615 if (fsp_get_pathref_fd(dir_fsp
) == -1) {
3616 DBG_ERR("Need a valid directory fd\n");
3617 tevent_req_error(req
, EINVAL
);
3618 return tevent_req_post(req
, ev
);
3621 if (alloc_hint
> 0) {
3622 state
->xattr_value
= talloc_zero_array(state
,
3625 if (tevent_req_nomem(state
->xattr_value
, req
)) {
3626 return tevent_req_post(req
, ev
);
3631 vfswrap_getxattrat_do_sync(req
);
3632 return tevent_req_post(req
, ev
);
3636 * Now allocate all parameters from a memory context that won't go away
3637 * no matter what. These parameters will get used in threads and we
3638 * can't reliably cancel threads, so all buffers passed to the threads
3639 * must not be freed before all referencing threads terminate.
3642 state
->name
= talloc_strdup(state
, smb_fname
->base_name
);
3643 if (tevent_req_nomem(state
->name
, req
)) {
3644 return tevent_req_post(req
, ev
);
3647 state
->xattr_name
= talloc_strdup(state
, xattr_name
);
3648 if (tevent_req_nomem(state
->xattr_name
, req
)) {
3649 return tevent_req_post(req
, ev
);
3653 * This is a hot codepath so at first glance one might think we should
3654 * somehow optimize away the token allocation and do a
3655 * talloc_reference() or similar black magic instead. But due to the
3656 * talloc_stackframe pool per SMB2 request this should be a simple copy
3657 * without a malloc in most cases.
3659 if (geteuid() == sec_initial_uid()) {
3660 state
->token
= root_unix_token(state
);
3662 state
->token
= copy_unix_token(
3664 dir_fsp
->conn
->session_info
->unix_token
);
3666 if (tevent_req_nomem(state
->token
, req
)) {
3667 return tevent_req_post(req
, ev
);
3670 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3672 subreq
= pthreadpool_tevent_job_send(
3675 dir_fsp
->conn
->sconn
->pool
,
3676 vfswrap_getxattrat_do_async
,
3678 if (tevent_req_nomem(subreq
, req
)) {
3679 return tevent_req_post(req
, ev
);
3681 tevent_req_set_callback(subreq
, vfswrap_getxattrat_done
, req
);
3683 talloc_set_destructor(state
, vfswrap_getxattrat_state_destructor
);
3688 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
)
3690 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3691 req
, struct vfswrap_getxattrat_state
);
3693 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3694 state
->smb_fname
->fsp
,
3697 talloc_array_length(state
->xattr_value
));
3698 if (state
->xattr_size
== -1) {
3699 tevent_req_error(req
, errno
);
3703 tevent_req_done(req
);
3707 static void vfswrap_getxattrat_do_async(void *private_data
)
3709 struct vfswrap_getxattrat_state
*state
= talloc_get_type_abort(
3710 private_data
, struct vfswrap_getxattrat_state
);
3711 struct timespec start_time
;
3712 struct timespec end_time
;
3715 PROFILE_TIMESTAMP(&start_time
);
3716 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
3719 * Here we simulate a getxattrat()
3720 * call using fchdir();getxattr()
3723 per_thread_cwd_activate();
3725 /* Become the correct credential on this thread. */
3726 ret
= set_thread_credentials(state
->token
->uid
,
3728 (size_t)state
->token
->ngroups
,
3729 state
->token
->groups
);
3731 state
->xattr_size
= -1;
3732 state
->vfs_aio_state
.error
= errno
;
3736 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3737 state
->smb_fname
->fsp
,
3740 talloc_array_length(state
->xattr_value
));
3741 if (state
->xattr_size
== -1) {
3742 state
->vfs_aio_state
.error
= errno
;
3746 PROFILE_TIMESTAMP(&end_time
);
3747 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
3748 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3751 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
)
3753 struct tevent_req
*req
= tevent_req_callback_data(
3754 subreq
, struct tevent_req
);
3755 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3756 req
, struct vfswrap_getxattrat_state
);
3761 * Make sure we run as the user again
3763 ok
= change_to_user_and_service_by_fsp(state
->dir_fsp
);
3766 ret
= pthreadpool_tevent_job_recv(subreq
);
3767 TALLOC_FREE(subreq
);
3768 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
3769 talloc_set_destructor(state
, NULL
);
3771 if (ret
!= EAGAIN
) {
3772 tevent_req_error(req
, ret
);
3776 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3777 * means the lower level pthreadpool failed to create a new
3778 * thread. Fallback to sync processing in that case to allow
3779 * some progress for the client.
3781 vfswrap_getxattrat_do_sync(req
);
3785 if (state
->xattr_size
== -1) {
3786 tevent_req_error(req
, state
->vfs_aio_state
.error
);
3790 if (state
->xattr_value
== NULL
) {
3792 * The caller only wanted the size.
3794 tevent_req_done(req
);
3799 * shrink the buffer to the returned size.
3800 * (can't fail). It means NULL if size is 0.
3802 state
->xattr_value
= talloc_realloc(state
,
3807 tevent_req_done(req
);
3810 static ssize_t
vfswrap_getxattrat_recv(struct tevent_req
*req
,
3811 struct vfs_aio_state
*aio_state
,
3812 TALLOC_CTX
*mem_ctx
,
3813 uint8_t **xattr_value
)
3815 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3816 req
, struct vfswrap_getxattrat_state
);
3819 if (tevent_req_is_unix_error(req
, &aio_state
->error
)) {
3820 tevent_req_received(req
);
3824 *aio_state
= state
->vfs_aio_state
;
3825 xattr_size
= state
->xattr_size
;
3826 if (xattr_value
!= NULL
) {
3827 *xattr_value
= talloc_move(mem_ctx
, &state
->xattr_value
);
3830 tevent_req_received(req
);
3834 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
3836 int fd
= fsp_get_pathref_fd(fsp
);
3838 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3840 if (!fsp
->fsp_flags
.is_pathref
) {
3841 return flistxattr(fd
, list
, size
);
3844 if (fsp
->fsp_flags
.have_proc_fds
) {
3845 struct sys_proc_fd_path_buf buf
;
3847 return listxattr(sys_proc_fd_path(fd
, &buf
), list
, size
);
3851 * This is no longer a handle based call.
3853 return listxattr(fsp
->fsp_name
->base_name
, list
, size
);
3856 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
3858 int fd
= fsp_get_pathref_fd(fsp
);
3860 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3862 if (!fsp
->fsp_flags
.is_pathref
) {
3863 return fremovexattr(fd
, name
);
3866 if (fsp
->fsp_flags
.have_proc_fds
) {
3867 struct sys_proc_fd_path_buf buf
;
3869 return removexattr(sys_proc_fd_path(fd
, &buf
), name
);
3873 * This is no longer a handle based call.
3875 return removexattr(fsp
->fsp_name
->base_name
, name
);
3878 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
3880 int fd
= fsp_get_pathref_fd(fsp
);
3882 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3884 if (!fsp
->fsp_flags
.is_pathref
) {
3885 return fsetxattr(fd
, name
, value
, size
, flags
);
3888 if (fsp
->fsp_flags
.have_proc_fds
) {
3889 struct sys_proc_fd_path_buf buf
;
3891 return setxattr(sys_proc_fd_path(fd
, &buf
),
3899 * This is no longer a handle based call.
3901 return setxattr(fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
3904 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
3909 static bool vfswrap_is_offline(struct connection_struct
*conn
,
3910 const struct smb_filename
*fname
)
3914 bool offline
= false;
3916 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
3920 if (!lp_dmapi_support(SNUM(conn
)) || !dmapi_have_session()) {
3921 #if defined(ENOTSUP)
3927 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
3928 if (!NT_STATUS_IS_OK(status
)) {
3929 errno
= map_errno_from_nt_status(status
);
3933 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
3940 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
3941 struct files_struct
*fsp
,
3942 TALLOC_CTX
*mem_ctx
,
3945 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
3948 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
3949 struct files_struct
*fsp
,
3950 const DATA_BLOB old_cookie
,
3951 TALLOC_CTX
*mem_ctx
,
3952 DATA_BLOB
*new_cookie
)
3954 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
3958 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
3959 struct smb_request
*smb1req
,
3960 struct smbXsrv_open
*op
,
3961 const DATA_BLOB old_cookie
,
3962 TALLOC_CTX
*mem_ctx
,
3963 struct files_struct
**fsp
,
3964 DATA_BLOB
*new_cookie
)
3966 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
3967 old_cookie
, mem_ctx
,
3971 static struct vfs_fn_pointers vfs_default_fns
= {
3972 /* Disk operations */
3974 .connect_fn
= vfswrap_connect
,
3975 .disconnect_fn
= vfswrap_disconnect
,
3976 .disk_free_fn
= vfswrap_disk_free
,
3977 .get_quota_fn
= vfswrap_get_quota
,
3978 .set_quota_fn
= vfswrap_set_quota
,
3979 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
3980 .statvfs_fn
= vfswrap_statvfs
,
3981 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
3982 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
3983 .create_dfs_pathat_fn
= vfswrap_create_dfs_pathat
,
3984 .read_dfs_pathat_fn
= vfswrap_read_dfs_pathat
,
3985 .snap_check_path_fn
= vfswrap_snap_check_path
,
3986 .snap_create_fn
= vfswrap_snap_create
,
3987 .snap_delete_fn
= vfswrap_snap_delete
,
3989 /* Directory operations */
3991 .fdopendir_fn
= vfswrap_fdopendir
,
3992 .readdir_fn
= vfswrap_readdir
,
3993 .freaddir_attr_fn
= vfswrap_freaddir_attr
,
3994 .rewind_dir_fn
= vfswrap_rewinddir
,
3995 .mkdirat_fn
= vfswrap_mkdirat
,
3996 .closedir_fn
= vfswrap_closedir
,
3998 /* File operations */
4000 .openat_fn
= vfswrap_openat
,
4001 .create_file_fn
= vfswrap_create_file
,
4002 .close_fn
= vfswrap_close
,
4003 .pread_fn
= vfswrap_pread
,
4004 .pread_send_fn
= vfswrap_pread_send
,
4005 .pread_recv_fn
= vfswrap_pread_recv
,
4006 .pwrite_fn
= vfswrap_pwrite
,
4007 .pwrite_send_fn
= vfswrap_pwrite_send
,
4008 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
4009 .lseek_fn
= vfswrap_lseek
,
4010 .sendfile_fn
= vfswrap_sendfile
,
4011 .recvfile_fn
= vfswrap_recvfile
,
4012 .renameat_fn
= vfswrap_renameat
,
4013 .fsync_send_fn
= vfswrap_fsync_send
,
4014 .fsync_recv_fn
= vfswrap_fsync_recv
,
4015 .stat_fn
= vfswrap_stat
,
4016 .fstat_fn
= vfswrap_fstat
,
4017 .lstat_fn
= vfswrap_lstat
,
4018 .fstatat_fn
= vfswrap_fstatat
,
4019 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
4020 .unlinkat_fn
= vfswrap_unlinkat
,
4021 .fchmod_fn
= vfswrap_fchmod
,
4022 .fchown_fn
= vfswrap_fchown
,
4023 .lchown_fn
= vfswrap_lchown
,
4024 .chdir_fn
= vfswrap_chdir
,
4025 .getwd_fn
= vfswrap_getwd
,
4026 .fntimes_fn
= vfswrap_fntimes
,
4027 .ftruncate_fn
= vfswrap_ftruncate
,
4028 .fallocate_fn
= vfswrap_fallocate
,
4029 .lock_fn
= vfswrap_lock
,
4030 .filesystem_sharemode_fn
= vfswrap_filesystem_sharemode
,
4031 .fcntl_fn
= vfswrap_fcntl
,
4032 .linux_setlease_fn
= vfswrap_linux_setlease
,
4033 .getlock_fn
= vfswrap_getlock
,
4034 .symlinkat_fn
= vfswrap_symlinkat
,
4035 .readlinkat_fn
= vfswrap_readlinkat
,
4036 .linkat_fn
= vfswrap_linkat
,
4037 .mknodat_fn
= vfswrap_mknodat
,
4038 .realpath_fn
= vfswrap_realpath
,
4039 .fchflags_fn
= vfswrap_fchflags
,
4040 .file_id_create_fn
= vfswrap_file_id_create
,
4041 .fs_file_id_fn
= vfswrap_fs_file_id
,
4042 .fstreaminfo_fn
= vfswrap_fstreaminfo
,
4043 .get_real_filename_at_fn
= vfswrap_get_real_filename_at
,
4044 .connectpath_fn
= vfswrap_connectpath
,
4045 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
4046 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
4047 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
4048 .translate_name_fn
= vfswrap_translate_name
,
4049 .parent_pathname_fn
= vfswrap_parent_pathname
,
4050 .fsctl_fn
= vfswrap_fsctl
,
4051 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
4052 .get_dos_attributes_send_fn
= vfswrap_get_dos_attributes_send
,
4053 .get_dos_attributes_recv_fn
= vfswrap_get_dos_attributes_recv
,
4054 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
4055 .offload_read_send_fn
= vfswrap_offload_read_send
,
4056 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
4057 .offload_write_send_fn
= vfswrap_offload_write_send
,
4058 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
4059 .fget_compression_fn
= vfswrap_fget_compression
,
4060 .set_compression_fn
= vfswrap_set_compression
,
4062 /* NT ACL operations. */
4064 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
4065 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
4066 .audit_file_fn
= vfswrap_audit_file
,
4068 /* POSIX ACL operations. */
4070 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
4071 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
4072 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
4073 .sys_acl_delete_def_fd_fn
= vfswrap_sys_acl_delete_def_fd
,
4075 /* EA operations. */
4076 .getxattrat_send_fn
= vfswrap_getxattrat_send
,
4077 .getxattrat_recv_fn
= vfswrap_getxattrat_recv
,
4078 .fgetxattr_fn
= vfswrap_fgetxattr
,
4079 .flistxattr_fn
= vfswrap_flistxattr
,
4080 .fremovexattr_fn
= vfswrap_fremovexattr
,
4081 .fsetxattr_fn
= vfswrap_fsetxattr
,
4083 /* aio operations */
4084 .aio_force_fn
= vfswrap_aio_force
,
4086 /* durable handle operations */
4087 .durable_cookie_fn
= vfswrap_durable_cookie
,
4088 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
4089 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
4093 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
4096 * Here we need to implement every call!
4098 * As this is the end of the vfs module chain.
4100 smb_vfs_assert_all_fns(&vfs_default_fns
, DEFAULT_VFS_MODULE_NAME
);
4101 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
4102 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);