mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 14:46:03 +00:00
Data Recovery: on Windows the lock file check compares file identity
On Windows a recovery area's lock file counted as the one that was opened when the two had the same creation time. NTFS gives a file made within 15 seconds under a removed file's name that file's creation time, so a second running copy could take an area another copy had just made again. The check now compares the volume serial number and file index, as Unix compares the device and inode, and counts a file it cannot read as not the same. The test that a lock file made again is not the one opened now also runs on Windows.
This commit is contained in:
Generated
+1
@@ -6498,6 +6498,7 @@ dependencies = [
|
||||
"roxmltree 0.21.2",
|
||||
"rustix 1.1.6",
|
||||
"ruzstd",
|
||||
"same-file",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"skrifa 0.47.0",
|
||||
|
||||
@@ -67,6 +67,11 @@ log = { workspace = true }
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
rustix = { workspace = true, features = ["std", "process"] }
|
||||
|
||||
# Whether a recovery area's lock file is still the one that was opened (`FolderStore::still_named`).
|
||||
# Already in Cargo.lock (walkdir), so this adds no new crate.
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
same-file = "1.0.6"
|
||||
|
||||
# The tiles of a HEIC photo decode in parallel on native; wasm stays single-threaded.
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
heic-rs = { version = "=0.1.4", default-features = false, features = ["std", "parallel"], optional = true }
|
||||
|
||||
@@ -342,7 +342,8 @@ impl FolderStore {
|
||||
}
|
||||
|
||||
/// Does `path` still name `file`? On Unix the two must be the same file (device and inode); on
|
||||
/// Windows they must have the same creation time; elsewhere `path` must exist.
|
||||
/// Windows they must be the same file (volume serial number and file index); elsewhere `path`
|
||||
/// must exist. When either file can't be read, it does not.
|
||||
fn still_named(file: &std::fs::File, path: &std::path::Path) -> bool {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
@@ -354,9 +355,9 @@ impl FolderStore {
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use std::os::windows::fs::MetadataExt as _;
|
||||
match (file.metadata(), std::fs::symlink_metadata(path)) {
|
||||
(Ok(a), Ok(b)) => a.creation_time() == b.creation_time(),
|
||||
let opened = file.try_clone().and_then(same_file::Handle::from_file);
|
||||
match (opened, same_file::Handle::from_path(path)) {
|
||||
(Ok(a), Ok(b)) => a == b,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,8 +572,9 @@ fn an_area_tidied_away_before_it_is_locked_is_busy() {
|
||||
// The folder went before it was checked or its lock file opened.
|
||||
std::fs::remove_dir(&area).unwrap();
|
||||
assert!(matches!(FolderStore::lock_area(&area), Ok(Lock::Busy)));
|
||||
// A lock file made again under the same name is not the one opened.
|
||||
#[cfg(unix)]
|
||||
// A lock file made again under the same name is not the one opened, also where it keeps the
|
||||
// removed one's creation time (NTFS does within 15 seconds).
|
||||
#[cfg(any(unix, windows))]
|
||||
{
|
||||
std::fs::create_dir_all(&area).unwrap();
|
||||
let opened = open(true);
|
||||
|
||||
Reference in New Issue
Block a user