home *** CD-ROM | disk | FTP | other *** search
- /* x-check.c */
-
- #include "kernel.h"
- #include <stdio.h>
- #include <ctype.h>
- #include "swis.h"
- #include <stdarg.h>
- #include <setjmp.h>
-
- #include "chunks.h"
-
- #define FREE 0x45455246
-
- static jmp_buf jb;
-
- static void ASSERT(int t)
- {
- static _kernel_oserror assertFailed = { 0, "Assert failed" };
-
- if (!t)
- e(&assertFailed);
- }
-
- static void e(_kernel_oserror *err)
- {
- if (err)
- longjmp(jb, (int) err);
- }
-
- static int power2(int x)
- {
- while (x && !(x & 1)) x >>= 1;
- return x == 1;
- }
-
- static void test(int c, const char *fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
-
- if (!c)
- {
- char buffer[256];
- vsprintf(buffer, fmt, ap);
- printf("x-check: %s\n", buffer);
- }
-
- va_end(ap);
- }
-
- static int okOffset(xFiles_info *pInfo, unsigned offset)
- {
- return (offset & (pInfo->fileHeader.allocationSize - 1)) == 0;
- }
-
- static void testChunk(xFiles_info *pInfo, unsigned cnkNum, xFiles_chunk *pChunk)
- {
- unsigned maxChunk;
-
- test(pInfo->fileHeader.chunkTable.size % sizeof(xFiles_chunk) == 0,
- "Bad size for chunk table %d",
- pInfo->fileHeader.chunkTable.size);
-
- maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
-
- test(cnkNum < maxChunk, "Bad chunk number %d", cnkNum);
-
- if (pChunk->usage == FREE)
- {
- test(pChunk->offset < maxChunk,
- "Chunk %d (free) bad offset %08x", cnkNum, pChunk->offset);
-
- test(pChunk->size == FREE,
- "Chunk %d (free) size is %08x (should be %08x)",
- cnkNum, pChunk->size, FREE);
-
- test(pChunk->allocSize == FREE,
- "Chunk %d (free) allocSize is %08x (should be %08x)",
- cnkNum, pChunk->allocSize, FREE);
- }
- else
- {
- test(okOffset(pChunk->offset),
- "Chunk %d (used) bad offset %08x", cnkNum, pChunk->offset);
- test(pChunk->size <= pChunk->allocSize)
- "Chunk %d (used) bad size %08x (allocSize %08x)",
- cnkNum, pChunk->size, pChunk->allocSize);
- test(okOffset(pChunk->allocSize),
- "Chunk %d (used) bad allocSize %08x", cnkNum, pChunk->allocSize);
- }
- }
-
- static int chcmp(const void *a, const void *b)
- {
- const xFiles_chunk *ca = a;
- const xFiles_chunk *cb = b;
-
- return (int) ca->offset - (int) cb->offset;
- }
-
- static void checkChunkTable(xFiles_info *pInfo)
- {
- xFiles_chunk *ct;
- unsigned maxChunk, freeChunk;
- unsigned i, j;
-
- maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
-
- ct = malloc(maxChunk * sizeof(xFiles_chunk));
- ASSERT(ct != NULL);
-
- e(xFiles_readChunk(pInfo, ct, 0, maxChunk * sizeof(xFiles_chunk), 0));
-
- /* First follow the free chain */
-
- freeChunk = pInfo->fileHeader.freeChunk;
-
- while (freeChunk != 0)
- {
- testChunk(pInfo, freeChunk, &ct[freeChunk]);
- ct[freeChunk].usage = 0;
- freeChunk = ct[freeChunk].offset;
- }
-
- /* Scan for any untouched free chunks and also discard any free chunks ready
- * for checking the used ones.
- */
-
- for (i = 0, j = 0; i < maxChunk; i++)
- {
- if (ct[i].usage == FREE)
- {
- printf("x-check: free chunk %d is unlinked\n", c);
- }
-
- if (ct[i].size != free)
- ct[j++] = ct[i];
- }
-
- maxChunk = j;
-
- /* Now sort the array on offset so we can look for overlaps */
-
- qsort(ct, maxChunk, sizeof(xFiles_chunk), chcmp);
-
- free(ct);
- }
-
- static _kernel_oserror *check(const char *fileName, int fix)
- {
- xFiles_info info;
- _kernel_swi_regs regs;
- _kernel_oserror *err;
- unsigned fileSize;
-
- regs.r[0] = 0x4F;
- regs.r[1] = (int) fileName;
- if (err = _kernel_swi(OS_Find, ®s, ®s), err)
- return err;
-
- info.FileHandle = regs.r[0];
-
- if (err = xFiles_openImage(&info), err)
- goto fail;
-
- if (err = xFiles_getLength(&info, &fileSize), err)
- goto fail;
-
- if (err = (_kernel_oserror *) setjmp(jb), err)
- goto fail;
-
- /* Validate the header */
-
- test(info.fileHeader.hdrSize == sizeof(xFiles_header),
- "Illegal hdrSize %d",
- info.fileHeader.hdrSize);
-
- test(info.fileHeader.structureVersion == xFiles_STRUCTUREVERSION,
- "Illegal structureVersion %d",
- info.fileHeader.structureVersion);
-
- test(info.fileHeader.directoryVersion == xFiles_DIRECTORYVERSION,
- "Illegal directoryVersion %d",
- info.fileHeader.directoryVersion);
-
- testChunk(&info, 0, &info.fileHeader.chunkTable);
-
- test(power2(info.fileHeader.allocationUnit),
- "Illegal allocationUnit %d",
- info.fileHeader.allocationUnit);
-
- testChunkTable(&info);
- test(info.fileHeader.waste < fileSize,
- "Illegal waste %d (fileSize is %d)",
- info.fileHeader.waste, fileSize);
-
- testStructure(&info);
-
- if (err = xFiles_FlushFileInfo(&info), err)
- goto fail;
-
- regs.r[0] = 0;
- regs.r[1] = info.fileHandle;
- return _kernel_swi(OS_Find, ®s, ®s);
-
- fail:
- regs.r[0] = 0;
- regs.r[1] = info.fileHandle;
- (void) _kernel_swi(OS_Find, ®s, ®s);
- return err;
- }
-
- int main(int argc, char *argv[])
- {
- int argn;
- int fix = 0;
-
- for (argn = 1; argn < argc; argn++)
- {
- if (*argv[argn] == '-')
- {
- switch (tolower(argv[argn][1]))
- {
- case 'f':
- fix = 1;
- break;
- default:
- fprintf(stderr, "Ignoring unknown option \"%s\"\n", argv[argn]);
- break;
- }
- }
- }
-
- for (argn = 1; argn < argc; argn++)
- {
- if (*argv[argn] != '-')
- {
- check(argv[argn], fix);
- }
- }
-
- return 0;
- }
-