2010-01-11 4 views
8

У меня есть программа, которая принимает два имени файла в качестве аргументов: он читает первый файл, чтобы создать второй файл. Как я могу гарантировать, что программа не будет перезаписывать первый файл?Как проверить, указывают ли два имени файла на один и тот же физический файл

Ограничения:

  • Метод должен продолжать работать, когда файловая система поддерживает (мягкие или жесткие) ссылки
  • Права доступа к файлу фиксированы и требуется только, что первый файл читается и второй файл Writeable
  • Она предпочтительно должна быть платформа нейтральной (хотя Linux является основной мишенью)
+8

В философии UNIX и Linux такая программа называется фильтром. Он обычно читается со стандартного ввода (STDIN) и записывается на стандартный вывод (STDOUT). Это облегчает написание таких программ, поскольку оно отменяет ответственность таких проверок для вызывающего. Ваша программа может сосредоточиться на выполнении своей работы. –

ответ

12

В linux откройте оба файла и используйте fstat, чтобы проверить, не совпадают ли st_ino (edit :) и st_dev. open будет следовать символическим ссылкам. Не используйте stat напрямую, чтобы предотвратить условия гонки.

+4

Состояние гонки означает, что статус файла может измениться между stat (2) и open (2). Вы делаете stat, а затем некоторый пользователь отключает файл, который вы только что указали, и связывает свой второй файл с тем, который вы собираетесь открыть (2). Просто разъяснение. –

+7

Также убедитесь, что поля 'st_dev' совпадают. Нет ничего, что мешало бы разным файлам на двух разных томах иметь одинаковый номер inode. –

3

Если возможно, открыть первый файл только для чтения, (O_RDONLY) в LINUX. Затем, если вы попытаетесь открыть его снова, чтобы написать ему, вы получите сообщение об ошибке.

+0

Вы получите ложные срабатывания, если второй файл уже открыт только для чтения другим процессом. Я даже не уверен, что универсальное решение возможно (вам нужно прибегать к особенностям файловой системы, таким как получение идентификаторов файлов). – Costique

9

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

+0

Не очень unixy, но хорошая мета-логика, которая будет работать на большинстве платформ, – dmckee

0

Вы можете использовать stat, чтобы получить статус файла, и проверьте, совпадают ли номера индексов.

-1

Возможно, вы могли бы использовать функцию system() для вызова некоторых команд оболочки?

В Баш, вы просто звоните:

stat -c %i filename 

Это показывает номер иноды файла. Вы можете сравнить два файла таким образом, и если их inodes идентичны, это означает, что они являются жесткими ссылками. Следующий вызов:

stat -c %N filename 

будет отображать имя файла и, если это символическая ссылка, он будет печатать имя файла, ссылки на, а также. Он печатает только одно имя, даже если файл, на который указывает он, имеет жесткие ссылки, поэтому для проверки символической ссылки потребуется сравнить номера индексов для второго файла и файла, на который ссылаются символические ссылки, чтобы убедиться.

Вы можете перенаправить вывод статистики в текстовый файл и затем проанализировать файл в своей программе.

+1

Не мой нисходящий канал, но редко бывает, что нужно выполнить команду для преобразования данных в текст и затем разбора текста. В Unix-системах секция SEE ALSO на странице руководства обычно расскажет вам, какую функцию утилиты командной строки вызывают для достижения своей работы. В этом случае 'man 1 stat' сообщает мне о' lstat (2) 'и' stat (2) ', которые совместно используют man-страницу с' fstat (2) ', поэтому вы можете легко получить оптимальный ответ. – dmckee

+0

В общем, я называю system() - Bad Thing (tm). Просто предложил возможность, хотя я понимаю, что она субоптимальна. – mingos

Смежные вопросы