Вы здесь
access
int access(const char *filename, int mode)
Описание:
Функция access() относится к UNIX-подобной файловой системе и не определяется стандартом ANSI С. Она используется для проверки существования файла. Может использоваться и для того, чтобы выяснить, защищен ли файл от записи и является ли он исполняемым. Имя проверяемого файла указывается с помощью filename. Значение mode определяет, что именно проверяет access():
Значение | Проверяет |
---|---|
0 | Существование файла |
1 | Исполняемость файла |
2 | Доступность для записи |
3 | Доступность для чтения |
4 | Доступность для чтения/записи |
Функция access() возвращает 0, если проверяемый вид доступа разрешен; в противном случае она возвращает —1. В случае ошибки заранее определенная глобальная переменная errno устанавливается в одно из следующих значений:
ENOENT | Файл не найден |
EACCES | Нет доступа |
Функции ввода/вывода
Страницы
This article introduces you to the use of access/_access functions in C language through example code. The code is simple and easy to understand, very good, and has a certain reference value. Friends who need it can refer to it.
Under Linux, the access function is declared in the file <unistd.h>, as follows:
int access(const char *pathname, int mode);
The access function is used to determine whether the specified file or directory exists (F_OK), and whether the existing file or directory has readable (R_OK), writable (W_OK), and executable (X_OK) permissions. The four modes of F_OK, R_OK, W_OK, and X_OK are specified by the second parameter mode in the access function. If the specified method is valid, this function returns 0, otherwise it returns -1.
There is no access function under Windows, but there is _access function in the <io.h> file, which is declared as follows:
int _access(const char* _Filename, int _AccessMode);
The function _access under windows is similar to the access function under linux. It is used to determine whether the specified file or directory only exists (00), whether the existing file or directory has only read (04), write only (02), Both read and write (06) permissions. These four methods are specified by the second parameter mode in the _access function. If the value passed in mode is not 0 or 2 or 4 or 6, calling this function will crash. If the specified method is valid, this function returns 0, otherwise it returns -1.
The following is the test code (access.cpp):
#include "access.hpp" #include <iostream> #include <vector> #include <string> #ifdef _MSC_VER #include <io.h> #else #include <unistd.h> #endif namespace access_ { int test_access_1() { #ifdef _MSC_VER const std::string path{ "E:/GitCode/Messy_Test/" }; const std::vector<const std::string> names {"testdata", ".gitignore", "src", "invalid"}; for (auto& name : names) { const std::string tmp = path + name; fprintf(stdout, "file or directory name: \"%s\": ", name.c_str()); if (_access(tmp.c_str(), 0) == 0) fprintf(stdout, "exist, "); else fprintf(stdout, "not exist, "); if (_access(tmp.c_str(), 4) == 0) fprintf(stdout, "only has read premission, "); else fprintf(stdout, "does not have read premission, "); if (_access(tmp.c_str(), 2) == 0) fprintf(stdout, "only has write premission, "); else fprintf(stdout, "does not have write premission, "); if (_access(tmp.c_str(), 6) == 0) fprintf(stdout, "has both read and write premission\n"); else fprintf(stdout, "has neither read nor write premission\n"); } #else const std::vector<const char*> names {"testdata", "CMakeLists.txt", "build.sh", "invalid"}; for (auto name : names) { fprintf(stdout, "file or directory name: \"%s\": ", name); if (access(name, F_OK) == 0) fprintf(stdout, "exist, "); else fprintf(stdout, "not exist, ", name); if (access(name, R_OK) == 0) fprintf(stdout, "has read premission, "); else fprintf(stdout, "does not have read premission, "); if (access(name, W_OK) == 0) fprintf(stdout, "has write premission, "); else fprintf(stdout, "does not have write premission, "); if (access(name, X_OK) == 0) fprintf(stdout, "has execute premission\n"); else fprintf(stdout, "does not have execute premission\n"); } #endif return 0; } } // namespace access_
The execution results under Linux are as follows:
GitHub:https://github.com//fengbingchun/Messy_Test
to sum up
The above is a detailed explanation of the use of the access/_access function in the C language introduced by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message. The editor will reply to you in time. Thank you very much for your support to the Scripthome website!
If you think this article is helpful to you, welcome to reprint, please indicate the source, thank you!
turn:https://www.jb51.net/article/169245.htm
1. The access() function is used to determine whether the user has the permission to access a file (or determine whether a file exists).
Two, need to include #include<unistd.h>
Three, parameters and return values
int access(const char *pathname,int mode)
Parameter:
pathname: indicates the path of the file to be tested
mode: indicates that the possible values of the test mode are:
R_OK: Do you have read permission
W_OK: Whether to have write permission
X_OK: Does it have executable permissions?
F_OK: Does the file exist?
Return value: If the test is successful, return 0, otherwise return -1
Four, actual test
1. Test c code
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
/*
The access() function is used to determine whether the user has permission to access a file (or to determine whether a file exists).
int access(const char *pathname,int mode)
Parameters:
pathname: indicates the path of the file to be tested
mode: indicates that the possible values of the test mode are:
R_OK: Do you have read permission
W_OK: Do you have write permission
X_OK: Does it have executable permissions
F_OK: Does the file exist
Return value: If the test is successful, return 0, otherwise return -1
*/
int main(int argc,char *argv[]){
int rt_value;
if(argc<2){
printf("Usage:%s filename\n",argv[0]);
exit(1);
}
rt_value=access(argv[1],R_OK);
if(rt_value==0)
printf("File:%s can read rt_value=%d\n",argv[1],rt_value);
else
printf("File:%s can't read rt_value=%d \n",argv[1],rt_value);
rt_value=access(argv[1],W_OK);
if(rt_value==0)
printf("File:%s can write rt_value=%d\n",argv[1],rt_value);
else
printf("File:%s can't write rt_value=%d \n",argv[1],rt_value);
rt_value=access(argv[1],X_OK);
if(rt_value==0)
printf("File:%s can execute rt_value=%d\n",argv[1],rt_value);
else
printf("File:%s can't execute rt_value=%d \n",argv[1],rt_value);
rt_value=access(argv[1],F_OK);
if(rt_value==0)
printf("File:%s exist rt_value=%d\n",argv[1],rt_value);
else
printf("File:%s not exist rt_value=%d \n",argv[1],rt_value);
return 0;
}
2. Compile and execute
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* Check for existence */
if( (_access( «crt_ACCESS.TXT», 0 )) != -1 )
{
printf( «File crt_ACCESS.TXT exists\n» );
/* Check for write permission */
/* assume file is read-only */
if( (_access( «crt_ACCESS.TXT», 2 )) == -1 )
printf( «File crt_ACCESS.C does not have write permission\n» );
}
}
/*
Parameters
path
File or directory path.
mode
Permission setting.
Return Value
Each function returns 0 if the file has the given mode. The function returns –1 if the named file does not exist or is not accessible in the given mode; in this case, errno is set as follows:
EACCES
Access denied: file’s permission setting does not allow specified access.
ENOENT
Filename or path not found.
mode value Checks file for
00 Existence only
02 Write permission
04 Read permission
06 Read and write permission
ОБЗОР
#include <unistd.h>
int access(const char *pathname, int mode);
#include <fcntl.h> /* определения констант of AT_* */
#include <unistd.h>
int faccessat(int dirfd, const char *pathname, int mode, int flags);
Требования макроса тестирования свойств для glibc
(см. feature_test_macros(7)):
faccessat():
-
- Начиная с glibc 2.10:
- _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _ATFILE_SOURCE
ОПИСАНИЕ
access проверяет, имеет ли вызвавший процесс права доступа к файлу
pathname. Если pathname является символьной ссылкой, то проверяются
права доступа к файлу, на который она ссылается.
Аргумент mode — это маска выполняемых проверок доступа; может быть
равна значению F_OK, или состоять из одного или несколько побитово
сложенных R_OK, W_OK и X_OK. F_OK проверяет существование
файла. R_OK, W_OK и X_OK запрашивают проверку, соответственно,
существования файла и возможности его чтения, записи или выполнения.
Проверка осуществляется с использованием реального, а не эффективного
идентификатора пользователя (UID) и группы (GID) вызвавшего
процесса. Эффективные идентификаторы будут использоваться при действительной
попытке выполнения той или иной операции с файлом (например,
open(2)). Аналогичным образом, для пользователя root, при проверке
используется набор разрешающих мандатов, а не набор эффективных мандатов;
для не root-пользователей при проверке используется пустой набор мандатов.
Это дает программам с set-user-ID или снабжённых мандатами простой способ
проверить права доступа вызвавшего пользователя. Другими словами,
access() не отвечает на вопрос «могу я прочитать/записать/выполнить этот
файл?». Он отвечает на немного другой вопрос: «(предположим я исполняемый
файл с setuid) может ли пользователь, запустивший меня
прочитать/записать/выполнить этот файл?», что даёт программам с set-user-ID
возможность не дать злонамеренным пользователям прочитать файлы, которые
пользователи не должны читать.
Если вызвавший процесс имеет соответствующие привилегии (например, его
реальный UID равен нулю), то проверка X_OK пройдёт успешно для обычного
файла, если у него установлено право на выполнение в любой группе бит: у
владельца, группы или остальных.
faccessat()
Системный вызов faccessat() работает также как системный вызов
access(), за исключением случаев, описанных здесь.
Если в pathname задан относительный путь, то он считается относительно
каталога, на который ссылается файловый дескриптор dirfd (а не
относительно текущего рабочего каталога вызывающего процесса, как это
делается в access()).
Если в pathname задан относительный путь и dirfd равно специальному
значению AT_FDCWD, то pathname рассматривается относительно текущего
рабочего каталога вызывающего процесса (как access()).
Если в pathname задан абсолютный путь, то dirfd игнорируется.
Значение flags составляется из побитово сложенных следующих значений:
- AT_EACCESS
-
Выполнять проверку, доступа используя эффективный идентификатор пользователя
и группы. По умолчанию в faccessat() используются реальные идентификаторы
(как в access()). - AT_SYMLINK_NOFOLLOW
-
Если значение pathname является символьной ссылкой, не разыменовывать её,
а выдать информацию о самой ссылке.
Смотрите в openat(2) объяснение необходимости faccessat().
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении (есть все запрошенные права или значение mode
равно F_OK и файл существует) возвращается ноль. При ошибке (по крайней
мере, одно право из mode было не удовлетворено, значение mode равно
F_OK и файл не существует, или случилась другая ошибка), возвращается -1,
а errno устанавливается должным образом.
ОШИБКИ
Вызов access() и faccessat() будут завершаться с ошибкой если:
- EACCES
-
Запрошенный тип доступа не удовлетворён или в одном из каталогов в
pathname не разрешён поиск. (См. также path_resolution(7).) - ELOOP
-
Во время определения pathname встретилось слишком много символьных
ссылок. - ENAMETOOLONG
- Слишком длинное значение аргумента pathname.
- ENOENT
-
Компонент пути pathname не существует или является повисшей символьной
ссылкой. - ENOTDIR
-
Компонент пути, использованный как каталог в pathname, в действительности
таковым не является. - EROFS
-
Запрошено право на запись в файл, расположенный в файловой системе,
доступной только для чтения.
Вызов access() и faccessat() могут завершиться с ошибкой, если:
- EFAULT
- Аргумент pathname указывает за пределы доступного адресного пространства.
- EINVAL
- Аргумент mode был задан неверно.
- EIO
- Произошла ошибка ввода-вывода.
- ENOMEM
- Недостаточное количество памяти ядра.
- ETXTBSY
-
Запрошены права на запись для исполняемого файла, который сейчас
выполняется.
В faccessat() дополнительно могут возникнуть следующие ошибки:
- EBADF
- dirfd не является правильным файловым дескриптором.
- EINVAL
- Указано неверное значение в flags.
- ENOTDIR
-
Значение pathname содержит относительный путь и dirfd содержит
файловый дескриптор, указывающий на файл, а не на каталог.
ВЕРСИИ
Вызов faccessat() был добавлен в ядро Linux версии 2.6.16; поддержка в
glibc доступна с версии 2.4.
СООТВЕТСТВИЕ СТАНДАРТАМ
access(): SVr4, 4.3BSD, POSIX.1-2001, POSIX.1-2008.
faccessat(): POSIX.1-2008.
ЗАМЕЧАНИЯ
Предупреждение: Использование этих вызовов для проверки, например,
разрешено ли пользователю открытие файла перед реальным выполнением
open(2), создаёт брешь в безопасности, так как пользователь может
использовать короткий промежуток времени между проверкой и открытием файла
для управления им. По этой причине лучше избегать использования данного
системного вызова (в только что описанном примере, безопасной альтернативой
будет временное переключение эффективного пользовательского идентификатора
процесса на реальный идентификатор и вызов open(2)).
Вызов access() всегда разыменовывает символьные ссылки. Если вам нужно
проверить права символьной ссылки, используйте вызов faccessat(2) с
флагом AT_SYMLINK_NOFOLLOW.
Эти вызовы возвращают ошибку, если отказано в любом из типов доступа
mode, даже если разрешены остальные типы.
Если вызывающий процесс имеет соответствующие привилегии (например,
суперпользователя), то POSIX.1-2001 разрешает реализации сообщить об
успешном выполнении при проверке X_OK даже, если ни один из битов
выполнения файла не установлен. В Linux так не происходит.
Файл доступен только в случае, если для каждого каталога в пути, указанном в
pathname, имеется право выполнять поиск (то есть, установлен бит
выполнения). Если какой-то каталог недоступен, то вызов access() вернёт
ошибку, независимо от имеющихся прав файла.
Проверяются только биты доступа, но не тип файла или его
содержимое. Поэтому, если обнаруживается, что в каталог можно писать, то
это, вероятно, означает, что в этом каталоге можно создавать файлы, и что в
этот каталог нельзя писать как в файл. Также, файл DOS может быть посчитан
как «исполняемый», но вызов execve(2) всё равно не сможет его запустить.
Эти вызовы access() могут некорректно работать на файловых системах NFSv2
со включённым преобразованием UID-ов, потому что это преобразование
происходит на сервере и спрятано от клиента, который пытается проверить
права (в NFS версии 3 и выше выполняется проверка на сервере). Похожие
проблемы могут возникать при монтировании FUSE.
Отличия между библиотекой C и ядром
Нижележащий системный вызов faccessat() имеет только первые три
аргумента. Флаги AT_EACCESS и AT_SYMLINK_NOFOLLOW на самом деле
реализованы внутри обёрточной функции glibc faccessat(). Если задан
какой-то из этих флагов, то обёрточная функция использует fstatat(2) для
определения прав доступа.
Замечания по glibc
В старых ядрах, где faccessat() отсутствует (и если не указаны флаги
AT_EACCESS и AT_SYMLINK_NOFOLLOW), обёрточная функция glibc использует
access(). Если pathname является относительным путём, то glibc
собирает путь относительно символической ссылки в /proc/self/fd, которая
соответствует аргументу dirfd.
ДЕФЕКТЫ
В ядрах версии 2.4 (и более ранних) есть некоторая странность в работе теста
X_OK для суперпользователя. Если для всех категорий право исполнения
отключено для файла-не каталога, то тест access() возвращает -1 только
когда mode задан как X_OK; если в mode также указан флаг R_OK
или W_OK, то access() вернёт для таких файлов 0. Ранние версии ядер
2.6 (до 2.6.3 включительно) ведут себя также как ядра 2.4.
В ядрах до версии 2.6.20 эти вызовы игнорировали влияние флага MS_NOEXEC,
если он был установлен с помощью mount(2) для содержащей файл файловой
системы. Начиная с версия ядра 2.6.20, этот флаг учитывается.