Выбрать главу

 fd_dst=open(argv[2], O_RDWR | O_CREAT);

 /* Определим размер исходного файла */

 fstat(fd_src, &filestat);

 /* Сделаем размер целевого файла равным исходному */

 lseek(fd_dst, filestat.st_size - 1, SEEK_SET);

 /* Зададим отображение */

 addr_src=mmap((caddr_t)0, filestat.st_size,

  PROT_READ, MAP_SHARED, fd_src, 0);

 addr_dst=mmap((caddr_t)0, filestat.st_size,

  PROT_READ | PROT_WRITE, MAP_SHARED, fd_dst, 0);

 /* Копируем области памяти */

 memcpy(addr_dst, addr_src, filestat.st_size);

 exit(0);

}

Поскольку, как обсуждалось выше, с помощью вызова mmap(2) нельзя изменить размер файла, это было сделано с помощью вызова lseek(2) с последующей записью одного байта так, что размер целевого файла стал равным размеру исходного. При этом в целевом файле образуется "дыра", которая, к счастью, сразу же заполняется содержимым копируемого файла.

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

Владелец-пользователь и владелец-группа файла могут быть изменены с помощью системных вызовов chown(2), fchown(2) и lchown(2):

#include <unistd.h>

#include <sys/types.h>

int chown(const char *path, uid_t owner, gid_t group);

int fchown(int fildes, uid_t owner, gid_t group);

int lchown(const char *path, uid_t owner, gid_t group);

Все три вызова работают одинаково за исключением ситуации, когда адресуемый файл является символической связью. В последнем случае вызов lchown(2) действует на сам файл — символическую связь, а не на целевой файл (т.е. не следует символической связи). В функциях chown(2) и lchown(2) файл адресуется по имени, а в fchown(2) — по файловому дескриптору. Если значение owner или group установлено равным -1, соответствующий владелец файла не изменяется.

В версиях BSD UNIX только суперпользователь может изменить владение файлом. Это ограничение призвано, в первую очередь, не допустить "скрытие" файлов под именем другого пользователя, например, при установке квотирования ресурсов файловой системы. Владельца-группу можно изменить только для файлов, которыми вы владеете, причем им может стать одна из групп, членом которой вы являетесь. Эти же ограничения определены и стандартом POSIX.1.

В системах ветви System V эти ограничения являются конфигурируемыми, и в общем случае в UNIX System V пользователь может изменить владельца собственных файлов.

В случае успешного изменения владельцев файла биты SUID и SGID сбрасываются, если процесс, вызвавший chown(2) не обладает правами суперпользователя.

Права доступа

Как уже обсуждалось в предыдущей главе, каждый процесс имеет четыре пользовательских идентификатора — UID, GID, EUID и EGID. В то время как UID и GID определяют реального владельца процесса, EUID и EGID определяют права доступа процесса к файлам в процессе выполнения. В общем случае реальные и эффективные идентификаторы эквивалентны. Это значит, что процесс имеет те же привилегии, что и пользователь, запустивший его. Однако, как уже обсуждалось выше, возникают ситуации, когда процесс должен получить дополнительные привилегии, чаще всего — привилегии суперпользователя. Это достигается установкой битов SUID и SGID. Примером такого процесса может служить утилита passwd(1), изменяющая пароль пользователя.

Права доступа к файлу могут быть изменены с помощью системных вызовов chmod(2) и fchmod(2):

#include <sys/types.h>

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

int fchmod(int fildes, mode_t mode);

Значение аргумента mode определяет устанавливаемые права доступа и дополнительные атрибуты (такие как SUID, SGID и Sticky bit), и создается путем логического объединения различных флагов, представленных в табл. 2.14. Вторая колонка таблицы содержит восьмеричные значения для девяти битов прав доступа (чтение, запись и выполнение для трех классов доступа) и трех битов дополнительных атрибутов.

Таблица 2.14. Флаги аргумента mode

Флаг Биты Значение
S_ISUID 04000 Установить бит SUID
S_ISGID 020#0 Установить бит SGID, если # равно 7, 5, 3 или 1. Установить обязательное блокирование файла, если # равно 6, 4, 2 или 0
S_ISVTX 01000 Установить Sticky bit
S_IRWXU 00700 Установить право на чтение, запись и выполнение для владельца-пользователя
S_IRUSR 00400 Установить право на чтение для владельца-пользователя
S_IWUSR 00200 Установить право на запись для владельца-пользователя
S_IXUSR 00100 Установить право на выполнение для владельца-пользователя
S_IRWXG 00070 Установить право на чтение, запись и выполнение для владельца-группы
S_IRGRP 00040 Установить право на чтение для владельца-группы
S_IWGRP 00020 Установить право на запись для владельца-группы
S_IXGRP 00010 Установить право на выполнение для владельца-группы
S_IRWXO 00007 Установить право на чтение, запись и выполнение для остальных пользователей
S_IROTH 00004 Установить право на чтение для остальных пользователей
S_IWOTH 00002 Установить право на запись для остальных пользователей
S_IXOTH 00001 Установить право на выполнение для остальных пользователей