home *** CD-ROM | disk | FTP | other *** search
- // Backup.c
- // 06 Dec 1996 11:23:22
-
- #ifndef BACKUP_INCLUDE
- #include "IncludeAll.c"
- #endif
- #include "Backup.h"
- #include "cdio.h"
- #include "FileSelect.h"
- #include "ByteCount.h"
- #include "Backup_proto.h"
- #include "BackupStrings.h"
-
- // #define d(x) x
- #define d(x) ;
-
- #define DFLT_INCLUDE "*" // default Include Pattern
- #define DFLT_EXCLUDE "" // default Exclude Pattern
-
- #define ULINE 12 // Nr. d. untersten Zeile im Namensfenster
-
-
- static long gettime(void);
- static short GetDrive(const char *str, short unit);
- static short FindDrive(const char *Name);
- static void CheckForCmdFile(const char *name, BPTR DirLock, char *dirname);
- static int GetParms(int argc, const char **argv);
- static void cleanup(void);
- static void OpenAll(void);
- static void CleanupPasswordFont(void);
- static void DisplayNewDir(const struct DirEntry *aktdir);
- static ULONG __saveds __asm PreviewHookDisplay(register __a0 struct Hook *theHook,
- register __a1 object,
- register __a2 struct BCInfo *BCount);
- static void action(void);
- static void TestCompress(struct NameField *file);
- static unsigned long GetNewFile(struct Buffer *aktbuff, BOOL *FileFound);
- static BOOL isReadDiskFull(unsigned long ZusatzPlatz);
- static short lesen(void);
- static void initDisk(void);
- static void InitDiskUnit(short Unit, short DiskNo, BOOL FirstDisk);
- static void NewReadDisk(struct FileInfoBlock *fib);
- static long inhibit(BOOL onoff, struct DiskFlags *Dsk);
- static short CheckVolumes(const struct BackupOptions *Opt, short unit);
- static short CmpVolumeName(char *DirName, char *VolName);
- static void CheckDriveFormat(void);
-
-
- extern struct IntuitionBase *IntuitionBase;
- extern struct DosLibrary *DOSBase;
-
- extern struct WBStartup *WBenchMsg;
-
-
- #ifdef TAPEDEBUG
- // aus Backup_Tape.c
- short TapeDebugLevel;
- #endif
-
- // aus Backup_Window.c
- extern struct TextAttr PWDFONT, DefaultFAttr;
- extern struct Screen *WBScreen;
- extern short WindowColumns; // lichte Weite des Window in Chars
- extern unsigned long DiskChangeMaske;
-
-
- // aus Revision.c
- extern short Version; // aktuelle Versionsnummer
-
- // aus NextFile.c
- extern BOOL NextFileAbort; // Abbruch-Flag für NextFile
-
- // aus CmdFile.c
- extern FILE *aktCmdFile; // fp für Kommandofile
- extern char __far CmdFileName[]; // Name des Kommandofile
-
- // aus ProtFile.c
- extern FILE *ProtFileHandle; // File Handle für Protokoll-File
-
- // aus ScaledImageClass.c
- extern Class *ScaledImageClass; // Image Class für skalierte Images
-
-
- struct Task *BackupTask;
-
- static struct Window *prWindowPtr; // original-Inhalt von Process->pr_WindowPtr
-
- struct Window *aktWindow;
- struct TextFont *myFont = NULL;
- struct TextFont *ScreenFont = NULL;
- struct TextFont PasswordFont;
-
- struct MsgPort *AppPort = NULL; // Msg Port für AppMessages
- static struct BInputHandler *AppInput = NULL;
-
- short BuffCount = MAX_CYLBUFF; // tatsächliche Anzahl Buffer
-
- struct DiskFlags __far *Disks = NULL;
- unsigned short NDisk = 0; // Anzahl Einträge in Disks[]
-
- BOOL toTape = FALSE; // Backup erfolgt auf Tape
-
- static BOOL InteractiveBackup = FALSE; // Parameter sind manuell eingestellt
-
- short BuffersFull = 0; // Anzahl gefüllter Buffer
-
- BOOL AllFilesRead; // Backup-Ende (lesen) erreicht
- BPTR aktReadFileHandle = NULL; // fh für Lese-File
-
- static short ErrorCount = 0l; // Zähler für aufgetretene Fehler
-
-
- struct Buffer __far CylBuff[MAX_CYLBUFF]; // Schreib-/Lese-Buffer (für je einen Cylinder)
-
- // globale Disk-Parameter
- struct BackupDevInfo globDrvDat;
-
- struct Buffer *AktReadBuffer;
- unsigned short ReadBuffNr, WriteBuffNr, OldestWriteBuffNr=(unsigned short)(~0);
-
- struct FileInfoBlock __aligned __far Root_fib;
- struct PartitionInfo Root_pInfo;
-
- static char __far zeile[129];
-
- static char LinkPath[FMSIZE];
- static char *LinkPathPtr;
-
- char WBDiskNames[FMSIZE]; // Laufwerksnamen aus WB ToolTypes
-
- short DiskUnit; // aktuelles Laufwerk für Backup
-
- static BPTR InitialCurrentDir = ~0; // CurrentDir-Lock bei Programmstart
-
- unsigned char disknr; // laufende Nummer der Backup-Diskette
-
- long readoffset; // Offset innerhalb des aktuellen Lese-Buffers
-
- struct SignalSemaphore NFSema; // Lock für aktName und dir NameField-Verkettung
- struct NameField *aktName; // aktuelles NameField
- static struct NfSplit aktNameInfo;
-
- struct BackupOptions myOptions; // Einstellungen für die aktuelle Sicherung
-
- char *BackupStartDir = NULL; // Startdirectory für Backup
-
- char *AktPath; // Text mit aktuellem Suchpfad (bei NextFile)
- char __far NormalizedAktPath[FMSIZE]; // AktPath normalisiert
-
-
- static unsigned long TotalFiles; // Anzahl zu sichernde Files
- static unsigned long TotalBytes; // Anzahl zu sichernde Bytes
-
-
- // fortlaufende Numerierung für mehrfache Sicherungen auf einem Medium
- // (mit Append, ist == 0 bei normaler (Einzel-) Sicherung
- unsigned short CurrentSessionNr = 0;
-
-
- struct Disk ReadDisk;
- struct Disk WriteDisk;
-
- static struct SignalSemaphore WriteDiskSema;
-
-
- struct NextFileInfo NFInfo = // Datensatz für NextFile()
- {
- 0L, 0, 0L, NULL, NULL,
- { (struct MinNode *) &NFInfo.nfi_FirstDir.mlh_Tail,
- NULL, (struct MinNode *) &NFInfo.nfi_FirstDir },
- NULL, NULL };
-
- // Variablen für Backup-Statistik
- unsigned long FilesProcessed; // Anzahl Files
- unsigned long BytesProcessed; // Anzahl Bytes
- char StartZeit[8];
-
- // Declarations for CBACK
- extern BPTR __Backstdout; // standard output when run in background
- long __BackGroundIO = 0; // Flag to tell it we don't want to do I/O
- long __stack = MIN_STACK; // Amount of stack space our task needs
- char *__procname = "Backup"; // The name of the task to create
- long __priority = 0; // The priority to run us at
-
-
- #undef min
- int min(int aa, int bb)
- {
- return ( aa < bb ? aa : bb );
- }
-
-
- #undef max
- int max(int aa, int bb)
- {
- return ( aa < bb ? bb : aa );
- }
-
-
- int sectotrack(int sektor)
- {
- return (int) (sektor / (globDrvDat.NumHeads * globDrvDat.NumSecs));
- }
-
-
- // liefert nächsthöhere integere Zahl von a/b
- int ceildiv(int a, int b)
- {
- int erg;
-
- erg = a / b;
- if (a % b)
- erg++;
- return erg;
- }
-
-
- // (Fehler-)Meldung absetzen
- void PostError(BOOL Primary, enum MsgPriority Priority, const char *ErrText, ...)
- {
- va_list args;
-
- ASSERT_VALID(ErrText);
-
- va_start(args, ErrText);
-
- if (Priority >= myOptions.bo_WarnLevel)
- {
- char zeile[129];
-
- vsprintf(zeile, ErrText, args);
-
- ErrorCount++;
-
- SignalUnIconifyMainWindow();
-
- if (Primary)
- AddErrorText(zeile, NULL);
- else
- AddErrorText(NULL, zeile, NULL);
- }
-
- va_end(args);
- }
-
-
- const char *ShortFileName(const char *RawName, short maxlen)
- {
- static char NameSpace[FMSIZE];
- const char *result;
- short len, pos;
-
- ASSERT_VALID(RawName);
-
- len = strlen(RawName);
- if (len > maxlen)
- {
- // zu lange Zeile wird als "Anfang...Ende" angezeigt
- pos = (2 * maxlen) / 3 - 3;
-
- stccpy(NameSpace, RawName, min(pos, sizeof(NameSpace)));
- strcat(NameSpace, "...");
- strcat(NameSpace, RawName + len - maxlen + pos+3);
-
- result = NameSpace;
- }
- else
- result = RawName;
-
- return result;
- }
-
-
- // liefert Zeit in hundertstel s
- static long gettime()
- {
- static char clock[8];
- long secs;
-
- getclk(clock);
- secs = ((clock[4]*60)+clock[5])*60+clock[6];
- return 100*secs + clock[7];
- }
-
-
- // liefert den nackten Filenamen aus "name"
- // ohne Path
- unsigned const char *NurName(const char *name)
- {
- ASSERT_VALID(name);
-
- return FilePart((STRPTR) name);
- }
-
-
- int myatoi(const char **str, int n)
- {
- int erg = 0;
-
- ASSERT_VALID(*str);
-
- *str = stpblk(*str);
- while (n && **str && isdigit(**str))
- {
- erg = 10 * erg + (**str - '0');
- (*str)++;
- n--;
- }
- return erg;
- }
-
-
- // Tagesnummer (long, ab 1.1.1978) umwandeln in Tag,Monat,Jahr
- short UnpackDate(long Day, struct myDate *Date)
- {
- char DateStr[6];
-
- ASSERT_VALID(Date);
-
- utunpk((Day+YEARDIFF)*3600l*24l, DateStr);
- Date->Day = DateStr[2];
- Date->Month = DateStr[1];
- Date->Year = DateStr[0] + YEARZERO;
-
- return 0;
- }
-
-
- // Datum in Tagesnummer (long, ab 1.1.1978) umwandeln
- // liefert ~0 bei Fehler im Datum
- long PackDate(short Tag, short Monat, short Jahr)
- {
- long tagnr;
- short ok;
- struct DateTime dt;
- char DateStr[20];
-
- if (Jahr > 1900)
- Jahr -= 1900;
-
- sprintf(DateStr, "%d-%d-%d", Monat, Tag, Jahr);
- dt.dat_Format = FORMAT_USA;
- dt.dat_Flags = 0;
- dt.dat_StrDate = DateStr;
- dt.dat_StrTime = NULL;
-
- ok = StrToDate(&dt);
- tagnr = dt.dat_Stamp.ds_Days;
-
- return ok ? tagnr : ~0l;
- }
-
-
- char *ReadString(char *nach, const char *von, size_t maxlen)
- {
- char FirstC;
-
- ASSERT_VALID(nach);
- ASSERT_VALID(von);
-
- FirstC = *von;
- if (FirstC == '"')
- von++;
-
- while (maxlen && *von && ((FirstC == '"' && *von != '"') ||
- (FirstC != '"' && !isspace(*von))))
- {
- *nach++ = *von++;
- maxlen--;
- }
- *nach = '\0';
-
- if (*von && FirstC == '"')
- von++; // " am Schluß überlesen
-
- return von;
- }
-
-
- static short GetDrive(const char *str, short unit)
- {
- short len, n;
- char *DupStr;
-
- ASSERT_VALID(str);
- assert(unit == NO_DRIVE || (unit >= 0 && unit < NDisk));
-
- // das ':' am Ende des Device-Namens muß für FindDrive() entfernt werden.
- DupStr = strdup(str);
- if (NULL == DupStr)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DupStr", strlen(str));
- myabort(20);
- }
- len = strlen(DupStr);
- if (DupStr[len-1] == ':')
- DupStr[len-1] = '\0';
-
- n = FindDrive(DupStr);
-
- free(DupStr);
-
- if (n == NO_DRIVE)
- {
- alarm(GetString(MSG_NOT_A_VALID_DRIVE), str);
- myabort(0);
- }
- if (n == unit)
- {
- alarm(GetString(MSG_ALREADY_INUSE), Disks[n].DOSName);
- n = NO_DRIVE;
- }
-
- return n;
- }
-
-
-
- static short FindDrive(const char *Name)
- {
- short n;
- BOOL found;
-
- ASSERT_VALID(Name);
-
- for (n=0, found=FALSE; !found && n<NDisk; )
- {
- found = Disks[n].valid && stricmp(Disks[n].DOSName, Name) == 0;
- if (!found)
- n++;
- }
-
- return (short) (found ? n : NO_DRIVE);
- }
-
-
-
- static void CheckForCmdFile(const char *name, BPTR DirLock, char *dirname)
- {
- char *path;
- BPTR OldLock = NULL;
-
- ASSERT_VALID0(name);
- ASSERT_VALID0(BADDR(DirLock));
- ASSERT_VALID(dirname);
-
- if (name == NULL || *name == '\0')
- return;
-
- strcpy(CmdFileName, name);
-
- if (DirLock)
- OldLock = CurrentDir(DupLock(DirLock));
-
- if (!OpenCmdFile(CmdFileName))
- {
- if (OldLock)
- UnLock(CurrentDir(OldLock)); // Current Dir restaurieren
- myabort(1);
- }
-
- if (aktCmdFile)
- {
- path = ReadCmdFile(&myOptions, 1);
- if (path)
- strcpy(dirname, path);
- else
- CloseCmdFile();
- }
-
- if (OldLock)
- UnLock(CurrentDir(OldLock)); // Current Dir restaurieren
- }
-
-
- void DefaultOptions(struct BackupOptions *Opts, BOOL NewFS)
- {
- static char dirname[FMSIZE];
- char zeit[8];
-
- ASSERT_VALID(Opts);
-
- if (NewFS)
- {
- Opts->bo_FSDirList = NULL;
- Opts->bo_FSDirCount = 0L;
-
- Opts->bo_WhereSortDirs = DirFirst; // default: Directories zuerst einsortieren
-
- Opts->bo_FSCompare = FSCompareName; // default: sortieren nach Name
- Opts->bo_HowToSort = SortName;
- }
-
- Opts->bo_MainWindowPos.Left = 0;
- Opts->bo_MainWindowPos.Top = 25;
- Opts->bo_MainWindowPos.Width = BREITE;
- Opts->bo_MainWindowPos.Height = HOEHE;
-
- Opts->bo_Append = FALSE; // Default: kein Append
- Opts->bo_IncludeSubDirs = TRUE; // Default: mit Subdirectories
- Opts->bo_UseArc = Ignore; // Default: Archiv-Flag ist egal
- Opts->bo_SetArc = Set; // default: Archiv-Flag setzen
- Opts->bo_ProtFile = PT_ASCII; // default: mit Protokollfile
- Opts->bo_Verify = FALSE; // default: ohne Verify
- Opts->bo_UseFirstDate = FALSE; // default: nicht nach Datum prüfen
- Opts->bo_UseLastDate = FALSE; // default: nicht nach Datum prüfen
- Opts->bo_Compress = COMPRESS_NONE; // default: nicht komprimieren
- Opts->bo_KeepProtFile = TRUE; // default: Protokollfile nicht löschen
- Opts->bo_SaveSoftLinks = FALSE; // default: SoftLinks als Link sichern
- Opts->bo_SaveHardLinks = TRUE; // default: HardLinks als Inhalt sichern
- Opts->bo_Preview = FALSE; // default: kein Preview
- Opts->bo_UseHardwareCompression = TRUE; // default: Hardware-Kompression nutzen
- Opts->bo_UseGrepPattern = TRUE; // default: OS2.0 #? Wildcards nutzen
- Opts->bo_Iconify = FALSE; // default: nicht ikonifizieren
- Opts->bo_WarnDosDisk = TRUE; // default: Nachfragen bei DOS-Disk
-
- Opts->bo_WarnLevel = 0; // default: alles anzeigen
-
- Opts->bo_AppIconPosX = NO_ICON_POSITION;
- Opts->bo_AppIconPosY = NO_ICON_POSITION;
-
- Opts->bo_QFAPartitionSize = DEFAULT_QFA_PARTSIZE; // Größe für die QFA-Partition in MB
-
- BackupStartDir = dirname;
-
- // Datumsgrenzen default vom 1.1.80 bis heute
- Opts->bo_FirstDate = ReadDate(DateString(1, 1, 80));
- getclk(zeit);
- Opts->bo_LastDate = ReadDate(DateString(zeit[3], zeit[2], zeit[1]+80));
-
- getcwd(dirname, 128); // Default Directory
- if ( strchr(dirname, ':')==NULL && dirname[strlen(dirname)-1]!=':')
- strcat(dirname, ":");
-
- strcpy(Opts->bo_AppIconName, "");
-
- strcpy(Opts->bo_CmdFileIcon, "");
- strcpy(Opts->bo_DrivesWithoutGeometry, "");
-
- strcpy(Opts->bo_IncludeFile.RawName, DFLT_INCLUDE);
- strcpy(Opts->bo_ExcludeFile.RawName, DFLT_EXCLUDE);
-
- strcpy(Opts->bo_ProtFileName, LOGDIR LOGNAME);
- strcpy(Opts->bo_DiskSavePrefix, DEFAULT_DISKSAVE);
- strcpy(Opts->bo_HelpPath, DEFAULT_HELPPATH);
- strcpy(Opts->bo_ScriptPath, DEFAULT_SCRIPTPATH);
- strcpy(Opts->bo_TapeDriveDataFileName, DEFAULT_TAPEDRIVEDATABASE);
-
- strcpy(Opts->bo_Language, ""); // default: System-Standardsprache
- strcpy(Opts->bo_PubScreen, ""); // default: Default Screen
- strcpy(Opts->bo_CurrentDir, "PROGDIR:"); // default: PROGDIR:
-
- // Defaultwerte für bo_ListFontName werden aus dem System Default Font übernommen!!
- sprintf(Opts->bo_ListFontName, "%s/%d", DefaultFAttr.ta_Name, DefaultFAttr.ta_YSize);
-
- TranslateWildCards(Opts);
- }
-
-
- void SetupDrives(struct BackupOptions *Opt, const char *DriveNames)
- {
- short n;
-
- ASSERT_VALID(DriveNames);
-
- Opt->bo_FirstUnit = Opt->bo_SecondUnit = NO_DRIVE;
-
- for (n=NDisk-1; n>=0; n--)
- {
- if (Disks[n].valid && MatchToolValue((STRPTR) DriveNames, Disks[n].DOSName))
- {
- if (Opt->bo_FirstUnit == NO_DRIVE)
- Opt->bo_FirstUnit = n;
- else if (Opt->bo_SecondUnit == NO_DRIVE && n != Opt->bo_FirstUnit)
- Opt->bo_SecondUnit = n;
- }
- }
- }
-
-
- static int GetParms(int argc, const char *argv[])
- {
- static char dirname[FMSIZE] = "";
- short drvdef, i;
-
- ASSERT_VALID(argv);
-
- DefaultOptions(&myOptions, 1);
-
- // Wenn von Workbench gestartet, aus den Tool Types die default-
- // Werte für die diversen Flags lesen
- if (argc == 0) // Start von Workbench
- {
- // WB Tool Types auswerten.
- // vor getdisks() damit die Tape-Namen vorgegeben werden können.
- struct WBArg CmdFile;
-
- WBDiskNames[0] = '\0';
-
- if (GetWBDefaults(&CmdFile, WBenchMsg, &myOptions))
- CheckForCmdFile(CmdFile.wa_Name, CmdFile.wa_Lock, dirname);
- }
-
- myOpenLocale(myOptions.bo_Language);
- OpenBackupScreen(*myOptions.bo_PubScreen ? myOptions.bo_PubScreen : NULL);
-
- getdisks(); // Verfügbare Disk-Laufwerke suchen
-
- if (argc == 0)
- {
- // Laufwerke aus WB Tool Types übernehmen.
- // MUSS nach getdisks() erfolgen!!!!!
- SetupDrives(&myOptions, WBDiskNames);
- }
-
- SetupNextFileInfo(&NFInfo, &myOptions, DisplayNewDir);
-
- // Default-Laufwerk(e) festlegen (die beiden höchsten verfügbaren
- // Laufwerke DFx werden für LW 1 und 2 verwendet)
- if (myOptions.bo_FirstUnit == NO_DRIVE)
- {
- for (i=3-1; i>=0; i--)
- {
- int DiskNo;
-
- sprintf(zeile, "DF%d", i);
- if ((DiskNo = FindDrive(zeile)) != NO_DRIVE)
- {
- if (myOptions.bo_FirstUnit == NO_DRIVE)
- {
- myOptions.bo_FirstUnit = DiskNo;
- myOptions.bo_SecondUnit = NO_DRIVE;
- }
- else if (myOptions.bo_SecondUnit == NO_DRIVE && DiskNo != myOptions.bo_FirstUnit)
- myOptions.bo_SecondUnit = DiskNo;
- }
- }
- }
-
- if (argc < 2)
- {
- if (aktCmdFile == NULL)
- {
- // ohne Kommandofile: Interaktives Backup!
- InteractiveBackup = TRUE;
-
- if (!getargs(&myOptions))
- myabort(0);
- }
- }
- else
- {
- if (strcmp(argv[1], "?") == 0)
- {
- CallHelp(0L, 0);
- myabort(0);
- }
-
- if (argv[1][0] == '@')
- CheckForCmdFile(&argv[1][1], NULL, dirname);
-
- if (aktCmdFile == NULL)
- {
- stcgfp(dirname, argv[1]); // Get file path
- stcgfn(myOptions.bo_IncludeFile.RawName, argv[1]); // Get file node
- }
- for (drvdef=0, i=2; i<argc; i++)
- {
- switch (argv[i][0])
- {
- case '/':
- case '-': // Option
- processOption(&argv[i][1], "", &myOptions);
- break;
- default:
- if (argv[i][strlen(argv[i])-1] == ':')
- {
- // Ziellaufwerk
- if (drvdef == 0)
- {
- myOptions.bo_FirstUnit = GetDrive(argv[i], NO_DRIVE);
- myOptions.bo_SecondUnit = NO_DRIVE;
- }
- else if (drvdef == 1)
- myOptions.bo_SecondUnit = GetDrive(argv[i], myOptions.bo_FirstUnit);
- else
- alarm(GetString(MSG_IGNORE_THIRD_DRIVE), argv[i]);
- drvdef++;
- }
- else
- {
- if (!CheckLineForToolType(argv[i], &myOptions))
- {
- // Schrott
- alarm(GetString(MSG_INVALID_PARAMETER), argv[i]);
- myabort(0);
- }
- }
- break;
- }
- }
- }
-
- if (*dirname)
- NewDir(&NFInfo.nfi_FirstDir, dirname, 0);
-
- #if 0
- if (myOptions.bo_FirstUnit != NO_DRIVE)
- {
- printf(" First Unit %d: \"%s\" TapeReq=%08lx\n",
- myOptions.bo_FirstUnit,
- Disks[myOptions.bo_FirstUnit].DOSName,
- Disks[myOptions.bo_FirstUnit].TapeReq);
- }
- if (myOptions.bo_SecondUnit != NO_DRIVE)
- {
- printf("Second Unit %d: \"%s\" TapeReq=%08lx\n",
- myOptions.bo_SecondUnit,
- Disks[myOptions.bo_SecondUnit].DOSName,
- Disks[myOptions.bo_SecondUnit].TapeReq);
- }
- #endif
-
- return 1;
- }
-
-
- void myabort(int errcode)
- {
- myOptions.bo_KeepProtFile = 0;
-
- exit(errcode);
- }
-
-
- static void cleanup(void)
- {
- unsigned short i;
-
- StopWriter(TRUE);
- ShutdownHelp();
- CleanupError();
- DeinitCompress();
- CleanUpFS();
- CleanupXGO();
- CleanupXpk();
- CleanupNextFileInfo(&NFInfo);
- CleanupProtFile(FALSE);
- CleanupTapeInfo();
- CleanupAbout();
- CleanupStat();
- CleanupST(); // Cleanup für SetupTape
- GlobalYesNoCleanup();
-
- CDClose();
- CleanupMainWindow();
- CleanupFileDisplay();
-
- if (myOptions.bo_ProtFile != PT_None && !myOptions.bo_KeepProtFile)
- {
- // ggf. temporäres Protokollfile löschen
- DeleteFile(myOptions.bo_ProtFileName);
- }
-
- if (AppPort)
- {
- RemBInputHandler(&AppInput);
-
- DeletePort(AppPort);
- AppPort = NULL;
- }
- if (AktPath != NULL)
- {
- free(AktPath);
- AktPath = NULL;
- }
- if (aktReadFileHandle)
- {
- Close(aktReadFileHandle);
- aktReadFileHandle = NULL;
- }
- if (aktCmdFile)
- CloseCmdFile();
-
- if (NDisk > 0 && myOptions.bo_FirstUnit != NO_DRIVE)
- {
- assert(myOptions.bo_FirstUnit >= 0 && myOptions.bo_FirstUnit < NDisk);
- CleanUpDisk(&Disks[myOptions.bo_FirstUnit], TRUE);
- myOptions.bo_FirstUnit = NO_DRIVE;
- }
- if (NDisk > 0 && myOptions.bo_SecondUnit != NO_DRIVE)
- {
- assert(myOptions.bo_SecondUnit >= 0 && myOptions.bo_SecondUnit < NDisk);
- CleanUpDisk(&Disks[myOptions.bo_SecondUnit], TRUE);
- myOptions.bo_SecondUnit = NO_DRIVE;
- }
-
- ClosePartition(&Root_pInfo); // evtl. offene Partition schließen
-
- for (i=0; i<BuffCount; i++)
- {
- if (CylBuff[i].dbp != NULL)
- {
- FreeVec(CylBuff[i].dbp);
- CylBuff[i].dbp = NULL;
- }
- if (CylBuff[i].TapeReq)
- {
- FreeVec(CylBuff[i].TapeReq);
- CylBuff[i].TapeReq = NULL;
- }
- }
-
- DeleteSaveInfo();
-
- CleanupRWDisk(&ReadDisk);
- CleanupRWDisk(&WriteDisk);
-
- if (Disks)
- {
- free(Disks);
- Disks = NULL;
- }
-
- if (myFont)
- {
- CloseFont(myFont);
- myFont = NULL;
- }
- if (ScreenFont)
- {
- CloseFont(ScreenFont);
- ScreenFont = NULL;
- }
-
- CleanupPasswordFont();
-
- if (InitialCurrentDir != ~0)
- UnLock(CurrentDir(InitialCurrentDir));
-
- if (prWindowPtr)
- {
- ((struct Process*) BackupTask)->pr_WindowPtr = prWindowPtr;
- prWindowPtr = NULL;
- }
-
- if (ScaledImageClass)
- {
- freeScaledImageClass(ScaledImageClass);
- ScaledImageClass = NULL;
- }
-
- CloseLibraries();
- }
-
-
- // Angelegte Directory-Cylinderliste wieder auflösen
- void CleanupRWDisk(struct Disk *Dsk)
- {
- struct DirBlock *aktblock;
-
- ASSERT_VALID(Dsk);
-
- while (Dsk->DirBuffers.mlh_Head != NULL && !IsListEmpty((struct List *) &Dsk->DirBuffers))
- {
- aktblock = (struct DirBlock *) RemHead((struct List *) &Dsk->DirBuffers);
- if (aktblock->LostNF)
- {
- free(aktblock->LostNF);
- aktblock->LostNF = NULL;
- }
- FreeVec(aktblock);
- }
- }
-
-
- void CleanUpDisk(struct DiskFlags *Dsk, BOOL Release)
- {
- ASSERT_VALID(Dsk);
-
- if (Dsk->DcI)
- {
- EndDiskChanger(Dsk->DcI);
- Dsk->DcI = NULL;
- }
-
- if (Dsk->inhibited)
- inhibit(FALSE, Dsk); // Laufwerk freigeben
-
- if (Release && Dsk->TapeReq)
- {
- FreeVec(Dsk->TapeReq);
- Dsk->TapeReq = NULL;
- }
- }
-
-
- static void OpenAll(void)
- {
- atexit(cleanup);
-
- BackupTask = FindTask(NULL);
-
- prWindowPtr = ((struct Process*) BackupTask)->pr_WindowPtr;
-
- OpenLibraries();
-
- ScaledImageClass = initScaledImageClass();
-
- // System Default Font öffnen
- myFont = OpenDiskFont(&DefaultFAttr);
- if (NULL == myFont)
- {
- alarm(GetString(MSG_CANNOT_OPEN_FONT), DefaultFAttr.ta_Name);
- myabort(10);
- }
-
- if (WorkbenchBase)
- {
- if ((AppPort = CreatePort(NULL, 0)) == NULL)
- {
- alarm(GetString(MSG_CREATEPORT_FAILED), __FUNC__, "AppPort");
- myabort(15);
- }
- else
- {
- AppInput = AddBInputHandler(1 << AppPort->mp_SigBit, HandleAppMsg);
- }
- }
-
- InitSemaphore(&NFSema);
- InitXpk();
-
- InitTape();
- }
-
-
- static void CleanupPasswordFont(void)
- {
- if (PasswordFont.tf_CharLoc)
- {
- RemFont(&PasswordFont);
-
- free(PasswordFont.tf_CharLoc);
- PasswordFont.tf_CharLoc = NULL;
- }
-
- if (PasswordFont.tf_Message.mn_ReplyPort)
- {
- DeleteMsgPort(PasswordFont.tf_Message.mn_ReplyPort);
- PasswordFont.tf_Message.mn_ReplyPort = NULL;
- }
- }
-
-
- // Initialisieren der IORequest's für die Cylinderbuffer
- short InitBufReq(void)
- {
- unsigned short i;
-
- for (i=0; i<BuffCount; i++)
- {
- assert(DiskUnit >= 0 && DiskUnit < NDisk);
-
- if (CylBuff[i].BufIOReq.iotd_Req.io_Command != CMD_INVALID)
- {
- alarm(GetString(MSG_INITBUFREQ_BUFFER_NOT_FREE), i);
- myabort(50);
- }
- CylBuff[i].BufIOReq = *Disks[DiskUnit].diskreq;
- CylBuff[i].BufIOReq.iotd_Req.io_Command = CMD_INVALID;
-
- if (Disks[DiskUnit].TapeReq)
- {
- CylBuff[i].TapeReq = AllocVec(sizeof(struct TapeIO),
- globDrvDat.BufMemType);
- if (CylBuff[i].TapeReq == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "TapeReq", sizeof(struct TapeIO));
- return TRUE;
- }
- *CylBuff[i].TapeReq = *Disks[DiskUnit].TapeReq;
- CylBuff[i].TapeReq->Req = &CylBuff[i].BufIOReq;
- }
- else if (myOptions.bo_Verify)
- {
- CylBuff[i].VerifyReq = *Disks[DiskUnit].diskreq;
- CylBuff[i].VerifyReq.iotd_Req.io_Command = CMD_INVALID;
- }
- }
-
- return FALSE;
- }
-
-
- BOOL InitSearchPattern(struct BackupOptions *Opt)
- {
- ASSERT_VALID(Opt);
-
- if (Opt->bo_UseGrepPattern)
- {
- // Sicherstellen, daß alle Patterns bereit sind
-
- if (!Opt->bo_IncludeFile.isParsed)
- {
- if(ParsePatternNoCase(Opt->bo_IncludeFile.RawName,
- Opt->bo_IncludeFile.ParsedPattern,
- sizeof(Opt->bo_IncludeFile.ParsedPattern) ) == -1)
- {
- alarm(GetString(MSG_XLATEERROR_INCLUDE));
- Opt->bo_IncludeFile.isParsed = 0;
-
- return FALSE;
- }
- else
- {
- Opt->bo_IncludeFile.isParsed = 1;
- }
- }
- if (!Opt->bo_ExcludeFile.isParsed)
- {
- if(ParsePatternNoCase(Opt->bo_ExcludeFile.RawName,
- Opt->bo_ExcludeFile.ParsedPattern,
- sizeof(Opt->bo_ExcludeFile.ParsedPattern) ) == -1)
- {
- alarm(GetString(MSG_XLATEERROR_EXCLUDE));
- Opt->bo_ExcludeFile.isParsed = 0;
-
- return FALSE;
- }
- else
- {
- Opt->bo_ExcludeFile.isParsed = 1;
- }
- }
- }
- return TRUE;
- }
-
-
- // alle Zylinderpuffer anlegen
- void AllocDiskBuffer(void)
- {
- unsigned short i;
- unsigned long UsableMemory;
-
- if (CylBuff[0].dbp != NULL)
- return; // ...war schon initialisiert
-
- BuffCount = MAX_CYLBUFF;
-
- UsableMemory = AvailMem(globDrvDat.BufMemType);
-
- UsableMemory = CreateSaveInfo(UsableMemory);
-
- // max. 1/2 des verfügbaren Speichers für Diskbuffer belegen !
- if (globDrvDat.CylSize * BuffCount > UsableMemory / 2)
- BuffCount = (UsableMemory / globDrvDat.CylSize) / 2;
-
- if (BuffCount < MIN_CYLBUFF)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DiskBuffer", MIN_CYLBUFF * globDrvDat.CylSize);
- myabort(10);
- }
-
- for (i=0; i<BuffCount; i++)
- {
- InitSemaphore(&CylBuff[i].BuffSema);
-
- CylBuff[i].Status = LEER; // Buffer leer
-
- CylBuff[i].dbp = (BYTE *) AllocVec(globDrvDat.CylSize, globDrvDat.BufMemType);
- if (CylBuff[i].dbp == NULL)
- {
- char tLine[25];
-
- sprintf(tLine, "DiskBuffer %d", i);
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, tLine, globDrvDat.CylSize);
- myabort(10);
- }
- }
-
- ShowBuffStatus(&CylBuff[0], TRUE); // Bufferstatus erstmalig anzeigen
- }
-
-
- void KMBytes(char *Line, unsigned long Value)
- {
- unsigned long KBytes = Value / 1024l;
-
- if (Value > 2000*1024)
- {
- // alles > 2000 kB in MBytes anzeigen
- sprintf(Line, "%4ld%c%1d M", KBytes/1024l,
- GetDecimalPoint(),
- (10*KBytes/1024l) % 10);
- }
- else if (Value > 2048)
- {
- // alles > 2048 Bytes in KBytes anzeigen
- sprintf(Line, "%6ld K", KBytes);
- }
- else
- sprintf(Line, "%6ld ", Value);
- }
-
-
- static void DisplayNewDir(const struct DirEntry *aktdir)
- {
- ASSERT_VALID(aktdir);
-
- if (aktdir->Done || *aktdir->Name == '\0')
- return;
-
- FDDisplayNewDir(AktPath);
- }
-
-
- void UpdateFileDisplay(void)
- {
- static unsigned long LastFilesProcessed = ~0;
- static unsigned long LastBytesProcessed = ~0;
- char Text[80];
-
- if (FilesProcessed != LastFilesProcessed)
- {
- DisplayNewFile(Root_fib.fib_FileName);
- }
- if (BytesProcessed != LastBytesProcessed)
- {
- char BText1[20], BText2[20];
-
- KMBytes(BText1, BytesProcessed);
-
- if (myOptions.bo_Preview)
- {
- KMBytes(BText2, TotalBytes);
- sprintf(Text, GetString(MSG_BYTESPROCESSED_PREVIEW), BText1, BText2);
- }
- else
- sprintf(Text, GetString(MSG_BYTESPROCESSED), BText1, BText2);
-
- ShowByteCount(Text);
- }
-
- if (myOptions.bo_Preview)
- {
- if (BytesProcessed != LastBytesProcessed)
- ShowProgress(BytesProcessed, TotalBytes);
-
- sprintf(Text, GetString(MSG_FILESPROCESSED_PREVIEW),
- FilesProcessed, TotalFiles);
- }
- else
- {
- sprintf(Text, GetString(MSG_FILESPROCESSED), FilesProcessed);
- }
-
- if (FilesProcessed != LastFilesProcessed)
- ShowFileCount(Text);
-
- LastFilesProcessed = FilesProcessed;
- LastBytesProcessed = BytesProcessed;
- }
-
-
- void SetupNewDir(struct NextFileInfo *Info, const char *IncludePattern,
- struct DirEntry *aktdir)
- {
- BPTR OldCurrentDir;
- int len;
- struct DirEntry *akt;
-
- ASSERT_VALID(Info);
- ASSERT_VALID(IncludePattern);
- ASSERT_VALID(aktdir);
-
- if (aktdir->Done)
- return;
-
- if (Info->nfi_DirLock)
- {
- UnLock(Info->nfi_DirLock);
- Info->nfi_DirLock = NULL;
- }
-
- if (AktPath != NULL)
- {
- free(AktPath);
- AktPath = NULL;
- }
- aktdir->Virgin = 0;
- aktdir->Contents = 0;
-
- len = strlen(IncludePattern) + 6;
- for (akt = aktdir; akt; akt = akt->Root)
- len += strlen(akt->Name) + 1;
- AktPath = (char *) calloc(len, 1);
- if (AktPath == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "AktPath", len);
- myabort(10);
- }
- *AktPath = '\0';
- for (akt = aktdir; akt; akt = akt->Root)
- {
- char c;
- int l;
-
- l = strlen(akt->Name);
- c = akt->Name[l-1];
- if (l > 0 && c != ':' && c != '/')
- strins(AktPath, "/");
- strins(AktPath, akt->Name);
- }
-
- // Der Abschluß von Pfaden mit '/' ist nicht notwendig und
- // führt bei SoftLinks sogar zu Problemen (Lock klappt nicht)
- len = strlen(AktPath);
- if (AktPath[len-1] == '/')
- AktPath[len-1] = '\0';
-
- Info->nfi_DirLock = Lock(AktPath, ACCESS_READ);
- if (Info->nfi_DirLock)
- {
- NameFromLock(Info->nfi_DirLock, NormalizedAktPath, sizeof(NormalizedAktPath));
-
- OldCurrentDir = CurrentDir(DupLock(Info->nfi_DirLock));
-
- if (InitialCurrentDir == ~0)
- InitialCurrentDir = OldCurrentDir;
- else
- UnLock(OldCurrentDir);
- }
- else
- {
- PostError(TRUE, MSGPRI_Warning, GetString(MSG_LOCK_FAILURE), __FUNC__,
- AktPath, GetIoErrText() );
- }
-
-
- if (AktPath[len-1] == '\0')
- AktPath[len-1] = '/';
- }
-
-
- struct DirEntry *NewDir(struct MinList *Home, const char *name, BOOL temp)
- {
- size_t l;
- struct DirEntry *akt;
-
- ASSERT_VALID(Home);
- ASSERT_VALID(name);
-
- l = strlen(name);
-
- akt = (struct DirEntry *) malloc(sizeof(struct DirEntry) + l);
- if (akt == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "akt", sizeof(struct DirEntry) + l);
- myabort(10);
- }
-
- NewList((struct List *) &akt->Sub);
- akt->Root = NULL;
- akt->Virgin = 1;
- akt->Done = 0;
- akt->Temporary = temp;
- akt->Contents = 0;
- strcpy(akt->Name, name);
-
- AddTail((struct List *) Home, (struct Node *) akt);
-
- return akt;
- }
-
-
- // Prüfsumme für Buffer berechnen
- unsigned long ComputeBufferCheckSum(const struct Buffer *buff)
- {
- unsigned long CheckSum;
- const unsigned long *BuffPtr;
- size_t n;
-
- ASSERT_VALID(buff);
-
- for (CheckSum=0L, n=globDrvDat.CylSize/sizeof(long),
- BuffPtr=(const long *) buff->dbp;
- n; n--)
- {
- CheckSum += *BuffPtr++;
- }
-
- return CheckSum;
- }
-
-
- // Prüfsumme für DiskLabel berechnen
- unsigned long ComputeLabelCheckSum(const struct DiskLabel *Label)
- {
- unsigned long CheckSum;
- const unsigned long *LabelPtr;
- size_t n;
-
- ASSERT_VALID(Label);
-
- for (CheckSum=0L, n=sizeof(struct DiskLabel)/sizeof(long),
- LabelPtr=(const long *) Label;
- n; n--)
- {
- CheckSum += *LabelPtr++;
- }
-
- return CheckSum;
- }
-
-
- // Prüfsumme für FileLabel berechnen
- unsigned long ComputeFileLabelCheckSum(const struct FileLabel *Label)
- {
- unsigned long CheckSum;
- const unsigned long *LabelPtr;
- size_t n;
-
- ASSERT_VALID(Label);
-
- n = Label->FL_Length / sizeof(long);
- for (CheckSum=0L, LabelPtr=(const long *) Label; n; n--)
- {
- CheckSum += *LabelPtr++;
- }
-
- return CheckSum;
- }
-
-
- // Bestimmung der physikalischen Länge eines Files.
- // Notwendig zum Lesen des Formats #0 (alt)
- long FileLength(const struct DiskLabel *Label, const struct NameField *nf)
- {
- long laenge;
-
- ASSERT_VALID(Label);
- ASSERT_VALID(nf);
-
- if (!nf->isComplete)
- {
- // File ist nicht vollständig auf dieser Disk
- laenge = Label->EndOfData - nf->Offset;
- if (COMPRESS_NONE == nf->CompressionType)
- laenge = min(laenge, nf->FileLen);
- }
- else
- {
- // File ist komplett
- if (nf->CompressionType != COMPRESS_NONE || nf->Extension)
- {
- if (nf->NextName)
- {
- // nicht das letzte File auf der Disk
- laenge = nf->NextName->Offset - nf->Offset;
- }
- else
- {
- // letztes File aus der Disk
- laenge = Label->EndOfData - nf->Offset;
- }
- }
- else
- {
- laenge = nf->FileLen;
- }
- }
- if (nf->FileLen == 0)
- laenge = 0;
-
- return (laenge);
- }
-
-
- void ShowBackupTime(void)
- {
- static char zeile[80];
-
- sprintf(zeile, "%s %s %s %s",
- GetString(MSG_BACKUP_START),
- DateString(StartZeit[3], StartZeit[2], StartZeit[1]+1980),
- GetString(MSG_STARTTIME),
- TimeString(StartZeit[4], StartZeit[5], StartZeit[6]) );
- SessionInfo(zeile);
- }
-
-
- static ULONG __saveds __asm PreviewHookDisplay(register __a0 struct Hook *theHook,
- register __a1 object,
- register __a2 struct BCInfo *BCount)
- {
- if (BCS_Final == BCount->bci_Status || 0 == BCount->bci_FileCount % BCount->bci_Threshold)
- {
- char Line[40];
-
- sprintf(Line, GetString(MSG_FILES_COLLECTED), BCount->bci_FileCount);
- ShowFileCount(Line);
- }
-
- return 0L;
- }
-
-
- static void action(void)
- {
- if (!CheckPassword(&myOptions)) // ggf. Password anfordern
- return;
-
- getclk(StartZeit); // Startzeit merken
-
- ShowBackupTime(); // Startzeit und -Datum anzeigen
-
- if (myOptions.bo_ProtFile != PT_None)
- OpenProtFile();
-
- NextFileAbort = FALSE;
- disknr = 0;
- DiskUnit = myOptions.bo_FirstUnit;
-
- if (!StartWriter())
- return;
-
- initDisk(); // Startet DiskChanger!
- InitBufReq();
-
- readoffset = globDrvDat.BlockSize; // Sektor 0 überspringen, Header !
- AktPath = NULL;
-
- if (!InitSearchPattern(&myOptions))
- return;
-
- if (myOptions.bo_Preview)
- {
- // Files und Bytes zählen für Preview
- InfoLineHandle Pil;
- struct BCInfo BCount;
- struct Hook PreviewHook;
-
- PreviewHook.h_Entry = HookEntry;
- PreviewHook.h_SubEntry = (unsigned long (* )()) PreviewHookDisplay;
- PreviewHook.h_Data = NULL;
-
- Pil = PushInfoLine(GetString(MSG_CREATING_PREVIEW));
-
- DoByteCount(&myOptions, &BCount, &PreviewHook, 50);
-
- TotalBytes = BCount.bci_ByteCount;
- TotalFiles = BCount.bci_FileCount;
- NextFileAbort = FALSE;
-
- ShowFileCount("");
- PopInfoLine(&Pil);
- }
-
- NFInfo.nfi_TellSkips = TRUE;
-
- // Erste Disk anfordern.
- // Damit werden auch die endgültigen Werte in globDevInfo bestimmt.
- SignalNewDisk();
-
- // <maxbyte> anhand der engültigen globDevInfo-Daten nachtragen
- LockWriteDisk();
- WriteDisk.maxbyte = ReadDisk.maxbyte = globDrvDat.NumCyls * globDrvDat.CylSize;
- UnlockWriteDisk();
-
- // InitCompress() braucht die endgültigen globDevInfo-Daten !!!
- switch (myOptions.bo_Compress)
- {
- case COMPRESS_INTERNAL:
- if (!InitCompress())
- myOptions.bo_Compress = COMPRESS_NONE;
- break;
- case COMPRESS_XPK:
- if (!XPKInitCompress())
- myOptions.bo_Compress = COMPRESS_NONE;
- break;
- }
-
- CheckDriveFormat();
-
- AllocDiskBuffer();
-
- // Buffer erstmal zu 1/2 füllen
- while (!myOptions.bo_Append && !AllFilesRead && BuffersFull < BuffCount/2 )
- lesen();
-
- SignalBeginWriting(); // Jetzt mit Schreiben beginnen
-
- while (!AllFilesRead)
- lesen();
-
- if (!DB_EMPTY(ReadDisk))
- NewReadDisk(NULL);
-
- SignalDiskClose(); // "Letztes Medium komplett" an Writer-Prozeß melden
-
- CompressProtocol(); // jetzt ggf. Protokoll komprimieren
-
- while (!WriteReady())
- eingabe(0l); // Warten bis alles geschrieben
-
- StopWriter(0); // Writer-Prozeß beenden
- }
-
-
- // Prüft Filenamen zum komprimieren, offensichtlich bereits komprimierte
- // Files werden nicht komprimiert.
- // Ebenfalls nicht komprimiert werden Files, die kürzer als 100 Bytes sind
- static void TestCompress(struct NameField *file)
- {
- static const char *NCExt[] =
- { "Z", "ZOO", "ARC", "LZH", "ZIP", "LHA", NULL };
- char FileExt[FMSIZE];
- const char **akt;
-
- ASSERT_VALID(file);
-
- if (file->FileLen < 100l)
- return;
-
- switch (myOptions.bo_Compress)
- {
- case COMPRESS_NONE:
- return;
- case COMPRESS_XPK:
- break;
- case COMPRESS_INTERNAL:
- stcgfe(FileExt, file->Name);
- for (akt=NCExt; *akt; akt++)
- {
- if (stricmp(FileExt, *akt) == 0)
- return;
-
- if (*FileExt && MatchToolValue(myOptions.bo_NeverCompress, FileExt))
- return;
- }
-
- // wegen der Rückwärts-Kompatibilität
- file->isCompressed = TRUE;
- break;
- }
-
- file->CompressionType = myOptions.bo_Compress;
- }
-
-
- enum BufferStatus GetBuffStatus(const struct Buffer *buff)
- {
- ASSERT_VALID(buff);
-
- return buff->Status;
- }
-
-
- void SetBuffStatus(struct Buffer *buff, enum BufferStatus NewState)
- {
- enum BufferStatus OldState;
-
- ASSERT_VALID(buff);
-
- ObtainSemaphore(&buff->BuffSema);
- OldState = buff->Status;
- buff->Status = NewState;
-
- if (NewState == VOLL && OldState != VOLL)
- BuffersFull++;
- else if (OldState == VOLL && NewState != VOLL)
- BuffersFull--;
-
- ASSERT_VALID(buff);
-
- ShowBuffStatus(&CylBuff[0], FALSE); // Änderung gleich anzeigen
- ReleaseSemaphore(&buff->BuffSema);
-
- if (NewState == VOLL)
- SignalBufferFull();
- }
-
-
- void NextBuffNr(unsigned short *CurrentBuffNr)
- {
- ASSERT_VALID(CurrentBuffNr);
-
- *CurrentBuffNr = (*CurrentBuffNr + 1) % BuffCount;
- }
-
-
- struct Buffer *GetBuffer(void)
- {
- struct Buffer *aktbuff;
-
- aktbuff = &CylBuff[ReadBuffNr];
-
- switch (GetBuffStatus(aktbuff))
- {
- case VOLL:
- d(printf("aktbuff %2d %08lx: VOLL\n", ReadBuffNr, aktbuff));
- aktbuff = NULL;
- break;
- case FUELLEN:
- d(printf("aktbuff %2d %08lx: FUELLEN\n", ReadBuffNr, aktbuff));
- break;
- case LEER:
- d(printf("aktbuff %2d %08lx: LEER\n", ReadBuffNr, aktbuff));
- // Neuen Buffer suchen
- aktbuff->WritePtr = aktbuff->dbp + readoffset;
- aktbuff->disknr = ReadDisk.nr; // Buffer zur aktuellen Disk-Nr. zuordnen
- aktbuff->BufferCheckSum = 0L;
- aktbuff->BuffFree = globDrvDat.CylSize - readoffset;
-
- if (ReadDisk.Offset == globDrvDat.BlockSize && readoffset == globDrvDat.BlockSize)
- {
- // Anfang einer neuen Disk, provisorisches Label anlegen
- BuildDiskLabel((struct DiskLabel *) aktbuff->dbp, ReadDisk.nr);
- }
-
- break;
- default:
- d(printf("aktbuff %2d %08lx: ???\n", ReadBuffNr, aktbuff));
- aktbuff = NULL;
- break;
- }
-
- AktReadBuffer = aktbuff;
-
- return aktbuff;
- }
-
-
- void BuildDiskLabel(struct DiskLabel *Label, short DiskNr)
- {
- ASSERT_VALID(Label);
-
- memset(Label, 0, sizeof(struct DiskLabel));
-
- Label->LabelCheckSum = 0l;
- Label->DirCheckSum = 0l;
-
- Label->Version = Version; // Versionsnummer
- Label->diskno = DiskNr;
- Label->RecordedFormat = BACKUP_FORMAT_ID;
- strcpy(Label->Id, DISKID);
- CopyMem(StartZeit, Label->BackupZeit, sizeof(StartZeit) );
-
- if (myOptions.bo_ProtFile != PT_None)
- {
- stccpy(Label->ProtFileName, myOptions.bo_ProtFileName,
- sizeof(Label->ProtFileName));
- }
-
- Label->LabelCheckSum = -ComputeLabelCheckSum(Label);
- }
-
-
- static unsigned long GetNewFile(struct Buffer *aktbuff, BOOL *FileFound)
- {
- BPTR LinkLock;
- unsigned long filesize = 0;
- static BOOL filehanging = FALSE; // zeigt an, wenn File mit NextFile() gefunden,
- // aber auf ReadDisk kein Platz für den Dir.-
- // Eintrag war.
-
- ASSERT_VALID(aktbuff);
- ASSERT_VALID(FileFound);
-
- if (!filehanging)
- {
- // Neues File suchen
- AllFilesRead = !NextFile(&NFInfo, &Root_fib);
-
- // ggf. nächste File-Spec. aus Kommandofile holen
- if (AllFilesRead && aktCmdFile)
- {
- char *path;
-
- path = ReadCmdFile(&myOptions, 1);
- if (path)
- {
- NewDir(&NFInfo.nfi_FirstDir, path, 0);
- AllFilesRead = !NextFile(&NFInfo, &Root_fib);
- }
- }
-
- // jetzt wirklich zu Ende, ProtFile wird ans Ende des Backups angehängt
- if (AllFilesRead && ProtFileHandle)
- {
- char ProtPath[FMSIZE];
-
- LockWriteDisk();
- if (!DB_EMPTY(WriteDisk) && !WriteDisk.dirwritten)
- {
- WriteProtFile(FIRST_NF(WriteDisk), WriteDisk.nr);
- WriteDisk.dirwritten = TRUE;
- }
- UnlockWriteDisk();
-
- if (!DB_EMPTY(ReadDisk) && !ReadDisk.dirwritten)
- {
- WriteProtFile(FIRST_NF(ReadDisk), ReadDisk.nr);
- ReadDisk.dirwritten = TRUE;
- }
-
- CleanupProtFile(TRUE);
-
- myOptions.bo_IncludeSubDirs = 0;
- myOptions.bo_UseArc = Ignore;
- myOptions.bo_SetArc = Set;
- myOptions.bo_UseFirstDate = 0;
- myOptions.bo_UseLastDate = 0;
-
- stcgfp(ProtPath, myOptions.bo_ProtFileName);
- NewDir(&NFInfo.nfi_FirstDir, ProtPath, 0);
-
- stccpy(myOptions.bo_IncludeFile.RawName, NurName(myOptions.bo_ProtFileName),
- sizeof(myOptions.bo_IncludeFile.RawName) );
- myOptions.bo_IncludeFile.isParsed = 0;
- myOptions.bo_ExcludeFile.RawName[0] = '\0';
- myOptions.bo_ExcludeFile.isParsed = 0;
-
- InitSearchPattern(&myOptions);
-
- AllFilesRead = !NextFile(&NFInfo, &Root_fib);
- }
- }
-
- if (!AllFilesRead)
- {
- // Neues File gefunden
- if (EnterName(&Root_fib, ReadDisk.Offset, AktPath, NULL) != NULL)
- {
- filehanging = FALSE;
- *FileFound = TRUE;
-
- if (LONG_MIN == Root_fib.fib_DirEntryType)
- {
- // Partitions (Devices) behandeln
- TestCompress(aktName); // Partition kann komprimiert werden!
-
- aktName->isPartition = 1;
- aktName->FileLen = Root_fib.fib_Size = OpenPartition(aktName->Name, &Root_pInfo);
- if (0 == aktName->FileLen)
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_OPENPARTITION_FAILURE),
- aktName->Name);
- }
- }
- else if (ST_USERDIR == Root_fib.fib_DirEntryType)
- {
- // Directories behandeln
- aktName->isDir = 1;
- aktName->isComplete = 1;
-
- aktName->FileLen = Root_fib.fib_Size = 0;
- }
- else if (!myOptions.bo_SaveSoftLinks &&
- ST_SOFTLINK == Root_fib.fib_DirEntryType)
- {
- // SoftLinks behandeln (File oder Directory)
-
- // Flag für SoftLink setzen, keine Kompression
- aktName->isSoftLink = 1;
-
- LinkPathPtr = LinkPath;
- LinkLock = Lock(AktPath, ACCESS_READ);
-
- if (LinkLock)
- {
- if (ReadLink(DeviceProc(AktPath), LinkLock,
- Root_fib.fib_FileName, LinkPath,
- sizeof(LinkPath)) )
- {
- aktName->FileLen = Root_fib.fib_Size = strlen(LinkPath) + 1;
- }
- else
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_READLINK_FAILURE),
- ShortFileName(aktName->Name, 60),
- GetIoErrText() );
- }
-
- UnLock(LinkLock);
- }
- else
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_LOCK_FAILURE), __FUNC__,
- AktPath, GetIoErrText() );
- }
- }
- else if (!myOptions.bo_SaveHardLinks &&
- (ST_LINKFILE == Root_fib.fib_DirEntryType ||
- ST_LINKDIR == Root_fib.fib_DirEntryType) )
- {
- // HardLinks behandeln (File oder Directory)
-
- // Flag für HardLink setzen, keine Kompression
- aktName->isHardLink = 1;
-
- LinkPathPtr = LinkPath;
- LinkLock = Lock(aktName->Name, ACCESS_READ);
- if (LinkLock)
- {
- if (NameFromLock(LinkLock, LinkPath, sizeof(LinkPath)))
- {
- aktName->FileLen = Root_fib.fib_Size = strlen(LinkPath) + 1;
- }
- else
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_NAMEFROMLOCK_FAILURE),
- ShortFileName(aktName->Name, 60),
- GetIoErrText() );
- }
- UnLock(LinkLock);
- }
- else
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_LOCK_FAILURE), __FUNC__,
- ShortFileName(aktName->Name, 60), GetIoErrText() );
- }
- }
- else
- {
- // normale Files behandeln (keine Links)
- TestCompress(aktName);
-
- aktReadFileHandle = Open(Root_fib.fib_FileName, MODE_OLDFILE);
- if (NULL == aktReadFileHandle)
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_CANNOT_OPENFILE),
- ShortFileName(aktName->Name, 60),
- GetIoErrText() );
-
- *FileFound = FALSE;
- }
- }
-
- filesize = Root_fib.fib_Size;
- }
- else
- {
- // Kein Platz mehr auf ReadDisk für den Directory-Eintrag!
- // Der aktuelle Buffer wird mit 00 gefüllt und als VOLL deklariert.
- if (GetBuffStatus(aktbuff) == FUELLEN)
- {
- memset(AktReadBuffer->WritePtr, 0, AktReadBuffer->BuffFree);
- BufferFull(aktbuff);
- }
- filehanging = TRUE;
- NewReadDisk(&Root_fib); // Weiterlesen für nächste Disk
- }
- }
- else
- {
- *FileFound = FALSE;
-
- // Backup fertig, "Buffer voll" melden.
- // Der aktuelle Buffer wird mit 00 gefüllt und als VOLL deklariert.
- if (GetBuffStatus(aktbuff) == FUELLEN)
- {
- memset(AktReadBuffer->WritePtr, 0, AktReadBuffer->BuffFree);
- BufferFull(aktbuff);
- }
-
- ClearFileName(); // Letzten Filenamen auf der Anzeige löschen
- }
-
- UpdateFileDisplay();
-
- return filesize;
- }
-
-
- // Der aktuelle Lese-Buffer in ReadDisk wird VOLL gemeldet.
- // Liefert TRUE wenn neue ReadDisk, sonst FALSE
- BOOL BufferFull(struct Buffer *aktbuff)
- {
- BOOL NewDisk = FALSE;
-
- ASSERT_VALID(aktbuff);
-
- // aktueller Buffer ist voll
- SetBuffStatus(aktbuff, VOLL);
- aktbuff->BuffFree = 0l;
- readoffset = 0l;
- NextBuffNr(&ReadBuffNr);
-
- if (BuffersFull >= BuffCount/2 )
- SignalBeginWriting(); // Jetzt mit Schreiben beginnen
-
- // Es muß noch Platz sein für den neu anzulegenden Zylinder, sonst neue Disk
- if (isReadDiskFull(globDrvDat.CylSize))
- {
- // Disk ist voll
- NewReadDisk(&Root_fib);
- NewDisk = TRUE;
- }
-
- return NewDisk;
- }
-
-
- struct NameField *GetAktName(void)
- {
- return aktName;
- }
-
-
- // Test, ob auf <ReadDisk> noch Platz ist für <ZusatzPlatz> Bytes.
- // liefert TRUE wenn genug Platz, sonst FALSE.
- static BOOL isReadDiskFull(unsigned long ZusatzPlatz)
- {
- return (short) (ReadDisk.maxbyte <
- ceildiv(ReadDisk.Offset, globDrvDat.CylSize) * globDrvDat.CylSize +
- ceildiv(ReadDisk.dirlength, globDrvDat.CylSize) * globDrvDat.CylSize +
- ZusatzPlatz);
- }
-
-
- static short lesen(void)
- {
- static unsigned long filesize;
- static unsigned long FLSize;
- static BOOL FileInArbeit = FALSE;
- static BOOL inFileLabel = FALSE;
- static struct FileLabel *aktFileLabel = NULL;
- static struct FileLabel *FileLabelPtr;
- long NewFlags;
- short result;
-
- chkinput();
-
- if (AllFilesRead) // Backup zu Ende
- return FALSE;
-
- GetBuffer();
-
- if (AktReadBuffer != NULL) // freien Buffer gefunden
- {
- result = TRUE;
-
- if (!FileInArbeit)
- {
- filesize = GetNewFile(AktReadBuffer, &FileInArbeit);
-
- // FileLabel erzeugen wenn Backup auf Tape
- inFileLabel = AktReadBuffer->TapeReq != NULL;
- }
-
- if (FileInArbeit)
- {
- unsigned long readlen, count;
-
- if (GetBuffStatus(AktReadBuffer) == LEER)
- {
- // Neuen Buffer jetzt belegen
- SetBuffStatus(AktReadBuffer, FUELLEN);
- }
-
- if (inFileLabel)
- {
- // FileLabel sichern
- if (aktFileLabel == NULL)
- {
- // aktFileLabel neu anlegen
- long FLSkip;
-
- // die Länge muß auf Langworte aufgerundet werden
- FLSize = sizeof(struct FileLabel) + aktName->NameLen;
- if (FLSize & 0x03)
- FLSize = (FLSize & ~0x03) + 4;
-
- aktFileLabel = calloc(FLSize, 1);
- if (aktFileLabel == NULL)
- {
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "aktFileLabel", FLSize);
- myabort(10);
- }
- aktFileLabel->FL_Magic1 = FILELABEL;
- aktFileLabel->FL_Magic2 = -FILELABEL;
- aktFileLabel->FL_CheckSum = 0l;
- aktFileLabel->FL_Length = FLSize;
-
- CopyMem(aktName, &aktFileLabel->FL_nf, NF_LEN(aktName));
-
- FileLabelPtr = aktFileLabel;
- aktFileLabel->FL_nf.Offset += FLSize;
-
- // Beginn des FileLabel an einer Block-Grenze
- FLSkip = globDrvDat.BlockSize - (readoffset % globDrvDat.BlockSize);
- if (FLSkip > 0 && FLSkip < globDrvDat.BlockSize)
- {
- memset(AktReadBuffer->WritePtr, 0, FLSkip);
- readoffset += FLSkip;
- ReadDisk.Offset += FLSkip;
- AktReadBuffer->WritePtr += FLSkip;
- AktReadBuffer->BuffFree -= FLSkip;
- aktFileLabel->FL_nf.Offset += FLSkip;
- }
-
- aktFileLabel->FL_CheckSum = -ComputeFileLabelCheckSum(aktFileLabel);
- }
-
- readlen = min(FLSize, AktReadBuffer->BuffFree);
- if (readlen)
- CopyMem(aktFileLabel, AktReadBuffer->WritePtr, readlen);
-
- FileLabelPtr += readlen;
- FLSize -= readlen;
- readoffset += readlen;
- ReadDisk.Offset += readlen;
- AktReadBuffer->WritePtr += readlen;
- AktReadBuffer->BuffFree -= readlen;
-
- if (FLSize == 0)
- {
- // FileLabel fertig gesichert
- if (aktFileLabel)
- free(aktFileLabel);
- aktFileLabel = NULL;
- inFileLabel = FALSE;
- aktName->Offset = ReadDisk.Offset;
- }
- }
- else if (aktName->CompressionType != COMPRESS_NONE)
- {
- switch (aktName->CompressionType)
- {
- case COMPRESS_INTERNAL:
- CompressFile(aktName, filesize, NULL);
- break;
- case COMPRESS_XPK:
- XPKCompressFile(aktName, filesize);
- break;
- default:
- alarm(GetString(MSG_UNKNOWNCOMPRESSION));
- myabort(20);
- break;
- }
-
- filesize = 0;
- }
- else if (aktName->isSoftLink || aktName->isHardLink)
- {
- // Link sichern
- readlen = min(filesize, AktReadBuffer->BuffFree);
- if (readlen)
- CopyMem(LinkPathPtr, AktReadBuffer->WritePtr, readlen);
-
- LinkPathPtr += readlen;
- filesize -= readlen;
- readoffset += readlen;
- ReadDisk.Offset += readlen;
- AktReadBuffer->WritePtr += readlen;
- AktReadBuffer->BuffFree -= readlen;
- aktName->RecordedLen += readlen;
-
- BytesProcessed += readlen;
- }
- else if (aktName->isPartition)
- {
- // Partition sichern
- readlen = min(filesize, AktReadBuffer->BuffFree);
- ReadPartition(&Root_pInfo, readlen, AktReadBuffer->WritePtr);
-
- filesize -= readlen;
- readoffset += readlen;
- ReadDisk.Offset += readlen;
- AktReadBuffer->WritePtr += readlen;
- AktReadBuffer->BuffFree -= readlen;
- aktName->RecordedLen += readlen;
-
- BytesProcessed += readlen;
- }
- else if (aktName->isDir)
- {
- // Directory sichern
- filesize = 0;
- }
- else
- {
- // normales File sichern
- readlen = min(filesize, AktReadBuffer->BuffFree);
-
- if (aktReadFileHandle == NULL)
- {
- alarm("%s: aktReadFileHandle == NULL", __FUNC__);
- myabort(30);
- }
- count = Read(aktReadFileHandle, AktReadBuffer->WritePtr, readlen);
-
- if (count != readlen)
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_ERROR_READINGFILE),
- ShortFileName(aktName->Name, 60),
- GetIoErrText() );
- filesize = count;
- }
- filesize -= count;
- readoffset += count;
- ReadDisk.Offset += count;
- AktReadBuffer->WritePtr += count;
- AktReadBuffer->BuffFree -= count;
- aktName->RecordedLen += count;
- BytesProcessed += readlen;
- }
-
- if (0 == filesize)
- {
- // File fertig gelesen
- aktName->isComplete = 1; // File komplett auf akt. Disk
-
- if (aktName->isPartition)
- {
- ClosePartition(&Root_pInfo);
- }
- if (LONG_MIN == Root_fib.fib_DirEntryType ||
- Root_fib.fib_DirEntryType < 0)
- {
- // Achtung: genau gleiche Abfrage hier wie in GetByteCount()
- FilesProcessed++;
- }
-
- if (aktReadFileHandle)
- {
- Close(aktReadFileHandle);
- aktReadFileHandle = NULL;
- }
-
- aktNameDone();
- FileInArbeit = FALSE;
-
- // Jetzt Archiv-Flag setzen oder löschen
- if (myOptions.bo_SetArc != Ignore && !aktName->isPartition)
- {
- NewFlags = Root_fib.fib_Protection;
-
- switch (myOptions.bo_SetArc)
- {
- case Set:
- NewFlags |= FIBF_ARCHIVE;
- break;
- case Reset:
- NewFlags &= ~FIBF_ARCHIVE;
- break;
- }
-
- if (NewFlags != Root_fib.fib_Protection &&
- !SetProtection(Root_fib.fib_FileName, NewFlags))
- {
- if (!aktName->isDir)
- {
- PostError(TRUE, MSGPRI_Warning,
- GetString(MSG_ERROR_SETPROTECTION),
- ShortFileName(NurName(aktName->Name), 60),
- GetIoErrText() );
- }
- }
- }
-
- }
-
- if (AktReadBuffer && AktReadBuffer->BuffFree <= 0)
- {
- // aktueller Buffer ist voll
- BufferFull(AktReadBuffer);
- }
-
- UpdateFileDisplay();
- }
- }
- else // alle Buffer sind voll
- {
- eingabe(0l); // Warten bis Buffer leer oder Abbruch...
- result = FALSE;
- }
-
- return result;
- }
-
-
- static void initDisk(void)
- {
- unsigned short i;
-
- assert(myOptions.bo_FirstUnit >= 0 && myOptions.bo_FirstUnit < NDisk);
-
- // globale Diskparameter provisorisch eintragen.
- // Die endgültigen Werte werden von newdisk() eingetragen sobald
- // die erste Disk eingelegt ist.
- globDrvDat = Disks[myOptions.bo_FirstUnit].DrvDat;
- globDrvDat.isPreliminary = TRUE;
-
- DiskChangeMaske = 0L;
-
- if (CylBuff[0].dbp)
- {
- for (i=0; i<BuffCount; i++)
- SetBuffStatus(&CylBuff[i], LEER); // alle Buffer leer
- }
-
- InitSemaphore(&WriteDiskSema);
-
- NewList((struct List *) &ReadDisk.DirBuffers);
- ReadDisk.dirlength = 0;
- ReadDisk.diranf = 0;
- ReadDisk.diranz = 0;
- ReadDisk.maxbyte = globDrvDat.NumCyls * globDrvDat.CylSize;
- ReadDisk.Offset = globDrvDat.BlockSize;
- ReadDisk.nr = 1;
-
- LockWriteDisk();
- WriteDisk = ReadDisk;
- NewList((struct List *) &WriteDisk.DirBuffers);
- WriteDisk.dirwritten = 1;
- UnlockWriteDisk();
-
- AllFilesRead = FALSE;
- FilesProcessed = BytesProcessed = 0;
- aktName = NULL;
- ReadBuffNr = WriteBuffNr = OldestWriteBuffNr = 0;
-
- InitDiskUnit(myOptions.bo_FirstUnit, 1, TRUE); // enthält StartDiskChanger()
-
- if (myOptions.bo_SecondUnit != NO_DRIVE)
- {
- InitDiskUnit(myOptions.bo_SecondUnit, 2, FALSE);
- DiskUnit = myOptions.bo_SecondUnit; // nachher beginnen mit myOptions.bo_FirstUnit
- }
- else if (NULL == Disks[DiskUnit].TapeReq)
- GhostField();
-
- // feststellen ob Backup auf Tape
- toTape = Disks[DiskUnit].TapeReq != NULL;
- }
-
-
- static void InitDiskUnit(short Unit, short DiskNo, BOOL FirstDisk)
- {
- assert(Unit >= 0 && Unit < NDisk);
-
- if (Disks[Unit].DcI)
- return; // Unit ist schon initialisiert
-
- if (Disks[Unit].TapeReq == NULL)
- inhibit(TRUE, &Disks[Unit]); // Laufwerk sperren
-
- Disks[Unit].DcI = StartDiskChanger(Unit, FirstDisk, DiskNo);
-
- if (Disks[Unit].DcI == NULL)
- {
- alarm(GetString(MSG_CANNOT_START_DISKCHANGER), Disks[Unit].DOSName);
- myabort(10);
- }
- }
-
-
- static void NewReadDisk(struct FileInfoBlock *fib)
- {
- long save;
- short DiskNr;
-
- if (fib == NULL)
- {
- while (!DB_EMPTY(WriteDisk))
- Delay(25); // 0.5s warten
- }
-
- LockWriteDisk();
- if (!DB_EMPTY(WriteDisk))
- {
- UnlockWriteDisk();
- alarm(GetString(MSG_INTERNALERROR_NEWREADDISK));
- myabort(50);
- }
-
- save = WriteDisk.Offset;
- WriteDisk = ReadDisk;
- WriteDisk.MaxOffset = ReadDisk.Offset;
- WriteDisk.Offset = save;
- DiskNr = WriteDisk.nr;
- MoveDirBuff(&WriteDisk, &ReadDisk);
- UnlockWriteDisk();
-
- ReadDisk.dirwritten = 0;
- ReadDisk.dirlength = 0;
- ReadDisk.diranf = 0;
- ReadDisk.diranz = 0;
- ReadDisk.maxbyte = globDrvDat.NumCyls * globDrvDat.CylSize;
- ReadDisk.nr = DiskNr + 1;
- ReadDisk.Offset = readoffset = globDrvDat.BlockSize;
-
- if (fib && aktName && !aktName->isComplete)
- {
- // Überlauf-Eintrag für letzte Datei behalten !
- struct NameField *Last;
-
- ASSERT_VALID(fib);
-
- aktNameDone();
-
- Last = aktName;
- aktName = NULL;
-
- EnterName(fib, ReadDisk.Offset, AktPath, Last); // halbfertiges File auf der nächsten Disk weiterführen
- aktName->Extension++;
- aktName->RecordedLen = 0l;
- }
- else
- aktName = NULL;
- }
-
-
- void MoveDirBuff(struct Disk *Dest, struct Disk *Source)
- {
- ASSERT_VALID(Dest);
- ASSERT_VALID(Source);
-
- NewList((struct List *) &(Dest->DirBuffers));
-
- // Alle Listeneinträge in DirBuffers umhängen von <Source> nach <Dest>
- while (!IsListEmpty((struct List *) &(Source->DirBuffers)))
- {
- struct Node *dbNode = (struct Node *) RemHead((struct List *) &Source->DirBuffers);
- AddTail((struct List *) &(Dest->DirBuffers), dbNode);
- }
- }
-
-
- // Verriegeln der NameField-Verkettung über <aktName>
- void LockNFList(void)
- {
- ObtainSemaphore(&NFSema);
- }
-
-
- // Entriegeln der NameField-Verkettung über <aktName>
- void UnlockNFList(void)
- {
- ReleaseSemaphore(&NFSema);
- }
-
-
- void FillNameField(struct NameField *akt, const struct FileInfoBlock *fib)
- {
- akt->FileLen = fib->fib_Size;
- akt->FileDate = fib->fib_Date;
- akt->Protection = fib->fib_Protection;
- akt->NameLen = 0;
- akt->RecordedLen = 0l;
- akt->Extension = 0;
- akt->SessionNr = 0;
- akt->isComplete = 0;
- akt->isSoftLink = 0;
- akt->isHardLink = 0;
- akt->isDir = 0;
- akt->DiskNr = 0;
- akt->CompressionType = COMPRESS_NONE;
- akt->Reserved1 = 0;
- akt->Reserved2 = 0;
- akt->NFCheckSum = 0;
- // memset(akt->Reserved2, 0, sizeof(akt->Reserved2));
- }
-
-
- // ist ein Kommentar zum File (FileNote) vorhanden, wird er, getrennt
- // durch ein \0, an den kompletten Filenamen angehängt.
- // Return NULL, wenn der Platz auf der Diskette <ReadDisk> nicht mehr
- // für den nächsten Directory-Buffer ausreicht.
- struct NameField *EnterName(struct FileInfoBlock *fib, unsigned long offset,
- const char *path, struct NameField *Stencil)
- {
- size_t pathlen, len;
- BOOL kommda;
- struct NameField *akt;
- char *commstr;
-
- LockNFList();
-
- if (Stencil)
- {
- ASSERT_VALID(Stencil);
- len = NF_LEN(Stencil);
- }
- else
- {
- ASSERT_VALID(path);
- ASSERT_VALID(fib);
-
- if (fib->fib_DirEntryType == ST_SOFTLINK)
- {
- // Softlinks jetzt auflösen
- static struct FileInfoBlock __aligned LinkFib;
- BPTR LinkLock;
-
- LinkLock = Lock((STRPTR) path, ACCESS_READ);
- if (LinkLock)
- {
- ResolveSoftLink(fib->fib_FileName, LinkLock, &LinkFib);
- UnLock(LinkLock);
-
- // wahre Filegröße eintragen
- fib->fib_Size = LinkFib.fib_Size;
- }
- else
- {
- PostError(TRUE, MSGPRI_Error,
- GetString(MSG_LOCK_FAILURE), __FUNC__,
- path, GetIoErrText() );
- }
- }
-
- pathlen = strlen(path);
- kommda = (BOOL) (fib->fib_Comment[0]); // Ist Kommentar (FileNote) vorhanden ?
- len = sizeof(struct NameField) + strlen(fib->fib_FileName) + pathlen;
- if (kommda) // Extra Platz für Kommentar reservieren
- len += strlen(fib->fib_Comment) + 1;
- }
-
- if (len & 0x01)
- len++; // len auf gerade Werte runden
- // len = 2 * ceildiv(len, 2); // len auf gerade Werte runden !
-
- if (DB_EMPTY(ReadDisk) || len > LATEST_DB(ReadDisk)->Space)
- {
- // neuen Buffer anlegen
- struct DirBlock *aktblock;
- unsigned long RestLaenge;
-
- // Es muß noch Platz sein für den neu anzulegenden Dir-Cylinder
- if (isReadDiskFull(globDrvDat.CylSize))
- {
- // kein Platz mehr auf ReadDisk
- UnlockNFList();
- return NULL;
- }
-
- RestLaenge = len - LATEST_DB(ReadDisk)->Space;
-
- aktblock = (struct DirBlock *) AllocVec( sizeof(struct DirBlock) + globDrvDat.CylSize, globDrvDat.BufMemType|MEMF_CLEAR);
- if (aktblock == NULL)
- {
- UnlockNFList();
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "aktblock", sizeof(struct DirBlock) + globDrvDat.CylSize);
- myabort(10);
- }
-
- aktblock->DataLength = aktblock->Space = globDrvDat.CylSize;
- aktblock->wp = aktblock->Data;
-
- if (RestLaenge < len)
- {
- akt = (struct NameField *) calloc(len, 1);
- if (akt == NULL)
- {
- UnlockNFList();
- alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "akt", len);
- myabort(10);
- }
- aktblock->LostNF = akt;
-
- aktNameInfo.FirstPart = LATEST_DB(ReadDisk)->wp;
- aktNameInfo.SecondPart = aktblock->wp;
- aktNameInfo.FirstPartLen = LATEST_DB(ReadDisk)->Space;
- aktNameInfo.SecondPartLen = RestLaenge;
- aktNameInfo.aktName = akt;
- }
- else
- {
- aktblock->LostNF = NULL;
- akt = (struct NameField *) aktblock->wp;
- }
-
- LATEST_DB(ReadDisk)->Space = 0;
-
- AddTail((struct List *) &ReadDisk.DirBuffers, (struct Node *) aktblock);
-
- LATEST_DB(ReadDisk)->wp += RestLaenge;
- LATEST_DB(ReadDisk)->Space -= RestLaenge;
- }
- else
- {
- akt = (struct NameField *) LATEST_DB(ReadDisk)->wp;
- LATEST_DB(ReadDisk)->wp += len;
- LATEST_DB(ReadDisk)->Space -= len;
- }
-
- if (Stencil)
- {
- *akt = *Stencil;
- CopyMem(Stencil->Name, akt->Name, Stencil->NameLen+1);
- }
- else
- {
- FillNameField(akt, fib);
- akt->NameLen = strlen(fib->fib_FileName) + pathlen;
- if (kommda)
- akt->NameLen += strlen(fib->fib_Comment) + 1;
- akt->SessionNr = CurrentSessionNr;
-
- akt->DiskNr = ReadDisk.nr;
- akt->CompressionType = COMPRESS_NONE;
-
- strcpy(akt->Name, path);
- strcat(akt->Name, fib->fib_FileName);
-
- if (kommda)
- {
- // Kommentar zum File an den Namen anhängen
- commstr = akt->Name + strlen(akt->Name) + 1;
- strcpy(commstr, fib->fib_Comment);
- }
- }
-
- akt->Offset = offset;
-
- akt->NextName = NULL;
-
- if (aktName)
- aktName->NextName = akt;
-
- aktName = akt;
-
- ReadDisk.dirlength += len;
- ReadDisk.diranz++;
-
- UnlockNFList();
-
- return akt;
- }
-
-
- // liegt aktName auf der Grenze zwischen zwei DirBlocks, dann wird hier
- // der endgültige Inhalt von aktName in die beiden DirBlocks kopiert.
- // aktName selber wird nicht aufgelöst, da z.B. WriteProtFile() später noch
- // über die Verkettung ->NextName darauf zugreift.
- //
- // Die hierfür temporär angelegten NameFields werden gelöscht in CleanupRWDisk().
- void aktNameDone(void)
- {
- ComputeNfChecksum(aktName);
-
- if (aktNameInfo.FirstPart && aktNameInfo.FirstPartLen)
- {
- CopyMem((char *) aktName, aktNameInfo.FirstPart, aktNameInfo.FirstPartLen);
- CopyMem(((char *) aktName) + aktNameInfo.FirstPartLen, aktNameInfo.SecondPart,
- aktNameInfo.SecondPartLen);
- aktNameInfo.FirstPart = NULL;
- aktNameInfo.FirstPartLen = 0;
- }
- }
-
-
- // sucht in ReadDisk nach dem File, das zwischen <MinOffset> und <MaxOffset>
- // aufgezeichnet ist. Liefert den NameField zurück oder NULL
- struct NameField *LookupFile(unsigned long MinOffset, unsigned long MaxOffset)
- {
- struct NameField *akt;
- BOOL found = FALSE;
-
- akt = FIRST_NF(ReadDisk);
- while (akt && !found)
- {
- found = !((akt->Offset > MaxOffset) ||
- ((akt->Offset + akt->RecordedLen) < MinOffset));
-
- if (!found)
- akt = akt->NextName;
- }
-
- return akt;
- }
-
-
- // Laufwerk <Dsk>: sperren mit <onoff>=TRUE, mit <onoff>=FALSE => freigeben
- static long inhibit(BOOL onoff, struct DiskFlags *Dsk)
- {
- char tline[20];
- long erg;
-
- ASSERT_VALID(Dsk);
-
- Dsk->inhibited = onoff;
- sprintf(tline, "%s:", Dsk->DOSName);
- erg = Inhibit(tline, onoff ? DOSTRUE : DOSFALSE);
-
- // Spezialbehandlung:
- // wenn die Laufwerke DF0: bis DF3: benutzt werden,
- // wird (falls vorhanden) gleichzeitig PC0: bis PC3: stillgelegt,
- // da sich sonst der PCx-Handler mit Backup ins Gehege kommt.
- if (0 == strnicmp(Dsk->DOSName, "DF", 2) && strlen(Dsk->DOSName) == 3 && isdigit(Dsk->DOSName[2]))
- {
- short PCNr;
-
- PCNr = atoi(Dsk->DOSName + 2);
- if (PCNr >= 0 && PCNr <= 3)
- {
- char PCName[5];
-
- sprintf(PCName, "PC%d:", PCNr);
- Inhibit(PCName, onoff ? DOSTRUE : DOSFALSE);
- }
- }
-
- return erg;
-
- }
-
-
- // Prüfung, ob Ziel- und Quell-Device gleich sind.
- // Return FALSE wenn Ok, TRUE wenn Quelle und Ziel sich überschneiden
- static short CheckVolumes(const struct BackupOptions *Opt, short unit)
- {
- static struct FileInfoBlock __aligned fib;
- long n;
- struct Process *Proc;
- APTR OrigWindowPtr;
- struct FSDir *Dir;
- BPTR VolLock;
- char VolumeName[FNSIZE+2];
-
- ASSERT_VALID(Opt);
-
- if (unit == NO_DRIVE)
- return FALSE;
-
- assert(unit >= 0 && unit < NDisk);
-
- if (Disks[unit].TapeReq)
- return FALSE; // Tape kann keine Quelle sein
-
- Proc = (struct Process *) FindTask(NULL);
-
- OrigWindowPtr = Proc->pr_WindowPtr;
- Proc->pr_WindowPtr = (APTR) ~0; // Fehler-Requester unterdrücken
-
- strcpy(VolumeName, Disks[unit].DOSName);
- strcat(VolumeName, ":");
- VolLock = Lock(VolumeName, ACCESS_READ);
-
- Proc->pr_WindowPtr = OrigWindowPtr; // .. restaurieren
-
- if (VolLock)
- {
- Examine(VolLock, &fib);
- UnLock(VolLock);
- }
- else
- return FALSE;
-
- for (n=0; n<Opt->bo_FSDirCount; n++)
- {
- Dir = Opt->bo_FSDirList[n];
-
- if (Dir->fsd_SelectCount)
- {
- if (Dir->fsd_isVolList)
- {
- unsigned short cnt;
-
- for (cnt=0; cnt<Dir->fsd_DirCount; cnt++)
- {
- if (Dir->fsd_EntryList[cnt]->fse_Selected &&
- CmpVolumeName(Dir->fsd_EntryList[cnt]->fse_Name, fib.fib_FileName))
- {
- return TRUE;
- }
- }
- }
- else if (CmpVolumeName(Dir->fsd_Name, fib.fib_FileName))
- return 1;
- }
- }
-
- return FALSE;
- }
-
-
- static BOOL CmpVolumeName(char *DirName, char *VolName)
- {
- BOOL Result;
- BPTR DirLock, VolLock;
-
- ASSERT_VALID(DirName);
- ASSERT_VALID(VolName);
-
- DirLock = Lock(DirName, ACCESS_READ);
- VolLock = Lock(VolName, ACCESS_READ);
-
- Result = SameDevice(DirLock, VolLock);
-
- if (DirLock)
- UnLock(DirLock);
- if (VolLock)
- UnLock(VolLock);
-
- return Result;
- }
-
-
- // Prüfen, ob die beiden eingestellten Laufwerke gleiche Formate haben
- static void CheckDriveFormat(void)
- {
- if (CheckVolumes(&myOptions, myOptions.bo_FirstUnit) || CheckVolumes(&myOptions, myOptions.bo_SecondUnit))
- {
- alarm(GetString(MSG_SAME_DEVICE));
- myabort(1);
- }
- }
-
-
- char *GetIoErrText(void)
- {
- static char ErrBuff[80];
-
- ErrBuff[0] = '\0';
-
- Fault(IoErr(), (STRPTR) "", ErrBuff, sizeof(ErrBuff));
-
- return ErrBuff;
- }
-
-
- void LockWriteDisk(void)
- {
- ObtainSemaphore(&WriteDiskSema);
- }
-
-
- void UnlockWriteDisk(void)
- {
- ReleaseSemaphore(&WriteDiskSema);
- }
-
-
- // NameField-Prüfsumme berechnen
- void ComputeNfChecksum(struct NameField *akt)
- {
- char *p;
- size_t len;
- unsigned char Cks;
-
- ASSERT_VALID(akt);
-
- akt->NFCheckSum = 0;
- p = (char *) akt + sizeof(akt->NextName);
- for (len=sizeof(akt->NextName), Cks=0; len < NF_LEN(akt); len++)
- {
- Cks += *p++;
- }
- akt->NFCheckSum = -Cks;
-
- // if (!akt->isComplete)
- // {
- // kprintf(__FUNC__ ": Name=\"%s\" compl=%ld Cks=%lx\n", akt->Name, (long) akt->isComplete, (long) akt->NFCheckSum);
- // }
- }
-
-
- #ifndef NDEBUG
- extern void __assert(int, const char *, const char *, int);
-
- void __assert(int Result, const char *Expression, const char *File, int Line)
- {
- if (!Result)
- {
- alarm("File %s, Line %ld:\nAssertion \"%s\" Failed",
- File, Line, Expression);
- myabort(99);
- }
- }
- #endif
-
-
- void main(int argc, char *argv[])
- {
- long startzeit, endzeit;
- ULONG StackSize;
-
- OpenAll();
-
- StackSize = stacksize();
- if (StackSize < MIN_STACK - 512)
- {
- alarm(GetString(MSG_STACK_TOO_SMALL), MIN_STACK, StackSize);
- myabort(20);
- }
-
- GetParms(argc, argv);
-
- PrepareMainWindow(CmdFileName);
-
- if (NO_DRIVE != myOptions.bo_FirstUnit && Disks[myOptions.bo_FirstUnit].TapeReq)
- {
- Disks[myOptions.bo_FirstUnit].diskreq = OpenDisk(&Disks[myOptions.bo_FirstUnit], TRUE);
- if (Disks[myOptions.bo_FirstUnit].diskreq)
- {
- Disks[myOptions.bo_FirstUnit].TapeReq->Req = Disks[myOptions.bo_FirstUnit].diskreq;
-
- TapeInitProperties(Disks[myOptions.bo_FirstUnit].TapeReq);
- CloseDisk(&Disks[myOptions.bo_FirstUnit], CDP_KeepTape);
- CleanUpDisk(&Disks[myOptions.bo_FirstUnit], 0);
- }
-
- if (!Disks[myOptions.bo_FirstUnit].DrvDat.Properties.DriveKnown)
- {
- // Start mit einem unbekannten Bandlaufwerk
- alarm(GetString(MSG_UNKNOWN_TAPEDRIVE), Disks[myOptions.bo_FirstUnit].DOSName);
- SetupTape(aktWindow, &Disks[myOptions.bo_FirstUnit]);
-
- myabort(1);
- }
- }
-
- startzeit = gettime();
- action();
- endzeit = gettime();
-
- if (InteractiveBackup || ErrorCount)
- {
- SignalUnIconifyMainWindow();
- printstat(FilesProcessed, BytesProcessed, startzeit, endzeit, toTape);
- }
- }
-