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 = 0o170000 ; // bitmask for the file-type field
474+ pub const S_IFSOCK : u32 = 0o140000 ; // socket
475+ pub const S_IFLNK : u32 = 0o120000 ; // symbolic link
476+ pub const S_IFREG : u32 = 0o100000 ; // regular file
477+ pub const S_IFBLK : u32 = 0o060000 ; // block device
478+ pub const S_IFDIR : u32 = 0o040000 ; // directory
479+ pub const S_IFCHR : u32 = 0o020000 ; // character device
480+ pub const S_IFIFO : u32 = 0o010000 ; // 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 :: * ;
487515 match mode & S_IFMT {
488516 S_IFDIR => 'd' ,
489517 S_IFCHR => 'c' ,
@@ -500,9 +528,9 @@ 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 :: * ;
506534 let mut result;
507535 if display_file_type {
508536 result = String :: with_capacity ( 10 ) ;
@@ -511,31 +539,31 @@ pub fn display_permissions_unix(mode: mode_t, display_file_type: bool) -> String
511539 result = String :: with_capacity ( 9 ) ;
512540 }
513541
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 ) {
542+ result. push ( if mode & S_IRUSR != 0 { 'r' } else { '-' } ) ;
543+ result. push ( if mode & S_IWUSR != 0 { 'w' } else { '-' } ) ;
544+ result. push ( if mode & S_ISUID != 0 {
545+ if mode & S_IXUSR != 0 { 's' } else { 'S' }
546+ } else if mode & S_IXUSR != 0 {
519547 'x'
520548 } else {
521549 '-'
522550 } ) ;
523551
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 ) {
552+ result. push ( if mode & S_IRGRP != 0 { 'r' } else { '-' } ) ;
553+ result. push ( if mode & S_IWGRP != 0 { 'w' } else { '-' } ) ;
554+ result. push ( if mode & S_ISGID != 0 {
555+ if mode & S_IXGRP != 0 { 's' } else { 'S' }
556+ } else if mode & S_IXGRP != 0 {
529557 'x'
530558 } else {
531559 '-'
532560 } ) ;
533561
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 ) {
562+ result. push ( if mode & S_IROTH != 0 { 'r' } else { '-' } ) ;
563+ result. push ( if mode & S_IWOTH != 0 { 'w' } else { '-' } ) ;
564+ result. push ( if mode & S_ISVTX != 0 {
565+ if mode & S_IXOTH != 0 { 't' } else { 'T' }
566+ } else if mode & S_IXOTH != 0 {
539567 'x'
540568 } else {
541569 '-'
@@ -730,8 +758,9 @@ pub fn path_ends_with_terminator(path: &Path) -> bool {
730758pub fn is_stdin_directory ( stdin : & Stdin ) -> bool {
731759 #[ cfg( unix) ]
732760 {
761+ use mode:: { S_IFDIR , S_IFMT } ;
733762 use nix:: sys:: stat:: fstat;
734- let mode = fstat ( stdin. as_fd ( ) ) . unwrap ( ) . st_mode as mode_t ;
763+ let mode = fstat ( stdin. as_fd ( ) ) . unwrap ( ) . st_mode as u32 ;
735764 // We use the S_IFMT mask ala S_ISDIR() to avoid mistaking
736765 // sockets for directories.
737766 mode & S_IFMT == S_IFDIR
@@ -964,58 +993,25 @@ mod tests {
964993 }
965994 }
966995
967- #[ cfg( unix) ]
968996 #[ test]
969997 fn test_display_permissions ( ) {
998+ use mode:: * ;
970999 // spell-checker:ignore (perms) brwsr drwxr rwxr
971- assert_eq ! (
972- "drwxr-xr-x" ,
973- display_permissions_unix( S_IFDIR | 0o755 , true )
974- ) ;
975- assert_eq ! (
976- "rwxr-xr-x" ,
977- display_permissions_unix( S_IFDIR | 0o755 , false )
978- ) ;
979- assert_eq ! (
980- "-rw-r--r--" ,
981- display_permissions_unix( S_IFREG | 0o644 , true )
982- ) ;
983- assert_eq ! (
984- "srw-r-----" ,
985- display_permissions_unix( S_IFSOCK | 0o640 , true )
986- ) ;
987- assert_eq ! (
988- "lrw-r-xr-x" ,
989- display_permissions_unix( S_IFLNK | 0o655 , true )
990- ) ;
1000+ assert_eq ! ( "drwxr-xr-x" , display_permissions_unix( S_IFDIR | 0o755 , true ) ) ;
1001+ assert_eq ! ( "rwxr-xr-x" , display_permissions_unix( S_IFDIR | 0o755 , false ) ) ;
1002+ assert_eq ! ( "-rw-r--r--" , display_permissions_unix( S_IFREG | 0o644 , true ) ) ;
1003+ assert_eq ! ( "srw-r-----" , display_permissions_unix( S_IFSOCK | 0o640 , true ) ) ;
1004+ assert_eq ! ( "lrw-r-xr-x" , display_permissions_unix( S_IFLNK | 0o655 , true ) ) ;
9911005 assert_eq ! ( "?rw-r-xr-x" , display_permissions_unix( 0o655 , true ) ) ;
9921006
993- assert_eq ! (
994- "brwSr-xr-x" ,
995- display_permissions_unix( S_IFBLK | S_ISUID as mode_t | 0o655 , true )
996- ) ;
997- assert_eq ! (
998- "brwsr-xr-x" ,
999- display_permissions_unix( S_IFBLK | S_ISUID as mode_t | 0o755 , true )
1000- ) ;
1001-
1002- assert_eq ! (
1003- "prw---sr--" ,
1004- display_permissions_unix( S_IFIFO | S_ISGID as mode_t | 0o614 , true )
1005- ) ;
1006- assert_eq ! (
1007- "prw---Sr--" ,
1008- display_permissions_unix( S_IFIFO | S_ISGID as mode_t | 0o604 , true )
1009- ) ;
1010-
1011- assert_eq ! (
1012- "c---r-xr-t" ,
1013- display_permissions_unix( S_IFCHR | S_ISVTX as mode_t | 0o055 , true )
1014- ) ;
1015- assert_eq ! (
1016- "c---r-xr-T" ,
1017- display_permissions_unix( S_IFCHR | S_ISVTX as mode_t | 0o054 , true )
1018- ) ;
1007+ assert_eq ! ( "brwSr-xr-x" , display_permissions_unix( S_IFBLK | S_ISUID | 0o655 , true ) ) ;
1008+ assert_eq ! ( "brwsr-xr-x" , display_permissions_unix( S_IFBLK | S_ISUID | 0o755 , true ) ) ;
1009+
1010+ assert_eq ! ( "prw---sr--" , display_permissions_unix( S_IFIFO | S_ISGID | 0o614 , true ) ) ;
1011+ assert_eq ! ( "prw---Sr--" , display_permissions_unix( S_IFIFO | S_ISGID | 0o604 , true ) ) ;
1012+
1013+ assert_eq ! ( "c---r-xr-t" , display_permissions_unix( S_IFCHR | S_ISVTX | 0o055 , true ) ) ;
1014+ assert_eq ! ( "c---r-xr-T" , display_permissions_unix( S_IFCHR | S_ISVTX | 0o054 , true ) ) ;
10191015 }
10201016
10211017 #[ cfg( unix) ]
@@ -1095,9 +1091,9 @@ mod tests {
10951091 assert ! ( are_hardlinks_to_same_file( path1, & path2) ) ;
10961092 }
10971093
1098- #[ cfg( unix) ]
10991094 #[ test]
11001095 fn test_get_file_display ( ) {
1096+ use mode:: * ;
11011097 assert_eq ! ( get_file_display( S_IFDIR | 0o755 ) , 'd' ) ;
11021098 assert_eq ! ( get_file_display( S_IFCHR | 0o644 ) , 'c' ) ;
11031099 assert_eq ! ( get_file_display( S_IFBLK | 0o600 ) , 'b' ) ;
0 commit comments