readlink(2) System Calls Manual readlink(2)

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

Standardowa biblioteka C (libc, -lc)

#include <unistd.h>
ssize_t readlink(const char *restrict pathname, char *restrict buf,
                 size_t bufsiz);
#include <fcntl.h>            /* Definicja stałych AT_* */
#include <unistd.h>
ssize_t readlinkat(int dirfd, const char *restrict pathname,
                 char *restrict buf, 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

readlink() umieszcza zawartość dowiązania symbolicznego pathname 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).

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

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

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

Od Linuksa 2.6.39, pathname 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).

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.

Brak praw do przeszukiwania składowej ścieżki (patrz także path_resolution(7)).
(readlinkat()) pathname jest względne, lecz dirfd nie wynosi ani AT_FDCWD, ani nie jest prawidłowym deskryptorem pliku.
buf wskazuje poza przydzieloną procesowi przestrzeń adresową.
bufsiz nie jest dodatnie.
Nazwany plik (tj. ostatnia składowa ścieżki pathname) nie jest dowiązaniem symbolicznym.
Podczas odczytu z systemu plików wystąpił błąd wejścia/wyjścia.
Natrafiono na zbyt wiele dowiązań symbolicznych podczas tłumaczenia ścieżki.
Scieżka, lub składnik ścieżki, były za długie.
Plik wskazywany przez nazwę nie istnieje.
Brak pamięci jądra.
Składowa ścieżki nie jest katalogiem.
(readlinkat()) pathname jest względna, a dirfd jest deskryptorem pliku odnoszącym się do pliku zamiast do katalogu.

POSIX.1-2008.

4.4BSD (pojawiło się pierwotnie w 4.2BSD), POSIX.1-2001, POSIX.1-2008.
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.

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

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.

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

readlink(1), lstat(2), stat(2), symlink(2), realpath(3), path_resolution(7), symlink(7)

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