Skip to content

Commit 8bc46cf

Browse files
authored
Fix windows inode to use u128 (RustPython#6377)
1 parent 6003c87 commit 8bc46cf

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

crates/vm/src/stdlib/os.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,9 @@ pub(super) mod _os {
510510
lstat: OnceCell<PyObjectRef>,
511511
#[cfg(unix)]
512512
ino: AtomicCell<u64>,
513-
#[cfg(not(unix))]
513+
#[cfg(windows)]
514+
ino: AtomicCell<Option<u128>>,
515+
#[cfg(not(any(unix, windows)))]
514516
ino: AtomicCell<Option<u64>>,
515517
}
516518

@@ -608,9 +610,9 @@ pub(super) mod _os {
608610
Ok(stat.clone())
609611
}
610612

611-
#[cfg(not(unix))]
613+
#[cfg(windows)]
612614
#[pymethod]
613-
fn inode(&self, vm: &VirtualMachine) -> PyResult<u64> {
615+
fn inode(&self, vm: &VirtualMachine) -> PyResult<u128> {
614616
match self.ino.load() {
615617
Some(ino) => Ok(ino),
616618
None => {
@@ -625,9 +627,14 @@ pub(super) mod _os {
625627
)
626628
.map_err(|e| e.into_pyexception(vm))?
627629
.ok_or_else(|| crate::exceptions::cstring_error(vm))?;
630+
// On Windows, combine st_ino and st_ino_high into 128-bit value
631+
#[cfg(windows)]
632+
let ino: u128 = stat.st_ino as u128 | ((stat.st_ino_high as u128) << 64);
633+
#[cfg(not(windows))]
634+
let ino: u128 = stat.st_ino as u128;
628635
// Err(T) means other thread set `ino` at the mean time which is safe to ignore
629-
let _ = self.ino.compare_exchange(None, Some(stat.st_ino));
630-
Ok(stat.st_ino)
636+
let _ = self.ino.compare_exchange(None, Some(ino));
637+
Ok(ino)
631638
}
632639
}
633640
}
@@ -638,6 +645,12 @@ pub(super) mod _os {
638645
Ok(self.ino.load())
639646
}
640647

648+
#[cfg(not(any(unix, windows)))]
649+
#[pymethod]
650+
fn inode(&self, _vm: &VirtualMachine) -> PyResult<Option<u64>> {
651+
Ok(self.ino.load())
652+
}
653+
641654
#[cfg(not(windows))]
642655
#[pymethod]
643656
const fn is_junction(&self, _vm: &VirtualMachine) -> PyResult<bool> {
@@ -737,6 +750,12 @@ pub(super) mod _os {
737750
use std::os::unix::fs::DirEntryExt;
738751
entry.ino()
739752
};
753+
// TODO: wasi is nightly
754+
// #[cfg(target_os = "wasi")]
755+
// let ino = {
756+
// use std::os::wasi::fs::DirEntryExt;
757+
// entry.ino()
758+
// };
740759
#[cfg(not(unix))]
741760
let ino = None;
742761

@@ -882,9 +901,16 @@ pub(super) mod _os {
882901
#[cfg(not(windows))]
883902
let st_file_attributes = 0;
884903

904+
// On Windows, combine st_ino and st_ino_high into a 128-bit value
905+
// like _pystat_l128_from_l64_l64
906+
#[cfg(windows)]
907+
let st_ino: u128 = stat.st_ino as u128 | ((stat.st_ino_high as u128) << 64);
908+
#[cfg(not(windows))]
909+
let st_ino = stat.st_ino;
910+
885911
Self {
886912
st_mode: vm.ctx.new_pyref(stat.st_mode),
887-
st_ino: vm.ctx.new_pyref(stat.st_ino),
913+
st_ino: vm.ctx.new_pyref(st_ino),
888914
st_dev: vm.ctx.new_pyref(stat.st_dev),
889915
st_nlink: vm.ctx.new_pyref(stat.st_nlink),
890916
st_uid: vm.ctx.new_pyref(stat.st_uid),

crates/vm/src/windows.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,11 @@ fn win32_xstat_impl(path: &OsStr, traverse: bool) -> std::io::Result<StatStruct>
515515
{
516516
let mut result =
517517
crate::common::fileutils::windows::stat_basic_info_to_stat(&stat_info);
518-
result.update_st_mode_from_path(path, stat_info.FileAttributes);
519-
return Ok(result);
518+
// If st_ino is 0, fall through to slow path to get proper file ID
519+
if result.st_ino != 0 || result.st_ino_high != 0 {
520+
result.update_st_mode_from_path(path, stat_info.FileAttributes);
521+
return Ok(result);
522+
}
520523
}
521524
}
522525
Err(e) => {

0 commit comments

Comments
 (0)