Восстановление данных и файловая система.

О файловой системе и именах.

Файловая система предназначена для организации хранения данных на жёстких дисках и других носителях, здесь и далее речь пойдёт о ФС EXT3, хотя во многих случаях это можно (частично) перенести и на другие FS, например NTFS или FAT.

Почти весь файл хранится в т.н. инодах (inode), это область на диске фиксированного размера (128 байт). Количество инодов так-же фиксировано и неизменно (оно задаётся при создании ФС). В инодах (так-же они называются файловые дескрипторы) хранятся следующие данные:

  1. Уникальный (в пределах этой ФС) номер инода, этот номер часто называется просто инод, однако есть разница между инодом - областью памяти на диске, и инодом - номером этой области.
  2. Тип файла. Файлы бывают разных типов, мы будем рассматривать только три типа:
    f
    обычный регулярный файл.
    d
    каталог, в этом файле хранятся имена других файлов и номера их инодов - если заменить имя файла в каком-то каталоге для какого-то инода, то это приведёт к тому, что имя файла поменяется. Ничего не запрещает иметь одному файлу множество разных имён в разных каталогах (или в одном и том-же, или одни и те-же), это вполне нормальное явление и называется жёсткой ссылкой (hard link).
    l
    Мягкая ссылка (sofl link, symlink). Это одиночная строка текста, в которой указан путь к файлу. Сам файл не обязан находится на той-же ФС, и даже может вообще отсутствовать (тогда ссылка называется битой (broken symbolic link)). В большинстве случаев, при обращении к симлинку мы получаем доступ к файлу, на который указывает симлинк, однако имеется множество исключений, в большинстве утилит мы можем явно указать, что делать с симлинками.
  3. Атрибуты прав доступа. Имеются три права доступа:
    001
    Право выполнения. Для обычного файла это право разрешает выполнить данный файл. Однако, если у нас имеется право чтения этого файла, мы можем прочитать его, и создать свою копию, которой дадим право исполнения. Кроме того, имея право чтения, мы можем запустить какую-либо утилиту, которая выполнит данный файл. К примеру мы можем запустить sed -f secret_script, которая выполнит secret_script, даже если у нас нет права на его выполнение. Для каталогов это право разрешает доступ к содержащимся в данном каталоге файлам.
    010
    Право модификации, которое часто неправильно называют правом записи. Это право даёт нам возможность изменить файл. Однако, отсутствие права модификации вовсе не запрещает нам удалить этот файл. Что приводит к тому, что можем легко модифицировать любой такой файл с помощью той-же sed -i - с этой опцией sed сначала создаст временный файл в котором запишет модифицированный вариант, а затем удалит старый файл(защищённый), и сменит имя новому файлу - мы увидим, что файл как-бы модифицировался. Для защиты необходимо менять права доступа к каталогу, а именно то-же право модификации каталога - юзер, у которого нет этого права не может создавать и удалять файлы в этом каталоге. Однако, юзер может модифицировать данные файлы (да, удалить файл не сможет, но сможет стереть всю информацию в нём).
    100
    Право чтения. Это право разрешает нам читать содержимое файла. Для каталога это право даёт возможность получить полный список файлов, которые содержатся в данном каталоге (кроме того, мы можем узнать их иноды).
    К примеру создадим 2 каталога, и файл в первом:
    doc@localhost:~/tests$ mkdir d1 d2 && echo "доступ к содержимому получен" >d1/t1
    doc@localhost:~/tests$ ls -l d[12]
    d1:
    total 4
    -rw-r--r--  1 doc users 29 2010-02-13 14:31 t1
    
    d2:
    total 0
    Теперь дадим возможность доступа к этому файлу через другой каталог: для этого, в каталоге d2 мы создадим новую ссылку (в файл (каталог - тоже файл) мы добавим новую строчку, в которой будет написано, что t1 имеет inode как у d1/t1).
    doc@localhost:~/tests$ ln d1/t1 d2/t1
    doc@localhost:~/tests$ ls -li d[12]
    d1:
    total 4
    245770 -rw-r--r--  2 doc users 29 2010-02-13 14:31 t1
    
    d2:
    total 4
    245770 -rw-r--r--  2 doc users 29 2010-02-13 14:31 t1
    А сейчас мы видим один и тот-же файл сразу в двух каталогах, о том, что это одинаковый файл говорит вовсе не одинаковое имя, а один и тот-же инод - 245770. Закроем доступ к файлам в каталоге d1 и попробуем прочитать файл:
    doc@localhost:~/tests$ chmod 600 d1
    doc@localhost:~/tests$ cat d1/*
    cat: d1/t1: Permission denied
    Команда cat жалуется на отсутствие доступа к файлу t1, как видите, о том что в каталоге есть этот файл cat узнала, но не смогла его прочитать. При таком ограничении можно прочитать имена всех файлов в каталоге (и их inode), но не возможно прочитать(выполнить) эти файлы. Если-бы в d1 лежал-бы другой каталог, мы не смогли-бы с ним ничего сделать, впрочем смотрите:
    doc@localhost:~/tests$ chmod 700 d1 && mkdir d1/d11 && chmod 600 d1
    doc@localhost:~/tests$ ls -l d1
    /usr/bin/ls: d1/t1: Permission denied
    /usr/bin/ls: d1/d11: Permission denied
    total 0
    Как видите, мы получили список файлов и каталогов в закрытой директории, но не можем получить к ним доступ. Теперь уберём право чтения каталога d2:
    doc@localhost:~/tests$ chmod 300 d2
    doc@localhost:~/tests$ ls d2
    /usr/bin/ls: d2: Permission denied
    doc@localhost:~/tests$ cat d2/t1
    доступ к содержимому получен
    Мы не можем узнать, как называются файлы в каталоге, но можем их читать, если знаем точное имя! А это имя узнать нет никакой возможности - оно записано в файле-каталоге, к которому у нас нет доступа на чтение.

    Замечание

    Конечно все эти "закрытия" довольно ограничены: во первых, если это наш файл (мы его владелец), то мы можем и открыть что угодно и как угодно поменять любые атрибуты (единственное исключение: мы не можем удалить или переименовать наш файл в не нашем каталоге, если в этом не нашем каталоге у нас нет права модификации, к примеру, мы не можем переименовать и удалить свою домашнюю папку). Во вторых, root может всё, а если ему на что-то не хватает прав, то он может эти права получить. И в третьих, злоумышленник может смонтировать нашу фс к своей системе, и тогда клал он на все наши права.
    На самом деле прав доступа не 3, а 9 - отдельно для владельца, для группы и для всех прочих. Кроме того имеются дополнительные права: SUID бит применяемый для того, что-бы выполнять файл с правами владельца этого файла, а не с правами того, кто запускает. Так-же имеется stiky бит, который не даёт удалять файлы из директории с этим битам всем, кроме владельца (применяется обычно в общедоступных директориях, что-бы разные юзеры не удаляли чужие файлы).
  4. Идентификатор владельца - число которое говорит о том, кто является владельцем этого файла.
  5. Идентификатор группы
  6. Расширенные атрибуты (действуют в EXT3/EXT4 и может быть ещё где-то). Вот самые полезные (скопировал из книжки про Mandriva):
    A (no Access time)
    если для файла или каталога установлен этот атрибут, то, всякий раз при обращении к нему для чтения или записи, у него не будет обновляться время последнего доступа. Это может быть полезно, например, для файлов и каталогов, к которым очень часто обращаются для чтения, особенно из-за того, что это единственный параметр в inode, который изменяется при открытии файла только для чтения.
    a (append only)
    Если для файла установлен этот атрибут, и этот файл открыт для записи, то единственной доступной операцией будет добавление данных к его предыдущему содержимому. Для каталога это означает, что вы сможете только добавить файлы, но не сможете переименовать или удалить ни одного из существующих файлов. Только root может установить или снять этот атрибут.

    Замечание

    Как выяснилось, с файлами в таком каталоге вообще ничего нельзя делать: фактически возможно только создать файл, сделать хардлинк в этот каталог, и переместить файл в этот каталог из той-же файловой системы. Такая директория похожа на янтарь, а файлы в нём на мух в янтаре - если туда попал любой файл, то на него можно только любоваться. Сделать с ним ничего нельзя. Причём - это свойство ФС, а потому даже рут ничего не может сделать (пока не снимет этот атрибут конечно).
    d (no dump)
    dump - это стандартная утилита UNIX(R) для резервного копирования. Она делает дамп любой файловой системы, для которой счётчик дампов равен 1 в файле /etc/fstab (см. Глава 6, Файловые системы и точки монтирования). Но если этот атрибут установлен для файла или каталога, то он, в отличие от других, будет пропущен при снятии дампа. Обратите внимание, что при установке его для каталогов, это также распространяется на все их подкаталоги и файлы.
    i (immutable)
    файл или каталог с этим атрибутом вообще не может быть изменён: он не может быть переименован, на него не может быть создана ссылка[6] и он не может быть удалён. Только root может установить или снять этот атрибут. Обратите внимание, что это также предотвращает изменение времени последнего доступа, поэтому вам нет необходимости устанавливать атрибут A, если установлен i.
    s (secure deletion)
    когда удаляется файл или каталог с этим атрибутом, блоки, которые он занимал на диске перезаписываются нулями.
    S (Synchronous mode)
    если для файла или каталога установлен этот атрибут, все его изменения синхронизируются и немедленно записываются на диск.
  7. Временные метки, коих имеется ровно 4 штуки:
    Время доступа.
    Это время, когда к файлу был в последний раз получен доступ для чтения, записи или исполнения. Нетрудно догадаться, что на разделах смонтированных только для чтения эта метка не может изменится (например на CD-ROM'е). Можно запретить изменение данной метки установив атрибут файла A - это ускорит выполнение файловых операций.
    Время модификации.
    Время, когда файл был изменён.
    Время последнего изменения статуса.
    Время изменения последнего изменения атрибутов (например прав доступа или владельца. Если таких изменений никогда не было, то тут хранится время создания файла). Хочу особо отметить, что это вовсе не время создания файла, узнать время создания файла невозможно принципиально, и к тому-же, оно не нужно (как не странно).

    Замечание

    Если изменить содержимое файла, то изменяется не только время модификации, но и эта временная метка.
    Время удаления.
    Имеется и время удаления - дело в том, что как я уже писал выше, количество и позиция инодов на диске никогда не меняется. После удаления файла его инод остаётся на диске, и в нём хранится в т.ч. время удаления. Используя его, ФС может создавать файлы не в первых попавшихся инодах, а в тех, которые были удалены раньше всего. Хотя я не знаю, реализована-ли данная стратегия сегодня.
    Посмотреть временные метки можно командой stat (конечно кроме времени удаления - оно не имеет смысла для файлов которых ещё не удалили). Например:
    doc@localhost:~/tests$ stat d1
    File: `d1'
    Size: 4096            Blocks: 8          IO Block: 4096   directory
    Device: 307h/775d       Inode: 245768      Links: 3
    Access: (0700/drwx------)  Uid: ( 1000/     doc)   Gid: (  100/   users)
    Access: 2010-02-13 16:00:38.000000000 +0300
    Modify: 2010-02-13 14:55:15.000000000 +0300
    Change: 2010-02-13 16:15:00.000000000 +0300
    Как видите, этот файл был изменён в 14:55, последний доступ к содержимому был в 16:00, а его права и/или владелец были изменены в 16:15. Узнать когда файл был создан невозможно, видимо либо в 14:55, либо ещё раньше.

Сортировка файлов по расширению.

Восстановить файлы очень просто! Достаточно воспользоваться программой PhotoRec. Я вот воспользовался, и получил 16 каталогов с 7819ю файлами... А что дальше? Все эти файлы названы как-нибудь вроде f8036016.txt, так-как их имена безвозвратно исчезли. Остались только расширения, которые данная программа устанавливает исходя из содержимого восстановленных файлов (скажем, если в файле только буквы, то PhotoRec называет его как .txt). Анализировать это ручками невозможно, а потому заставим sed для начала рассортировать похожие файлы по каталогам.

Вот такой скриптик, запускается так:

find recup_dir.* -type f | ../ln_ext.sed

Пример 4.20.

#!/bin/sed -rnf

h
s%.*(\.[^./]+)$%X\1%
T
H
s%.*%test -d '&'; echo $?%e
/^1$/{
	# нет такого каталога
	g
	s/.*\n(.*)/mkdir '\1'; echo $?/e
	/^0$/!{
		# невозможно создать каталог
		x
		s/.*/Error 71\n&/p
		q 71
	}
}
/^0$/!{
	# неизвестная ошибка
	x
	s/.*/Error 72\n&/p
	q 72
}
x
s%(.*)\n(.*)%ln -fv '\1' '\2' >/dev/stderr; echo $?%e
/^0$/!{
	# ошибка создания ссылки
	s/.*/Error 73 (code &)/p
	q 73
}


Важно

Это один из немногих реальных скриптов в данной книге - как вы можете заметить, большинство букв посвящены вовсе не работе, а проверке ошибок - это нормально, использовать такие скрипты намного удобнее, больше всего меня бесит в программах то, что многие из них просто молча падают (зависают, сваливаются в BSOD и проч.), если входные данные несколько отличаются от тех, которые подразумевались программером (а так бывает всегда). В случае ошибки мой скрипт выводит код, и потом можно глянуть исходник (а sed-скрипт это ещё и исходник), в котором есть комментарии и по которому можно понять, что собственно не нравится скрипту.

Копирование файлов - не самый лучший подход, слишком много надо места и времени. Переносить файлы так-же не самая лучшая идея, при разборе их страшно удалять. Я создаю жёсткие ссылки, которые очень удобны для этого случая.

Замечание

кроме того, см. также Хранить вечно!

Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).

Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.