11use anyhow:: Result ;
22
3- use cap_std:: fs:: { Dir , File , Permissions , PermissionsExt } ;
3+ #[ cfg( unix) ]
4+ use cap_std:: fs:: PermissionsExt ;
5+ use cap_std:: fs:: { Dir , File , Permissions } ;
6+ use cap_std_ext:: cap_std;
7+ #[ cfg( not( windows) ) ]
48use cap_std_ext:: cmdext:: CapStdExtCommandExt ;
59use cap_std_ext:: dirext:: { CapStdExtDirExt , WalkConfiguration } ;
6- use cap_std_ext:: { cap_std, RootDir } ;
10+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
11+ use cap_std_ext:: RootDir ;
12+ #[ cfg( unix) ]
713use rustix:: path:: DecInt ;
814use std:: cmp:: Ordering ;
915use std:: ffi:: OsStr ;
@@ -13,6 +19,7 @@ use std::path::{Path, PathBuf};
1319use std:: { process:: Command , sync:: Arc } ;
1420
1521#[ test]
22+ #[ cfg( not( windows) ) ]
1623fn take_fd ( ) -> Result < ( ) > {
1724 let mut c = Command :: new ( "/bin/bash" ) ;
1825 c. arg ( "-c" ) ;
@@ -31,6 +38,7 @@ fn take_fd() -> Result<()> {
3138}
3239
3340#[ test]
41+ #[ cfg( not( windows) ) ]
3442fn fchdir ( ) -> Result < ( ) > {
3543 static CONTENTS : & [ u8 ] = b"hello world" ;
3644
@@ -108,20 +116,23 @@ fn ensuredir() -> Result<()> {
108116 td. write ( p, "some file contents" ) ?;
109117 assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
110118
111- // Broken symlinks aren't followed and are errors
112- let p = Path :: new ( "linksrc" ) ;
113- td. symlink ( "linkdest" , p) ?;
114- assert ! ( td. metadata( p) . is_err( ) ) ;
115- assert ! ( td
116- . symlink_metadata_optional( p)
117- . unwrap( )
118- . unwrap( )
119- . is_symlink( ) ) ;
120- // Non-broken symlinks are also an error
121- assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
122- td. create_dir ( "linkdest" ) ?;
123- assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
124- assert ! ( td. metadata_optional( p) . unwrap( ) . unwrap( ) . is_dir( ) ) ;
119+ #[ cfg( not( windows) ) ]
120+ {
121+ // Broken symlinks aren't followed and are errors
122+ let p = Path :: new ( "linksrc" ) ;
123+ td. symlink ( "linkdest" , p) ?;
124+ assert ! ( td. metadata( p) . is_err( ) ) ;
125+ assert ! ( td
126+ . symlink_metadata_optional( p)
127+ . unwrap( )
128+ . unwrap( )
129+ . is_symlink( ) ) ;
130+ // Non-broken symlinks are also an error
131+ assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
132+ td. create_dir ( "linkdest" ) ?;
133+ assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
134+ assert ! ( td. metadata_optional( p) . unwrap( ) . unwrap( ) . is_dir( ) ) ;
135+ }
125136
126137 Ok ( ( ) )
127138}
@@ -142,12 +153,15 @@ fn test_remove_all_optional() -> Result<()> {
142153 td. write ( p, "test" ) ?;
143154 assert ! ( td. remove_all_optional( p) . unwrap( ) ) ;
144155
145- // symlinks; broken and not
146- let p = Path :: new ( "linksrc" ) ;
147- td. symlink ( "linkdest" , p) ?;
148- assert ! ( td. remove_all_optional( p) . unwrap( ) ) ;
149- td. symlink ( "linkdest" , p) ?;
150- assert ! ( td. remove_all_optional( p) . unwrap( ) ) ;
156+ #[ cfg( not( windows) ) ]
157+ {
158+ // symlinks; broken and not
159+ let p = Path :: new ( "linksrc" ) ;
160+ td. symlink ( "linkdest" , p) ?;
161+ assert ! ( td. remove_all_optional( p) . unwrap( ) ) ;
162+ td. symlink ( "linkdest" , p) ?;
163+ assert ! ( td. remove_all_optional( p) . unwrap( ) ) ;
164+ }
151165
152166 Ok ( ( ) )
153167}
@@ -198,50 +212,55 @@ fn link_tempfile_with() -> Result<()> {
198212 ) ;
199213 assert_eq ! ( td. metadata( p) ?. permissions( ) , default_perms) ;
200214
201- td. atomic_write_with_perms ( p, "atomic replacement 3\n " , Permissions :: from_mode ( 0o700 ) )
202- . unwrap ( ) ;
203- assert_eq ! (
204- td. read_to_string( p) . unwrap( ) . as_str( ) ,
205- "atomic replacement 3\n "
206- ) ;
207- assert_eq ! ( td. metadata( p) ?. permissions( ) . mode( ) & 0o777 , 0o700 ) ;
208-
209- // Ensure we preserve the executable bit on an existing file
210- assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o700 , 0o700 ) ;
211- td. atomic_write ( p, "atomic replacement 4\n " ) . unwrap ( ) ;
212- assert_eq ! (
213- td. read_to_string( p) . unwrap( ) . as_str( ) ,
214- "atomic replacement 4\n "
215- ) ;
216- assert_eq ! ( td. metadata( p) ?. permissions( ) . mode( ) & 0o777 , 0o700 ) ;
217-
218- // But we should ignore permissions on a symlink (both existing and broken)
219- td. remove_file ( p) ?;
220- let p2 = Path :: new ( "bar" ) ;
221- td. atomic_write_with_perms ( p2, "link target" , Permissions :: from_mode ( 0o755 ) )
222- . unwrap ( ) ;
223- td. symlink ( p2, p) ?;
224- td. atomic_write ( p, "atomic replacement symlink\n " ) . unwrap ( ) ;
225- assert_eq ! ( td. metadata( p) ?. permissions( ) , default_perms) ;
226- // And break the link
227- td. remove_file ( p2) ?;
228- td. atomic_write ( p, "atomic replacement symlink\n " ) . unwrap ( ) ;
229- assert_eq ! ( td. metadata( p) ?. permissions( ) , default_perms) ;
215+ #[ cfg( unix) ]
216+ {
217+ td. atomic_write_with_perms ( p, "atomic replacement 3\n " , Permissions :: from_mode ( 0o700 ) )
218+ . unwrap ( ) ;
219+ assert_eq ! (
220+ td. read_to_string( p) . unwrap( ) . as_str( ) ,
221+ "atomic replacement 3\n "
222+ ) ;
223+ assert_eq ! ( td. metadata( p) ?. permissions( ) . mode( ) & 0o777 , 0o700 ) ;
224+
225+ // Ensure we preserve the executable bit on an existing file
226+ assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o700 , 0o700 ) ;
227+ td. atomic_write ( p, "atomic replacement 4\n " ) . unwrap ( ) ;
228+ assert_eq ! (
229+ td. read_to_string( p) . unwrap( ) . as_str( ) ,
230+ "atomic replacement 4\n "
231+ ) ;
232+ assert_eq ! ( td. metadata( p) ?. permissions( ) . mode( ) & 0o777 , 0o700 ) ;
233+
234+ // But we should ignore permissions on a symlink (both existing and broken)
235+ td. remove_file ( p) ?;
236+ let p2 = Path :: new ( "bar" ) ;
237+ td. atomic_write_with_perms ( p2, "link target" , Permissions :: from_mode ( 0o755 ) )
238+ . unwrap ( ) ;
239+ td. symlink ( p2, p) ?;
240+ td. atomic_write ( p, "atomic replacement symlink\n " ) . unwrap ( ) ;
241+ assert_eq ! ( td. metadata( p) ?. permissions( ) , default_perms) ;
242+ // And break the link
243+ td. remove_file ( p2) ?;
244+ td. atomic_write ( p, "atomic replacement symlink\n " ) . unwrap ( ) ;
245+ assert_eq ! ( td. metadata( p) ?. permissions( ) , default_perms) ;
246+
247+ // Also test with mode 0600
248+ td. atomic_write_with_perms ( p, "self-only file" , Permissions :: from_mode ( 0o600 ) )
249+ . unwrap ( ) ;
250+ assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o600 ) ;
251+ td. atomic_write ( p, "self-only file v2" ) . unwrap ( ) ;
252+ assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o600 ) ;
253+ // But we can override
254+ td. atomic_write_with_perms ( p, "self-only file v3" , Permissions :: from_mode ( 0o640 ) )
255+ . unwrap ( ) ;
256+ assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o640 ) ;
257+ }
230258
231- // Also test with mode 0600
232- td. atomic_write_with_perms ( p, "self-only file" , Permissions :: from_mode ( 0o600 ) )
233- . unwrap ( ) ;
234- assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o600 ) ;
235- td. atomic_write ( p, "self-only file v2" ) . unwrap ( ) ;
236- assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o600 ) ;
237- // But we can override
238- td. atomic_write_with_perms ( p, "self-only file v3" , Permissions :: from_mode ( 0o640 ) )
239- . unwrap ( ) ;
240- assert_eq ! ( td. metadata( p) . unwrap( ) . permissions( ) . mode( ) & 0o777 , 0o640 ) ;
241259 Ok ( ( ) )
242260}
243261
244262#[ test]
263+ #[ cfg( unix) ]
245264fn test_timestamps ( ) -> Result < ( ) > {
246265 let td = cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
247266 let p = Path :: new ( "foo" ) ;
@@ -292,20 +311,23 @@ fn ensuredir_utf8() -> Result<()> {
292311 td. write ( p, "some file contents" ) ?;
293312 assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
294313
295- // Broken symlinks aren't followed and are errors
296- let p = Utf8Path :: new ( "linksrc" ) ;
297- td. symlink ( "linkdest" , p) ?;
298- assert ! ( td. metadata( p) . is_err( ) ) ;
299- assert ! ( td
300- . symlink_metadata_optional( p)
301- . unwrap( )
302- . unwrap( )
303- . is_symlink( ) ) ;
304- // Non-broken symlinks are also an error
305- assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
306- td. create_dir ( "linkdest" ) ?;
307- assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
308- assert ! ( td. metadata_optional( p) . unwrap( ) . unwrap( ) . is_dir( ) ) ;
314+ #[ cfg( not( windows) ) ]
315+ {
316+ // Broken symlinks aren't followed and are errors
317+ let p = Utf8Path :: new ( "linksrc" ) ;
318+ td. symlink ( "linkdest" , p) ?;
319+ assert ! ( td. metadata( p) . is_err( ) ) ;
320+ assert ! ( td
321+ . symlink_metadata_optional( p)
322+ . unwrap( )
323+ . unwrap( )
324+ . is_symlink( ) ) ;
325+ // Non-broken symlinks are also an error
326+ assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
327+ td. create_dir ( "linkdest" ) ?;
328+ assert ! ( td. ensure_dir_with( p, b) . is_err( ) ) ;
329+ assert ! ( td. metadata_optional( p) . unwrap( ) . unwrap( ) . is_dir( ) ) ;
330+ }
309331
310332 Ok ( ( ) )
311333}
@@ -345,6 +367,7 @@ fn filenames_utf8() -> Result<()> {
345367}
346368
347369#[ test]
370+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
348371fn test_rootdir_open ( ) -> Result < ( ) > {
349372 let td = & cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
350373 let root = RootDir :: new ( td, "." ) . unwrap ( ) ;
@@ -373,6 +396,7 @@ fn test_rootdir_open() -> Result<()> {
373396}
374397
375398#[ test]
399+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
376400fn test_rootdir_entries ( ) -> Result < ( ) > {
377401 let td = & cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
378402 let root = RootDir :: new ( td, "." ) . unwrap ( ) ;
@@ -389,6 +413,7 @@ fn test_rootdir_entries() -> Result<()> {
389413}
390414
391415#[ test]
416+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
392417fn test_mountpoint ( ) -> Result < ( ) > {
393418 let root = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
394419 assert_eq ! ( root. is_mountpoint( "." ) . unwrap( ) , Some ( true ) ) ;
@@ -413,7 +438,7 @@ fn test_open_noxdev() -> Result<()> {
413438 // This hard requires the host setup to have /usr/bin on the same filesystem as /
414439 let usr = Dir :: open_ambient_dir ( "/usr" , cap_std:: ambient_authority ( ) ) ?;
415440 assert ! ( usr. open_dir_noxdev( "bin" ) . unwrap( ) . is_some( ) ) ;
416- // Requires a mounted /proc, but that also seems ane .
441+ // Requires a mounted /proc, but that also seems sane .
417442 assert ! ( root. open_dir_noxdev( "proc" ) . unwrap( ) . is_none( ) ) ;
418443 // Test an error case
419444 let td = cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
@@ -433,10 +458,13 @@ fn test_walk() -> std::io::Result<()> {
433458 td. write ( "usr/bin/true" , b"true" ) ?;
434459 td. write ( "usr/lib/foo/libfoo.so" , b"libfoo" ) ?;
435460 td. write ( "usr/lib/libbar.so" , b"libbar" ) ?;
436- // Broken link
437- td. symlink ( "usr/share/timezone" , "usr/share/EST" ) ?;
438- // Symlink to self
439- td. symlink ( "." , "usr/bin/selflink" ) ?;
461+ #[ cfg( not( windows) ) ]
462+ {
463+ // Broken link
464+ td. symlink ( "usr/share/timezone" , "usr/share/EST" ) ?;
465+ // Symlink to self
466+ td. symlink ( "." , "usr/bin/selflink" ) ?;
467+ }
440468 td. write ( "etc/foo.conf" , b"fooconf" ) ?;
441469 td. write ( "etc/blah.conf" , b"blahconf" ) ?;
442470
@@ -466,6 +494,7 @@ fn test_walk() -> std::io::Result<()> {
466494 } )
467495 . unwrap ( ) ;
468496 assert_eq ! ( n_dirs, 4 ) ;
497+ #[ cfg( not( windows) ) ]
469498 assert_eq ! ( n_symlinks, 2 ) ;
470499 assert_eq ! ( n_regfiles, 4 ) ;
471500 }
@@ -488,6 +517,7 @@ fn test_walk() -> std::io::Result<()> {
488517}
489518
490519#[ test]
520+ #[ cfg( unix) ]
491521fn test_walk_sorted ( ) -> Result < ( ) > {
492522 let td = cap_tempfile:: TempDir :: new ( cap_std:: ambient_authority ( ) ) ?;
493523
@@ -536,6 +566,7 @@ fn test_walk_sorted() -> Result<()> {
536566}
537567
538568#[ test]
569+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
539570fn test_walk_noxdev ( ) -> Result < ( ) > {
540571 let rootfs = Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
541572
0 commit comments