@@ -627,33 +627,50 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
627
627
/// to any pre-opened file descriptor.
628
628
fn open_parent ( p : & Path ) -> io:: Result < ( ManuallyDrop < WasiFd > , PathBuf ) > {
629
629
let p = CString :: new ( p. as_os_str ( ) . as_bytes ( ) ) ?;
630
- unsafe {
631
- let mut ret = ptr:: null ( ) ;
632
- let fd = __wasilibc_find_relpath ( p. as_ptr ( ) , & mut ret) ;
633
- if fd == -1 {
634
- let msg = format ! (
635
- "failed to find a pre-opened file descriptor \
636
- through which {:?} could be opened",
637
- p
630
+ let mut buf = Vec :: < u8 > :: with_capacity ( 512 ) ;
631
+ loop {
632
+ unsafe {
633
+ let mut relative_path = buf. as_ptr ( ) . cast ( ) ;
634
+ let mut abs_prefix = ptr:: null ( ) ;
635
+ let fd = __wasilibc_find_relpath (
636
+ p. as_ptr ( ) ,
637
+ & mut abs_prefix,
638
+ & mut relative_path,
639
+ buf. capacity ( ) ,
638
640
) ;
639
- return Err ( io:: Error :: new ( io:: ErrorKind :: Other , msg) ) ;
641
+ if fd == -1 {
642
+ if io:: Error :: last_os_error ( ) . raw_os_error ( ) == Some ( libc:: ENOMEM ) {
643
+ // Trigger the internal buffer resizing logic of `Vec` by requiring
644
+ // more space than the current capacity.
645
+ let cap = buf. capacity ( ) ;
646
+ buf. set_len ( cap) ;
647
+ buf. reserve ( 1 ) ;
648
+ continue ;
649
+ }
650
+ let msg = format ! (
651
+ "failed to find a pre-opened file descriptor \
652
+ through which {:?} could be opened",
653
+ p
654
+ ) ;
655
+ return Err ( io:: Error :: new ( io:: ErrorKind :: Other , msg) ) ;
656
+ }
657
+ let len = CStr :: from_ptr ( buf. as_ptr ( ) . cast ( ) ) . to_bytes ( ) . len ( ) ;
658
+ buf. set_len ( len) ;
659
+ buf. shrink_to_fit ( ) ;
660
+
661
+ return Ok ( (
662
+ ManuallyDrop :: new ( WasiFd :: from_raw ( fd as u32 ) ) ,
663
+ PathBuf :: from ( OsString :: from_vec ( buf) ) ,
664
+ ) ) ;
640
665
}
641
- let path = Path :: new ( OsStr :: from_bytes ( CStr :: from_ptr ( ret) . to_bytes ( ) ) ) ;
642
-
643
- // FIXME: right now `path` is a pointer into `p`, the `CString` above.
644
- // When we return `p` is deallocated and we can't use it, so we need to
645
- // currently separately allocate `path`. If this becomes an issue though
646
- // we should probably turn this into a closure-taking interface or take
647
- // `&CString` and then pass off `&Path` tied to the same lifetime.
648
- let path = path. to_path_buf ( ) ;
649
-
650
- return Ok ( ( ManuallyDrop :: new ( WasiFd :: from_raw ( fd as u32 ) ) , path) ) ;
651
666
}
652
667
653
668
extern "C" {
654
669
pub fn __wasilibc_find_relpath (
655
670
path : * const libc:: c_char ,
671
+ abs_prefix : * mut * const libc:: c_char ,
656
672
relative_path : * mut * const libc:: c_char ,
673
+ relative_path_len : libc:: size_t ,
657
674
) -> libc:: c_int ;
658
675
}
659
676
}
0 commit comments