Если для пользователей необходимо отображать текущий путь каталога, хорошим решением будет проверка переменной окружения
PWD
. Если она установлена, она содержит путь, который применяется пользователем и который может содержать символические ссылки на некоторые элементы пути. Этот путь обычно и должен отображаться приложением по желанию пользователя. Для облегчения задачи библиотека С в Linux предоставляет функцию
get_current_dir_name
, реализуемую следующим образом.
char * get_current_dir_name {
char * env = getenv("PWD");
if (env)
return strdup(env);
else
return getcwd(NULL, 0);
}
14.1.2.
Специальные файлы
.
и
..
Каждый каталог, включая корневой, содержит также два специальных файла под именами
.
и
..
, полезные при определенных условиях. Первый,
.
— то же самое, что и текущий каталог. Это означает, что имена
somefile
и
./somefile
эквивалентны.
Еще одно специальное имя файла,
..
, является родительским каталогом текущего каталога. В случае корневого каталога
..
относится к самому корневому каталогу (поскольку у корневого каталога нет родительского каталога).
И
.
, и
..
можно применять везде, где можно использовать имя каталога. Нормально то, что отношение символических ссылок к путям вроде
../include/mylib
и именам файлов наподобие
/./foo/.././bar/./fubar/../../usr/bin/less
является законным (хотя эти названия довольно запутаны) [101] .
101
Имя этого пути эквивалентно более простому
/usr/bin/less
.
14.1.3. Смена текущего каталога
Предусмотрено два системных вызова, меняющих текущий каталог процесса:
chdir
и
fchdir
.
#include <unistd.h>
int chdir(const char * pathname);
int fchdir(int fd);
Первый системный вызов получает имя каталога в качестве единственного аргумента; второй принимает файловый дескриптор, являющийся открытым каталогом. В каждом случае специфицированный каталог делается текущим рабочим каталогом. Эти функции могут не работать, если в аргументе определен файл, который не является каталогом, или если у процесса нет соответствующих полномочий.
14.2. Смена корневого каталога
Хотя в системе имеется один корневой каталог, значение
/
может меняться для каждого процесса в системе. Это обычно делается для предотвращения доступа к файловой системе со стороны сомнительных процессов (например, демоны ftp, обрабатывающие запросы ненадежных пользователей). Например, если в качестве корневого каталога процесса определен
/home/ftp
, запуск
chdir("/")
сделает текущий каталог процесса
/home/ftp
, a
getcwd
вернет
/
для поддержания последовательности данного процесса. С целью обеспечения безопасности, если процесс пытается выполнить
chdir("/..")
, он остается в своем каталоге
/
(каталог
/home/ftp
в масштабах всей системы), так же как и нормальные процессы, выполняющие
chdir("/..")
остаются в корневом каталоге в масштабах всей системы. Процесс может легко изменять
свой текущий корневой каталог с помощью системного вызова
chroot
. Но путь нового корневого каталога процесса интерпретируется с помощью текущего установленного корневого каталога, поэтому
chroot("/")
не модифицирует текущий корневой каталог процесса.
#include <unistd.h>
int chroot(const char * path);
Здесь
path
определяет новый корневой каталог для процесса. Этот системный вызов, однако, не изменяет текущий каталог процесса. У процесса все еще есть доступ к файлам в текущем каталоге, а также в родственном ему каталоге (
../../directory/file
). Большинство процессов, выполняющих
chroot
, немедленно меняют свои текущие каталоги, чтобы находиться внутри новой корневой иерархии, с помощью
chdir("/")
или чего-либо подобного. Отмена этого действия может вызвать проблемы с безопасностью в некоторых приложениях.
14.3. Создание и удаление каталогов
14.3.1. Создание новых каталогов
Создание новых каталогов выполняется очень просто.
#include <fcntl.h>
#include <unistd.h>
int mkdir(const char * dirname, mode_t mode);
Путь, определенный в
dirname
, создается как новый каталог с полномочием
mode
(что модифицируется
umask
процесса). Если
dirname
определяет существующий файл, или некоторые элементы dirname не являются каталогом или символической ссылкой на него, системный вызов не удается.
14.3.2. Удаление каталогов
Удаление каталога — это практически то же, что и удаление файла; меняется разве что имя системного вызова.
#include <unistd.h>
int rmdir(char * pathname);
Для успешного выполнения
rmdir
каталог должен быть пустым (он не должен содержать ничего, кроме вездесущих
.
и
..
); в противном случае возвращается
ENOTEMPTY
.
14.4. Чтение содержимого каталога
Обычно программам требуется получать список файлов, содержащихся в каталоге. Linux предоставляет ряд функций, позволяющих обрабатывать каталог как абстрактный объект, что дает возможность избежать зависимости программ от точного формата каталогов, реализуемого файловой системой. Открытие и закрытие каталогов осуществляется очень просто.
#include <dirent.h>
DIR * opendir(const char * pathname);
int closedir(DIR * dir);
Системный вызов
opendir
возвращает указатель на тип данных
DIR
, который является абстрактным (как и структура
stdio
по имени
FILE
) и которым не следует манипулировать вне библиотеки С. Поскольку каталоги можно открывать только для чтения, нет необходимости определять, в каком режиме открывается каталог,
opendir
срабатывает только в случае существования каталога — этот вызов нельзя использовать для создания новых каталогов (для этого служит
mkdir
). Закрытие каталога может не сработать только в случае некорректного значения аргумента