readlink(2)

NAZWA
readlink, readlinkat - odczytuje wartość dowiązania symbolicznego

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <unistd.h>

ssize_t readlink(size_t bufsiz;
                 const char *restrict path,
                 char buf[restrict bufsiz], size_t bufsiz);

#include <fcntl.h>            /* Definicja stałych AT_* */
#include <unistd.h>

ssize_t readlinkat(size_t bufsiz;
                 int dirfd, const char *restrict path,
                 char buf[restrict bufsiz], size_t bufsiz);

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

readlink():
    _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L
        || /* glibc <= 2.19: */ _BSD_SOURCE

readlinkat():
    Od glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    Przed glibc 2.10:
        _ATFILE_SOURCE

OPIS
readlink() umieszcza zawartość dowiązania symbolicznego path w buforze buf, którego wielkość wynosi bufsiz. readlink() nie dokleja do bufora buf końcowego bajtu null. W przypadku, gdy bufor jest za mały, aby pomieścić całą zawartość dowiązania, jest ona (po cichu) obcinana (do ilości znaków równej długości bufsiz).

  readlinkat()
Wywołanie systemowe readlinkat() operuje w dokładnie taki sam sposób jak readlink(), z wyjątkiem różnic opisanych tutaj.

Jeśli ścieżka podana w path 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 readlink()).

Jeśli path jest względna a dirfd ma wartość specjalną AT_FDCWD, to path jest interpretowana w odniesieniu do bieżącego katalogu roboczego procesu wywołującego (jak readlink()).

Jeśli ścieżka path jest bezwzględna, to dirfd jest ignorowane.

Od Linuksa 2.6.39, path może być łańcuchem pustym; wówczas wywołanie działa na dowiązaniu symbolicznym, do którego odnosi się dirfd (które powinno być uzyskane za pomocą open(2) ze znacznikami O_PATH i O_NOFOLLOW).

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

WARTOŚĆ ZWRACANA
W przypadku powodzenia, te wywołania zwracają liczbę bajtów umieszczonych w buf (jeśli wartość zwracana równa się bufsiz, to mogło dojść do obcięcia). W razie wystąpienia błędu zwracane jest -1 i ustawiane errno wskazując błąd.

BŁĘDY

EACCES
    Brak praw do przeszukiwania składowej ścieżki (patrz także path_resolution(7)).

EBADF
    (readlinkat()) path jest względna, lecz dirfd nie wynosi ani AT_FDCWD, ani nie jest prawidłowym deskryptorem pliku.

EFAULT
    buf wskazuje poza przydzieloną procesowi przestrzeń adresową.

EINVAL
    bufsiz nie jest dodatnie.

EINVAL
    Nazwany plik (tj. ostatnia składowa ścieżki path) nie jest dowiązaniem symbolicznym.

EIO Podczas odczytu z systemu plików wystąpił błąd wejścia/wyjścia.

ELOOP
    Natrafiono na zbyt wiele dowiązań symbolicznych podczas tłumaczenia ścieżki.

ENAMETOOLONG
    Scieżka, lub składnik ścieżki, były za długie.

ENOENT
    Plik wskazywany przez nazwę nie istnieje.

ENOMEM
    Brak pamięci jądra.

ENOTDIR
    Składowa ścieżki nie jest katalogiem.

ENOTDIR
    (readlinkat()) path jest względna, a dirfd jest deskryptorem pliku odnoszącym się do pliku zamiast do katalogu.

STANDARDY
POSIX.1-2024.

HISTORIA

readlink()
    4.4BSD (pojawiło się pierwotnie w 4.2BSD), POSIX.1-2001, POSIX.1-2008.

readlinkat()
    POSIX.1-2008. Linux 2.6.16, glibc 2.4.

Do glibc 2.4 włącznie, zwracany typ readlink() był zadeklarowany jako int. Obecnie, zwracany typ jest zadeklarowany jako ssize_t, zgodnie z (nowym) wymaganiem POSIX.1-2001.

  glibc
Na starszych wersjach jądra Linuxa gdzie readlinkat() nie było dostępne, funkcja opakowująca z glibc wraca do używania readlink(). Kiedy path jest względna, glibc konstruuje ścieżkę na bazie dowiązania symbolicznego w /proc/self/fd, które odpowiada argumentowi dirfd.

UWAGI
Używanie bufora o statycznym rozmiarze, może nie dać wystarczająco dużo miejsca na zawartość dowiązania symbolicznego. Wymagany rozmiar bufora można uzyskać z wartości stat.st_size, zwracanej przez wywołanie lstat(2), na dowiązaniu. Jednak należy sprawdzić liczbę bajtów zapisanych przez readlink() i readlinkat() aby upewnić się, że rozmiar dowiązania symbolicznego nie zmienił się między tymi wywołaniami. Dynamicznie przydzielany bufor readlink() i readlinkat() rozwiązuje również częsty problem z przenośnością, gdy korzysta się PATH_MAX jako rozmiaru bufora, bowiem zdefiniowanie tej stałej nie jest gwarantowane przez POSIX, jeśli system nie posiada takiego limitu.

PRZYKŁADY
Poniższy program dynamicznie przydziela bufor, potrzebny readlink(), na podstawie informacji zapewnionych przez lstat(2), alternatywnie używając bufora o rozmiarze PATH_MAX, w przypadku gdy lstat(2) zwróci rozmiar zerowy.

    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>

    int
    main(int argc, char *argv[])
    {
        char         *buf;
        ssize_t      nbytes, bufsiz;
        struct stat  sb;

        if (argc != 2) {
            fprintf(stderr, "Użycie: %s <ścieżka>\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        if (lstat(argv[1], &sb) == -1) {
            perror("lstat");
            exit(EXIT_FAILURE);
        }

        /* Dodaje jeden do rozmiaru dowiązania, dzięki czemu można
           sprawdzić, czy bufor zwrócony przez readlink() był obcięty.  */

        bufsiz = sb.st_size + 1;

        /* Niektóre magiczne dowiązania symboliczne np. w /proc i /sys
           zgłaszają 'st_size' równy zero. W takim przypadku
           używa PATH_MAX jako "wystarczającego" oszacowania.  */

        if (sb.st_size == 0)
            bufsiz = PATH_MAX;

        buf = malloc(bufsiz);
        if (buf == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }

        nbytes = readlink(argv[1], buf, bufsiz);
        if (nbytes == -1) {
            perror("readlink");
            exit(EXIT_FAILURE);
        }

        /* Wypisuje jedynie 'nbytes' z 'buf', dzięki czemu nie zawiera
           kończącego znaku null ('\0').  */
        printf("'%s' wskazuje na '%.*s'\n", argv[1], (int) nbytes, buf);

        /* Jeśli wartość zwracana jest równa rozmiarowi bufora, to dowiązanie
           docelowe było dłuższe niż oczekiwano (być może cel zmienił się
           pomiędzy wywołaniem lstat() i wywołaniem readlink()). Ostrzega
           użytkownika, że zwracany cel mógł być przycięty.  */

        if (nbytes == bufsiz)
            printf("(Zwracany bufor mógł być przycięty)\n");

        free(buf);
        exit(EXIT_SUCCESS);
    }

ZOBACZ TAKŻE
readlink(1), lstat(2), stat(2), symlink(2), realpath(3), path_resolution(7), symlink(7)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: 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.