table of contents
- bookworm-backports 1:4.24.0-2~bpo12+1
- testing 1:4.24.0-2
- unstable 1:4.25.0-1
getdents(2) | System Calls Manual | getdents(2) |
NAZWA¶
getdents, getdents64 - pobiera wpisy z katalogu
BIBLIOTEKA¶
Standardowa biblioteka C (libc, -lc)
SKŁADNIA¶
#include <sys/syscall.h> /* Definicja stałych SYS_* */ #include <unistd.h>
long syscall(SYS_getdents, unsigned int fd, struct linux_dirent *dirp, unsigned int count);
#define _GNU_SOURCE /* Zob. feature_test_macros(7) */ #include <dirent.h>
ssize_t getdents64(int fd, void dirp[.count], size_t count);
Uwaga: glibc nie udostępnia opakowania dla getdents(), co wymusza użycie syscall(2).
Note: W glibc brak definicji struct linux_dirent; zob. UWAGI.
OPIS¶
Nie są to interfejsy, które cię interesują. Opis implementacji interfejsu zgodnego z POSIX w bibliotece C znajduje się w readdir(3). Niniejsza strona opisuje nagi interfejs wywołania systemowego.
getdents()¶
Wywołanie systemowe getdents() odczytuje kolejne struktury linux_dirent z katalogu wskazywanego przez przez deskryptor otwartego pliku fd do bufora wskazywanego przez dirp. Argument count określa rozmiar tego bufora.
Struktura linux_dirent jest zadeklarowana następująco:
struct linux_dirent {
unsigned long d_ino; /* Numer i-węzła */
unsigned long d_off; /* Nie jest przesunięciem; zob. niżej */
unsigned short d_reclen; /* Długość tego linux_dirent */
char d_name[]; /* Nazwa pliku (zakończ. znakiem null) */
/* długość to faktycznie (d_reclen - 2 -
offsetof(struct linux_dirent, d_name)) */
/*
char pad; // Zerowy bajt wyrównania
char d_type; // Typ pliku (tylko od Linuksa
// 2.6.4); przesunięciem jest (d_reclen - 1)
*/ }
d_ino jest numerem i-węzła. d_off jest wartością zależną od systemu plików, która nie ma znaczenia dla przestrzeni użytkownika, choć w starszych systemach plików była odległością od początku katalogu do początku następnej struktury linux_dirent; zob. readdir(3). d_reclen jest wielkością tej całej struktury linux_dirent. d_name jest nazwą pliku zakończoną znakiem NUL.
d_type jest bajtem na końcu struktury wskazującym typ pliku. Zawiera jedną z następujących wartości (zdefiniowanym w <dirent.h>):
- DT_BLK
- Jest to urządzenie blokowe
- DT_CHR
- Jest to urządzenie znakowe.
- DT_DIR
- Jest to katalog.
- DT_FIFO
- Jest to potok nazwany (FIFO).
- DT_LNK
- Jest to dowiązanie symboliczne.
- DT_REG
- Jest to zwykły plik.
- DT_SOCK
- Jest to gniazdo dziedziny Uniksa.
- DT_UNKNOWN
- Typ pliku jest nieznany.
Pole d_type zaimplementowano od Linuksa 2.6.4. Zajmuje miejsce, które wcześniej zajmował zerowy bajt wypełnienia w strukturze linux_dirent. Z tego względu jądra do Linuksa 2.6.3, próbujące uzyskać dostęp do tego pola zawsze zwracają wartość 0 (DT_UNKNOWN).
Obecnie jedynie niektóre systemy plików (m.in Btrfs, ext2, ext3 i ext4) obsługują w pełni zwracanie typu pliku w d_type. Wszystkie programy muszą poprawnie obsługiwać zwrócenie wartości DT_UNKNOWN.
getdents64()¶
Pierwotne, linuksowe wywołanie getdents() nie obsługiwało dużych systemów plików i dużych przesunięć pliku. Z tego powodu, Linux 2.4 dodał getdents64(), z szerszymi typami pól d_ino i d_off. Dodatkowo, getdents64() obsługuje wprost pole d_type.
Wywołanie systemowe getdents64() zachowuje się jak getdents(), tyle że jego drugi argument jest wskaźnikiem do bufora zawierającego strukturę następującego typu:
struct linux_dirent64 {
ino64_t d_ino; /* 64-bitowy numer i-węzła */
off64_t d_off; /* Nie jest przesunięciem, zob. getdents() */
unsigned short d_reclen; /* Rozmiar tego dirent */
unsigned char d_type; /* Typ pliku */
char d_name[]; /* Nazwa pliku (zakończona null) */ };
WARTOŚĆ ZWRACANA¶
Po pomyślnym zakończeniu zwracana jest ilość odczytanych bajtów. Na końcu katalogu zwracane jest 0. Przy błędzie zwracane jest -1 i ustawiane errno wskazując błąd.
BŁĘDY¶
STANDARDY¶
Brak.
HISTORIA¶
SVr4.
- getdents64()
- glibc 2.30.
UWAGI¶
glibc nie udostępnia opakowania dla getdents(); należy je wywołać za pomocą syscall(2). W takim przypadku konieczne będzie samodzielne zdefiniowanie struktury linux_dirent lub linux_dirent64.
Zamiast opisywanych wywołań systemowych, prawdopodobnie lepszym pomysłem będzie użycie readdir(3).
Te wywołania zastępują readdir(2).
PRZYKŁADY¶
Program poniżej demonstruje użycie getdents(). Poniższe wyjście pokazuje przykład, w którym można zaobserwować działanie tego programu w katalogu ext2:
$ ./a.out /testfs/ --------------- nread=120 --------------- i-węzeł# typ pliku d_reclen d_off d_name
2 katalog 16 12 .
2 katalog 16 24 ..
11 katalog 24 44 lost+found
12 zwykły 16 56 a
228929 katalog 16 68 sub
16353 katalog 16 80 sub2
130817 katalog 16 4096 sub3
Kod źródłowy programu¶
#define _GNU_SOURCE #include <dirent.h> /* Definiuje stałe DT_* */ #include <err.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> struct linux_dirent {
unsigned long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[]; }; #define BUF_SIZE 1024 int main(int argc, char *argv[]) {
int fd;
char d_type;
char buf[BUF_SIZE];
long nread;
struct linux_dirent *d;
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
err(EXIT_FAILURE, "open");
for (;;) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
err(EXIT_FAILURE, "getdents");
if (nread == 0)
break;
printf("--------------- nread=%ld ---------------\n", nread);
printf("i-węzeł# typ pliku d_reclen d_off d_name\n");
for (size_t bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
printf("%8lu ", d->d_ino);
d_type = *(buf + bpos + d->d_reclen - 1);
printf("%-10s ", (d_type == DT_REG) ? "zwykły" :
(d_type == DT_DIR) ? "katalog" :
(d_type == DT_FIFO) ? "FIFO" :
(d_type == DT_SOCK) ? "gniazdo" :
(d_type == DT_LNK) ? "dow. symbol." :
(d_type == DT_BLK) ? "urz. blok." :
(d_type == DT_CHR) ? "urz. znak." : "???");
printf("%4d %10jd %s\n", d->d_reclen,
(intmax_t) d->d_off, d->d_name);
bpos += d->d_reclen;
}
}
exit(EXIT_SUCCESS); }
ZOBACZ TAKŻE¶
TŁUMACZENIE¶
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>
Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.
Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.
2 maja 2024 r. | Linux man-pages 6.8 |