#include #include #include #include #include #include #include #include #include // necesar pentru PATH_MAX int copie_opts_i_u(char *nume_sursa, char *nume_dest, int flag_opt_i, int flag_opt_u); int main(int argc, char *argv[]) { int i, flag_opt_i = 0, flag_opt_u = 0; char *nume_sursa = NULL; char *nume_dest = NULL; if (argc < 3) { fprintf(stderr, "Usage: %s [-i] [-u] fisier-sursa fisier-destinatie\n", argv[0]); exit(1); } for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-i") == 0) { flag_opt_i = 1; continue; } if (strcmp(argv[i], "-u") == 0) { flag_opt_u = 1; continue; } if (nume_sursa == NULL) { nume_sursa = argv[i]; continue; } if (nume_dest == NULL) { nume_dest = argv[i]; continue; } fprintf(stderr, "Eroare: nu ati respectat formatul impus pentru argumentele din linia de comanda.\n"); exit(2); } if (nume_sursa == NULL) { fprintf(stderr, "Eroare: nu ati specificat fisierul sursa.\n"); exit(3); } if (nume_dest == NULL) { fprintf(stderr, "Eroare: nu ati specificat fisierul destinatie.\n"); exit(4); } return copie_opts_i_u(nume_sursa, nume_dest, flag_opt_i, flag_opt_u); } int copie_simpla(char *nume_sursa, char *nume_dest); int copie_opts_i_u(char *nume_sursa, char *nume_dest, int flag_opt_i, int flag_opt_u) { if (access(nume_sursa, R_OK) != 0) { fprintf(stderr, "Eroare: fisierul sursa %s nu este accesibil (i.e. nu exista, sau nu am drept de citire, sau ce?)\t", nume_sursa); perror("Cauza exacta este"); return 10; } int flag_dest_exista = access(nume_dest, F_OK) == 0 ? 1 : 0; int flag_abort_copiere = 0; if (flag_dest_exista) { if (flag_opt_u) { struct stat st_sursa, st_dest; if (0 != stat(nume_sursa, &st_sursa)) { fprintf(stderr, "Eroare la stat pentru fisierul sursa %s .\t", nume_sursa); perror("Cauza este"); return 11; } if (0 != stat(nume_dest, &st_dest)) { fprintf(stderr, "Eroare la stat pentru fisierul destinatie %s .\t", nume_dest); perror("Cauza este"); return 12; } if (st_sursa.st_mtime > st_dest.st_mtime) { printf("\tSursa %s are 'last modified time': %s", nume_sursa, ctime(&st_sursa.st_mtime)); printf("\tDestinatia %s are 'last modified time': %s", nume_dest, ctime(&st_dest.st_mtime)); printf("Notify message: copierea se va face cu suprascrierea destinatiei (deoarece sursa este mai recenta decat destinatia).\n"); } else { flag_abort_copiere = 1; printf("Sursa %s nu este mai recenta decat destinatia %s. Deci NU suprascriu destinatia cu sursa!\n", nume_sursa, nume_dest); } } if (!flag_abort_copiere && flag_opt_i) { char raspuns; printf("Fisierul destinatie %s exista deja (dar este mai vechi decat sursa). Vreti sa-l suprascrieti? (D/N)\n", nume_dest); do { scanf("%c", &raspuns); } while ((raspuns != 'D') && (raspuns != 'N')); if (raspuns == 'N') flag_abort_copiere = 1; else printf("Notify message: copierea se va face cu suprascrierea destinatiei (cu acceptul utilizatorului).\n"); } else { /* Vom da prioritate opțiunii -u : dacă destinația este mai recentă decât sursa, nu mai întrebăm utilizatorul, ci anulăm copierea. */ } } if (!flag_abort_copiere) { return copie_simpla(nume_sursa, nume_dest); } else { fprintf(stderr, "Copierea lui %s in %s nu s-a mai efectuat.\n", nume_sursa, nume_dest); return 13; } } int copie_simpla(char *nume_sursa, char *nume_dest) { int f1, f2; struct stat sb; if (-1 == (f1 = open(nume_sursa, O_RDONLY))) { fprintf(stderr, "Eroare la deschiderea fisierului sursa %s\n", nume_sursa); perror("Cauza este"); return 20; } if (-1 == (f2 = open(nume_dest, O_RDWR | O_CREAT))) { fprintf(stderr, "Eroare la deschiderea fisierului destinatie %s\n", nume_dest); perror("Cauza este"); return 21; } if (fstat(f1, &sb) == -1) perror("Eroare la fstat."); int offset = 0; int length = sb.st_size; if (ftruncate(f2, length) == -1) perror("Eroare la trunchiere"); chmod(nume_dest, S_IRUSR | S_IWUSR); char *map_addr1 = mmap(NULL, length, PROT_READ, MAP_PRIVATE, f1, offset); char *map_addr2 = mmap(NULL, length, PROT_WRITE, MAP_SHARED, f2, offset); if (map_addr1 == MAP_FAILED || map_addr2 == MAP_FAILED) perror("Eroare la mmap."); for (int i = 0; i < length; i++) *(map_addr2 + i) = *(map_addr1 + i); if (-1 == msync(map_addr2, length, MS_SYNC)) perror("Erroar la msync"); if (close(f1) == -1 || close(f2) == -1) perror("Eroare la inchiderea fisierelor."); if (munmap(map_addr1, length) == -1 || munmap(map_addr2, length) == -1) perror("Erroare la munmap."); printf("Am copiat cu succes fisierul sursa %s in destinatia %s\n", nume_sursa, nume_dest); return 0; }