Il n'existe pas de fonction CopyFile équivalente intégrée dans les API. Mais sendfile peut être utilisé pour copier un fichier en mode noyau, ce qui est une solution plus rapide et meilleure (pour de nombreuses raisons) que d'ouvrir un fichier, de le lire en boucle dans un tampon et d'écrire la sortie dans un autre fichier.
Mise à jour :
À partir de la version 2.6.33 du noyau Linux, la limitation exigeant la sortie de sendfile
pour être un socket a été levée et le code original fonctionnerait à la fois sur Linux et - cependant, à partir de OS X 10.9 Mavericks, sendfile
sur OS X exige maintenant que la sortie soit un socket et le code ne fonctionnera pas !
L'extrait de code suivant devrait fonctionner sur la plupart des systèmes OS X (à partir de 10.5), (Free)BSD, et Linux (à partir de 2.6.33). L'implémentation est "zero-copy" pour toutes les plateformes, ce qui signifie que tout est fait dans l'espace noyau et qu'il n'y a pas de copie de tampons ou de données dans et hors de l'espace utilisateur. C'est à peu près la meilleure performance que vous pouvez obtenir.
#include <fcntl.h>
#include <unistd.h>
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <copyfile.h>
#else
#include <sys/sendfile.h>
#endif
int OSCopyFile(const char* source, const char* destination)
{
int input, output;
if ((input = open(source, O_RDONLY)) == -1)
{
return -1;
}
if ((output = creat(destination, 0660)) == -1)
{
close(input);
return -1;
}
//Here we use kernel-space copying for performance reasons
#if defined(__APPLE__) || defined(__FreeBSD__)
//fcopyfile works on FreeBSD and OS X 10.5+
int result = fcopyfile(input, output, 0, COPYFILE_ALL);
#else
//sendfile will work with non-socket output (i.e. regular file) on Linux 2.6.33+
off_t bytesCopied = 0;
struct stat fileinfo = {0};
fstat(input, &fileinfo);
int result = sendfile(output, input, &bytesCopied, fileinfo.st_size);
#endif
close(input);
close(output);
return result;
}
EDITAR : Remplacé l'ouverture de la destination par l'appel à creat()
comme nous voulons le drapeau O_TRUNC
à spécifier. Voir le commentaire ci-dessous.
6 votes
Pour ne pas réinventer la roue, compilez GNU coreutils, à ma connaissance, il possède une bibliothèque statique pour copier les fichiers dans son arbre de construction, utilisée par
cp
et d'autres. Il supporte le sparseness et la vache btrfs.2 votes
Sous-ensemble linux : stackoverflow.com/questions/7463689/