fstatat(2) pobieranie stanu pliku

Other Alias

stat, fstat, lstat

SKŁADNIA

#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():

/* glibc 2.19 i wcześniejsze */ _BSD_SOURCE ||
/* Od glibc 2.20 */_DEFAULT_SOURCE ||
_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* od glibc 2.10: */ _POSIX_C_SOURCE >= 200112L

fstatat():

Od glibc 2.10:
_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
Przed glibc 2.10:
_ATFILE_SOURCE

OPIS

Funkcje te zwracają informacje o podanym pliku w buforze wskazanym przez stat. 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) */
    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 */
    /* Od Linuksa 2.6 jądro obsługuje nanosekundową
       rozdzielczość następującym 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.

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 wartości masek do części określającej typ pliku w polu st_mode:

S_IFMT0170000maska bitowa dla pól bitowych typu pliku

S_IFSOCK0140000gniazdo
S_IFLNK0120000dowiązanie symboliczne (symbolic link)
S_IFREG0100000plik regularny
S_IFBLK0060000urządzenie blokowe
S_IFDIR0040000katalog
S_IFCHR0020000urządzenie znakowe
S_IFIFO0010000kolejka 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) {
    /* Handle regular file */
}

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:

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

Poprzedni przykład kodu można dlatego przepisać w następujący sposób:

stat(pathname, &sb);
if (S_ISREG(sb.st_mode)) {
    /* Handle regular file */
}

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 uprawnienia pliku w polu st_mode:

S_ISUID0004000bit "set-used-ID"
S_ISGID0002000bit "set-group-ID" (patrz niżej)
S_ISVTX0001000bit "sticky" (patrz niżej)

S_IRWXU 00700maska praw dostępu właściciela pliku
S_IRUSR 00400właściciel ma prawa odczytu
S_IWUSR 00200właściciel ma prawa zapisu
S_IXUSR 00100właściciel ma prawa wykonania

S_IRWXG 00070maska praw dostępu dla grupy
S_IRGRP 00040grupa ma prawa odczytu
S_IWGRP 00020grupa ma prawa zapisu
S_IXGRP 00010grupa ma prawa wykonania

S_IRWXO 00007 maska uprawnień dla innych (poza grupą)
S_IROTH 00004inni mają prawa odczytu
S_IWOTH 00002inni mają prawa zapisu
S_IXOTH 00001inni 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.

fstatat()

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:

AT_EMPTY_PATH (od Linuksa 2.6.39)
Jeśli pathname jest łańcuchem pustym, to działa na pliku do którego odnosi się dirfd (który mógł zostać pozyskany za pomocą flagi O_PATH open(2)). Jeśli dirfd wynosi AT_FDCWD, to wywołujący działa w bieżącym katalogu roboczym. W takim przypadku dirfd może odnosić się do każdego typu pliku, nie tylko katalogu. Jest to opcja charakterystyczna dla Linuksa, proszę zdefiniować _GNU_SOURCE, aby dostać się do jej definicji.
AT_NO_AUTOMOUNT (od Linuksa 2.6.38)
Nie montuje automatycznie ostatniego komponentu ("basename") ścieżki podanej w pathname, jeśli ścieżka odnosi się do katalogu, który jest punktem automatycznego montowania. Pozwala to programowi wywołującemu zebrać atrybuty samego punktu montowania (a nie atrybuty lokalizacji, która zostałaby zamontowana). Znacznika tego można użyć w narzędziach, które przeszukują katalogi, aby zapobiec ich automatycznemu montowaniu. Znacznik AT_NO_AUTOMOUNT nie ma żadnego znaczenia, jeśli punkt montowania został już wcześniej zamontowany. Jest to opcja charakterystyczna dla Linuksa, proszę zdefiniować _GNU_SOURCE, aby dostać się do jej definicji.
AT_SYMLINK_NOFOLLOW
Jeśli pathname jest dowiązaniem symbolicznym nie podąża za nim, w zamian zwraca informacje o samym dowiązaniu, jak lstat(). Domyślnie fstatat () podąża za dowiązaniami symbolicznymi, jak stat().)

Więcej informacji o potrzebie wprowadzenia fstatat() można znaleźć w podręczniku openat(2).

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 pathname. (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 pathname jest zbyt długa.
ENOENT
Składnik ścieżki pathname nie istnieje lub pathname jest pustym łańcuchem znaków.
ENOMEM
Brak pamięci (tj. pamięci jądra).
ENOTDIR
Składnik ścieżki pathname nie jest katalogiem.
EOVERFLOW
pathname 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.

Mogą wystąpić następujące dodatkowe błędy dla fstatat():

EBADF
dirfd nie jest prawidłowym deskryptorem pliku.
EINVAL
Podano nieprawidłową opcję w flags.
ENOTDIR
pathname jest względna a dirfd jest deskryptorem pliku odnoszącym się do pliku zamiast do katalogu.

WERSJE

fstatat() zostało dodane do Linuksa w jądrze 2.6.16; obsługę biblioteki dodano do glibc w wersji 2.4.

ZGODNE Z

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 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.nazwalsósemk.opis
f000S_IFMT170000maska bitowa dla pól bitowych typu pliku
0000000000 niedziałający i-węzeł w SCO; nieznany typ w BSD; SVID-v2 i XPG2 0, jak i 0100000 dla zwykłego pliku
1000S_IFIFOp|010000kolejka FIFO (potok nazwany)
2000S_IFCHRc020000specjalny znakowy (V7)
3000S_IFMPC030000specjalny znakowy zwielokrotniony (V7)
4000S_IFDIRd/040000katalog (V7)
5000S_IFNAM050000 nazwany plik specjalny XENIX-a z dwoma podtypami, rozróżnianymi przez wartości 1, 2 w st_rdev
0001S_INSEMs000001podtyp IFNAM semafora XENIX
0002S_INSHDm000002podtyp IFNAM dzielonych danych XENIX
6000S_IFBLKb060000specjalny blokowy (V7)
7000S_IFMPB070000specjalny blokowy zwielokrotniony (V7)
8000S_IFREG-100000regularny (V7)
9000S_IFCMP110000skompresowany VxFS
9000S_IFNWKn110000sieciowy specjalny (HP-UX)
a000S_IFLNKl@120000dowiązanie symboliczne (BSD)
b000S_IFSHAD130000 shadow i-węzeł ACL w Solarisie (niewidzialny w przestrzeni użytkownika)
c000S_IFSOCKs=140000gniazdo (BSD; także "S_IFSOC" na VxFS)
d000S_IFDOORD>150000drzwi Solarisa
e000S_IFWHTw%160000BSD whiteout (nieużywane dla i-węzła)
0200S_ISVTX001000 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)
0400S_ISGID002000 set-group-ID podczas wykonywania (V7)
dla katalogów: używa semantyki BSD do propagacji GID
0400S_ENFMT002000 egzekwowanie blokowania plików Systemu V (dzielone z S_ISGID)
0800S_ISUID004000set-user-ID podczas wykonywania (V7)
0800S_CDF004000 katalog jest plikiem zależnym od kontekstu (HP-UX)

Polecenie "sticky" pojawiło się w wersji 32V systemu AT&T UNIX.

UWAGI

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.

Pola znaczników czasu

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.

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

Wywołanie systemowe niższego stopnia używane przez funkcję opakowującą fstatat() glibc nazywa się w rzeczywistości fstatat64().

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);
}

O STRONIE

Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału 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) <[email protected]>, Robert Luberda <[email protected]> i Michał Kułach <[email protected]>.

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.71 oryginału.