STAT(2)

NAZWA
stat, fstat, lstat - pobieranie stanu pliku

SKŁADNIA
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

lstat():
    _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
    || /* od glibc 2.10: */ _POSIX_C_SOURCE >= 200112L

OPIS

Funkcje te zwracają informacje o podanym pliku. Do uzyskania tej informacji nie są wymagane prawa dostępu do samego pliku, lecz — w przypadku stat() i lstat() — konieczne są prawa wykonywania (przeszukiwania) do wszystkich katalogów na prowadzącej do pliku ścieżce path.

stat() zwraca status pliku wskazywanego przez path, ładując go do argumentu buf.

lstat() jest identyczny z stat(), lecz w przypadku gdy path jest dowiązaniem symbolicznym, to zwraca status tego dowiązania, a nie pliku, do którego się to dowiązanie odwołuje.

fstat() jest identyczny z stat(), z tym wyjątkiem, że plik, którego status ma zwrócić, 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) */
    umode_t   st_mode;     /* ochrona */
    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 */
    time_t    st_atime;    /* czas ostatniego dostępu */
    time_t    st_mtime;    /* czas ostatniej modyfikacji */
    time_t    st_ctime;    /* czas ostatniej zmiany */
};

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.).

Zdefiniowane są następujące makra POSIX sprawdzające typ pliku przy użyciu pola st_mode:

    S_ISREG(m)
        czy plik jest regularny?

    S_ISDIR(m)
        katalog?

    S_ISCHR(m)
        urządzenie znakowe?

    S_ISBLK(m)
        urządzenie blokowe?

    S_ISFIFO(m)
        kolejka FIFO (potok nazwany)?

    S_ISLNK(m)
        dowiązanie symboliczne? (Nie w POSIX.1-1996).

    S_ISSOCK(m)
        gniazdo? (Nie w POSIX.1-1996).

Dla pola st_mode zdefiniowano następujące flagi:
S_IFMT | 0170000 | maska bitowa dla pól bitowych 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
S_ISUID | 0004000 | bit "set-used-ID"
S_ISGID | 0002000 | bit "set-group-ID" (patrz niżej)
S_ISVTX | 0001000 | bit "sticky" (patrz niżej)
S_IRWXU | 00700 | maska praw dostępu właściciela pliku
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 | maska praw dostępu dla grupy
S_IRGRP | 00040 | grupa ma prawa odczytu
S_IWGRP | 00020 | grupa ma prawa zapisu
S_IXGRP | 00010 | grupa ma prawa wykonania
S_IRWXO | 00007 | maska uprawnień dla innych (poza grupą)
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.

WARTOŚĆ ZWRACANA
W przypadku powodzenia zwracane jest zero. W razie wystąpienia błędu zwracane jest -1 i ustawiana jest odpowiednia wartość zmiennej errno.

BŁĘDY

EACCES
    Brak uprawnień do przeszukiwania jednego z katalogów w ścieżce zaczynającej path. (Patrz także path_resolution(7)).

EBADF
    fd jest nieprawidłowy.

EFAULT
    Niepoprawny adres.

ELOOP
    Podczas rozwiązywania ścieżki napotkano zbyt wiele dowiązań symbolicznych.

ENAMETOOLONG
    Ścieżka path jest zbyt długa.

ENOENT
    Składnik ścieżki path nie istnieje lub path jest pustym łańcuchem znaków.

ENOMEM
    Brak pamięci (tj. pamięci jądra).

ENOTDIR
    Składnik ścieżki path nie jest katalogiem.

EOVERFLOW
    path lub fd odnosi się do pliku, numeru i-węzła lub numeru bloków, których rozmiar nie jest reprezentowalny w - odpowiednio - typie off_t, ino_t, blkcnt_t. Błąd ten może wystąpić na przykład wtedy, gdy aplikacja skompilowana na platformie 32-bitowej bez -D_FILE_OFFSET_BITS=64 wywoła stat() na pliku, którego rozmiar jest większy niż (1<<31)-1 bajtów.

ZGODNE Z
Opisywane wywołanie systemowe są zgodne z SVr4, BSD 4.3, POSIX.1-2001.

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 uprawnień 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.

  Inne systemy
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 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.

UWAGI
Od wersji jądra 2.5.48 struktura stat obsługuje nanosekundową dokładność wszystkich trzech pól czasowych. Glibc podaje nanosekundową część każdego z tych pól, używając albo st_atim.tv_nsec, jeżeli zdefiniowano makro _BSD_SOURCE lub _SVID_SOURCE. Pola te są podane w POSIX.1-2008 i w związku z tym, począwszy od wersji 2.12 biblioteka glibc udostępnia nazwy tych pól, 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. W systemach plików, które nie obsługują takiej dokładności czasowej, wartości nanosekund w tych polach wynoszą 0.

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.

  Interfejs jądra
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() (nowe w jądrze 2.4; slot __NR_stat64). Funkcja opakowująca stat() biblioteki glibc ukrywa te szczegóły przed aplikacjami, wywołując najnowszą wersję wywołania systemowego dostarczanego przez jądro i przepakowując zwracaną informację, jeśli jest to wymagane przez starsze aplikacje. Podobne uwagi odnoszą się do fstat() i lstat().

PRZYKŁAD
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);
}

ZOBACZ TAKŻE
access(2), chmod(2), chown(2), fstatat(2), readlink(2), utime(2), capabilities(7), symlink(7)

O STRONIE
Angielska wersja tej strony pochodzi z wydania 3.52 projektu Linux man-pages. Opis projektu oraz informacje dotyczące zgłaszania błędów można znaleźć pod adresem http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE
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ą 3.52 oryginału.