STAT(2) | Podręcznik programisty Linuksa | STAT(2) |
stat, fstat, lstat, fstatat - pobieranie stanu pliku
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> int stat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *pathname, struct stat *buf); #include <fcntl.h> /* Definicja stałych AT_* */ #include <sys/stat.h> int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags);
Wymagane ustawienia makr biblioteki glibc (patrz
feature_test_macros(7)):
lstat():
fstatat():
Funkcje te zwracają informacje o podanym pliku w buforze wskazanym przez buf. Do uzyskania tej informacji nie są wymagane prawa dostępu do samego pliku, lecz — w przypadku stat, fstatat() i lstat() — konieczne są prawa wykonywania (przeszukiwania) do wszystkich katalogów na prowadzącej do pliku ścieżce pathname.
stat() i fstatat() pobierają informacje o pliku wskazanym przez pathname; cechy wyróżniające fstatat() opisano poniżej.
lstat() jest identyczny z stat(), lecz w przypadku gdy pathname jest dowiązaniem symbolicznym, to zwraca informacje o samym dowiązaniu, a nie pliku, do którego się to dowiązanie odwołuje.
fstat() jest identyczny z stat(), z tym wyjątkiem, że plik o którym mają być pobrane informacje, jest określony przez deskryptor pliku fd.
Wszystkie te funkcje zwracają strukturę stat, zawierającą następujące pola:
struct stat {
dev_t st_dev; /* ID urządzenia zawierającego plik */
ino_t st_ino; /* numer i-węzła (inode) */
mode_t st_mode; /* tryb i typ pliku */
nlink_t st_nlink; /* liczba dowiązań stałych (hardlinks) */
uid_t st_uid; /* ID użytkownika właściciela */
gid_t st_gid; /* ID grupy właściciela */
dev_t st_rdev; /* ID urządzenia (jeśli plik specjalny) */
off_t st_size; /* całkowity rozmiar w bajtach */
blksize_t st_blksize; /* wielkość bloku dla I/O systemu plików */
blkcnt_t st_blocks; /* liczba zaalokowanych bloków 512-bajtowych */
/* Od Linuksa 2.6 jądro obsługuje nanosekundową
rozdzielczość następujących pól znaczników czasu.
Szczegóły opisujące Linuksa w wersji starszej niż 2.6
znajdują się w rozdziale UWAGI */
struct timespec st_atim; /* czas ostatniego dostępu */
struct timespec st_mtim; /* czas ostatniej modyfikacji */
struct timespec st_ctim; /* czas ostatniej zmiany */ }; #define st_atime st_atim.tv_sec /* Kompatybilność wsteczna */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
Uwaga: kolejność pól w strukturze stat różni się nieco w zależności od architektury. Dodatkowo, powyższa definicja nie pokazuje bajtów wyrównujących, które mogą być obecne pomiędzy niektórymi polami na różnych architekturach. Z tymi detalami można się zapoznać analizując glibc i kod źródłowy jądra.
Uwaga: Dla zachowania wydajności i prostoty, różne pola w strukturze stat mogą zawierać stany z różnych momentów wykonywania wywołania systemowego. Przykładowo, jeśli st_mode lub st_uid zostanie zmieniony przez inny proces za pomocą wywołania chmod(2) lub chown(2), stat() może zwrócić stary st_mode razem z nowym st_uid albo stary st_uid razem z nowym st_mode.
Pole st_dev opisuje urządzenie, w którym plik się znajduje. (Makra major(3) i minor(3) mogą się przydać przy dekodowaniu identyfikatora urządzenia znajdującego się w tym polu).
Pole st_rdev opisuje urządzenie reprezentowane przez ten plik (i-węzeł).
Pole st_size podaje rozmiar pliku w bajtach (jeżeli plik jest plikiem regularnym lub dowiązaniem symbolicznym). Rozmiarem dowiązania symbolicznego jest długość ścieżki, na którą wskazuje, z wyłączeniem końcowego bajtu NULL.
Pole st_sblocks określa liczbę bloków zajmowanych przez plik w jednostkach 512-bajtowych. (Liczba ta może być mniejsza niż st_size/512, na przykład wtedy, gdy plik ma dziury).
Pole st_blksize zawiera "preferowany" rozmiar bloku dla efektywnych operacji wejścia/wyjścia dla pliku. (Zapis do pliku mniejszych kawałków może spowodować nieefektywne operacje odczyt-modyfikacja-powtórny zapis).
Nie wszystkie systemy plików pod Linuksem obsługują wszystkie pola czasu. Niektóre systemy plików można zamontować w ten sposób, że dostęp do pliku lub katalogu nie powoduje uaktualnienia pola st_atime. (Patrz noatime, nodiratime i relatime w mount(8) oraz powiązane informacje w mount(2)). Dodatkowo st_atime nie jest aktualizowane, jeśli plik jest otwierany z flagą O_NOATIME, patrz open(2).
Pole st_atime jest zmieniane przez każdy dostęp do pliku, np. przez execve(2), mknod(2), pipe(2), utime(2) i read(2) (w razie odczytania więcej niż zera bajtów). Inne procedury, jak mmap(2) mogą, ale nie muszą, zaktualizować st_atime.
Zazwyczaj pole st_mtime jest zmieniane przez modyfikowanie pliku, np. przez mknod(2), truncate(2), utime(2) i write(2) (więcej niż zera bajtów). Co więcej st_mtime katalogu jest zmieniane przy tworzeniu plików w tym katalogu lub ich usuwaniu. Pole st_mtime nie jest zmieniane po zmianach właściciela, grupy, liczby dowiązań (hard links) czy uprawnień.
Pole st_ctime jest zmieniane przy zapisywaniu lub ustawianiu informacji i-węzła (np. właściciela, grupy, liczby dowiązań, praw itp.).
POSIX odnosi się do bitów st_mode odpowiadających masce S_IFMT (zob. poniżej) jako typu pliku, 12 bitów odpowiadających masce 07777 jako bitów trybu pliku i najmniej znaczących 9 bitów (0777) jako bitów uprawnień pliku.
Zdefiniowane są następujące wartości
masek do typu pliku z pola st_mode:
S_IFMT | 0170000 | maska bitowa dla pola bitowego typu pliku |
S_IFSOCK | 0140000 | gniazdo |
S_IFLNK | 0120000 | dowiązanie symboliczne (symbolic link) |
S_IFREG | 0100000 | plik regularny |
S_IFBLK | 0060000 | urządzenie blokowe |
S_IFDIR | 0040000 | katalog |
S_IFCHR | 0020000 | urządzenie znakowe |
S_IFIFO | 0010000 | kolejka FIFO |
Dlatego, aby sprawdzić czy plik jest (przykładowo) zwykłym plikiem można napisać:
stat(pathname, &sb); if ((sb.st_mode & S_IFMT) == S_IFREG) {
/* Obsługa zwykłego pliku */ }
Ponieważ testy w powyższej postaci są popularne, dodatkowe makra są zdefiniowane przez POSIX w celu umożliwienia sprawdzenia typu pliku w st_mode w spójniejszej formie:
Poprzedni przykład kodu można dlatego przepisać w następujący sposób:
stat(pathname, &sb); if (S_ISREG(sb.st_mode)) {
/* Obsługa zwykłego pliku */ }
Definicje większości powyższych makr sprawdzających typ pliku są udostępniane, jeśli tylko któraś z następujących funkcji makd sprawdzających jest zdefiniowana: _BSD_SOURCE (w 2.19 i wcześniejszych), _SVID_SOURCE (w glibc 2.19 i wcześniejszych) lub _DEFAULT_SOURCE (w glibc 2.20 i późniejszych). Dodatkowo, definicje wszystkich powyższych makr z wyjątkiem S_IFSOCK i S_ISSOCK() są udostępniane jeśli zdefiniowano _XOPEN_SOURCE. Zdefiniowanie S_IFSOCK można również uwidocznić definiując _XOPEN_SOURCE z wartością większą lub równą 500.
Zdefiniowanie S_ISSOCK() jest uwidocznione, jeśli zdefiniowano dowolne z następujących makr sprawdzających: _BSD_SOURCE (w 2.19 i wcześniejszych), _DEFAULT_SOURCE (w glibc 2.20 i późniejszych), _XOPEN_SOURCE z wartością większą lub równą 500 lub _POSIX_C_SOURCE z wartością większą lub równą 200112L.
Zdefiniowane są następujące wartości
masek do części określającej tryb pliku w polu
st_mode:
S_ISUID | 04000 | bit "set-used-ID" |
S_ISGID | 02000 | bit "set-group-ID" (patrz niżej) |
S_ISVTX | 01000 | bit "sticky" (patrz niżej) |
S_IRWXU | 00700 | właściciel ma prawa odczytu, zapisu i wykonania |
S_IRUSR | 00400 | właściciel ma prawa odczytu |
S_IWUSR | 00200 | właściciel ma prawa zapisu |
S_IXUSR | 00100 | właściciel ma prawa wykonania |
S_IRWXG | 00070 | grupa ma prawa odczytu, zapisu i wykonania |
S_IRGRP | 00040 | grupa ma prawa odczytu |
S_IWGRP | 00020 | grupa ma prawa zapisu |
S_IXGRP | 00010 | grupa ma prawa wykonania |
S_IRWXO | 00007 | inni (nie z grupy) mają prawo odczytu, zapisu i wykonania |
S_IROTH | 00004 | inni mają prawa odczytu |
S_IWOTH | 00002 | inni mają prawa zapisu |
S_IXOTH | 00001 | inni mają prawa wykonania |
Bit "set-group-ID" (S_ISGID) ma kilka specjalnych znaczeń. Ustawiony na katalogu oznacza, że dla tego katalogu powinna być używana semantyka BSD: pliki w nim utworzone dziedziczą identyfikator grupy z katalogu, a nie z efektywnego identyfikatora grupy procesu tworzącego plik, ponadto tworzone katalogi będą miały także ustawiony bit S_ISGID. Dla pliku, który nie ma ustawionego bitu wykonywania dla grupy (S_IXGRP), bit "set-group-ID" oznacza obowiązkowe blokowanie pliku/rekordu.
Bit "sticky" (S_ISVTX) ustawiony na katalogu oznacza, że tylko właściciel pliku lub właściciel katalogu albo proces uprzywilejowany może usunąć plik w tym katalogu lub zmienić nazwę tego pliku.
Wywołanie systemowe fstatat() działa w ten sam sposób co stat(), z wyjątkiem opisanych tu różnic.
Jeśli ścieżka podana w pathname jest względna, jest to interpretowane w odniesieniu do katalogu do którego odnosi się deskryptor pliku dirfd (zamiast w odniesieniu do bieżącego katalogu roboczego procesu wywołującego, jak w stosunku do ścieżek względnych robi to stat()).
Jeśli pathname jest względna a dirfd ma wartość specjalną AT_FDCWD, to pathname jest interpretowana w odniesieniu do bieżącego katalogu roboczego procesu wywołującego (jak stat()).
If ścieżka pathname jest bezwzględna, to dirfd jest ignorowane.
flags mogą wynosić albo 0, albo składać się z co najmniej jednej z poniższych opcji połączonych operatorem OR:
Więcej informacji o potrzebie wprowadzenia fstatat() można znaleźć w podręczniku openat(2).
W przypadku powodzenia zwracane jest zero. W razie wystąpienia błędu zwracane jest -1 i ustawiana jest odpowiednia wartość zmiennej errno.
Mogą wystąpić następujące dodatkowe błędy dla fstatat():
fstatat() zostało dodane do Linuksa w jądrze 2.6.16; obsługę biblioteki dodano do glibc w wersji 2.4.
stat(), fstat(), lstat(): SVr4, 4.3BSD, POSIX.1-2001, POSIX.1.2008.
fstatat(): POSIX.1-2008.
Według POSIX.1-2001 lstat() na dowiązaniu symbolicznym powinien zwrócić poprawne wartości tylko w polu st_size i w części pola st_mode związanej z typem pliku struktury stat. POSIX.1-2008 zaostrza tę specyfikację, wymagając od lstat() zwracania poprawnych informacji we wszystkich polach z wyjątkiem bitów trybu w st_mode.
Używanie pól st_blocks i st_blksize może być nieprzenośne. (Były wprowadzone w BSD; interpretacje różnią się zarówno między systemami, jak i na jednym systemie, jeśli użyty jest zdalny system plików montowany po NFS-ie). Aby uzyskać definicje typów blkcnt_t i blksize_t z <sys/stat.h> należy zdefiniować _XOPEN_SOURCE na wartość 500 lub wyższą (przed dołączeniem jakiegokolwiek innego pliku nagłówkowego).
POSIX.1-1990 nie opisywał stałych S_IFMT, S_IFSOCK, S_IFLNK, S_IFREG, S_IFBLK, S_IFDIR, S_IFCHR, S_IFIFO, S_ISVTX , ale zamiast tego wymagał używania makr S_ISDIR() itp. Stałe S_IF* są obecne w POSIX.1-2001 i późniejszych.
Makra S_ISLNK() i S_ISSOCK() nie są wymienione w POSIX.1-1996, ale są obecne w POSIX.1-2001; pierwsze z nich pochodzi z SVID 4, a drugie z SUSv2.
Unix V7 (i kolejne systemy) miał S_IREAD, S_IWRITE, S_IEXEC, podczas gdy POSIX nakazuje używanie synonimów S_IRUSR, S_IWUSR, S_IXUSR.
Wartości, które były (lub nadal są) w użyciu w różnych systemach:
szesn. | nazwa | ls | ósemk. | opis |
f000 | S_IFMT | 170000 | maska bitowa dla pól bitowych typu pliku | |
0000 | 000000 | niedziałający i-węzeł w SCO; nieznany typ w BSD; SVID-v2 i XPG2 mają zarówno 0, jak i 0100000 dla zwykłego pliku | ||
1000 | S_IFIFO | p| | 010000 | kolejka FIFO (potok nazwany) |
2000 | S_IFCHR | c | 020000 | specjalny znakowy (V7) |
3000 | S_IFMPC | 030000 | specjalny znakowy zwielokrotniony (V7) | |
4000 | S_IFDIR | d/ | 040000 | katalog (V7) |
5000 | S_IFNAM | 050000 | nazwany plik specjalny XENIX-a z dwoma podtypami, rozróżnianymi przez wartości 1, 2 w st_rdev | |
0001 | S_INSEM | s | 000001 | podtyp IFNAM semafora XENIX |
0002 | S_INSHD | m | 000002 | podtyp IFNAM dzielonych danych XENIX |
6000 | S_IFBLK | b | 060000 | specjalny blokowy (V7) |
7000 | S_IFMPB | 070000 | specjalny blokowy zwielokrotniony (V7) | |
8000 | S_IFREG | - | 100000 | regularny (V7) |
9000 | S_IFCMP | 110000 | skompresowany VxFS | |
9000 | S_IFNWK | n | 110000 | sieciowy specjalny (HP-UX) |
a000 | S_IFLNK | l@ | 120000 | dowiązanie symboliczne (BSD) |
b000 | S_IFSHAD | 130000 | shadow i-węzeł ACL w Solarisie (niewidzialny w przestrzeni użytkownika) | |
c000 | S_IFSOCK | s= | 140000 | gniazdo (BSD; także "S_IFSOC" na VxFS) |
d000 | S_IFDOOR | D> | 150000 | drzwi Solarisa |
e000 | S_IFWHT | w% | 160000 | BSD whiteout (nieużywane dla i-węzła) |
0200 | S_ISVTX | 001000 | bit lepkości: zachowuje tekst na urządzeniu wymiany nawet po użyciu (V7) zarezerwowane (SVID-v2) Dla niekatalogów: nie buforuj tego (SunOS) Dla katalogów: ograniczone prawo usunięcia (SVID-v4.2) | |
0400 | S_ISGID | 002000 | set-group-ID podczas wykonywania (V7) dla katalogów: używa semantyki BSD do propagacji GID | |
0400 | S_ENFMT | 002000 | egzekwowanie blokowania plików Systemu V (dzielone z S_ISGID) | |
0800 | S_ISUID | 004000 | set-user-ID podczas wykonywania (V7) | |
0800 | S_CDF | 004000 | katalog jest plikiem zależnym od kontekstu (HP-UX) |
Polecenie "sticky" pojawiło się w wersji 32V systemu AT&T UNIX.
Pod Linuksem, lstat() nie spowoduje uruchomienia akcji automontera, natomiast stat() - spowoduje (patrz jednakże fstatat(2)).
Dla większości plików w katalogu /proc, stat() w polu st_size zwraca 0, a nie rzeczywisty rozmiar pliku.
Starsze jądra i starsze standardy nie obsługują nanosekundowych pól znaczników czasu. Zamiast tego były trzy pola znaczników czasu — st_atime, st_mtime i st_ctime— zapisywane jako time_t przechowujące znaczniki czasu z sekundową precyzją.
Od wersji jądra 2.5.48 struktura stat obsługuje nanosekundową dokładność wszystkich trzech pól czasowych. Nanosekundowa część każdego z tych pól jest dostępna za pomocą nazw w postaci st_atim.tv_nsec, jeżeli zdefiniowano makro _BSD_SOURCE lub _SVID_SOURCE. Nanosekundowe pola czasowe są obecnie ustandaryzowane, począwszy od POSIX.1-2008 i w związku z tym, począwszy od wersji 2.12 biblioteka glibc udostępnia również część nanosekundową, jeśli _POSIX_C_SOURCE jest zdefiniowane na wartość 200809L lub większą, albo _XOPEN_SOURCE jest zdefiniowane na wartość 700 lub większą. Jeśli nie zdefiniowano żadnego z powyższych makr, to nanosekundowe wartości są dostępne w polu st_atimensec.
Nanosekundowe pola czasowe są obsługiwane przez XFS, JFS, Btrfs i ext4 (od Linuksa 2.6.23). natomiast nie są obsługiwane w ext2, ext3 i Reiserfs. W systemach plików, które nie obsługują takiej dokładności czasowej, wartości nanosekund w tych polach wynoszą 0.
Z upływem czasu, zwiększanie rozmiarów struktury stat doprowadziło do powstania trzech kolejnych wersji funkcji stat(): sys_stat() (slot __NR_oldstat), sys_newstat() (slot __NR_stat) i sys_stat64() (slot __NR_stat64) na platformach 32-bitowych takich jak i386. Pierwsze dwie wersje były już obecne w Linuksie 1.0 (choć z różnymi nazwami), ostatnią dodano w Linuksie 2.4. Podobne uwagi mają zastosowanie do fstat() i lstat().
Wewnątrzjądrowe wersje struktury stat, za pomocą których jądro obsługuje te różne wersje, to odpowiednio:
Funkcja opakowująca glibc stat() ukrywa te detale przed użytkownikami, wywołując najnowszą wersję wywołania systemowego udostępnianą przez jądra i przepakowując zwracane informacje, jeśli jest to wymagane, dla starszych plików wykonywalnych.
Na współczesnych systemach 64-bitowych wszystko jest prostsze: istnieje jedno wywołanie systemowe stat(), a jądro wykorzystuje strukturę stat zawierającą pola o wystarczającym rozmiarze.
Wywołanie systemowe niższego stopnia używane przez funkcję opakowującą fstatat() glibc nazywa się w rzeczywistości fstatat64() lub, na niektórych architekturach, newfstatat().
Poniższy program wywołuje stat() i wypisuje wybrane pola zwrócone w strukturze stat:
#include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) {
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Użycie: %s <ścieżka>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
printf("Typ pliku: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("urządzenie blokowe\n"); break;
case S_IFCHR: printf("urządzenie znakowe\n"); break;
case S_IFDIR: printf("katalog\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("dowiązanie symboliczne\n"); break;
case S_IFREG: printf("zwykły plik\n"); break;
case S_IFSOCK: printf("gniazdo\n"); break;
default: printf("typ nieznany\n"); break;
}
printf("numer I-węzła: %ld\n", (long) sb.st_ino);
printf("Tryb: %lo (octal)\n",
(unsigned long) sb.st_mode);
printf("Liczba dowiązań: %ld\n", (long) sb.st_nlink);
printf("Właściciel: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
printf("Preferowany rozmiar bloku I/O: %ld bajtów\n",
(long) sb.st_blksize);
printf("Rozmiar bloku: %lld bajtów\n",
(long long) sb.st_size);
printf("Liczba zaalokowanych bloków: %lld\n",
(long long) sb.st_blocks);
printf("Ostatnia zmiana stanu: %s", ctime(&sb.st_ctime));
printf("Ostatni dostęp do pliku: %s", ctime(&sb.st_atime));
printf("Ostatnia zmiana pliku: %s", ctime(&sb.st_mtime));
exit(EXIT_SUCCESS); }
ls(1), stat(1), access(2), chmod(2), chown(2), readlink(2), utime(2), capabilities(7), symlink(7)
Angielska wersja tej strony pochodzi z wydania 4.07 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.
Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Przemek Borys (PTM) <pborys@dione.ids.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.
Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 4.07 oryginału.
2016-03-15 | Linux |