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 |