88// spell-checker:ignore backport
99
1010#[ cfg( unix) ]
11- use libc:: {
12- S_IFBLK , S_IFCHR , S_IFDIR , S_IFIFO , S_IFLNK , S_IFMT , S_IFREG , S_IFSOCK , S_IRGRP , S_IROTH ,
13- S_IRUSR , S_ISGID , S_ISUID , S_ISVTX , S_IWGRP , S_IWOTH , S_IWUSR , S_IXGRP , S_IXOTH , S_IXUSR ,
14- mkfifo, mode_t,
15- } ;
11+ use libc:: mkfifo;
1612#[ cfg( all( unix, not( target_os = "redox" ) ) ) ]
1713pub use libc:: { major, makedev, minor} ;
1814use std:: collections:: HashSet ;
@@ -464,12 +460,44 @@ pub fn display_permissions(metadata: &fs::Metadata, display_file_type: bool) ->
464460#[ cfg( unix) ]
465461/// Display the permissions of a file
466462pub fn display_permissions ( metadata : & fs:: Metadata , display_file_type : bool ) -> String {
467- let mode: mode_t = metadata. mode ( ) as mode_t ;
468- display_permissions_unix ( mode, display_file_type)
463+ display_permissions_unix ( metadata. mode ( ) , display_file_type)
464+ }
465+
466+ /// Portable file mode bit constants, equivalent to the POSIX `S_I*` values.
467+ ///
468+ /// These are defined here as plain `u32` so they are available on every
469+ /// platform, including Windows, without requiring `libc` or a Unix target.
470+ /// Callers that previously used `libc::S_IFDIR` etc. can import these instead.
471+ pub mod mode {
472+ // File-type mask and values
473+ pub const S_IFMT : u32 = 0o170_000 ; // bitmask for the file-type field
474+ pub const S_IFSOCK : u32 = 0o140_000 ; // socket
475+ pub const S_IFLNK : u32 = 0o120_000 ; // symbolic link
476+ pub const S_IFREG : u32 = 0o100_000 ; // regular file
477+ pub const S_IFBLK : u32 = 0o060_000 ; // block device
478+ pub const S_IFDIR : u32 = 0o040_000 ; // directory
479+ pub const S_IFCHR : u32 = 0o020_000 ; // character device
480+ pub const S_IFIFO : u32 = 0o010_000 ; // named pipe (FIFO)
481+
482+ // Permission and special-mode bits
483+ pub const S_ISUID : u32 = 0o4000 ; // setuid
484+ pub const S_ISGID : u32 = 0o2000 ; // setgid
485+ pub const S_ISVTX : u32 = 0o1000 ; // sticky
486+
487+ pub const S_IRUSR : u32 = 0o0400 ; // owner read
488+ pub const S_IWUSR : u32 = 0o0200 ; // owner write
489+ pub const S_IXUSR : u32 = 0o0100 ; // owner execute
490+
491+ pub const S_IRGRP : u32 = 0o0040 ; // group read
492+ pub const S_IWGRP : u32 = 0o0020 ; // group write
493+ pub const S_IXGRP : u32 = 0o0010 ; // group execute
494+
495+ pub const S_IROTH : u32 = 0o0004 ; // other read
496+ pub const S_IWOTH : u32 = 0o0002 ; // other write
497+ pub const S_IXOTH : u32 = 0o0001 ; // other execute
469498}
470499
471500/// Returns a character representation of the file type based on its mode.
472- /// This function is specific to Unix-like systems.
473501///
474502/// - `mode`: The mode of the file, typically obtained from file metadata.
475503///
@@ -482,8 +510,8 @@ pub fn display_permissions(metadata: &fs::Metadata, display_file_type: bool) ->
482510/// - 'l' for symbolic links
483511/// - 's' for sockets
484512/// - '?' for any other unrecognized file types
485- # [ cfg ( unix ) ]
486- fn get_file_display ( mode : mode_t ) -> char {
513+ fn get_file_display ( mode : u32 ) -> char {
514+ use mode:: { S_IFBLK , S_IFCHR , S_IFDIR , S_IFIFO , S_IFLNK , S_IFMT , S_IFREG , S_IFSOCK } ;
487515 match mode & S_IFMT {
488516 S_IFDIR => 'd' ,
489517 S_IFCHR => 'c' ,
@@ -500,9 +528,12 @@ fn get_file_display(mode: mode_t) -> char {
500528// The logic below is more readable written this way.
501529#[ allow( clippy:: if_not_else) ]
502530#[ allow( clippy:: cognitive_complexity) ]
503- #[ cfg( unix) ]
504- /// Display the permissions of a file on a unix like system
505- pub fn display_permissions_unix ( mode : mode_t , display_file_type : bool ) -> String {
531+ /// Display the unix permissions of a file
532+ pub fn display_permissions_unix ( mode : u32 , display_file_type : bool ) -> String {
533+ use mode:: {
534+ S_IRGRP , S_IROTH , S_IRUSR , S_ISGID , S_ISUID , S_ISVTX , S_IWGRP , S_IWOTH , S_IWUSR , S_IXGRP ,
535+ S_IXOTH , S_IXUSR ,
536+ } ;
506537 let mut result;
507538 if display_file_type {
508539 result = String :: with_capacity ( 10 ) ;
@@ -511,31 +542,31 @@ pub fn display_permissions_unix(mode: mode_t, display_file_type: bool) -> String
511542 result = String :: with_capacity ( 9 ) ;
512543 }
513544
514- result. push ( if has ! ( mode, S_IRUSR ) { 'r' } else { '-' } ) ;
515- result. push ( if has ! ( mode, S_IWUSR ) { 'w' } else { '-' } ) ;
516- result. push ( if has ! ( mode, S_ISUID as mode_t ) {
517- if has ! ( mode, S_IXUSR ) { 's' } else { 'S' }
518- } else if has ! ( mode, S_IXUSR ) {
545+ result. push ( if mode & S_IRUSR != 0 { 'r' } else { '-' } ) ;
546+ result. push ( if mode & S_IWUSR != 0 { 'w' } else { '-' } ) ;
547+ result. push ( if mode & S_ISUID != 0 {
548+ if mode & S_IXUSR != 0 { 's' } else { 'S' }
549+ } else if mode & S_IXUSR != 0 {
519550 'x'
520551 } else {
521552 '-'
522553 } ) ;
523554
524- result. push ( if has ! ( mode, S_IRGRP ) { 'r' } else { '-' } ) ;
525- result. push ( if has ! ( mode, S_IWGRP ) { 'w' } else { '-' } ) ;
526- result. push ( if has ! ( mode, S_ISGID as mode_t ) {
527- if has ! ( mode, S_IXGRP ) { 's' } else { 'S' }
528- } else if has ! ( mode, S_IXGRP ) {
555+ result. push ( if mode & S_IRGRP != 0 { 'r' } else { '-' } ) ;
556+ result. push ( if mode & S_IWGRP != 0 { 'w' } else { '-' } ) ;
557+ result. push ( if mode & S_ISGID != 0 {
558+ if mode & S_IXGRP != 0 { 's' } else { 'S' }
559+ } else if mode & S_IXGRP != 0 {
529560 'x'
530561 } else {
531562 '-'
532563 } ) ;
533564
534- result. push ( if has ! ( mode, S_IROTH ) { 'r' } else { '-' } ) ;
535- result. push ( if has ! ( mode, S_IWOTH ) { 'w' } else { '-' } ) ;
536- result. push ( if has ! ( mode, S_ISVTX as mode_t ) {
537- if has ! ( mode, S_IXOTH ) { 't' } else { 'T' }
538- } else if has ! ( mode, S_IXOTH ) {
565+ result. push ( if mode & S_IROTH != 0 { 'r' } else { '-' } ) ;
566+ result. push ( if mode & S_IWOTH != 0 { 'w' } else { '-' } ) ;
567+ result. push ( if mode & S_ISVTX != 0 {
568+ if mode & S_IXOTH != 0 { 't' } else { 'T' }
569+ } else if mode & S_IXOTH != 0 {
539570 'x'
540571 } else {
541572 '-'
@@ -730,8 +761,9 @@ pub fn path_ends_with_terminator(path: &Path) -> bool {
730761pub fn is_stdin_directory ( stdin : & Stdin ) -> bool {
731762 #[ cfg( unix) ]
732763 {
764+ use mode:: { S_IFDIR , S_IFMT } ;
733765 use nix:: sys:: stat:: fstat;
734- let mode = fstat ( stdin. as_fd ( ) ) . unwrap ( ) . st_mode as mode_t ;
766+ let mode = fstat ( stdin. as_fd ( ) ) . unwrap ( ) . st_mode as u32 ;
735767 // We use the S_IFMT mask ala S_ISDIR() to avoid mistaking
736768 // sockets for directories.
737769 mode & S_IFMT == S_IFDIR
@@ -964,9 +996,9 @@ mod tests {
964996 }
965997 }
966998
967- #[ cfg( unix) ]
968999 #[ test]
9691000 fn test_display_permissions ( ) {
1001+ use mode:: * ;
9701002 // spell-checker:ignore (perms) brwsr drwxr rwxr
9711003 assert_eq ! (
9721004 "drwxr-xr-x" ,
@@ -992,29 +1024,29 @@ mod tests {
9921024
9931025 assert_eq ! (
9941026 "brwSr-xr-x" ,
995- display_permissions_unix( S_IFBLK | S_ISUID as mode_t | 0o655 , true )
1027+ display_permissions_unix( S_IFBLK | S_ISUID | 0o655 , true )
9961028 ) ;
9971029 assert_eq ! (
9981030 "brwsr-xr-x" ,
999- display_permissions_unix( S_IFBLK | S_ISUID as mode_t | 0o755 , true )
1031+ display_permissions_unix( S_IFBLK | S_ISUID | 0o755 , true )
10001032 ) ;
10011033
10021034 assert_eq ! (
10031035 "prw---sr--" ,
1004- display_permissions_unix( S_IFIFO | S_ISGID as mode_t | 0o614 , true )
1036+ display_permissions_unix( S_IFIFO | S_ISGID | 0o614 , true )
10051037 ) ;
10061038 assert_eq ! (
10071039 "prw---Sr--" ,
1008- display_permissions_unix( S_IFIFO | S_ISGID as mode_t | 0o604 , true )
1040+ display_permissions_unix( S_IFIFO | S_ISGID | 0o604 , true )
10091041 ) ;
10101042
10111043 assert_eq ! (
10121044 "c---r-xr-t" ,
1013- display_permissions_unix( S_IFCHR | S_ISVTX as mode_t | 0o055 , true )
1045+ display_permissions_unix( S_IFCHR | S_ISVTX | 0o055 , true )
10141046 ) ;
10151047 assert_eq ! (
10161048 "c---r-xr-T" ,
1017- display_permissions_unix( S_IFCHR | S_ISVTX as mode_t | 0o054 , true )
1049+ display_permissions_unix( S_IFCHR | S_ISVTX | 0o054 , true )
10181050 ) ;
10191051 }
10201052
@@ -1095,9 +1127,9 @@ mod tests {
10951127 assert ! ( are_hardlinks_to_same_file( path1, & path2) ) ;
10961128 }
10971129
1098- #[ cfg( unix) ]
10991130 #[ test]
11001131 fn test_get_file_display ( ) {
1132+ use mode:: * ;
11011133 assert_eq ! ( get_file_display( S_IFDIR | 0o755 ) , 'd' ) ;
11021134 assert_eq ! ( get_file_display( S_IFCHR | 0o644 ) , 'c' ) ;
11031135 assert_eq ! ( get_file_display( S_IFBLK | 0o600 ) , 'b' ) ;
0 commit comments