home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * BACKUP.C
- *
- * (C)Copyright 1986-90, Matthew Dillon, All Rights Reserved.
- * Permission is granted to distribute for non-profit only.
- *
- * Thanks to Jan Sven Trabandt for finding some major bugs!
- *
- * This program will backup a filesystem or directory, creating a single
- * output file which can later be RESTORE'd from. It is a quick way to
- * backup your work to a 'backup' disk.
- *
- * backup [options] path path path ... path [-ooutputfile]
- *
- * NOTE: if -o is not specified, not output file will be created
- *
- * NOTE: Any files/directories containing the keyword NOBACKUP in
- * its comment field will not be backed up.
- *
- * options:
- *
- * -0 (Restore): Cause all restored files to be placed
- * in the current (or -o) directory. No directory
- * structure is restored at all
- *
- * -A ARCHIVE. Clear the archive bit on backed up files
- *
- * -U UPDATE. Backup only those files which have the archive bit
- * cleared.
- *
- * -f[#KB] Floppy... actually, this option is used to force the backup
- * program to automatically split up the backup files in #KB
- * sections (default 800). I.E. -f with nothing else will
- * use 800KB chunks. -f200 would use 200KB chunks, etc...
- *
- * PLEASE SEE THE DOCS FOR MORE INFORMATION ON FLOPPY BACKUP
- * AND RESTORE
- *
- * -Fvol example: -FDF0: -FDF1: This command specifies the ordering
- * and number of (floppy) drives to backup to. This allows
- * one to change floppies in one drive while it is backing up
- * to another. It automatically cycles through the drives but
- * you still must specify an initial output file (-ofile) to
- * determine the base name for the files.
- *
- * This command also forces user prompting.
- *
- * PLEASE SEE THE DOCS FOR MORE INFORMATION ON FLOPPY BACKUP
- * AND RESTORE
- *
- * -b backup (default if executable name is 'backup')
- *
- * -r restore (default if executable nam is 'restore')
- *
- * -a append to the destination file.
- *
- * -c Compress files during backup
- *
- * -Cpat add file pattern to those which will not
- * be compressed.
- *
- * -s Only display directories as we go along.
- *
- * -l/-t (either option) Causes a RESTORE to only LIST the files,
- * not do an actual restore.
- *
- * -T (Restore) TIMESTAMP, COMMENT, AND PROTECTION BITS ONLY.
- * NO files are created. It is assumed the files already
- * exist. The timestamp and other fields are transfered
- * from the backup file to the already-restored files (useful
- * if the files were restored with a copy command that did
- * non copy the timestamps. Even if the backup file is old,
- * you can recover most of your time data).
- *
- * -S Silent. Don't display files or directories.
- *
- * -nKB Set buffer size to use, in KB.
- *
- * -v Verbose... Additionaly, display those files which will NOT
- * be backed up.
- *
- * -pPAT only file-paths matching this pattern are backed up. You
- * may specify more than one '-p' option.
- *
- * -dPAT file-paths matching this pattern are NOT backed up. you
- * may specify more than one '-d' option.
- *
- * -ofile Output File
- *
- * -Ooffset Set Offset (manual recover on restore)
- *
- * ---------------------------------------------------------------------
- *
- * destination file format:
- *
- * HDR = <HDR><N.B><datestamp> -Backup Date
- * VOL = <VOL><name_size.B><name> -VOLUME base
- * DDS = <DDS><name_size.B><name> -down-directory
- * END = <END><0.B> -up directory
- * DAT = <DAT><N.B><datestamp> -datestamp for file
- * PRO = <PRO><4.B><protection> -protection for file
- * COM = <COM><N.B><comment> -comment for file
- * FIL0= <FIL0><N.B><name><size.L><data> -uncompressed file
- * FIL1= <FIL1><N.B><name><size.L><usize.L><data> -compressed form #1
- * INC = <INC><12.B><ttlsize><strt><segsize> -next file is part of an
- * incomplete file
- */
-
- #include "defs.h"
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
-
- ubyte Break;
- ubyte Restore;
- ubyte NoStructure;
- ubyte ListOnly;
- ubyte ShowFiles = 1;
- ubyte ShowDirs = 1;
- ubyte Verbose;
- ubyte Archive;
- ubyte Update;
- ubyte Append;
- ubyte Compress;
- ubyte TimeStampOnly;
- char *OutFile;
- long BacBytes;
- short BacCnt = 1;
- short MyBreak;
-
- char DirPath[256];
- short DPLen;
-
- char *BadFormat;
-
- long BufSize = 65536;
- long BufI;
- ubyte *Buf;
- long InBufSize = 8192;
- long InBufI, InBufN;
- ubyte *InBuf;
- char Overide;
-
- MLIST VList; /* Volume list (-F), of NODEs */
- MLIST DList; /* Directory Stack */
-
- MLIST CSList; /* compression patterns */
- MLIST PSList; /* pick patterns */
- MLIST DSList; /* don't pick patterns */
-
- long CLen; /* Actual compressed file output length */
- MLIST CList; /* List of memory buffers */
- SCOMP *CWrite; /* Current memory buffer pointer */
-
- extern void *GetHead(MLIST *);
- extern void *GetTail(MLIST *);
- extern void *GetSucc(MNODE *);
- extern void *GetPred(MNODE *);
-
- void AddPattern (MLIST *, char *);
- void BackupFiles (int, char **);
- void RestoreFiles(int, char **, long);
- FIB *GetFileInfo(char *, long *);
- void FreeFileInfo(FIB *, long);
- void PushDir (char *, long);
- int PopDirs (uword);
- void BackupFlagHasFile(void);
- long scan_directory(FIB *, long);
- int mycheckbreak(void);
- long scan_file (FIB *, long);
- int match_file (char *);
- void writeheaders(FIB *);
- int newfile (void);
- int read_file (short, char *, long, long);
- int openoutput (char *, int, int);
- void oputc (char);
- void outlwatseek (long, long);
- void owrite (void *, long);
- void dumpoutput (void);
- void dumpcrc (void);
- void closeoutput (void);
- long outbytes (void);
- void outentry (ubyte, int, void *);
- int openinput (char *, long);
- void closeinput (void);
- void seekinputend(void);
- void setinputbound(long);
- long oread (void *, long);
- void AppendCrc (ubyte *, long);
- int oreadchar (void);
- void rollbackinput(void);
- void mputc (char);
- void mwrite (char *, long);
- SCOMP *NewSComp (void);
- void transfer0 (long);
- void transfer1 (void);
-
- int brk (void);
- void UnCompressFile(long);
- long CompressFile(char *, long);
-
-
- int
- brk()
- {
- MyBreak = 1;
- return(0);
- }
-
- main(ac, av)
- char **av;
- {
- register short i, notdone;
- register char *str;
- long manOffset = 0;
- short xac = 0;
- static char *Xav[256];
-
- BadFormat = "Bad Format";
- SetSignal(0, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D);
- onbreak(brk);
-
- NewList(&VList);
- NewList(&DList);
- NewList(&CList);
-
- NewList(&PSList);
- NewList(&DSList);
- NewList(&CSList);
-
- AddPattern(&CSList, "*.Z");
- AddPattern(&CSList, "*.ARC");
- AddPattern(&CSList, "*.ZOO");
- AddPattern(&CSList, "*.LZH");
-
- for (str = av[0] + strlen(av[0]); str >= av[0] && *str != '/' && *str != ':'; --str);
- ++str;
- if ((*str|0x20) == 'r')
- Restore = 1;
-
- if (ac == 1) {
- printf("Backup/Restore V2.06, (c)Copyright 1988,1989 Matthew Dillon, All Rights Reserved\n", str);
- printf("Backup/Restore is useful for HD backup and file transfers\n");
- printf("%s -rbactlvASTU -d<pat> -p<pat> -f[#kb] -F<vol> -n<#kb> -ofile <file-dir-list>\n", str);
- puts("\nread the docs for more info. Example for use w/ file transfer:");
- puts("\t1> backup -c file/dir -oout.bak -create archive");
- puts("\t1> restore -t out.bak -list archive");
- puts("\t1> restore out.bak [-odest] -restore archive");
- }
-
- for (i = 1; i < ac; ++i) {
- str = av[i];
- if (*str != '-') {
- if (xac == sizeof(Xav)/sizeof(Xav[0])) {
- printf("Maximum %d files/dirs specifiable on command line\n", sizeof(Xav)/sizeof(Xav[0]));
- exit(15);
- }
- Xav[xac++] = str;
- continue;
- }
- notdone = 1;
- ++str;
-
- while (notdone && *str) {
- switch(*str) {
- case '0':
- NoStructure = 1;
- break;
- case 'r':
- Restore = 1;
- break;
- case 'b':
- Restore = 0;
- break;
- case 'a':
- Append = 1;
- break;
- case 'c':
- Compress = 1;
- break;
- case 'd':
- AddPattern(&DSList, str + 1);
- notdone = 0;
- break;
- case 'f':
- BacBytes = 800 * 1024;
- if (str[1] >= '0' && str[1] <= '9') {
- BacBytes = atoi(str+1) * 1024;
- notdone = 0;
- }
- break;
- case 'F':
- { /* strlen(str+1)+1 */
- char *name = (str[1]) ? str + 1 : av[++i];
- NODE *node = malloc(sizeof(NODE) + strlen(name) + 1);
- node->ln_Name = (char *)(node + 1);
- strcpy((char *)(node + 1), name);
- AddTail(&VList, node);
- }
- notdone = 0;
- break;
- case 'O':
- {
- char *name = (str[1]) ? str + 1 : av[++i];
- manOffset = atoi(name);
- }
- Overide = 1;
- notdone = 0;
- break;
- case 'n':
- {
- char *name = (str[1]) ? str + 1 : av[++i];
- BufSize = atoi(name) * 1024;
- }
- if (BufSize <= 0)
- BufSize = 65536;
- notdone = 0;
- break;
- case 'o':
- {
- char *name = (str[1]) ? str + 1 : av[++i];
- OutFile = name;
- }
- notdone = 0;
- break;
- case 'p':
- {
- char *name = (str[1]) ? str + 1 : av[++i];
- AddPattern(&PSList, name);
- }
- notdone = 0;
- break;
- case 's':
- ShowFiles = 0;
- break;
- case 't':
- case 'l':
- ListOnly = 1;
- break;
- case 'v':
- Verbose= 1;
- break;
- case 'A':
- Archive= 1;
- break;
- case 'C':
- {
- char *name = (str[1]) ? str + 1 : av[++i];
- AddPattern(&CSList, name);
- }
- notdone = 0;
- break;
- case 'S':
- ShowFiles = 0;
- ShowDirs = 0;
- break;
- case 'T':
- TimeStampOnly = 1;
- break;
- case 'U':
- Update = 1;
- break;
- default:
- puts("failure, backup w/ no args for help");
- exit(20);
- }
- ++str;
- }
- }
- if (i > ac) {
- puts("Expected argument to last option!");
- exit(20);
- }
- Buf = malloc(BufSize);
- if (Buf == NULL) {
- printf("Unable to malloc %ld bytes\n", BufSize);
- exit(20);
- }
- if (ListOnly)
- InBufSize = 512; /* small buffer to avoid read overhead */
- /* since we are skipping the meat */
-
- InBuf = malloc(InBufSize);
- if (InBuf == NULL) {
- printf("Unable to malloc %ld bytes\n", InBufSize);
- exit(20);
- }
-
- if (Restore)
- RestoreFiles(xac, Xav, manOffset);
- else
- BackupFiles(xac, Xav);
- return(0);
- }
-
- void
- AddPattern(list, str)
- MLIST *list;
- char *str;
- {
- register NODE *node = malloc(sizeof(NODE));
-
- AddTail(list, node);
- node->ln_Name = str;
- }
-
-
- long SaveLock;
-
- void
- BackupFiles(ac, av)
- char **av;
- {
- register short i;
- register char *str, *ptr;
- char notdone;
-
- if (OutFile && openoutput(OutFile, Append, ((BacBytes)?1:0)) == 0)
- exit(20);
- if (OutFile) { /* write header */
- DATESTAMP Date;
- DateStamp(&Date);
- outentry(XHDR, sizeof(DATESTAMP), &Date);
- }
-
- SaveLock = CurrentDir(DupLock(((PROC *)FindTask(NULL))->pr_CurrentDir));
-
- for (i = 0; i < ac; ++i) {
- str = av[i];
-
- /*
- * Push DDS entries for each name segment of the path
- */
-
- notdone = 1;
- while (notdone) {
- for (ptr = str; *ptr && *ptr != ':' && *ptr != '/'; ++ptr);
- switch(*ptr) {
- case '/': /* normal directory */
- *ptr = 0;
- PushDir(str, XDDS);
- str = ptr + 1;
- *ptr = '/';
- break;
- case ':': /* volume */
- *ptr = 0;
- PushDir(str, XVOL);
- str = ptr + 1;
- *ptr = ':';
- break;
- default: /* directory or file */
- {
- char *path = av[i];
- FIB *fib;
- long lock;
-
- if (fib = GetFileInfo(path, &lock)) {
- if (fib->fib_DirEntryType > 0) {
- if (str[0])
- PushDir(str, XDDS);
- lock = scan_directory(fib, lock);
- if (str[0])
- PopDirs(1);
- } else {
- lock = scan_file(fib, lock);
- }
- FreeFileInfo(fib, lock);
- } else {
- printf("Unable to get info for %s\n", av[i]);
- }
- }
- notdone = 0;
- break;
- }
- }
- PopDirs((uword)-1);
- }
-
- UnLock(CurrentDir(SaveLock));
- if (OutFile)
- closeoutput();
- }
-
- DATESTAMP Date;
- ulong Crc; /* compare w/ */
- ulong CrcGen;
- ulong CrcSeek; /* (backup) where in file is CrcGen lw? */
- char CrcEna;
- char Comment[256];
- char Scr[256];
- long Protection;
- long IncSize; /* Size of entire file */
- long IncSeek; /* Seek offset into file */
- long IncLen; /* # bytes in this segment */
-
- void
- RestoreFiles(ac, av, startoffset)
- char **av;
- long startoffset;
- {
- register short i;
- register char *str;
- char notdone;
- char havedate;
- char havecrc;
- char havepro;
- char havecom;
- char haveinc;
- long bytes;
- long actual;
- long baselock;
- long lock;
- PROC *proc = (PROC *)FindTask(NULL);
-
- if (OutFile) {
- lock = Lock(OutFile, SHARED_LOCK);
- if (lock == NULL && (lock = CreateDir(OutFile))) {
- UnLock(lock);
- lock = Lock(OutFile, SHARED_LOCK);
- }
- } else {
- lock = Lock("", SHARED_LOCK);
- }
- if (!lock) {
- printf("Unable to lock/create %s\n", (OutFile) ? OutFile : "<currentdir>");
- return;
- }
- baselock = lock;
- SaveLock = CurrentDir(DupLock(baselock));
-
- for (i = 0; i < ac; ++i) {
- str = av[i];
-
- lock = CurrentDir(SaveLock);
- if (openinput(str, startoffset) == 0) {
- startoffset = 0;
- printf("Unable to open %s for input\n", str);
- CurrentDir(lock);
- continue;
- }
- startoffset = 0;
- CurrentDir(lock);
-
- lock = DupLock(baselock);
- UnLock(CurrentDir(lock));
-
- notdone = 1;
- havedate = havecrc = havepro = havecom = haveinc = 0;
-
- while (notdone) {
- short c = oreadchar();
- short l = oreadchar();
- recover:
- switch(c) {
- case -1: /* EOF */
- notdone = 0;
- break;
- case 0: /* NUL */
- case 'z'&0x1F: /* ^Z */
- if (Overide == 0)
- notdone = 0;
- break;
- case XVOL:
- case XDDS:
- oread(Scr, l);
- Scr[l] = 0;
-
- /*
- * In the replacement of the first
- * argument case, we are already in
- * the proper directory.
- */
-
- if (EMPTYLIST(DList) && OutFile) {
- register short j = strlen(OutFile);
-
- UnLock(CurrentDir(DupLock(SaveLock)));
- c = XDDS;
- strcpy(Scr, OutFile);
- if (j--) {
- if (OutFile[j] == ':') {
- Scr[j] = 0;
- c = XVOL;
- }
- if (OutFile[j] == '/')
- Scr[j] = 0;
- }
- }
- PushDir(Scr, c);
- if (ShowDirs)
- printf("%-40s\n", DirPath);
- if (ListOnly)
- break;
- if (NoStructure == 0) {
- if (c == XVOL) {
- lock = Lock(DirPath, SHARED_LOCK); /* DirPath incs ':' */
- } else {
- lock = Lock(Scr, SHARED_LOCK);
- if (lock == NULL && (lock = CreateDir(Scr))) {
- UnLock(lock);
- lock = Lock(Scr, SHARED_LOCK);
- }
- }
- }
- {
- SDIR *sd = GetTail(&DList);
- sd->HaveFile = 1; /* don't remove dir */
- }
- if (NoStructure == 0) {
- if (lock == NULL) {
- printf("Unable to create directory %s\n", Scr);
- notdone = 0;
- } else {
- UnLock(CurrentDir(lock));
- }
- }
- break;
- case XEND:
- {
- SDIR *sd = GetTail(&DList);
- ubyte type;
-
- c = 1;
- if (!sd)
- break;
- type = sd->Type;
- strcpy(Scr, sd->Element);
- c = PopDirs(1);
- if (ListOnly)
- break;
- if (type == XVOL) /* no parent directory */
- break;
- if (NoStructure == 0) {
- lock = ParentDir(proc->pr_CurrentDir);
- if (lock == NULL) {
- puts("Unable to ParentDir!");
- notdone = 0;
- } else {
- UnLock(CurrentDir(lock));
- /*
- if (c == 0)
- DeleteFile(Scr);
- */
- }
- }
- }
- break;
- case XCRC:
- if (l != 4) {
- puts(BadFormat);
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- oread(&Crc, l);
- havecrc = 1;
- break;
- case XDAT:
- if (l != sizeof(DATESTAMP)) {
- puts(BadFormat);
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- oread(&Date, l);
- havedate = 1;
- break;
- case XPRO:
- if (l != 4) {
- puts("Expected 4 bytes for protection");
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- oread(&Protection, l);
- havepro = 1;
- break;
- case XCOM:
- oread(Comment, l);
- Comment[l] = 0;
- havecom = 1;
- break;
- case XFIL0:
- case XFIL1:
- if (!havepro)
- Protection = 0;
- if (!havecom)
- Comment[0] = 0;
- if (!havedate)
- DateStamp(&Date);
- if (!haveinc)
- IncSize = 0;
-
- oread(Scr, l);
- Scr[l] = 0;
- oread(&bytes, 4); /* length of file */
- actual = bytes;
- if (c == XFIL1) {
- oread(&actual, 4);
- bytes -= 4;
- }
- setinputbound(bytes);
- {
- short res = read_file(c, Scr, bytes, actual);
- seekinputend();
- if (res < 0)
- goto bend;
- }
- if (ListOnly)
- goto bend;
- if (Archive)
- SetProtection(Scr, Protection|FIBF_ARCHIVE);
- else
- SetProtection(Scr, Protection&~FIBF_ARCHIVE);
- if (havecrc && Crc != CrcGen)
- printf("WARNING, Crc failed! %s\n", Scr);
- if (havedate)
- setfiledate(Scr, &Date);
- if (havecom && Comment[0])
- SetComment(Scr, Comment);
- bend:
- havecom = havecrc = havedate = havepro = haveinc = 0;
- break;
- case XHDR:
- if (l != sizeof(DATESTAMP)) {
- puts("expected sizeof datestamp");
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- oread(&Date, l);
- printf(" ----- BACKUP ----- BACKUP DATE: %s\n", datetos(&Date, Scr, NULL));
- break;
- case XINC:
- if (l != 12) {
- puts("expected 12 bytes for XINC");
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- oread(&IncSize, 4);
- oread(&IncSeek, 4);
- oread(&IncLen, 4);
- haveinc = 1;
- break;
- default:
- printf("Unknown Record Type: %02x\n", c);
- notdone = SkipBad(&c, &l);
- goto recover;
- }
- setinputbound(-1);
- if (mycheckbreak()) {
- Break = 1;
- notdone = 0;
- break;
- }
- }
- if (Break)
- break;
- }
- UnLock(baselock);
- UnLock(CurrentDir(SaveLock));
- }
-
- SkipBad(pc, pl)
- short *pc;
- short *pl;
- {
- long skip = 0;
- long offset = otellread();
- short notdone = 1;
- short c;
- short l;
-
- loop:
- while ((c = oreadchar()) >= 0 && c != XDAT)
- ++skip;
- if (c == XDAT) {
- l = oreadchar();
- ++skip;
- if (l != sizeof(DATESTAMP))
- goto loop;
- }
- printf("Error at offset %d, skipping %d bytes", offset, skip);
- if (c < 0) {
- printf(" (EOF reached!)");
- notdone = 0;
- }
- printf("\n");
- *pc = c;
- *pl = l;
- return((int)notdone);
- }
-
- FIB *
- GetFileInfo(path, plock)
- char *path;
- long *plock;
- {
- register long lock;
- register FIB *fib;
-
- *plock = NULL;
- if (lock = Lock(path, SHARED_LOCK)) {
- if (fib = malloc(sizeof(FIB))) {
- if (Examine(lock, fib)) {
- *plock = lock;
- return(fib);
- }
- free(fib);
- }
- UnLock(lock);
- }
- return(NULL);
- }
-
- void
- FreeFileInfo(fib, lock)
- FIB *fib;
- long lock;
- {
- if (fib)
- free(fib);
- if (lock)
- UnLock(lock);
- }
-
- void
- PushDir(element, type)
- char *element;
- {
- register SDIR *sd = malloc(sizeof(SDIR));
- register char *str = malloc(strlen(element)+1);
-
- strcpy(str, element);
- sd->Type = type;
- sd->HaveFile = 0;
- sd->Element = str;
- AddTail(&DList, sd);
- strcat(DirPath+DPLen, str);
- if (type == XVOL)
- strcat(DirPath+DPLen, ":");
- else if (type == XDDS)
- strcat(DirPath+DPLen, "/");
- DPLen += strlen(DirPath+DPLen);
- }
-
- int
- PopDirs(num)
- uword num;
- {
- register SDIR *sd, *sp;
- char lasthave = 0;
-
- while (num && (sd = GetTail(&DList))) {
- lasthave |= sd->HaveFile;
- if (!Restore && sd->HaveFile) /* MUST write end-block */
- outentry(XEND, 0, NULL);
- if (sp = GetPred(sd))
- sp->HaveFile |= sd->HaveFile;
- Remove(sd);
- DPLen -= strlen(sd->Element) + 1;
- if (DPLen < 0) {
- puts("DPLEN ERROR");
- DPLen = 0;
- }
- DirPath[DPLen] = 0;
- free(sd->Element);
- free(sd);
- --num;
- }
- return((int)lasthave);
- }
-
- void
- BackupFlagHasFile()
- {
- register SDIR *sd;
- SDIR *sdb = NULL;
-
- for (sd = GetTail(&DList); sd; sd = GetPred(sd)) {
- if (sd->HaveFile == 0)
- sdb = sd;
- }
- for (sd = sdb; sd; sd = GetSucc(sd)) {
- sd->HaveFile = 1;
- outentry(sd->Type, strlen(sd->Element), sd->Element);
- }
- }
-
-
- /*
- * SCAN_DIRECTORY() (CORE OF BACKUP)
- */
-
- long
- scan_directory(dirfib, dirlock)
- FIB *dirfib;
- long dirlock;
- {
- register FIB *fib;
- long lock;
- long save = CurrentDir(dirlock);
-
- if (Update == 0) /* force save entire tree */
- BackupFlagHasFile();
- while (ExNext(dirlock, dirfib) && (fib = GetFileInfo(dirfib->fib_FileName, &lock))) {
- if (fib->fib_DirEntryType > 0) {
- PushDir(fib->fib_FileName, XDDS);
- if (ShowDirs)
- printf("%-40s (DIR)\n", DirPath);
- if (NoBack(fib) == 0)
- lock = scan_directory(fib, lock);
- PopDirs(1);
- } else {
- if (NoBack(fib) == 0)
- lock = scan_file(fib, lock);
- }
- FreeFileInfo(fib, lock);
- if (Break || mycheckbreak()) {
- Break = 1;
- break;
- }
- }
- CurrentDir(save);
- return(dirlock);
- }
-
- int
- mycheckbreak()
- {
-
- if (MyBreak || (SetSignal(0, (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D))) {
- puts(" ***** BREAK *****");
- return(1);
- }
- return(0);
- }
-
- /*
- * SCAN_FILE()
- *
- * If the file is accepted, write out pending directory entries, do
- * compression if any, and write out the file.
- */
-
- long
- scan_file(fib, lock)
- FIB *fib;
- long lock;
- {
- long save;
- char dbuf[32];
-
- strcat(DirPath, fib->fib_FileName);
-
- if (Update && (fib->fib_Protection & FIBF_ARCHIVE))
- goto nomatch;
- if (!match_file(DirPath))
- goto nomatch;
-
- if (ShowFiles)
- printf("%-40s %6ld %s\n", DirPath, fib->fib_Size, datetos(&fib->fib_Date, dbuf, NULL));
-
- BackupFlagHasFile();
- if (OutFile) {
- save = CurrentDir(lock);
- if (openinput("", 0) == 0) {
- CurrentDir(save);
- printf("Unable to open %s\n", fib->fib_FileName);
- goto nomatch;
- }
- if (Compress && CompressFile(fib->fib_FileName, fib->fib_Size)) {
- if (OutFile && BacBytes && outbytes() + CLen > BacBytes) {
- if (newfile() == 0)
- goto skip1;
- }
- writeheaders(fib);
- outentry(XFIL1, strlen(fib->fib_FileName), fib->fib_FileName);
- CLen += 4;
- owrite(&CLen, 4);
- CLen -= 4;
- owrite(&fib->fib_Size, 4);
- transfer1();
- } else {
- if (OutFile && BacBytes && outbytes() + fib->fib_Size > BacBytes) {
- if (newfile() == 0)
- goto skip1;
- }
- if (Compress)
- rollbackinput();
- writeheaders(fib);
- outentry(XFIL0, strlen(fib->fib_FileName), fib->fib_FileName);
- owrite(&fib->fib_Size, 4);
- transfer0(fib->fib_Size);
- }
- outlwatseek(CrcSeek, CrcGen);
- skip1:
- closeinput();
- CurrentDir(save);
- }
- if (Break)
- goto nomatch;
- if (Archive && !(fib->fib_Protection & FIBF_ARCHIVE)) {
- if (save = ParentDir(lock)) {
- UnLock(lock);
- save = CurrentDir(save);
- SetProtection(fib->fib_FileName, fib->fib_Protection | FIBF_ARCHIVE);
- lock = CurrentDir(save);
- }
- }
- DirPath[DPLen] = 0;
- return(lock);
- nomatch:
- if (Verbose)
- printf("%-40s (NOT ACCEPTED)\n", DirPath, fib->fib_Size, datetos(&fib->fib_Date, dbuf, NULL));
-
- DirPath[DPLen] = 0;
- return(lock);
- }
-
- int
- match_file(name)
- char *name;
- {
- register NODE *node;
-
- for (node = (NODE *)PSList.mlh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (WildCmp(node->ln_Name, name))
- break;
- }
- if (node->ln_Succ == NULL && !EMPTYLIST(PSList))
- return(0);
-
- for (node = (NODE *)DSList.mlh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (WildCmp(node->ln_Name, name))
- return(0);
- }
- return(1);
- }
-
- void
- writeheaders(fib)
- register FIB *fib;
- {
- long dummy = 0;
- outentry(XDAT, sizeof(DATESTAMP), &fib->fib_Date);
- outentry(XPRO, 4, &fib->fib_Protection);
- if (fib->fib_Comment[0])
- outentry(XCOM, strlen(fib->fib_Comment), fib->fib_Comment);
- outentry(XCRC, 4, &dummy);
- CrcSeek = outbytes() - 4;
- }
-
- /*
- * (1) Write out XEND's to finish this archive,
- * (2) Open a new output file
- * (3) Write out XDDS's to build back to the current position
- */
-
- int
- newfile()
- {
- {
- register SDIR *sd;
-
- for (sd = GetTail(&DList); sd; sd = GetPred(sd)) {
- if (sd->HaveFile)
- outentry(XEND, 0, NULL);
- }
- }
- ++BacCnt;
- if (OutFile && openoutput(OutFile, Append, 1) == 0) {
- Break = 1;
- return(0);
- }
- {
- register SDIR *sd;
- DATESTAMP Date;
- DateStamp(&Date);
- outentry(XHDR, sizeof(DATESTAMP), &Date);
- for (sd = GetHead(&DList); sd; sd = GetSucc(sd)) {
- if (sd->HaveFile)
- outentry(sd->Type, strlen(sd->Element), sd->Element);
- }
- }
- return(1);
- }
-
- int
- read_file(type, fname, inbytes, outbytes)
- short type;
- char *fname;
- long inbytes;
- long outbytes;
- {
- char dbuf[32];
- long save;
-
- strcat(DirPath, fname);
-
- if (!match_file(DirPath)) {
- if (Verbose)
- printf("%-40s (NOT ACCEPTED)\n", DirPath);
- goto nomatch;
- }
-
- if (ShowFiles)
- printf("%-40s %6ld %6ld %s %s\n", DirPath, inbytes, outbytes, datetos(&Date, dbuf, NULL), Comment);
-
- if (ListOnly)
- goto nomatch;
- if (TimeStampOnly)
- goto matchskip;
-
- openoutput(fname, 0, 0);
- switch(type) {
- case XFIL0:
- transfer0(inbytes);
- break;
- case XFIL1:
- CrcGen = 0;
- CrcEna = 1;
- UnCompressFile(inbytes);
- CrcEna = 0;
- save = CrcGen;
- transfer1(); /* ??? needed ??? */
- CrcGen = save;
- break;
- }
- closeoutput();
- matchskip:
- DirPath[DPLen] = 0;
- return(1);
- nomatch:
- DirPath[DPLen] = 0;
- return(-1);
- }
-
- /*
- * FILE SUPPORT
- */
-
- static int Infd = -1;
- static int Outfd = -1;
- static long OutBytes;
-
- int
- openoutput(name, append, enabtail)
- char *name;
- {
- char *ptr = name;
- static NODE *VNode; /* Volume node */
- long lock;
- extern int errno;
-
- if (Outfd >= 0) {
- dumpoutput();
- close(Outfd);
- Outfd = -1;
- }
- if (enabtail) {
- if (VNode)
- VNode = GetSucc(VNode);
- if (!VNode)
- VNode = GetHead(&VList);
- if (VNode) {
- ptr = malloc(strlen(VNode->ln_Name)+strlen(name)+8);
- sprintf(ptr, "%s%s.%02ld", VNode->ln_Name, name, BacCnt);
- } else {
- ptr = malloc(strlen(name)+8);
- sprintf(ptr, "%s.%02ld", name, BacCnt);
- }
- }
- OutBytes = 0;
- while (GetHead(&VList)) {
- short c;
- short d;
-
- fprintf(stderr, "Ready for %s (y=go,n=abort) -", ptr);
- fflush(stderr);
- if ((c = getc(stdin)) == EOF) {
- fprintf(stderr, "EOF, aborted\n");
- c = 'n';
- }
- while ((d = getc(stdin)) != EOF && d != '\n');
- if ((c|0x20) == 'y')
- break;
- if ((c|0x20) == 'n')
- goto skip;
- }
- if (enabtail && SaveLock) /* original directory */
- lock = CurrentDir(SaveLock);
- if (append) {
- Outfd = open(ptr, O_WRONLY|O_CREAT|O_APPEND);
- if (Outfd >= 0) {
- OutBytes = lseek(Outfd, 0L, 2);
- /* lseek(Outfd, 0L, 0); */
- }
- } else {
- Outfd = open(ptr, O_WRONLY|O_CREAT|O_TRUNC);
- }
- if (enabtail && SaveLock) /* back to before */
- CurrentDir(lock);
- if (Outfd < 0)
- printf("Unable to open output file %s (%ld)\n", ptr, errno);
- skip:
- BufI = 0;
- if (enabtail)
- free(ptr);
- return(Outfd >= 0);
- }
-
- void
- oputc(v)
- char v;
- {
- ++OutBytes;
- if (Outfd >= 0) {
- if (BufI == BufSize)
- dumpoutput();
- Buf[BufI++] = v;
- }
- }
-
- void
- outlwatseek(pos, lw)
- long pos;
- long lw;
- {
- long index = BufI + pos - OutBytes; /* index into buffer */
-
- if (index > BufI - 4) {
- puts("SW ERROR");
- return;
- }
- if (index >= 0) {
- Buf[index+0] = lw >> 24;
- Buf[index+1] = lw >> 16;
- Buf[index+2] = lw >> 8;
- Buf[index+3] = lw;
- } else { /* uh oh */
- if (Outfd >= 0) {
- long old = lseek(Outfd, 0, 1); /* save current pos */
- lseek(Outfd, pos, 0); /* seek back */
- write(Outfd, (char *)&lw, 4); /* write data */
- lseek(Outfd, old, 0); /* seek to end */
- }
- }
- }
-
- void
- owrite(buf, n)
- void *buf;
- long n;
- {
- register long avail;
-
- OutBytes += n;
- if (Outfd >= 0) {
- while (BufI + n > BufSize) {
- avail = BufSize - BufI;
- movmem(buf, Buf + BufI, avail);
- n -= avail;
- buf = (void *)((char *)buf + avail);
- BufI = BufSize;
- dumpoutput();
- }
- movmem(buf, Buf + BufI, n);
- BufI += n;
- }
- }
-
- void
- dumpoutput()
- {
- if (Outfd >= 0 && BufI) {
- write(Outfd, Buf, BufI);
- BufI = 0;
- }
- }
-
- void
- closeoutput()
- {
- if (Outfd >= 0) {
- dumpoutput();
- close(Outfd);
- Outfd = -1;
- }
- }
-
- long
- outbytes()
- {
- return(OutBytes);
- }
-
- /*
- * <type><len><buf>
- */
-
- void
- outentry(type, len, buf)
- ubyte type;
- int len;
- void *buf;
- {
- OutBytes += len + 2;
- if (Outfd >= 0) {
- if (BufI + len + 2 >= BufSize)
- dumpoutput();
- Buf[BufI+0] = type;
- Buf[BufI+1] = len;
- movmem(buf, Buf+BufI+2, len);
- BufI += len + 2;
- }
- }
-
- ulong OMax;
-
- int
- openinput(name, offset)
- char *name;
- long offset;
- {
- if (Infd >= 0)
- close(Infd);
- Infd = open(name, O_RDONLY);
- InBufI = InBufN = 0;
- OMax = -1;
- if (Infd >= 0 && offset)
- lseek(Infd, offset, 0);
- return(Infd >= 0);
- }
-
- void
- closeinput()
- {
- if (Infd >= 0)
- close(Infd);
- Infd = -1;
- }
-
- void
- seekinputend()
- {
- register long inbuf = InBufI - InBufN;
- register long forward = OMax;
-
- if (forward > inbuf) {
- lseek(Infd, forward - inbuf, 1);
- OMax = InBufI = InBufN = 0;
- return;
- }
- InBufN += forward;
- }
-
- void
- setinputbound(max)
- long max;
- {
- OMax = max;
- }
-
- long
- oread(buf, n)
- void *buf;
- long n;
- {
- long x = 0;
- long avail;
-
- if (Infd < 0)
- return(0);
- if (n > OMax)
- n = OMax;
-
- while (n > (avail = InBufI - InBufN)) {
- if (InBufN == -1)
- return(0);
- movmem(InBuf + InBufN, buf, avail);
- AppendCrc(buf, avail);
- OMax-= avail;
- n -= avail;
- buf = (void *)((char *)buf + avail);
- x += avail;
- InBufI = read(Infd, InBuf, InBufSize);
- InBufN = 0;
- if (InBufI <= 0) {
- InBufI = 0;
- return(x);
- }
- }
- movmem(InBuf + InBufN, buf, n);
- AppendCrc(buf, n);
- InBufN += n;
- x += n;
- OMax -= n;
- return(x);
- }
-
- long
- otellread()
- {
- long pos = 0;
- if (Infd >= 0)
- pos = lseek(Infd, 0L, 1) - (InBufI - InBufN);
- return(pos);
- }
-
- int
- oreadchar()
- {
- if (!OMax || Infd < 0)
- return(-1);
- if (InBufN == InBufI) {
- if (InBufN < 0)
- return(EOF);
- InBufI = read(Infd, InBuf, InBufSize);
- InBufN = 0;
- if (InBufI == 0) {
- InBufN = InBufI = -1;
- return(-1);
- }
- }
- if (CrcEna)
- CrcGen = (CrcGen << 3) ^ InBuf[InBufN] ^ (CrcGen >> 29);
- return((int)InBuf[InBufN++]);
- }
-
- void
- AppendCrc(buf, bytes)
- register ubyte *buf;
- register long bytes;
- {
- if (CrcEna) {
- while (bytes--)
- CrcGen = (CrcGen << 3) ^ *buf++ ^ (CrcGen >> 29);
- }
- }
-
- void
- rollbackinput()
- {
- if (Infd >= 0)
- lseek(Infd, 0L, 0);
- InBufI = InBufN = 0;
- }
-
- void
- mputc(v)
- char v;
- {
- register SCOMP *sc = CWrite;
-
- ++CLen;
- if (sc->N == sc->Bytes) {
- sc = GetSucc(sc);
- if (sc == NULL);
- sc = NewSComp();
- if (sc == NULL) {
- puts("SCOMP FAILED");
- return;
- }
- sc->N = 0;
- CWrite = sc;
- }
- ((char *)(sc + 1))[sc->N++] = v;
- }
-
- void
- mwrite(buf, n)
- char *buf;
- long n;
- {
- register SCOMP *sc = CWrite;
- register long avail;
-
- CLen += n;
- while ((avail = sc->Bytes - sc->N) < n) {
- movmem(buf, (char *)(sc + 1) + sc->N, avail);
- buf += avail;
- n -= avail;
- sc->N = sc->Bytes;
- sc = GetSucc(sc);
- if (sc == NULL)
- sc = NewSComp();
- if (sc == NULL) {
- puts("SCOMP FAILED");
- return;
- }
- sc->N = 0;
- }
- movmem(buf, (char *)(sc + 1) + sc->N, n);
- sc->N += n;
- CWrite = sc;
- }
-
- SCOMP *
- NewSComp()
- {
- register SCOMP *sc = malloc(sizeof(SCOMP) + 8192);
-
- if (sc) {
- sc->Bytes = 8192;
- sc->N = 0;
- AddTail(&CList, sc);
- }
- return(sc);
- }
-
- void
- transfer0(n)
- long n;
- {
- register long len;
-
- if (Outfd < 0)
- return;
-
- CrcGen = 0;
- CrcEna = 1;
- for (len = BufSize - BufI; n; len = BufSize - BufI) {
- if (len == 0) {
- dumpoutput();
- len = BufSize;
- }
- if (n < len)
- len = n;
- oread(Buf + BufI, len);
- BufI += len;
- n -= len;
- OutBytes += len;
- }
- CrcEna = 0;
- }
-
- /*
- * Compression Routines
- *
- * transfer1() : Backup: copy compression buffer to output file
- */
-
- void
- transfer1()
- {
- register long len;
- register SCOMP *sc = GetHead(&CList);
- register ubyte *ptr;
- long n = CLen;
-
- if (Outfd < 0)
- return;
- CrcGen = 0;
- CrcEna = 1;
- for (sc = GetHead(&CList); sc && n; sc = GetSucc(sc)) {
- len = sc->Bytes;
- ptr = (ubyte *)(sc + 1);
- if (n < len)
- len = n;
- n -= len;
-
- AppendCrc(ptr, len);
-
- while (len > BufSize - BufI) {
- movmem(ptr, Buf + BufI, BufSize - BufI);
- ptr += BufSize - BufI;
- len -= BufSize - BufI;
- OutBytes += BufSize - BufI;
- BufI = BufSize;
- dumpoutput();
- }
- movmem(ptr, Buf + BufI, len);
- BufI += len;
- OutBytes += len;
- }
- CrcEna = 0;
- if (n)
- puts("Unexpected EOF in compression file");
- }
-
- /*
- * NoBack() returns true if 'NOBACK' is found in the fib_Comment
- * field.
- */
-
- NoBack(fib)
- FIB *fib;
- {
- char *str = fib->fib_Comment;
-
- while (*str) {
- if (*str == 'N' && strncmp(str, "NOBACK", 6) == 0)
- return(1);
- ++str;
- }
- return(0);
- }
-
- /*
- * quick hack to fix some macro bugs...
- */
-
- long
- CTOB(cptr)
- void *cptr;
- {
- return((long)cptr >> 2);
- }
-
- void *
- BTOC(bptr)
- long bptr;
- {
- return((void *)(bptr << 2));
- }
-
- void *
- GetHead(list)
- MLIST *list;
- {
- MNODE *node = list->mlh_Head;
- if (node->mln_Succ)
- return(node);
- return(NULL);
- }
-
- void *
- GetTail(list)
- MLIST *list;
- {
- MNODE *node = list->mlh_TailPred;
- if (node->mln_Pred)
- return(node);
- return(NULL);
- }
-
- void *
- GetSucc(node)
- MNODE *node;
- {
- node = node->mln_Succ;
- if (node->mln_Succ)
- return(node);
- return(NULL);
- }
-
- void *
- GetPred(node)
- MNODE *node;
- {
- node = node->mln_Pred;
- if (node->mln_Pred)
- return(node);
- return(NULL);
- }
-
-
-