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 #if defined(HAVE_SYS_QUOTAS)
181 caps
|= FILE_VOLUME_QUOTAS
;
184 if (lp_nt_acl_support(SNUM(conn
))) {
185 caps
|= FILE_PERSISTENT_ACLS
;
188 caps
|= lp_parm_int(SNUM(conn
), "share", "fake_fscaps", 0);
190 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
192 /* Work out what timestamp resolution we can
193 * use when setting a timestamp. */
195 ret
= SMB_VFS_STAT(conn
, smb_fname_cpath
);
197 TALLOC_FREE(smb_fname_cpath
);
201 if (smb_fname_cpath
->st
.st_ex_mtime
.tv_nsec
||
202 smb_fname_cpath
->st
.st_ex_atime
.tv_nsec
||
203 smb_fname_cpath
->st
.st_ex_ctime
.tv_nsec
) {
204 /* If any of the normal UNIX directory timestamps
205 * have a non-zero tv_nsec component assume
206 * we might be able to set sub-second timestamps.
207 * See what filetime set primitives we have.
209 #if defined(HAVE_UTIMENSAT)
210 *p_ts_res
= TIMESTAMP_SET_NT_OR_BETTER
;
211 #elif defined(HAVE_UTIMES)
212 /* utimes allows msec timestamps to be set. */
213 *p_ts_res
= TIMESTAMP_SET_MSEC
;
214 #elif defined(HAVE_UTIME)
215 /* utime only allows sec timestamps to be set. */
216 *p_ts_res
= TIMESTAMP_SET_SECONDS
;
219 DBG_DEBUG("vfswrap_fs_capabilities: timestamp "
221 "available on share %s, directory %s\n",
222 *p_ts_res
== TIMESTAMP_SET_MSEC
? "msec" : "sec",
223 lp_servicename(talloc_tos(), lp_sub
, conn
->params
->service
),
226 TALLOC_FREE(smb_fname_cpath
);
230 static NTSTATUS
vfswrap_get_dfs_referrals(struct vfs_handle_struct
*handle
,
231 struct dfs_GetDFSReferral
*r
)
233 struct junction_map
*junction
= NULL
;
234 size_t consumedcnt
= 0;
235 bool self_referral
= false;
236 char *pathnamep
= NULL
;
237 char *local_dfs_path
= NULL
;
240 uint16_t max_referral_level
= r
->in
.req
.max_referral_level
;
242 if (DEBUGLVL(DBGLVL_DEBUG
)) {
243 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral
, r
);
246 /* get the junction entry */
247 if (r
->in
.req
.servername
== NULL
) {
248 return NT_STATUS_NOT_FOUND
;
252 * Trim pathname sent by client so it begins with only one backslash.
253 * Two backslashes confuse some dfs clients
256 local_dfs_path
= talloc_strdup(r
, r
->in
.req
.servername
);
257 if (local_dfs_path
== NULL
) {
258 return NT_STATUS_NO_MEMORY
;
260 pathnamep
= local_dfs_path
;
261 while (IS_DIRECTORY_SEP(pathnamep
[0]) &&
262 IS_DIRECTORY_SEP(pathnamep
[1])) {
266 junction
= talloc_zero(r
, struct junction_map
);
267 if (junction
== NULL
) {
268 return NT_STATUS_NO_MEMORY
;
271 /* The following call can change cwd. */
272 status
= get_referred_path(r
,
273 handle
->conn
->session_info
,
275 handle
->conn
->sconn
->remote_address
,
276 handle
->conn
->sconn
->local_address
,
277 junction
, &consumedcnt
, &self_referral
);
278 if (!NT_STATUS_IS_OK(status
)) {
279 struct smb_filename connectpath_fname
= {
280 .base_name
= handle
->conn
->connectpath
282 vfs_ChDir(handle
->conn
, &connectpath_fname
);
286 struct smb_filename connectpath_fname
= {
287 .base_name
= handle
->conn
->connectpath
289 vfs_ChDir(handle
->conn
, &connectpath_fname
);
292 if (!self_referral
) {
293 pathnamep
[consumedcnt
] = '\0';
295 if (DEBUGLVL(DBGLVL_INFO
)) {
296 dbgtext("Path %s to alternate path(s):",
298 for (i
=0; i
< junction
->referral_count
; i
++) {
300 junction
->referral_list
[i
].alternate_path
);
306 if (r
->in
.req
.max_referral_level
<= 2) {
307 max_referral_level
= 2;
309 if (r
->in
.req
.max_referral_level
>= 3) {
310 max_referral_level
= 3;
313 r
->out
.resp
= talloc_zero(r
, struct dfs_referral_resp
);
314 if (r
->out
.resp
== NULL
) {
315 return NT_STATUS_NO_MEMORY
;
318 r
->out
.resp
->path_consumed
= strlen_m(pathnamep
) * 2;
319 r
->out
.resp
->nb_referrals
= junction
->referral_count
;
321 r
->out
.resp
->header_flags
= DFS_HEADER_FLAG_STORAGE_SVR
;
323 r
->out
.resp
->header_flags
|= DFS_HEADER_FLAG_REFERAL_SVR
;
326 r
->out
.resp
->referral_entries
= talloc_zero_array(r
,
327 struct dfs_referral_type
,
328 r
->out
.resp
->nb_referrals
);
329 if (r
->out
.resp
->referral_entries
== NULL
) {
330 return NT_STATUS_NO_MEMORY
;
333 switch (max_referral_level
) {
335 for(i
=0; i
< junction
->referral_count
; i
++) {
336 struct referral
*ref
= &junction
->referral_list
[i
];
337 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
338 struct dfs_referral_type
*t
=
339 &r
->out
.resp
->referral_entries
[i
];
340 struct dfs_referral_v2
*v2
= &t
->referral
.v2
;
343 v2
->size
= VERSION2_REFERRAL_SIZE
;
345 v2
->server_type
= DFS_SERVER_ROOT
;
347 v2
->server_type
= DFS_SERVER_NON_ROOT
;
350 v2
->proximity
= ref
->proximity
;
352 v2
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
353 if (v2
->DFS_path
== NULL
) {
354 return NT_STATUS_NO_MEMORY
;
356 v2
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
357 if (v2
->DFS_alt_path
== NULL
) {
358 return NT_STATUS_NO_MEMORY
;
360 v2
->netw_address
= talloc_strdup(mem_ctx
,
361 ref
->alternate_path
);
362 if (v2
->netw_address
== NULL
) {
363 return NT_STATUS_NO_MEMORY
;
369 for(i
=0; i
< junction
->referral_count
; i
++) {
370 struct referral
*ref
= &junction
->referral_list
[i
];
371 TALLOC_CTX
*mem_ctx
= r
->out
.resp
->referral_entries
;
372 struct dfs_referral_type
*t
=
373 &r
->out
.resp
->referral_entries
[i
];
374 struct dfs_referral_v3
*v3
= &t
->referral
.v3
;
375 struct dfs_normal_referral
*r1
= &v3
->referrals
.r1
;
378 v3
->size
= VERSION3_REFERRAL_SIZE
;
380 v3
->server_type
= DFS_SERVER_ROOT
;
382 v3
->server_type
= DFS_SERVER_NON_ROOT
;
386 r1
->DFS_path
= talloc_strdup(mem_ctx
, pathnamep
);
387 if (r1
->DFS_path
== NULL
) {
388 return NT_STATUS_NO_MEMORY
;
390 r1
->DFS_alt_path
= talloc_strdup(mem_ctx
, pathnamep
);
391 if (r1
->DFS_alt_path
== NULL
) {
392 return NT_STATUS_NO_MEMORY
;
394 r1
->netw_address
= talloc_strdup(mem_ctx
,
395 ref
->alternate_path
);
396 if (r1
->netw_address
== NULL
) {
397 return NT_STATUS_NO_MEMORY
;
402 DBG_ERR("Invalid dfs referral version: %d\n",
404 return NT_STATUS_INVALID_LEVEL
;
407 if (DEBUGLVL(DBGLVL_DEBUG
)) {
408 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral
, r
);
414 static NTSTATUS
vfswrap_create_dfs_pathat(struct vfs_handle_struct
*handle
,
415 struct files_struct
*dirfsp
,
416 const struct smb_filename
*smb_fname
,
417 const struct referral
*reflist
,
418 size_t referral_count
)
420 TALLOC_CTX
*frame
= talloc_stackframe();
421 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
423 char *msdfs_link
= NULL
;
425 /* Form the msdfs_link contents */
426 msdfs_link
= msdfs_link_string(frame
,
429 if (msdfs_link
== NULL
) {
433 ret
= symlinkat(msdfs_link
,
434 fsp_get_pathref_fd(dirfsp
),
435 smb_fname
->base_name
);
437 status
= NT_STATUS_OK
;
439 status
= map_nt_error_from_unix(errno
);
449 * Read and return the contents of a DFS redirect given a
450 * pathname. A caller can pass in NULL for ppreflist and
451 * preferral_count but still determine if this was a
452 * DFS redirect point by getting NT_STATUS_OK back
453 * without incurring the overhead of reading and parsing
454 * the referral contents.
457 static NTSTATUS
vfswrap_read_dfs_pathat(struct vfs_handle_struct
*handle
,
459 struct files_struct
*dirfsp
,
460 struct smb_filename
*smb_fname
,
461 struct referral
**ppreflist
,
462 size_t *preferral_count
)
464 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
466 char *link_target
= NULL
;
469 #if defined(HAVE_BROKEN_READLINK)
470 char link_target_buf
[PATH_MAX
];
472 char link_target_buf
[7];
476 if (is_named_stream(smb_fname
)) {
477 status
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
481 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
483 * We're only checking if this is a DFS
484 * redirect. We don't need to return data.
486 bufsize
= sizeof(link_target_buf
);
487 link_target
= link_target_buf
;
490 link_target
= talloc_array(mem_ctx
, char, bufsize
);
496 referral_len
= readlinkat(fsp_get_pathref_fd(dirfsp
),
497 smb_fname
->base_name
,
500 if (referral_len
== -1) {
501 if (errno
== EINVAL
) {
503 * If the path isn't a link, readlinkat
504 * returns EINVAL. Allow the caller to
507 DBG_INFO("%s is not a link.\n", smb_fname
->base_name
);
508 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
510 status
= map_nt_error_from_unix(errno
);
511 if (errno
== ENOENT
) {
512 DBG_NOTICE("Error reading "
513 "msdfs link %s: %s\n",
514 smb_fname
->base_name
,
517 DBG_ERR("Error reading "
518 "msdfs link %s: %s\n",
519 smb_fname
->base_name
,
525 link_target
[referral_len
] = '\0';
527 DBG_INFO("%s -> %s\n",
528 smb_fname
->base_name
,
531 if (!strnequal(link_target
, "msdfs:", 6)) {
532 status
= NT_STATUS_OBJECT_TYPE_MISMATCH
;
536 ret
= sys_fstatat(fsp_get_pathref_fd(dirfsp
),
537 smb_fname
->base_name
,
540 lp_fake_directory_create_times(SNUM(handle
->conn
)));
542 status
= map_nt_error_from_unix(errno
);
546 if (ppreflist
== NULL
&& preferral_count
== NULL
) {
547 /* Early return for checking if this is a DFS link. */
551 ok
= parse_msdfs_symlink(mem_ctx
,
552 lp_msdfs_shuffle_referrals(SNUM(handle
->conn
)),
558 status
= NT_STATUS_OK
;
560 status
= NT_STATUS_NO_MEMORY
;
565 if (link_target
!= link_target_buf
) {
566 TALLOC_FREE(link_target
);
571 static NTSTATUS
vfswrap_snap_check_path(struct vfs_handle_struct
*handle
,
573 const char *service_path
,
576 return NT_STATUS_NOT_SUPPORTED
;
579 static NTSTATUS
vfswrap_snap_create(struct vfs_handle_struct
*handle
,
581 const char *base_volume
,
587 return NT_STATUS_NOT_SUPPORTED
;
590 static NTSTATUS
vfswrap_snap_delete(struct vfs_handle_struct
*handle
,
595 return NT_STATUS_NOT_SUPPORTED
;
598 /* Directory operations */
600 static DIR *vfswrap_fdopendir(vfs_handle_struct
*handle
,
607 START_PROFILE(syscall_fdopendir
);
608 result
= sys_fdopendir(fsp_get_io_fd(fsp
));
609 END_PROFILE(syscall_fdopendir
);
613 static struct dirent
*vfswrap_readdir(vfs_handle_struct
*handle
,
614 struct files_struct
*dirfsp
,
617 struct dirent
*result
;
619 START_PROFILE(syscall_readdir
);
621 result
= readdir(dirp
);
622 END_PROFILE(syscall_readdir
);
627 static NTSTATUS
vfswrap_freaddir_attr(struct vfs_handle_struct
*handle
,
628 struct files_struct
*fsp
,
630 struct readdir_attr_data
**attr_data
)
632 return NT_STATUS_NOT_SUPPORTED
;
635 static void vfswrap_rewinddir(vfs_handle_struct
*handle
, DIR *dirp
)
637 START_PROFILE(syscall_rewinddir
);
639 END_PROFILE(syscall_rewinddir
);
642 static int vfswrap_mkdirat(vfs_handle_struct
*handle
,
643 struct files_struct
*dirfsp
,
644 const struct smb_filename
*smb_fname
,
649 START_PROFILE(syscall_mkdirat
);
651 result
= mkdirat(fsp_get_pathref_fd(dirfsp
), smb_fname
->base_name
, mode
);
653 END_PROFILE(syscall_mkdirat
);
657 static int vfswrap_closedir(vfs_handle_struct
*handle
, DIR *dirp
)
661 START_PROFILE(syscall_closedir
);
662 result
= closedir(dirp
);
663 END_PROFILE(syscall_closedir
);
667 /* File operations */
669 static int vfswrap_openat(vfs_handle_struct
*handle
,
670 const struct files_struct
*dirfsp
,
671 const struct smb_filename
*smb_fname
,
673 const struct vfs_open_how
*how
)
675 int flags
= how
->flags
;
676 mode_t mode
= how
->mode
;
677 bool have_opath
= false;
678 bool became_root
= false;
681 START_PROFILE(syscall_openat
);
683 if (how
->resolve
& ~(VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
|
684 VFS_OPEN_HOW_WITH_BACKUP_INTENT
)) {
690 SMB_ASSERT(!is_named_stream(smb_fname
));
694 if (fsp
->fsp_flags
.is_pathref
) {
697 if (flags
& O_PATH
) {
699 * From "man 2 openat":
701 * When O_PATH is specified in flags, flag bits other than
702 * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored.
704 * From "man 2 openat2":
706 * Whereas openat(2) ignores unknown bits in its flags
707 * argument, openat2() returns an error if unknown or
708 * conflicting flags are specified in how.flags.
710 * So we better clear ignored/invalid flags
711 * and only keep the expected ones.
713 flags
&= (O_PATH
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
717 if (how
->resolve
& VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
) {
718 struct open_how linux_how
= {
721 .resolve
= RESOLVE_NO_SYMLINKS
,
724 result
= openat2(fsp_get_pathref_fd(dirfsp
),
725 smb_fname
->base_name
,
729 if (errno
== ENOSYS
) {
731 * The kernel doesn't support
732 * openat2(), so indicate to
734 * VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
735 * would just be a waste of time.
737 fsp
->conn
->open_how_resolve
&=
738 ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
;
746 if (fsp
->fsp_flags
.is_pathref
&& !have_opath
) {
751 result
= openat(fsp_get_pathref_fd(dirfsp
),
752 smb_fname
->base_name
,
764 fsp
->fsp_flags
.have_proc_fds
= fsp
->conn
->have_proc_fds
;
767 * "/proc/self/fd/-1" never exists. Indicate to upper
768 * layers that for this fsp a possible name-based
769 * fallback is the only way to go.
771 fsp
->fsp_flags
.have_proc_fds
= false;
775 END_PROFILE(syscall_openat
);
778 static NTSTATUS
vfswrap_create_file(vfs_handle_struct
*handle
,
779 struct smb_request
*req
,
780 struct files_struct
*dirfsp
,
781 struct smb_filename
*smb_fname
,
782 uint32_t access_mask
,
783 uint32_t share_access
,
784 uint32_t create_disposition
,
785 uint32_t create_options
,
786 uint32_t file_attributes
,
787 uint32_t oplock_request
,
788 const struct smb2_lease
*lease
,
789 uint64_t allocation_size
,
790 uint32_t private_flags
,
791 struct security_descriptor
*sd
,
792 struct ea_list
*ea_list
,
793 files_struct
**result
,
795 const struct smb2_create_blobs
*in_context_blobs
,
796 struct smb2_create_blobs
*out_context_blobs
)
798 return create_file_default(handle
->conn
, req
, dirfsp
, smb_fname
,
799 access_mask
, share_access
,
800 create_disposition
, create_options
,
801 file_attributes
, oplock_request
, lease
,
802 allocation_size
, private_flags
,
804 pinfo
, in_context_blobs
, out_context_blobs
);
807 static int vfswrap_close(vfs_handle_struct
*handle
, files_struct
*fsp
)
811 START_PROFILE(syscall_close
);
812 result
= fd_close_posix(fsp
);
813 END_PROFILE(syscall_close
);
817 static ssize_t
vfswrap_pread(vfs_handle_struct
*handle
, files_struct
*fsp
, void *data
,
818 size_t n
, off_t offset
)
822 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
823 START_PROFILE_BYTES(syscall_pread
, n
);
824 result
= sys_pread_full(fsp_get_io_fd(fsp
), data
, n
, offset
);
825 END_PROFILE_BYTES(syscall_pread
);
827 if (result
== -1 && errno
== ESPIPE
) {
828 /* Maintain the fiction that pipes can be seeked (sought?) on. */
829 result
= sys_read(fsp_get_io_fd(fsp
), data
, n
);
830 fh_set_pos(fsp
->fh
, 0);
833 #else /* HAVE_PREAD */
836 #endif /* HAVE_PREAD */
841 static ssize_t
vfswrap_pwrite(vfs_handle_struct
*handle
, files_struct
*fsp
, const void *data
,
842 size_t n
, off_t offset
)
846 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
847 START_PROFILE_BYTES(syscall_pwrite
, n
);
848 result
= sys_pwrite_full(fsp_get_io_fd(fsp
), data
, n
, offset
);
849 END_PROFILE_BYTES(syscall_pwrite
);
851 if (result
== -1 && errno
== ESPIPE
) {
852 /* Maintain the fiction that pipes can be sought on. */
853 result
= sys_write(fsp_get_io_fd(fsp
), data
, n
);
856 #else /* HAVE_PWRITE */
859 #endif /* HAVE_PWRITE */
864 struct vfswrap_pread_state
{
871 struct vfs_aio_state vfs_aio_state
;
872 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
875 static void vfs_pread_do(void *private_data
);
876 static void vfs_pread_done(struct tevent_req
*subreq
);
877 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
);
879 static struct tevent_req
*vfswrap_pread_send(struct vfs_handle_struct
*handle
,
881 struct tevent_context
*ev
,
882 struct files_struct
*fsp
,
884 size_t n
, off_t offset
)
886 struct tevent_req
*req
, *subreq
;
887 struct vfswrap_pread_state
*state
;
889 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pread_state
);
895 state
->fd
= fsp_get_io_fd(fsp
);
898 state
->offset
= offset
;
900 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread
, profile_p
,
901 state
->profile_bytes
, n
);
902 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
904 subreq
= pthreadpool_tevent_job_send(
905 state
, ev
, handle
->conn
->sconn
->pool
,
906 vfs_pread_do
, state
);
907 if (tevent_req_nomem(subreq
, req
)) {
908 return tevent_req_post(req
, ev
);
910 tevent_req_set_callback(subreq
, vfs_pread_done
, req
);
912 talloc_set_destructor(state
, vfs_pread_state_destructor
);
917 static void vfs_pread_do(void *private_data
)
919 struct vfswrap_pread_state
*state
= talloc_get_type_abort(
920 private_data
, struct vfswrap_pread_state
);
921 struct timespec start_time
;
922 struct timespec end_time
;
924 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
926 PROFILE_TIMESTAMP(&start_time
);
928 state
->ret
= sys_pread_full(state
->fd
,
933 if (state
->ret
== -1) {
934 state
->vfs_aio_state
.error
= errno
;
937 PROFILE_TIMESTAMP(&end_time
);
939 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
941 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
944 static int vfs_pread_state_destructor(struct vfswrap_pread_state
*state
)
949 static void vfs_pread_done(struct tevent_req
*subreq
)
951 struct tevent_req
*req
= tevent_req_callback_data(
952 subreq
, struct tevent_req
);
953 struct vfswrap_pread_state
*state
= tevent_req_data(
954 req
, struct vfswrap_pread_state
);
957 ret
= pthreadpool_tevent_job_recv(subreq
);
959 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
960 talloc_set_destructor(state
, NULL
);
963 tevent_req_error(req
, ret
);
967 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
968 * means the lower level pthreadpool failed to create a new
969 * thread. Fallback to sync processing in that case to allow
970 * some progress for the client.
975 tevent_req_done(req
);
978 static ssize_t
vfswrap_pread_recv(struct tevent_req
*req
,
979 struct vfs_aio_state
*vfs_aio_state
)
981 struct vfswrap_pread_state
*state
= tevent_req_data(
982 req
, struct vfswrap_pread_state
);
984 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
988 *vfs_aio_state
= state
->vfs_aio_state
;
992 struct vfswrap_pwrite_state
{
999 struct vfs_aio_state vfs_aio_state
;
1000 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
1003 static void vfs_pwrite_do(void *private_data
);
1004 static void vfs_pwrite_done(struct tevent_req
*subreq
);
1005 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
);
1007 static struct tevent_req
*vfswrap_pwrite_send(struct vfs_handle_struct
*handle
,
1008 TALLOC_CTX
*mem_ctx
,
1009 struct tevent_context
*ev
,
1010 struct files_struct
*fsp
,
1012 size_t n
, off_t offset
)
1014 struct tevent_req
*req
, *subreq
;
1015 struct vfswrap_pwrite_state
*state
;
1017 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_pwrite_state
);
1023 state
->fd
= fsp_get_io_fd(fsp
);
1026 state
->offset
= offset
;
1028 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite
, profile_p
,
1029 state
->profile_bytes
, n
);
1030 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1032 subreq
= pthreadpool_tevent_job_send(
1033 state
, ev
, handle
->conn
->sconn
->pool
,
1034 vfs_pwrite_do
, state
);
1035 if (tevent_req_nomem(subreq
, req
)) {
1036 return tevent_req_post(req
, ev
);
1038 tevent_req_set_callback(subreq
, vfs_pwrite_done
, req
);
1040 talloc_set_destructor(state
, vfs_pwrite_state_destructor
);
1045 static void vfs_pwrite_do(void *private_data
)
1047 struct vfswrap_pwrite_state
*state
= talloc_get_type_abort(
1048 private_data
, struct vfswrap_pwrite_state
);
1049 struct timespec start_time
;
1050 struct timespec end_time
;
1052 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
1054 PROFILE_TIMESTAMP(&start_time
);
1056 state
->ret
= sys_pwrite_full(state
->fd
,
1061 if (state
->ret
== -1) {
1062 state
->vfs_aio_state
.error
= errno
;
1065 PROFILE_TIMESTAMP(&end_time
);
1067 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1069 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1072 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state
*state
)
1077 static void vfs_pwrite_done(struct tevent_req
*subreq
)
1079 struct tevent_req
*req
= tevent_req_callback_data(
1080 subreq
, struct tevent_req
);
1081 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1082 req
, struct vfswrap_pwrite_state
);
1085 ret
= pthreadpool_tevent_job_recv(subreq
);
1086 TALLOC_FREE(subreq
);
1087 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1088 talloc_set_destructor(state
, NULL
);
1090 if (ret
!= EAGAIN
) {
1091 tevent_req_error(req
, ret
);
1095 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1096 * means the lower level pthreadpool failed to create a new
1097 * thread. Fallback to sync processing in that case to allow
1098 * some progress for the client.
1100 vfs_pwrite_do(state
);
1103 tevent_req_done(req
);
1106 static ssize_t
vfswrap_pwrite_recv(struct tevent_req
*req
,
1107 struct vfs_aio_state
*vfs_aio_state
)
1109 struct vfswrap_pwrite_state
*state
= tevent_req_data(
1110 req
, struct vfswrap_pwrite_state
);
1112 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1116 *vfs_aio_state
= state
->vfs_aio_state
;
1120 struct vfswrap_fsync_state
{
1124 struct vfs_aio_state vfs_aio_state
;
1125 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
1128 static void vfs_fsync_do(void *private_data
);
1129 static void vfs_fsync_done(struct tevent_req
*subreq
);
1130 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
);
1132 static struct tevent_req
*vfswrap_fsync_send(struct vfs_handle_struct
*handle
,
1133 TALLOC_CTX
*mem_ctx
,
1134 struct tevent_context
*ev
,
1135 struct files_struct
*fsp
)
1137 struct tevent_req
*req
, *subreq
;
1138 struct vfswrap_fsync_state
*state
;
1140 req
= tevent_req_create(mem_ctx
, &state
, struct vfswrap_fsync_state
);
1146 state
->fd
= fsp_get_io_fd(fsp
);
1148 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync
, profile_p
,
1149 state
->profile_bytes
, 0);
1150 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1152 subreq
= pthreadpool_tevent_job_send(
1153 state
, ev
, handle
->conn
->sconn
->pool
, vfs_fsync_do
, state
);
1154 if (tevent_req_nomem(subreq
, req
)) {
1155 return tevent_req_post(req
, ev
);
1157 tevent_req_set_callback(subreq
, vfs_fsync_done
, req
);
1159 talloc_set_destructor(state
, vfs_fsync_state_destructor
);
1164 static void vfs_fsync_do(void *private_data
)
1166 struct vfswrap_fsync_state
*state
= talloc_get_type_abort(
1167 private_data
, struct vfswrap_fsync_state
);
1168 struct timespec start_time
;
1169 struct timespec end_time
;
1171 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
1173 PROFILE_TIMESTAMP(&start_time
);
1176 state
->ret
= fsync(state
->fd
);
1177 } while ((state
->ret
== -1) && (errno
== EINTR
));
1179 if (state
->ret
== -1) {
1180 state
->vfs_aio_state
.error
= errno
;
1183 PROFILE_TIMESTAMP(&end_time
);
1185 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
1187 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
1190 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state
*state
)
1195 static void vfs_fsync_done(struct tevent_req
*subreq
)
1197 struct tevent_req
*req
= tevent_req_callback_data(
1198 subreq
, struct tevent_req
);
1199 struct vfswrap_fsync_state
*state
= tevent_req_data(
1200 req
, struct vfswrap_fsync_state
);
1203 ret
= pthreadpool_tevent_job_recv(subreq
);
1204 TALLOC_FREE(subreq
);
1205 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
1206 talloc_set_destructor(state
, NULL
);
1208 if (ret
!= EAGAIN
) {
1209 tevent_req_error(req
, ret
);
1213 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1214 * means the lower level pthreadpool failed to create a new
1215 * thread. Fallback to sync processing in that case to allow
1216 * some progress for the client.
1218 vfs_fsync_do(state
);
1221 tevent_req_done(req
);
1224 static int vfswrap_fsync_recv(struct tevent_req
*req
,
1225 struct vfs_aio_state
*vfs_aio_state
)
1227 struct vfswrap_fsync_state
*state
= tevent_req_data(
1228 req
, struct vfswrap_fsync_state
);
1230 if (tevent_req_is_unix_error(req
, &vfs_aio_state
->error
)) {
1234 *vfs_aio_state
= state
->vfs_aio_state
;
1238 static off_t
vfswrap_lseek(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t offset
, int whence
)
1242 START_PROFILE(syscall_lseek
);
1244 result
= lseek(fsp_get_io_fd(fsp
), offset
, whence
);
1246 * We want to maintain the fiction that we can seek
1247 * on a fifo for file system purposes. This allows
1248 * people to set up UNIX fifo's that feed data to Windows
1249 * applications. JRA.
1252 if((result
== -1) && (errno
== ESPIPE
)) {
1257 END_PROFILE(syscall_lseek
);
1261 static ssize_t
vfswrap_sendfile(vfs_handle_struct
*handle
, int tofd
, files_struct
*fromfsp
, const DATA_BLOB
*hdr
,
1262 off_t offset
, size_t n
)
1266 START_PROFILE_BYTES(syscall_sendfile
, n
);
1267 result
= sys_sendfile(tofd
, fsp_get_io_fd(fromfsp
), hdr
, offset
, n
);
1268 END_PROFILE_BYTES(syscall_sendfile
);
1272 static ssize_t
vfswrap_recvfile(vfs_handle_struct
*handle
,
1274 files_struct
*tofsp
,
1280 START_PROFILE_BYTES(syscall_recvfile
, n
);
1281 result
= sys_recvfile(fromfd
, fsp_get_io_fd(tofsp
), offset
, n
);
1282 END_PROFILE_BYTES(syscall_recvfile
);
1286 static int vfswrap_renameat(vfs_handle_struct
*handle
,
1287 files_struct
*srcfsp
,
1288 const struct smb_filename
*smb_fname_src
,
1289 files_struct
*dstfsp
,
1290 const struct smb_filename
*smb_fname_dst
,
1291 const struct vfs_rename_how
*how
)
1296 START_PROFILE(syscall_renameat
);
1298 SMB_ASSERT(!is_named_stream(smb_fname_src
));
1299 SMB_ASSERT(!is_named_stream(smb_fname_dst
));
1301 if (how
->flags
& ~VFS_RENAME_HOW_NO_REPLACE
) {
1302 END_PROFILE(syscall_renameat
);
1307 if (how
->flags
& VFS_RENAME_HOW_NO_REPLACE
) {
1308 flags
|= RENAME_NOREPLACE
;
1311 result
= renameat2(fsp_get_pathref_fd(srcfsp
),
1312 smb_fname_src
->base_name
,
1313 fsp_get_pathref_fd(dstfsp
),
1314 smb_fname_dst
->base_name
,
1317 END_PROFILE(syscall_renameat
);
1321 static int vfswrap_stat(vfs_handle_struct
*handle
,
1322 struct smb_filename
*smb_fname
)
1326 START_PROFILE(syscall_stat
);
1328 SMB_ASSERT(!is_named_stream(smb_fname
));
1330 result
= sys_stat(smb_fname
->base_name
, &smb_fname
->st
,
1331 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1333 END_PROFILE(syscall_stat
);
1337 static int vfswrap_fstat(vfs_handle_struct
*handle
, files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1341 START_PROFILE(syscall_fstat
);
1342 result
= sys_fstat(fsp_get_pathref_fd(fsp
),
1343 sbuf
, lp_fake_directory_create_times(SNUM(handle
->conn
)));
1344 END_PROFILE(syscall_fstat
);
1348 static int vfswrap_lstat(vfs_handle_struct
*handle
,
1349 struct smb_filename
*smb_fname
)
1353 START_PROFILE(syscall_lstat
);
1355 SMB_ASSERT(!is_named_stream(smb_fname
));
1357 result
= sys_lstat(smb_fname
->base_name
, &smb_fname
->st
,
1358 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1360 END_PROFILE(syscall_lstat
);
1364 static int vfswrap_fstatat(
1365 struct vfs_handle_struct
*handle
,
1366 const struct files_struct
*dirfsp
,
1367 const struct smb_filename
*smb_fname
,
1368 SMB_STRUCT_STAT
*sbuf
,
1373 START_PROFILE(syscall_fstatat
);
1375 SMB_ASSERT(!is_named_stream(smb_fname
));
1377 result
= sys_fstatat(
1378 fsp_get_pathref_fd(dirfsp
),
1379 smb_fname
->base_name
,
1382 lp_fake_directory_create_times(SNUM(handle
->conn
)));
1384 END_PROFILE(syscall_fstatat
);
1388 static NTSTATUS
vfswrap_translate_name(struct vfs_handle_struct
*handle
,
1390 enum vfs_translate_direction direction
,
1391 TALLOC_CTX
*mem_ctx
,
1394 return NT_STATUS_NONE_MAPPED
;
1398 * Return allocated parent directory and basename of path
1400 * Note: if requesting atname, it is returned as talloc child of the
1401 * parent. Freeing the parent is thus sufficient to free both.
1403 static NTSTATUS
vfswrap_parent_pathname(struct vfs_handle_struct
*handle
,
1404 TALLOC_CTX
*mem_ctx
,
1405 const struct smb_filename
*smb_fname_in
,
1406 struct smb_filename
**parent_dir_out
,
1407 struct smb_filename
**atname_out
)
1409 struct smb_filename
*parent
= NULL
;
1410 struct smb_filename
*name
= NULL
;
1413 parent
= cp_smb_filename_nostream(mem_ctx
, smb_fname_in
);
1414 if (parent
== NULL
) {
1415 return NT_STATUS_NO_MEMORY
;
1417 SET_STAT_INVALID(parent
->st
);
1419 p
= strrchr_m(parent
->base_name
, '/'); /* Find final '/', if any */
1421 TALLOC_FREE(parent
->base_name
);
1422 parent
->base_name
= talloc_strdup(parent
, ".");
1423 if (parent
->base_name
== NULL
) {
1424 TALLOC_FREE(parent
);
1425 return NT_STATUS_NO_MEMORY
;
1427 p
= smb_fname_in
->base_name
;
1433 if (atname_out
== NULL
) {
1434 *parent_dir_out
= parent
;
1435 return NT_STATUS_OK
;
1438 name
= synthetic_smb_fname(
1441 smb_fname_in
->stream_name
,
1444 smb_fname_in
->flags
);
1446 return NT_STATUS_NO_MEMORY
;
1449 *parent_dir_out
= parent
;
1451 return NT_STATUS_OK
;
1455 * Implement the default fsctl operation.
1457 static bool vfswrap_logged_ioctl_message
= false;
1459 static NTSTATUS
vfswrap_fsctl(struct vfs_handle_struct
*handle
,
1460 struct files_struct
*fsp
,
1463 uint16_t req_flags
, /* Needed for UNICODE ... */
1464 const uint8_t *_in_data
,
1466 uint8_t **_out_data
,
1467 uint32_t max_out_len
,
1470 const char *in_data
= (const char *)_in_data
;
1471 char **out_data
= (char **)_out_data
;
1475 * Currently all fsctls operate on the base
1476 * file if given an alternate data stream.
1477 * Revisit this if we implement fsctls later
1478 * that need access to the ADS handle.
1480 fsp
= metadata_fsp(fsp
);
1483 case FSCTL_SET_SPARSE
:
1485 bool set_sparse
= true;
1487 if (in_len
>= 1 && in_data
[0] == 0) {
1491 status
= file_set_sparse(handle
->conn
, fsp
, set_sparse
);
1493 DEBUG(NT_STATUS_IS_OK(status
) ? 10 : 9,
1494 ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1495 smb_fname_str_dbg(fsp
->fsp_name
), set_sparse
,
1496 nt_errstr(status
)));
1501 case FSCTL_CREATE_OR_GET_OBJECT_ID
:
1503 unsigned char objid
[16];
1504 uint8_t *return_data
= NULL
;
1506 /* This should return the object-id on this file.
1507 * I think I'll make this be the inode+dev. JRA.
1510 DBG_DEBUG("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1513 *out_len
= MIN(max_out_len
, 64);
1515 /* Hmmm, will this cause problems if less data asked for? */
1516 return_data
= talloc_array(ctx
, uint8_t, 64);
1517 if (return_data
== NULL
) {
1518 return NT_STATUS_NO_MEMORY
;
1521 /* For backwards compatibility only store the dev/inode. */
1522 push_file_id_16(return_data
, &fsp
->file_id
);
1523 memcpy(return_data
+16,create_volume_objectid(fsp
->conn
,objid
),16);
1524 push_file_id_16(return_data
+ 32, &fsp
->file_id
);
1525 memset(return_data
+48, 0, 16);
1526 *_out_data
= return_data
;
1527 return NT_STATUS_OK
;
1530 case FSCTL_GET_REPARSE_POINT
:
1533 status
= fsctl_get_reparse_point(
1534 fsp
, ctx
, &tag
, _out_data
, max_out_len
, out_len
);
1538 case FSCTL_SET_REPARSE_POINT
:
1540 status
= fsctl_set_reparse_point(fsp
, ctx
, _in_data
, in_len
);
1544 case FSCTL_DELETE_REPARSE_POINT
:
1546 status
= fsctl_del_reparse_point(fsp
, ctx
, _in_data
, in_len
);
1550 case FSCTL_GET_SHADOW_COPY_DATA
:
1553 * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1554 * and return their volume names. If max_data_count is 16, then it is just
1555 * asking for the number of volumes and length of the combined names.
1557 * pdata is the data allocated by our caller, but that uses
1558 * total_data_count (which is 0 in our case) rather than max_data_count.
1559 * Allocate the correct amount and return the pointer to let
1560 * it be deallocated when we return.
1562 struct shadow_copy_data
*shadow_data
= NULL
;
1563 bool labels
= False
;
1564 uint32_t labels_data_count
= 0;
1566 char *cur_pdata
= NULL
;
1568 if (max_out_len
< 16) {
1569 DBG_ERR("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1571 return NT_STATUS_INVALID_PARAMETER
;
1574 if (max_out_len
> 16) {
1578 shadow_data
= talloc_zero(ctx
, struct shadow_copy_data
);
1579 if (shadow_data
== NULL
) {
1580 DBG_ERR("TALLOC_ZERO() failed!\n");
1581 return NT_STATUS_NO_MEMORY
;
1585 * Call the VFS routine to actually do the work.
1587 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp
, shadow_data
, labels
)!=0) {
1588 int log_lev
= DBGLVL_ERR
;
1590 /* broken module didn't set errno on error */
1591 status
= NT_STATUS_UNSUCCESSFUL
;
1593 status
= map_nt_error_from_unix(errno
);
1594 if (NT_STATUS_EQUAL(status
,
1595 NT_STATUS_NOT_SUPPORTED
)) {
1596 log_lev
= DBGLVL_INFO
;
1599 DEBUG(log_lev
, ("FSCTL_GET_SHADOW_COPY_DATA: "
1600 "connectpath %s, failed - %s.\n",
1601 fsp
->conn
->connectpath
,
1602 nt_errstr(status
)));
1603 TALLOC_FREE(shadow_data
);
1607 labels_data_count
= (shadow_data
->num_volumes
* 2 *
1608 sizeof(SHADOW_COPY_LABEL
)) + 2;
1613 *out_len
= 12 + labels_data_count
;
1616 if (max_out_len
< *out_len
) {
1617 DBG_ERR("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1618 max_out_len
, *out_len
);
1619 TALLOC_FREE(shadow_data
);
1620 return NT_STATUS_BUFFER_TOO_SMALL
;
1623 cur_pdata
= talloc_zero_array(ctx
, char, *out_len
);
1624 if (cur_pdata
== NULL
) {
1625 TALLOC_FREE(shadow_data
);
1626 return NT_STATUS_NO_MEMORY
;
1629 *out_data
= cur_pdata
;
1631 /* num_volumes 4 bytes */
1632 SIVAL(cur_pdata
, 0, shadow_data
->num_volumes
);
1635 /* num_labels 4 bytes */
1636 SIVAL(cur_pdata
, 4, shadow_data
->num_volumes
);
1639 /* needed_data_count 4 bytes */
1640 SIVAL(cur_pdata
, 8, labels_data_count
);
1644 DBG_DEBUG("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1645 shadow_data
->num_volumes
, fsp_str_dbg(fsp
));
1646 if (labels
&& shadow_data
->labels
) {
1647 for (i
=0; i
<shadow_data
->num_volumes
; i
++) {
1649 status
= srvstr_push(cur_pdata
, req_flags
,
1650 cur_pdata
, shadow_data
->labels
[i
],
1651 2 * sizeof(SHADOW_COPY_LABEL
),
1652 STR_UNICODE
|STR_TERMINATE
, &len
);
1653 if (!NT_STATUS_IS_OK(status
)) {
1654 TALLOC_FREE(*out_data
);
1655 TALLOC_FREE(shadow_data
);
1658 cur_pdata
+= 2 * sizeof(SHADOW_COPY_LABEL
);
1659 DEBUGADD(DBGLVL_DEBUG
,("Label[%u]: '%s'\n",i
,shadow_data
->labels
[i
]));
1663 TALLOC_FREE(shadow_data
);
1665 return NT_STATUS_OK
;
1668 case FSCTL_FIND_FILES_BY_SID
:
1670 /* pretend this succeeded -
1672 * we have to send back a list with all files owned by this SID
1674 * but I have to check that --metze
1678 struct dom_sid_buf buf
;
1682 DBG_DEBUG("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1686 /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1687 return NT_STATUS_INVALID_PARAMETER
;
1690 sid_len
= MIN(in_len
- 4,SID_MAX_SIZE
);
1692 /* unknown 4 bytes: this is not the length of the sid :-( */
1693 /*unknown = IVAL(pdata,0);*/
1695 ret
= sid_parse(_in_data
+ 4, sid_len
, &sid
);
1697 return NT_STATUS_INVALID_PARAMETER
;
1699 DEBUGADD(DBGLVL_DEBUG
, ("for SID: %s\n",
1700 dom_sid_str_buf(&sid
, &buf
)));
1702 if (!sid_to_uid(&sid
, &uid
)) {
1703 DBG_ERR("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1704 dom_sid_str_buf(&sid
, &buf
),
1705 (unsigned long)sid_len
);
1709 /* we can take a look at the find source :-)
1711 * find ./ -uid $uid -name '*' is what we need here
1714 * and send 4bytes len and then NULL terminated unicode strings
1717 * but I don't know how to deal with the paged results
1718 * (maybe we can hang the result anywhere in the fsp struct)
1720 * but I don't know how to deal with the paged results
1721 * (maybe we can hang the result anywhere in the fsp struct)
1723 * we don't send all files at once
1724 * and at the next we should *not* start from the beginning,
1725 * so we have to cache the result
1730 /* this works for now... */
1731 return NT_STATUS_OK
;
1734 case FSCTL_QUERY_ALLOCATED_RANGES
:
1736 /* FIXME: This is just a dummy reply, telling that all of the
1737 * file is allocated. MKS cp needs that.
1738 * Adding the real allocated ranges via FIEMAP on Linux
1739 * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1740 * this FSCTL correct for sparse files.
1742 uint64_t offset
, length
;
1743 char *out_data_tmp
= NULL
;
1746 DBG_ERR("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1748 return NT_STATUS_INVALID_PARAMETER
;
1751 if (max_out_len
< 16) {
1752 DBG_ERR("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1754 return NT_STATUS_INVALID_PARAMETER
;
1757 offset
= BVAL(in_data
,0);
1758 length
= BVAL(in_data
,8);
1760 if (offset
+ length
< offset
) {
1761 /* No 64-bit integer wrap. */
1762 return NT_STATUS_INVALID_PARAMETER
;
1765 /* Shouldn't this be SMB_VFS_STAT ... ? */
1766 status
= vfs_stat_fsp(fsp
);
1767 if (!NT_STATUS_IS_OK(status
)) {
1772 out_data_tmp
= talloc_array(ctx
, char, *out_len
);
1773 if (out_data_tmp
== NULL
) {
1774 DBG_DEBUG("unable to allocate memory for response\n");
1775 return NT_STATUS_NO_MEMORY
;
1778 if (offset
> fsp
->fsp_name
->st
.st_ex_size
||
1779 fsp
->fsp_name
->st
.st_ex_size
== 0 ||
1781 memset(out_data_tmp
, 0, *out_len
);
1783 uint64_t end
= offset
+ length
;
1784 end
= MIN(end
, fsp
->fsp_name
->st
.st_ex_size
);
1785 SBVAL(out_data_tmp
, 0, 0);
1786 SBVAL(out_data_tmp
, 8, end
);
1789 *out_data
= out_data_tmp
;
1791 return NT_STATUS_OK
;
1794 case FSCTL_IS_VOLUME_DIRTY
:
1796 DBG_DEBUG("FSCTL_IS_VOLUME_DIRTY: called on %s "
1797 "(but remotely not supported)\n", fsp_fnum_dbg(fsp
));
1799 * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1800 * says we have to respond with NT_STATUS_INVALID_PARAMETER
1802 return NT_STATUS_INVALID_PARAMETER
;
1807 * Only print once ... unfortunately there could be lots of
1808 * different FSCTLs that are called.
1810 if (!vfswrap_logged_ioctl_message
) {
1811 vfswrap_logged_ioctl_message
= true;
1812 DBG_NOTICE("%s (0x%x): Currently not implemented.\n",
1813 __func__
, function
);
1817 return NT_STATUS_NOT_SUPPORTED
;
1820 static bool vfswrap_is_offline(struct connection_struct
*conn
,
1821 const struct smb_filename
*fname
);
1823 struct vfswrap_get_dos_attributes_state
{
1824 struct vfs_aio_state aio_state
;
1825 connection_struct
*conn
;
1826 TALLOC_CTX
*mem_ctx
;
1827 struct tevent_context
*ev
;
1828 files_struct
*dir_fsp
;
1829 struct smb_filename
*smb_fname
;
1834 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
);
1836 static struct tevent_req
*vfswrap_get_dos_attributes_send(
1837 TALLOC_CTX
*mem_ctx
,
1838 struct tevent_context
*ev
,
1839 struct vfs_handle_struct
*handle
,
1840 files_struct
*dir_fsp
,
1841 struct smb_filename
*smb_fname
)
1843 struct tevent_req
*req
= NULL
;
1844 struct tevent_req
*subreq
= NULL
;
1845 struct vfswrap_get_dos_attributes_state
*state
= NULL
;
1847 SMB_ASSERT(!is_named_stream(smb_fname
));
1849 req
= tevent_req_create(mem_ctx
, &state
,
1850 struct vfswrap_get_dos_attributes_state
);
1855 *state
= (struct vfswrap_get_dos_attributes_state
) {
1856 .conn
= dir_fsp
->conn
,
1860 .smb_fname
= smb_fname
,
1863 if (!lp_store_dos_attributes(SNUM(dir_fsp
->conn
))) {
1864 DBG_ERR("%s: \"smbd async dosmode\" enabled, but "
1865 "\"store dos attributes\" is disabled\n",
1866 dir_fsp
->conn
->connectpath
);
1867 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1868 return tevent_req_post(req
, ev
);
1871 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1875 SAMBA_XATTR_DOS_ATTRIB
,
1877 if (tevent_req_nomem(subreq
, req
)) {
1878 return tevent_req_post(req
, ev
);
1880 tevent_req_set_callback(subreq
,
1881 vfswrap_get_dos_attributes_getxattr_done
,
1887 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req
*subreq
)
1889 struct tevent_req
*req
=
1890 tevent_req_callback_data(subreq
,
1892 struct vfswrap_get_dos_attributes_state
*state
=
1893 tevent_req_data(req
,
1894 struct vfswrap_get_dos_attributes_state
);
1896 DATA_BLOB blob
= {0};
1898 char *tofree
= NULL
;
1899 char pathbuf
[PATH_MAX
+1];
1901 struct smb_filename smb_fname
;
1905 xattr_size
= SMB_VFS_GETXATTRAT_RECV(subreq
,
1909 TALLOC_FREE(subreq
);
1910 if (xattr_size
== -1) {
1911 status
= map_nt_error_from_unix(state
->aio_state
.error
);
1913 if (state
->as_root
) {
1914 tevent_req_nterror(req
, status
);
1917 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1918 tevent_req_nterror(req
, status
);
1922 state
->as_root
= true;
1925 subreq
= SMB_VFS_GETXATTRAT_SEND(state
,
1929 SAMBA_XATTR_DOS_ATTRIB
,
1932 if (tevent_req_nomem(subreq
, req
)) {
1935 tevent_req_set_callback(subreq
,
1936 vfswrap_get_dos_attributes_getxattr_done
,
1941 blob
.length
= xattr_size
;
1943 status
= parse_dos_attribute_blob(state
->smb_fname
,
1946 if (!NT_STATUS_IS_OK(status
)) {
1947 tevent_req_nterror(req
, status
);
1951 pathlen
= full_path_tos(state
->dir_fsp
->fsp_name
->base_name
,
1952 state
->smb_fname
->base_name
,
1957 if (pathlen
== -1) {
1958 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
1962 smb_fname
= (struct smb_filename
) {
1964 .st
= state
->smb_fname
->st
,
1965 .flags
= state
->smb_fname
->flags
,
1966 .twrp
= state
->smb_fname
->twrp
,
1969 offline
= vfswrap_is_offline(state
->conn
, &smb_fname
);
1971 state
->dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
1973 TALLOC_FREE(tofree
);
1975 tevent_req_done(req
);
1979 static NTSTATUS
vfswrap_get_dos_attributes_recv(struct tevent_req
*req
,
1980 struct vfs_aio_state
*aio_state
,
1983 struct vfswrap_get_dos_attributes_state
*state
=
1984 tevent_req_data(req
,
1985 struct vfswrap_get_dos_attributes_state
);
1988 if (tevent_req_is_nterror(req
, &status
)) {
1989 tevent_req_received(req
);
1993 *aio_state
= state
->aio_state
;
1994 *dosmode
= state
->dosmode
;
1995 tevent_req_received(req
);
1996 return NT_STATUS_OK
;
1999 static NTSTATUS
vfswrap_fget_dos_attributes(struct vfs_handle_struct
*handle
,
2000 struct files_struct
*fsp
,
2005 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
2007 offline
= vfswrap_is_offline(handle
->conn
, fsp
->fsp_name
);
2009 *dosmode
|= FILE_ATTRIBUTE_OFFLINE
;
2012 return fget_ea_dos_attribute(fsp
, dosmode
);
2015 static NTSTATUS
vfswrap_fset_dos_attributes(struct vfs_handle_struct
*handle
,
2016 struct files_struct
*fsp
,
2019 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
2021 return set_ea_dos_attribute(handle
->conn
, fsp
->fsp_name
, dosmode
);
2024 static struct vfs_offload_ctx
*vfswrap_offload_ctx
;
2026 struct vfswrap_offload_read_state
{
2030 static struct tevent_req
*vfswrap_offload_read_send(
2031 TALLOC_CTX
*mem_ctx
,
2032 struct tevent_context
*ev
,
2033 struct vfs_handle_struct
*handle
,
2034 struct files_struct
*fsp
,
2040 struct tevent_req
*req
= NULL
;
2041 struct vfswrap_offload_read_state
*state
= NULL
;
2044 req
= tevent_req_create(mem_ctx
, &state
,
2045 struct vfswrap_offload_read_state
);
2050 status
= vfs_offload_token_ctx_init(fsp
->conn
->sconn
->client
,
2051 &vfswrap_offload_ctx
);
2052 if (tevent_req_nterror(req
, status
)) {
2053 return tevent_req_post(req
, ev
);
2056 if (fsctl
!= FSCTL_SRV_REQUEST_RESUME_KEY
&&
2057 fsctl
!= FSCTL_DUP_EXTENTS_TO_FILE
)
2059 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
2060 return tevent_req_post(req
, ev
);
2063 if (fsctl
== FSCTL_DUP_EXTENTS_TO_FILE
&&
2064 !(fsp
->conn
->fs_capabilities
& FILE_SUPPORTS_BLOCK_REFCOUNTING
))
2066 tevent_req_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
2067 return tevent_req_post(req
, ev
);
2070 status
= vfs_offload_token_create_blob(state
, fsp
, fsctl
,
2072 if (tevent_req_nterror(req
, status
)) {
2073 return tevent_req_post(req
, ev
);
2076 status
= vfs_offload_token_db_store_fsp(vfswrap_offload_ctx
, fsp
,
2078 if (tevent_req_nterror(req
, status
)) {
2079 return tevent_req_post(req
, ev
);
2082 tevent_req_done(req
);
2083 return tevent_req_post(req
, ev
);
2086 static NTSTATUS
vfswrap_offload_read_recv(struct tevent_req
*req
,
2087 struct vfs_handle_struct
*handle
,
2088 TALLOC_CTX
*mem_ctx
,
2093 struct vfswrap_offload_read_state
*state
= tevent_req_data(
2094 req
, struct vfswrap_offload_read_state
);
2097 if (tevent_req_is_nterror(req
, &status
)) {
2098 tevent_req_received(req
);
2104 token
->length
= state
->token
.length
;
2105 token
->data
= talloc_move(mem_ctx
, &state
->token
.data
);
2107 tevent_req_received(req
);
2108 return NT_STATUS_OK
;
2111 struct vfswrap_offload_write_state
{
2113 bool read_lck_locked
;
2114 bool write_lck_locked
;
2116 struct tevent_context
*src_ev
;
2117 struct files_struct
*src_fsp
;
2119 struct tevent_context
*dst_ev
;
2120 struct files_struct
*dst_fsp
;
2125 size_t next_io_size
;
2128 static void vfswrap_offload_write_cleanup(struct tevent_req
*req
,
2129 enum tevent_req_state req_state
)
2131 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2132 req
, struct vfswrap_offload_write_state
);
2135 if (state
->dst_fsp
== NULL
) {
2139 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2141 state
->dst_fsp
= NULL
;
2144 static NTSTATUS
vfswrap_offload_fast_copy(struct tevent_req
*req
, int fsctl
);
2145 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
);
2147 static struct tevent_req
*vfswrap_offload_write_send(
2148 struct vfs_handle_struct
*handle
,
2149 TALLOC_CTX
*mem_ctx
,
2150 struct tevent_context
*ev
,
2153 off_t transfer_offset
,
2154 struct files_struct
*dest_fsp
,
2158 struct tevent_req
*req
;
2159 struct vfswrap_offload_write_state
*state
= NULL
;
2160 /* off_t is signed! */
2161 off_t max_offset
= INT64_MAX
- to_copy
;
2162 off_t num
= to_copy
;
2163 files_struct
*src_fsp
= NULL
;
2167 req
= tevent_req_create(mem_ctx
, &state
,
2168 struct vfswrap_offload_write_state
);
2173 *state
= (struct vfswrap_offload_write_state
) {
2175 .src_off
= transfer_offset
,
2177 .dst_fsp
= dest_fsp
,
2178 .dst_off
= dest_off
,
2180 .remaining
= to_copy
,
2183 status
= vfs_offload_token_ctx_init(handle
->conn
->sconn
->client
,
2184 &vfswrap_offload_ctx
);
2185 if (tevent_req_nterror(req
, status
)) {
2186 return tevent_req_post(req
, ev
);
2189 tevent_req_set_cleanup_fn(req
, vfswrap_offload_write_cleanup
);
2192 case FSCTL_DUP_EXTENTS_TO_FILE
:
2195 case FSCTL_SRV_COPYCHUNK
:
2196 case FSCTL_SRV_COPYCHUNK_WRITE
:
2197 num
= MIN(to_copy
, COPYCHUNK_MAX_TOTAL_LEN
);
2200 case FSCTL_OFFLOAD_WRITE
:
2201 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2202 return tevent_req_post(req
, ev
);
2205 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2206 return tevent_req_post(req
, ev
);
2210 tevent_req_done(req
);
2211 return tevent_req_post(req
, ev
);
2214 if (state
->src_off
> max_offset
) {
2216 * Protect integer checks below.
2218 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2219 return tevent_req_post(req
, ev
);
2221 if (state
->src_off
< 0) {
2223 * Protect integer checks below.
2225 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2226 return tevent_req_post(req
, ev
);
2228 if (state
->dst_off
> max_offset
) {
2230 * Protect integer checks below.
2232 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2233 return tevent_req_post(req
, ev
);
2235 if (state
->dst_off
< 0) {
2237 * Protect integer checks below.
2239 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2240 return tevent_req_post(req
, ev
);
2243 status
= vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx
,
2245 if (tevent_req_nterror(req
, status
)) {
2246 return tevent_req_post(req
, ev
);
2249 DBG_DEBUG("server side copy (%s) of length %" PRIu64
"\n",
2250 fsctl
== FSCTL_DUP_EXTENTS_TO_FILE
? "reflink" : "chunk",
2253 status
= vfs_offload_token_check_handles(fsctl
, src_fsp
, dest_fsp
);
2254 if (!NT_STATUS_IS_OK(status
)) {
2255 tevent_req_nterror(req
, status
);
2256 return tevent_req_post(req
, ev
);
2259 ok
= change_to_user_and_service_by_fsp(src_fsp
);
2261 tevent_req_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2262 return tevent_req_post(req
, ev
);
2265 state
->src_ev
= src_fsp
->conn
->sconn
->ev_ctx
;
2266 state
->src_fsp
= src_fsp
;
2268 status
= vfs_stat_fsp(src_fsp
);
2269 if (tevent_req_nterror(req
, status
)) {
2270 return tevent_req_post(req
, ev
);
2273 if (src_fsp
->fsp_name
->st
.st_ex_size
< state
->src_off
+ to_copy
) {
2275 * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2276 * If the SourceOffset or SourceOffset + Length extends beyond
2277 * the end of file, the server SHOULD<240> treat this as a
2278 * STATUS_END_OF_FILE error.
2280 * <240> Section 3.3.5.15.6: Windows servers will return
2281 * STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2283 tevent_req_nterror(req
, NT_STATUS_INVALID_VIEW_SIZE
);
2284 return tevent_req_post(req
, ev
);
2287 status
= vfswrap_offload_fast_copy(req
, fsctl
);
2288 if (NT_STATUS_IS_OK(status
)) {
2289 tevent_req_done(req
);
2290 return tevent_req_post(req
, ev
);
2292 if (!NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
2293 tevent_req_nterror(req
, status
);
2294 return tevent_req_post(req
, ev
);
2297 state
->buf
= talloc_array(state
, uint8_t, num
);
2298 if (tevent_req_nomem(state
->buf
, req
)) {
2299 return tevent_req_post(req
, ev
);
2302 status
= vfswrap_offload_write_loop(req
);
2303 if (!NT_STATUS_IS_OK(status
)) {
2304 tevent_req_nterror(req
, status
);
2305 return tevent_req_post(req
, ev
);
2311 static NTSTATUS
vfswrap_offload_fast_copy(struct tevent_req
*req
, int fsctl
)
2313 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2314 req
, struct vfswrap_offload_write_state
);
2315 struct lock_struct lck
;
2320 static bool try_copy_file_range
= true;
2322 same_file
= file_id_equal(&state
->src_fsp
->file_id
,
2323 &state
->dst_fsp
->file_id
);
2325 sys_io_ranges_overlap(state
->remaining
,
2330 if (fsctl
== FSCTL_DUP_EXTENTS_TO_FILE
) {
2331 return NT_STATUS_INVALID_PARAMETER
;
2333 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2336 if (fsp_is_alternate_stream(state
->src_fsp
) ||
2337 fsp_is_alternate_stream(state
->dst_fsp
))
2339 if (fsctl
== FSCTL_DUP_EXTENTS_TO_FILE
) {
2340 return NT_STATUS_NOT_SUPPORTED
;
2342 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2345 if (fsctl
== FSCTL_DUP_EXTENTS_TO_FILE
) {
2348 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2350 return NT_STATUS_INTERNAL_ERROR
;
2353 ret
= copy_reflink(fsp_get_io_fd(state
->src_fsp
),
2355 fsp_get_io_fd(state
->dst_fsp
),
2359 DBG_INFO("copy_reflink() failed: %s\n", strerror(errno
));
2360 return map_nt_error_from_unix(errno
);
2363 state
->copied
= state
->to_copy
;
2367 if (!try_copy_file_range
) {
2368 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
2371 init_strict_lock_struct(state
->src_fsp
,
2372 state
->src_fsp
->op
->global
->open_persistent_id
,
2376 lp_posix_cifsu_locktype(state
->src_fsp
),
2379 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2383 return NT_STATUS_FILE_LOCK_CONFLICT
;
2386 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2388 return NT_STATUS_INTERNAL_ERROR
;
2391 init_strict_lock_struct(state
->dst_fsp
,
2392 state
->dst_fsp
->op
->global
->open_persistent_id
,
2396 lp_posix_cifsu_locktype(state
->dst_fsp
),
2399 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2403 return NT_STATUS_FILE_LOCK_CONFLICT
;
2406 while (state
->remaining
> 0) {
2407 nwritten
= copy_file_range(fsp_get_io_fd(state
->src_fsp
),
2409 fsp_get_io_fd(state
->dst_fsp
),
2413 if (nwritten
== -1) {
2414 DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2415 "n [%jd] failed: %s\n",
2416 fsp_str_dbg(state
->src_fsp
),
2417 (intmax_t)state
->src_off
,
2418 fsp_str_dbg(state
->dst_fsp
),
2419 (intmax_t)state
->dst_off
,
2420 (intmax_t)state
->remaining
,
2425 try_copy_file_range
= false;
2426 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2429 status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
2432 status
= map_nt_error_from_unix(errno
);
2433 if (NT_STATUS_EQUAL(
2435 NT_STATUS_MORE_PROCESSING_REQUIRED
))
2437 /* Avoid triggering the fallback */
2438 status
= NT_STATUS_INTERNAL_ERROR
;
2445 if (state
->remaining
< nwritten
) {
2446 DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2447 "n [%jd] remaining [%jd]\n",
2448 fsp_str_dbg(state
->src_fsp
),
2449 fsp_str_dbg(state
->dst_fsp
),
2451 (intmax_t)state
->remaining
);
2452 return NT_STATUS_INTERNAL_ERROR
;
2455 if (nwritten
== 0) {
2458 state
->copied
+= nwritten
;
2459 state
->remaining
-= nwritten
;
2464 * Tell the req cleanup function there's no need to call
2465 * change_to_user_and_service_by_fsp() on the dst handle.
2467 state
->dst_fsp
= NULL
;
2468 return NT_STATUS_OK
;
2471 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
);
2473 static NTSTATUS
vfswrap_offload_write_loop(struct tevent_req
*req
)
2475 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2476 req
, struct vfswrap_offload_write_state
);
2477 struct tevent_req
*subreq
= NULL
;
2478 struct lock_struct read_lck
;
2482 * This is called under the context of state->src_fsp.
2485 state
->next_io_size
= MIN(state
->remaining
, talloc_array_length(state
->buf
));
2487 init_strict_lock_struct(state
->src_fsp
,
2488 state
->src_fsp
->op
->global
->open_persistent_id
,
2490 state
->next_io_size
,
2492 lp_posix_cifsu_locktype(state
->src_fsp
),
2495 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->src_fsp
->conn
,
2499 return NT_STATUS_FILE_LOCK_CONFLICT
;
2502 subreq
= SMB_VFS_PREAD_SEND(state
,
2506 state
->next_io_size
,
2508 if (subreq
== NULL
) {
2509 return NT_STATUS_NO_MEMORY
;
2511 tevent_req_set_callback(subreq
, vfswrap_offload_write_read_done
, req
);
2513 return NT_STATUS_OK
;
2516 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
);
2518 static void vfswrap_offload_write_read_done(struct tevent_req
*subreq
)
2520 struct tevent_req
*req
= tevent_req_callback_data(
2521 subreq
, struct tevent_req
);
2522 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2523 req
, struct vfswrap_offload_write_state
);
2524 struct vfs_aio_state aio_state
;
2525 struct lock_struct write_lck
;
2529 nread
= SMB_VFS_PREAD_RECV(subreq
, &aio_state
);
2530 TALLOC_FREE(subreq
);
2532 DBG_ERR("read failed: %s\n", strerror(aio_state
.error
));
2533 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2536 if (nread
!= state
->next_io_size
) {
2537 DBG_ERR("Short read, only %zd of %zu\n",
2538 nread
, state
->next_io_size
);
2539 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2543 state
->src_off
+= nread
;
2545 ok
= change_to_user_and_service_by_fsp(state
->dst_fsp
);
2547 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2551 init_strict_lock_struct(state
->dst_fsp
,
2552 state
->dst_fsp
->op
->global
->open_persistent_id
,
2554 state
->next_io_size
,
2556 lp_posix_cifsu_locktype(state
->dst_fsp
),
2559 ok
= SMB_VFS_STRICT_LOCK_CHECK(state
->dst_fsp
->conn
,
2563 tevent_req_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
2567 subreq
= SMB_VFS_PWRITE_SEND(state
,
2571 state
->next_io_size
,
2573 if (subreq
== NULL
) {
2574 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
2577 tevent_req_set_callback(subreq
, vfswrap_offload_write_write_done
, req
);
2580 static void vfswrap_offload_write_write_done(struct tevent_req
*subreq
)
2582 struct tevent_req
*req
= tevent_req_callback_data(
2583 subreq
, struct tevent_req
);
2584 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2585 req
, struct vfswrap_offload_write_state
);
2586 struct vfs_aio_state aio_state
;
2591 nwritten
= SMB_VFS_PWRITE_RECV(subreq
, &aio_state
);
2592 TALLOC_FREE(subreq
);
2593 if (nwritten
== -1) {
2594 DBG_ERR("write failed: %s\n", strerror(aio_state
.error
));
2595 tevent_req_nterror(req
, map_nt_error_from_unix(aio_state
.error
));
2598 if (nwritten
!= state
->next_io_size
) {
2599 DBG_ERR("Short write, only %zd of %zu\n", nwritten
, state
->next_io_size
);
2600 tevent_req_nterror(req
, NT_STATUS_IO_DEVICE_ERROR
);
2604 state
->dst_off
+= nwritten
;
2606 if (state
->remaining
< nwritten
) {
2607 /* Paranoia check */
2608 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2611 state
->copied
+= nwritten
;
2612 state
->remaining
-= nwritten
;
2613 if (state
->remaining
== 0) {
2614 tevent_req_done(req
);
2618 ok
= change_to_user_and_service_by_fsp(state
->src_fsp
);
2620 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2624 status
= vfswrap_offload_write_loop(req
);
2625 if (!NT_STATUS_IS_OK(status
)) {
2626 tevent_req_nterror(req
, status
);
2633 static NTSTATUS
vfswrap_offload_write_recv(struct vfs_handle_struct
*handle
,
2634 struct tevent_req
*req
,
2637 struct vfswrap_offload_write_state
*state
= tevent_req_data(
2638 req
, struct vfswrap_offload_write_state
);
2641 if (tevent_req_is_nterror(req
, &status
)) {
2642 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status
));
2644 tevent_req_received(req
);
2648 *copied
= state
->copied
;
2649 DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied
);
2650 tevent_req_received(req
);
2652 return NT_STATUS_OK
;
2655 static NTSTATUS
vfswrap_fget_compression(struct vfs_handle_struct
*handle
,
2656 TALLOC_CTX
*mem_ctx
,
2657 struct files_struct
*fsp
,
2658 uint16_t *_compression_fmt
)
2660 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2663 static NTSTATUS
vfswrap_set_compression(struct vfs_handle_struct
*handle
,
2664 TALLOC_CTX
*mem_ctx
,
2665 struct files_struct
*fsp
,
2666 uint16_t compression_fmt
)
2668 return NT_STATUS_INVALID_DEVICE_REQUEST
;
2671 /********************************************************************
2672 Given a stat buffer return the allocated size on disk, taking into
2673 account sparse files.
2674 ********************************************************************/
2675 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct
*handle
,
2676 struct files_struct
*fsp
,
2677 const SMB_STRUCT_STAT
*sbuf
)
2681 START_PROFILE(syscall_get_alloc_size
);
2683 if(S_ISDIR(sbuf
->st_ex_mode
)) {
2688 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2689 /* The type of st_blocksize is blkcnt_t which *MUST* be
2690 signed (according to POSIX) and can be less than 64-bits.
2691 Ensure when we're converting to 64 bits wide we don't
2693 #if defined(SIZEOF_BLKCNT_T_8)
2694 result
= (uint64_t)STAT_ST_BLOCKSIZE
* (uint64_t)sbuf
->st_ex_blocks
;
2695 #elif defined(SIZEOF_BLKCNT_T_4)
2697 uint64_t bs
= ((uint64_t)sbuf
->st_ex_blocks
) & 0xFFFFFFFFLL
;
2698 result
= (uint64_t)STAT_ST_BLOCKSIZE
* bs
;
2701 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2705 * Some file systems do not allocate a block for very
2706 * small files. But for non-empty file should report a
2710 uint64_t filesize
= get_file_size_stat(sbuf
);
2712 result
= MIN((uint64_t)STAT_ST_BLOCKSIZE
, filesize
);
2716 result
= get_file_size_stat(sbuf
);
2719 if (fsp
&& fsp
->initial_allocation_size
)
2720 result
= MAX(result
,fsp
->initial_allocation_size
);
2722 result
= smb_roundup(handle
->conn
, result
);
2725 END_PROFILE(syscall_get_alloc_size
);
2729 static int vfswrap_unlinkat(vfs_handle_struct
*handle
,
2730 struct files_struct
*dirfsp
,
2731 const struct smb_filename
*smb_fname
,
2736 START_PROFILE(syscall_unlinkat
);
2738 SMB_ASSERT(!is_named_stream(smb_fname
));
2740 result
= unlinkat(fsp_get_pathref_fd(dirfsp
),
2741 smb_fname
->base_name
,
2744 END_PROFILE(syscall_unlinkat
);
2748 static int vfswrap_fchmod(vfs_handle_struct
*handle
, files_struct
*fsp
, mode_t mode
)
2752 START_PROFILE(syscall_fchmod
);
2754 if (!fsp
->fsp_flags
.is_pathref
) {
2755 result
= fchmod(fsp_get_io_fd(fsp
), mode
);
2756 END_PROFILE(syscall_fchmod
);
2760 if (fsp
->fsp_flags
.have_proc_fds
) {
2761 int fd
= fsp_get_pathref_fd(fsp
);
2762 struct sys_proc_fd_path_buf buf
;
2764 result
= chmod(sys_proc_fd_path(fd
, &buf
), mode
);
2766 END_PROFILE(syscall_fchmod
);
2771 * This is no longer a handle based call.
2773 result
= chmod(fsp
->fsp_name
->base_name
, mode
);
2775 END_PROFILE(syscall_fchmod
);
2779 static int vfswrap_fchown(vfs_handle_struct
*handle
, files_struct
*fsp
, uid_t uid
, gid_t gid
)
2784 START_PROFILE(syscall_fchown
);
2785 if (!fsp
->fsp_flags
.is_pathref
) {
2786 result
= fchown(fsp_get_io_fd(fsp
), uid
, gid
);
2787 END_PROFILE(syscall_fchown
);
2791 if (fsp
->fsp_flags
.have_proc_fds
) {
2792 int fd
= fsp_get_pathref_fd(fsp
);
2793 struct sys_proc_fd_path_buf buf
;
2795 result
= chown(sys_proc_fd_path(fd
, &buf
), uid
, gid
);
2797 END_PROFILE(syscall_fchown
);
2802 * This is no longer a handle based call.
2804 result
= chown(fsp
->fsp_name
->base_name
, uid
, gid
);
2805 END_PROFILE(syscall_fchown
);
2813 static int vfswrap_lchown(vfs_handle_struct
*handle
,
2814 const struct smb_filename
*smb_fname
,
2820 START_PROFILE(syscall_lchown
);
2821 result
= lchown(smb_fname
->base_name
, uid
, gid
);
2822 END_PROFILE(syscall_lchown
);
2826 static int vfswrap_chdir(vfs_handle_struct
*handle
,
2827 const struct smb_filename
*smb_fname
)
2831 START_PROFILE(syscall_chdir
);
2832 result
= chdir(smb_fname
->base_name
);
2833 END_PROFILE(syscall_chdir
);
2837 static struct smb_filename
*vfswrap_getwd(vfs_handle_struct
*handle
,
2841 struct smb_filename
*smb_fname
= NULL
;
2843 START_PROFILE(syscall_getwd
);
2844 result
= sys_getwd();
2845 END_PROFILE(syscall_getwd
);
2847 if (result
== NULL
) {
2850 smb_fname
= synthetic_smb_fname(ctx
,
2857 * sys_getwd() *always* returns malloced memory.
2858 * We must free here to avoid leaks:
2859 * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2865 /*********************************************************************
2866 nsec timestamp resolution call. Convert down to whatever the underlying
2867 system will support.
2868 **********************************************************************/
2870 static int vfswrap_fntimes(vfs_handle_struct
*handle
,
2872 struct smb_file_time
*ft
)
2875 struct timespec ts
[2];
2876 struct timespec
*times
= NULL
;
2878 START_PROFILE(syscall_fntimes
);
2880 if (fsp_is_alternate_stream(fsp
)) {
2886 if (is_omit_timespec(&ft
->atime
)) {
2887 ft
->atime
= fsp
->fsp_name
->st
.st_ex_atime
;
2890 if (is_omit_timespec(&ft
->mtime
)) {
2891 ft
->mtime
= fsp
->fsp_name
->st
.st_ex_mtime
;
2894 if (!is_omit_timespec(&ft
->create_time
)) {
2895 set_create_timespec_ea(fsp
,
2899 if ((timespec_compare(&ft
->atime
,
2900 &fsp
->fsp_name
->st
.st_ex_atime
) == 0) &&
2901 (timespec_compare(&ft
->mtime
,
2902 &fsp
->fsp_name
->st
.st_ex_mtime
) == 0)) {
2914 if (!fsp
->fsp_flags
.is_pathref
) {
2915 result
= futimens(fsp_get_io_fd(fsp
), times
);
2919 if (fsp
->fsp_flags
.have_proc_fds
) {
2920 int fd
= fsp_get_pathref_fd(fsp
);
2921 struct sys_proc_fd_path_buf buf
;
2923 result
= utimensat(AT_FDCWD
,
2924 sys_proc_fd_path(fd
, &buf
),
2932 * The fd is a pathref (opened with O_PATH) and there isn't fd to
2933 * path translation mechanism. Fallback to path based call.
2935 result
= utimensat(AT_FDCWD
, fsp
->fsp_name
->base_name
, times
, 0);
2938 END_PROFILE(syscall_fntimes
);
2944 /*********************************************************************
2945 A version of ftruncate that will write the space on disk if strict
2947 **********************************************************************/
2949 static int strict_allocate_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
2951 off_t space_to_write
;
2952 uint64_t space_avail
;
2953 uint64_t bsize
,dfree
,dsize
;
2956 SMB_STRUCT_STAT
*pst
;
2959 ok
= vfs_valid_pwrite_range(len
, 0);
2965 status
= vfs_stat_fsp(fsp
);
2966 if (!NT_STATUS_IS_OK(status
)) {
2969 pst
= &fsp
->fsp_name
->st
;
2972 if (S_ISFIFO(pst
->st_ex_mode
))
2976 if (pst
->st_ex_size
== len
)
2979 /* Shrink - just ftruncate. */
2980 if (pst
->st_ex_size
> len
)
2981 return ftruncate(fsp_get_io_fd(fsp
), len
);
2983 space_to_write
= len
- pst
->st_ex_size
;
2985 /* for allocation try fallocate first. This can fail on some
2986 platforms e.g. when the filesystem doesn't support it and no
2987 emulation is being done by the libc (like on AIX with JFS1). In that
2988 case we do our own emulation. fallocate implementations can
2989 return ENOTSUP or EINVAL in cases like that. */
2990 ret
= SMB_VFS_FALLOCATE(fsp
, 0, pst
->st_ex_size
, space_to_write
);
2991 if (ret
== -1 && errno
== ENOSPC
) {
2997 DBG_DEBUG("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2998 "error %d. Falling back to slow manual allocation\n", errno
);
3000 /* available disk space is enough or not? */
3002 get_dfree_info(fsp
->conn
, fsp
->fsp_name
, &bsize
, &dfree
, &dsize
);
3003 /* space_avail is 1k blocks */
3004 if (space_avail
== (uint64_t)-1 ||
3005 ((uint64_t)space_to_write
/1024 > space_avail
) ) {
3010 /* Write out the real space on disk. */
3011 ret
= vfs_slow_fallocate(fsp
, pst
->st_ex_size
, space_to_write
);
3019 static int vfswrap_ftruncate(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t len
)
3022 SMB_STRUCT_STAT
*pst
;
3026 START_PROFILE(syscall_ftruncate
);
3028 if (lp_strict_allocate(SNUM(fsp
->conn
)) && !fsp
->fsp_flags
.is_sparse
) {
3029 result
= strict_allocate_ftruncate(handle
, fsp
, len
);
3030 END_PROFILE(syscall_ftruncate
);
3034 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
3035 ftruncate if the system supports it. Then I discovered that
3036 you can have some filesystems that support ftruncate
3037 expansion and some that don't! On Linux fat can't do
3038 ftruncate extend but ext2 can. */
3040 result
= ftruncate(fsp_get_io_fd(fsp
), len
);
3042 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3043 extend a file with ftruncate. Provide alternate implementation
3046 /* Do an fstat to see if the file is longer than the requested
3047 size in which case the ftruncate above should have
3048 succeeded or shorter, in which case seek to len - 1 and
3049 write 1 byte of zero */
3050 status
= vfs_stat_fsp(fsp
);
3051 if (!NT_STATUS_IS_OK(status
)) {
3055 /* We need to update the files_struct after successful ftruncate */
3060 pst
= &fsp
->fsp_name
->st
;
3063 if (S_ISFIFO(pst
->st_ex_mode
)) {
3069 if (pst
->st_ex_size
== len
) {
3074 if (pst
->st_ex_size
> len
) {
3075 /* the ftruncate should have worked */
3079 if (SMB_VFS_PWRITE(fsp
, &c
, 1, len
-1)!=1) {
3087 END_PROFILE(syscall_ftruncate
);
3091 static int vfswrap_fallocate(vfs_handle_struct
*handle
,
3099 START_PROFILE(syscall_fallocate
);
3101 result
= sys_posix_fallocate(fsp_get_io_fd(fsp
), offset
, len
);
3103 * posix_fallocate returns 0 on success, errno on error
3104 * and doesn't set errno. Make it behave like fallocate()
3105 * which returns -1, and sets errno on failure.
3112 /* sys_fallocate handles filtering of unsupported mode flags */
3113 result
= sys_fallocate(fsp_get_io_fd(fsp
), mode
, offset
, len
);
3115 END_PROFILE(syscall_fallocate
);
3119 static bool vfswrap_lock(vfs_handle_struct
*handle
, files_struct
*fsp
, int op
, off_t offset
, off_t count
, int type
)
3123 START_PROFILE(syscall_fcntl_lock
);
3125 if (fsp
->fsp_flags
.use_ofd_locks
) {
3126 op
= map_process_lock_to_ofd_lock(op
);
3129 result
= fcntl_lock(fsp_get_io_fd(fsp
), op
, offset
, count
, type
);
3130 END_PROFILE(syscall_fcntl_lock
);
3134 static int vfswrap_filesystem_sharemode(vfs_handle_struct
*handle
,
3136 uint32_t share_access
,
3137 uint32_t access_mask
)
3143 static int vfswrap_fcntl(vfs_handle_struct
*handle
, files_struct
*fsp
, int cmd
,
3147 va_list dup_cmd_arg
;
3151 START_PROFILE(syscall_fcntl
);
3153 va_copy(dup_cmd_arg
, cmd_arg
);
3159 #if defined(HAVE_OFD_LOCKS)
3164 #if defined(HAVE_F_OWNER_EX)
3168 #if defined(HAVE_RW_HINTS)
3171 case F_GET_FILE_RW_HINT
:
3172 case F_SET_FILE_RW_HINT
:
3174 argp
= va_arg(dup_cmd_arg
, void *);
3175 result
= sys_fcntl_ptr(fsp_get_io_fd(fsp
), cmd
, argp
);
3178 val
= va_arg(dup_cmd_arg
, int);
3179 result
= sys_fcntl_int(fsp_get_io_fd(fsp
), cmd
, val
);
3182 va_end(dup_cmd_arg
);
3184 END_PROFILE(syscall_fcntl
);
3188 static bool vfswrap_getlock(vfs_handle_struct
*handle
, files_struct
*fsp
, off_t
*poffset
, off_t
*pcount
, int *ptype
, pid_t
*ppid
)
3193 START_PROFILE(syscall_fcntl_getlock
);
3195 if (fsp
->fsp_flags
.use_ofd_locks
) {
3196 op
= map_process_lock_to_ofd_lock(op
);
3199 result
= fcntl_getlock(fsp_get_io_fd(fsp
), op
, poffset
, pcount
, ptype
, ppid
);
3200 END_PROFILE(syscall_fcntl_getlock
);
3204 static int vfswrap_linux_setlease(vfs_handle_struct
*handle
, files_struct
*fsp
,
3209 START_PROFILE(syscall_linux_setlease
);
3211 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3213 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3214 result
= linux_setlease(fsp_get_io_fd(fsp
), leasetype
);
3218 END_PROFILE(syscall_linux_setlease
);
3222 static int vfswrap_symlinkat(vfs_handle_struct
*handle
,
3223 const struct smb_filename
*link_target
,
3224 struct files_struct
*dirfsp
,
3225 const struct smb_filename
*new_smb_fname
)
3229 START_PROFILE(syscall_symlinkat
);
3231 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3233 result
= symlinkat(link_target
->base_name
,
3234 fsp_get_pathref_fd(dirfsp
),
3235 new_smb_fname
->base_name
);
3236 END_PROFILE(syscall_symlinkat
);
3240 static int vfswrap_readlinkat(vfs_handle_struct
*handle
,
3241 const struct files_struct
*dirfsp
,
3242 const struct smb_filename
*smb_fname
,
3248 START_PROFILE(syscall_readlinkat
);
3250 SMB_ASSERT(!is_named_stream(smb_fname
));
3252 result
= readlinkat(fsp_get_pathref_fd(dirfsp
),
3253 smb_fname
->base_name
,
3257 END_PROFILE(syscall_readlinkat
);
3261 static int vfswrap_linkat(vfs_handle_struct
*handle
,
3262 files_struct
*srcfsp
,
3263 const struct smb_filename
*old_smb_fname
,
3264 files_struct
*dstfsp
,
3265 const struct smb_filename
*new_smb_fname
,
3270 START_PROFILE(syscall_linkat
);
3272 SMB_ASSERT(!is_named_stream(old_smb_fname
));
3273 SMB_ASSERT(!is_named_stream(new_smb_fname
));
3275 result
= linkat(fsp_get_pathref_fd(srcfsp
),
3276 old_smb_fname
->base_name
,
3277 fsp_get_pathref_fd(dstfsp
),
3278 new_smb_fname
->base_name
,
3281 END_PROFILE(syscall_linkat
);
3285 static int vfswrap_mknodat(vfs_handle_struct
*handle
,
3286 files_struct
*dirfsp
,
3287 const struct smb_filename
*smb_fname
,
3293 START_PROFILE(syscall_mknodat
);
3295 SMB_ASSERT(!is_named_stream(smb_fname
));
3297 result
= sys_mknodat(fsp_get_pathref_fd(dirfsp
),
3298 smb_fname
->base_name
,
3302 END_PROFILE(syscall_mknodat
);
3306 static struct smb_filename
*vfswrap_realpath(vfs_handle_struct
*handle
,
3308 const struct smb_filename
*smb_fname
)
3311 struct smb_filename
*result_fname
= NULL
;
3313 START_PROFILE(syscall_realpath
);
3314 result
= sys_realpath(smb_fname
->base_name
);
3315 END_PROFILE(syscall_realpath
);
3317 result_fname
= synthetic_smb_fname(ctx
,
3325 return result_fname
;
3328 static int vfswrap_fchflags(vfs_handle_struct
*handle
,
3329 struct files_struct
*fsp
,
3332 #ifdef HAVE_FCHFLAGS
3333 int fd
= fsp_get_pathref_fd(fsp
);
3335 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3337 if (!fsp
->fsp_flags
.is_pathref
) {
3338 return fchflags(fd
, flags
);
3341 if (fsp
->fsp_flags
.have_proc_fds
) {
3342 struct sys_proc_fd_path_buf buf
;
3344 return chflags(sys_proc_fd_path(fd
, &buf
), flags
);
3348 * This is no longer a handle based call.
3350 return chflags(fsp
->fsp_name
->base_name
, flags
);
3357 static struct file_id
vfswrap_file_id_create(struct vfs_handle_struct
*handle
,
3358 const SMB_STRUCT_STAT
*sbuf
)
3362 /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3366 key
.devid
= sbuf
->st_ex_dev
;
3367 key
.inode
= sbuf
->st_ex_ino
;
3368 /* key.extid is unused by default. */
3373 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct
*handle
,
3374 const SMB_STRUCT_STAT
*psbuf
)
3378 if (handle
->conn
->base_share_dev
== psbuf
->st_ex_dev
) {
3379 return (uint64_t)psbuf
->st_ex_ino
;
3383 file_id
= ((psbuf
->st_ex_ino
) & UINT32_MAX
);
3386 file_id
|= ((uint64_t)((psbuf
->st_ex_dev
) & UINT32_MAX
)) << 32;
3391 static NTSTATUS
vfswrap_fstreaminfo(vfs_handle_struct
*handle
,
3392 struct files_struct
*fsp
,
3393 TALLOC_CTX
*mem_ctx
,
3394 unsigned int *pnum_streams
,
3395 struct stream_struct
**pstreams
)
3397 struct stream_struct
*tmp_streams
= NULL
;
3398 unsigned int num_streams
= *pnum_streams
;
3399 struct stream_struct
*streams
= *pstreams
;
3402 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3404 if (fsp
->fsp_flags
.is_directory
) {
3406 * No default streams on directories
3410 status
= vfs_stat_fsp(fsp
);
3411 if (!NT_STATUS_IS_OK(status
)) {
3415 if (num_streams
+ 1 < 1) {
3417 return NT_STATUS_INVALID_PARAMETER
;
3420 tmp_streams
= talloc_realloc(mem_ctx
,
3422 struct stream_struct
,
3424 if (tmp_streams
== NULL
) {
3425 return NT_STATUS_NO_MEMORY
;
3427 tmp_streams
[num_streams
].name
= talloc_strdup(tmp_streams
, "::$DATA");
3428 if (tmp_streams
[num_streams
].name
== NULL
) {
3429 return NT_STATUS_NO_MEMORY
;
3431 tmp_streams
[num_streams
].size
= fsp
->fsp_name
->st
.st_ex_size
;
3432 tmp_streams
[num_streams
].alloc_size
= SMB_VFS_GET_ALLOC_SIZE(
3435 &fsp
->fsp_name
->st
);
3438 *pnum_streams
= num_streams
;
3439 *pstreams
= tmp_streams
;
3441 return NT_STATUS_OK
;
3444 static NTSTATUS
vfswrap_get_real_filename_at(
3445 struct vfs_handle_struct
*handle
,
3446 struct files_struct
*dirfsp
,
3448 TALLOC_CTX
*mem_ctx
,
3452 * Don't fall back to get_real_filename so callers can differentiate
3453 * between a full directory scan and an actual case-insensitive stat.
3455 return NT_STATUS_NOT_SUPPORTED
;
3458 static const char *vfswrap_connectpath(struct vfs_handle_struct
*handle
,
3459 const struct files_struct
*dirfsp
,
3460 const struct smb_filename
*smb_fname
)
3462 return handle
->conn
->connectpath
;
3465 static NTSTATUS
vfswrap_brl_lock_windows(struct vfs_handle_struct
*handle
,
3466 struct byte_range_lock
*br_lck
,
3467 struct lock_struct
*plock
)
3469 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3471 /* Note: blr is not used in the default implementation. */
3472 return brl_lock_windows_default(br_lck
, plock
);
3475 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct
*handle
,
3476 struct byte_range_lock
*br_lck
,
3477 const struct lock_struct
*plock
)
3479 SMB_ASSERT(plock
->lock_flav
== WINDOWS_LOCK
);
3481 return brl_unlock_windows_default(br_lck
, plock
);
3484 static bool vfswrap_strict_lock_check(struct vfs_handle_struct
*handle
,
3486 struct lock_struct
*plock
)
3488 SMB_ASSERT(plock
->lock_type
== READ_LOCK
||
3489 plock
->lock_type
== WRITE_LOCK
);
3491 return strict_lock_check_default(fsp
, plock
);
3494 /* NT ACL operations. */
3496 static NTSTATUS
vfswrap_fget_nt_acl(vfs_handle_struct
*handle
,
3498 uint32_t security_info
,
3499 TALLOC_CTX
*mem_ctx
,
3500 struct security_descriptor
**ppdesc
)
3504 START_PROFILE(fget_nt_acl
);
3506 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3508 result
= posix_fget_nt_acl(fsp
, security_info
,
3510 END_PROFILE(fget_nt_acl
);
3514 static NTSTATUS
vfswrap_fset_nt_acl(vfs_handle_struct
*handle
, files_struct
*fsp
, uint32_t security_info_sent
, const struct security_descriptor
*psd
)
3518 START_PROFILE(fset_nt_acl
);
3520 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3522 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
3523 END_PROFILE(fset_nt_acl
);
3527 static NTSTATUS
vfswrap_audit_file(struct vfs_handle_struct
*handle
,
3528 struct smb_filename
*file
,
3529 struct security_acl
*sacl
,
3530 uint32_t access_requested
,
3531 uint32_t access_denied
)
3533 return NT_STATUS_OK
; /* Nothing to do here ... */
3536 static SMB_ACL_T
vfswrap_sys_acl_get_fd(vfs_handle_struct
*handle
,
3538 SMB_ACL_TYPE_T type
,
3539 TALLOC_CTX
*mem_ctx
)
3541 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3543 return sys_acl_get_fd(handle
, fsp
, type
, mem_ctx
);
3546 static int vfswrap_sys_acl_set_fd(vfs_handle_struct
*handle
,
3548 SMB_ACL_TYPE_T type
,
3551 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3553 return sys_acl_set_fd(handle
, fsp
, type
, theacl
);
3556 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct
*handle
,
3559 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3561 return sys_acl_delete_def_fd(handle
, fsp
);
3564 /****************************************************************
3565 Extended attribute operations.
3566 *****************************************************************/
3568 static ssize_t
vfswrap_fgetxattr(struct vfs_handle_struct
*handle
,
3569 struct files_struct
*fsp
,
3574 int fd
= fsp_get_pathref_fd(fsp
);
3576 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3578 if (!fsp
->fsp_flags
.is_pathref
) {
3579 return fgetxattr(fd
, name
, value
, size
);
3582 if (fsp
->fsp_flags
.have_proc_fds
) {
3583 struct sys_proc_fd_path_buf buf
;
3585 return getxattr(sys_proc_fd_path(fd
, &buf
), name
, value
, size
);
3589 * This is no longer a handle based call.
3591 return getxattr(fsp
->fsp_name
->base_name
, name
, value
, size
);
3594 struct vfswrap_getxattrat_state
{
3595 struct tevent_context
*ev
;
3596 struct vfs_handle_struct
*handle
;
3597 files_struct
*dir_fsp
;
3598 const struct smb_filename
*smb_fname
;
3601 * The following variables are talloced off "state" which is protected
3602 * by a destructor and thus are guaranteed to be safe to be used in the
3603 * job function in the worker thread.
3606 const char *xattr_name
;
3607 uint8_t *xattr_value
;
3608 struct security_unix_token
*token
;
3611 struct vfs_aio_state vfs_aio_state
;
3612 SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes
);
3615 static int vfswrap_getxattrat_state_destructor(
3616 struct vfswrap_getxattrat_state
*state
)
3621 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
);
3622 static void vfswrap_getxattrat_do_async(void *private_data
);
3623 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
);
3625 static struct tevent_req
*vfswrap_getxattrat_send(
3626 TALLOC_CTX
*mem_ctx
,
3627 struct tevent_context
*ev
,
3628 struct vfs_handle_struct
*handle
,
3629 files_struct
*dir_fsp
,
3630 const struct smb_filename
*smb_fname
,
3631 const char *xattr_name
,
3634 struct tevent_req
*req
= NULL
;
3635 struct tevent_req
*subreq
= NULL
;
3636 struct vfswrap_getxattrat_state
*state
= NULL
;
3637 size_t max_threads
= 0;
3638 bool have_per_thread_cwd
= false;
3639 bool have_per_thread_creds
= false;
3640 bool do_async
= false;
3642 SMB_ASSERT(!is_named_stream(smb_fname
));
3644 req
= tevent_req_create(mem_ctx
, &state
,
3645 struct vfswrap_getxattrat_state
);
3649 *state
= (struct vfswrap_getxattrat_state
) {
3653 .smb_fname
= smb_fname
,
3656 max_threads
= pthreadpool_tevent_max_threads(dir_fsp
->conn
->sconn
->pool
);
3657 if (max_threads
>= 1) {
3659 * We need a non sync threadpool!
3661 have_per_thread_cwd
= per_thread_cwd_supported();
3663 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3664 have_per_thread_creds
= true;
3666 if (have_per_thread_cwd
&& have_per_thread_creds
) {
3670 SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat
, profile_p
,
3671 state
->profile_bytes
, 0);
3673 if (fsp_get_pathref_fd(dir_fsp
) == -1) {
3674 DBG_ERR("Need a valid directory fd\n");
3675 tevent_req_error(req
, EINVAL
);
3676 return tevent_req_post(req
, ev
);
3679 if (alloc_hint
> 0) {
3680 state
->xattr_value
= talloc_zero_array(state
,
3683 if (tevent_req_nomem(state
->xattr_value
, req
)) {
3684 return tevent_req_post(req
, ev
);
3689 vfswrap_getxattrat_do_sync(req
);
3690 return tevent_req_post(req
, ev
);
3694 * Now allocate all parameters from a memory context that won't go away
3695 * no matter what. These parameters will get used in threads and we
3696 * can't reliably cancel threads, so all buffers passed to the threads
3697 * must not be freed before all referencing threads terminate.
3700 state
->name
= talloc_strdup(state
, smb_fname
->base_name
);
3701 if (tevent_req_nomem(state
->name
, req
)) {
3702 return tevent_req_post(req
, ev
);
3705 state
->xattr_name
= talloc_strdup(state
, xattr_name
);
3706 if (tevent_req_nomem(state
->xattr_name
, req
)) {
3707 return tevent_req_post(req
, ev
);
3711 * This is a hot codepath so at first glance one might think we should
3712 * somehow optimize away the token allocation and do a
3713 * talloc_reference() or similar black magic instead. But due to the
3714 * talloc_stackframe pool per SMB2 request this should be a simple copy
3715 * without a malloc in most cases.
3717 if (geteuid() == sec_initial_uid()) {
3718 state
->token
= root_unix_token(state
);
3720 state
->token
= copy_unix_token(
3722 dir_fsp
->conn
->session_info
->unix_token
);
3724 if (tevent_req_nomem(state
->token
, req
)) {
3725 return tevent_req_post(req
, ev
);
3728 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3730 subreq
= pthreadpool_tevent_job_send(
3733 dir_fsp
->conn
->sconn
->pool
,
3734 vfswrap_getxattrat_do_async
,
3736 if (tevent_req_nomem(subreq
, req
)) {
3737 return tevent_req_post(req
, ev
);
3739 tevent_req_set_callback(subreq
, vfswrap_getxattrat_done
, req
);
3741 talloc_set_destructor(state
, vfswrap_getxattrat_state_destructor
);
3746 static void vfswrap_getxattrat_do_sync(struct tevent_req
*req
)
3748 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3749 req
, struct vfswrap_getxattrat_state
);
3751 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3752 state
->smb_fname
->fsp
,
3755 talloc_array_length(state
->xattr_value
));
3756 if (state
->xattr_size
== -1) {
3757 tevent_req_error(req
, errno
);
3761 tevent_req_done(req
);
3765 static void vfswrap_getxattrat_do_async(void *private_data
)
3767 struct vfswrap_getxattrat_state
*state
= talloc_get_type_abort(
3768 private_data
, struct vfswrap_getxattrat_state
);
3769 struct timespec start_time
;
3770 struct timespec end_time
;
3773 PROFILE_TIMESTAMP(&start_time
);
3774 SMBPROFILE_BYTES_ASYNC_SET_BUSY(state
->profile_bytes
);
3777 * Here we simulate a getxattrat()
3778 * call using fchdir();getxattr()
3781 per_thread_cwd_activate();
3783 /* Become the correct credential on this thread. */
3784 ret
= set_thread_credentials(state
->token
->uid
,
3786 (size_t)state
->token
->ngroups
,
3787 state
->token
->groups
);
3789 state
->xattr_size
= -1;
3790 state
->vfs_aio_state
.error
= errno
;
3794 state
->xattr_size
= vfswrap_fgetxattr(state
->handle
,
3795 state
->smb_fname
->fsp
,
3798 talloc_array_length(state
->xattr_value
));
3799 if (state
->xattr_size
== -1) {
3800 state
->vfs_aio_state
.error
= errno
;
3804 PROFILE_TIMESTAMP(&end_time
);
3805 state
->vfs_aio_state
.duration
= nsec_time_diff(&end_time
, &start_time
);
3806 SMBPROFILE_BYTES_ASYNC_SET_IDLE(state
->profile_bytes
);
3809 static void vfswrap_getxattrat_done(struct tevent_req
*subreq
)
3811 struct tevent_req
*req
= tevent_req_callback_data(
3812 subreq
, struct tevent_req
);
3813 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3814 req
, struct vfswrap_getxattrat_state
);
3819 * Make sure we run as the user again
3821 ok
= change_to_user_and_service_by_fsp(state
->dir_fsp
);
3824 ret
= pthreadpool_tevent_job_recv(subreq
);
3825 TALLOC_FREE(subreq
);
3826 SMBPROFILE_BYTES_ASYNC_END(state
->profile_bytes
);
3827 talloc_set_destructor(state
, NULL
);
3829 if (ret
!= EAGAIN
) {
3830 tevent_req_error(req
, ret
);
3834 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3835 * means the lower level pthreadpool failed to create a new
3836 * thread. Fallback to sync processing in that case to allow
3837 * some progress for the client.
3839 vfswrap_getxattrat_do_sync(req
);
3843 if (state
->xattr_size
== -1) {
3844 tevent_req_error(req
, state
->vfs_aio_state
.error
);
3848 if (state
->xattr_value
== NULL
) {
3850 * The caller only wanted the size.
3852 tevent_req_done(req
);
3857 * shrink the buffer to the returned size.
3858 * (can't fail). It means NULL if size is 0.
3860 state
->xattr_value
= talloc_realloc(state
,
3865 tevent_req_done(req
);
3868 static ssize_t
vfswrap_getxattrat_recv(struct tevent_req
*req
,
3869 struct vfs_aio_state
*aio_state
,
3870 TALLOC_CTX
*mem_ctx
,
3871 uint8_t **xattr_value
)
3873 struct vfswrap_getxattrat_state
*state
= tevent_req_data(
3874 req
, struct vfswrap_getxattrat_state
);
3877 if (tevent_req_is_unix_error(req
, &aio_state
->error
)) {
3878 tevent_req_received(req
);
3882 *aio_state
= state
->vfs_aio_state
;
3883 xattr_size
= state
->xattr_size
;
3884 if (xattr_value
!= NULL
) {
3885 *xattr_value
= talloc_move(mem_ctx
, &state
->xattr_value
);
3888 tevent_req_received(req
);
3892 static ssize_t
vfswrap_flistxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, char *list
, size_t size
)
3894 int fd
= fsp_get_pathref_fd(fsp
);
3896 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3898 if (!fsp
->fsp_flags
.is_pathref
) {
3899 return flistxattr(fd
, list
, size
);
3902 if (fsp
->fsp_flags
.have_proc_fds
) {
3903 struct sys_proc_fd_path_buf buf
;
3905 return listxattr(sys_proc_fd_path(fd
, &buf
), list
, size
);
3909 * This is no longer a handle based call.
3911 return listxattr(fsp
->fsp_name
->base_name
, list
, size
);
3914 static int vfswrap_fremovexattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
)
3916 int fd
= fsp_get_pathref_fd(fsp
);
3918 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3920 if (!fsp
->fsp_flags
.is_pathref
) {
3921 return fremovexattr(fd
, name
);
3924 if (fsp
->fsp_flags
.have_proc_fds
) {
3925 struct sys_proc_fd_path_buf buf
;
3927 return removexattr(sys_proc_fd_path(fd
, &buf
), name
);
3931 * This is no longer a handle based call.
3933 return removexattr(fsp
->fsp_name
->base_name
, name
);
3936 static int vfswrap_fsetxattr(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
, const char *name
, const void *value
, size_t size
, int flags
)
3938 int fd
= fsp_get_pathref_fd(fsp
);
3940 SMB_ASSERT(!fsp_is_alternate_stream(fsp
));
3942 if (!fsp
->fsp_flags
.is_pathref
) {
3943 return fsetxattr(fd
, name
, value
, size
, flags
);
3946 if (fsp
->fsp_flags
.have_proc_fds
) {
3947 struct sys_proc_fd_path_buf buf
;
3949 return setxattr(sys_proc_fd_path(fd
, &buf
),
3957 * This is no longer a handle based call.
3959 return setxattr(fsp
->fsp_name
->base_name
, name
, value
, size
, flags
);
3962 static bool vfswrap_aio_force(struct vfs_handle_struct
*handle
, struct files_struct
*fsp
)
3967 static bool vfswrap_is_offline(struct connection_struct
*conn
,
3968 const struct smb_filename
*fname
)
3972 bool offline
= false;
3974 if (ISDOT(fname
->base_name
) || ISDOTDOT(fname
->base_name
)) {
3978 if (!lp_dmapi_support(SNUM(conn
)) || !dmapi_have_session()) {
3979 #if defined(ENOTSUP)
3985 status
= get_full_smb_filename(talloc_tos(), fname
, &path
);
3986 if (!NT_STATUS_IS_OK(status
)) {
3987 errno
= map_errno_from_nt_status(status
);
3991 offline
= (dmapi_file_flags(path
) & FILE_ATTRIBUTE_OFFLINE
) != 0;
3998 static NTSTATUS
vfswrap_durable_cookie(struct vfs_handle_struct
*handle
,
3999 struct files_struct
*fsp
,
4000 TALLOC_CTX
*mem_ctx
,
4003 return vfs_default_durable_cookie(fsp
, mem_ctx
, cookie
);
4006 static NTSTATUS
vfswrap_durable_disconnect(struct vfs_handle_struct
*handle
,
4007 struct files_struct
*fsp
,
4008 const DATA_BLOB old_cookie
,
4009 TALLOC_CTX
*mem_ctx
,
4010 DATA_BLOB
*new_cookie
)
4012 return vfs_default_durable_disconnect(fsp
, old_cookie
, mem_ctx
,
4016 static NTSTATUS
vfswrap_durable_reconnect(struct vfs_handle_struct
*handle
,
4017 struct smb_request
*smb1req
,
4018 struct smbXsrv_open
*op
,
4019 const DATA_BLOB old_cookie
,
4020 TALLOC_CTX
*mem_ctx
,
4021 struct files_struct
**fsp
,
4022 DATA_BLOB
*new_cookie
)
4024 return vfs_default_durable_reconnect(handle
->conn
, smb1req
, op
,
4025 old_cookie
, mem_ctx
,
4029 static struct vfs_fn_pointers vfs_default_fns
= {
4030 /* Disk operations */
4032 .connect_fn
= vfswrap_connect
,
4033 .disconnect_fn
= vfswrap_disconnect
,
4034 .disk_free_fn
= vfswrap_disk_free
,
4035 .get_quota_fn
= vfswrap_get_quota
,
4036 .set_quota_fn
= vfswrap_set_quota
,
4037 .get_shadow_copy_data_fn
= vfswrap_get_shadow_copy_data
,
4038 .statvfs_fn
= vfswrap_statvfs
,
4039 .fs_capabilities_fn
= vfswrap_fs_capabilities
,
4040 .get_dfs_referrals_fn
= vfswrap_get_dfs_referrals
,
4041 .create_dfs_pathat_fn
= vfswrap_create_dfs_pathat
,
4042 .read_dfs_pathat_fn
= vfswrap_read_dfs_pathat
,
4043 .snap_check_path_fn
= vfswrap_snap_check_path
,
4044 .snap_create_fn
= vfswrap_snap_create
,
4045 .snap_delete_fn
= vfswrap_snap_delete
,
4047 /* Directory operations */
4049 .fdopendir_fn
= vfswrap_fdopendir
,
4050 .readdir_fn
= vfswrap_readdir
,
4051 .freaddir_attr_fn
= vfswrap_freaddir_attr
,
4052 .rewind_dir_fn
= vfswrap_rewinddir
,
4053 .mkdirat_fn
= vfswrap_mkdirat
,
4054 .closedir_fn
= vfswrap_closedir
,
4056 /* File operations */
4058 .openat_fn
= vfswrap_openat
,
4059 .create_file_fn
= vfswrap_create_file
,
4060 .close_fn
= vfswrap_close
,
4061 .pread_fn
= vfswrap_pread
,
4062 .pread_send_fn
= vfswrap_pread_send
,
4063 .pread_recv_fn
= vfswrap_pread_recv
,
4064 .pwrite_fn
= vfswrap_pwrite
,
4065 .pwrite_send_fn
= vfswrap_pwrite_send
,
4066 .pwrite_recv_fn
= vfswrap_pwrite_recv
,
4067 .lseek_fn
= vfswrap_lseek
,
4068 .sendfile_fn
= vfswrap_sendfile
,
4069 .recvfile_fn
= vfswrap_recvfile
,
4070 .renameat_fn
= vfswrap_renameat
,
4071 .fsync_send_fn
= vfswrap_fsync_send
,
4072 .fsync_recv_fn
= vfswrap_fsync_recv
,
4073 .stat_fn
= vfswrap_stat
,
4074 .fstat_fn
= vfswrap_fstat
,
4075 .lstat_fn
= vfswrap_lstat
,
4076 .fstatat_fn
= vfswrap_fstatat
,
4077 .get_alloc_size_fn
= vfswrap_get_alloc_size
,
4078 .unlinkat_fn
= vfswrap_unlinkat
,
4079 .fchmod_fn
= vfswrap_fchmod
,
4080 .fchown_fn
= vfswrap_fchown
,
4081 .lchown_fn
= vfswrap_lchown
,
4082 .chdir_fn
= vfswrap_chdir
,
4083 .getwd_fn
= vfswrap_getwd
,
4084 .fntimes_fn
= vfswrap_fntimes
,
4085 .ftruncate_fn
= vfswrap_ftruncate
,
4086 .fallocate_fn
= vfswrap_fallocate
,
4087 .lock_fn
= vfswrap_lock
,
4088 .filesystem_sharemode_fn
= vfswrap_filesystem_sharemode
,
4089 .fcntl_fn
= vfswrap_fcntl
,
4090 .linux_setlease_fn
= vfswrap_linux_setlease
,
4091 .getlock_fn
= vfswrap_getlock
,
4092 .symlinkat_fn
= vfswrap_symlinkat
,
4093 .readlinkat_fn
= vfswrap_readlinkat
,
4094 .linkat_fn
= vfswrap_linkat
,
4095 .mknodat_fn
= vfswrap_mknodat
,
4096 .realpath_fn
= vfswrap_realpath
,
4097 .fchflags_fn
= vfswrap_fchflags
,
4098 .file_id_create_fn
= vfswrap_file_id_create
,
4099 .fs_file_id_fn
= vfswrap_fs_file_id
,
4100 .fstreaminfo_fn
= vfswrap_fstreaminfo
,
4101 .get_real_filename_at_fn
= vfswrap_get_real_filename_at
,
4102 .connectpath_fn
= vfswrap_connectpath
,
4103 .brl_lock_windows_fn
= vfswrap_brl_lock_windows
,
4104 .brl_unlock_windows_fn
= vfswrap_brl_unlock_windows
,
4105 .strict_lock_check_fn
= vfswrap_strict_lock_check
,
4106 .translate_name_fn
= vfswrap_translate_name
,
4107 .parent_pathname_fn
= vfswrap_parent_pathname
,
4108 .fsctl_fn
= vfswrap_fsctl
,
4109 .fset_dos_attributes_fn
= vfswrap_fset_dos_attributes
,
4110 .get_dos_attributes_send_fn
= vfswrap_get_dos_attributes_send
,
4111 .get_dos_attributes_recv_fn
= vfswrap_get_dos_attributes_recv
,
4112 .fget_dos_attributes_fn
= vfswrap_fget_dos_attributes
,
4113 .offload_read_send_fn
= vfswrap_offload_read_send
,
4114 .offload_read_recv_fn
= vfswrap_offload_read_recv
,
4115 .offload_write_send_fn
= vfswrap_offload_write_send
,
4116 .offload_write_recv_fn
= vfswrap_offload_write_recv
,
4117 .fget_compression_fn
= vfswrap_fget_compression
,
4118 .set_compression_fn
= vfswrap_set_compression
,
4120 /* NT ACL operations. */
4122 .fget_nt_acl_fn
= vfswrap_fget_nt_acl
,
4123 .fset_nt_acl_fn
= vfswrap_fset_nt_acl
,
4124 .audit_file_fn
= vfswrap_audit_file
,
4126 /* POSIX ACL operations. */
4128 .sys_acl_get_fd_fn
= vfswrap_sys_acl_get_fd
,
4129 .sys_acl_blob_get_fd_fn
= posix_sys_acl_blob_get_fd
,
4130 .sys_acl_set_fd_fn
= vfswrap_sys_acl_set_fd
,
4131 .sys_acl_delete_def_fd_fn
= vfswrap_sys_acl_delete_def_fd
,
4133 /* EA operations. */
4134 .getxattrat_send_fn
= vfswrap_getxattrat_send
,
4135 .getxattrat_recv_fn
= vfswrap_getxattrat_recv
,
4136 .fgetxattr_fn
= vfswrap_fgetxattr
,
4137 .flistxattr_fn
= vfswrap_flistxattr
,
4138 .fremovexattr_fn
= vfswrap_fremovexattr
,
4139 .fsetxattr_fn
= vfswrap_fsetxattr
,
4141 /* aio operations */
4142 .aio_force_fn
= vfswrap_aio_force
,
4144 /* durable handle operations */
4145 .durable_cookie_fn
= vfswrap_durable_cookie
,
4146 .durable_disconnect_fn
= vfswrap_durable_disconnect
,
4147 .durable_reconnect_fn
= vfswrap_durable_reconnect
,
4151 NTSTATUS
vfs_default_init(TALLOC_CTX
*ctx
)
4154 * Here we need to implement every call!
4156 * As this is the end of the vfs module chain.
4158 smb_vfs_assert_all_fns(&vfs_default_fns
, DEFAULT_VFS_MODULE_NAME
);
4159 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
,
4160 DEFAULT_VFS_MODULE_NAME
, &vfs_default_fns
);