Pourquoi ne mmap() échoue avec l'autorisation refusée pour le fichier de destination de la copie d'un fichier de programme?

J'aimerais essayer de copier le contenu d'un fichier à un autre en utilisant memory mapped I/O sous Linux via mmap(). L'intention est de vérifier par moi-même si c'est mieux que d'utiliser fread() et fwrite() et comment serait-il traiter de gros fichiers (comme quelques Lardons par exemple, puisque le fichier est lu en entier, je veux savoir si j'ai besoin d'avoir une telle quantité de mémoire pour elle).

C'est le code, je travaille avec maintenant:

//Open original file descriptor:
int orig_fd = open(argv[1], O_RDONLY);
//Check if it was really opened:
if (orig_fd == -1) {
fprintf(stderr, "ERROR: File %s couldn't be opened:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
exit(EX_NOINPUT);
}
//Idem for the destination file:
int dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
//Check if it was really opened:
if (dest_fd == -1) {
fprintf(stderr, "ERROR: File %s couldn't be opened:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
//Close original file descriptor too:
close(orig_fd);
exit(EX_CANTCREAT);
}
//Acquire file size:
struct stat info = {0};
if (fstat(orig_fd, &info)) {
fprintf(stderr, "ERROR: Couldn't get info on %s:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
//Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
//Set destination file size:
if (ftruncate(dest_fd, info.st_size)) {
fprintf(stderr, "ERROR: Unable to set %s file size:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
//Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
//Map original file and close its descriptor:
char *orig = mmap(NULL, info.st_size, PROT_READ, MAP_PRIVATE, orig_fd, 0);
if (orig == MAP_FAILED) {
fprintf(stderr, "ERROR: Mapping of %s failed:\n", argv[1]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
//Close file descriptors:
close(orig_fd);
close(dest_fd);
exit(EX_IOERR);
}
close(orig_fd);
//Map destination file and close its descriptor:
char *dest = mmap(NULL, info.st_size, PROT_WRITE, MAP_SHARED, dest_fd, 0);
if (dest == MAP_FAILED) {
fprintf(stderr, "ERROR: Mapping of %s failed:\n", argv[2]);
fprintf(stderr, "%d - %s\n", errno, strerror(errno));
//Close file descriptors and unmap first file:
munmap(orig, info.st_size);
close(dest_fd);
exit(EX_IOERR);
}
close(dest_fd);
//Copy file contents:
int i = info.st_size;
char *read_ptr = orig, *write_ptr = dest;
while (--i) {
*write_ptr++ = *read_ptr++;
}
//Unmap files:
munmap(orig, info.st_size);
munmap(dest, info.st_size);

Je pense que c'est peut-être une façon de le faire, mais je reçois un message d'erreur en essayant de carte le fichier de destination, concrètement, code 13 (permission denied).

Je n'ai pas la moindre idée pourquoi est-elle défaillante, je peux écrire dans ce fichier car le fichier est créé et tous et le fichier que je suis en train de copier est juste un couple de ces services dans la taille.

Quelqu'un peut-il repérer le problème? Comment ai-je eu l'autorisation de la carte le fichier d'origine mais pas la destination?

REMARQUE: Si quelqu'un est d'utiliser la boucle pour copier des octets publié dans la question de la place de memcpy par exemple, la condition de la boucle doit être i-- au lieu de copier tout le contenu. Grâce à jxh pour s'apercevoir qu'.

Pouvez-vous vérifier pour voir si le ftruncate appel a réussi?
Merci jxh, le fichier de destination semble être créés avec la taille appropriée. J'ai été vérifier manuellement jusqu'à maintenant, je vais mettre à jour le code que j'ai posté.
Mappage de la mémoire n'est utile que si vous l'utiliser pour recueillir les données à partir d'un fichier source. Ce n'est pas aussi efficace que l'écriture de la cible. Je dirais que vous seriez mieux à l'aide de unistd.h faible niveau I/O (open(), read(), write(), fdatasync(), et close()) avec tampons (tailles de segment) basé sur ce que fstat() suggère de fichiers; largeish des puissances de deux, comme 262144 ou plus autrement. Il y a même des manières plus rapides pour copier des fichiers.

OriginalL'auteur James Russell | 2013-06-19