@@ -3,15 +3,14 @@ use crate::{
3
3
Errno ,
4
4
NixPath ,
5
5
Result ,
6
- sys:: uio:: IoVec
7
6
} ;
8
7
use libc:: { c_char, c_int, c_uint, c_void} ;
9
8
use std:: {
10
9
borrow:: Cow ,
11
10
ffi:: { CString , CStr } ,
12
11
fmt,
13
12
io,
14
- ptr
13
+ marker :: PhantomData ,
15
14
} ;
16
15
17
16
@@ -198,13 +197,45 @@ pub type NmountResult = std::result::Result<(), NmountError>;
198
197
#[ cfg_attr( docsrs, doc( cfg( all( ) ) ) ) ]
199
198
#[ derive( Debug , Default ) ]
200
199
pub 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 > ,
202
204
is_owned : Vec < bool > ,
205
+ marker : PhantomData < & ' a ( ) > ,
203
206
}
204
207
205
208
#[ cfg( target_os = "freebsd" ) ]
206
209
#[ cfg_attr( docsrs, doc( cfg( all( ) ) ) ) ]
207
210
impl < ' 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
+
208
239
/// Add an opaque mount option.
209
240
///
210
241
/// Some file systems take binary-valued mount options. They can be set
@@ -239,10 +270,8 @@ impl<'a> Nmount<'a> {
239
270
len : usize
240
271
) -> & mut Self
241
272
{
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 ) ;
246
275
self
247
276
}
248
277
@@ -258,10 +287,8 @@ impl<'a> Nmount<'a> {
258
287
/// .null_opt(&read_only);
259
288
/// ```
260
289
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 ) ;
265
292
self
266
293
}
267
294
@@ -283,17 +310,8 @@ impl<'a> Nmount<'a> {
283
310
/// ```
284
311
pub fn null_opt_owned < P : ?Sized + NixPath > ( & mut self , name : & P ) -> & mut Self
285
312
{
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 ) ;
297
315
self
298
316
}
299
317
@@ -315,10 +333,8 @@ impl<'a> Nmount<'a> {
315
333
val : & ' a CStr
316
334
) -> & mut Self
317
335
{
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 ) ;
322
338
self
323
339
}
324
340
@@ -341,24 +357,8 @@ impl<'a> Nmount<'a> {
341
357
where P1 : ?Sized + NixPath ,
342
358
P2 : ?Sized + NixPath
343
359
{
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) ;
362
362
self
363
363
}
364
364
@@ -369,18 +369,19 @@ impl<'a> Nmount<'a> {
369
369
370
370
/// Actually mount the file system.
371
371
pub fn nmount ( & mut self , flags : MntFlags ) -> NmountResult {
372
- // nmount can return extra error information via a "errmsg" return
373
- // argument.
374
372
const ERRMSG_NAME : & [ u8 ] = b"errmsg\0 " ;
375
373
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
+ } ) ;
384
385
385
386
let niov = self . iov . len ( ) as c_uint ;
386
387
let iovp = self . iov . as_mut_ptr ( ) as * mut libc:: iovec ;
@@ -412,7 +413,7 @@ impl<'a> Drop for Nmount<'a> {
412
413
// Free the owned string. Safe because we recorded ownership,
413
414
// and Nmount does not implement Clone.
414
415
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 ) ) ;
416
417
}
417
418
}
418
419
}
0 commit comments