#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include #include /* ***D11*** copia di un file regolare, tra processi: è dato un file origine, da copiare il processo padre legge tutto il file in memoria; poi il processo padre crea il processo figlio, che va a scrivere il file destinazione. quando il file è stato scritto, il processo padre scrive "ok" su stdout. come si fa a verificare che il contenuto dei due file sia identico? nota: vedere esercizio C03 */ // 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() { 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"; // 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); pid_t pid; pid = fork(); if (pid == -1) { perror("fork"); exit(1); } else if (pid == 0) { // processo figlio // creiamo 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("[child] ho copiato %ld bytes\n", source_file_size); exit(0); } // cancelliamo la memory map (se non lo facciamo, lo farà il kernel quando il processo termina) if (munmap(source_map, source_file_size) == -1) { perror("munmap"); } // il processo padre aspetta la conclusione del processo figlio if (wait(NULL) == -1) { perror("wait"); exit(1); } // come si fa a verificare che il contenuto dei due file sia identico? // si può fare così: // calcolare il digest con sha256 del file origine // calcolare il digest con sha256 del file destinazione // confrontare i due digest: se sono uguali => OK printf("[parent] bye\n"); return 0; }