| 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():
fstatat():
Данные системные вызовы возвращают информацию о файле в буфер, на который указывает statbuf. Для этого не требуется иметь права доступа к самому файлу, но — в случае stat(), fstatat() и lstat() — потребуются права выполнения (поиска) на все каталоги, указанные в полном имени файла pathname.
Вызовы stat() и fstatat() возвращают информацию о файле, указанном в pathname; различия с fstatat() описаны далее.
Вызов lstat() идентичен stat(), но в случае, если pathname является символьной ссылкой, то возвращается информация о самой ссылке, а не о файле, на который она указывает.
Вызов fstat() идентичен stat(), но опрашиваемый файл задаётся в виде файлового дескриптора fd.
Все эти системные вызовы возвращают структуру 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:
Дополнительную информацию об этих полях смотрите в inode(7).
Системный вызов fstatat() представляет собой обобщённый интерфейс доступа к файловой информации, и может выполнить работу за stat(), lstat() и fstat().
Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в stat() и lstat()).
Если в pathname задан относительный путь и значение dirfd равно AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как stat() и lstat()).
Если в pathname задан абсолютный путь, то dirfd игнорируется.
Значение flags может быть 0, или включать один или более следующих флагов:
Смотрите в openat(2) объяснение необходимости fstatat().
При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
В fstatat() дополнительно могут возникнуть следующие ошибки:
Вызов 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.
В течении долгого времени увеличение размера структуры 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 в разных версиях:
Обёрточная функция 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), statx(2), utime(2), capabilities(7), inode(7), symlink(7)
| 2019-03-06 | Linux |