Warum wird mmap () - Fehler mit permission denied für die Ziel-Datei eine Datei kopieren Programm?

Möchte ich zu geben versuchen beim kopieren der Inhalt einer Datei auf ein anderes durch die Verwendung von memory-mapped I/O in Linux über mmap(). Die Absicht ist zu prüfen, selbst wenn das besser als mit fread() und fwrite() und wie würde es viel mit großen Dateien (wie paar GiBs zum Beispiel, da wird die Datei eingelesen ganzen möchte ich wissen, wenn ich brauche, um eine solche Menge von Speicher).

Dies ist der code, mit dem ich arbeite und jetzt:

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

Ich denke, es kann ein Weg, es zu tun, aber ich bekomme immer einen Fehler beim Versuch die Karte der Ziel-Datei, konkret code 13 (permission denied).

Habe ich nicht die geringste Ahnung, warum es scheitert, kann ich schreiben, dass die Datei da die Datei wird erstellt und alle, und die Datei, die ich versuche zu kopieren, ist nur ein paar von KiBs in der Größe.

Kann jemand vor Ort das problem? Wie kommt es, ich musste die Berechtigung zum anzeigen der original-Datei, aber nicht das Ziel einer?

HINWEIS: Wenn jemand zu verwenden, die Schleife zum kopieren von bytes gesendet in der Frage statt memcpy zum Beispiel die loop-Zustand sein sollte i-- statt kopieren aller Inhalte. Dank jxh für spotting, dass.

  • Können Sie überprüfen, um zu sehen, ob die ftruncate Aufruf erfolgreich war?
  • Danke jxh, die Ziel-Datei scheint entstanden zu sein, mit der entsprechenden Größe. Ich war die überprüfung manuell bis jetzt, ich werde aktualisieren Sie den code, den ich gepostet haben.
  • Memory mapping ist nur sinnvoll, wenn Sie es verwenden, um das sammeln von Daten aus einer Quell-Datei. Es ist nicht so effizient wie ein schreiben Ziel. Ich würde sagen, Sie wäre das beste, aus mit unistd.h low-level-I/O (open(), read(), write(), fdatasync(), und close()) mit Puffer (chunk-Größen) basiert auf dem, was fstat() schlägt für die Dateien; largeish Zweierpotenzen wie 262144 oder größer sonst. Es gibt auch schnellere Möglichkeiten um Dateien zu kopieren, wenn.
Schreibe einen Kommentar