#include #include #include #include #include #include /* For O_* constants */ #include /* For mode constants */ #include #include #include #include #include #include #include #include /* *** esercizio C04 *** doppia pipe [difficoltà: medio] il programma calcola il digest di sha256 di un file regolare, utilizzando un processo figlio che fà tutto il calcolo; la comunicazione tra i due processi avviene tramite due pipe, una per inviare i dati al processo figlio (il contenuto del file) e l'altra pipe per inviare il digest al processo padre. processo padre crea due pipe: pipe_tx per trasmettere dati al processo figlio pipe_rx per ricevere dati dal processo figlio il processo padre un file (ad esempio: scaricate ed usate https://github.com/marcotessarotto/exOpSys/blob/master/res/text01.txt) il processo padre manda, usando pipe_tx, un "pacchetto" dati (vedere sotto packet_t) così organizzato: 4 byte iniziali (unsigned int) che specifica la lunghezza dei dati (array di char) che vengono inviati subito dopo. typedef struct { char * data; unsigned int len; } packet_t; alla ricezione di un pacchetto dati, il processo figlio calcola sha256 e trasmette, usando pipe_rx, il digest al processo padre (usando lo stessa organizzazione dei dati della trasmissione vista sopra) il processo padre riceve il digest e scrive su stdout una cosa del genere: "file xyz sha256 digest: " */ int pipe_tx[2]; int pipe_rx[2]; typedef struct { char * data; unsigned int len; } packet_t; //struct digest_result { // unsigned int digest_len; // unsigned char * digest; //}; packet_t calculate_sha256(packet_t * p) { packet_t result = { NULL , 0 }; // if returned, means this functions was not successful EVP_MD_CTX * mdctx; unsigned char * digest; unsigned int digest_len; EVP_MD * algo; algo = EVP_sha256(); if ((mdctx = EVP_MD_CTX_create()) == NULL) { printf("EVP_MD_CTX_create() error\n"); return result; } // initialize digest engine if (EVP_DigestInit_ex(mdctx, algo, NULL) != 1) { // EVP_DigestInit_ex returns 1 if successful EVP_MD_CTX_destroy(mdctx); printf("EVP_DigestInit_ex() error\n"); return result; } // provide data to digest engine if (EVP_DigestUpdate(mdctx, p->data, p->len) != 1) { // EVP_DigestUpdate returns 1 if successful EVP_MD_CTX_destroy(mdctx); printf("EVP_DigestUpdate() error\n"); return result; } digest_len = EVP_MD_size(algo); if ((digest = (unsigned char *)OPENSSL_malloc(digest_len)) == NULL) { EVP_MD_CTX_destroy(mdctx); printf("OPENSSL_malloc() error\n"); return result; } // produce digest if (EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { // EVP_DigestFinal_ex returns 1 if successful OPENSSL_free(digest); EVP_MD_CTX_destroy(mdctx); printf("EVP_DigestFinal_ex() error\n"); return result; } //OPENSSL_free(digest); EVP_MD_CTX_destroy(mdctx); result.data = digest; result.len = digest_len; return result; // OK: a copy of struct result is returned } // write_packet_to_pipe(&prova, pipe_tx); void write_packet_to_pipe(packet_t * p, int pipe_fd[]) { int res; res = write(pipe_fd[1], &p->len, sizeof(p->len)); if (res == -1) { perror("write"); exit(1); } res = write(pipe_fd[1], p->data, p->len); if (res == -1) { perror("write"); exit(1); } } packet_t read_packet_from_pipe(int pipe_fd[]) { int res; packet_t result = { NULL, 0 }; res = read(pipe_fd[0], &result.len, sizeof(result.len)); if (res == -1) { perror("read"); exit(1); } if (res == 0) { //printf("EOF su pipe\n"); return result; } result.data = malloc(result.len); // TODO: completare res = read(pipe_fd[0], result.data, result.len); if (res == -1) { perror("read"); exit(1); } return result; } void child_process() { close(pipe_tx[1]); close(pipe_rx[0]); while (1) { packet_t dati_in_ingresso = read_packet_from_pipe(pipe_tx); if (dati_in_ingresso.data == NULL) { printf("[child] EOF su pipe\n"); break; } printf("[child] ho ricevuto: len=%d data=%s\n", dati_in_ingresso.len, dati_in_ingresso.data); packet_t risultato_digest = calculate_sha256(&dati_in_ingresso); write_packet_to_pipe(&risultato_digest, pipe_rx); } printf("[child] bye\n"); exit(0); } int main() { if (pipe(pipe_tx) == -1) { perror("pipe"); exit(1); } if (pipe(pipe_rx) == -1) { perror("pipe"); exit(1); } // manca la parte di lettura da file packet_t prova = { "1234", 5 }; pid_t pid; pid = fork(); if (pid == -1) { perror("fork"); exit(1); } if (pid == 0) child_process(); // processo padre close(pipe_tx[0]); close(pipe_rx[1]); write_packet_to_pipe(&prova, pipe_tx); packet_t risultato = read_packet_from_pipe(pipe_rx); printf("[parent] ho ricevuto: len=%d \n", risultato.len); printf("[parent] digest: "); for (int i = 0; i < risultato.len; i++) printf("%02x", (unsigned char) risultato.data[i]); printf("\n"); return 0; }