Ситуация: на старом макбуке лежит очень важная переписка, которую один мой друг вёл через программу Mail много лет назад. С тех пор макбук сломался и перестал включаться. Судя по всему, отказал диск. Я решил попробовал помочь другу и восстановить письма с этого нерабочего ноутбука.
Оказывается, на маке очень легко можно запустить Linux. Берем загрузочную флешку с Ubuntu и запускаемся с неё. Единственная проблема в том, что драйверов маковской сетевой карты в стандартном дистрибутиве Ubuntu нет, поэтому всё необходимое пришлось скачивать отдельно и переносить на внешнем жёстком диске.
Читаем всё подряд
Главное - это то, что Ubuntu позволила обратиться к проблемному диску без необходимости монтировать файловую систему. Возникла идея сделать дамп диска при помощи программы ddrescue, а прочитать содержимого этого дампа уже на другом компьютере. Идея сработала частично: поначалу данные копировались, но потом что-то ломалось, и кроме ошибок с этого диска уже ничего невозможно было получить до следующего презапуска. Преимущество ddrescue в том, что его исполнение можно прервать, и при последующем запуске копирование продолжится для необработанных секторов. Каждый запуск приводил к копированию дополнительных 4% содержимого, после чего диск отключался и начинал сыпать ошибки. Если выключить компьютер и дать ему постоять полчаса, то можно было скопировать ещё 4%. Похоже, что диск перегревался и автоматически отключался, чтобы не дать себе сгореть.
Я опробовал несколько разных способов не дать диску перегреться: ограничивал скорость чтения и запускал копирование на пару минут, после чего делал паузу. Диск всё равно отключался, поэтому лучшей методикой было просто пытаться прочитать максимальное количество данных, пока диск не отключится. Таким образом у меня получилось достать 20% содержимого, после чего у меня закончилось терпение, и я решил пробовать работать с тем, что удалось скопировать.
Монтируем частичный образ
Mac использует файловую систему APFS. Какой-то энтузиаст провёл ревёрс-инжиниринг этой файловой системы, написал драйвер под Linux и выложил его на GitHub: apfs-fuse. Я сбилдил этот драйвер на другом компьютере с Ubuntu и попробовал смонтировать то, что получилось извлечь со сломанного диска. Ожидаемо, драйвер упал с вот такой ошибкой:
ReadAndVerifyHeaderBlock checksum error.
Failed to load checkpoint map
Unable to init containerУ меня возникла идея, которая оказалась решающей для всего дальнейшего процесса восстановления. Что если добавить в код дополнительное логирование, чтобы знать точно, какой адрес драйвер пытается прочитать? Зная адрес проблемного сектора, можно будет запустить ddrescue в соответствующей области диска, и попробовать смонтировать дополненный образ снова. Таким образом я смог восстановить все необходимые служебные части диска, руководствуясь новыми сообщениями об ошибках, которые выглядели примерно так:
CheckPointMap: reading header block paddr=3995372
ApfsContainer: reading spaceman paddr=3981781, num_blcks=1
ReadAndVerifyHeaderBlock checksum error.
Драйвер прошёл первые стадии инициализации, пока не дошёл до следующего препятствия...

