Реферат: Я хочу получить номер поколения (i_generation
) файла в Linux (или, по крайней мере, ext4) из пользовательского пространства. Или, альтернативно, «время рождения» (время создания файла).Как получить номер поколения inode в Linux?
Я пытаюсь написать программу двусторонней синхронизации файлов (aka Unison), но без центральной базы данных (просто, просто сохраняйте данные в корнях синхронизации) и сохраняя перемещения файлов (очень и очень сложно получить право, если вы хотите поддержать все странные случаи, например, перемещение файла из каталога, который впоследствии удаляется).
Имея возможность однозначно идентифицировать файлы, облегчит вещи. Я знаю, как получить индекс inode и устройства (через stat
), но поскольку inodes можно повторно использовать (я видел это сам), я хочу использовать более стабильную уникальную идентификацию.
Я прочитал о «номере поколения», который используется NFS для уникальной идентификации файлов. В NFS комбинация (, i_generation
) используется для уникальной идентификации дескрипторов файлов при перезагрузках и сбоях сервера (или, по крайней мере, для предотвращения повторного использования одного и того же дескриптора файла, приводящего к возможному повреждению данных).
Мне не удалось получить номер. This ext4 documentation, по-видимому, предполагает, что число может быть получено из файловой системы ext4, но я не могу получить от него руки из пользовательского пространства (я не буду запускать эту простую программу в пространстве ядра). См. EXT4_IOC_GETVERSION
. Я не могу найти соответствующий заголовочный файл в моей системе (LMDE, тестирование Debian). Есть два варианта, которые я мог бы найти:
- Попытайтесь использовать тот, что в ядре, - не говорит, что он не должен использоваться из пользовательского пространства.
- Пользуйтесь
EXT2_IOC_GETVERSION
в должности<linux/ext2_fs.h>
- даетEBADF
(errno
9). Может быть, потому, что я пытаюсь получить информацию EXT2 из файловой системы EXT4? Или, может быть, я делаю что-то неправильно сioctl
, это первый раз, когда я пытаюсь его использовать. Файл открывается правильно, потому что вызовopen
возвращает 3 в моем случае (который должен быть действительным).
код:
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <linux/ext2_fs.h>
#include <stdio.h>
#include <errno.h>
int main() {
int fileno = open("generation.c", O_RDONLY);
printf("fileno: %d\n", fileno);
int generation = 0;
if (ioctl(EXT2_IOC_GETVERSION, fileno, &generation)) {
printf("errno: %d\n", errno);
}
printf("generation: %d\n", generation);
}
Этот код выдает ошибку (ошибка = 9) на Ubuntu 12.04, на LMDE (Debian Testing) дает ошибку компилятора (EXT2_IOC_GETVERSION
не найден).
Альтернативой было бы получить время создания (crtime
или btime
/время рождения) файла, но все мои Googling подвернулся, что это, кажется, невозможно получить из пользовательского пространства в Linux (IIRC FreeBSD имеет системный вызов для него). Я предпочел бы crtime
, потому что crtime
может быть более портативным (для Windows), чем номер поколения.
Я знаю, что это будет зависящим от системы. Я хочу иметь резервную копию, если не найден уникальный уникальный индекс (или вообще не используется inode, в случае FAT, который является общим для USB-накопителей).
inotify
не является вариантом. Это программа для синхронизации файлов после их изменения, например, rsync. Не нравится, как Dropbox остается в фоновом режиме, наблюдая за изменениями файлов.
Если нет никакого способа, чтобы получить эти цифры, я также признаю, что в качестве ответа (с соответствующей документацией, конечно) :)