• Если аргумент oldpath ссылается на файл, который не является каталогом, то в этом случае в аргументе newpath нельзя указывать имя пути для каталога (ошибка EISDIR). Чтобы переименовать файл, указав на местоположение внутри каталога (то есть переместить файл в другой каталог), аргумент newpath должен содержать новое имя файла. Следующий системный вызов одновременно перемещает файл в другой каталог и меняет его имя:
rename("sub1/x", "sub2/y");
• При указании имени каталога в аргументе oldpath появляется возможность переименовать этот каталог. В таком случае ссылка newpath должна либо быть несуществующей, либо являться именем пустого каталога. Если аргумент newpath — существующий файл или существующий непустой каталог, то возникнет ошибка (соответственно ENOTDIR и ENOTEMPTY).
• Если аргумент oldpath является каталогом, то аргумент newpath не может содержать тот же префикс каталога, что и у аргумента oldpath. Например, мы не смогли бы переименовать /home/mtk на /home/mtk/bin (ошибка EINVAL).
• Файлы, с которыми соотносятся аргументы oldpath и newpath, должны располагаться в одной файловой системе. Это необходимо, поскольку каталог является списком жестких ссылок, указывающих на индексные дескрипторы в той же файловой системе, где расположен данный каталог. Как было сказано ранее, системный вызов rename() всего лишь оперирует содержимым списков каталога. При попытке переименовать файл с его переносом в другую файловую систему возникнет ошибка EXDEV. (Чтобы добиться желаемого результата, следует скопировать содержимое данного файла из одной файловой системы в другую, а затем удалить старый файл. Именно это выполняет команда mv.)
Теперь рассмотрим системные вызовы, которые применяются для создания символических ссылок и проверки их содержимого.
Системный вызов symlink() создает новую символическую ссылку linkpath для имени пути, указанного в аргументе filepath. (Чтобы удалить ее, используется системный вызов unlink().)
#include
int symlink(const char *
Возвращает 0 при успешном завершении или –1 при ошибке
Если имя пути, переданное в аргумент linkpath, уже существует, системный вызов завершается ошибкой (для переменной errno устанавливается значение EEXIST). Имя пути, указанное в аргументе filepath, может быть абсолютным или относительным.
Файл или каталог, указанные в аргументе filepath, могут и не существовать в момент совершения системного вызова. И даже если они существуют, ничто не препятствует их удалению впоследствии. Тогда ссылка linkpath становится
Если мы укажем символическую ссылку в качестве аргумента pathname системного вызова open(), то он откроет файл, на который указывает эта ссылка. Иногда может потребоваться извлечь содержимое самой ссылки, то есть имя пути, с которым она соотносится. Данную задачу выполняет системный вызов readlink(), помещающий копию строки символической ссылки в символьный массив, на который указывает аргумент buffer.
#include
ssize_t readlink(const char *
Возвращает количество байтов, помещенных в массиве buffer, при успешном завершении или –1 при ошибке
Аргумент bufsiz является целым числом, которое используется, чтобы сообщить системному вызову readlink() количество байтов, доступных в массиве buffer.
Если не возникает ошибка, системный вызов readlink() возвращает количество байтов, фактически размещенных в массиве buffer. Если длина ссылки превышает величину bufsiz, в этот массив помещается обрезанная строка (а системный вызов readlink() возвращает размер этой строки — то есть bufsiz).
Поскольку в конце массива buffer не помещен завершающий нулевой байт, нет способа отличить обрезанную строку, возвращенную системным вызовом readlink(), от строки, которая в точности заполняет массив buffer. Один из вариантов проверки состоит в том, чтобы выделить массив buffer большего размера, а затем еще раз выполнить вызов readlink(). В другом варианте можно указать размер для имени пути с помощью константы PATH_MAX (описанной в разделе 11.1), определяющей длину самого длинного имени пути, который должна воспринимать программа.
Пример использования системного вызова readlink() приведен в листинге 18.4.
Стандарт SUSv3 определяет новое ограничение, SYMLINK_MAX, — его должна задавать конкретная реализация, чтобы указать максимальное количество байтов, которое может хранить символическая ссылка. Рекомендуемая величина данного ограничения — не менее 255 байт. На момент написания книги Linux не задает это ограничение. В основном тексте мы предлагаем использовать константу PATH_MAX, поскольку указанное ограничение должно быть по меньшей мере таким же, что и SYMLINK_MAX.