Other Alias
fchown, lchown, fchownatОБЗОР
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);
#include <fcntl.h> /* определения констант of AT_* */
#include <unistd.h>
int fchownat(int dirfd, const char *pathname,
uid_t owner, gid_t group, int flags);
Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):
fchown(), lchown():
-
_BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* начиная с glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
fchownat():
-
- Начиная с glibc 2.10:
- _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _ATFILE_SOURCE
ОПИСАНИЕ
Данные системные вызовы изменяют владельца и группу для файла. Системные вызовы chown(), fchown() и lchown() отличаются только в том, каким образом задается файл:- *
- chown() изменяет владельца для файла, задаваемого параметром pathname, который разыменовывается, если является символьной ссылкой.
- *
- fchown() изменяет владельца для файла, задаваемого открытым файловым дескриптором fd.
- *
- lchown() похож на chown() за исключением того, что он не разыменовывает символьные ссылки.
Только привилегированный процесс (Linux: имеющий мандат CAP_CHOWN) может сменить владельца файла. Владелец файла может сменить группу файла на любую группу, в которой он числится. Привилегированный процесс (Linux: с CAP_CHOWN) может задавать произвольную группу.
Если параметр owner или group равен -1, то соответствующий идентификатор не изменяется.
Когда владелец или группа исполняемого файла изменяется непривилегированным пользователем, то биты режима S_ISUID и S_ISGID сбрасываются. В POSIX не указано, должно ли это происходить если chown() выполняется суперпользователем; поведение в Linux зависит от версии ядра. В случае исполняемого файла вне группы (т.е., у которого не установлен бит S_IXGRP) бит S_ISGID указывает на обязательную блокировку, и не сбрасывается при выполнении chown().
fchownat()
Системный вызов fchownat() работает также как системный вызов chown(), за исключением случаев, описанных здесь.Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в chown()).
Если в pathname задан относительный путь и dirfd равно специальному значению AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как chown()).
Если в pathname задан абсолютный путь, то dirfd игнорируется.
Аргумент flags представляет собой битовую маску, создаваемую побитовым сложением (OR) следующих значений;
- AT_EMPTY_PATH (начиная с Linux 2.6.39)
-
Если значение pathname равно пустой строке, то выполнять действие над
файлом, на который указывает dirfd (который может быть получен с помощью
open(2) с флагом O_PATH). В этом случае, dirfd может указывать на
файл любого типа, а не только на каталог. Если dirfd равно AT_FDCWD,
то вызов выполняет действие над текущим рабочим каталогом. Этот флаг есть
только в Linux; для получения его определения определите _GNU_SOURCE.
- AT_SYMLINK_NOFOLLOW
- Если значение pathname является символьной ссылкой, не разыменовывать её, а изменить владельца самой ссылки, как это делается в lchown() (по умолчанию, fchownat() разыменовывает символьные ссылки как и chown()).
Смотрите в openat(2) объяснение необходимости fchownat().
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.ОШИБКИ
В зависимости от файловой системы могут также возвращаться другие ошибки, перечисленные далее.Наиболее распространённые ошибки chown() перечислены далее.
- EACCES
- Поиск запрещён из-за одного из частей префикса пути (См. также path_resolution(7).)
- EFAULT
- Аргумент pathname указывает за пределы доступного адресного пространства.
- ELOOP
- Во время определения pathname встретилось слишком много символьных ссылок.
- ENAMETOOLONG
- Слишком длинное значение аргумента pathname.
- ENOENT
- Файл не существует.
- ENOMEM
- Недостаточное количество памяти ядра.
- ENOTDIR
- Компонент в префиксе пути не является каталогом.
- EPERM
- Вызывающий процесс не имеет требуемых прав (см. выше), чтобы изменять владельца и/или группу.
- EROFS
- Указанный файл находится на файловой системе, смонтированной только для чтения.
Общие ошибки fchown() таковы:
- EBADF
- Значение fd не является правильным открытым файловым дескриптором.
- EIO
- Во время изменения индексного дескриптора (inode) возникла низкоуровневая ошибка ввода/вывода.
- ENOENT
- См. выше.
- EPERM
- См. выше.
- EROFS
- См. выше.
В fchownat() могут возникнуть те же ошибки, что и в chown(). Также, в fchownat() могут возникнуть следующие ошибки:
- EBADF
- Значение dirfd не является правильным файловым дескриптором.
- EINVAL
- Указано неверное значение в flags.
- ENOTDIR
- Значение pathname содержит относительный путь и dirfd содержит файловый дескриптор, указывающий на файл, а не на каталог.
ВЕРСИИ
Вызов fchownat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.СООТВЕТСТВИЕ СТАНДАРТАМ
chown(), fchown(), lchown(): 4.4BSD, SVr4, POSIX.1-2001, POSIX.1-2008.Версия из 4.4BSD может использоваться только суперпользователем (то есть, обычные пользователи не могут менять владельцев).
fchownat(): POSIX.1-2008.
ЗАМЕЧАНИЯ
Назначение владельца новых файлов
При создании нового файла (например с помощью open(2) или mkdir(2)), его владельцем будет установлен ID пользователя из файловой системы создающего процесса. Группа файла зависит от нескольких факторов, включая тип файловой системы, параметры монтирования и установлен ли бит режима set-group-ID на родительском каталоге. Если файловая система поддерживает параметры mount(8) -o grpid (тоже что и -o bsdgroups) и -o nogrpid (тоже что и -o sysvgroups), то правила следующие:- *
- Если файловая система смонтирована с параметром -o grpid, то группой нового файла будет группа родительского каталога.
- *
- Если файловая система смонтирована с параметром -o nogrpid и на родительском каталоге сброшен бит set-group-ID, то группой нового файла будет GID файловой системы того же процесса.
- *
- Если файловая система смонтирована с параметром -o nogrpid и на родительском каталоге установлен бит set-group-ID, то группой нового файла будет группа родительского каталога.
Начиная с Linux 2.6.25, параметры монтирования -o grpid и -o nogrpid поддерживаются для ext2, ext3, ext4 и XFS. Для файловых систем, не поддерживающих эти параметры монтирования, используются правила как для -o nogrpid.
Замечания по glibc
В старых ядрах, где fchownat() отсутствует, обёрточная функция glibc использует chown() или lchown(). Если pathname является относительным путём, то glibc собирает путь относительно символической ссылки в /proc/self/fd, которая соответствует аргументу dirfd.NFS
Семантика chown() сознательно нарушается в файловых системах NFS, в которых включено отображение UID. Также, нарушается семантика всех системных вызовов, которые обеспечивают доступ к содержимому файлов, так как chown() может привести к немедленному отзыву доступа к уже открытым файлам. Кэширование на клиентской стороне может привести к задержке между сменой доступа пользователю и временем, когда файл действительно станет доступным.Историческая справка
Первоначальные версии системных вызовов chown(), fchown() и lchown() в Linux поддерживали только 16-битные идентификаторы пользователей и групп. Позднее в Linux 2.4 были добавлены вызовы chown32(), fchown32() и lchown32(), поддерживающие 32-битные идентификаторы. В glibc обёрточные функции chown(), fchown() и lchown() работают одинаково вне зависимости от версий ядра.В версиях Linux до 2.1.81 (кроме 2.1.46) chown() не следовал по символьным ссылкам. Начиная с версии Linux 2.1.81 chown() следует по символьным ссылкам, и существует новый системный вызов lchown(), который не следует по символьным ссылкам. Начиная с Linux 2.1.86 этот новый вызов (имеющий тот же смысл, что и старый chown()) имеет тот же самый номер системного вызова, а chown() получил новый номер.
ПРИМЕР
Следующая программа изменять владельца файла, указанного вторым в командной строке, на значение, указанное в первом аргументе командной строки. Новый владелец может задаваться в виде числового пользовательского ID, или в виде имени пользователя (которое преобразуется в пользовательский ID с помощью getpwnam(3), выполняющего поиск в системном файле паролей).
Исходный код программы
#include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { uid_t uid; struct passwd *pwd; char *endptr; if (argc != 3 || argv[1][0] == '\0') { fprintf(stderr, "%s <owner> <file>\n", argv[0]); exit(EXIT_FAILURE); } uid = strtol(argv[1], &endptr, 10); /* Allow a numeric string */ if (*endptr != '\0') { /* Was not pure numeric string */ pwd = getpwnam(argv[1]); /* Try getting UID for username */ if (pwd == NULL) { perror("getpwnam"); exit(EXIT_FAILURE); } uid = pwd->pw_uid; } if (chown(argv[2], uid, -1) == -1) { perror("chown"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }