@@ -13,10 +13,8 @@ use std::ffi::{OsStr, OsString};
1313use std:: os:: unix:: ffi:: OsStrExt ;
1414use std:: path:: Path ;
1515
16- /// Returns true if the error is the kernel/filesystem signaling that
17- /// extended attributes are not supported (`ENOTSUP` / `EOPNOTSUPP`).
18- /// On Linux these are the same errno; on the BSDs they differ, so we
19- /// match on either.
16+ /// True if the error is `ENOTSUP` / `EOPNOTSUPP` (same errno on Linux,
17+ /// distinct on the BSDs).
2018#[ cfg( unix) ]
2119fn is_xattr_unsupported ( err : & std:: io:: Error ) -> bool {
2220 matches ! (
@@ -30,62 +28,55 @@ fn is_xattr_unsupported(_err: &std::io::Error) -> bool {
3028 false
3129}
3230
33- /// Copies extended attributes (xattrs) from one file or directory to another.
34- ///
35- /// Returns `Ok(())` if the destination filesystem signals that xattrs are
36- /// not supported (`ENOTSUP` / `EOPNOTSUPP`), since cross-filesystem moves
37- /// onto e.g. tmpfs without xattr support are a legitimate scenario. All
38- /// other errors propagate so the caller can surface (for example)
39- /// permission failures on `security.*` namespaces.
40- ///
41- /// # Arguments
42- ///
43- /// * `source` - A reference to the source path.
44- /// * `dest` - A reference to the destination path.
31+ /// Copies extended attributes (xattrs) from one path to another.
32+ /// All errors propagate, including `ENOTSUP` / `EOPNOTSUPP`; for
33+ /// best-effort callers see [`copy_xattrs_ignore_unsupported`].
4534pub fn copy_xattrs < P : AsRef < Path > > ( source : P , dest : P ) -> std:: io:: Result < ( ) > {
46- let attrs = match xattr:: list ( & source) {
47- Ok ( a) => a,
48- Err ( e) if is_xattr_unsupported ( & e) => return Ok ( ( ) ) ,
49- Err ( e) => return Err ( e) ,
50- } ;
51- for attr_name in attrs {
35+ for attr_name in xattr:: list ( & source) ? {
5236 if let Some ( value) = xattr:: get ( & source, & attr_name) ? {
53- if let Err ( e) = xattr:: set ( & dest, & attr_name, & value) {
54- if is_xattr_unsupported ( & e) {
55- return Ok ( ( ) ) ;
56- }
57- return Err ( e) ;
58- }
37+ xattr:: set ( & dest, & attr_name, & value) ?;
5938 }
6039 }
6140 Ok ( ( ) )
6241}
6342
43+ /// Like [`copy_xattrs`], but maps `ENOTSUP` / `EOPNOTSUPP` to `Ok(())`
44+ /// for callers where xattr preservation is best-effort.
45+ pub fn copy_xattrs_ignore_unsupported < P : AsRef < Path > > ( source : P , dest : P ) -> std:: io:: Result < ( ) > {
46+ match copy_xattrs ( source, dest) {
47+ Ok ( ( ) ) => Ok ( ( ) ) ,
48+ Err ( e) if is_xattr_unsupported ( & e) => Ok ( ( ) ) ,
49+ Err ( e) => Err ( e) ,
50+ }
51+ }
52+
6453/// Copies xattrs between two open file descriptors. Pins both inodes so
6554/// list/get/set calls cannot be redirected by a concurrent renamer, unlike
66- /// the path-based [`copy_xattrs`]. `ENOTSUP` / `EOPNOTSUPP` is treated as
67- /// success.
55+ /// the path-based [`copy_xattrs`].
6856#[ cfg( unix) ]
6957pub fn copy_xattrs_fd ( source : & std:: fs:: File , dest : & std:: fs:: File ) -> std:: io:: Result < ( ) > {
7058 use xattr:: FileExt ;
71- let attrs = match source. list_xattr ( ) {
72- Ok ( a) => a,
73- Err ( e) if is_xattr_unsupported ( & e) => return Ok ( ( ) ) ,
74- Err ( e) => return Err ( e) ,
75- } ;
76- for attr_name in attrs {
59+ for attr_name in source. list_xattr ( ) ? {
7760 if let Some ( value) = source. get_xattr ( & attr_name) ? {
78- if let Err ( e) = dest. set_xattr ( & attr_name, & value) {
79- if is_xattr_unsupported ( & e) {
80- return Ok ( ( ) ) ;
81- }
82- return Err ( e) ;
83- }
61+ dest. set_xattr ( & attr_name, & value) ?;
8462 }
8563 }
8664 Ok ( ( ) )
8765}
8866
67+ /// Like [`copy_xattrs_fd`], but maps `ENOTSUP` / `EOPNOTSUPP` to `Ok(())`.
68+ #[ cfg( unix) ]
69+ pub fn copy_xattrs_fd_ignore_unsupported (
70+ source : & std:: fs:: File ,
71+ dest : & std:: fs:: File ,
72+ ) -> std:: io:: Result < ( ) > {
73+ match copy_xattrs_fd ( source, dest) {
74+ Ok ( ( ) ) => Ok ( ( ) ) ,
75+ Err ( e) if is_xattr_unsupported ( & e) => Ok ( ( ) ) ,
76+ Err ( e) => Err ( e) ,
77+ }
78+ }
79+
8980/// Like `copy_xattrs`, but skips the security.selinux attribute.
9081#[ cfg( unix) ]
9182pub fn copy_xattrs_skip_selinux < P : AsRef < Path > > ( source : P , dest : P ) -> std:: io:: Result < ( ) > {
0 commit comments