|
::Главная страница :: С++/Си :: Статьи |
Как мы говорили ранее, любой файл может иметь несколько записей в директории, ука-зывающие на его I-node. Способ, которым мы создаем ссылку на существующий файл - по-средством функции link().
#include <unistd.h> int link(const char *existingpath, const char *newpath); Return: 0 если OK, -1 при ошибке |
Эта функция создает новый элемент каталога, newpath, который ссылается на сущест-вующий файл existingpath. Создание нового элемента каталога и увеличение счетчика ссылок должно быть элементарной операцией. Только процесс суперпользователя может создать ссыл-ку, которая указывает на директорию. Причина состоит в том, что при этом возможно зацикли-вание в файловой системе. При этом, большинство утилит, завязанных в работе файловой сис-темы, неспособны функционировать. Мы рассмотрим зацикливание на примере символических ссылок чуть позже.
Чтобы удалить существующий элемент директория, мы вызываем функцию unlink().
#include <unistd.h> int unlink(const char *pathname); Return: 0 если OK, -1 при ошибке |
Эта функция удаляет элемент директория и уменьшает количество ссылок на файл, ука-зываемый pathname.
Если на этот файл существуют и другие ссылки, то данные этого файла остаются дос-тупными через них. Этот файл не изменяется, если происходит ошибка.
Мы уже обсуждали ранее, для того чтобы удалить файл мы должны иметь права записи и выполнения в директории, содержащей элементы директория. Также мы говорили, что если на эту директорию установлен липкий бит, мы должны иметь права записи для директории и либо:
Только когда количество ссылок достигнет нуля, содержимое файла может быть удале-но. Одним из условий предотвращающих удаление содержимого файла - до тех пор пока какой-либо процесс имеет файл открытым, его содержимое не может быть удалено. Когда файл за-крывается, ядро сначала поверяет счетчик количества процессов которые открыли файл. Если он равен нулю, ядро поверяет счетчик ссылок и если и он равен нулю, тогда содержимое файла удаляется.
Пример 3.5
/* Файл test_unlink.c */ #includeПрограмма 3.5 открывает файл и затем удаляет его. Затем она засыпает на 15 секунд пе-ред завершением.#include #include #include "errorx.h" int main() { if(open("tempfile",O_RDWR") err_sys("open error"); if(unlink("tempfile") <0) err_sys("unlink error"); printf("file unlinked\n"); sleep(15); printf("done\n"); exit(0); }
Запуск этой программы дает нам:
$ ls -l tempfile смотрим насколько большой этот файл -rw-r--r-- 1 aster 9240990 Jul 31 13:42 tempfile $ df /home сколько доступно свободного места Filesystem Kbytes used avail capacity Mounted on /dev/hda1 282908 181979 72368 71% /home $ ./test_unlink & Запускаем программу в фоновом режиме 1364 Шелл выдает ID процесса $ file unlinked Файл удален ls -l tempfile Смотрим на месте ли файл tempfile not found Элемента директория уже нет $ df /home сколько доступно свободного места Filesystem Kbytes used avail capacity Mounted on /dev/hda1 282908 181979 72368 71% /home $ done программа завершена, все открытые файлы закрываются df /home теперь дисковое пространство должно быть свободно Filesystem Kbytes used avail capacity Mounted on /dev/hda1 282908 172939 81678 68% /home теперь 9.2 Мб свободно
Свойство функции unlink() часто используется программой для гарантии того, что вре-менный файл, который она создает не будет оставлен, в случае, если программа аварийно за-вершит работу. Процесс создает файл, используя либо open() или crate() и сразу же вызывает unlink(). Файл не удаляется, поскольку все еще открыт. Только когда процесс либо закроет файл или завершиться (в этом случае ядро само закроет все открытые файлы) файл будет удален.
Если pathname это символическая ссылка, unlink() ссылается на символическую ссылку, а не на файл на который та указывает.
Суперпользователь может вызвать unlink() с pathname, указывающим на директорию, но для удаления директории должна быть использована функция rmdir().
Мы также можем удалить файл или директорию, вызвав функцию remove(). Для файла remove() идентична unlink(), а для директории - rmdir().
#include <stdio.h> int remove(const char *pathname); Return: 0 если OK, -1 при ошибке |
Файл или директорий переименовываются с помощью функции rename().
#include <stdio.h> int rename(const char *oldname, const char *newname); Return: 0 если OK, -1 при ошибке |
Рассмотрим два условия, в зависимости от того ссылается ли oldname на файл или на ди-ректорий. Мы опишем также, что произойдет, если newname уже существует.
Если newname уже существует, нам необходимы права доступа, как если бы мы его уда-ляли. Поскольку мы удаляем элемент директория для oldname и возможно создаем элемент ди-ректория для newname, нам нужны права записи и выполнения в директории, содержащие old-name и newname.
Символическая ссылка это косвенный указатель на файл, в отличие от жестких ссылок, которые указывали прямо на I-node файла. Символические ссылки были введены для обхода ограничений, связанных с жесткими ссылками: (a) жесткие ссылки обычно требуют, чтобы ссылка и файл размещались в одной файловой системе, и (b) только суперпользователь может создать жесткую ссылку на директорию. Символические ссылки не накладывают никаких огра-ничений на файловую систему и на что они указывают, и любой пользователь может создать символическую ссылку на директорий. Символические ссылки типично используются, чтобы переместить файл или целую иерархию директория в другое местоположение в системе.
При использовании функций, которые ссылаются на файл по имени, нам всегда надо знать придерживается ли функция символических ссылок или нет. Если функция придержива-ется символических ссылок, то аргумент путевого имени ссылается на файл, указываемый сим-волической ссылкой. В противном случае аргумент ссылается на саму ссылку, а не файл на ко-торый та указывает. Таблица 3.6 кратко характеризует функции на предмет, придерживаются ли они символических ссылок или нет.
Используя символические ссылки возможно ввести файловую систему в состояние за-цикливания. Большинство функций которые просматривают путевое имя возвращают перемен-ную errno установленную в ELOOP, когда это происходит. Рассмотрим следующие команды:
$ mkdir foo создаем новый директорий $ touch foo/a создаем файл нулевой длины $ ln -s ./foo foo/testdir создаем символическую ссылку $ ls -l foo taotal 1 -rw-rw-r-- 1 aster 0 Dec 6 06:06 a lrwxrwxrwx 1 aster 6 Dec 6 06:06 testdir->./foo
Этот набор команд создает директорий foo который содержит файл a и символическую ссылку, которая указывает на foo. Мы показали такое расположение на рис 3.4, рисуя директо-рий как кружок, а файл как квадратик.
Если мы напишем простую программу, которая исполь-зует стандартную функцию ftw(), чтобы спуститься через всю файловую иерархию, печатая ка-ждое встреченное имя файла, результат будет:
foo foo/a foo/testdir foo/testdir/a foo/testdir/testdir/ foo/testdir/testdir/a foo/testdir/testdir/testdir foo/testdir/testdir/testdir/a (many more lines) ftw return -1: Too many levels of symbolic links
Мы предоставим, нашу собственную версию функции ftw(), которая использует функ-цию lstat взамен stat, чтобы предупредить следование за символическими ссылками.
Цикл такой формы легко удалить - мы способны удалить файл foo/testdir, поскольку unlink() не следит за символической ссылкой. Но если мы создадим жесткую ссылку которая формирует цикл такого типа, его удаление гораздо сложнее. Вот почему функция link не фор-мирует жесткие ссылки на директории, до тех пор пока процесс не имеет привилегий супер-пользователя.
Когда мы открываем файл, если путевое имя передаваемое функции open() специфици-рует символическую ссылку, open() следует за ссылкой к указанному файлу. Если файл, указы-ваемый символической ссылкой не существует, open() возвращает ошибку, говоря, что она не может открыть файл. Это может запутать пользователей, что не привык к ссылкам. Например:
$ ln -s /no/such/file myfile создаем символическую ссылку $ ls myfile myfile ls говорит, что файл там $ cat myfile поэтому мы пытаемся открыть его cat: myfile: No such file or directory $ ls -l myfile lrwxrwxrwx 1 aster 13 Dec 6 07:00 myfile->/no/such/file
Файл myfile не существует, и cat говорит, что нет такого файла, поскольку myfile - это символическая ссылка и файл на который она указывает - не существует. Опция -l к команде ls дает нам две подсказки: первый символ - l, который означает символическую ссылку, и после-довательность -> также указывающая на символическую ссылку.
Тематические
ссылки
|
Ваша ссылка | Ваша ссылка |
Обмен кнопками, ведение статистики, реклама. |
|||