@@ -17,8 +17,15 @@ const RULE_HIDE_DEVICE_EARLY_PRIORITY: &str = "50";
1717const RULE_HIDE_DEVICE_LATE_PRIORITY : & str = "96" ;
1818const RULES_PREFIX : & str = "/run/udev/rules.d" ;
1919
20+ /// HideFlags can be used to change the behavior of how devices are hidden.
21+ #[ derive( Debug , PartialEq , Eq ) ]
22+ pub enum HideFlag {
23+ ChangePermissions ,
24+ MoveSourceDevice ,
25+ }
26+
2027/// Hide the given input device from regular users.
21- pub async fn hide_device ( path : & str ) -> Result < ( ) , Box < dyn Error > > {
28+ pub async fn hide_device ( path : & str , flags : & [ HideFlag ] ) -> Result < ( ) , Box < dyn Error > > {
2229 // Get the device to hide
2330 let device = get_device ( path. to_string ( ) ) . await ?;
2431 let name = device. name . clone ( ) ;
@@ -30,34 +37,64 @@ pub async fn hide_device(path: &str) -> Result<(), Box<dyn Error>> {
3037 return Err ( "Unable to create match rule for device" . into ( ) ) ;
3138 } ;
3239
33- // Create the directory to move devnodes to
34- tokio:: fs:: create_dir_all ( "/dev/inputplumber/sources" ) . await ?;
40+ // Create the udev rule content to update permissions on the source node.
41+ let mut chmod_early_rule = String :: new ( ) ;
42+ let mut chmod_late_rule = String :: new ( ) ;
43+ if flags. contains ( & HideFlag :: ChangePermissions ) {
44+ // Find the chmod command to use for hiding
45+ let chmod_cmd = if Path :: new ( "/bin/chmod" ) . exists ( ) {
46+ "/bin/chmod" . to_string ( )
47+ } else if Path :: new ( "/usr/bin/chmod" ) . exists ( ) {
48+ "/usr/bin/chmod" . to_string ( )
49+ } else {
50+ let output = Command :: new ( "which" ) . arg ( "chmod" ) . output ( ) . await ?;
51+ if !output. status . success ( ) {
52+ return Err ( "Unable to determine chmod command location" . into ( ) ) ;
53+ }
54+ str:: from_utf8 ( output. stdout . as_slice ( ) ) ?. trim ( ) . to_string ( )
55+ } ;
3556
36- // Find the chmod command to use for hiding
37- let chmod_cmd = if Path :: new ( "/bin/chmod" ) . exists ( ) {
38- "/bin/chmod" . to_string ( )
39- } else if Path :: new ( "/usr/bin/chmod" ) . exists ( ) {
40- "/usr/bin/chmod" . to_string ( )
41- } else {
42- let output = Command :: new ( "which" ) . arg ( "chmod" ) . output ( ) . await ? ;
43- if !output . status . success ( ) {
44- return Err ( "Unable to determine chmod command location" . into ( ) ) ;
45- }
46- str :: from_utf8 ( output . stdout . as_slice ( ) ) ? . trim ( ) . to_string ( )
47- } ;
57+ // Build the rule content
58+ chmod_early_rule = format ! (
59+ r#"KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", MODE:="0000", GROUP:="root", RUN+="{chmod_cmd} 000 /dev/input/%k", SYMLINK+="inputplumber/by-hidden/%k"
60+ KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE:="0000", GROUP:="root", RUN+="{chmod_cmd} 000 /dev/%k", SYMLINK+="inputplumber/by-hidden/%k"
61+ "#
62+ ) ;
63+ chmod_late_rule = format ! (
64+ r#"KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/input/%k"
65+ KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/%k"
66+ "#
67+ ) ;
68+ }
4869
49- // Find the mv command to use for hiding
50- let mv_cmd = if Path :: new ( "/bin/mv" ) . exists ( ) {
51- "/bin/mv" . to_string ( )
52- } else if Path :: new ( "/usr/bin/mv" ) . exists ( ) {
53- "/usr/bin/mv" . to_string ( )
54- } else {
55- let output = Command :: new ( "which" ) . arg ( "mv" ) . output ( ) . await ?;
56- if !output. status . success ( ) {
57- return Err ( "Unable to determine mv command location" . into ( ) ) ;
58- }
59- str:: from_utf8 ( output. stdout . as_slice ( ) ) ?. trim ( ) . to_string ( )
60- } ;
70+ // Create the udev rule content to move the device node
71+ let mut mv_early_rule = String :: new ( ) ;
72+ let mut mv_late_rule = String :: new ( ) ;
73+ if flags. contains ( & HideFlag :: MoveSourceDevice ) {
74+ // Create the directory to move devnodes to
75+ tokio:: fs:: create_dir_all ( "/dev/inputplumber/sources" ) . await ?;
76+
77+ // Find the mv command to use for hiding
78+ let mv_cmd = if Path :: new ( "/bin/mv" ) . exists ( ) {
79+ "/bin/mv" . to_string ( )
80+ } else if Path :: new ( "/usr/bin/mv" ) . exists ( ) {
81+ "/usr/bin/mv" . to_string ( )
82+ } else {
83+ let output = Command :: new ( "which" ) . arg ( "mv" ) . output ( ) . await ?;
84+ if !output. status . success ( ) {
85+ return Err ( "Unable to determine mv command location" . into ( ) ) ;
86+ }
87+ str:: from_utf8 ( output. stdout . as_slice ( ) ) ?. trim ( ) . to_string ( )
88+ } ;
89+
90+ // Build the rule content
91+ mv_early_rule = format ! (
92+ r#"KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/input/%k /dev/inputplumber/sources/%k"
93+ KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/%k /dev/inputplumber/sources/%k"
94+ "#
95+ ) ;
96+ mv_late_rule = mv_early_rule. clone ( ) ;
97+ }
6198
6299 // Create an early udev rule to hide the device
63100 let rule = format ! (
@@ -66,10 +103,8 @@ pub async fn hide_device(path: &str) -> Result<(), Box<dyn Error>> {
66103{match_rule}, GOTO="inputplumber_valid"
67104GOTO="inputplumber_end"
68105LABEL="inputplumber_valid"
69- KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", MODE:="0000", GROUP:="root", RUN+="{chmod_cmd} 000 /dev/input/%k", SYMLINK+="inputplumber/by-hidden/%k"
70- KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE:="0000", GROUP:="root", RUN+="{chmod_cmd} 000 /dev/%k", SYMLINK+="inputplumber/by-hidden/%k"
71- KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/input/%k /dev/inputplumber/sources/%k"
72- KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/%k /dev/inputplumber/sources/%k"
106+ {chmod_early_rule}
107+ {mv_early_rule}
73108LABEL="inputplumber_end"
74109"#
75110 ) ;
@@ -87,10 +122,8 @@ LABEL="inputplumber_end"
87122{match_rule}, GOTO="inputplumber_valid"
88123GOTO="inputplumber_end"
89124LABEL="inputplumber_valid"
90- KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/input/%k"
91- KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", MODE="000", GROUP="root", TAG-="uaccess", RUN+="{chmod_cmd} 000 /dev/%k"
92- KERNEL=="js[0-9]*|event[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/input/%k /dev/inputplumber/sources/%k"
93- KERNEL=="hidraw[0-9]*", SUBSYSTEM=="{subsystem}", RUN+="{mv_cmd} /dev/%k /dev/inputplumber/sources/%k"
125+ {chmod_late_rule}
126+ {mv_late_rule}
94127LABEL="inputplumber_end"
95128"#
96129 ) ;
0 commit comments