@@ -237,7 +237,7 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
237237}
238238}
239239
240- #[ cfg( all( target_os = "linux" , target_env = "gnu" , ) ) ]
240+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
241241#[ cfg( feature = "fs" ) ]
242242libc_bitflags ! {
243243 #[ cfg_attr( docsrs, doc( cfg( feature = "fs" ) ) ) ]
@@ -250,10 +250,7 @@ libc_bitflags! {
250250
251251feature ! {
252252#![ feature = "fs" ]
253- #[ cfg( all(
254- target_os = "linux" ,
255- target_env = "gnu" ,
256- ) ) ]
253+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
257254pub fn renameat2<P1 : ?Sized + NixPath , P2 : ?Sized + NixPath >(
258255 old_dirfd: Option <RawFd >,
259256 old_path: & P1 ,
@@ -308,54 +305,80 @@ fn readlink_maybe_at<P: ?Sized + NixPath>(
308305
309306fn inner_readlink<P : ?Sized + NixPath >( dirfd: Option <RawFd >, path: & P ) -> Result <OsString > {
310307 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+ }
317317 }
318+
318319 // Uh oh, the result is too long...
319320 // 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+ }
332350 . map( |x| x. st_size)
333351 . 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+ }
342362 } ;
363+
343364 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) ;
357372 }
358373 }
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+ }
359382 }
360383}
361384
0 commit comments