{"version":"2.1.216","anchor":"filehistory-rewind-atomic-restore-with-symlink-safety","canonical_anchor":"filehistory-rewind-atomic-restore-with-symlink-safety","heading":"FileHistory Rewind: Atomic Restore with Symlink Safety","tier":null,"area":null,"scope":null,"heads_up":null,"url":"https:\/\/changelogs.core-directive.com\/v\/2.1.216\/e\/filehistory-rewind-atomic-restore-with-symlink-safety","release_url":"https:\/\/changelogs.core-directive.com\/v\/2.1.216","markdown":"### FileHistory Rewind: Atomic Restore with Symlink Safety\n\n**What**\n\nThe file-history rewind (checkpoint restore) function now uses low-level file descriptors with `O_NOFOLLOW` to safely read backup files and write destination files, detecting symlink injection, hard links, FIFO substitution, and identity changes during the restore.\n\n**Details**\n\n- Backup source is opened with `O_RDONLY | O_NOFOLLOW | O_NONBLOCK`; `ELOOP`\/`EMLINK` means the backup became a symlink \u2014 restore is refused\n- Destination is opened with `O_WRONLY | O_CREAT | O_NOFOLLOW | O_NONBLOCK`\n- Checks `nlink > 1` and refuses to overwrite hard-linked files\n- Verifies `\/proc\/self\/fd\/<n>` path matches the expected parent directory (Linux only)\n- Re-verifies `dev`\/`ino` identity after opening, before truncating and writing\n- Returns `{ filesChanged, skippedLinks }` instead of just an array; skipped-links count is surfaced to the caller\n\n**Evidence**\n\nRestore implementation (search for `\"FileHistory: [Rewind] Refusing to delete\"` or `\"destination is hard-linked\"`)."}