/* Synchronize disk directory with current directory. Before this program is called the following command should have been executed: cd ll >.dd.unix mcd a:/ mdir >.dd.dos The file .dd.trans contains information about how the file names have to be translated between unix and dos. This is needed because dos file names are restricted to the 8.3 format. Working of the program: - reading the .dd.trans file into a table. - reading the .dd.unix file. For any new files not in .dd.trans ask whether it should be included. If yes, construct the dos name in the following manner: find the last extension, and take the first three characters of it. Process everything before the extension, by only takening [a-z][A-z][0-9] characters, up-to 8 characters. Check if this name already exists, if so, ask user for new name. (Suggest to modify last character, to make the name unique.) - reading the .dd.dos file. For any new file, ask for the unix file. (Suggest file, with modified extension e.g. htm is changed into html ??) - compare the date/times, and determine in which direction the files should be transfered. Ask user for confirmation. - generate commands for transfering the files, (or deleting them) - write the .dd.trans file (removing the files that are deleted). */ #include #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 #define NO_DEBUG #define INFO #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) #define MALLOC(T) (T *)malloc(sizeof(T)) #define SMALLOC(L) (char *)malloc((L)+1) #define STRCPY(D,S) D = SMALLOC(strlen(S)); strcpy(D,S) #define STATE_UNK 0 #define STATE_DEL 1 #define STATE_KEEP 2 typedef struct file_T { struct file_T *next; char *unix_name; bool ignore; bool unix_exists; int unix_state; int unix_year; int unix_month; int unix_day; int unix_hour; int unix_min; char dos_name[13]; bool dos_exists; int dos_state; int dos_year; int dos_month; int dos_day; int dos_hour; int dos_min; } file_t; file_t *files = NULL; void read_table() { FILE *f = fopen(".dd.trans", "r"); file_t **r_f = &files; char fn[MAX_FN + 1]; char ch; int i; DEBUG_P("read_table\n"); if (f == NULL) return; ch = (char)fgetc(f); while (!feof(f)) { file_t *new = MALLOC(file_t); new->next = NULL; new->unix_exists = FALSE; new->unix_state = STATE_UNK; new->dos_exists = FALSE; new->dos_state = STATE_UNK; i = 0; while (!feof(f) && ch != ' ' && ch != '\n') { if (i < MAX_FN) fn[i++] = ch; ch = (char)fgetc(f); } fn[i] = '\0'; DEBUG_P1("unix name: `%s'\n", fn); STRCPY(new->unix_name, fn); while (!feof(f) && ch == ' ') ch = (char)fgetc(f); new->dos_name[0] = '\0'; if (feof(f) || ch == '\n') { new->ignore = TRUE; } else { new->ignore = FALSE; i = 0; while (!feof(f) && ch != '.' && ch != '\n' && ch != ' ') { if (i < 8) new->dos_name[i++] = tolower(ch); ch = (char)fgetc(f); } new->dos_name[i++] = '.'; if (!feof(f) && ch == '.') { int e = 0; ch = (char)fgetc(f); while (!feof(f) && ch != '\n' && ch != ' ') { if (e < 3) { new->dos_name[i++] = tolower(ch); e++; } ch = (char)fgetc(f); } } if (new->dos_name[i-1] == '.') i--; new->dos_name[i] = '\0'; } DEBUG_P3("table `%s' `%s' %d\n", new->unix_name, new->dos_name, new->ignore); while (!feof(f) && ch != '\n') ch = (char)fgetc(f); if (!feof(f) && ch == '\n') ch = (char)fgetc(f); *r_f = new; r_f = &(new->next); } fclose(f); } void write_table() { file_t *file; FILE *f = fopen(".dd.trans", "w"); if (f == NULL) return; for (file = files; file != NULL; file = file->next) if ( file->unix_name != NULL && file->unix_state != STATE_DEL && file->unix_exists) { DEBUG_P3("%s %d %s|\n", file->unix_name, file->ignore, file->dos_name); fprintf(f, "%s", file->unix_name); if (!file->ignore) fprintf(f, " %s", file->dos_name); fprintf(f, "\n"); } fclose(f); } /* Output generated by ls -l: 12345678901234567890123456789012345678901234567890123456 00000000011111111112222222222333333333344444444445555555 total 86 drwxr-xr-x 2 faase users 1024 Feb 10 13:56 ./ drwxr-xr-x 20 faase users 2048 Feb 10 00:49 ../ -rw-r--r-- 1 faase users 208 Jan 12 14:48 almig.html -rw-r--r-- 1 faase users 166 Jan 12 14:33 attr.html -rw-r--r-- 1 faase users 204 Jan 12 14:48 beaut.html -rw-r----- 1 faase users 18680 Jan 15 10:37 essense.html -rw-r--r-- 1 faase users 208 Jan 12 14:48 etern.html -rw-r--r-- 1 faase users 224 Jan 12 14:50 uncha.html */ char *nms[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; void dos_of_unix_name(char *un, char *dn) { int l, i, j; l = strlen(un); for (i = 0; i < strlen(un); i++) if (un[i] == '.') l = i; j = 0; for (i = 0; i < l; i++) if (j < 8 && (isdigit(un[i]) || isalpha(un[i]) || un[i] == '_')) dn[j++] = tolower(un[i]); if (un[l] == '.') { dn[j++] = '.'; i++; for (; i < strlen(un) && i < l + 4; i++) if ((isdigit(un[i]) || isalpha(un[i]) || un[i] == '_')) dn[j++] = tolower(un[i]); } dn[j] = '\0'; DEBUG_P2("dos_of_unix_name(`%s', `%s');\n", un, dn); } void ask_for_dos_name(char *un, file_t *file) { char sdn[13]; bool found = FALSE; file_t *f; char ch; dos_of_unix_name(un, sdn); for (f = files; f != NULL; f = f->next) if (!strcmp(sdn, f->dos_name)) { found = TRUE; break; } for (;;) { if (!found) printf("New unix file: `%s', accept as `%s' (y/m/i/d) ? ", un, sdn); else printf("New unix file: `%s', accept (m/i/d) ? ", un); ch = (char)fgetc(stdin); if ((ch == 'y' && !found) || ch == 'm' || ch == 'i' || ch == 'd') { char sch = ch; while (sch != '\n') sch = (char)fgetc(stdin); break; } while (ch != '\n') ch = (char)fgetc(stdin); } file->unix_state = STATE_KEEP; file->dos_name[0] = '\0'; if (ch == 'y') strcpy(file->dos_name, sdn); else if (ch == 'i') file->ignore = TRUE; else if (ch == 'd') file->unix_state = STATE_DEL; else if (ch == 'm') { for (;;) { if (found) printf("DOS name `%s' already used for `%s'\n", sdn, f->unix_name); printf("DOS name `%s' ? ", sdn); ch = (char)fgetc(stdin); while (ch == ' ') ch = (char)fgetc(stdin); if (ch != '\n') { int i = 0; while (ch != '.' && ch != '\n' && ch != ' ') { if (i < 8) sdn[i++] = tolower(ch); DEBUG_P1("take %c", ch); ch = (char)fgetc(stdin); } sdn[i++] = '.'; if (ch == '.') { int e = 0; ch = (char)fgetc(stdin); while (ch != '\n' && ch != ' ') { if (e < 3) { sdn[i++] = tolower(ch); e++; DEBUG_P1("take %c", ch); } ch = (char)fgetc(stdin); } } sdn[i] = '\0'; DEBUG_P1("sdn: `%s'\n", sdn); } while (ch != '\n') ch = (char)fgetc(stdin); found = FALSE; for (f = files; f != NULL; f = f->next) if (!strcmp(sdn, f->dos_name)) { found = TRUE; break; } if (!found) break; } strcpy(file->dos_name, sdn); } DEBUG_P2("State: %d |%s|\n", file->dos_state, file->dos_name); } #define READ_2D(V) \ V = 0; \ if (isdigit(ch)) \ V = ch - '0'; \ ch = (char)fgetc(f); \ if (isdigit(ch)) \ V = 10 * V + ch - '0'; \ ch = (char)fgetc(f); #define READ_2MD(V) \ if (isdigit(ch)) \ V = 10 * V + ch - '0'; \ ch = (char)fgetc(f); \ if (isdigit(ch)) \ V = 10 * V + ch - '0'; \ ch = (char)fgetc(f); #define READ_4D(V) READ_2D(V) READ_2MD(V) void read_unix() { FILE *f = fopen(".dd.unix", "r"); char fn[MAX_FN + 1]; int year, month, day, hour, min; char ch; if (f == NULL) return; ch = (char)fgetc(f); while (!feof(f)) { if (ch == '-') { char nm[4]; int i; file_t **r_f = &files; for (i = 1; i < 42; i++) ch = (char)fgetc(f); if (ch == ' ') ch = (char)fgetc(f); for (i = 0; i < 3; i++) { nm[i] = ch; ch = (char)fgetc(f); } nm[3] = '\0'; month = 0; for (i = 0; i < 12; i++) if (!strcmp(nm, nms[i])) month = i+1; DEBUG_P2("Month: %s %d\n", nm, month); ch = (char)fgetc(f); DEBUG_P1("First of day: %c\n", ch); READ_2D(day) ch = (char)fgetc(f); DEBUG_P1("First of hour: %c\n", ch); if (ch != ' ') { year = 0; READ_2D(hour) ch = (char)fgetc(f); READ_2D(min) } else { ch = (char)fgetc(f); READ_4D(year) hour = 0; min = 0; } ch = (char)fgetc(f); i = 0; while (!feof(f) && ch != '\n') { if (i < MAX_FN) fn[i++] = ch; ch = (char)fgetc(f); } fn[i] = '\0'; DEBUG_P1("unix fn: `%s'\n", fn); while (*r_f != NULL && strcmp((*r_f)->unix_name, fn)) r_f = &(*r_f)->next; if (*r_f == NULL) { (*r_f) = MALLOC(file_t); (*r_f)->next = NULL; (*r_f)->dos_exists = FALSE; (*r_f)->dos_state = STATE_UNK; (*r_f)->dos_name[0] = '\0'; ask_for_dos_name(fn, (*r_f)); STRCPY((*r_f)->unix_name, fn); } (*r_f)->unix_exists = TRUE; (*r_f)->unix_year = year; (*r_f)->unix_month = month; (*r_f)->unix_day = day; (*r_f)->unix_hour = hour; (*r_f)->unix_min = min; } while (!feof(f) && ch != '\n') ch = (char)fgetc(f); if (!feof(f)) ch = (char)fgetc(f); } fclose(f); } /* Output generated by: mdir 12345678901234567890123456789012345678901234567890123456 00000000011111111112222222222333333333344444444445555555 Volume in drive A has no label Directory for A:/KG . 2-10-96 8:58p .. 2-10-96 8:58p ALMIG HTM 533 2-10-96 1:47p ATTR HTM 180 1-12-96 2:33p BEAUT HTM 218 1-12-96 2:48p */ void ask_for_unix_name(char *dn, file_t *file) { char sun[MAX_FN + 1]; bool found = FALSE; file_t *f; char ch; strcpy(sun, dn); if (strlen(sun) > 4 && !strcmp(sun + strlen(sun) - 4, ".htm")) strcat(sun, "l"); for (f = files; f != NULL; f = f->next) if (!strcmp(sun, f->unix_name)) { found = TRUE; break; } for (;;) { if (!found) printf("New DOS file: `%s', accept as `%s' (y/m/d) ? ", dn, sun); else if (f->ignore) printf("New DOS file: `%s', overwrite `%s' (o/m/d) ? ", dn, sun); else printf("New DOS file: `%s', accept (m/d) ? ", dn); ch = (char)fgetc(stdin); if ( (!found ? ch == 'y' : (f->ignore && ch == 'o')) || ch == 'm' || ch == 'd') { char sch = ch; while (sch != '\n') sch = (char)fgetc(stdin); break; } while (ch != '\n') ch = (char)fgetc(stdin); } file->dos_state = STATE_KEEP; if (ch == 'd') file->dos_state = STATE_DEL; else if (ch == 'y') { STRCPY(file->unix_name, sun); } else if (ch == 'o') { strcpy(file->dos_name, dn); file->ignore = FALSE; } else if (ch == 'm') { for (;;) { if (found) if (f->ignore) printf("Unix name `%s' is restricted to unix.\n", sun); else printf("Unix name `%s' already used for `%s'\n", sun, f->dos_name); printf("unix name: `%s' ? ", sun); ch = (char)fgetc(stdin); while (ch == ' ') ch = (char)fgetc(stdin); if (ch != '\n') { int i = 0; while (ch != '\n' && ch != ' ') { if (i < MAX_FN) sun[i] = tolower(ch); ch = (char)fgetc(stdin); } sun[i] = '\0'; } while (ch != '\n') ch = (char)fgetc(stdin); found = FALSE; for (f = files; f != NULL; f = f->next) if (!strcmp(sun, f->unix_name)) { found = TRUE; break; } if (!found) break; } STRCPY(file->unix_name, sun); } } void read_dos() { FILE *f = fopen(".dd.dos", "r"); char fn[13]; int year, month, day, hour, min; char ch; int i; if (f == NULL) return; ch = (char)fgetc(f); for (i = 0; i < 3 && !feof(f); i++) { while (!feof(f) && ch != '\n') ch = (char)fgetc(f); if (!feof(f)) ch = (char)fgetc(f); } while (!feof(f)) { int j; char fch; j = 0; for (i = 0; i < 9; i++) { if (ch != ' ') fn[j++] = tolower(ch); ch = (char)fgetc(f); } fn[j++] = '.'; for (i = 0; i < 3; i++) { if (ch != ' ') fn[j++] = tolower(ch); ch = (char)fgetc(f); } if (fn[j-1] == '.') j--; fn[j] = '\0'; fch = ' '; for (i = 0; i < 15; i++) { if (ch != ' ' && fch == ' ') fch = ch; ch = (char)fgetc(f); } if (fch != '<' && fch != 'e') { file_t **r_f = &files; /* found file */ READ_2D(month) ch = (char)fgetc(f); READ_2D(day) ch = (char)fgetc(f); READ_2D(year) year += 1900; ch = (char)fgetc(f); ch = (char)fgetc(f); READ_2D(hour) ch = (char)fgetc(f); READ_2D(min) if (ch == 'p' && hour < 12) hour += 12; if (ch == 'a' && hour == 12) hour -= 12; while (*r_f != NULL && strcmp((*r_f)->dos_name, fn)) r_f = &(*r_f)->next; if (*r_f == NULL) { (*r_f) = MALLOC(file_t); (*r_f)->next = NULL; (*r_f)->unix_exists = FALSE; (*r_f)->unix_state = STATE_UNK; (*r_f)->unix_name = NULL; ask_for_unix_name(fn, (*r_f)); strcpy((*r_f)->dos_name, fn); } (*r_f)->dos_exists = TRUE; (*r_f)->dos_year = year; (*r_f)->dos_month = month; (*r_f)->dos_day = day; (*r_f)->dos_hour = hour; (*r_f)->dos_min = min; } while (!feof(f) && ch != '\n') ch = (char)fgetc(f); if (!feof(f)) ch = (char)fgetc(f); } } void compare() { FILE *f = fopen(".dd.do", "w"); file_t *file; time_t ti; struct tm *t; time(&ti); t = localtime(&ti); if (f == NULL) return; for (file = files; file != NULL; file = file->next) { int eq = 0; /* dos < unix */ #ifdef DEBUG if (file->unix_exists) printf("Unix: %4d-%2d-%2d %2d:%2d", file->unix_year, file->unix_month, file->unix_day, file->unix_hour, file->unix_min); else printf("Unix: - - : "); printf(" %c %c %s\n", file->unix_state == STATE_UNK ? '?' : file->unix_state == STATE_DEL ? 'd' : 'k', file->ignore ? 'i' : '.', file->unix_name); if (file->dos_exists) printf("DOS: %4d-%2d-%2d %2d:%2d", file->dos_year, file->dos_month, file->dos_day, file->dos_hour, file->dos_min); else printf("DOS: - - : "); printf(" %c %s\n", file->dos_state == STATE_UNK ? '?' : file->dos_state == STATE_DEL ? 'd' : 'k', file->dos_name); #endif if ( file->unix_exists && !file->dos_exists && !file->ignore && file->unix_state == STATE_UNK) { /* Ask whether we should delete unix file */ char ch; for (;;) { printf("Delete unix file `%s' (d/k/i) : ", file->unix_name); ch = (char)fgetc(stdin); if (ch == 'd') { file->unix_state = STATE_DEL; while (ch != '\n') ch = (char)fgetc(stdin); break; } else if (ch == 'k') { file->unix_state = STATE_KEEP; while (ch != '\n') ch = (char)fgetc(stdin); break; } else if (ch == 'i') { file->ignore = TRUE; while (ch != '\n') ch = (char)fgetc(stdin); break; } while (ch != '\n') ch = (char)fgetc(stdin); } } if ( !file->unix_exists && file->dos_exists && file->dos_state == STATE_UNK) { /* Ask whether we should delete dos file */ char ch; for (;;) { printf("Delete DOS file `%s' (d/k) : ", file->dos_name); ch = (char)fgetc(stdin); if (ch == 'd') { file->dos_state = STATE_DEL; break; } else if (ch == 'k') { file->dos_state = STATE_KEEP; break; } while (ch != '\n') ch = (char)fgetc(stdin); } } if (file->dos_state == STATE_DEL) { DEBUG_P1("mdel %s\n", file->dos_name); #ifdef INFO fprintf(f, "echo \"Delete DOS file %s\"\n", file->dos_name); #endif fprintf(f, "mdel a:%s\n", file->dos_name); } if (file->unix_state == STATE_DEL) { DEBUG_P1("rm %s\n", file->unix_name); #ifdef INFO fprintf(f, "echo \"Delete unix file %s\"\n", file->unix_name); #endif fprintf(f, "rm -i %s\n", file->unix_name); } if ( file->unix_exists && file->unix_state != STATE_DEL && !file->ignore && !file->dos_exists) { #ifdef INFO fprintf(f, "echo \"Copy new unix file %s to DOS file %s\"\n", file->unix_name, file->dos_name); #endif eq = -1; } else if ( file->dos_exists && file->dos_state != STATE_DEL && !file->unix_exists && !file->ignore) { #ifdef INFO fprintf(f, "echo \"Copy new DOS file %s to unix file %s\"\n", file->dos_name, file->unix_name); #endif eq = 1; } else if ( file->dos_exists && file->dos_state != STATE_DEL && file->unix_exists && file->unix_state != STATE_DEL && !file->ignore) { /* compare the times: */ bool compare_all; DEBUG_P2("Year: %d Mon: %d\n", t->tm_year, t->tm_mon); if (file->unix_year == 0) { file->unix_year = t->tm_year + 1900; if (file->unix_month > t->tm_mon + 1) file->unix_year--; compare_all = TRUE; } else compare_all = FALSE; #ifdef DEBUG printf("Unix: %4d-%2d-%2d %2d:%2d\n", file->unix_year, file->unix_month, file->unix_day, file->unix_hour, file->unix_min); printf("DOS: %4d-%2d-%2d %2d:%2d", file->dos_year, file->dos_month, file->dos_day, file->dos_hour, file->dos_min); #endif if (file->dos_year < file->unix_year) eq = -1; else if (file->dos_year > file->unix_year) eq = 1; if (eq == 0) if (file->dos_month < file->unix_month) eq = -1; else if (file->dos_month > file->unix_month) eq = 1; if (eq == 0) if (file->dos_day < file->unix_day) eq = -1; else if (file->dos_day > file->unix_day) eq = 1; if (eq == 0 && compare_all) if (file->dos_hour < file->unix_hour) eq = -1; else if (file->dos_hour > file->unix_hour) eq = 1; if (eq == 0 && compare_all) if (file->dos_min < file->unix_min) eq = -1; else if (file->dos_min > file->unix_min) eq = 1; #ifdef INFO if (eq < 0) fprintf(f, "echo \"Unix file %s newer then DOS file %s\"\n", file->unix_name, file->dos_name); if (eq > 0) fprintf(f, "echo \"DOS file %s newer then unix file %s\"\n", file->dos_name, file->unix_name); #endif } if (eq < 0) { DEBUG_P2("mcopy -tm %s a:%s\n", file->unix_name, file->dos_name); fprintf(f, "mcopy -tm %s a:%s\n", file->unix_name, file->dos_name); } if (eq > 0) { DEBUG_P2("mcopy -tm a:%s %s\n", file->dos_name, file->unix_name); fprintf(f, "mcopy -tm a:%s %s\n", file->dos_name, file->unix_name); } #ifdef DEBUG fgetc(stdin); #endif } } void main(argc, argv) int argc; char *argv[]; { read_table(); read_unix(); read_dos(); compare(); write_table(); }