Файлы существуют в нескольких качествах:
В файловой системе UNIX хранятся различные объекты: файлы, каталоги, символические ссылки, файлы устройств, FIFO, сокеты. Объекты в ФС адресуются именами и характеризуются правами доступа. Один объект может иметь несколько имен. Права доступа (R)ead, (W)rite, e(X)ecute определены по отдельности для трех категорий пользователей (U)ser, (G)roup, (O)ther. Дополнительно к правам доступа есть флаг смены владельца на время выполнения файла, смены группы на время выполнения файла и признак «липкости», что бы он не означал. Права доступа и флаги для разных типов объектов интерпретируются немного по-разному.
Файлы можно создавать (одновременно давая имя), добавлять новые имена, удалять старые имена, а также менять права доступа к файлу (влияет на сам файл, вне зависимости от того к какому из его имен применялась операция). Администратор может еще и поменять владельца файла.
Файл оставшийся без имени и не используемый для вода/вывода или в качестве источника данных программы – уничтожается. Вызовы ядра Unix, связанные с файловой системой можно условно поделить на несколько групп:
Метаданные:
int chown(const char *path, uid_t owner, gid_t group); //смена владельца и группы
int chmod(const char *path, mode_t mode); //смена прав доступа
int stat(const char *file_name, struct stat *buf); //получение всех атрибутов файла
Имена в каталогах:
int mkdir(const char *pathname, mode_t mode); //создание каталога
int rmdir(const char *pathname); //удаление каталога
int link(const char *oldpath, const char *newpath); //создание нового имени
int unlink(const char *pathname); //удаление старого имени
int rename(const char *oldpath, const char *newpath); //атомарная операция удаляющая имя oldpath и создающая newpath
Создание символических ссылок, FIFO и файлов устройств:
int symlink(const char *oldpath, const char *newpath); //создание файла ссылки newpath ссылающегося на oldpath
int mknod(const char *path, mode_t mode, dev_t dev); //создание FIFO или файла устройства (определяется mode)
Открытые файлы = файловые дескрипторы
В качестве источника данных файлы представлены в программе в виде файловых дескрипторов – целых чисел являющимися индексами в таблице открытых файлов. За файловыми дескрипторами могут скрываться файлы, FIFO и файлы устройств в ФС, неименованые каналы - pipe или сокеты. Для операций чтения и записи все эти источники данных равноценны.
По соглашениям UNIX вновь запущенная программа может рассчитывать на три открытых файла с индексами 0,1,2, соответствующие stdin, stdout, stderr. Ответственность за это возлагается на программу вызвавшую exec().
Работа с метаданными файла может происходить и по имени и по файловому дескриптору.
int fchmod(int fd, mode_t mode);
int fchown(int fd, uid_t owner, gid_t group);
int fstat(int fd, struct stat *buf);
//Перенаправление стандартного файла ошибок
int newfd;
char *fname="file";
if( (newd = creat(fname, S_IRUSR|S_IWUSR) >=0 ) ){
dup2(newfd,2);
close(newfd);
}else{
perror("Cannot open new stderr file:");
exit(1);
}
// Создание большого "дырявого" файла, который имеет длину 10000000 байт а реально занимает 1 блок на диске
newd = open(fname, O_WRONLY|O_TRUNC);
lseek(fd,10000000,SEEK_SET);
write(fd," ",1);
//узнаем текущую позицию чтения/записи
pos=lseek(newfd,0,SEEK_CUR);
//делаем "невидимым" временный файл
int tmpfd;
char tmpname[]="/tmp/qqqXXXXXX"
mktemp(tmpname);
int tmpfs = open(tmpfname, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
unlink(tmpfname);
//теперь файл не имеет имени и будет уничтожен по завершению нашей программы
//читать и писать в него можно без проблем
write(tmpfd,tmpname,1);
lseek(tmpfd,0,SEEK_SET);
read(tmpfd,tmpname,1);