@@ -237,7 +237,7 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
237
237
}
238
238
}
239
239
240
- #[ cfg( all( target_os = "linux" , target_env = "gnu" , ) ) ]
240
+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
241
241
#[ cfg( feature = "fs" ) ]
242
242
libc_bitflags ! {
243
243
#[ cfg_attr( docsrs, doc( cfg( feature = "fs" ) ) ) ]
@@ -250,10 +250,7 @@ libc_bitflags! {
250
250
251
251
feature ! {
252
252
#![ feature = "fs" ]
253
- #[ cfg( all(
254
- target_os = "linux" ,
255
- target_env = "gnu" ,
256
- ) ) ]
253
+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
257
254
pub fn renameat2<P1 : ?Sized + NixPath , P2 : ?Sized + NixPath >(
258
255
old_dirfd: Option <RawFd >,
259
256
old_path: & P1 ,
@@ -308,54 +305,80 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
308
305
309
306
fn inner_readlink<P : ?Sized + NixPath >( dirfd: Option <RawFd >, path: & P ) -> Result <OsString > {
310
307
let mut v = Vec :: with_capacity( libc:: PATH_MAX as usize ) ;
311
- // simple case: result is strictly less than `PATH_MAX`
312
- let res = readlink_maybe_at( dirfd, path, & mut v) ?;
313
- let len = Errno :: result( res) ?;
314
- debug_assert!( len >= 0 ) ;
315
- if ( len as usize ) < v. capacity( ) {
316
- return wrap_readlink_result( v, res) ;
308
+
309
+ {
310
+ // simple case: result is strictly less than `PATH_MAX`
311
+ let res = readlink_maybe_at( dirfd, path, & mut v) ?;
312
+ let len = Errno :: result( res) ?;
313
+ debug_assert!( len >= 0 ) ;
314
+ if ( len as usize ) < v. capacity( ) {
315
+ return wrap_readlink_result( v, res) ;
316
+ }
317
317
}
318
+
318
319
// Uh oh, the result is too long...
319
320
// Let's try to ask lstat how many bytes to allocate.
320
- let reported_size = match dirfd {
321
- #[ cfg( target_os = "redox" ) ]
322
- Some ( _) => unreachable!( ) ,
323
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
324
- Some ( dirfd) => {
325
- let flags = if path. is_empty( ) { AtFlags :: AT_EMPTY_PATH } else { AtFlags :: empty( ) } ;
326
- super :: sys:: stat:: fstatat( dirfd, path, flags | AtFlags :: AT_SYMLINK_NOFOLLOW )
327
- } ,
328
- #[ cfg( not( any( target_os = "android" , target_os = "linux" , target_os = "redox" ) ) ) ]
329
- Some ( dirfd) => super :: sys:: stat:: fstatat( dirfd, path, AtFlags :: AT_SYMLINK_NOFOLLOW ) ,
330
- None => super :: sys:: stat:: lstat( path)
331
- }
321
+ let mut try_size = {
322
+ let reported_size = match dirfd {
323
+ #[ cfg( target_os = "redox" ) ]
324
+ Some ( _) => unreachable!( ) ,
325
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
326
+ Some ( dirfd) => {
327
+ let flags = if path. is_empty( ) {
328
+ AtFlags :: AT_EMPTY_PATH
329
+ } else {
330
+ AtFlags :: empty( )
331
+ } ;
332
+ super :: sys:: stat:: fstatat(
333
+ dirfd,
334
+ path,
335
+ flags | AtFlags :: AT_SYMLINK_NOFOLLOW ,
336
+ )
337
+ }
338
+ #[ cfg( not( any(
339
+ target_os = "android" ,
340
+ target_os = "linux" ,
341
+ target_os = "redox"
342
+ ) ) ) ]
343
+ Some ( dirfd) => super :: sys:: stat:: fstatat(
344
+ dirfd,
345
+ path,
346
+ AtFlags :: AT_SYMLINK_NOFOLLOW ,
347
+ ) ,
348
+ None => super :: sys:: stat:: lstat( path) ,
349
+ }
332
350
. map( |x| x. st_size)
333
351
. unwrap_or( 0 ) ;
334
- let mut try_size = if reported_size > 0 {
335
- // Note: even if `lstat`'s apparently valid answer turns out to be
336
- // wrong, we will still read the full symlink no matter what.
337
- reported_size as usize + 1
338
- } else {
339
- // If lstat doesn't cooperate, or reports an error, be a little less
340
- // precise.
341
- ( libc:: PATH_MAX as usize ) . max( 128 ) << 1
352
+
353
+ if reported_size > 0 {
354
+ // Note: even if `lstat`'s apparently valid answer turns out to be
355
+ // wrong, we will still read the full symlink no matter what.
356
+ reported_size as usize + 1
357
+ } else {
358
+ // If lstat doesn't cooperate, or reports an error, be a little less
359
+ // precise.
360
+ ( libc:: PATH_MAX as usize ) . max( 128 ) << 1
361
+ }
342
362
} ;
363
+
343
364
loop {
344
- v. reserve_exact( try_size) ;
345
- let res = readlink_maybe_at( dirfd, path, & mut v) ?;
346
- let len = Errno :: result( res) ?;
347
- debug_assert!( len >= 0 ) ;
348
- if ( len as usize ) < v. capacity( ) {
349
- break wrap_readlink_result( v, res) ;
350
- } else {
351
- // Ugh! Still not big enough!
352
- match try_size. checked_shl( 1 ) {
353
- Some ( next_size) => try_size = next_size,
354
- // It's absurd that this would happen, but handle it sanely
355
- // anyway.
356
- None => break Err ( Errno :: ENAMETOOLONG ) ,
365
+ {
366
+ v. reserve_exact( try_size) ;
367
+ let res = readlink_maybe_at( dirfd, path, & mut v) ?;
368
+ let len = Errno :: result( res) ?;
369
+ debug_assert!( len >= 0 ) ;
370
+ if ( len as usize ) < v. capacity( ) {
371
+ return wrap_readlink_result( v, res) ;
357
372
}
358
373
}
374
+
375
+ // Ugh! Still not big enough!
376
+ match try_size. checked_shl( 1 ) {
377
+ Some ( next_size) => try_size = next_size,
378
+ // It's absurd that this would happen, but handle it sanely
379
+ // anyway.
380
+ None => break Err ( Errno :: ENAMETOOLONG ) ,
381
+ }
359
382
}
360
383
}
361
384
0 commit comments