Scroll to navigation

STAT(2) Руководство программиста Linux STAT(2)

ИМЯ

stat, fstat, lstat, fstatat - считывает состояние файла

СИНТАКСИС

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
#include <fcntl.h>           /* определения констант AT_* */
#include <sys/stat.h>
int fstatat(int dirfd, const char *pathname, struct stat *statbuf,
            int flags);


Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

lstat():

/* glibc 2.19 и старее */ _BSD_SOURCE
|| /* начиная с glibc 2.20 */ _DEFAULT_SOURCE
|| _XOPEN_SOURCE >= 500
|| /* начиная с glibc 2.10: */ _POSIX_C_SOURCE >= 200112L

fstatat():

Начиная с glibc 2.10:
_POSIX_C_SOURCE >= 200809L
До glibc 2.10:
_ATFILE_SOURCE

ОПИСАНИЕ

Данные системные вызовы возвращают информацию о файле в буфер, на который указывает statbuf. Для этого не требуется иметь права доступа к самому файлу, но — в случае stat(), fstatat() и lstat() — потребуются права выполнения (поиска) на все каталоги, указанные в полном имени файла pathname.

Вызовы stat() и fstatat() возвращают информацию о файле, указанном в pathname; различия с fstatat() описаны далее.

Вызов lstat() идентичен stat(), но в случае, если pathname является символьной ссылкой, то возвращается информация о самой ссылке, а не о файле, на который она указывает.

Вызов fstat() идентичен stat(), но опрашиваемый файл задаётся в виде файлового дескриптора fd.

Структура stat

Все эти системные вызовы возвращают структуру stat, которая содержит следующие поля:


struct stat {

dev_t st_dev; /* ID устройства с файлом */
ino_t st_ino; /* номер иноды */
mode_t st_mode; /* тип файла и режим доступа */
nlink_t st_nlink; /* количество жёстких ссылок */
uid_t st_uid; /* идентификатор пользователя-владельца */
gid_t st_gid; /* идентификатор группы-владельца */
dev_t st_rdev; /* идентификатор устройства
(для специального файла) */
off_t st_size; /* общий размер в байтах */
blksize_t st_blksize; /* размер блока ввода-вывода файловой системы */
blkcnt_t st_blocks; /* количество выделенных 512Б блоков */
/* Начиная с Linux 2.6, ядро поддерживает точность до
наносекунд в следующих полям меток времени.
Подробней о версиях до Linux 2.6, смотрите ЗАМЕЧАНИЯ. */
struct timespec st_atim; /* время последнего доступа */
struct timespec st_mtim; /* время последнего изменения */
struct timespec st_ctim; /* время последней смены состояния */ #define st_atime st_atim.tv_sec /* для обратной совместимости */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };

Замечание: порядок полей структуры stat для разных архитектур отличается. Также, в определении выше не показаны дополняющие байты, которые для различных архитектур могут присутствовать между некоторыми полями Если необходимы подробности, то посмотрите исходный код glibc и ядра.

Замечание: Для простоты и производительности различные поля структуры stat могут содержать информацию о состоянии из разных моментов работы системного вызова. Например, если st_mode или st_uid изменились другим процессом с помощью вызова chmod(2) или chown(2), то stat() может вернуть старое значение st_mode вместе с новым st_uid, или старое значение st_uid вместе с новым st_mode.

Поля структуры stat:

Устройство, на котором расположен файл (для разбора идентификатора этого поля могут пригодиться макросы major(3) и minor(3)).
Номер иноды файла.
Тип файла и режим доступа. Дополнительную информацию смотрите в inode(7).
Количество жёстких ссылок на файл.
Пользовательский идентификатор владельца файла.
Групповой идентификатор владельца файла.
Устройство, который этот файл (инода) представляет.
Размер файла (если он обычный или является символьной ссылкой) в байтах. Размер символьной ссылки равен длине пути файла, на который она ссылается, без конечного нулевого байта.
«Предпочтительный» размер блока для эффективного ввода/вывода в файловой системе.
Количество блоков (по 512 байт), выделенных для файла (может быть меньше, чем st_size/512, когда в файле есть пропуски (holes)).
Метка времени последнего доступа к файлу.
Метка времени последнего изменения файла.
Метка времени последнего изменения состояния файла.

Дополнительную информацию об этих полях смотрите в inode(7).

fstatat()

Системный вызов fstatat() представляет собой обобщённый интерфейс доступа к файловой информации, и может выполнить работу за stat(), lstat() и fstat().

Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в stat() и lstat()).

Если в pathname задан относительный путь и значение dirfd равно AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как stat() и lstat()).

Если в pathname задан абсолютный путь, то dirfd игнорируется.

Значение flags может быть 0, или включать один или более следующих флагов:

Если значение pathname равно пустой строке, то выполнять действие над файлом, на который указывает dirfd (который может быть получен с помощью open(2) с флагом O_PATH). В этом случае dirfd может указывать на файл любого типа, а не только на каталог и поведение fstatat() подобно fstat(). Если dirfd равно AT_FDCWD, то вызов выполняет действие над текущим рабочим каталогом. Этот флаг есть только в Linux; для получения его определения определите _GNU_SOURCE.
Не выполнять автоматическое монтирование конечного компонента («basename») pathname, если этот каталог является точкой автоматического монтирования. Это позволяет вызывающему получить атрибуты точки автоматического монтирования (а не расположения, где её предполагалось смонтировать). Начиная с Linux 4.14, также не создаётся несуществующее имя в каталоге по требованию, например в неявных картах автоматического монтировщика. Этот флаг можно использовать в инструментах, сканирующих каталоги, для предотвращения массового автоматического монтирования каталогов в их точки автоматического монтирования. Флаг AT_NO_AUTOMOUNT не учитывается, если к точке уже была выполнено монтирование. Этот флаг есть только Linux; для его получения нужно задать _GNU_SOURCE. Вызовы stat() и lstat() работают, как если бы был установлен флаг AT_NO_AUTOMOUNT.
Если значение pathname является символьной ссылкой, не разыменовывать её, а вернуть информацию о самой ссылке, как это делается в lstat(). (По умолчанию, fstatat() разыменовывает символьные ссылки как и stat().)

Смотрите в openat(2) объяснение необходимости fstatat().

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

ОШИБКИ

Запрещён поиск в одном из каталогов пути pathname (смотрите также path_resolution(7)).
Значение fd не является правильным открытым файловым дескриптором.
Неправильный адрес.
Во время определения пути встретилось слишком много символьных ссылок.
Слишком длинное значение аргумента pathname.
Компонент пути pathname не существует или в pathname указана пустая строка и в flags не указан AT_EMPTY_PATH.
Не хватает памяти (например, памяти ядра).
Компонент в префиксе пути pathname не является каталогом.
Значение pathname или fd ссылаются на файл, чей размер, номер inode или количество блоков не может быть представлено с помощью типов off_t, ino_t или blkcnt_t, соответственно. Эта ошибка может возникнуть, если, например, приложение собрано на 32-битной платформе без флага -D_FILE_OFFSET_BITS=64 при вызове stat() для файла, чей размер превышает (1<<31)-1 байт.

В fstatat() дополнительно могут возникнуть следующие ошибки:

dirfd не является правильным файловым дескриптором.
Указано неверное значение в flags.
Значение pathname содержит относительный путь и dirfd содержит файловый дескриптор, указывающий на файл, а не на каталог.

ВЕРСИИ

Вызов fstatat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.

СООТВЕТСТВИЕ СТАНДАРТАМ

stat(), fstat(), lstat(): SVr4, 4.3BSD, POSIX.1-2001, POSIX.1.2008.

fstatat(): POSIX.1-2008.

Согласно POSIX.1-2001, lstat() для символьной ссылки требует вернуть корректную информацию только в поле st_size и в типе файла в поле st_mode структуры stat. В POSIX.1-2008 более жёсткая спецификация, требующая, чтобы lstat() возвращал корректную информацию во всех полях кроме битов режима в st_mode.

Использование полей st_blocks и st_blksize может усложнить перенос на другие платформы. (Эти поля появились из BSD. Их смысл различается в разных системах и, вероятно, даже в одной системе при использовании NFS).

ЗАМЕЧАНИЯ

Поля с отметками времени

В старых ядрах и стандартах нет поддержки полей времени в наносекундах. Вместо них есть три поря времени — st_atime, st_mtime и st_ctime — с типом time_t, который имеет секундную точность.

Начиная с ядра 2.5.48, в структуре stat поддерживается наносекундная точность для всех трёх полей времени. Наносекундные компоненты каждой метки времени доступны под именами вида st_atim.tv_nsec, если определён подходящий макрос тестирования свойств. Наносекундные метки времени стандартизованы в POSIX.1-2008, и, начиная с версии 2.12, в glibc также есть поддержка имён наносекундных компонент, если определён _POSIX_C_SOURCE со значением 200809L или более, или _XOPEN_SOURCE со значением 700 или более. До glibc 2.19 включительно определения наносекундных компонент также доступны, если определён _BSD_SOURCE или _SVID_SOURCE. Если ни один из вышеупомянутых макросов не определён, то наносекундные значения доступны под именами вида st_atimensec.

Отличия между библиотекой C и ядром

В течении долгого времени увеличение размера структуры stat привело к появлению трёх новых версий stat(): sys_stat() (слот __NR_oldstat), sys_newstat() (слот __NR_stat) и sys_stat64() (слот __NR_stat64) на 32-битных платформах, например, i386. Первые две версии уже существовали в Linux 1.0 (но под другими именами); последняя была добавлена в Linux 2.4. Подобное замечание применимо к fstat() и lstat().

Внутренние ядерные структуры stat в разных версиях:

__old_kernel_stat
Самая первая версия структуры со слегка узкими полями и без заполнителей.
Увеличенное поле st_ino и добавлены заполнители в различные части структуры для расширения в дальнейшем.
Ещё раз увеличенное поле st_ino, увеличены поля st_uid и st_gid для работы с увеличенными в Linux-2.4 UID и GID до 32 бит, увеличены другие поля, дальнейшее добавление заполнителей в структуру (различные байты заполнения в дальнейшем были задействованы в Linux 2.6 с появлением 32-битных ID устройств и наносекундной части в полях временных отметок).

Обёрточная функция glibc stat() прячет эти подробности от приложений, вызывая самую новую версию системного вызова, предоставляемого ядром, и перепаковывая возвращаемую информацию, если это нужно для старых программ.

В современных 64-битных системах жизнь упростилась: единственный системный вызов stat() и ядро работает со структурой stat, в которой поля достаточного размера.

Нижележащий системный вызов, используемый обёрточной функцией fstatat() в glibc, на самом деле называется fstatat64() или, на некоторых архитектурах, newfstatat().

ПРИМЕР

Следующая программа вызывает lstat() и показывает некоторые поля из полученной структуры stat.

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysmacros.h>
int
main(int argc, char *argv[])
{

struct stat sb;
if (argc != 2) {
fprintf(stderr, "Использование: %s <путь>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (lstat(argv[1], &sb) == -1) {
perror("lstat");
exit(EXIT_FAILURE);
}
printf("ID содержащего устройства: [%lx,%lx]\n", (long) major(sb.st_dev), (long) minor(sb.st_dev));
printf("Тип файла: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("блочное устройство\n"); break;
case S_IFCHR: printf("символьное устройство\n"); break;
case S_IFDIR: printf("каталог\n"); break;
case S_IFIFO: printf("FIFO/канал\n"); break;
case S_IFLNK: printf("символьная ссылка\n"); break;
case S_IFREG: printf("обычный файл\n"); break;
case S_IFSOCK: printf("сокет\n"); break;
default: printf("неизвестно?\n"); break;
}
printf("номер inode: %ld\n", (long) sb.st_ino);
printf("Режим доступа: %lo (octal)\n",
(unsigned long) sb.st_mode);
printf("Кол-во ссылок: %ld\n", (long) sb.st_nlink);
printf("Владелец: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
printf("Предпоч. размер бл. в/в: %ld байт\n",
(long) sb.st_blksize);
printf("Размер файла: %lld байт\n",
(long long) sb.st_size);
printf("Выделено блоков: %lld\n",
(long long) sb.st_blocks);
printf("Посл. изм. состояния: %s", ctime(&sb.st_ctime));
printf("Посл. доступ к файлу: %s", ctime(&sb.st_atime));
printf("Посл. изм. файла: %s", ctime(&sb.st_mtime));
exit(EXIT_SUCCESS); }

СМ. ТАКЖЕ

ls(1), stat(1), access(2), chmod(2), chown(2), readlink(2), utime(2), capabilities(7), inode(7), symlink(7)

ЗАМЕЧАНИЯ

Эта страница является частью проекта Linux man-pages версии 4.16. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.

15 сентября 2017 г. Linux