@@ -49,10 +49,14 @@ impl FileType {
4949 }
5050}
5151
52- /// Configuration for directory creation.
52+ /// Configuration for special inode creation.
5353pub struct Config < ' a > {
54+ /// bitmask of inode mode (permissions and file type)
5455 pub mode : mode_t ,
5556
57+ /// when false, the exact mode bits will be set
58+ pub use_umask : bool ,
59+
5660 pub dev : dev_t ,
5761
5862 /// Set `SELinux` security context.
@@ -65,18 +69,19 @@ pub struct Config<'a> {
6569fn mknod ( file_name : & str , config : Config ) -> i32 {
6670 let c_str = CString :: new ( file_name) . expect ( "Failed to convert to CString" ) ;
6771
68- // the user supplied a mode
69- let set_umask = config. mode & MODE_RW_UGO != MODE_RW_UGO ;
70-
7172 unsafe {
72- // store prev umask
73- let last_umask = if set_umask { libc:: umask ( 0 ) } else { 0 } ;
73+ // set umask to 0 and store previous umask
74+ let have_prev_umask = if config. use_umask {
75+ None
76+ } else {
77+ Some ( libc:: umask ( 0 ) )
78+ } ;
7479
7580 let errno = libc:: mknod ( c_str. as_ptr ( ) , config. mode , config. dev ) ;
7681
7782 // set umask back to original value
78- if set_umask {
79- libc:: umask ( last_umask ) ;
83+ if let Some ( prev_umask ) = have_prev_umask {
84+ libc:: umask ( prev_umask ) ;
8085 }
8186
8287 if errno == -1 {
@@ -109,8 +114,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
109114 let matches = uu_app ( ) . try_get_matches_from ( args) ?;
110115
111116 let file_type = matches. get_one :: < FileType > ( "type" ) . unwrap ( ) ;
112- let mode = get_mode ( matches. get_one :: < String > ( "mode" ) ) . map_err ( |e| USimpleError :: new ( 1 , e) ) ?
113- | file_type. as_mode ( ) ;
117+
118+ let mut use_umask = true ;
119+ let mode_permissions = match matches. get_one :: < String > ( "mode" ) {
120+ None => MODE_RW_UGO ,
121+ Some ( str_mode) => {
122+ use_umask = false ;
123+ parse_mode ( str_mode) . map_err ( |e| USimpleError :: new ( 1 , e) ) ?
124+ }
125+ } ;
126+ let mode = mode_permissions | file_type. as_mode ( ) ;
114127
115128 let file_name = matches
116129 . get_one :: < String > ( "name" )
@@ -143,6 +156,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
143156
144157 let config = Config {
145158 mode,
159+ use_umask,
146160 dev,
147161 set_selinux_context : set_selinux_context || context. is_some ( ) ,
148162 context,
@@ -210,19 +224,21 @@ pub fn uu_app() -> Command {
210224 )
211225}
212226
213- fn get_mode ( str_mode : Option < & String > ) -> Result < mode_t , String > {
214- match str_mode {
215- None => Ok ( MODE_RW_UGO ) ,
216- Some ( str_mode) => uucore:: mode:: parse_mode ( str_mode)
217- . map_err ( |e| translate ! ( "mknod-error-invalid-mode" , "error" => e) )
218- . and_then ( |mode| {
219- if mode > 0o777 {
220- Err ( translate ! ( "mknod-error-mode-permission-bits-only" ) )
221- } else {
222- Ok ( mode)
223- }
224- } ) ,
225- }
227+ fn parse_mode ( str_mode : & str ) -> Result < mode_t , String > {
228+ uucore:: mode:: parse_mode ( str_mode)
229+ . map_err ( |e| {
230+ translate ! (
231+ "mknod-error-invalid-mode" ,
232+ "error" => e
233+ )
234+ } )
235+ . and_then ( |mode| {
236+ if mode > 0o777 {
237+ Err ( translate ! ( "mknod-error-mode-permission-bits-only" ) )
238+ } else {
239+ Ok ( mode)
240+ }
241+ } )
226242}
227243
228244fn parse_type ( tpe : & str ) -> Result < FileType , String > {
0 commit comments