Files
guara/scripts/ntfs-mark-deleted.py
Lucas RayanandClaude Sonnet 5 6328220c60
CI / Format and clippy (push) Successful in 1m57s
CI / Dependency audit (push) Successful in 13s
CI / Check desktop app (Linux) (push) Successful in 3m54s
CI / Tests (Linux) (push) Failing after 7m25s
Release / Create release (push) Successful in 6s
Release / CLI (linux-aarch64) (push) Successful in 1m48s
Release / CLI (linux-x86_64) (push) Successful in 2m39s
Release / Desktop app (linux-aarch64) (push) Successful in 10m9s
Release / Desktop app (linux-x86_64) (push) Successful in 12m20s
Release / Desktop app (windows) (push) Successful in 7m32s
Release / Build latest.json (push) Successful in 5s
chore(i18n): finish translating code comments and scripts to English
Completes the English-only standardization for code, comments, scripts
and CI templates (UI/CLI-facing strings stay bilingual pt-BR/en,
untouched). Covers the remaining crates/, apps/gui/ui/ and
apps/gui/src-tauri/ comments, .gitea/ workflow and template comments,
.githooks/ hooks, and the scripts/ source comments for the files
already renamed in a prior commit (check.sh, generate-logo.py,
install-hooks.sh).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
2026-10-30 20:43:02 -03:00

43 lines
1.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Marks NTFS MFT records as deleted (clears the in-use bit) for test fixtures.
Usage: ntfs-mark-deleted.py image.img path/file1 path/file2 ...
Only the basename is matched (ntfscp writes files to the root directory).
"""
import os
import struct
import sys
img, names = sys.argv[1], {os.path.basename(n) for n in sys.argv[2:]}
f = open(img, "r+b")
boot = f.read(512)
bps = struct.unpack_from("<H", boot, 11)[0]
spc = boot[13]
mft_lcn = struct.unpack_from("<Q", boot, 48)[0]
rs = struct.unpack_from("<b", boot, 64)[0]
rec = rs * bps * spc if rs > 0 else 1 << -rs
f.seek(mft_lcn * bps * spc)
data = f.read(rec * 4096) # Initial MFT is contiguous on small volumes
count = 0
for i in range(len(data) // rec):
r = bytearray(data[i * rec:(i + 1) * rec])
if r[:4] != b"FILE" or not (r[22] & 1):
continue
p = struct.unpack_from("<H", r, 20)[0]
while p + 8 <= len(r):
t, ln = struct.unpack_from("<II", r, p)
if t == 0xFFFFFFFF or ln == 0:
break
if t == 0x30 and r[p + 8] == 0:
vo = p + struct.unpack_from("<H", r, p + 20)[0]
nl = r[vo + 0x40]
name = bytes(r[vo + 0x42:vo + 0x42 + nl * 2]).decode("utf-16le")
if name in names and r[vo + 0x41] != 2:
f.seek(mft_lcn * bps * spc + i * rec + 22)
f.write(bytes([r[22] & ~1 & 0xFF]))
count += 1
break
p += ln
f.flush()
print(f"marked as deleted: {count}", file=sys.stderr)