Эта простая программа выводит текущий каталог, переходит в родительский каталог, затем выводит новый текущий каталог. (Переменная cp
$ ch08-getcwd
Current dir: /home/arnold/work/prenhall/progex/code/ch08
Changing to ..
Current dir is now: /home/arnold/work/prenhall/progex/code
Формально, если аргумент buf
NULL
, поведение getcwd()
не определено. В данном случае версия GLIBC getcwd()
вызовет malloc()
за вас, выделяя буфер с размером size
. Идя даже дальше, если size
равен 0, выделяется «достаточно большой» буфер для вмещения возвращенного имени пути. В любом случае вы должны вызвать для возвращенного указателя free()
после завершения работы с буфером.Поведение GLIBC полезно, но не переносимо. Для кода, который должен работать на разных платформах, вы можете написать замещающую функцию, которая предоставляет те же самые возможности, в то же время заставив ее непосредственно вызывать getcwd()
Системы GNU/Linux предоставляют файл /proc/self/cwd
$ cd /tmp
$ ls -l /рroc/self/cwd
lrwxrwxrwx 1 arnold devel 0 Sep 9 17:29 /proc/self/cwd -> /tmp
$ cd
$ ls -l /proc/self/cwd
lrwxrwxrwx 1 arnold devel 0 Sep 9 17:30 /proc/self/cwd -> /home/arnold
Это удобно на уровне оболочки, но представляет проблему на уровне программирования. В частности, размер файла равен нулю! (Это потому, что это файл в /proc
Почему нулевой размер является проблемой? Если вы помните из раздела 5.4.5 «Работа с символическими ссылками», lstat()
st_size
структуры struct stat
число символов в имени связанного файла. Это число может затем использоваться для выделения буфера соответствующего размера для использования с readlink()
. Здесь это не будет работать, поскольку размер равен нулю. Вам придется использовать (или выделять) буфер, который, как вы полагаете, достаточно большой. Однако, поскольку readlink()
не выдает символов больше, чем вы предоставили места, readlink()
не завершается неудачей, когда недостаточно места. (См. в разделе 5.4.5 «Работа с символическими ссылками» функцию Coreutils xreadlink()
, которая решает проблему.)В дополнение к getcwd()
8.4.3. Перемещение по иерархии: nftw()
Обычной задачей программирования является обработка целых иерархий каталогов: выполнение действий над каждым файлом и каждым каталогом и подкаталогом в целостном дереве. Рассмотрите, например, команду du
chown -R
', которая рекурсивно изменяет владельцев, или программу find
, которая находит файлы, подходящие по определенным критериям.На данный момент вы знаете достаточно, чтобы написать собственный код для открывания и чтения каталогов вручную, вызова stat()
lstat()
) для каждого элемента и рекурсивной обработки подкаталогов. Однако, такой код трудно сделать правильным; можно выйти за пределы дескрипторов файлов, если вы будете оставлять родительские каталоги открытыми при обработке подкаталогов; нужно решить, обрабатывать ли символические ссылки как таковые или как файлы, на которые они указывают; нужно суметь справиться с каталогами, которые недоступны для чтения или поиска и т.д. Также трудно писать один и тот же код снова и снова, когда он требуется в нескольких приложениях.8.4.3.1. Интерфейс nftw()
Чтобы избавиться от проблем, System V предложила функцию ftw()
ftw()
осуществляла всю работу по «прохождению» дерева (иерархии) файлов. Вы предоставляете ей указатель на функцию, и она вызывает эту функцию для каждого объекта файла, с которым сталкивается. Ваша функция должна затем обработать каждый объект файловой системы, как считает нужным.