CHOWN(2) | Руководство программиста Linux | CHOWN(2) |
chown, 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():
fchownat():
Данные системные вызовы изменяют владельца и группу для файла. Системные вызовы chown(), fchown() и lchown() отличаются только в том, каким образом задается файл:
Только привилегированный процесс (Linux: имеющий мандат CAP_CHOWN) может сменить владельца файла. Владелец файла может сменить группу файла на любую группу, в которой он числится. Привилегированный процесс (Linux: с CAP_CHOWN) может задавать произвольную группу.
Если параметр owner или group равен -1, то соответствующий идентификатор не изменяется.
Когда владелец или группа исполняемого файла изменяется непривилегированным пользователем, то биты режима S_ISUID и S_ISGID сбрасываются В POSIX не указано, должно ли это происходить если chown() выполняется суперпользователем; поведение в Linux зависит от версии ядра и начиная с Linux 2.2.13, root рассматривается как обычный пользователь. В случае исполняемого файла вне группы (т. е., у которого не установлен бит S_IXGRP) бит S_ISGID указывает на обязательную блокировку, и не сбрасывается при выполнении chown().
Когда владелец или группа исполняемого файла изменяется (любым пользователем), то все наборы мандатов файла очищаются.
Системный вызов fchownat() работает также как системный вызов chown(), за исключением случаев, описанных здесь.
Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в chown()).
Если в pathname задан относительный путь и dirfd равно специальному значению AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как chown()).
Если в pathname задан абсолютный путь, то dirfd игнорируется.
Аргумент flags представляет собой битовую маску, создаваемую побитовым сложением (OR) следующих значений;
Смотрите в openat(2) объяснение необходимости fchownat().
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
В зависимости от файловой системы могут также возвращаться другие ошибки, перечисленные далее.
Наиболее распространённые ошибки chown() перечислены далее.
Общие ошибки fchown() таковы:
В fchownat() могут возникнуть те же ошибки, что и в chown(). Также, в fchownat() могут возникнуть следующие ошибки:
Вызов 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), то правила следующие:
Начиная с Linux 4.12, параметры монтирования -o grpid и -o nogrpid поддерживаются для ext2, ext3, ext4 и XFS. Для файловых систем, не поддерживающих эти параметры монтирования, используются правила как для -o nogrpid.
В старых ядрах, где fchownat() отсутствует, обёрточная функция glibc использует chown() или lchown(). Если pathname является относительным путём, то glibc собирает путь относительно символической ссылки в /proc/self/fd, которая соответствует аргументу dirfd.
Семантика 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); }
chgrp(1), chown(1), chmod(2), flock(2), path_resolution(7), symlink(7)
2019-03-06 | Linux |