Scroll to navigation

COPY_FILE_RANGE(2) Manuel du programmeur Linux COPY_FILE_RANGE(2)

NOM

copy_file_range - Copier une plage de données d'un fichier vers un autre

SYNOPSIS

#define _GNU_SOURCE
#include <unistd.h>
ssize_t copy_file_range(int fd_in, loff_t *off_in,
                        int fd_out, loff_t *off_out,
                        size_t len, unsigned int flags);

DESCRIPTION

L'appel système copy_file_range() effectue une copie interne au noyau entre deux descripteurs de fichier sans devoir en plus transférer des données du noyau à l'espace utilisateur puis revenir au noyau. Jusqu'à len octets de données sont transférés du descripteur de fichier source fd_in au descripteur de fichier cible fd_out, écrasant toute donnée se trouvant dans la plage du fichier cible sollicité.

La sémantique suivante s'applique à off_in et des déclarations identiques s'appliquent à off_out :

  • Si off_in est NULL, les octets sont lus dans fd_in à partir de la position du fichier, laquelle est ajustée par le nombre d'octets copiés.
  • Si off_in n'est pas NULL, off_in doit pointer vers un tampon qui indique le point de départ à partir duquel les octets de fd_in seront lus. La position du fichier de fd_in n'est pas modifiée mais off_in est ajusté correctement.

L'argument flags n'est fourni que pour des extensions futures et doit être positionné à 0 pour l'instant.

VALEUR RENVOYÉE

En cas de succès, copy_file_range() renverra le nombre d'octets copiés entre les fichiers. Il pourrait être inférieur à la taille demandée au départ.

En cas d'erreur, copy_file_range() renvoie -1 et errno est configuré pour indiquer l'erreur.

ERREURS

Un ou plusieurs descripteurs de fichier ne sont pas valables, ou fd_in n'est pas ouvert en lecture, ou bien fd_out n'est pas ouvert en écriture, ou bien le drapeau O_APPEND est positionné pour un descripteur de fichier auquel se rapporte fd_out.
Tentative d'écriture d'une plage dépassant la taille maximale d'un fichier définie par l'implémentation ou la limite de taille de fichier du processus, ou bien sur une position au-delà de celle maximum autorisée.
La plage demandée dépasse la fin du fichier source ou le paramètre flags ne vaut pas 0.
Une erreur E/S de bas niveau s'est produite lors de la copie.
fd_in ou fd_out se rapporte à un répertoire.
Plus assez de mémoire.
Il n'y a pas assez d'espace sur le système de fichiers cible pour terminer la copie.
Les fichiers auxquels se rapportent file_in et file_out ne sont pas sur le même système de fichiers monté.

VERSIONS

L'appel système copy_file_range() est apparu pour la première fois dans Linux 4.5, mais la glibc 2.27 offre une émulation dans l'espace utilisateur s'il n'est pas disponible.

CONFORMITÉ

L'appel système copy_file_range() est une extension GNU et un non standard de Linux.

NOTES

Si file_in est un fichier éparpillé, il se peut que copy_file_range() agrandisse les trous existant dans la plage demandée. Les utilisateurs peuvent tirer avantage de profiter d'un appel à copy_file_range() dans une boucle et en utilisant les opérations SEEK_DATA et SEEK_HOLE de lseek(2) pour chercher des emplacements de segments de données.

copy_file_range() donne aux systèmes de fichiers la possibilité d'implémenter des techniques de « copie accélérée » telles que l'utilisation de reflink (c'est-à-dire deux ou plusieurs i-nœuds partageant des pointeurs avec les mêmes blocs de disque copy-on-write) ou server-side-copy (dans le cas de NFS).

EXEMPLE

#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
/* Sur les versions de la glibc antérieures à 2.27, il faut

appeler copy_file_range() en utilisant syscall(2) */ static loff_t copy_file_range(int fd_in, loff_t *off_in, int fd_out,
loff_t *off_out, size_t len, unsigned int flags) {
return syscall(__NR_copy_file_range, fd_in, off_in, fd_out,
off_out, len, flags); } int main(int argc, char **argv) {
int fd_in, fd_out;
struct stat stat;
loff_t len, ret;
if (argc != 3) {
fprintf(stderr, "Utilisation : %s <source> <destination>\n", argv[0]);
exit(EXIT_FAILURE);
}
fd_in = open(argv[1], O_RDONLY);
if (fd_in == -1) {
perror("open (argv[1])");
exit(EXIT_FAILURE);
}
if (fstat(fd_in, &stat) == -1) {
perror("fstat");
exit(EXIT_FAILURE);
}
len = stat.st_size;
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd_out == -1) {
perror("open (argv[2])");
exit(EXIT_FAILURE);
}
do {
ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
if (ret == -1) {
perror("copy_file_range");
exit(EXIT_FAILURE);
}
len -= ret;
} while (len > 0);
close(fd_in);
close(fd_out);
exit(EXIT_SUCCESS); }

VOIR AUSSI

lseek(2), sendfile(2), splice(2)

COLOPHON

Cette page fait partie de la publication 4.16 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org> et Jean-Philippe MENGUAL <jpmengual@debian.org>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.

2 février 2018 Linux