/* given a list of filenames in input (one per line), and a set of directories; for each filename, compare the versions in the directories. If they are the same, copy one of them to dest; otherwise, copy all of them with appropriate prefixes */ #include #include #include #include #include #define MAX_DIRS 100 #define BUFF_SIZE 8192 #define MAXPATHLEN 10000 #define MAX_BUFFERS 1000 extern char *malloc (); extern char *strchr (); extern int system (); extern int errno; int nb_dirs; char *dir [MAX_DIRS]; char *suffix [MAX_DIRS]; int nb_buffs; char *buffer [MAX_BUFFERS]; int size [MAX_BUFFERS]; char line [MAXPATHLEN]; char filename [MAXPATHLEN]; char command [MAXPATHLEN]; char *output; int verbose; void error (va_alist) va_dcl { va_list args; char *fmt; fprintf (stderr, "merge2: "); va_start (args); fmt = va_arg (args, char*); vfprintf (stderr, fmt, args); va_end (args); fprintf (stderr, "\n"); fflush (stderr); perror (""); exit (1); } char read_line (dest) char *dest; { char c; while (((c = getchar ()) != '\n') && (c != EOF)) { *dest++ = c; } *dest = '\0'; return c; } void protected_system (command) char * command; { int i; errno = 0; if ((i = system (command)) != 0) { error ("system exited with 0x%x", i); } } main (argc, argv) int argc; char **argv; { int bad_usage; char *c; int i, j, n, b; int f; int output_length = 0; argc--; argv++; while ((argc > 0) && (argv[0][0] == '-')) { switch (argv[0][1]) { case 'v': verbose = 1; break; case 'o': output = argv[0] + 2; break; default: bad_usage = 1; break; } argv++; argc--; } while (argc > 0) { c = strchr (argv[0], '='); if (c == 0) { bad_usage = 1; break; } else { dir[nb_dirs] = c + 1; suffix[nb_dirs] = argv[0]; *c = '\0'; nb_dirs++; } argc--; argv++; } if (bad_usage) { fprintf (stderr, "usage: merge2 [-v] [-odest] suffix=dir ...\n"); exit (1); } buffer [0] = malloc (BUFF_SIZE); while (read_line (line) != EOF) { /* read in the first file */ sprintf (filename, "%s/%s", dir[0], line); if ((f = open (filename, O_RDONLY, 0)) <= -1) { if (errno == ENOENT) { goto diff; } error ("opening %s\n", filename); } nb_buffs = 0; while (1) { nb_buffs++; if (buffer [nb_buffs] == 0) { buffer [nb_buffs] = malloc (BUFF_SIZE); } size [nb_buffs] = read (f, buffer[nb_buffs], BUFF_SIZE); if (size [nb_buffs] < 0) { error ("reading %s\n", filename); } if (size [nb_buffs] == 0) { if (close (f) != 0) { error ("closing %s\n", filename); } break; }} /* compare each of the other files */ for (j = 1; j < nb_dirs; j++) { sprintf (filename, "%s/%s", dir[j], line); if ((f = open (filename, O_RDONLY, 0)) <= -1) { if (errno == ENOENT) { goto diff; } error ("opening %s\n", filename); } b = 1; while (b <= nb_buffs) { n = read (f, buffer [0], BUFF_SIZE); if (n < 0) { error ("reading %s", filename); } if (n != size [b]) { goto diff; } if (memcmp (buffer[0], buffer [b], n) != 0) { goto diff; } b ++; } if (close (f) != 0) { error ("closing %s\n", filename); }} /* they are the same */ if (verbose) { fprintf (stderr, "same %s\n", line); } else { if (output_length > 70) { printf ("\n"); output_length = 0; } output_length++; printf ("."); fflush (stdout); } sprintf (command, "cp %s/%s %s/%s\n", dir[0], line, output, line); protected_system (command); continue; diff: /* they differ */ if (close (f) != 0) { error ("closing %s\n", filename); } if (output_length != 0) { printf ("\n"); } fprintf (stderr, "#### %s\n", line); output_length = 0; for (j = 0; j < nb_dirs; j++) { sprintf (command, "touch %s/%s; cp %s/%s %s/%s.%s\n", dir[j], line, dir[j], line, output, line, suffix[j]); protected_system (command); } continue; } exit (0); }