- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <limits.h> // 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;
- }