#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include #include /* * * *** esercizio C03 *** copia di file con mmap *** [difficoltà: facile] copiare un file usando la system call mmap (in entrambe le fasi: leggere il file sorgente, scrivere il file destinazione) [cosa fare se il file sorgente coincide con il file destinazione?] * */ int is_fd_a_regular_file(int fd) { struct stat sb; int res; res = fstat(fd, &sb); if (res == -1) { perror("fstat()"); return -1; } return (sb.st_mode & S_IFMT) == S_IFREG; } // restituisce la dimensione del file, -1 in caso di errore __off_t get_fd_size(int fd) { struct stat sb; int res; res = fstat(fd, &sb); if (res == -1) { perror("fstat()"); return -1; } return sb.st_size; } int main(int arwgc, char * argv[]) { char * source_filename; char * target_filename; int fd; char * source_map; char * target_map; __off_t source_file_size; source_filename = "text01.txt"; target_filename = "copia.txt"; // check: source_filename è un file regolare? // apriamo il file in sola lettura fd = open(source_filename, O_RDONLY); if (fd == -1) { perror("open"); exit(1); } // se non è un file regolare, terminiamo if (!is_fd_a_regular_file(fd)) { printf("il file da copiare non è un file regolare.\n"); exit(1); } // dimensione del file da copiare source_file_size = get_fd_size(fd); // mappiamo in memoria tutto il file da copiare source_map = mmap(NULL, source_file_size, PROT_READ, MAP_PRIVATE, fd, 0); if (source_map == MAP_FAILED) { perror("mmap"); exit(1); } close(fd); // creaiamo il file destinazione fd = open(target_filename, O_CREAT | O_TRUNC | O_RDWR, S_IWUSR | S_IRUSR); if (fd == -1) { perror("open"); exit(1); } // impostiamo la dimensione del file destinazione // il suo contenuto è 'zero' if (ftruncate(fd, source_file_size) == -1) { perror("ftruncate"); exit(1); } // mappiamo in memoria il file destinazione target_map = mmap(NULL, source_file_size, PROT_WRITE, MAP_SHARED, fd, 0); if (target_map == MAP_FAILED) { perror("mmap"); exit(1); } close(fd); // copiamo tutto il contenuto della memory map del file sorgente // nella memory map del file destinazione memcpy(target_map, source_map, source_file_size); printf("ho copiato %ld bytes\n", source_file_size); // le due memory map verranno chiuse dal kernel, quando il programma termina return 0; }