/******************************************************/ /* EasyBackup, Backup.c (c)1989 Oliver Enseling */ /******************************************************/ extern void EndBackup(), UserRequest(); #include "support.c" long CompDate[3]; /* DateStamp zum vergleichen */ int Drive; /* Nummer des selektierten * Disk-Drives */ char *Source; /* Source-Directorypath */ char Buffer[FMSIZE]; /* Hilfspuffer zum * "Zusammenbau" des ganzen * filenamens */ char DirPath[FMSIZE] = ""; /* aktueller Directorypath */ BOOL FoundInter = FALSE, FoundArchiviere = FALSE, FoundArchivstatus = FALSE; FILE *ListFile = NULL; /* Variablen */ LONG TrackNr, ByteNr; /* NewDisk: neue Diskette anfordern */ LONG DiskNr; void NewDisk() { BOOL diskcorrect; char buf[5]; TrackDiskBlock->iotd_Req.io_Length = 0; /* Drive-Motor aus */ DeviceCommand(TrackDiskBlock, (UWORD) TD_MOTOR); DiskNr++; do { setmem(buf, 5, 0); Beep(880, 25, 64); #ifdef DEUTSCH printf("Neue Kopie-Diskette #%d in Laufwerk DF%d: einlegen\n", DiskNr, Drive); #else printf("Insert new backup disk #%d in drive DF%d:", DiskNr, Drive); #endif WaitDisk(TrackDiskBlock); ReadTrack(TrackDiskBlock, &TrackBuffer[TRACK_SIZE], LabelBuffer, 0); strncpy(buf, &TrackBuffer[TRACK_SIZE], 4); if (buf[0] != 'B') diskcorrect = TRUE; else { int dnr = atoi(buf + 1); if (dnr < DiskNr && dnr > 0) { #ifdef DEUTSCH printf("Achtung Kopie-Diskette #%d wird überschrieben !!!\n", dnr); printf("Diskette wechseln ? "); #else printf("Old backup disk #%d is being overwritten\n", dnr); printf("Change disk ? "); #endif diskcorrect = FileAbfrage(); } else diskcorrect = TRUE; } } while (!diskcorrect); #ifdef DEUTSCH printf("Diskette OK\n"); #else printf("Disk OK\n"); #endif sprintf(TrackBuffer, "B%d%d%d", DiskNr / 100 % 10, DiskNr / 10 % 10, DiskNr % 10); setmem(&TrackBuffer[4], 4, 0xff); TrackNr = 0; ByteNr = 0; PrintDisk(DiskNr); PrintTrack(0); } /* FormatTrack: einen Track formatieren */ void FormatTrack(db, nr, buf) struct IOExtTD *db; LONG nr; BYTE *buf; { PrintTrack((nr + 1) % MAX_TRACKS); FOREVER { DeviceCommand(db, (UWORD) TD_CHANGENUM); db->iotd_Count = db->iotd_Req.io_Actual; db->iotd_Req.io_Data = (APTR) buf; db->iotd_Req.io_Length = (ULONG) TRACK_SIZE; db->iotd_Req.io_Offset = nr * TRACK_SIZE; DeviceCommand(db, (UWORD) ETD_FORMAT); if (db->iotd_Req.io_Error) { #ifdef DEUTSCH printf("Fehler beim Schreiben auf Spur #%d:\n%s\n", nr, TrackDiskError((LONG) db->iotd_Req.io_Error)); #else printf("Error writing track #%d:\n%s\n", nr, TrackDiskError((LONG) db->iotd_Req.io_Error)); #endif UserRequest(); } else break; } } /* RawPutByte: ein Byte in ein Backup schreiben */ void RawPutByte(b) BYTE b; { ByteNr++; if (ByteNr >= TRACK_SIZE) { TrackNr++; if (TrackNr >= MAX_TRACKS) { #ifdef DEUTSCH printf("Diskette voll\n"); #else printf("Disk full\n"); #endif NewDisk(); } else if (TrackNr != MAX_TRACKS - 1) ByteNr = 0; else { strcpy(&TrackBuffer[8], DirPath); ByteNr = strlen(&TrackBuffer[8]) + 1 + 8; } FormatTrack(TrackDiskBlock, TrackNr, TrackBuffer); } TrackBuffer[ByteNr] = b; } /* Bytes mit Dateiendemarkierung kodieren */ void EncodeByte(b) char b; { if (b == DATEIENDEMARKE) { RawPutByte(DATEIENDEMARKE); RawPutByte(DATEIENDEMARKE); } else RawPutByte(b); } /* RawWrite: Anzahl Bytes auf das Backup schreiben */ void RawWrite(buf, len) BYTE *buf; LONG len; { LONG i; for (i = 0; i < len; i++) EncodeByte(buf[i]); } /* * ByteCount: Anzahl der aufeinanderfolgenden gleichen Bytes * ermitteln */ LONG ByteCount(begin, max) UBYTE *begin, *max; { int count; UBYTE b; b = *begin; for (count = 0L; count < 255L; count++) if ((begin[count] != b) || ((UBYTE *) (begin + count) > max)) break; return (count); } /* * EndBackup: Backup beenden / letzten Buffer schreiben + Endmarke * setzen Drive-Motor ausschalten */ void EndBackup() { LONG diskfull; diskfull = (TrackNr + 1) * TRACK_SIZE + ByteNr; RawPutByte(ID_ENDDIR); ByteNr = TRACK_SIZE - 1; RawPutByte((BYTE) - 1); ReadTrack(TrackDiskBlock, TrackBuffer, LabelBuffer, 0); memcpy(&TrackBuffer[4], (char *) &diskfull, 4); FormatTrack(TrackDiskBlock, 0, TrackBuffer); TrackDiskBlock->iotd_Req.io_Length = 0; /* Drive-Motor aus */ DeviceCommand(TrackDiskBlock, (UWORD) TD_MOTOR); } /* * BackupFile: ein File überprüfen, ggf. packen und auf die * BackupDisk schreiben */ BOOL BackupFile(path, fib) char *path; struct FileInfoBlock *fib; { LONG ssize = fib->fib_Size; int file; char *fn = fib->fib_FileName; ConcatPath(Buffer, Source, path); if (datecmp((long *) &fib->fib_Date, CompDate) < 0) { if (FoundArchivstatus && (fib->fib_Protection & FIBF_ARCHIVE)) return (TRUE); #ifdef DEUTSCH printf("Kopie für \033[33m%s\033[0m %d Bytes ... ", Buffer, fib->fib_Size); #else printf("Backup for \033[33m%s\033[0m %d Bytes ... ", Buffer, fib->fib_Size); #endif if (FoundInter) if (!FileAbfrage()) return (TRUE); RawPutByte(ID_FILE); RawWrite(fn, strlen(fn) + 1); RawWrite((BYTE *) & fib->fib_Protection, sizeof(fib->fib_Protection)); if (FoundArchiviere) { fib->fib_Protection |= FIBF_ARCHIVE; SetProtection(Buffer, fib->fib_Protection); } RawWrite((BYTE *) & fib->fib_Date, sizeof(fib->fib_Date)); RawWrite(fib->fib_Comment, strlen(fib->fib_Comment) + 1); if (ListFile) fprintf(ListFile, "%8d%5d%5d %-51s%9d\n", DiskNr, (TrackNr + 1) / 2, (TrackNr + 1) % 2, path, ssize); if (ssize > 0) { if ((file = open(Buffer, O_RDONLY, 0)) != -1) { LONG remain; for (remain = ssize; remain > BUFFER_SIZE; remain -= BUFFER_SIZE) { read(file, FileBuffer, BUFFER_SIZE); RawWrite(FileBuffer, BUFFER_SIZE); } read(file, FileBuffer, remain); RawWrite(FileBuffer, remain); close(file); printf("OK\n"); } else { #ifdef DEUTSCH printf("Lesefehler, DOS-Fehlernummer: %d\n", _OSERR); #else poserr(Buffer); #endif UserRequest(); } RawPutByte(DATEIENDEMARKE); return ((BOOL) (file > 0)); } else { #ifdef DEUTSCH printf("Leere Datei --> 0 Bytes\n"); #else printf("Empty file --> 0 Bytes\n"); #endif RawPutByte(DATEIENDEMARKE); return (TRUE); } } return (TRUE); } /* ein Verzeichnis "backuppen" */ BOOL BackupDir(path, fib) char *path; struct FileInfoBlock *fib; { char *dn = fib->fib_FileName; if (datecmp((long *) &fib->fib_Date, CompDate) >= 0) return (FALSE); if (FoundArchivstatus && (fib->fib_Protection & FIBF_ARCHIVE)) return (FALSE); strcpy(DirPath, path); ConcatPath(Buffer, Source, path); if (datecmp((long *) &fib->fib_Date, CompDate) < 0) { #ifdef DEUTSCH printf("Verzeichnis \033[33;2m%s\033[0m", Buffer); #else printf("Directory \033[33;2m%s\033[0m", Buffer); #endif if (FoundInter) { if (!FileAbfrage()) return (FALSE); } else printf("\n"); RawPutByte(ID_DIR); RawWrite(dn, strlen(dn) + 1); return (TRUE); } else return (FALSE); } /* BackupEndDir: ENDE-Markierung für ein Verzeichnis "backuppen" */ void BackupEndDir() { RawPutByte(ID_ENDDIR); } /* BackupTree: Verzeichnisbaum rekursiv backuppen */ BOOL BackupTree(s) char *s; { struct FileInfoBlock *fib; BOOL ok = TRUE; LONG err; char path[FMSIZE]; BPTR lock; ConcatPath(Buffer, Source, s); if (fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR | MEMF_CHIP)) { if (lock = Lock(Buffer, ACCESS_READ)) { if (Examine(lock, fib)) { while (ok && ExNext(lock, fib)) { ConcatPath(path, s, fib->fib_FileName); if (fib->fib_DirEntryType > 0) { if (BackupDir(path, fib)) { ok = BackupTree(path); BackupEndDir(); } } else ok = BackupFile(path, fib); } } UnLock(lock); } FreeMem(fib, sizeof(struct FileInfoBlock)); } else { ok = FALSE; #ifdef DEUTSCH printf("Nicht genügend Speicher für den FileInfoBlock !!!\n"); #else printf("Not enough memory for FileInfoBlock\n"); #endif } if (err = IoErr()) if (!(ok = (err == ERROR_NO_MORE_ENTRIES))) { #ifdef DEUTSCH printf("Fehler beim Lesen des Verzeichnisses.\n" "DOS-Fehlernummer:%4d\n", err); #else printf("Error reading directory.\n" "DOS-Error:%4d\n", err); #endif UserRequest(); } return (ok); } /* Umwandlung von String nach DateStamp */ BYTE MonthDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; LONG LeapYears = 0x44444444; BOOL StrToDs(s, ds) char *s; struct DateStamp *ds; { int i, d = atoi(s), m = atoi(&s[3]), y = atoi(&s[6]) - 78; if ((d > 0) && (m > 0) && (y >= 0)) { for (i = 0; i < y; i++) ds->ds_Days += LeapYears & (1 << i) ? 366 : 365; for (i = 0; i < m - 1; i++) ds->ds_Days += MonthDays[i]; ds->ds_Days += d - 1 + ((LeapYears & (1 << y)) && (m > 2) ? 1 : 0); return (TRUE); } return (FALSE); } /* Hauptprogramm: Parameter parsen, Error-Messages ausgeben */ void main(argc, argv) int argc; char **argv; { BOOL foundfrom = FALSE, foundto = FALSE, foundsince = FALSE, foundappend = FALSE, foundliste = FALSE; char *dest, *date, *listname; int i; FILE *file; printf("EasyBackup V1.0, Backup ©1990 Oliver Enseling\n\n"); for (i = 1; i < argc; i++) { #ifdef DEUTSCH if (stricmp(argv[i], "VON") == 0) #else if (stricmp(argv[i], "FROM") == 0) #endif { foundfrom = TRUE; i++; Source = argv[i]; } else { #ifdef DEUTSCH if (stricmp(argv[i], "NACH") == 0) #else if (stricmp(argv[i], "TO") == 0) #endif { foundto = TRUE; i++; dest = argv[i]; } else { #ifdef DEUTSCH if (stricmp(argv[i], "SEIT") == 0) #else if (stricmp(argv[i], "SINCE") == 0) #endif { foundsince = TRUE; i++; date = argv[i]; } else { #ifdef DEUTSCH if (stricmp(argv[i], "ERWEITERN") == 0) #else if (stricmp(argv[i], "APPEND") == 0) #endif { foundappend = TRUE; i++; DiskNr = atoi(argv[i]); if (DiskNr < 1) DiskNr = 1; } else { #ifdef DEUTSCH if (stricmp(argv[i], "INTERAKTIV") == 0) #else if (stricmp(argv[i], "QUERY") == 0) #endif { FoundInter = TRUE; } else { #ifdef DEUTSCH if (stricmp(argv[i], "LISTE") == 0) #else if (stricmp(argv[i], "LIST") == 0) #endif { foundliste = TRUE; i++; listname = argv[i]; } else { #ifdef DEUTSCH if (stricmp(argv[i], "ARCHIVIERE") == 0) #else if (stricmp(argv[i], "ARCHIVATE") == 0) #endif { FoundArchiviere = TRUE; } else { #ifdef DEUTSCH if (stricmp(argv[i], "ARCHIVSTATUS") == 0) #else if (stricmp(argv[i], "CHECKARCHIVE") == 0) #endif { FoundArchivstatus = TRUE; } else { if (!foundfrom) { Source = argv[i]; foundfrom = TRUE; } else { if (!foundto) { dest = argv[i]; foundto = TRUE; } #ifdef DEUTSCH else printf("Parameter \033[32m%s\033[31m wird ignoriert !\n", argv[i]); #else else printf("Argument \033[32m%s\033[31m ignored\n", argv[i]); #endif } } } } } } } } } } if (!(foundfrom && foundto)) { #ifdef DEUTSCH printf("Syntax: Backup [VON] [NACH] [SEIT |ZULETZT]\n" " [ERWEITERN ] [INTERAKTIV] [LISTE ]\n" " [ARCHIVIERE] [ARCHIVSTATUS]\n" " ver ------ Das zu kopierende Verzeichnis\n" " laufwerk - Das Laufwerk mit dem gearbeitet wird\n" " datum ---- Das Datum von dem aus alle zu einem späteren\n" " Zeitpunkt erstellten oder veränderten Dateien\n" " kopiert werden, das Format: DD MM YY.\n" " Es kann ZULETZT eingegeben werden um das\n" " Datum des letzten Aufrufes von BACKUP zu\n" " verwenden.\n" " disk ----- Die Nummer der Kopie-Diskette, ab der eine\n" " Sichertheitskopie erweitert werden soll, wenn\n" " die ERWEITERN-Option benutzt wird\n" " listfile - Name der Datei für das Backup-Verzeichniss\n" "\n" " Die Schlüsselwörter VON und NACH können weggelassen werden.\n"); #else printf("Usage: Backup [FROM] [TO] [SINCE |LAST]\n" " [APPEND ] [QUERY] [LIST ]\n" " dir ------ Directory, which is being backed up\n" " drive ---- Disk-drive for backup-disks\n" " date ----- only files created later than are being\n" " backed up\n" " disknr --- Number of disk to start an incremental backup\n" " listfile - Filename for listing file\n"); #endif CloseAll(1); } Drive = -1; if (stricmp("DF0:", dest) == 0) Drive = 0; if (stricmp("DF1:", dest) == 0) Drive = 1; if (stricmp("DF2:", dest) == 0) Drive = 2; if (stricmp("DF3:", dest) == 0) Drive = 3; if (Drive < 0) { #ifdef DEUTSCH printf("Kein Laufwerk %s\n", dest); #else printf("Not a disk drive %s\n", dest); #endif CloseAll(5); } if (foundsince) { #ifdef DEUTSCH if (stricmp(date, "ZULETZT") == 0) #else if (stricmp(date, "LAST") == 0) #endif { if (file = fopen(CONFIG_NAME, "r")) { fread((char *) CompDate, 1, sizeof(CompDate), file); fclose(file); } #ifdef DEUTSCH else printf("Altes Datum kann nicht gelesen werden.\n" "Es wird eine komplette Sicherheitskopie erstellt.\n"); #else else printf("Error reading old date\n" "Doing complete backup instead\n"); #endif } else if (!StrToDs(date, (struct DateStamp *) CompDate)) { #ifdef DEUTSCH printf("Falsches Datumsformat !!!\n"); #else printf("Wrong date format\n"); #endif CloseAll(5); } } OpenAll(Drive); if (foundappend) { LONG dnr, pos; do { do { char buf[5]; buf[4] = 0; TrackDiskBlock->iotd_Req.io_Length = 0; DeviceCommand(TrackDiskBlock, (UWORD) TD_MOTOR); #ifdef DEUTSCH printf("Kopie-Diskette #%d in Laufwerk DF%d: einlegen\n", DiskNr, Drive); #else printf("Insert backup disk #%d in drive DF%d:\n", DiskNr, Drive); #endif WaitDisk(TrackDiskBlock); ReadTrack(TrackDiskBlock, TrackBuffer, LabelBuffer, 0); strncpy(buf, TrackBuffer, 4); if (buf[0] != 'B') { #ifdef DEUTSCH printf("Keine Kopie-Diskette !!!\n"); #else printf("Not a backup disk\n"); #endif UserRequest(); dnr = 0; } else { dnr = atoi(buf + 1); if (dnr != DiskNr) printf("Falsche Diskette #%d !!!\n", dnr); } } while (dnr != DiskNr); pos = ((LONG *) TrackBuffer)[1]; if (pos == -1) { #ifdef DEUTSCH printf("Diskette voll\n"); #else printf("Disk full\n"); #endif DiskNr++; } } while (pos == -1); TrackBuffer[4] = TrackBuffer[5] = TrackBuffer[6] = TrackBuffer[7] = 0xff; FormatTrack(TrackDiskBlock, 0, TrackBuffer); TrackNr = pos / TRACK_SIZE; ByteNr = pos % TRACK_SIZE - 1; ReadTrack(TrackDiskBlock, TrackBuffer, LabelBuffer, TrackNr + 1); } else { NewDisk(); TrackBuffer[8] = 0; ByteNr = 8; } TrackNr--; if (foundliste) { if (ListFile = fopen(listname, "w")) { unsigned char clock[8]; char time[9]; #ifndef DEUTSCH char date[20]; #endif fprintf(ListFile, "EasyBackup V1.0 ©1990 Oliver Enseling\n"); getclk(clock); stptime(time, 2, clock); #ifdef DEUTSCH fprintf(ListFile, "Verzeichnis der Sicherheitskopie %d.%d.%d %s\n", (int) clock[3], (int) clock[2], 1980 + clock[1], time); #else stpdate(date, 5, clock); fprintf(ListFile, "Backup directory %s %s\n", date, time); #endif fprintf(ListFile, "=========================================" "========================================\n"); #ifdef DEUTSCH fprintf(ListFile, "Diskette Spur Kopf Dateiname " " Länge\n"); #else fprintf(ListFile, " Disk Track Head Filename " " Length\n"); #endif fprintf(ListFile, "-----------------------------------------" "----------------------------------------\n"); } #ifdef DEUTSCH else printf("Listfile-Error: %d\n", _OSERR); #else else poserr("ListFile"); #endif } if (BackupTree("")) { DateStamp(CompDate); if (file = fopen(CONFIG_NAME, "w")) { fwrite((char *) CompDate, 1, sizeof(CompDate), file); fclose(file); } #ifdef DEUTSCH printf("Sicherheitskopie komplett.\n"); #else printf("Backup complete\n"); #endif } #ifdef DEUTSCH else printf("Sicherheitskopie abgebrochen.\n"); #else else printf("Backup aborted\n"); #endif if (ListFile) fclose(ListFile); CloseAll(0); }