Recovering Deleted Files

| No Comments

Recently, I had one particular file that I’d been working on that got corrupted somehow. Unfortunately, I’d let my Time Machine backup lapse somewhat and so I didn’t have a backup.

Anyway, the file wasn’t very big but it would have taken me a little while to write it again so I tried another way of getting the file back. I knew that Xcode uses atomic saves (it writes a new file and then uses a rename) so I figured, so long as I don’t write too much to the disk, there should be an old copy somewhere on the disk. Searching the entire disk would have been tedious though, so I wrote a quick program that creates a file on a volume that uses up all the free space. If you do this by conventional means, you’ll end up with a file full of zeros, but thankfully, OS X comes with the F_SETSIZE fcntl which allows you to set the size of a file without setting the contents. Here’s the code:

#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <err.h>

int main (int argc, char *argv[])
{
  int fd = open (argv[1], O_CREAT | O_RDWR, 0666);

  uint64_t size = 4096;

  for (;;) {
    if (fcntl (fd, F_SETSIZE, &size)) {
      if (errno == ENOSPC)
        break;
      else
        err (1, "fcntl failed\n");
    }
    size *= 2;
  }

  uint64_t high = size;
  uint64_t low = size / 2;

  while (high > low + 1) {
    size = low + (high - low) / 2;
    if (fcntl (fd, F_SETSIZE, &size)) {
      if (errno != ENOSPC)
        err (1, "fcntl failed");
      high = size;
    } else
      low = size;
  }

  printf ("done: %llu\n", size);

  return 0;
}

Obviously, you want to run this whilst booted from another volume and you have to run it as root.

So then it was a simple case of firing up HexFiend which I happen to know has pretty fast search and I managed to find my file.

Leave a comment