_Py_fopen_obj in cpython (Python/fileutils.c:1757-1835) Open a file using std::fs::File and convert to FILE Automatically handles path encoding and EINTR retries
(path: &std::path::Path, mode: &str)
| 445 | // Open a file using std::fs::File and convert to FILE* |
| 446 | // Automatically handles path encoding and EINTR retries |
| 447 | pub fn fopen(path: &std::path::Path, mode: &str) -> std::io::Result<*mut libc::FILE> { |
| 448 | use alloc::ffi::CString; |
| 449 | use std::fs::File; |
| 450 | |
| 451 | // Currently only supports read mode |
| 452 | // Can be extended to support "wb", "w+b", etc. if needed |
| 453 | if mode != "rb" { |
| 454 | return Err(std::io::Error::new( |
| 455 | std::io::ErrorKind::InvalidInput, |
| 456 | format!("unsupported mode: {}", mode), |
| 457 | )); |
| 458 | } |
| 459 | |
| 460 | // Open file using std::fs::File (handles path encoding and EINTR automatically) |
| 461 | let file = File::open(path)?; |
| 462 | |
| 463 | #[cfg(windows)] |
| 464 | { |
| 465 | use std::os::windows::io::IntoRawHandle; |
| 466 | |
| 467 | // Convert File handle to CRT file descriptor |
| 468 | let handle = file.into_raw_handle(); |
| 469 | let fd = unsafe { libc::open_osfhandle(handle as isize, libc::O_RDONLY) }; |
| 470 | if fd == -1 { |
| 471 | return Err(std::io::Error::last_os_error()); |
| 472 | } |
| 473 | |
| 474 | // Convert fd to FILE* |
| 475 | let mode_cstr = CString::new(mode).unwrap(); |
| 476 | let fp = unsafe { libc::fdopen(fd, mode_cstr.as_ptr()) }; |
| 477 | if fp.is_null() { |
| 478 | unsafe { libc::close(fd) }; |
| 479 | return Err(std::io::Error::last_os_error()); |
| 480 | } |
| 481 | |
| 482 | // Set non-inheritable (Windows needs this explicitly) |
| 483 | if let Err(e) = set_inheritable(fd, false) { |
| 484 | unsafe { libc::fclose(fp) }; |
| 485 | return Err(e); |
| 486 | } |
| 487 | |
| 488 | Ok(fp) |
| 489 | } |
| 490 | |
| 491 | #[cfg(not(windows))] |
| 492 | { |
| 493 | use std::os::fd::IntoRawFd; |
| 494 | |
| 495 | // Convert File to raw fd |
| 496 | let fd = file.into_raw_fd(); |
| 497 | |
| 498 | // Convert fd to FILE* |
| 499 | let mode_cstr = CString::new(mode).unwrap(); |
| 500 | let fp = unsafe { libc::fdopen(fd, mode_cstr.as_ptr()) }; |
| 501 | if fp.is_null() { |
| 502 | unsafe { libc::close(fd) }; |
| 503 | return Err(std::io::Error::last_os_error()); |
| 504 | } |
no test coverage detected