Доступ к каталогам

Создание каталога

Для создания каталога в вызов mkdir() передаётся путь к создаваемому каталогу. Вышележащий каталог должен существовать (??) и пользователь должен иметь право на запись в него.

#include <sys/stat.h>
int mkdir(const char *path, mode_t mode);

Создание имени файла

При создании файла вызовом open() с флагом O_CREAT в указанном в пути к файлу каталоге создаётся запись с именем файла. Новое имя для файла можно создать вызовом link().

#include <unistd.h>
 int link("oldpath", "newpath");

Поскольку жёсткие ссылки возможны только в рамках одной ФС, то и имена "oldpath" и "newpath" должны находиться внутри одной ФС.

Удаление имени файла

В Unix нет операции удаление файла. Есть лишь операция удаление из каталога жёсткой ссылки (имени) на объект. Каждый раз после удаления имени уменьшается счётчик имён в Inode файла. Когда счётчик имён становится равным нулю, файл становится недоступным по имени. Однако, если в этот момент файл был открыт одним или несколькими процессами, то он не удаляется из ФС. Только тогда, когда у файла ноль имён и он не открыт ни в одном процессе, его Inode и его блоки данных помечаются как свободные, т.е. происходит уничтожение файла.

Данное поведение позволяет выполнять трюк с невидимыми временными файлами. Файл создаётся, открывается, и тут же удаляется его имя. В результате невидимый файл будет существовать до завершения процесса в котором он был создан. В такой ситуации аварийное завершение процесса не оставляет нигде в ФС ненужных временных файлов.

Вызов unlink() неприменим к каталогам. unlink() символической ссылки удаляет имя символической ссылки, никак не влияя на объект, на который указывает символическая ссылка.

#include <unistd.h>
 int unlink("file");

Переименование файла

Вызов rename("old", "new") эквивалентен паре вызовов link("old", "new"); unlink("old");. В отличие от этой пары rename() можно применять к каталогам, а так же он не удалит объект при переименовании его в самого себя - rename("x", "x").

Чтение каталога

Каталог в Linux можно открыть как файл с помощью open с флагом O_DIRECTORY:

struct old_linux_dirent  {
     long d_ino;                 /* inode number */
     off_t d_off;                /* offset to this dirent */
     unsigned short d_reclen;    /* length of this d_name */
     char d_name [NAME_MAX+1];   /* file name (null-terminated) */
} olddirp[SIZE];

// в Linux каталог можно открыть с помощью open
int fd=open("dirname", O_DIRECTORY); 
// и прочитать его внутреннюю структуру
retval=readdir(fd, olddirp, SIZE);

но так делать не надо.

Для работы с каталогами надо использовать библиотечные функции opendir(3), readdir(3) и т.д.

#include <dirent.h>
struct dirent {
       ino_t          d_ino;       /* номер inode */
       off_t          d_off;         /* заглушка */
       unsigned short d_reclen;    /* заглушка */
       unsigned char  d_type;      /* тип файла; поле не стандартизовано */
       char           d_name[256]; /* имя файла */
};

// открыть каталог
DIR *dirp;
dirp=opendir("dirname");
// или
dirp=fopendir(fd);

// прочитать запись за записью
struct dirent *rec;
do{
    rec=readdir(dirp);
}while(rec)

// начать сначала
rewinddir(dirp);

// закрыть каталог
closedir(dirp);

Удаление каталога

Удалять можно только пустые каталоги.

#include <unistd.h>
int rmdir("pathname");