@@ -6,7 +6,8 @@ use std::{
66 path:: PathBuf ,
77} ;
88
9- use bstr:: { BStr , ByteSlice } ;
9+ use allocator_api2:: { alloc:: Allocator , vec:: Vec } ;
10+ use bstr:: ByteSlice ;
1011use fspy_shared:: ipc:: AccessMode ;
1112use libc:: { c_char, c_int} ;
1213use nix:: unistd:: getcwd;
@@ -40,55 +41,75 @@ fn get_fd_path(fd: RawFd) -> nix::Result<Option<PathBuf>> {
4041 }
4142}
4243
44+ pub struct AbsolutePath < A : Allocator > ( Vec < u8 , A > ) ;
45+
46+ impl < A : Allocator > AbsolutePath < A > {
47+ fn new_in ( path : & [ u8 ] , allocator : A ) -> Self {
48+ let mut bytes = Vec :: with_capacity_in ( path. len ( ) + 1 , allocator) ;
49+ bytes. extend_from_slice ( path) ;
50+ bytes. push ( 0 ) ;
51+ Self ( bytes)
52+ }
53+
54+ pub fn as_bytes ( & self ) -> & [ u8 ] {
55+ & self . 0 [ ..self . 0 . len ( ) - 1 ]
56+ }
57+
58+ #[ cfg( target_os = "linux" ) ]
59+ pub fn as_ptr ( & self ) -> * const c_char {
60+ self . 0 . as_ptr ( ) . cast ( )
61+ }
62+ }
63+
4364pub trait ToAbsolutePath {
44- unsafe fn to_absolute_path < R , F : FnOnce ( Option < & BStr > ) -> nix :: Result < R > > (
65+ unsafe fn to_absolute_path < A : Allocator > (
4566 self ,
46- f : F ,
47- ) -> nix:: Result < R > ;
67+ allocator : A ,
68+ ) -> nix:: Result < Option < AbsolutePath < A > > > ;
4869}
4970
5071pub struct Fd ( pub c_int ) ;
5172impl ToAbsolutePath for Fd {
52- unsafe fn to_absolute_path < R , F : FnOnce ( Option < & BStr > ) -> nix :: Result < R > > (
73+ unsafe fn to_absolute_path < A : Allocator > (
5374 self ,
54- f : F ,
55- ) -> nix:: Result < R > {
75+ allocator : A ,
76+ ) -> nix:: Result < Option < AbsolutePath < A > > > {
5677 let path = get_fd_path ( self . 0 ) ?;
57- f ( path. as_ref ( ) . map ( |p| p . as_os_str ( ) . as_bytes ( ) . as_bstr ( ) ) )
78+ Ok ( path. map ( |path| AbsolutePath :: new_in ( path . as_os_str ( ) . as_bytes ( ) , allocator ) ) )
5879 }
5980}
6081
6182pub struct PathAt ( pub c_int , pub * const c_char ) ;
6283
6384impl ToAbsolutePath for PathAt {
64- unsafe fn to_absolute_path < R , F : FnOnce ( Option < & BStr > ) -> nix :: Result < R > > (
85+ unsafe fn to_absolute_path < A : Allocator > (
6586 self ,
66- f : F ,
67- ) -> nix:: Result < R > {
87+ allocator : A ,
88+ ) -> nix:: Result < Option < AbsolutePath < A > > > {
6889 // SAFETY: self.1 is a non-null pointer to a valid null-terminated C string, as guaranteed by the libc calling convention
6990 let pathname = unsafe { CStr :: from_ptr ( self . 1 ) } . to_bytes ( ) . as_bstr ( ) ;
7091
7192 if pathname. first ( ) . copied ( ) == Some ( b'/' ) {
72- f ( pathname . into ( ) )
93+ Ok ( Some ( AbsolutePath :: new_in ( pathname , allocator ) ) )
7394 } else {
7495 let Some ( mut abs_path) = get_fd_path ( self . 0 ) ? else {
75- return f ( None ) ;
96+ return Ok ( None ) ;
7697 } ;
7798 if !pathname. is_empty ( ) {
7899 abs_path. push ( OsStr :: from_bytes ( pathname) ) ;
79100 }
80- f ( Some ( abs_path. as_os_str ( ) . as_bytes ( ) . as_bstr ( ) ) )
101+ Ok ( Some ( AbsolutePath :: new_in ( abs_path. as_os_str ( ) . as_bytes ( ) , allocator ) ) )
81102 }
82103 }
83104}
84105
85106impl ToAbsolutePath for * const c_char {
86- unsafe fn to_absolute_path < R , F : FnOnce ( Option < & BStr > ) -> nix :: Result < R > > (
107+ unsafe fn to_absolute_path < A : Allocator > (
87108 self ,
88- f : F ,
89- ) -> nix:: Result < R > {
109+ allocator : A ,
110+ ) -> nix:: Result < Option < AbsolutePath < A > > > {
90111 // SAFETY: delegates to PathAt::to_absolute_path with AT_FDCWD and the caller-provided C string pointer
91- unsafe { PathAt ( libc:: AT_FDCWD , self ) . to_absolute_path ( f ) }
112+ unsafe { PathAt ( libc:: AT_FDCWD , self ) . to_absolute_path ( allocator ) }
92113 }
93114}
94115
0 commit comments