plucky (2) getdents.2.gz

Provided by: manpages-pl-dev_4.25.1-1_all bug

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

       EBADF  Nieprawidłowy deskryptor fd.

       EFAULT Argument wskazuje poza przestrzeń adresową wywołującego procesu.

       EINVAL Bufor na wynik jest za mały.

       ENOENT Nie ma takiego katalogu.

       ENOTDIR
              Deskryptor pliku nie odnosi się do katalogu.

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

       readdir(2), readdir(3), inode(7)

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 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ 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⟩.