Skip to content
/linux-syscalls

Fichiers & E/S · Section 2

lseek(2)

Repositionne le décalage lecture/écriture d'un descripteur de fichier.

Signature

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
fd
Descripteur seekable (fichier régulier, périphérique bloc).
offset
Décalage signé en octets, interprété selon whence.
whence
SEEK_SET (absolu), SEEK_CUR (relatif), SEEK_END (depuis EOF), SEEK_DATA (prochaines données après offset), SEEK_HOLE (prochain trou après offset).

Description

lseek() repositionne le décalage du descripteur fd à offset octets interprétés selon whence : SEEK_SET (absolu depuis le début), SEEK_CUR (relatif au courant), SEEK_END (relatif à la fin — offset négatif pour reculer). Retourne le décalage absolu résultant, ou (off_t) -1 avec errno. lseek() ne fait pas d'E/S — il ajuste le curseur de position par fd côté noyau. Chercher au-delà de la fin d'un fichier inscriptible puis écrire crée un trou creux (les pages intermédiaires sont à zéro en lecture mais non allouées sur disque). lseek() ne fonctionne pas sur tubes, sockets, FIFO ou terminaux — pas d'accès aléatoire, retour -1/ESPIPE. Sur les ABI 32 bits avec off_t 64 bits, le noyau expose _llseek() (retournant le décalage via un paramètre de sortie pour éviter le rognage 32 bits) ; la glibc moderne choisit transparemment le bon syscall.

Numéros par architecture

ArchitectureNuméroABIPoint d'entrée
x86 (i386)19i386sys_lseek
x64 (x86_64)8commonsys_lseek

Historique noyau

Introduit dans Linux 1.0.

  1. 1.0

    lseek() est l'un des syscalls originels. La signature 32 bits limite offset à 2 GiB sur i386 ; _llseek() (1995) a ajouté le chemin 64 bits.

  2. 3.1

    SEEK_DATA et SEEK_HOLE ont été standardisés pour parcourir efficacement les fichiers creux sans lire chaque octet. Supportés par ext4, XFS, btrfs et tmpfs ; sur ceux qui n'exposent pas l'info de trou, le noyau retombe sur tout-le-fichier comme une seule région de données.

seccomp & conteneurs

Docker default profile

Autorisé

Podman default profile

Autorisé

lseek() et _llseek() sont dans tout profil par défaut. Pas de filtrage d'arguments utile — les applications utilisent whence et offset librement.

libseccomp

seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek),   0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(_llseek), 0);

Exemple strace

$ strace -e lseek dd if=/etc/hostname of=/dev/null bs=1 count=4 skip=2
lseek(0, 2, SEEK_SET)                   = 2

Les lignes lseek() s'associent à read()/write() pour former le mouvement d'E/S complet. L'usage le plus informatif est de suivre un parcours de fichier creux : SEEK_DATA → read → SEEK_HOLE → SEEK_DATA → read. -e lseek filtre.

Sécurité & observabilité

lseek() est rarement un signal direct. Motif notable : évasion de rotation de log où un malware reculer dans un fichier de log et écrase des octets antérieurs (au lieu d'append) pour masquer des entrées — mais la plupart des logs modernes sont append-only via O_APPEND, ce qui rend la course seek+write inopérante. Le tracepoint eBPF sys_enter_lseek est généralement trop bruyant pour la supervision.

Erreurs

EBADF
fd n'est pas un descripteur ouvert.
EINVAL
whence invalide, ou offset produirait une position absolue invalide (négative).
ENXIO
SEEK_DATA / SEEK_HOLE : offset au-delà d'EOF.
EOVERFLOW
Décalage résultant hors plage off_t (programme 32 bits non-LFS atteignant 4 GiB+).
ESPIPE
fd désigne un tube, une socket ou un FIFO — pas d'accès aléatoire.

Drapeaux

SEEK_SET
0
—
SEEK_CUR
1
—
SEEK_END
2
—
SEEK_DATA
3
Atteint le début de la prochaine région de données à ou après offset. Utilisé par cp --sparse et rsync pour sauter efficacement les trous.
SEEK_HOLE
4
Atteint le prochain trou à ou après offset. Combiné à SEEK_DATA, donne une énumération O(trous+données) de la disposition d'un fichier creux.

Syscalls liés