int fchdir(int fd); /* XSI */
Функция
chdir()
принимает строку с названием каталога, тогда как
fchdir()
ожидает дескриптор файла, который был открыт для каталога с помощью
open()
.
[83] Обе возвращают 0 при успехе и -1 при ошибке (с
errno
, установленной соответствующим образом). Обычно, если
open()
для каталога завершается успешно,
fchdir()
также достигает цели, если кто-то не изменил права доступа к каталогу между вызовами, (
fchdir()
сравнительно новая функция; на старых системах Unix ее нет.)
Использование этих функций почти тривиально. Следующая программа,
ch08-chdir.c
, демонстрирует обе функции. Она демонстрирует также, что
fchdir()
может потерпеть неудачу, если права доступа открытого каталога не включают доступа на поиск (исполнение).
1 /* ch08-chdir.c --- демонстрация chdir() и fchdir().
2 Для краткости проверка ошибок опущена */
3
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 int main(void)
11 {
12 int fd;
13 struct stat sbuf;
14
15 fd = open(".", O_RDONLY); /* открыть каталог для чтения */
16 fstat(fd, &sbuf); /* получить сведения, нужны начальные права доступа */
17 chdir(".."); /* 'cd ..' */
18 fchmod(fd, 0); /* отменить права доступа каталога */
19
20 if (fchdir(fd) < 0) /* попытаться выполнить 'cd' обратно, должно завершиться неудачей */
21 perror("fchdxr back");
22
23 fchmod(fd, sbuf.st_mode & 07777); /* восстановить первоначальные права доступа */
24 close(fd); /* все сделано */
25
26 return 0;
27 }
Строка 15 открывает текущий каталог. Строка 16 вызывает
fstat()
для открытого каталога, так что мы получаем копию его прав доступа. Строка 17 использует
chdir()
для перемещения на один уровень в иерархии файлов. Строка 18 выполняет грязную работу, отменяя все права доступа первоначального каталога.
Строки 20–21 пытаются перейти обратно в первоначальный каталог. Ожидается, что эта попытка будет безуспешной, поскольку текущие права доступа не позволяют это. Строка 23 восстанавливает первоначальные права доступа, '
sbuf.st_mode & 07777
' получает младшие 12 битов прав доступа; это обычные 9 битов rwxrwxrwx и биты setuid, setgid и «липкий» бит, которые мы обсудим в главе 11 «Права доступа и ID пользователя и группы». Наконец, строка 24 заканчивает работу, закрывая открытый дескриптор файла. Вот что происходит при запуске программы.
$ <b>ls -ld .</b> /* Показать текущие права доступа */
drwxr-xr-x 2 arnold devel 4096 Sep 9 16:42 .
$ <b>ch08-chdir</b> /* Запустить программу */
fchdir back: Permission denied /* Ожидаемая неудача */
$ <b>ls -ld .</b> /* Снова посмотреть на права доступа */
drwxr-xr-x 2 arnold devel 4096 Sep 9 16:42 /* Все восстановлено как раньше */
8.4.2. Получение текущего каталога:
getcwd()
Названная должным образом функция
getcwd()
получает абсолютный путь текущего рабочего каталога.
#include <unistd.h> /* POSIX */
char *getcwd(char *buf, size_t size);
Функция заносит в
buf
путь; ожидается, что размер
buf
равен
size
байтам. При успешном завершении функция возвращает свой первый аргумент. В противном случае, если требуется более
size
байтов, она возвращает
NULL
и устанавливает в
errno ЕRANGE
. Смысл в том, что если случится
ERANGE
, следует попытаться выделить буфер большего размера (с помощью
malloc()
или
realloc()
) и попытаться снова.
Если любой из компонентов каталога, ведущих к текущему каталогу, не допускает чтения или поиска,
getcwd()
может завершиться неудачей, а
errno
будет установлен в
EACCESS
. Следующая простая программа демонстрирует ее использование:
/* ch08-getcwd.c --- демонстрация getcwd().
Проверка ошибок для краткости опущена */
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(void) {
char buf[PATH_MAX];
char *cp;
cp = getcwd(buf, sizeof(buf));
printf("Current dir: %s\n", buf);
printf("Changing to ..\n");
chdir(".."); /* 'cd ..' */
cp = getcwd(buf, sizeof(buf));
printf("Current dir is now: %s\n", buf);