home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1988 Andrew Kemmis
- *
- * All Rights Reserved
- *
- * Date: Jan 1988
- */
- #include <ak/stdak.h>
-
- char Program_name[] = "Val";
- int Version = 2;
- int MinorVer = 3;
- char Date[] = "Dec 1993";
- char CRDate[] = "1988-93";
-
- #include <ak/err.h>
- #include <ak/pool.h>
- #include <ak/dev.h>
- #include <ak/dos.h>
- #include <intuition/intuitionbase.h>
- #include "val.h"
-
- #include "val.qi"
-
- #define ULONGS(l) ((ulong)(l)*(ulong)sizeof(ulong))
- #define ZAlloc(a) PoolAlloc((a), sizeof(*(a)), &GenPoolKey)
- #define LAlloc(a,n,z) { if (!Seek)\
- PoolAlloc((a), ULONGS(n), &GenPoolKey);\
- else\
- (char *)(a) = AllocMem(ULONGS(n), 0L);\
- }
-
- #define ULONGMAX 4294967295
-
- extern char *strchr();
- extern char *strrchr();
- extern int strlen();
- extern int strcmp();
- extern int sscanf();
-
- extern char *AllocMem();
-
- int cli;
-
- struct IBASE *IBASE = (struct IBASE *)NULL;
-
- Static int FileSystem;
-
- #define IS_OFS 0
- #define IS_FFS 1
-
- Static char StrRoot[] = "Root";
- Static char StrBitMap[] = "BitMap";
- Static char StrEtc[] = "Dir,Fil,Lnk";
- Static char StrDir[] = "Dir";
- Static char StrFil[] = "Fil";
- Static char StrExt[] = "Ext";
- Static char StrDat[] = "Dat";
- Static char StrSoftLnk[] = "SoftLnk";
- Static char StrDirLnk[] = "DirLnk";
- Static char StrFilLnk[] = "FilLnk";
- Static char StrNextD[] = "NextDat";
- Static char StrChain[] = "HashChain";
- Static char StrNext[] = "Next";
- Static char StrPrev[] = "Prev";
- Static char StrHuh[] = "Unknown";
- Static struct AkDevStuff Stuff = DEVSTUFFINIT;
- Static uchar *Buffer;
- Static long Dev = -1;
- Static struct Names RootName =
- { (struct Names *)NULL, (struct Names *)NULL, ULONGMAX, };
- Static struct Links
- { ushort type;
- ulong block;
- ulong prev;
- ulong next;
- struct Links *another;
- } *LinkHead, *LinkMaybe;
- Static uchar *FName;
- Static int Inhibited = 0;
-
- Static struct PoolKey BufPoolKey;
- Static struct PoolKey GenPoolKey;
- Static struct PoolKey ZerPoolKey;
-
- Static ulong ReadCount = 0;
- Static struct Info *LastInfo;
- Static ulong LastBlk;
- Static uchar *MyBitMap;
-
- Static ulong ReadSmall = 0;
- Static ulong ReadLarge = 0;
- Static ulong ReadLNum = 0;
- Static ulong HitSmall = 0;
- Static ulong HitLarge = 0;
- Static ulong MicSta;
- Static ulong MicFin;
- Static ulong MicCode;
- Static ulong MicRead;
-
- #define BMAP_TST(n) (MyBitMap[(n)>>3]&(1<<((n)&7)))
- #define BMAP_SET(n) (MyBitMap[(n)>>3]|=(1<<((n)&7)))
-
- Static Copy(d, s, l, siz)
- REG char *d;
- REG char *s;
- REG ulong l;
- REG int siz;
- {
- REG ulong len = l * (ulong)siz;
-
- while (len--)
- *(d++) = *(s++);
- }
-
- Static Get(Rem, num)
- REG struct Info *Rem;
- REG ulong num;
- {
- if ((Rem - InfoList) >= MaxDepth)
- MyError(ERR_TOODEEP, MaxDepth);
-
- getblok(num + Stuff.Info.Begin, Rem);
- }
-
- Static LONG DevRead(num, buf, size)
- REG ulong num;
- REG ulong *buf;
- REG LONG size;
- {
- REG LONG ret;
- REG int retry = Retries + 1;
-
- while (retry-- && (ret = AkDevRead(num, buf, &Stuff, size)))
- ;
-
- if (ret && FailReq)
- { if (!akrequester("Disk Read Error", "Continue", "Abort"))
- { puts("Aborted at users request on Read Error");
- Cleanup();
- }
- }
-
- return(ret);
- }
-
- Static int DoCache = !0;
-
- #define CACHE_INVALID -7
-
- Static LONG CacheRead(num, buf)
- REG ulong num;
- REG ulong **buf;
- {
- static ulong cache0 = CACHE_INVALID;
- static ulong cache1 = CACHE_INVALID;
- static ulong cache2 = CACHE_INVALID;
- REG LONG ret = 0;
-
- *buf = (ulong *)Buffer;
-
- if (Cache == 1)
- ret = DevRead(num, *buf, BLOCK_SIZE);
- else
- { if (num == cache0 || num == (cache0 + 1) || (cache1 <= num && num <= cache2))
- { if (StatCache)
- MicSta = IBASE->Micros;
-
- if (num == (cache0+1))
- *buf = (ulong *)&Buffer[BLOCK_SIZE];
- else
- if (num != cache0)
- *buf = (ulong *)&Buffer[BLOCK_SIZE*(2 + num - cache1)];
-
- if (StatCache)
- MicFin = IBASE->Micros;
-
- if (StatCache)
- { if (num == cache0 || num == (cache0+1))
- HitSmall++;
- else
- HitLarge++;
-
- if (MicSta > MicFin)
- MicFin += 1000000;
- MicCode += (MicFin - MicSta);
- }
- if (DebugCache)
- { if (num == cache0)
- printf("Hit at :0\n");
- else
- if (num == (cache0+1))
- printf("Hit at :1\n");
- else
- printf("Hit at %lu\n", 2 + num - cache1);
- }
- }
- else
- { if (DebugCache)
- { if (DoCache && num <= (Stuff.Info.End - 2))
- printf("Do Cache (miss %ld %ld)\n", num-cache0, num-cache1);
- else
- printf("Non Cache (miss %ld %ld)\n", num-cache0, num-cache1);
- }
-
- if (StatCache)
- MicSta = IBASE->Micros;
-
- if (DoCache && num <= (Stuff.Info.End - 2)) /* Must read 3 Blocks! */
- { cache0 = num;
- cache1 = num + 2;
- cache2 = num + Cache - 1;
- if (cache2 > Stuff.Info.End)
- cache2 = Stuff.Info.End;
- ret = DevRead(num, *buf, BLOCK_SIZE*(1 + cache2 - cache0));
- if (ret)
- cache0 = cache1 = cache2 = CACHE_INVALID;
- }
- else
- { if (num != Stuff.Info.End)
- cache0 = num;
- else
- { cache0 = num - 1;
- *buf = (ulong *)&Buffer[BLOCK_SIZE];
- }
-
- ret = DevRead(num, (ulong *)Buffer, BLOCK_SIZE*2);
- if (ret)
- cache0 = CACHE_INVALID;
- }
-
- if (StatCache)
- MicFin = IBASE->Micros;
-
- if (StatCache)
- { if (DoCache && num <= (Stuff.Info.End - 2))
- { ReadLarge++;
- ReadLNum += (1 + cache2 - cache0);
- }
- else
- ReadSmall++;
-
- if (MicSta > MicFin)
- MicFin += 1000000;
- MicRead += (MicFin - MicSta);
- }
- }
- }
- return(ret);
- }
-
- Static char *StrType(type)
- REG ushort type;
- {
- REG char *ans;
-
- switch(type)
- {
- case I_ROOT:
- ans = StrRoot;
- break;
- case I_DIR:
- ans = StrDir;
- break;
- case I_FIL:
- ans = StrFil;
- break;
- case I_EXT:
- ans = StrExt;
- break;
- case I_DAT:
- ans = StrDat;
- break;
- case I_S_LNK:
- ans = StrSoftLnk;
- break;
- case I_H_LNK_DIR:
- ans = StrDirLnk;
- break;
- case I_H_LNK_FIL:
- ans = StrFilLnk;
- break;
- /*
- case I_UNK:
- case I_UNREADABLE:
- */
- default:
- ans = StrHuh;
- break;
- }
- return(ans);
- }
-
- Static int BaD = 0;
- Static int WaR = 0;
- Static ulong SeqNum;
- Static ulong PrevD = 0;
- Static ulong NextD = 0;
-
- #define B_TYP 0
- #define B_KEY 1
- #define B_CHKSUM 2
- #define B_BMAP 3
- #define B_PAR 4
- #define B_COUNT 5
- #define B_FIRST 6
- #define B_BYTESIZE 7
- #define B_HED 8
- #define B_RANGE 9
- #define B_SEQ 10
- #define B_SHORT 11
- #define B_BMFLG 12
- #define B_HTSIZ 13
- #define B_BITMAP 14
- #define B_NEXTD 15
- #define B_BADNAME 16
- #define B_UNR 17
- #define B_BLOCKSIZE 18
- #define B_USED 19
- #define B_USEDBY 20
-
- #define B_PREVLINK 22
- #define B_NEXTLINK 23
- #define B_OFSLINK 24
- #define B_NOPREVLINK 25
- #define B_PREVINV 26
- #define B_NOTPREV 27
- #define B_PREVDIF 28
- #define B_LINKTYPERR 29
- #define B_XNOTLINK 30
-
- Static bad(Rem, num, err, typ, ex1, ex2, ex3)
- struct Info *Rem;
- REG ulong num;
- int err;
- REG char *typ;
- REG ulong ex1;
- ulong ex2;
- ulong ex3;
- {
- int idx;
- ulong blk;
- REG struct Info *CurRem;
- REG struct Names *CurName;
- ulong *Buf = (ulong *)Buffer;
- int seeked = 0;
-
- switch(err)
- {
- case B_BMFLG:
- case B_BITMAP:
- case B_HTSIZ:
- case B_BMAP:
- case B_BLOCKSIZE:
- case B_BYTESIZE:
- case B_OFSLINK:
- WaR++;
- printf("War: B %lu %s ", num, typ);
- break;
- default:
- BaD++;
- printf("Err: B %lu %s ", num, typ);
- break;
- }
-
- if (Rem && DosNames && num != Stuff.Info.Root)
- { CurRem = LastInfo;
- if (Seek)
- idx = CurRem - InfoList;
- else
- for (idx=0; CurRem != &InfoList[Stuff.Info.Root]; idx++)
- CurRem = &InfoList[CurRem->Obj.dir->parent];
- /* *** parent in same pos */
-
- CurName = &RootName;
- while (idx--)
- { if (CurName->next == (struct Names *)NULL)
- { ZAlloc(CurName->next);
- CurName->next->prev = CurName;
- CurName->next->next = (struct Names *)NULL;
- CurName->next->block = ULONGMAX;
- }
- CurName = CurName->next;
- }
- if (CurName->next)
- CurName->next->block = ULONGMAX;
-
- CurRem = LastInfo;
- blk = LastBlk;
- while (CurName)
- { if (CurName->block != blk)
- { CurName->block = blk;
- if (!Seek && !seeked)
- { AkMotorOn(&Stuff);
- seeked = !0;
- }
- if (CacheRead(blk + Stuff.Info.Begin, &Buf))
- FName = (uchar *)"\011***Bad***";
- else
- FName = (uchar *)(&Buf[POS_NAME]);
- if (*FName >= sizeof(RootName.name))
- *FName = sizeof(RootName.name) - 1;
- Copy(CurName->name, FName, (long)((*FName) + 1), sizeof(char));
- }
- if (Seek)
- blk = (CurRem--)->Obj.dir->parent;
- /* *** parent in same pos, blk not used if Root */
- else
- blk = InfoList[blk].Obj.dir->parent;
- /* *** parent in same pos, blk not used if Root */
-
- CurName = CurName->prev;
- }
- if (seeked)
- AkMotorOff(&Stuff);
-
- CurName = &RootName;
- while (CurName && CurName->block != ULONGMAX)
- { if (CurName->prev)
- { if (CurName->prev == &RootName)
- putchar(':');
- else
- putchar('/');
- }
- if (*CurName->name)
- printf("%.*s", (int)(*(CurName->name)), (CurName->name)+1);
- CurName = CurName->next;
- }
- putchar(' ');
- }
-
- switch(err)
- {
- case B_TYP:
- printf("Block type wrong (par = %lu)", ex1);
- break;
- case B_KEY:
- printf("Key wrong (par = %lu)", ex1);
- break;
- case B_CHKSUM:
- printf("Checksum wrong (par = %lu)", ex1);
- break;
- case B_BMAP:
- printf("No Bitmap blocks present!");
- break;
- case B_PAR:
- printf("Parent pointer (%lu) != parent block (%lu)", ex1, ex2);
- break;
- case B_COUNT:
- printf("Block Count incorrect (par = %lu)", ex1);
- break;
- case B_FIRST:
- printf("FirstData incorrect (should be = %lu)", ex1);
- break;
- case B_BYTESIZE:
- printf("Bytesize incorrect (calc = %lu actual = %lu)", ex1, ex2);
- break;
- case B_HED:
- printf("Header pointer (%lu) != header block (%lu)", ex1, ex2);
- break;
- case B_RANGE:
- printf("%s pointer (%lu) out of disk range!", ex1, ex2);
- break;
- case B_SEQ:
- printf("Sequence number wrong (should be %lu, is %lu)", ex1, ex2);
- break;
- case B_SHORT:
- printf("Data block not full (only allowed in last data block!)");
- break;
- case B_BMFLG:
- printf("Bitmap Flag says Bitmap is invalid!");
- break;
- case B_HTSIZ:
- printf("Hash table size != calculated size!");
- break;
- case B_BITMAP:
- printf("Block type NOT unknown type!");
- break;
- case B_NEXTD:
- printf("Next data block (%lu) != Previous data block's (%lu) Next data block (%lu)",
- ex1, ex2, ex3);
- break;
- case B_BADNAME:
- printf("Blocks name is invalid (BSTR size is 0 or > %d)", sizeof(RootName.name) - 1);
- break;
- case B_UNR:
- printf("Gave error (0x%lx) on read (par = %lu)", ex1, ex2);
- break;
- case B_BLOCKSIZE:
- printf("Total blocks incorrect (calc = %lu actual = %lu)", ex1, ex2);
- break;
- case B_USED:
- if (ex1)
- printf("Pointed to by %lu ", ex1);
- printf("Already used (FFS Error)");
- break;
- case B_USEDBY:
- printf("Pointed to by %lu Already used by %lu (FFS Error)", ex1, ex2);
- break;
- case B_PREVLINK:
- printf("Prev Link Pointer not 0");
- break;
- case B_NEXTLINK:
- printf("Next Link Pointer not 0");
- break;
- case B_OFSLINK:
- printf("Contains a link (but partition is OFS)");
- break;
- case B_NOPREVLINK:
- printf("Prev Link Pointer should not be 0");
- break;
- case B_PREVINV:
- printf("Prev (%lu) Must be Fil or Dir (not %s)", ex1, ex2);
- break;
- case B_NOTPREV:
- printf("Next's (%lu) Prev (%lu) should be This", ex1, ex2);
- break;
- case B_PREVDIF:
- printf("Next's (%lu) Prev (%lu) != This Prev (%lu)", ex3, ex2, ex1);
- break;
- case B_LINKTYPERR:
- printf("%s Pointer's type (%s) not valid for this type", ex1, ex2);
- break;
- case B_XNOTLINK:
- printf("%s (%lu) is not Linked", ex1, ex2);
- break;
- }
- putchar('\n');
-
- if (ErrLimit >= 0 && BaD > ErrLimit)
- { printf("Validation aborted ... Error Limit (%ld) Exceeded\n", ErrLimit);
- Cleanup();
- }
-
- if (WarnLimit >= 0 && WaR > WarnLimit)
- { printf("Validation aborted ... Warning Limit (%ld) Exceeded\n", WarnLimit);
- Cleanup();
- }
- }
-
- Static CompareLinkType(prev_is_head, prev, next)
- REG int prev_is_head;
- REG ushort prev;
- REG ushort next;
- {
- int ret = FALSE;
-
- if (!prev_is_head)
- { if (prev == I_H_LNK_DIR && next == I_H_LNK_DIR)
- ret = TRUE;
-
- if (prev == I_H_LNK_FIL && next == I_H_LNK_FIL)
- ret = TRUE;
- }
- else
- { if (prev == I_DIR && next == I_H_LNK_DIR)
- ret = TRUE;
-
- if (prev == I_FIL && next == I_H_LNK_FIL)
- ret = TRUE;
- }
-
- return(ret);
- }
-
- /* OK this is really quite slow - but I don't have many links! */
- Static CheckLinks()
- {
- REG struct Links *LinkTmp;
- REG struct Links *LinkTmp2;
- REG ulong next;
- REG ulong prev;
- REG ulong block;
- ushort type;
- int got_prev;
- int got_next;
-
- LinkTmp = LinkHead;
- while (LinkTmp)
- { next = LinkTmp->next;
- prev = LinkTmp->prev;
- block = LinkTmp->block;
- type = LinkTmp->type;
- got_prev = !prev;
- got_next = !next;
-
- LinkTmp2 = LinkHead;
- while (LinkTmp2)
- { if (prev && prev == LinkTmp2->block)
- { got_prev = !0;
- if (LinkTmp2->type != I_DIR && LinkTmp2->type != I_FIL)
- bad(NULL, block, B_PREVINV, StrType(type), prev, StrType(LinkTmp2->type));
-
- if (!CompareLinkType(!0, LinkTmp2->type, type))
- bad(NULL, block, B_LINKTYPERR, StrType(type), StrPrev, StrType(LinkTmp2->type));
- }
- if (next && next == LinkTmp2->block)
- { got_next = !0;
- if (!prev && LinkTmp2->prev != block)
- bad(NULL, block, B_NOTPREV, StrType(type), next, LinkTmp2->prev);
-
- if (prev && LinkTmp2->prev != prev)
- bad(NULL, block, B_PREVDIF, StrType(type), prev, LinkTmp2->prev, next);
-
- if (!CompareLinkType(prev == 0, type, LinkTmp2->type))
- bad(NULL, block, B_LINKTYPERR, StrType(type), StrNext, StrType(LinkTmp2->type));
- }
- LinkTmp2 = LinkTmp2->another;
- }
- if (!got_prev)
- bad(NULL, block, B_XNOTLINK, StrType(type), StrPrev, prev);
- if (!got_next)
- bad(NULL, block, B_XNOTLINK, StrType(type), StrNext, next);
- LinkTmp = LinkTmp->another;
- }
- }
-
- Static MoveMaybe(block)
- REG ulong block;
- {
- REG struct Links *LinkTmpPrev = NULL;
- REG struct Links *LinkTmp = LinkMaybe;
-
- while (LinkTmp && LinkTmp->block != block)
- { LinkTmpPrev = LinkTmp;
- LinkTmp = LinkTmp->another;
- }
-
- if (LinkTmp)
- { if (LinkTmpPrev)
- LinkTmpPrev->another = LinkTmp->another;
- else
- LinkMaybe = LinkTmp->another;
-
- LinkTmp->another = LinkHead;
- LinkHead = LinkTmp;
- }
- else
- { /* Huh? Shouldn't happen? */
- MyError(ERR_NOVAL, "Link Code Bug");
- }
- }
-
- Static AddLink(block, prev, next, type)
- REG ulong block;
- REG ulong prev;
- REG ulong next;
- REG ushort type;
- {
- struct Links *LinkTmp;
-
- ZAlloc(LinkTmp);
- LinkTmp->type = type;
- LinkTmp->block = block - Stuff.Info.Begin;
- LinkTmp->prev = prev;
- LinkTmp->next = next;
- LinkTmp->another = LinkMaybe;
- LinkMaybe = LinkTmp;
- }
-
- Static getblok(num, Rem)
- ulong num;
- REG struct Info *Rem;
- {
- REG ulong *Buf;
- REG uchar *obj;
- REG ulong i;
- REG ulong *l;
- REG ulong *l2;
- ulong count;
- ushort *flags;
- LONG ret;
- ulong *buf;
-
- if (ShowReads && (++ReadCount % Count) == 0)
- { akdeco(ReadCount, 'l', NULL, NULL, NULL, ' ', ' ');
- akhexo(num, 'l', NULL, NULL, NULL, '\r', '0');
- }
- if (Tracks && (ReadCount++ % Stuff.Info.Cyl) == 0)
- akdeco(ReadCount / Stuff.Info.Cyl, 'l', NULL, NULL, NULL, '\r', ' ');
-
- ret = CacheRead(num, &buf);
-
- if (!Seek)
- Rem = &InfoList[num - Stuff.Info.Begin];
-
- flags = &(Rem->flags);
- *flags = 0;
-
- if (ret)
- { Rem->type = I_UNREADABLE;
- Rem->Obj.ret = ret;
- return; /* N.B. */
- }
-
- Buf = buf;
-
- switch(Buf[POS_TYP])
- {
- case TYP_CONTROL:
- FName = (uchar *)(&Buf[POS_NAME]);
- if (*FName == 0 || *FName >= sizeof(RootName.name))
- *flags |= E_BADNAME;
- switch(Buf[POS_SEC])
- {
- case SEC_ROOT:
- Rem->type = I_ROOT;
- if (Buf[POS_KEY])
- *flags |= E_KEY;
-
- /* Appears to be a date at POS_LINK_NEXT
- if (Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (Buf[POS_LINK_NEXT])
- *flags |= E_NEXTLINK;
- */
- if (!Buf[POS_BMFLG])
- *flags |= E_BMFLG;
- if (Buf[POS_HTSIZ] != (1L + POS_LST_BLK - POS_FST_BLK))
- *flags |= E_HTSIZ;
- if (Seek)
- (struct Root *)obj = Rem->Obj.root;
- else
- { ZAlloc((struct Root *)obj);
- Rem->Obj.root = (struct Root *)obj;
- }
- for (count = 0, i = POS_FST_BLK, l = &Buf[i]; i <= POS_LST_BLK; l++, i++)
- if (*l)
- count++;
- if (count++)
- { LAlloc(l, count, StrRoot);
- ((struct Root *)obj)->blocks = l;
- for (i = POS_FST_BLK, l2 = &Buf[i]; i <= POS_LST_BLK; l2++, i++)
- if (*l2)
- *(l++) = *l2;
- *l = 0L;
- }
- else
- ((struct Root *)obj)->blocks = (ulong *)NULL;
-
- for (i = POS_BBLK, l = &Buf[i]; *l && i < POS_BBLK_END; i++, l++)
- ;
- count = i - POS_BBLK;
- if (*l)
- count++;
- if (count)
- { LAlloc(l, count+1, StrBitMap);
- Copy(l, &Buf[POS_BBLK], count, sizeof(ulong));
- ((struct Root *)obj)->bblocks = l;
- l[count] = 0L;
- }
- else
- ((struct Root *)obj)->bblocks = (ulong *)NULL;
- break;
- case SEC_DIR:
- Rem->type = I_DIR;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (Buf[POS_LINK_NEXT])
- { if (FileSystem == IS_OFS && !LinksAllowed)
- *flags |= E_OFSLINK;
- AddLink(num, 0L, Buf[POS_LINK_NEXT], I_DIR);
- }
- if (Seek)
- (struct Dir *)obj = Rem->Obj.dir;
- else
- { ZAlloc((struct Dir *)obj);
- Rem->Obj.dir = (struct Dir *)obj;
- }
- for (count = 0, i = POS_FST_BLK, l = &Buf[i]; i <= POS_LST_BLK; l++, i++)
- if (*l)
- count++;
- if (count++)
- { LAlloc(l, count, StrDir);
- ((struct Dir *)obj)->blocks = l;
- for (i = POS_FST_BLK, l2 = &Buf[i]; i <= POS_LST_BLK; l2++, i++)
- if (*l2)
- *(l++) = *l2;
- *l = 0L;
- }
- else
- ((struct Dir *)obj)->blocks = (ulong *)NULL;
-
- ((struct Dir *)obj)->chain = Buf[POS_HASH_CH];
- ((struct Dir *)obj)->parent = Buf[POS_PAR];
- ((struct Dir *)obj)->next = Buf[POS_LINK_NEXT];
- break;
- case SEC_FIL:
- Rem->type = I_FIL;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (Buf[POS_LINK_NEXT])
- { if (FileSystem == IS_OFS && !LinksAllowed)
- *flags |= E_OFSLINK;
- AddLink(num, 0L, Buf[POS_LINK_NEXT], I_FIL);
- }
- if (Seek)
- (struct Fil *)obj = Rem->Obj.fil;
- else
- { ZAlloc((struct Fil *)obj);
- Rem->Obj.fil = (struct Fil *)obj;
- }
- for (i=POS_LST_BLK, l = &Buf[i]; *l && i > POS_FST_BLK; i--, l--)
- ;
- count = POS_LST_BLK - i;
- if (*l)
- count++;
- else
- l++;
- if (count != Buf[POS_NUM_BLK])
- *flags |= E_COUNT;
- ((struct Fil *)obj)->num = count;
- if (count)
- { if (Buf[POS_FST_DAT] != Buf[POS_LST_BLK])
- *flags |= E_FIRST;
- LAlloc(l2, count, StrFil);
- Copy(l2, l, count, sizeof(ulong));
- ((struct Fil *)obj)->blocks = l2;
- }
- else
- { ((struct Fil *)obj)->blocks = (ulong *)NULL;
- if (Buf[POS_FST_DAT])
- *flags |= E_FIRST;
- }
- ((struct Fil *)obj)->bytesize = Buf[POS_F_BYTSIZ];
- ((struct Fil *)obj)->chain = Buf[POS_HASH_CH];
- ((struct Fil *)obj)->parent = Buf[POS_PAR];
- ((struct Fil *)obj)->extension = Buf[POS_EXT];
- ((struct Fil *)obj)->next = Buf[POS_LINK_NEXT];
- break;
- case SEC_S_LNK:
- Rem->type = I_S_LNK;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (Buf[POS_LINK_NEXT])
- *flags |= E_NEXTLINK;
- if (FileSystem == IS_OFS && !LinksAllowed)
- *flags |= E_OFSLINK;
- if (Seek)
- (struct Lnk *)obj = Rem->Obj.lnk;
- else
- { ZAlloc((struct Lnk *)obj);
- Rem->Obj.lnk = (struct Lnk *)obj;
- }
- ((struct Lnk *)obj)->chain = Buf[POS_HASH_CH];
- ((struct Lnk *)obj)->parent = Buf[POS_PAR];
- break;
- case SEC_H_LNK_DIR:
- Rem->type = I_H_LNK_DIR;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (!Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (FileSystem == IS_OFS && !LinksAllowed)
- *flags |= E_OFSLINK;
- AddLink(num, Buf[POS_LINK_PREV], Buf[POS_LINK_NEXT], I_H_LNK_DIR);
- if (Seek)
- (struct DirLnk *)obj = Rem->Obj.dirlnk;
- else
- { ZAlloc((struct DirLnk *)obj);
- Rem->Obj.dirlnk = (struct DirLnk *)obj;
- }
- ((struct DirLnk *)obj)->prev = Buf[POS_LINK_PREV];
- ((struct DirLnk *)obj)->next = Buf[POS_LINK_NEXT];
- ((struct DirLnk *)obj)->chain = Buf[POS_HASH_CH];
- ((struct DirLnk *)obj)->parent = Buf[POS_PAR];
- break;
- case SEC_H_LNK_FIL:
- Rem->type = I_H_LNK_FIL;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (!Buf[POS_LINK_PREV])
- *flags |= E_PREVLINK;
- if (FileSystem == IS_OFS && !LinksAllowed)
- *flags |= E_OFSLINK;
- AddLink(num, Buf[POS_LINK_PREV], Buf[POS_LINK_NEXT], I_H_LNK_FIL);
- if (Seek)
- (struct FilLnk *)obj = Rem->Obj.fillnk;
- else
- { ZAlloc((struct FilLnk *)obj);
- Rem->Obj.fillnk = (struct FilLnk *)obj;
- }
- ((struct FilLnk *)obj)->prev = Buf[POS_LINK_PREV];
- ((struct FilLnk *)obj)->next = Buf[POS_LINK_NEXT];
- ((struct FilLnk *)obj)->chain = Buf[POS_HASH_CH];
- ((struct FilLnk *)obj)->parent = Buf[POS_PAR];
- break;
- default:
- Rem->type = I_UNK;
- break;
- }
- break;
- case TYP_EXT:
- Rem->type = I_EXT;
- if (Buf[POS_KEY] != (num - Stuff.Info.Begin))
- *flags |= E_KEY;
- if (Seek)
- (struct Ext *)obj = Rem->Obj.ext;
- else
- { ZAlloc((struct Ext *)obj);
- Rem->Obj.ext = (struct Ext *)obj;
- }
- if (Buf[POS_FST_DAT])
- *flags |= E_FIRST;
- for (i=POS_LST_BLK, l = &Buf[i]; *l && i > POS_FST_BLK; i--, l--)
- ;
- count = POS_LST_BLK - i;
- if (*l)
- count++;
- else
- l++;
- if (count != Buf[POS_NUM_BLK])
- *flags |= E_COUNT;
- ((struct Ext *)obj)->num = count;
- if (count)
- { LAlloc(l2, count, StrExt);
- Copy(l2, l, count, sizeof(ulong));
- ((struct Ext *)obj)->blocks = l2;
- }
- else
- ((struct Ext *)obj)->blocks = (ulong *)NULL;
- ((struct Ext *)obj)->parent = Buf[POS_PAR];
- ((struct Ext *)obj)->extension = Buf[POS_EXT];
- break;
- case TYP_DAT:
- Rem->type = I_DAT;
- if (Seek)
- (struct Dat *)obj = Rem->Obj.dat;
- else
- { ZAlloc((struct Dat *)obj);
- Rem->Obj.dat = (struct Dat *)obj;
- }
- ((struct Dat *)obj)->key = Buf[POS_KEY];
- ((struct Dat *)obj)->seqnum = Buf[POS_D_SEQ_NUM];
- ((struct Dat *)obj)->size = Buf[POS_D_DAT_SIZ];
- ((struct Dat *)obj)->nextd = Buf[POS_D_NXT_DAT];
- if (((struct Dat *)obj)->nextd)
- if (((struct Dat *)obj)->size != (BLOCK_SIZE - (POS_FST_BLK << 2L)))
- *flags |= E_SHORT;
- break;
- default:
- Rem->type = I_UNK;
- break;
- }
- if (Rem->type != I_UNK && (Rem->type != I_DAT || FileSystem == IS_OFS))
- if (DosChecksum(Buf))
- *flags |= E_CHKSUM;
- }
-
- Static rchk(Rem, num, blk, typ, want)
- REG struct Info *Rem;
- REG ulong num;
- REG ulong blk;
- REG char *typ;
- REG char *want;
- {
- if (blk < Stuff.Info.res || blk > (Stuff.Info.End - Stuff.Info.Begin))
- { bad(Rem, num, B_RANGE, typ, want, blk);
- return(0);
- }
- return(!0);
- }
-
- Static int unreadable(Rem, num, Str, par)
- REG struct Info *Rem;
- REG ulong num;
- REG char *Str;
- REG ulong par;
- {
- if (Rem->type == I_UNREADABLE)
- { bad(Rem, num, B_UNR, Str, Rem->Obj.ret, par);
- return(!0);
- }
- else
- return(0);
- }
-
- Static FreeSeek(Rem)
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG ulong count;
-
- if (Seek)
- switch(Rem->type)
- {
- case I_ROOT:
- l = Rem->Obj.root->bblocks;
- if (l)
- { for (count = 1; *l; l++, count++)
- ;
- FreeMem(Rem->Obj.root->bblocks, ULONGS(count));
- }
- l = Rem->Obj.root->blocks;
- if (l)
- { for (count = 1; *l; l++, count++)
- ;
- FreeMem(Rem->Obj.root->blocks, ULONGS(count));
- }
- break;
- case I_DIR:
- l = Rem->Obj.dir->blocks;
- if (l)
- { for (count = 1; *l; l++, count++)
- ;
- FreeMem(Rem->Obj.dir->blocks, ULONGS(count));
- }
- break;
- case I_FIL:
- if (Rem->Obj.fil->blocks)
- FreeMem(Rem->Obj.fil->blocks, ULONGS(Rem->Obj.fil->num));
- break;
- case I_EXT:
- if (Rem->Obj.ext->blocks)
- FreeMem(Rem->Obj.ext->blocks, ULONGS(Rem->Obj.ext->num));
- break;
- /*
- case I_DAT:
- case I_S_LNK:
- case I_H_LNK_DIR:
- case I_H_LNK_FIL:
- */
- default:
- break;
- }
- }
-
- Static CheckUsed(num, Rem, str, par)
- REG ulong num;
- REG struct Info *Rem;
- REG char *str;
- REG ulong par;
- {
- if (FileSystem == IS_FFS)
- if (Seek)
- { if (BMAP_TST(num))
- bad(Rem, num, B_USED, str, par);
- else
- BMAP_SET(num);
- }
- else
- { if (Rem->flags & I_USED)
- switch(Rem->type)
- {
- case I_DAT: /* well maybe? ;-) */
- bad(Rem, num, B_USEDBY, str, par, Rem->Obj.dat->key);
- break;
- case I_DIR:
- case I_FIL:
- case I_EXT:
- case I_S_LNK:
- case I_H_LNK_DIR:
- case I_H_LNK_FIL:
- bad(Rem, num, B_USEDBY, str, par, Rem->Obj.dir->parent);
- break;
- /* Usually FFS Data Block
- case I_ROOT:
- case I_UNK:
- case I_UNREADABLE:
- */
- default:
- bad(Rem, num, B_USED, str, par);
- break;
- }
- else
- Rem->flags |= I_USED;
- }
- }
-
- Static long ChkDat(num, hed, Rem, key)
- REG ulong num;
- REG ulong hed;
- REG struct Info *Rem;
- REG ulong key;
- {
- REG ulong *l;
-
- DoCache = !0;
-
- if (Seek)
- Get(Rem, num);
- else
- Rem = &InfoList[num];
-
- CheckUsed(num, Rem, StrDat, key);
-
- if (unreadable(Rem, num, StrDat, hed))
- return(0);
-
- if (FileSystem == IS_FFS)
- { FreeSeek(Rem);
- return(1);
- }
-
- PrevD = num;
- NextD = ULONGMAX;
- SeqNum++;
-
- if (Rem->type != I_DAT)
- { bad(Rem, num, B_TYP, StrDat, hed);
-
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrDat, hed);
-
- FreeSeek(Rem);
- return(0);
- }
- else
- { if (Rem->Obj.dat->key != hed)
- bad(Rem, num, B_HED, StrDat, Rem->Obj.dat->key, hed);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrDat, hed);
-
- if (Rem->Obj.dat->seqnum != SeqNum)
- bad(Rem, num, B_SEQ, StrDat, SeqNum, Rem->Obj.dat->seqnum);
-
- if (Rem->flags & E_SHORT)
- bad(Rem, num, B_SHORT, StrDat);
-
- NextD = Rem->Obj.dat->nextd;
- if (NextD)
- rchk(Rem, num, NextD, StrDat, StrNextD);
-
- FreeSeek(Rem);
- return(Rem->Obj.dat->size);
- }
- }
-
- Static long ChkExt(num, par, Rem)
- ulong num;
- ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG ulong *l2;
- REG ulong bytesize = 0;
- REG int oBaD = BaD;
-
- DoCache = 0;
-
- if (Seek)
- Get(Rem, num);
- else
- Rem = &InfoList[num];
-
- CheckUsed(num, Rem, StrExt, par);
-
- if (unreadable(Rem, num, StrExt, par))
- return(0);
-
- if (Rem->type != I_EXT)
- bad(Rem, num, B_TYP, StrExt, par);
- else
- if (Rem->Obj.ext->parent != par)
- bad(Rem, num, B_PAR, StrExt, Rem->Obj.ext->parent, par);
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrExt, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrExt, par);
-
- if (Rem->flags & E_COUNT)
- bad(Rem, num, B_COUNT, StrExt, par);
- if (Rem->flags & E_FIRST)
- bad(Rem, num, B_FIRST, StrExt, 0L);
-
- if (IgnoreErr || BaD == oBaD)
- { l = Rem->Obj.ext->blocks;
- if (l)
- { for (l2 = &l[Rem->Obj.ext->num - 1]; l2 >= l; l2--)
- if (rchk(Rem, num, *l2, StrExt, StrDat))
- { if (FileSystem == IS_OFS && NextD != *l2 && NextD != ULONGMAX)
- bad(Rem, num, B_NEXTD, StrExt, *l2, PrevD, NextD);
- bytesize += ChkDat(*l2, par, Rem+1, num);
- }
- FreeSeek(Rem);
- if (Rem->Obj.ext->extension && rchk(Rem, num, Rem->Obj.ext->extension, StrExt, StrExt))
- bytesize += ChkExt(Rem->Obj.ext->extension, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- else
- FreeSeek(Rem);
- }
- else
- FreeSeek(Rem);
-
- return(bytesize);
- }
-
- Static ChkFil(num, par, Rem)
- ulong num;
- ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG ulong *l2;
- REG ulong bytesize = 0;
- REG int oBaD = BaD;
- int flag = 0;
- struct Info *oLastInfo = LastInfo;
- ulong oLastBlk = LastBlk;
-
- LastInfo = Rem;
- LastBlk = num;
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrFil, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrFil, par);
- if (Rem->flags & E_COUNT)
- bad(Rem, num, B_COUNT, StrFil, par);
- if (Rem->flags & E_FIRST)
- { if (Rem->Obj.fil->blocks)
- bad(Rem, num, B_FIRST, StrFil, Rem->Obj.fil->blocks[Rem->Obj.fil->num - 1]);
- else
- bad(Rem, num, B_FIRST, StrFil, 0L);
- }
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrFil);
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_PREVLINK, StrFil);
- if (Rem->flags & E_OFSLINK)
- bad(Rem, num, B_OFSLINK, StrFil);
-
- if (Rem->Obj.fil->parent != par)
- bad(Rem, num, B_PAR, StrFil, Rem->Obj.fil->parent, par);
-
- if (Rem->Obj.fil->next)
- { rchk(Rem, num, Rem->Obj.fil->next, StrFil, StrNext);
- MoveMaybe(num);
- }
-
- if (IgnoreErr || BaD == oBaD)
- { SeqNum = 0L;
- l = Rem->Obj.fil->blocks;
- if (l)
- { for(l2 = &l[Rem->Obj.fil->num - 1]; l2 >= l; l2--)
- if (rchk(Rem, num, *l2, StrFil, StrDat))
- { if (flag)
- { if (FileSystem == IS_OFS && NextD != *l2 && NextD != ULONGMAX)
- bad(Rem, num, B_NEXTD, StrFil, *l2, PrevD, NextD);
- }
- else
- flag = !0;
- bytesize += ChkDat(*l2, num, Rem+1, num);
- }
- if (Rem->Obj.fil->extension && rchk(Rem, num, Rem->Obj.fil->extension, StrFil, StrExt))
- bytesize += ChkExt(Rem->Obj.fil->extension, num, Rem+1);
- if (FileSystem == IS_OFS && NextD && NextD != ULONGMAX)
- bad(Rem, num, B_NEXTD, StrFil, 0L, PrevD, NextD);
-
- if (FileSystem == IS_OFS)
- if (bytesize != Rem->Obj.fil->bytesize)
- bad(Rem, num, B_BYTESIZE, StrFil, bytesize, Rem->Obj.fil->bytesize);
-
- if (FileSystem == IS_FFS)
- { Rem->Obj.fil->bytesize += 511;
- Rem->Obj.fil->bytesize /= 512; /* Calculate number of blocks - any other check available ???? */
- if (bytesize != Rem->Obj.fil->bytesize)
- bad(Rem, num, B_BLOCKSIZE, StrFil, bytesize, Rem->Obj.fil->bytesize);
- }
- }
- LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
-
- if (Rem->Obj.fil->chain && rchk(Rem, num, Rem->Obj.fil->chain, StrFil, StrChain))
- ChkEtc(Rem->Obj.fil->chain, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- else
- { LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
- }
- }
-
- Static ChkDir(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG int oBaD = BaD;
- struct Info *oLastInfo = LastInfo;
- ulong oLastBlk = LastBlk;
-
- LastInfo = Rem;
- LastBlk = num;
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrDir, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrDir, par);
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrDir);
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_PREVLINK, StrDir);
- if (Rem->flags & E_OFSLINK)
- bad(Rem, num, B_OFSLINK, StrDir);
-
- if (Rem->Obj.dir->parent != par)
- bad(Rem, num, B_PAR, StrDir, Rem->Obj.dir->parent, par);
-
- if (Rem->Obj.dir->next)
- { rchk(Rem, num, Rem->Obj.dir->next, StrDir, StrNext);
- MoveMaybe(num);
- }
-
- if (IgnoreErr || BaD == oBaD)
- { l = Rem->Obj.dir->blocks;
- if (l)
- for (; *l; l++)
- if (rchk(Rem, num, *l, StrDir, StrEtc))
- ChkEtc(*l, num, Rem+1);
-
- LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
-
- if (Rem->Obj.dir->chain && rchk(Rem, num, Rem->Obj.dir->chain, StrDir, StrChain))
- ChkEtc(Rem->Obj.dir->chain, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- else
- { LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
- }
- }
-
- Static ChkLnk(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG int oBaD = BaD;
- struct Info *oLastInfo = LastInfo;
- ulong oLastBlk = LastBlk;
-
- LastInfo = Rem;
- LastBlk = num;
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrSoftLnk, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrSoftLnk, par);
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrSoftLnk);
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_PREVLINK, StrRoot);
- if (Rem->flags & E_NEXTLINK)
- bad(Rem, num, B_NEXTLINK, StrRoot);
- if (Rem->flags & E_OFSLINK)
- bad(Rem, num, B_OFSLINK, StrSoftLnk);
-
- if (Rem->Obj.lnk->parent != par)
- bad(Rem, num, B_PAR, StrSoftLnk, Rem->Obj.lnk->parent, par);
-
- LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
-
- if (IgnoreErr || BaD == oBaD)
- { if (Rem->Obj.lnk->chain && rchk(Rem, num, Rem->Obj.lnk->chain, StrSoftLnk, StrChain))
- ChkEtc(Rem->Obj.lnk->chain, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- }
-
- Static ChkDirLnk(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG int oBaD = BaD;
- struct Info *oLastInfo = LastInfo;
- ulong oLastBlk = LastBlk;
-
- LastInfo = Rem;
- LastBlk = num;
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrDirLnk, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrDirLnk, par);
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrDirLnk);
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_NOPREVLINK, StrDirLnk);
- if (Rem->flags & E_OFSLINK)
- bad(Rem, num, B_OFSLINK, StrDirLnk);
-
- if (Rem->Obj.dirlnk->parent != par)
- bad(Rem, num, B_PAR, StrDirLnk, Rem->Obj.dirlnk->parent, par);
-
- if (Rem->Obj.dirlnk->prev)
- rchk(Rem, num, Rem->Obj.dirlnk->prev, StrDirLnk, StrPrev);
- if (Rem->Obj.dirlnk->next)
- rchk(Rem, num, Rem->Obj.dirlnk->next, StrDirLnk, StrNext);
-
- MoveMaybe(num);
-
- LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
-
- if (IgnoreErr || BaD == oBaD)
- { if (Rem->Obj.dirlnk->chain && rchk(Rem, num, Rem->Obj.dirlnk->chain, StrDirLnk, StrChain))
- ChkEtc(Rem->Obj.dirlnk->chain, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- }
-
- Static ChkFilLnk(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG int oBaD = BaD;
- struct Info *oLastInfo = LastInfo;
- ulong oLastBlk = LastBlk;
-
- LastInfo = Rem;
- LastBlk = num;
-
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrFilLnk, par);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrFilLnk, par);
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrFilLnk);
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_NOPREVLINK, StrFilLnk);
- if (Rem->flags & E_OFSLINK)
- bad(Rem, num, B_OFSLINK, StrFilLnk);
-
- if (Rem->Obj.fillnk->parent != par)
- bad(Rem, num, B_PAR, StrFilLnk, Rem->Obj.fillnk->parent, par);
-
- if (Rem->Obj.fillnk->prev)
- rchk(Rem, num, Rem->Obj.fillnk->prev, StrFilLnk, StrPrev);
- if (Rem->Obj.fillnk->next)
- rchk(Rem, num, Rem->Obj.fillnk->next, StrFilLnk, StrNext);
-
- MoveMaybe(num);
-
- LastInfo = oLastInfo;
- LastBlk = oLastBlk;
-
- FreeSeek(Rem);
-
- if (IgnoreErr || BaD == oBaD)
- { if (Rem->Obj.fillnk->chain && rchk(Rem, num, Rem->Obj.fillnk->chain, StrFilLnk, StrChain))
- ChkEtc(Rem->Obj.fillnk->chain, par, Rem);
- /* Same Level (and don't need Rem anymore) */
- }
- }
-
- Static ChkEtc(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- REG ulong *l;
-
- DoCache = 0;
-
- if (Seek)
- Get(Rem, num);
- else
- Rem = &InfoList[num];
-
- CheckUsed(num, Rem, StrEtc, par);
-
- if (unreadable(Rem, num, StrEtc, par))
- return;
-
- switch(Rem->type)
- {
- case I_DIR:
- ChkDir(num, par, Rem);
- break;
- case I_FIL:
- ChkFil(num, par, Rem);
- break;
- case I_S_LNK:
- ChkLnk(num, par, Rem);
- break;
- case I_H_LNK_DIR:
- ChkDirLnk(num, par, Rem);
- break;
- case I_H_LNK_FIL:
- ChkFilLnk(num, par, Rem);
- break;
- default:
- bad(Rem, num, B_TYP, StrEtc, par);
- FreeSeek(Rem);
- break;
- }
- }
-
- Static ChkBMap(num, par, Rem)
- REG ulong num;
- REG ulong par;
- REG struct Info *Rem;
- {
- DoCache = !0;
-
- if (Seek)
- Get(Rem, num);
- else
- Rem = &InfoList[num];
-
- CheckUsed(num, Rem, StrBitMap, par);
-
- if (unreadable(Rem, num, StrBitMap, par))
- return;
-
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrBitMap, par);
-
- if (Rem->type != I_UNK)
- bad(Rem, num, B_BITMAP, StrBitMap);
- /* How do I test that this really is a bitmap block? Probably generate a warning */
-
- FreeSeek(Rem);
- }
-
- Static ChkRoot(num, Rem)
- REG ulong num;
- REG struct Info *Rem;
- {
- REG ulong *l;
- REG int oBaD = BaD;
-
- if (Seek)
- Get(Rem, num);
- else
- Rem = &InfoList[num];
-
- LastInfo = Rem;
- LastBlk = num;
-
- CheckUsed(num, Rem, StrRoot, 0L);
-
- if (unreadable(Rem, num, StrRoot, 0L))
- return;
-
- if (Rem->type != I_ROOT)
- bad(Rem, num, B_TYP, StrRoot, 0L);
- if (Rem->flags & E_BMFLG)
- bad(Rem, num, B_BMFLG, StrRoot);
- if (Rem->flags & E_HTSIZ)
- bad(Rem, num, B_HTSIZ, StrRoot);
- if (Rem->flags & E_KEY)
- bad(Rem, num, B_KEY, StrRoot, 0L);
- if (Rem->flags & E_CHKSUM)
- bad(Rem, num, B_CHKSUM, StrRoot, 0L);
- if (Rem->flags & E_BADNAME)
- bad(Rem, num, B_BADNAME, StrRoot);
-
- /* appears to be a date in NEXTLINK position
- if (Rem->flags & E_PREVLINK)
- bad(Rem, num, B_PREVLINK, StrRoot);
- if (Rem->flags & E_NEXTLINK)
- bad(Rem, num, B_NEXTLINK, StrRoot);
- */
-
- if (IgnoreErr || BaD == oBaD)
- { l = Rem->Obj.root->bblocks;
- if (!l)
- bad(Rem, num, B_BMAP, NULL);
- else
- for (; *l; l++)
- if (rchk(Rem, num, *l, StrRoot, StrBitMap))
- ChkBMap(*l, num, Rem+1);
-
- l = Rem->Obj.root->blocks;
- if (l)
- for (; *l; l++)
- if (rchk(Rem, num, *l, StrRoot, StrEtc))
- ChkEtc(*l, num, Rem+1);
- }
- FreeSeek(Rem);
- }
-
- Static ValidateIt()
- {
- REG ulong l;
- REG ulong size;
- REG ulong *bptr;
-
- if (Seek)
- size = MaxDepth;
- else
- size = 1L + Stuff.Info.End - Stuff.Info.Begin;
-
- MPAlloc(InfoList, (sizeof(*InfoList) * size), &GenPoolKey);
-
- if (!Seek)
- { AkMotorOn(&Stuff);
- DoCache = !0;
- for (l = Stuff.Info.Begin; l <= Stuff.Info.End; l++)
- getblok(l, NULL);
- AkMotorOff(&Stuff);
- ChkRoot(Stuff.Info.Root, NULL);
- }
- else
- { while (size-- > 0)
- MPAlloc(InfoList[size].Obj.fil, sizeof(struct Fil), &GenPoolKey);
- if (FileSystem == IS_FFS)
- { size = 1L + Stuff.Info.End - Stuff.Info.Begin;
- MPAlloc(MyBitMap, (size+7)/8, &ZerPoolKey);
- }
- AkMotorOn(&Stuff);
- DoCache = !0;
- ChkRoot(Stuff.Info.Root, InfoList);
- AkMotorOff(&Stuff);
- }
-
- CheckLinks();
-
- if (BaD || WaR)
- printf("\nTotal Displayed errors for %s %d, Warnings: %d\n", Device, BaD, WaR);
- else
- printf("\nNo errors detected on %s\n", Device);
-
- if (DebugLink)
- { puts("Links:");
- if (!LinkHead)
- puts("\tNone!");
- else
- { while (LinkHead)
- { printf("\t%-10s Blk:%10lu Prev:%10lu Next:%10lu\n",
- StrType(LinkHead->type),
- LinkHead->block,
- LinkHead->prev,
- LinkHead->next);
- LinkHead = LinkHead->another;
- }
- }
- puts("Maybes: (but not!)");
- if (!LinkMaybe)
- puts("\tNone!");
- else
- { while (LinkMaybe)
- { printf("\t%-10s Blk:%10lu Prev:%10lu Next:%10lu\n",
- StrType(LinkMaybe->type),
- LinkMaybe->block,
- LinkMaybe->prev,
- LinkMaybe->next);
- LinkMaybe = LinkMaybe->another;
- }
- }
- }
- }
-
- Static Val()
- {
- LONG ret;
- ulong *buf;
-
- if (Dev = AkDevOpen(Device, &Stuff))
- MyError(Dev, Device);
-
- if (Inhibit)
- Inhibited = AkDevInhibit(&Stuff, -1L);
-
- MPAlloc(Buffer, (long)(BLOCK_SIZE*Cache), &BufPoolKey);
-
- AkDevMsg(&(Stuff.Info));
-
- if (Ffs || Ofs) /* Force FS choice */
- { if (Ofs)
- FileSystem = IS_OFS;
- else
- FileSystem = IS_FFS;
- }
- else
- { if (ShowFileSystem)
- printf("FileSystemHandler is \"%s\"\n", Stuff.Info.fsys);
-
- printf("Boot Block File System ... ");
- fflush(stdout);
-
- FileSystem = IS_FFS; /* Assume - change if wrong */
-
- AkMotorOn(&Stuff);
- DoCache = !Seek;
- ret = CacheRead(Stuff.Info.Begin, &buf);
- AkMotorOff(&Stuff);
-
- if (ret)
- printf("Error 0x%lx on Read Block Zero - Assumed FFS\n", ret);
- else
- { if ((*buf & 0xffffff00) != 0x444f5300)
- printf("Doesn't appear to be DOS - Assumed FFS\n");
- else
- { if ((*buf & 0xff) == 0)
- { FileSystem = IS_OFS;
- printf("Appears to be OFS\n");
- }
- else
- printf("Appears to be FFS or similar\n");
- }
- }
- }
- ValidateIt();
- }
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- REG int idx;
-
- cli = argc;
-
- DO_QUAL();
-
- if (Cache > 1)
- Cache += 2;
-
- if (!Quiet && cli)
- STARTUP_MSG;
-
- OPEN_LIB(IBASE, "intuition.library", INTUITION_REV);
-
- PoolInit(&BufPoolKey, 0L, MEMF_CHIP);
- PoolInit(&GenPoolKey, PoolSize, 0L);
- PoolInit(&ZerPoolKey, 0L, MEMF_CLEAR);
-
- Val();
-
- if (StatCache)
- { ulong BTot = ReadSmall*2 + ReadLNum;
- ulong RTot = HitSmall + HitLarge + ReadSmall + ReadLarge;
-
- #define PER(x) (RTot ? (double)(x) / (double)(RTot) * (double)(100): (double)0)
-
- printf("Cache Statistics (Real Time) - Cache = 2:%d\n", Cache-2);
- if (Cache == 1)
- puts("Well ... first you need to HAVE a cache! (Try /cache=75)");
- else
- { printf("Blocks Requested....... %10lu\n", RTot);
- printf("Blocks Read............ %10lu\n", BTot);
- printf("Average Reads/Request.. %10.2lf\n", (double)(BTot) / (double)(RTot));
- printf("Total µsecs Cache Code. %10lu\n", MicCode);
- if (MicCode)
- printf("Average µsec/CodeReq... %10.2lf\n",
- (double)(MicCode) / (double)(HitSmall + HitLarge));
- printf("Total µsecs Cache IOReq %10lu\n", MicRead);
- if (MicRead)
- printf("Average µsec/IOReq..... %10.2lf\n",
- (double)(MicRead) / (double)(ReadSmall + ReadLarge));
- printf("Total µsec Cache Req... %10lu\n", MicCode + MicRead);
- if (MicCode || MicRead)
- printf("Average µsec/Request... %10.2lf\n",
- ((double)(MicCode) + (double)(MicRead)) / (double)(RTot));
- printf("Hits on Small Cache.... %10lu %6.2lf%%\n", HitSmall, PER(HitSmall));
- printf("Hits on Large Cache.... %10lu %6.2lf%%\n", HitLarge, PER(HitLarge));
- printf("Reads to Small Cache... %10lu %6.2lf%%\n", ReadSmall, PER(ReadSmall));
- printf("Reads to Large Cache... %10lu %6.2lf%%\n", ReadLarge, PER(ReadLarge));
- }
- }
-
- Cleanup();
- }
-
- MyError(num, why)
- REG long num;
- REG char *why;
- {
- ERROR_INIT
-
- if (Inhibited)
- AkDevInhibit(&Stuff, 0L);
-
- if (!Dev)
- AkDevClose(&Stuff);
-
- ERROR_TEST
- CASE_ERR_TOODEEP
- CASE_ERR_AKDEVALL
- CASE_ERR_NOVAL
- CASE_ERR_NOMEM
- CASE_ERR_NOLIB
- CASE_ERR_BADFIL
- ERROR_END(FACILITY_VAL)
-
- PoolFree(&ZerPoolKey);
- PoolFree(&GenPoolKey);
- PoolFree(&BufPoolKey);
-
- if (IBASE)
- CloseLibrary(IBASE);
-
- CLEANUP_QUAL();
-
- ERROR_EXIT
- }
-