/*************************************************/ /* EasyBackup, Support.c (c)1989 Oliver Enseling */ /*************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TRACK_SIZE (11 * TD_SECTOR) #define LABEL_SIZE (11 * 16) #define MAX_TRACKS 160 #define MAX_SECTORS (11 * MAX_TRACKS) #define CONFIG_NAME "S:EasyBackup.config" #define BUFFER_SIZE (1024) /* 1K File Buffer */ #define DATEIENDEMARKE '£' /* empirisch sehr wenig * vorkommendes Zeichen */ #define ID_FILE 0 #define ID_DIR 1 #define ID_ENDDIR 2 struct NewWindow TrackNW = {20, 20, 200, 50, 0, 1, NULL, SMART_REFRESH, NULL, NULL, (UBYTE *) "EasyBackup Disk-Status", NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN}; struct Window *TrackWin = NULL; struct IntuitionBase *IntuitionBase; extern int _OSERR; BYTE *TrackBuffer, *LabelBuffer, *FileBuffer; struct IOExtTD *TrackDiskBlock; /* MakeDB: Device-Block anlegen und initialisieren */ void * MakeDB(len) LONG len; { struct MsgPort *p; APTR req; if (!(p = (struct MsgPort *) CreatePort(0L, 0L))) return (NULL); if (!(req = (APTR) CreateExtIO(p, len))) { DeletePort(p); return (NULL); } return (req); } /* FreeDB: Device-Block freigeben */ void FreeDB(req) struct IORequest *req; { if (req != 0L) { if (req->io_Message.mn_ReplyPort != 0L) DeletePort(req->io_Message.mn_ReplyPort); DeleteExtIO(req); } } /* InitDevice: Device öffnen und initialisieren */ BOOL InitDevice(name, unit, req, fl, len) char *name; LONG unit; struct IORequest **req; ULONG fl, len; { if (len != 0L) if (!(*req = MakeDB(len))) return (FALSE); if (OpenDevice(name, unit, *req, fl)) return (FALSE); else return (TRUE); } /* ExitDevice: Device schließen und Device-Block freigeben */ void ExitDevice(req) struct IORequest *req; { if (req != 0L) { if (req->io_Message.mn_ReplyPort != 0L) DeletePort(req->io_Message.mn_ReplyPort); if (req->io_Device != 0L) CloseDevice(req); DeleteExtIO(req); } } /* DeviceCommmand: Device-Kommando ausführen */ void DeviceCommand(db, com) struct IORequest *db; UWORD com; { db->io_Command = com; DoIO(db); } /* Fehlermeldungen des Trackdisk.device */ #ifdef DEUTSCH char *Errors[] = { "Nicht bestimmt.", "Kein Sektorkopf.", "Fehlerhafte Sektorpräambel.", "Fehlerhafte Sektoridentifikation.", "Fehlerhafte Sektorkopfsumme.", "Fehlerhafte Sektorsumme.", "Nicht genügend Sektoren.", "Fehlerhafter Sektorkopf.", "Diskette schreibgeschützt.", "Diskette gewechselt.", "Fehler beim Suchen.", "Nicht genügend Speicher.", "Falsche Laufwerksnummer.", "Falscher Laufwerkstyp.", "Laufwerk ist schon Betrieb.", "Zugriff nach System-Reset."}; #else char *Errors[] = { "Not defined", "No sector header", "Wrong sector preambule", "Wrong sector id", "Wrong sector head checksum", "Wrong sector checksum", "Not enough sectors", "Wrong sector header", "Disk write-protected", "Diskette gewechselt.", "Search error", "Not enough memory", "Wrong drive number", "Wrong drive type", "Drive already in use", "Access past system reset"}; #endif char * TrackDiskError(fn) LONG fn; { if ((fn >= 20) && (fn <= 35)) return (Errors[fn - 20]); #ifdef DEUTSCH else return ("Fehlerdiagnose nicht möglich."); #else else return ("Unknown error"); #endif } /* WaitDisk: auf eine neue Diskette warten */ void WaitDisk(db) struct IOExtTD *db; { do { DeviceCommand(db, (UWORD) TD_CHANGESTATE); } while (db->iotd_Req.io_Actual == 0); do { DeviceCommand(db, (UWORD) TD_CHANGESTATE); } while (db->iotd_Req.io_Actual != 0); } /* ReadTrack: einen Track lesen */ void ReadTrack(db, tbuf, lbuf, nr) struct IOExtTD *db; BYTE *tbuf; BYTE *lbuf; LONG nr; { FOREVER { DeviceCommand(db, (UWORD) TD_CHANGENUM); db->iotd_Count = db->iotd_Req.io_Actual; db->iotd_Req.io_Data = (APTR) tbuf; db->iotd_SecLabel = (ULONG) lbuf; db->iotd_Req.io_Length = TRACK_SIZE; db->iotd_Req.io_Offset = nr * TRACK_SIZE; DeviceCommand(db, (UWORD) ETD_READ); if (db->iotd_Req.io_Error) { #ifdef DEUTSCH printf("Fehler beim Lesen von Spur #%d\n%s\n", nr, TrackDiskError((LONG) db->iotd_Req.io_Error)); #else printf("Error reading track Track #%d\n%s\n", nr, TrackDiskError((LONG) db->iotd_Req.io_Error)); #endif UserRequest(); } else break; } } /* Alles geöffnete schließen und Programm beenden */ void CloseAll(err) int err; { if (TrackWin) { CloseWindow(TrackWin); TrackWin = NULL; } if (IntuitionBase) CloseLibrary(IntuitionBase); if ((LONG) TrackDiskBlock->iotd_Req.io_Device != -1) { if (!TrackDiskBlock->iotd_Req.io_Error) EndBackup(); ExitDevice(TrackDiskBlock); } else FreeDB(TrackDiskBlock); if (TrackBuffer) FreeMem(TrackBuffer, TRACK_SIZE + LABEL_SIZE); if (FileBuffer) FreeMem(FileBuffer, BUFFER_SIZE); exit (err); } /* UserRequest: Ja-Nein-Abfrage */ void UserRequest() { char c; #ifdef DEUTSCH printf("Abbrechen ? \033[32m(J/N)\033[31m"); #else printf("Abort ? \033[32m(Y/N)\033[31m"); #endif FOREVER { c = getchar(); #ifdef DEUTSCH if (toupper(c) == 'J') { printf("Abbruch !!!\n"); CloseAll(1); } #else if (toupper(c) == 'Y') { printf("Aborted\n"); CloseAll(1); } #endif if (toupper(c) == 'N') return; } } int DoNothing() { return (0); } /* Alles benötigte Öffnen */ void OpenAll(devunit) int devunit; { if (onbreak(DoNothing)) #ifdef DEUTSCH printf("Fehler beim Installieren der Unterbrechungsabfangroutine !!!\n" "Bei Unterbrechen des Programmes mit Ctrl-C oder Ctrl-D\n" "kann Datenverlust entstehen !\n"); #else printf("Error installing routine to catch user breaks\n" "User breaks by Ctrl-C or Ctrl-D may lead into loss of data\n"); #endif if (!InitDevice("trackdisk.device", devunit, &TrackDiskBlock, 0, sizeof(*TrackDiskBlock))) { #ifdef DEUTSCH printf("Trackdisk.device kann nicht geöffnet werden !!!\n" "Prüfen sie, ob das Laufwerk vorhanden ist.\n"); #else printf("Unable to open trackdisk.device\n" "Check disk drive\n"); #endif exit(10); } if (!(TrackBuffer = AllocMem(TRACK_SIZE * 2 + LABEL_SIZE, MEMF_CHIP))) { #ifdef DEUTSCH printf("Nicht genügend CHIP-Speicher !!!\n"); #else printf("Not enough CHIP-memory\n"); #endif CloseAll(20); } LabelBuffer = TrackBuffer + 2 * TRACK_SIZE; if (!(FileBuffer = AllocMem(BUFFER_SIZE, MEMF_PUBLIC))) { #ifdef DEUTSCH printf("Nicht genügend Speicher für Datenpuffer (1K) !!!\n"); #else printf("Not enough memory for data buffer (1K)\n"); #endif CloseAll(20); } if (IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0)) TrackWin = OpenWindow(&TrackNW); } /* * ConcatPath: einen Dateinamen zusammensetzen p1: Directory oder * Device p2: Directory oder Filename */ void ConcatPath(buffer, p1, p2) char *buffer, *p1, *p2; { strcpy(buffer, p1); if (strlen(p1) > 0 && strlen(p2) > 0) if (buffer[strlen(buffer) - 1] != ':') strcat(buffer, "/"); strcat(buffer, p2); } /* FileAbfrage: Abfrage für interaktiven Modus */ BOOL FileAbfrage() { char antwort[2]; do { #ifdef DEUTSCH printf("\033[33mJ\033[0ma/\033[33mN\033[0mein "); #else printf("\033[33mY\033[0mes/\033[33mN\033[0mo "); #endif scanf("%1s", antwort); } #ifdef DEUTSCH while (tolower(antwort[0]) != 'j' && tolower(antwort[0]) != 'n'); return ((BOOL) (tolower(antwort[0]) == 'j')); #else while (tolower(antwort[0]) != 'y' && tolower(antwort[0]) != 'n'); return ((BOOL) (tolower(antwort[0]) == 'y')); #endif } /* * Beep: einen Ton variabler Höhe und Länge ausgeben freq: Frequenz * cycles: Anzahl der Delay-Zyklen (1/50-Sekunde) */ UBYTE Channel_Map[] = {1, 8, 2, 4}; BYTE WaveForm[] = {0, 39, 74, 102, 120, 127, 120, 102, 74, 39, 0, -40, -75, -103, -121, -127, -121, -103, -75, -40}; struct IOAudio * MakeIOA(rate, vol, repeat, buf, len) LONG rate, vol, repeat; UBYTE *buf; LONG len; { struct IOAudio *ioa; struct MsgPort *port; char *PortName; PortName = "Beep-Port"; /* IO-Request holen */ if (ioa = (struct IOAudio *) AllocMem((LONG) sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR)) { ioa->ioa_Request.io_Message.mn_Node.ln_Pri = 10; if (!(port = CreatePort(PortName, 0L))) { FreeMem(ioa, (LONG) sizeof(struct IOAudio)); /* War nix */ } else { /* Audio-Kanal holen */ ioa->ioa_Request.io_Message.mn_ReplyPort = port; ioa->ioa_Data = Channel_Map; ioa->ioa_Length = (LONG) sizeof(Channel_Map); /* Audio Device oeffnen */ if (OpenDevice(AUDIONAME, 0L, (struct IORequest *) ioa, 0L)) { /* war nix */ DeletePort(port); FreeMem(ioa, (LONG) sizeof(struct IOAudio)); } else { /* Request initialisieren */ ioa->ioa_Request.io_Flags = ADIOF_PERVOL; ioa->ioa_Request.io_Command = CMD_WRITE; ioa->ioa_Period = (SHORT) (3579545L / rate); ioa->ioa_Volume = (SHORT) vol; ioa->ioa_Length = len; ioa->ioa_Data = buf; ioa->ioa_Cycles = (SHORT) repeat; } } } return (ioa); } void Beep(freq, dauer, vol) LONG freq, dauer, vol; { BYTE *DataPtr; LONG PlayLen = sizeof(WaveForm); LONG rate; struct IOAudio *ioa; rate = freq * sizeof(WaveForm); if (DataPtr = (BYTE *) AllocMem(sizeof(WaveForm), MEMF_CHIP)) { memcpy(DataPtr, WaveForm, sizeof(WaveForm)); /* IO-Request initialisieren */ if (ioa = MakeIOA(rate, vol, 0, DataPtr, PlayLen)) { /* Starten */ BeginIO((struct IORequest *) ioa); Delay(dauer); AbortIO((struct IORequest *) ioa); /* Halt!!! */ if (ioa->ioa_Request.io_Device) { CloseDevice((struct IORequest *) ioa); } if (ioa->ioa_Request.io_Message.mn_ReplyPort) { DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort); } if (ioa) { FreeMem(ioa, (LONG) sizeof(struct IOAudio)); } } FreeMem(DataPtr, sizeof(WaveForm)); } } /* Ausgabe für die Trackanzeige */ struct IntuiText TrackText = {2, 0, JAM2, 0, 0, NULL, (UBYTE *) " "}; void PrintTrack(nr) { if (TrackWin) { #ifdef DEUTSCH sprintf(TrackText.IText, "Spur:%3d, Kopf:%2d", nr / 2, nr % 2); #else sprintf(TrackText.IText,"Track:%3d, Head:%2d",nr / 2,nr % 2); #endif PrintIText(TrackWin->RPort, &TrackText, 20, 34); } } void PrintDisk(nr) { if (TrackWin) { #ifdef DEUTSCH sprintf(TrackText.IText, "Diskette:%4d", nr); #else sprintf(TrackText.IText, "Disk:%4d", nr); #endif PrintIText(TrackWin->RPort, &TrackText, 20, 18); } }