66//! [`CWD`]: crate::fs::CWD
77//! [`ABS`]: crate::fs::ABS
88
9+ #![ allow( unsafe_code) ]
10+
11+ use crate :: buffer:: Buffer ;
912use crate :: fd:: OwnedFd ;
10- use crate :: ffi:: CStr ;
1113#[ cfg( not( any( target_os = "espidf" , target_os = "horizon" , target_os = "vita" ) ) ) ]
1214use crate :: fs:: Access ;
1315#[ cfg( not( target_os = "espidf" ) ) ]
@@ -24,11 +26,14 @@ use crate::fs::{Dev, FileType};
2426use crate :: fs:: { Gid , Uid } ;
2527use crate :: fs:: { Mode , OFlags } ;
2628use crate :: { backend, io, path} ;
27- use backend:: fd:: { AsFd , BorrowedFd } ;
28- use core:: mem:: MaybeUninit ;
29- use core:: slice;
29+ use backend:: fd:: AsFd ;
3030#[ cfg( feature = "alloc" ) ]
31- use { crate :: ffi:: CString , crate :: path:: SMALL_PATH_BUFFER_SIZE , alloc:: vec:: Vec } ;
31+ use {
32+ crate :: ffi:: { CStr , CString } ,
33+ crate :: path:: SMALL_PATH_BUFFER_SIZE ,
34+ alloc:: vec:: Vec ,
35+ backend:: fd:: BorrowedFd ,
36+ } ;
3237#[ cfg( not( any( target_os = "espidf" , target_os = "vita" ) ) ) ]
3338use { crate :: fs:: Timestamps , crate :: timespec:: Nsecs } ;
3439
@@ -107,8 +112,16 @@ fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::R
107112 buffer. reserve ( SMALL_PATH_BUFFER_SIZE ) ;
108113
109114 loop {
110- let nread =
111- backend:: fs:: syscalls:: readlinkat ( dirfd. as_fd ( ) , path, buffer. spare_capacity_mut ( ) ) ?;
115+ let buf = buffer. spare_capacity_mut ( ) ;
116+
117+ // SAFETY: `readlinkat` behaves.
118+ let nread = unsafe {
119+ backend:: fs:: syscalls:: readlinkat (
120+ dirfd. as_fd ( ) ,
121+ path,
122+ ( buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) ) ,
123+ ) ?
124+ } ;
112125
113126 debug_assert ! ( nread <= buffer. capacity( ) ) ;
114127 if nread < buffer. capacity ( ) {
@@ -146,14 +159,9 @@ fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::R
146159/// `readlinkat(fd, path)`—Reads the contents of a symlink, without
147160/// allocating.
148161///
149- /// This is the "raw" version which avoids allocating, but which is
150- /// significantly trickier to use; most users should use plain [`readlinkat`].
151- ///
152- /// This version writes bytes into the buffer and returns two slices, one
153- /// containing the written bytes, and one containing the remaining
154- /// uninitialized space. If the number of written bytes is equal to the length
155- /// of the buffer, it means the buffer wasn't big enough to hold the full
156- /// string, and callers should try again with a bigger buffer.
162+ /// This is the "raw" version which avoids allocating, but which truncates the
163+ /// string if it doesn't fit in the provided buffer, and doesn't NUL-terminate
164+ /// the string.
157165///
158166/// # References
159167/// - [POSIX]
@@ -162,27 +170,17 @@ fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::R
162170/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlinkat.html
163171/// [Linux]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
164172#[ inline]
165- pub fn readlinkat_raw < P : path:: Arg , Fd : AsFd > (
173+ pub fn readlinkat_raw < P : path:: Arg , Fd : AsFd , Buf : Buffer < u8 > > (
166174 dirfd : Fd ,
167175 path : P ,
168- buf : & mut [ MaybeUninit < u8 > ] ,
169- ) -> io:: Result < ( & mut [ u8 ] , & mut [ MaybeUninit < u8 > ] ) > {
170- path. into_with_c_str ( |path| _readlinkat_raw ( dirfd. as_fd ( ) , path, buf) )
171- }
172-
173- #[ allow( unsafe_code) ]
174- fn _readlinkat_raw < ' a > (
175- dirfd : BorrowedFd < ' _ > ,
176- path : & CStr ,
177- buf : & ' a mut [ MaybeUninit < u8 > ] ,
178- ) -> io:: Result < ( & ' a mut [ u8 ] , & ' a mut [ MaybeUninit < u8 > ] ) > {
179- let n = backend:: fs:: syscalls:: readlinkat ( dirfd. as_fd ( ) , path, buf) ?;
180- unsafe {
181- Ok ( (
182- slice:: from_raw_parts_mut ( buf. as_mut_ptr ( ) . cast :: < u8 > ( ) , n) ,
183- & mut buf[ n..] ,
184- ) )
185- }
176+ mut buf : Buf ,
177+ ) -> io:: Result < Buf :: Output > {
178+ // SAFETY: `readlinkat` behaves.
179+ let len = path. into_with_c_str ( |path| unsafe {
180+ backend:: fs:: syscalls:: readlinkat ( dirfd. as_fd ( ) , path, buf. parts_mut ( ) )
181+ } ) ?;
182+ // SAFETY: `readlinkat` behaves.
183+ unsafe { Ok ( buf. assume_init ( len) ) }
186184}
187185
188186/// `mkdirat(fd, path, mode)`—Creates a directory.
0 commit comments