33// For the full copyright and license information, please view the LICENSE
44// file that was distributed with this source code.
55
6- // spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO
6+ // spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag
77
88use clap:: { Arg , ArgAction , Command , value_parser} ;
9- use libc:: { S_IFBLK , S_IFCHR , S_IFIFO , S_IRGRP , S_IROTH , S_IRUSR , S_IWGRP , S_IWOTH , S_IWUSR } ;
10- use libc:: { dev_t, mode_t} ;
11- use std:: ffi:: CString ;
9+ use nix:: libc:: { S_IRGRP , S_IROTH , S_IRUSR , S_IWGRP , S_IWOTH , S_IWUSR , mode_t} ;
10+ use nix:: sys:: stat:: { Mode , SFlag , mknod as nix_mknod, umask as nix_umask} ;
1211
1312use uucore:: display:: Quotable ;
1413use uucore:: error:: { UResult , USimpleError , UUsageError , set_exit_code} ;
1514use uucore:: format_usage;
1615use uucore:: fs:: makedev;
1716use uucore:: translate;
1817
19- const MODE_RW_UGO : mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ;
18+ #[ allow( clippy:: unnecessary_cast) ]
19+ const MODE_RW_UGO : u32 = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ) as u32 ;
2020
2121mod options {
2222 pub const MODE : & str = "mode" ;
@@ -35,86 +35,94 @@ enum FileType {
3535}
3636
3737impl FileType {
38- fn as_mode ( & self ) -> mode_t {
38+ fn as_sflag ( & self ) -> SFlag {
3939 match self {
40- Self :: Block => S_IFBLK ,
41- Self :: Character => S_IFCHR ,
42- Self :: Fifo => S_IFIFO ,
40+ Self :: Block => SFlag :: S_IFBLK ,
41+ Self :: Character => SFlag :: S_IFCHR ,
42+ Self :: Fifo => SFlag :: S_IFIFO ,
4343 }
4444 }
4545}
4646
4747/// Configuration for special inode creation.
48- pub struct Config < ' a > {
49- /// bitmask of inode mode (permissions and file type)
50- pub mode : mode_t ,
48+ struct Config {
49+ /// Permission bits for the inode
50+ mode : Mode ,
51+
52+ file_type : FileType ,
5153
5254 /// when false, the exact mode bits will be set
53- pub use_umask : bool ,
55+ use_umask : bool ,
5456
55- pub dev : dev_t ,
57+ dev : u64 ,
5658
5759 /// Set security context (SELinux/SMACK).
58- pub set_security_context : bool ,
60+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
61+ set_security_context : bool ,
5962
6063 /// Specific security context (SELinux/SMACK).
61- pub context : Option < & ' a String > ,
64+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
65+ context : Option < String > ,
6266}
6367
6468fn mknod ( file_name : & str , config : Config ) -> i32 {
65- let c_str = CString :: new ( file_name) . expect ( "Failed to convert to CString" ) ;
66-
67- unsafe {
68- // set umask to 0 and store previous umask
69- let have_prev_umask = if config. use_umask {
70- None
71- } else {
72- Some ( libc:: umask ( 0 ) )
73- } ;
69+ // set umask to 0 and store previous umask
70+ let have_prev_umask = if config. use_umask {
71+ None
72+ } else {
73+ Some ( nix_umask ( Mode :: empty ( ) ) )
74+ } ;
7475
75- let errno = libc:: mknod ( c_str. as_ptr ( ) , config. mode , config. dev ) ;
76+ let mknod_err = nix_mknod (
77+ file_name,
78+ config. file_type . as_sflag ( ) ,
79+ config. mode ,
80+ config. dev as _ ,
81+ )
82+ . err ( ) ;
83+ let errno = if mknod_err. is_some ( ) { -1 } else { 0 } ;
7684
77- // set umask back to original value
78- if let Some ( prev_umask) = have_prev_umask {
79- libc :: umask ( prev_umask) ;
80- }
85+ // set umask back to original value
86+ if let Some ( prev_umask) = have_prev_umask {
87+ nix_umask ( prev_umask) ;
88+ }
8189
82- if errno == -1 {
83- let c_str = CString :: new ( uucore:: execution_phrase ( ) . as_bytes ( ) )
84- . expect ( "Failed to convert to CString" ) ;
85- // shows the error from the mknod syscall
86- libc:: perror ( c_str. as_ptr ( ) ) ;
87- }
90+ if let Some ( err) = mknod_err {
91+ eprintln ! (
92+ "{}: {}" ,
93+ uucore:: execution_phrase( ) ,
94+ std:: io:: Error :: from( err)
95+ ) ;
96+ }
8897
89- // Apply SELinux context if requested
90- #[ cfg( feature = "selinux" ) ]
91- if config. set_security_context {
92- if let Err ( e) = uucore:: selinux:: set_selinux_security_context (
93- std:: path:: Path :: new ( file_name) ,
94- config. context ,
95- ) {
96- // if it fails, delete the file
97- let _ = std:: fs:: remove_file ( file_name) ;
98- eprintln ! ( "{}: {e}" , uucore:: util_name( ) ) ;
99- return 1 ;
100- }
98+ // Apply SELinux context if requested
99+ #[ cfg( feature = "selinux" ) ]
100+ if config. set_security_context {
101+ if let Err ( e) = uucore:: selinux:: set_selinux_security_context (
102+ std:: path:: Path :: new ( file_name) ,
103+ config. context . as_ref ( ) ,
104+ ) {
105+ // if it fails, delete the file
106+ let _ = std:: fs:: remove_file ( file_name) ;
107+ eprintln ! ( "{}: {e}" , uucore:: util_name( ) ) ;
108+ return 1 ;
101109 }
110+ }
102111
103- // Apply SMACK context if requested
104- #[ cfg( feature = "smack" ) ]
105- if config. set_security_context {
106- if let Err ( e) =
107- uucore:: smack:: set_smack_label_and_cleanup ( file_name, config. context , |p| {
108- std:: fs:: remove_file ( p)
109- } )
110- {
111- eprintln ! ( "{}: {e}" , uucore:: util_name( ) ) ;
112- return 1 ;
113- }
112+ // Apply SMACK context if requested
113+ #[ cfg( feature = "smack" ) ]
114+ if config. set_security_context {
115+ if let Err ( e) =
116+ uucore:: smack:: set_smack_label_and_cleanup ( file_name, config. context . as_ref ( ) , |p| {
117+ std:: fs:: remove_file ( p)
118+ } )
119+ {
120+ eprintln ! ( "{}: {e}" , uucore:: util_name( ) ) ;
121+ return 1 ;
114122 }
115-
116- errno
117123 }
124+
125+ errno
118126}
119127
120128#[ uucore:: main]
@@ -131,15 +139,17 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
131139 parse_mode ( str_mode) . map_err ( |e| USimpleError :: new ( 1 , e) ) ?
132140 }
133141 } ;
134- let mode = mode_permissions | file_type . as_mode ( ) ;
142+ let mode = Mode :: from_bits_truncate ( mode_permissions as mode_t ) ;
135143
136144 let file_name = matches
137145 . get_one :: < String > ( "name" )
138146 . expect ( "Missing argument 'NAME'" ) ;
139147
140148 // Extract the security context related flags and options
149+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
141150 let set_security_context = matches. get_flag ( options:: SECURITY_CONTEXT ) ;
142- let context = matches. get_one :: < String > ( options:: CONTEXT ) ;
151+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
152+ let context = matches. get_one :: < String > ( options:: CONTEXT ) . cloned ( ) ;
143153
144154 let dev = match (
145155 file_type,
@@ -153,7 +163,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
153163 translate ! ( "mknod-error-fifo-no-major-minor" ) ,
154164 ) ) ;
155165 }
156- ( _, Some ( & major) , Some ( & minor) ) => makedev ( major as _ , minor as _ ) ,
166+ ( _, Some ( & major) , Some ( & minor) ) => makedev ( major as _ , minor as _ ) as u64 ,
157167 _ => {
158168 return Err ( UUsageError :: new (
159169 1 ,
@@ -164,9 +174,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
164174
165175 let config = Config {
166176 mode,
177+ file_type : file_type. clone ( ) ,
167178 use_umask,
168179 dev,
180+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
169181 set_security_context : set_security_context || context. is_some ( ) ,
182+ #[ cfg( any( feature = "selinux" , feature = "smack" ) ) ]
170183 context,
171184 } ;
172185
@@ -233,9 +246,8 @@ pub fn uu_app() -> Command {
233246 )
234247}
235248
236- #[ allow( clippy:: unnecessary_cast) ]
237- fn parse_mode ( str_mode : & str ) -> Result < mode_t , String > {
238- let default_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ) as u32 ;
249+ fn parse_mode ( str_mode : & str ) -> Result < u32 , String > {
250+ let default_mode = MODE_RW_UGO ;
239251 uucore:: mode:: parse_chmod ( default_mode, str_mode, true , uucore:: mode:: get_umask ( ) )
240252 . map_err ( |e| {
241253 translate ! (
@@ -247,7 +259,7 @@ fn parse_mode(str_mode: &str) -> Result<mode_t, String> {
247259 if mode > 0o777 {
248260 Err ( translate ! ( "mknod-error-mode-permission-bits-only" ) )
249261 } else {
250- Ok ( mode as mode_t )
262+ Ok ( mode)
251263 }
252264 } )
253265}
0 commit comments