@@ -3,15 +3,14 @@ use crate::{
33 Errno ,
44 NixPath ,
55 Result ,
6- sys:: uio:: IoVec
76} ;
87use libc:: { c_char, c_int, c_uint, c_void} ;
98use std:: {
109 borrow:: Cow ,
1110 ffi:: { CString , CStr } ,
1211 fmt,
1312 io,
14- ptr
13+ marker :: PhantomData ,
1514} ;
1615
1716
@@ -198,13 +197,45 @@ pub type NmountResult = std::result::Result<(), NmountError>;
198197#[ cfg_attr( docsrs, doc( cfg( all( ) ) ) ) ]
199198#[ derive( Debug , Default ) ]
200199pub struct Nmount < ' a > {
201- iov : Vec < IoVec < & ' a [ u8 ] > > ,
200+ // n.b. notgull: In reality, this is a list that contains
201+ // both mutable and immutable pointers.
202+ // Be careful using this.
203+ iov : Vec < libc:: iovec > ,
202204 is_owned : Vec < bool > ,
205+ marker : PhantomData < & ' a ( ) > ,
203206}
204207
205208#[ cfg( target_os = "freebsd" ) ]
206209#[ cfg_attr( docsrs, doc( cfg( all( ) ) ) ) ]
207210impl < ' a > Nmount < ' a > {
211+ /// Helper function to push a slice onto the `iov` array.
212+ fn push_slice ( & mut self , val : & ' a [ u8 ] , is_owned : bool ) {
213+ self . iov . push ( libc:: iovec {
214+ iov_base : val. as_ptr ( ) as * mut _ ,
215+ iov_len : val. len ( ) ,
216+ } ) ;
217+ self . is_owned . push ( is_owned) ;
218+ }
219+
220+ /// Helper function to push a pointer and its length onto the `iov` array.
221+ fn push_pointer_and_length ( & mut self , val : * const u8 , len : usize , is_owned : bool ) {
222+ self . iov . push ( libc:: iovec {
223+ iov_base : val as * mut _ ,
224+ iov_len : len,
225+ } ) ;
226+ self . is_owned . push ( is_owned) ;
227+ }
228+
229+ /// Helper function to push a `nix` path as owned.
230+ fn push_nix_path < P : ?Sized + NixPath > ( & mut self , val : & P ) {
231+ val. with_nix_path ( |s| {
232+ let len = s. to_bytes_with_nul ( ) . len ( ) ;
233+ let ptr = s. to_owned ( ) . into_raw ( ) as * const u8 ;
234+
235+ self . push_pointer_and_length ( ptr, len, true ) ;
236+ } ) . unwrap ( ) ;
237+ }
238+
208239 /// Add an opaque mount option.
209240 ///
210241 /// Some file systems take binary-valued mount options. They can be set
@@ -239,10 +270,8 @@ impl<'a> Nmount<'a> {
239270 len : usize
240271 ) -> & mut Self
241272 {
242- self . iov . push ( IoVec :: from_slice ( name. to_bytes_with_nul ( ) ) ) ;
243- self . is_owned . push ( false ) ;
244- self . iov . push ( IoVec :: from_raw_parts ( val, len) ) ;
245- self . is_owned . push ( false ) ;
273+ self . push_slice ( name. to_bytes_with_nul ( ) , false ) ;
274+ self . push_pointer_and_length ( val. cast ( ) , len, false ) ;
246275 self
247276 }
248277
@@ -258,10 +287,8 @@ impl<'a> Nmount<'a> {
258287 /// .null_opt(&read_only);
259288 /// ```
260289 pub fn null_opt ( & mut self , name : & ' a CStr ) -> & mut Self {
261- self . iov . push ( IoVec :: from_slice ( name. to_bytes_with_nul ( ) ) ) ;
262- self . is_owned . push ( false ) ;
263- self . iov . push ( IoVec :: from_raw_parts ( ptr:: null_mut ( ) , 0 ) ) ;
264- self . is_owned . push ( false ) ;
290+ self . push_slice ( name. to_bytes_with_nul ( ) , false ) ;
291+ self . push_slice ( & [ ] , false ) ;
265292 self
266293 }
267294
@@ -283,17 +310,8 @@ impl<'a> Nmount<'a> {
283310 /// ```
284311 pub fn null_opt_owned < P : ?Sized + NixPath > ( & mut self , name : & P ) -> & mut Self
285312 {
286- name. with_nix_path ( |s| {
287- let len = s. to_bytes_with_nul ( ) . len ( ) ;
288- self . iov . push ( IoVec :: from_raw_parts (
289- // Must free it later
290- s. to_owned ( ) . into_raw ( ) as * mut c_void ,
291- len
292- ) ) ;
293- self . is_owned . push ( true ) ;
294- } ) . unwrap ( ) ;
295- self . iov . push ( IoVec :: from_raw_parts ( ptr:: null_mut ( ) , 0 ) ) ;
296- self . is_owned . push ( false ) ;
313+ self . push_nix_path ( name) ;
314+ self . push_slice ( & [ ] , false ) ;
297315 self
298316 }
299317
@@ -315,10 +333,8 @@ impl<'a> Nmount<'a> {
315333 val : & ' a CStr
316334 ) -> & mut Self
317335 {
318- self . iov . push ( IoVec :: from_slice ( name. to_bytes_with_nul ( ) ) ) ;
319- self . is_owned . push ( false ) ;
320- self . iov . push ( IoVec :: from_slice ( val. to_bytes_with_nul ( ) ) ) ;
321- self . is_owned . push ( false ) ;
336+ self . push_slice ( name. to_bytes_with_nul ( ) , false ) ;
337+ self . push_slice ( val. to_bytes_with_nul ( ) , false ) ;
322338 self
323339 }
324340
@@ -341,24 +357,8 @@ impl<'a> Nmount<'a> {
341357 where P1 : ?Sized + NixPath ,
342358 P2 : ?Sized + NixPath
343359 {
344- name. with_nix_path ( |s| {
345- let len = s. to_bytes_with_nul ( ) . len ( ) ;
346- self . iov . push ( IoVec :: from_raw_parts (
347- // Must free it later
348- s. to_owned ( ) . into_raw ( ) as * mut c_void ,
349- len
350- ) ) ;
351- self . is_owned . push ( true ) ;
352- } ) . unwrap ( ) ;
353- val. with_nix_path ( |s| {
354- let len = s. to_bytes_with_nul ( ) . len ( ) ;
355- self . iov . push ( IoVec :: from_raw_parts (
356- // Must free it later
357- s. to_owned ( ) . into_raw ( ) as * mut c_void ,
358- len
359- ) ) ;
360- self . is_owned . push ( true ) ;
361- } ) . unwrap ( ) ;
360+ self . push_nix_path ( name) ;
361+ self . push_nix_path ( val) ;
362362 self
363363 }
364364
@@ -369,18 +369,19 @@ impl<'a> Nmount<'a> {
369369
370370 /// Actually mount the file system.
371371 pub fn nmount ( & mut self , flags : MntFlags ) -> NmountResult {
372- // nmount can return extra error information via a "errmsg" return
373- // argument.
374372 const ERRMSG_NAME : & [ u8 ] = b"errmsg\0 " ;
375373 let mut errmsg = vec ! [ 0u8 ; 255 ] ;
376- self . iov . push ( IoVec :: from_raw_parts (
377- ERRMSG_NAME . as_ptr ( ) as * mut c_void ,
378- ERRMSG_NAME . len ( )
379- ) ) ;
380- self . iov . push ( IoVec :: from_raw_parts (
381- errmsg. as_mut_ptr ( ) as * mut c_void ,
382- errmsg. len ( )
383- ) ) ;
374+
375+ // nmount can return extra error information via a "errmsg" return
376+ // argument.
377+ self . push_slice ( ERRMSG_NAME , false ) ;
378+
379+ // SAFETY: we are pushing a mutable iovec here, so we can't use
380+ // the above method
381+ self . iov . push ( libc:: iovec {
382+ iov_base : errmsg. as_mut_ptr ( ) as * mut c_void ,
383+ iov_len : errmsg. len ( ) ,
384+ } ) ;
384385
385386 let niov = self . iov . len ( ) as c_uint ;
386387 let iovp = self . iov . as_mut_ptr ( ) as * mut libc:: iovec ;
@@ -412,7 +413,7 @@ impl<'a> Drop for Nmount<'a> {
412413 // Free the owned string. Safe because we recorded ownership,
413414 // and Nmount does not implement Clone.
414415 unsafe {
415- drop ( CString :: from_raw ( iov. 0 . iov_base as * mut c_char ) ) ;
416+ drop ( CString :: from_raw ( iov. iov_base as * mut c_char ) ) ;
416417 }
417418 }
418419 }
0 commit comments