@@ -5,9 +5,12 @@ use std::collections::{BTreeSet, HashMap};
55
66use log:: * ;
77
8+ /// POSIX requires fds to be assigned as `libc::c_int`, so we can't allow any fds larger than this.
9+ pub const FD_MAX : u32 = i32:: MAX as u32 ;
10+
811/// Map of file handles to file descriptors. Typically owned by a Process.
912pub struct DescriptorTable {
10- descriptors : HashMap < u32 , Descriptor > ,
13+ descriptors : HashMap < DescriptorHandle , Descriptor > ,
1114
1215 // Indices less than `next_index` known to be available.
1316 available_indices : BTreeSet < u32 > ,
@@ -26,9 +29,14 @@ impl DescriptorTable {
2629 }
2730 }
2831
29- /// Add the descriptor at an unused index, and return the index.
30- fn add ( & mut self , descriptor : Descriptor , min_index : u32 ) -> u32 {
31- let idx = if let Some ( idx) = self . available_indices . range ( min_index..) . next ( ) {
32+ /// Add the descriptor at an unused index, and return the index. If the descriptor could not be
33+ /// added, the descriptor is returned in the `Err`.
34+ fn add (
35+ & mut self ,
36+ descriptor : Descriptor ,
37+ min_index : DescriptorHandle ,
38+ ) -> Result < DescriptorHandle , Descriptor > {
39+ let idx = if let Some ( idx) = self . available_indices . range ( min_index. val ( ) ..) . next ( ) {
3240 // Un-borrow from `available_indices`.
3341 let idx = * idx;
3442 // Take from `available_indices`
@@ -38,16 +46,31 @@ impl DescriptorTable {
3846 } else {
3947 // Start our search at either the next likely available index or the minimum index,
4048 // whichever is larger.
41- let mut idx = std:: cmp:: max ( self . next_index , min_index) ;
49+ let mut idx = std:: cmp:: max ( self . next_index , min_index. val ( ) ) ;
50+
51+ // Check if this index out of range.
52+ if idx > FD_MAX {
53+ return Err ( descriptor) ;
54+ }
4255
4356 // Only update next_index if we started at it, otherwise there may be other
4457 // available indexes lower than idx.
4558 let should_update_next_index = idx == self . next_index ;
4659
4760 // Skip past any indexes that are in use. This can happen after
4861 // calling `set` with a value greater than `next_index`.
49- while self . descriptors . contains_key ( & idx) {
62+ while self
63+ . descriptors
64+ . contains_key ( & DescriptorHandle :: new ( idx) . unwrap ( ) )
65+ {
5066 trace ! ( "Skipping past in-use index {}" , idx) ;
67+
68+ // Check if the next index is out of range.
69+ if idx >= FD_MAX {
70+ return Err ( descriptor) ;
71+ }
72+
73+ // Won't overflow because of the check above.
5174 idx += 1 ;
5275 }
5376
@@ -60,10 +83,12 @@ impl DescriptorTable {
6083 idx
6184 } ;
6285
86+ let idx = DescriptorHandle :: new ( idx) . unwrap ( ) ;
87+
6388 let prev = self . descriptors . insert ( idx, descriptor) ;
64- debug_assert ! ( prev. is_none( ) , "Already a descriptor at {}" , idx) ;
89+ assert ! ( prev. is_none( ) , "Already a descriptor at {}" , idx) ;
6590
66- idx
91+ Ok ( idx)
6792 }
6893
6994 // Call after inserting to `available_indices`, to free any that are contiguous
@@ -82,23 +107,24 @@ impl DescriptorTable {
82107 }
83108
84109 /// Get the descriptor at `idx`, if any.
85- pub fn get ( & self , idx : u32 ) -> Option < & Descriptor > {
110+ pub fn get ( & self , idx : DescriptorHandle ) -> Option < & Descriptor > {
86111 self . descriptors . get ( & idx)
87112 }
88113
89114 /// Get the descriptor at `idx`, if any.
90- pub fn get_mut ( & mut self , idx : u32 ) -> Option < & mut Descriptor > {
115+ pub fn get_mut ( & mut self , idx : DescriptorHandle ) -> Option < & mut Descriptor > {
91116 self . descriptors . get_mut ( & idx)
92117 }
93118
94- /// Insert a descriptor at `index`. If a descriptor is already present at
95- /// that index, it is unregistered from that index and returned.
96- fn set ( & mut self , index : u32 , descriptor : Descriptor ) -> Option < Descriptor > {
119+ /// Insert a descriptor at `index`. If a descriptor is already present at that index, it is
120+ /// unregistered from that index and returned.
121+ #[ must_use]
122+ fn set ( & mut self , index : DescriptorHandle , descriptor : Descriptor ) -> Option < Descriptor > {
97123 // We ensure the index is no longer in `self.available_indices`. We *don't* ensure
98124 // `self.next_index` is > `index`, since that'd require adding the indices in between to
99125 // `self.available_indices`. It uses less memory and is no more expensive to iterate when
100126 // *using* `self.available_indices` instead.
101- self . available_indices . remove ( & index) ;
127+ self . available_indices . remove ( & index. val ( ) ) ;
102128
103129 if let Some ( prev) = self . descriptors . insert ( index, descriptor) {
104130 trace ! ( "Overwriting index {}" , index) ;
@@ -109,29 +135,45 @@ impl DescriptorTable {
109135 }
110136 }
111137
112- /// Register a descriptor and return its fd handle.
113- pub fn register_descriptor ( & mut self , desc : Descriptor ) -> u32 {
114- self . add ( desc, 0 )
138+ /// Register a descriptor and return its fd handle. Equivalent to
139+ /// `register_descriptor_with_min_fd(desc, 0)`. If the descriptor could not be added, the
140+ /// descriptor is returned in the `Err`.
141+ pub fn register_descriptor (
142+ & mut self ,
143+ desc : Descriptor ,
144+ ) -> Result < DescriptorHandle , Descriptor > {
145+ const ZERO : DescriptorHandle = match DescriptorHandle :: new ( 0 ) {
146+ Some ( x) => x,
147+ None => unreachable ! ( ) ,
148+ } ;
149+ self . add ( desc, ZERO )
115150 }
116151
117- /// Register a descriptor and return its fd handle.
118- pub fn register_descriptor_with_min_fd ( & mut self , desc : Descriptor , min_fd : u32 ) -> u32 {
152+ /// Register a descriptor and return its fd handle. If the descriptor could not be added, the
153+ /// descriptor is returned in the `Err`.
154+ pub fn register_descriptor_with_min_fd (
155+ & mut self ,
156+ desc : Descriptor ,
157+ min_fd : DescriptorHandle ,
158+ ) -> Result < DescriptorHandle , Descriptor > {
119159 self . add ( desc, min_fd)
120160 }
121161
122162 /// Register a descriptor with a given fd handle and return the descriptor that it replaced.
163+ #[ must_use]
123164 pub fn register_descriptor_with_fd (
124165 & mut self ,
125166 desc : Descriptor ,
126- new_fd : u32 ,
167+ new_fd : DescriptorHandle ,
127168 ) -> Option < Descriptor > {
128169 self . set ( new_fd, desc)
129170 }
130171
131172 /// Deregister the descriptor with the given fd handle and return it.
132- pub fn deregister_descriptor ( & mut self , fd : u32 ) -> Option < Descriptor > {
173+ #[ must_use]
174+ pub fn deregister_descriptor ( & mut self , fd : DescriptorHandle ) -> Option < Descriptor > {
133175 let maybe_descriptor = self . descriptors . remove ( & fd) ;
134- self . available_indices . insert ( fd) ;
176+ self . available_indices . insert ( fd. val ( ) ) ;
135177 self . trim_tail ( ) ;
136178 maybe_descriptor
137179 }
@@ -164,3 +206,71 @@ impl Default for DescriptorTable {
164206 Self :: new ( )
165207 }
166208}
209+
210+ /// A handle for a file descriptor.
211+ #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq , PartialOrd , Ord ) ]
212+ pub struct DescriptorHandle ( u32 ) ;
213+
214+ impl DescriptorHandle {
215+ /// Returns `Some` if `fd` is less than [`FD_MAX`]. Can be used in `const` contexts.
216+ pub const fn new ( fd : u32 ) -> Option < Self > {
217+ if fd > FD_MAX {
218+ return None ;
219+ }
220+
221+ Some ( DescriptorHandle ( fd) )
222+ }
223+
224+ pub fn val ( & self ) -> u32 {
225+ self . 0
226+ }
227+ }
228+
229+ impl std:: fmt:: Display for DescriptorHandle {
230+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
231+ self . 0 . fmt ( f)
232+ }
233+ }
234+
235+ impl From < DescriptorHandle > for u32 {
236+ fn from ( x : DescriptorHandle ) -> u32 {
237+ x. 0
238+ }
239+ }
240+
241+ impl From < DescriptorHandle > for i32 {
242+ fn from ( x : DescriptorHandle ) -> i32 {
243+ const _: ( ) = assert ! ( FD_MAX <= i32 :: MAX as u32 ) ;
244+ // the constructor makes sure this won't panic
245+ x. 0 . try_into ( ) . unwrap ( )
246+ }
247+ }
248+
249+ impl TryFrom < u32 > for DescriptorHandle {
250+ type Error = DescriptorHandleError ;
251+ fn try_from ( x : u32 ) -> Result < Self , Self :: Error > {
252+ DescriptorHandle :: new ( x) . ok_or ( DescriptorHandleError ( ) )
253+ }
254+ }
255+
256+ impl TryFrom < i32 > for DescriptorHandle {
257+ type Error = DescriptorHandleError ;
258+ fn try_from ( x : i32 ) -> Result < Self , Self :: Error > {
259+ x. try_into ( )
260+ . ok ( )
261+ . and_then ( DescriptorHandle :: new)
262+ . ok_or ( DescriptorHandleError ( ) )
263+ }
264+ }
265+
266+ /// The handle is not valid.
267+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
268+ pub struct DescriptorHandleError ( ) ;
269+
270+ impl std:: fmt:: Display for DescriptorHandleError {
271+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
272+ write ! ( f, "Not a valid descriptor handle" )
273+ }
274+ }
275+
276+ impl std:: error:: Error for DescriptorHandleError { }
0 commit comments