/* Written and copyrighted by Frans Faase, http://home.wxs.nl/~faase009. Can be used freely. NO WARRANTEES! */ #include #include #include #include typedef short int bool; #define TRUE (bool)1 #define FALSE (bool)0 #define MAX_FN 500 #define S_DATE 40 #define DATE_LEN 14 #define S_FN 54 #ifdef DEBUG #define DEBUG_P(P) fprintf(stderr, P) #define DEBUG_P1(P, S1) fprintf(stderr, P, S1) #define DEBUG_P2(P, S1, S2) fprintf(stderr, P, S1, S2) #define DEBUG_P3(P, S1, S2, S3) fprintf(stderr, P, S1, S2, S3) #define DEBUG_P4(P, S1, S2, S3, S4) fprintf(stderr, P, S1, S2, S3, S4) #define DEBUG_P5(P, S1, S2, S3, S4, S5) fprintf(stderr, P, S1, S2, S3, S4, S5) #else #define DEBUG_P(P) #define DEBUG_P1(P, S1) #define DEBUG_P2(P, S1, S2) #define DEBUG_P3(P, S1, S2, S3) #define DEBUG_P4(P, S1, S2, S3, S4) #define DEBUG_P5(P, S1, S2, S3, S4, S5) #endif #define DO_DEBUG_P(P) fprintf(stderr, P) #define DO_DEBUG_P1(P, S1) fprintf(stderr, P, S1) #define DO_DEBUG_P2(P, S1, S2) fprintf(stderr, P, S1, S2) #define DO_DEBUG_P3(P, S1, S2, S3) fprintf(stderr, P, S1, S2, S3) #define DO_DEBUG_P4(P, S1, S2, S3, S4) fprintf(stderr, P, S1, S2, S3, S4) #define DO_DEBUG_P5(P, S1, S2, S3, S4, S5) fprintf(stderr, P, S1, S2, S3, S4, S5) bool wildcard(w, s) char *w, *s; { DEBUG_P2("wildcard(%s,%s)\n", w, s); for (;;) { DEBUG_P2("%s %s\n", w, s); if (*s == '\0') return (*w == '\0' || !strcmp(w, "*")); if (*w == '?') { w++; s++; } else if (*w == '*') { if (w[1] == '\0' || wildcard(w + 1, s)) return TRUE; s++; } else if (*w == *s) { w++; s++; } else return FALSE; } } bool match_ignore(w1, w2, s) char *w1, *w2, *s; { DEBUG_P3("match_ignore(%s,%s,%s)\n", w1, w2, s); if (w2 == NULL) return wildcard(w1, s); else { int i; for (i = strlen(s) - 1; i > 0 && s[i] != '/'; i--); if (s[i] == '/') { bool r; s[i] = '\0'; r = wildcard(w1, s) && wildcard(w2, s + i + 1); s[i] = '/'; return r; } else return (!strcmp(w1, ".") || !strcmp(w1, "*")) && wildcard(w2, s); } } typedef struct ignore_T { struct ignore_T *next; char *w1, *w2; } ignore_t; ignore_t *ignores = NULL; void read_ignores(fignore) FILE *fignore; { ignore_t **ref = &ignores; char buffer[MAX_FN + 1]; { ignore_t *new = (ignore_t *)malloc(sizeof(ignore_t)); new->next = NULL; *ref = new; ref = &new->next; new->w1 = "*"; new->w2 = ".dt.*"; } while (!feof(fignore)) { int i = 0; char ch = (char)fgetc(fignore); while (!feof(fignore) && ch != '\n' && ch != '%' && ch != ' ') { if (i < MAX_FN) buffer[i++] = ch; ch = fgetc(fignore); } buffer[i] = 0; if (buffer[0] != 0) { ignore_t *new = (ignore_t *)malloc(sizeof(ignore_t)); new->next = NULL; *ref = new; ref = &new->next; new->w1 = (char *)malloc(strlen(buffer) + 1); strcpy(new->w1, buffer); while (!feof(fignore) && ch == ' ') ch = (char)fgetc(fignore); i = 0; while (!feof(fignore) && ch != '\n' && ch != '%' && ch != ' ') { if (i < MAX_FN) buffer[i++] = ch; ch = fgetc(fignore); } buffer[i] = '\0'; if (buffer[0] != '\0') { new->w2 = (char *)malloc(strlen(buffer) + 1); strcpy(new->w2, buffer); } else new->w2 = NULL; DEBUG_P2("ignore %s %s\n", new->w1, new->w2); } while (!feof(fignore) && ch != '\n') ch = fgetc(fignore); } } bool ignore(s) char *s; { ignore_t *ignore; for (ignore = ignores; ignore != NULL; ignore = ignore->next) if (match_ignore(ignore->w1, ignore->w2, s)) return TRUE; return FALSE; } void read_fn(f, b, fn, dt) FILE *f; char *b, **fn, **dt; { int i; char ch; if (f == NULL) { *b = '\0'; DEBUG_P("f == NULL\n"); return; } if (feof(f)) { *b = '\0'; DEBUG_P("feof(f)\n"); return; } i = 0; ch = (char)fgetc(f); while (!feof(f) && ch != '\n' && (i <= S_FN || (ch != '*' && ch != ' '))) { if (i < MAX_FN) b[i++] = ch; ch = (char)fgetc(f); } while (!feof(f) && ch != '\n') ch = (char)fgetc(f); b[i] = '\0'; if (i < S_FN) b[0] = '\0'; else { if (b[S_FN] == ' ') { *fn = b + S_FN + 1; *dt = b + S_DATE + 1; } else { *fn = b + S_FN; *dt = b + S_DATE; } } DEBUG_P1("Read: '%s'\n", b); } char *nms[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; int compare_time(char *t1, char *t2) { int y1, mo1, d1, h1, m1, y2, mo2, d2, h2, m2; time_t ti; struct tm *t; time(&ti); t = localtime(&ti); t1++; /* Yes, I know this is a fix */ t2++; DEBUG_P2("compare `%s' with `%s'\n", t1, t2); { int i; mo1 = 0; for (i = 0; i < 12; i++) if (!strncmp(t1, nms[i], 3)) { mo1 = i; break; } } if (t1[7] == ' ') { sscanf(t1 + 4, "%d %d", &d1, &y1); h1 = -1; m1 = 0; } else { sscanf(t1 + 4, "%d %d:%d", &d1, &h1, &m1); y1 = t->tm_year + 1900; if (mo1 > t->tm_mon + 1) y1--; } { int i; mo2 = 0; for (i = 0; i < 12; i++) if (!strncmp(t2, nms[i], 3)) { mo2 = i; break; } } if (t2[7] == ' ') { sscanf(t2 + 4, "%d %d", &d2, &y2); h2 = -1; m2 = 0; } else { sscanf(t2 + 4, "%d %d:%d", &d2, &h2, &m2); y2 = t->tm_year + 1900; if (mo2 > t->tm_mon + 1) y2--; } DEBUG_P5("%4d %2d %2d %2d:%2d\n", y1, mo1, d1, h1, m1); DEBUG_P5("%4d %2d %2d %2d:%2d\n", y2, mo2, d2, h2, m2); if (y1 < y2) return -1; if (y1 > y2) return 1; if (mo1 < mo2) return -1; if (mo1 > mo2) return 1; if (d1 < d2) return -1; if (d1 > d2) return 1; if (h1 == -1 || h2 == -1) return 0; if (h1 < h2) return -1; if (h1 > h2) return 1; if (m1 < m2) return -1; if (m1 > m2) return 1; return 0; } int main(argc, argv) int argc; char *argv[]; { FILE *fnew = fopen(".dt.new", "r"), *fin = fopen(".dt.in", "r"), *fignore = fopen(".dt.ignore", "r"), *fout = fopen(".dt.out", "w"), *fmake = fopen(".dt.make", "w"), *fdel = fopen(".dt.del", "w"); if (fnew == NULL) { printf("Cannot read: .dt.new\n"); return 1; } if (fout == NULL) { printf("Cannot write: .dt.out\n"); return 1; } if (fmake == NULL) { printf("Cannot write: .dt.make\n"); return 1; } if (fdel == NULL) { printf("Cannot write: .dt.del\n"); return 1; } fprintf(fmake, "tar -cf .dt.disk"); fprintf(fdel, "rm -i .dt.del"); if (fignore != NULL) { read_ignores(fignore); fclose(fignore); fignore = fopen(".dt.ignore", "a"); if (fignore == NULL) { printf("Cannot append: .dt.ignore\n"); return 1; } } else { fignore = fopen(".dt.ignore", "w"); if (fignore == NULL) { printf("Cannot write: .dt.ignore\n"); return 1; } } { char new_b[MAX_FN + 1], *new_fn, *new_date, in_b[MAX_FN + 1], *in_fn, *in_date; read_fn(fnew, new_b, &new_fn, &new_date); read_fn(fin, in_b, &in_fn, &in_date); while(*new_b != '\0') { DEBUG_P2("compare %s %s\n", new_fn, in_fn); if (new_b[0] == 'd' || ignore(new_fn)) { DEBUG_P("directory or ignore\n"); read_fn(fnew, new_b, &new_fn, &new_date); } else if (*in_b == '\0' || strcmp(new_fn, in_fn) < 0) { /* new file */ char ch; fprintf(stderr, "copy new file `%s' ? (y/n/i/d) : ", new_fn); ch = (char)fgetc(stdin); while (ch != 'n' && ch != 'y' && ch != 'i' && ch != 'd') ch = (char)fgetc(stdin); if (ch == 'y') { fprintf(fmake, " %s", new_fn); fprintf(fout, "%s\n", new_b); } else if (ch == 'd') { fprintf(fdel, " %s", new_fn); } else if (ch == 'i') { fprintf(fignore, "%s\n", new_fn); } else /* 'n' */ fprintf(fout, "%s\n", new_b); while (ch != '\n') ch = (char)fgetc(stdin); read_fn(fnew, new_b, &new_fn, &new_date); } else if (strcmp(new_fn, in_fn) > 0) { /* file deleted */ fprintf(stderr, "file `%s' has been deleted\n", in_fn); read_fn(fin, in_b, &in_fn, &in_date); } else { char ch; int c = compare_time(new_date, in_date); if (c > 0) { fprintf(stderr, "copy updated file `%s'\n", new_fn); fprintf(stderr, "was: %-12.12s new: %-12.12s ? (y/n/i/d) : ", in_date + 1, new_date + 1); ch = (char)fgetc(stdin); while (ch != 'n' && ch != 'y' && ch != 'i' && ch != 'd') ch = (char)fgetc(stdin); if (ch == 'y') { fprintf(fmake, " %s", new_fn); fprintf(fout, "%s\n", new_b); } else if (ch == 'd') { fprintf(fdel, " %s", new_fn); } else if (ch == 'i') { fprintf(fignore, "%s\n", new_fn); } else /* 'n' */ fprintf(fout, "%s\n", new_b); } else if (c < 0) { fprintf(stderr, "overwrite older file `%s'\n", new_fn); fprintf(stderr, "was: %-12.12s new: %-12.12s ? (o/n/i/d) : ", in_date + 1, new_date + 1); ch = (char)fgetc(stdin); while (ch != 'o' && ch != 'n' && ch != 'i' && ch != 'd') ch = (char)fgetc(stdin); if (ch == 'o') { fprintf(fmake, " %s", new_fn); fprintf(fout, "%s\n", new_b); } else if (ch == 'd') { fprintf(fdel, " %s", new_fn); } else if (ch == 'i') { fprintf(fignore, "%s\n", new_fn); } else /* 'n' */ fprintf(fout, "%s\n", new_b); } else fprintf(fout, "%s\n", new_b); read_fn(fnew, new_b, &new_fn, &new_date); read_fn(fin, in_b, &in_fn, &in_date); } } } if (fnew != NULL) fclose(fnew); if (fin != NULL) fclose(fin); if (fignore != NULL) fclose(fignore); if (fout != NULL) fclose(fout); if (fmake != NULL) fclose(fmake); if (fdel != NULL) fclose(fdel); return 0; }