usageErr("%s pathname\n", argv[0]);
if (lstat(argv[1], &statbuf) == -1)
errExit("lstat");
if (!S_ISLNK(statbuf.st_mode))
fatal("%s is not a symbolic link", argv[1]);
numBytes = readlink(argv[1], buf, BUF_SIZE — 1);
if (numBytes == -1)
errExit("readlink");
buf[numBytes] = '\0'; /* Добавляем завершающий нулевой байт */
printf("readlink: %s — > %s\n", argv[1], buf);
if (realpath(argv[1], buf) == NULL)
errExit("realpath");
printf("realpath: %s — > %s\n", argv[1], buf);
exit(EXIT_SUCCESS);
}
irs._links/view_symlink.c
Функции dirname() и basename() разбивают строку с именем пути на имя каталога и файловые имена частей. (Эти функции выполняют работу, сходную с командами dirname(1) и basename(1).)
#include
char *dirname(char *
char *basename(char *
Обе функции возвращают указатель на строку с завершающим нулем (которая может быть статически выделенной)
Так, например, для имени пути /home/britta/prog.c функция dirname() возвращает /home/britta, а функция basename() вернет prog.c. Благодаря сцеплению строки, возвращенной функцией dirname(), c символом слеша и со строкой, возвращенной функцией basename(), получается полное имя пути.
Обратите внимание на следующие моменты, касающиеся работы функций dirname() и basename().
• Завершающие символы / в аргументе pathname игнорируются.
• Если аргумент pathname не содержит слешей, функция dirname() возвращает строку с точкой (.), а функция basename() возвращает имя pathname.
• Если аргумент pathname состоит только из слеша, то обе функции возвращают строку /. Применение описанного выше правила сцепления для получения имени пути из возвращенных строк привело бы к появлению строки ///. Такое имя пути является корректным. Поскольку несколько последовательных символов / эквивалентны одному, имя пути /// эквивалентно имени /.
• Если аргумент pathname является нулевым (NULL) указателем или пустой строкой, обе функции возвращают строку с точкой (.). (Сцепление таких строк приводит к имени пути./., которое эквивалентно имени., то есть текущего каталога.)
В табл. 18.3 показаны строки, возвращаемые функциями dirname() и basename() при различных именах пути.
Обе функции, dirname() и basename(), могут изменять строку, на которую указывает аргумент pathname. Таким образом, если желательно сохранить строку с именем пути, то следует передать ее копии функциям dirname() и basename(), как показано в листинге 18.5. Эта программа задействует функцию strdup() (которая вызывает функцию malloc()), чтобы сделать копии строк, предназначенные для передачи функциям dirname() и basename(). Затем она применяет функцию free() для высвобождения пространства, использовавшегося дубликатами.
Таблица 18.3. Примеры строк, возвращаемых функциями dirname() и basename()
Строка имени пути
dirname()
basename()
/
/
/
/usr/bin/zip
/usr/bin
zip
/etc/passwd////
/etc
passwd
/etc////passwd
/etc
passwd
etc/passwd
etc
passwd
passwd
.
passwd
passwd/
.
passwd
..
.
..
NULL
.
.
Листинг 18.5. Использование функций dirname() и basename()
irs._links/t_dirbasename.c
#include
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
char *t1, *t2;
int j;
for (j = 1; j < argc; j++) {
t1 = strdup(argv[j]);
if (t1 == NULL)
errExit("strdup");
t2 = strdup(argv[j]);
if (t2 == NULL)
errExit("strdup");
printf("%s ==> %s + %s\n", argv[j],
dirname(t1), basename(t2));
free(t1);
free(t2);
}
exit(EXIT_SUCCESS);
}
irs._links/t_dirbasename.c
И в завершение обратите внимание на то, что функции dirname() и basename() могут возвращать указатели на статически выделенные строки, которые могут быть изменены последующими вызовами этих же функций.
Индексный дескриптор не содержит имени файла. Взамен этого имена назначаются файлам путем записей в каталогах, которые являются таблицами, перечисляющими имена файлов с соответствующими номерами индексных дескрипторов. Такие записи называют (жесткими) ссылками. Файл может обладать несколькими ссылками, статус которых одинаков. Ссылки создаются и удаляются с помощью системных вызовов link() и unlink(). Файл можно переименовать, используя системный вызов rename().