mirror of
https://github.com/bobbimanners/GNO-Extras.git
synced 2025-01-05 02:31:51 +00:00
Improvements to error reporting
This commit is contained in:
parent
43abef7f98
commit
585e285abd
@ -1,25 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Bobbi January-February 2020
|
* Bobbi January-February 2020
|
||||||
*
|
*
|
||||||
* TODO: Error counting & fix error return codes
|
|
||||||
* TODO: Error log file option
|
|
||||||
* TODO: Fix mode
|
* TODO: Fix mode
|
||||||
|
* TODO: Do-nothing sort option for use with case-change option
|
||||||
|
* TODO: Case insensitive sort option
|
||||||
* TODO: Tool for 'extending' volume dir to more than 4 blocks
|
* TODO: Tool for 'extending' volume dir to more than 4 blocks
|
||||||
* TODO: Legacy/extended date format conversion
|
* TODO: Legacy/extended date format conversion
|
||||||
* TODO: Trimming unused directory blocks
|
* TODO: Trimming unused directory blocks
|
||||||
* TODO: Improve output and user interface
|
* TODO: Make a version that doesn't need GNO - eliminate call to stat()
|
||||||
* TODO: Maybe make a version that doesn't need GNO
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma debug 25 /* Enable stack checking */
|
#pragma debug 9
|
||||||
#pragma lint -1
|
#pragma lint -1
|
||||||
#pragma stacksize 16384
|
#pragma stacksize 16384
|
||||||
#pragma memorymodel 0
|
#pragma memorymodel 0
|
||||||
|
#pragma optimize -1 /* Disable stack repair code */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -27,7 +28,6 @@
|
|||||||
#include <gsos.h>
|
#include <gsos.h>
|
||||||
#include <prodos.h>
|
#include <prodos.h>
|
||||||
|
|
||||||
|
|
||||||
#undef DEBUG /* Enable additional debug printout */
|
#undef DEBUG /* Enable additional debug printout */
|
||||||
#define CHECK /* Perform additional integrity checking */
|
#define CHECK /* Perform additional integrity checking */
|
||||||
|
|
||||||
@ -82,6 +82,12 @@ struct pd_dirent {
|
|||||||
#define PTRSZ 4 /* 4 bytes of pointers at beginning of each blk */
|
#define PTRSZ 4 /* 4 bytes of pointers at beginning of each blk */
|
||||||
#define FLSZ 8192 /* Bytes required for 64K block free-list */
|
#define FLSZ 8192 /* Bytes required for 64K block free-list */
|
||||||
|
|
||||||
|
/* Exit codes */
|
||||||
|
#define EXIT_SUCCESS 0
|
||||||
|
#define EXIT_BAD_ARG 1
|
||||||
|
#define EXIT_ALLOC_ERR 2
|
||||||
|
#define EXIT_FATAL_ERR 3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linked list of directory blocks read from disk
|
* Linked list of directory blocks read from disk
|
||||||
* Original directory block is stored in data[]
|
* Original directory block is stored in data[]
|
||||||
@ -143,6 +149,7 @@ static uchar entperblk; /* Number of entries per block */
|
|||||||
static char buf[BLKSZ]; /* General purpose scratch buffer */
|
static char buf[BLKSZ]; /* General purpose scratch buffer */
|
||||||
static char buf2[BLKSZ]; /* General purpose scratch buffer */
|
static char buf2[BLKSZ]; /* General purpose scratch buffer */
|
||||||
static char buf3[BLKSZ]; /* General purpose scratch buffer */
|
static char buf3[BLKSZ]; /* General purpose scratch buffer */
|
||||||
|
static uint errcount = 0; /* Error counter */
|
||||||
static uchar dowholedisk = 0; /* -D whole-disk option */
|
static uchar dowholedisk = 0; /* -D whole-disk option */
|
||||||
static uchar dorecurse = 0; /* -r recurse option */
|
static uchar dorecurse = 0; /* -r recurse option */
|
||||||
static uchar dowrite = 0; /* -w write option */
|
static uchar dowrite = 0; /* -w write option */
|
||||||
@ -153,8 +160,8 @@ static char sortopts[5] = ""; /* -s:abc list of sort options */
|
|||||||
static char caseopts[2] = ""; /* -c:x case conversion option */
|
static char caseopts[2] = ""; /* -c:x case conversion option */
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototypes */
|
||||||
void prerr(char *s);
|
|
||||||
void hline(void);
|
void hline(void);
|
||||||
|
void err(enum errtype severity, char *fmt, ...);
|
||||||
void flushall(void);
|
void flushall(void);
|
||||||
int readdiskblock(uchar device, uint blocknum, char *buf);
|
int readdiskblock(uchar device, uint blocknum, char *buf);
|
||||||
int writediskblock(uchar device, uint blocknum, char *buf);
|
int writediskblock(uchar device, uint blocknum, char *buf);
|
||||||
@ -199,18 +206,47 @@ void usage(void);
|
|||||||
void processdir(uint device, uint blocknum);
|
void processdir(uint device, uint blocknum);
|
||||||
void checkfreeandused(void);
|
void checkfreeandused(void);
|
||||||
|
|
||||||
/* Print error string to stderr */
|
|
||||||
void prerr(char *s) {
|
|
||||||
fputs(s, stderr);
|
|
||||||
fputs("\n", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Horizontal line */
|
/* Horizontal line */
|
||||||
void hline(void) {
|
void hline(void) {
|
||||||
for (uint i=0; i<80; ++i)
|
for (uint i=0; i<80; ++i)
|
||||||
putchar('-');
|
putchar('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum errtype {WARN, NONFATAL, FATAL, FATALALLOC, FATALBADARG, FINISHED};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display error message
|
||||||
|
*/
|
||||||
|
void err(enum errtype severity, char *fmt, ...) {
|
||||||
|
if (severity == FINISHED) {
|
||||||
|
hline();
|
||||||
|
if (errcount == 0)
|
||||||
|
printf("Done - no errors found.\n");
|
||||||
|
else
|
||||||
|
printf("Done - %u errors\n", errcount);
|
||||||
|
hline();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
++errcount;
|
||||||
|
fputs(" ", stdout);
|
||||||
|
va_list v;
|
||||||
|
va_start(v, fmt);
|
||||||
|
vprintf(fmt, v);
|
||||||
|
putchar('\n');
|
||||||
|
va_end(v);
|
||||||
|
switch (severity) {
|
||||||
|
case FATAL:
|
||||||
|
printf("Stopping after %u errors\n", errcount);
|
||||||
|
exit(EXIT_FATAL_ERR);
|
||||||
|
case FATALALLOC:
|
||||||
|
printf("Stopping after %u errors\n", errcount);
|
||||||
|
exit(EXIT_ALLOC_ERR);
|
||||||
|
case FATALBADARG:
|
||||||
|
printf("Stopping after %u errors\n", errcount);
|
||||||
|
exit(EXIT_BAD_ARG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable GSOS block cache and flush any unwritten changes
|
* Disable GSOS block cache and flush any unwritten changes
|
||||||
*/
|
*/
|
||||||
@ -233,7 +269,7 @@ int readdiskblock(uchar device, uint blocknum, char *buf) {
|
|||||||
#ifdef CHECK
|
#ifdef CHECK
|
||||||
if (flloaded)
|
if (flloaded)
|
||||||
if (isfree(blocknum))
|
if (isfree(blocknum))
|
||||||
printf(" Block %u is marked free!\n", blocknum);
|
err(NONFATAL, "Block %u is marked free!", blocknum);
|
||||||
#endif
|
#endif
|
||||||
BlockRec br;
|
BlockRec br;
|
||||||
br.blockDevNum = device;
|
br.blockDevNum = device;
|
||||||
@ -242,7 +278,7 @@ int readdiskblock(uchar device, uint blocknum, char *buf) {
|
|||||||
READ_BLOCK(&br);
|
READ_BLOCK(&br);
|
||||||
int rc = toolerror();
|
int rc = toolerror();
|
||||||
if (rc) {
|
if (rc) {
|
||||||
printf(" READ_BLOCK failed, err=%x\n", rc);
|
err(FATAL, "Block read failed, err=%x", rc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -258,7 +294,7 @@ int writediskblock(uchar device, uint blocknum, char *buf) {
|
|||||||
#endif
|
#endif
|
||||||
if ((strcmp(currdir, "LIB") == 0) ||
|
if ((strcmp(currdir, "LIB") == 0) ||
|
||||||
(strcmp(currdir, "LIBRARIES") == 0)) {
|
(strcmp(currdir, "LIBRARIES") == 0)) {
|
||||||
puts("Not writing library directory");
|
printf("Not writing library directory %s\n", currdir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
flushall();
|
flushall();
|
||||||
@ -270,8 +306,10 @@ int writediskblock(uchar device, uint blocknum, char *buf) {
|
|||||||
dr.startingBlock = blocknum;
|
dr.startingBlock = blocknum;
|
||||||
dr.blockSize = BLKSZ;
|
dr.blockSize = BLKSZ;
|
||||||
DWriteGS(&dr);
|
DWriteGS(&dr);
|
||||||
if (dr.transferCount != BLKSZ)
|
if (dr.transferCount != BLKSZ) {
|
||||||
|
err(FATAL, "Block write failed");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +344,6 @@ void fixcase(char *in, char *out, uchar minvers, uchar vers, uchar len) {
|
|||||||
*/
|
*/
|
||||||
void lowercase(char *p, uchar len, uchar *minvers, uchar *vers) {
|
void lowercase(char *p, uchar len, uchar *minvers, uchar *vers) {
|
||||||
uchar idx = 0;
|
uchar idx = 0;
|
||||||
//printf("vers 0x%2x minvers 0x%2x\n", *vers, *minvers);
|
|
||||||
*vers = 0x01;
|
*vers = 0x01;
|
||||||
*minvers = 0x00;
|
*minvers = 0x00;
|
||||||
for (uint i=0; i<7; ++i) {
|
for (uint i=0; i<7; ++i) {
|
||||||
@ -319,7 +356,6 @@ void lowercase(char *p, uchar len, uchar *minvers, uchar *vers) {
|
|||||||
if ((idx < len) && isalpha(p[idx++]))
|
if ((idx < len) && isalpha(p[idx++]))
|
||||||
*minvers |= 0x01;
|
*minvers |= 0x01;
|
||||||
}
|
}
|
||||||
//printf("vers 0x%2x minvers 0x%2x\n", *vers, *minvers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -340,7 +376,6 @@ void uppercase(char *p, uchar len, uchar *minvers, uchar *vers) {
|
|||||||
void initialcase(uchar mode, char *p, uchar len, uchar *minvers, uchar *vers) {
|
void initialcase(uchar mode, char *p, uchar len, uchar *minvers, uchar *vers) {
|
||||||
uchar idx = 0;
|
uchar idx = 0;
|
||||||
uchar capsflag = 1;
|
uchar capsflag = 1;
|
||||||
//printf("vers 0x%2x minvers 0x%2x\n", *vers, *minvers);
|
|
||||||
*vers = 0x01;
|
*vers = 0x01;
|
||||||
*minvers = 0x00;
|
*minvers = 0x00;
|
||||||
for (uint i=0; i<7; ++i) {
|
for (uint i=0; i<7; ++i) {
|
||||||
@ -363,9 +398,10 @@ void initialcase(uchar mode, char *p, uchar len, uchar *minvers, uchar *vers) {
|
|||||||
else
|
else
|
||||||
capsflag = 0;
|
capsflag = 0;
|
||||||
}
|
}
|
||||||
//printf("vers 0x%2x minvers 0x%2x\n", *vers, *minvers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
segment "extra";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the first block of a directory and deduce the device ID and block
|
* Read the first block of a directory and deduce the device ID and block
|
||||||
* number of the first block of the directory.
|
* number of the first block of the directory.
|
||||||
@ -376,28 +412,24 @@ uchar firstblk(char *dirname, uchar *device, uint *block) {
|
|||||||
|
|
||||||
fp = open(dirname, O_RDONLY);
|
fp = open(dirname, O_RDONLY);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
printf("Error opening dir %s\n", dirname);
|
err(NONFATAL, "Error opening dir %s", dirname);
|
||||||
rv = 1;
|
rv = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t len = read(fp, buf, BLKSZ);
|
ssize_t len = read(fp, buf, BLKSZ);
|
||||||
if (len != BLKSZ) {
|
if (len != BLKSZ) {
|
||||||
printf("Error reading first block of dir %s", dirname);
|
err(NONFATAL, "Error reading first block of dir %s", dirname);
|
||||||
rv = 1;
|
rv = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(dirname, &st) == -1) {
|
if (stat(dirname, &st) == -1)
|
||||||
printf("Can't stat %s\n", dirname);
|
err(FATAL, "Can't stat %s", dirname);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
if (!S_ISDIR(st.st_mode))
|
||||||
printf("%s is not a directory\n", dirname);
|
err(FATAL, "%s is not a directory", dirname);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
*device = st.st_dev;
|
*device = st.st_dev;
|
||||||
|
|
||||||
@ -411,7 +443,7 @@ uchar firstblk(char *dirname, uchar *device, uint *block) {
|
|||||||
|
|
||||||
#ifdef CHECK
|
#ifdef CHECK
|
||||||
if ((hdr->typ_len & 0xf0) != 0xe0) {
|
if ((hdr->typ_len & 0xf0) != 0xe0) {
|
||||||
puts("Bad storage type");
|
err(NONFATAL, "Bad storage type");
|
||||||
rv = 1;
|
rv = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
@ -423,11 +455,8 @@ uchar firstblk(char *dirname, uchar *device, uint *block) {
|
|||||||
uint parententlen = hdr->parentlen;
|
uint parententlen = hdr->parentlen;
|
||||||
|
|
||||||
/* Read parent directory block */
|
/* Read parent directory block */
|
||||||
if (readdiskblock(*device, parentblk, buf) == -1) {
|
if (readdiskblock(*device, parentblk, buf) == -1)
|
||||||
printf("Can't read parent directory for %s", dirname);
|
err(FATAL, "Can't read parent directory for %s", dirname);
|
||||||
rv = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pd_dirent *ent =
|
struct pd_dirent *ent =
|
||||||
(struct pd_dirent *)(buf + PTRSZ + (parententry-1) * parententlen);
|
(struct pd_dirent *)(buf + PTRSZ + (parententry-1) * parententlen);
|
||||||
@ -440,8 +469,6 @@ ret:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
segment "extra";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse mtime or ctime fields and populate the fields of the datetime struct
|
* Parse mtime or ctime fields and populate the fields of the datetime struct
|
||||||
* Supports the legacy ProDOS date/time format as used by ProDOS 1.0->2.4.0
|
* Supports the legacy ProDOS date/time format as used by ProDOS 1.0->2.4.0
|
||||||
@ -478,21 +505,17 @@ void convertdatetime(uchar time[4], struct datetime *dt) {
|
|||||||
*/
|
*/
|
||||||
int readfreelist(uchar device) {
|
int readfreelist(uchar device) {
|
||||||
freelist = (uchar*)malloc(FLSZ);
|
freelist = (uchar*)malloc(FLSZ);
|
||||||
if (!freelist) {
|
if (!freelist)
|
||||||
puts("** Unable to allocate memory **");
|
err(FATALALLOC, "** Unable to allocate memory **");
|
||||||
exit(3);
|
|
||||||
}
|
|
||||||
bzero(freelist, FLSZ);
|
bzero(freelist, FLSZ);
|
||||||
usedlist = (uchar*)malloc(FLSZ);
|
usedlist = (uchar*)malloc(FLSZ);
|
||||||
if (!usedlist) {
|
if (!usedlist)
|
||||||
puts("** Unable to allocate memory **");
|
err(FATALALLOC, "** Unable to allocate memory **");
|
||||||
exit(3);
|
|
||||||
}
|
|
||||||
bzero(usedlist, FLSZ);
|
bzero(usedlist, FLSZ);
|
||||||
markused(0); /* Boot block */
|
markused(0); /* Boot block */
|
||||||
markused(1); /* SOS boot block */
|
markused(1); /* SOS boot block */
|
||||||
if (readdiskblock(device, 2, buf) == -1) {
|
if (readdiskblock(device, 2, buf) == -1) {
|
||||||
puts("Error reading volume dir");
|
err(NONFATAL, "Error reading volume dir");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint flblk = buf[0x27] + 256U * buf[0x28];
|
uint flblk = buf[0x27] + 256U * buf[0x28];
|
||||||
@ -506,7 +529,7 @@ int readfreelist(uchar device) {
|
|||||||
for (uint i=0; i<flsize; ++i) {
|
for (uint i=0; i<flsize; ++i) {
|
||||||
markused(flblk);
|
markused(flblk);
|
||||||
if (readdiskblock(device, flblk++, p) == -1) {
|
if (readdiskblock(device, flblk++, p) == -1) {
|
||||||
puts("Error reading free list");
|
err(NONFATAL, "Error reading free list");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p += BLKSZ;
|
p += BLKSZ;
|
||||||
@ -537,7 +560,6 @@ int isused(uint blk) {
|
|||||||
* Mark a block as used
|
* Mark a block as used
|
||||||
*/
|
*/
|
||||||
void markused(uint blk) {
|
void markused(uint blk) {
|
||||||
//printf("markused(%u)\n", blk);
|
|
||||||
uint idx = blk / 8;
|
uint idx = blk / 8;
|
||||||
uint bit = blk % 8;
|
uint bit = blk % 8;
|
||||||
usedlist[idx] |= (0x80 >> bit);
|
usedlist[idx] |= (0x80 >> bit);
|
||||||
@ -550,9 +572,9 @@ void markused(uint blk) {
|
|||||||
*/
|
*/
|
||||||
void checkblock(uint blk, char *msg) {
|
void checkblock(uint blk, char *msg) {
|
||||||
if (isfree(blk))
|
if (isfree(blk))
|
||||||
printf(" %s block %u is marked free!\n", msg, blk);
|
err(WARN, "%s block %u is marked free!", msg, blk);
|
||||||
if (isused(blk))
|
if (isused(blk))
|
||||||
printf(" %s block %u is already used!\n", msg, blk);
|
err(WARN, "%s block %u is already used!", msg, blk);
|
||||||
markused(blk);
|
markused(blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +593,7 @@ int seedlingblocks(uchar device, uint keyblk, uint *blkcnt) {
|
|||||||
int saplingblocks(uchar device, uint keyblk, uint *blkcnt) {
|
int saplingblocks(uchar device, uint keyblk, uint *blkcnt) {
|
||||||
checkblock(keyblk, "Data");
|
checkblock(keyblk, "Data");
|
||||||
if (readdiskblock(device, keyblk, buf) == -1) {
|
if (readdiskblock(device, keyblk, buf) == -1) {
|
||||||
printf(" Error reading blk %u\n", keyblk);
|
err(NONFATAL, "Error reading blk %u", keyblk);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*blkcnt = 1;
|
*blkcnt = 1;
|
||||||
@ -591,7 +613,7 @@ int saplingblocks(uchar device, uint keyblk, uint *blkcnt) {
|
|||||||
int treeblocks(uchar device, uint keyblk, uint *blkcnt) {
|
int treeblocks(uchar device, uint keyblk, uint *blkcnt) {
|
||||||
checkblock(keyblk, "Tree index");
|
checkblock(keyblk, "Tree index");
|
||||||
if (readdiskblock(device, keyblk, buf2) == -1) {
|
if (readdiskblock(device, keyblk, buf2) == -1) {
|
||||||
printf(" Error reading blk %u\n", keyblk);
|
err(NONFATAL, "Error reading blk %u", keyblk);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*blkcnt = 1;
|
*blkcnt = 1;
|
||||||
@ -615,7 +637,7 @@ int treeblocks(uchar device, uint keyblk, uint *blkcnt) {
|
|||||||
int forkblocks(uchar device, uint keyblk, uint *blkcnt) {
|
int forkblocks(uchar device, uint keyblk, uint *blkcnt) {
|
||||||
checkblock(keyblk, "Fork key");
|
checkblock(keyblk, "Fork key");
|
||||||
if (readdiskblock(device, keyblk, buf3) == -1) {
|
if (readdiskblock(device, keyblk, buf3) == -1) {
|
||||||
printf(" Error reading blk %u\n", keyblk);
|
err(NONFATAL, "Error reading blk %u", keyblk);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*blkcnt = 1;
|
*blkcnt = 1;
|
||||||
@ -639,14 +661,16 @@ int forkblocks(uchar device, uint keyblk, uint *blkcnt) {
|
|||||||
treeblocks(device, keyblk, &count);
|
treeblocks(device, keyblk, &count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
puts(" Invalid storage type for data fork");
|
err(NONFATAL, "Invalid storage type for data fork");
|
||||||
count = 0;
|
count = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (blks != count) {
|
if (blks != count) {
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
printf(" Data fork size %u is incorrect", blks);
|
err(NONFATAL,
|
||||||
printf(", should be %u\n", count);
|
"Data fork size %u is incorrect, should be %u",
|
||||||
|
blks, count);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*blkcnt += count;
|
*blkcnt += count;
|
||||||
@ -669,14 +693,16 @@ int forkblocks(uchar device, uint keyblk, uint *blkcnt) {
|
|||||||
treeblocks(device, keyblk, &count);
|
treeblocks(device, keyblk, &count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
puts(" Invalid storage type for resource fork");
|
err(NONFATAL, "Invalid storage type for resource fork");
|
||||||
count = 0;
|
count = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (blks != count) {
|
if (blks != count) {
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
printf(" Resource fork size %u is incorrect", blks);
|
err(NONFATAL,
|
||||||
printf(", should be %u\n", count);
|
"Res fork size %u is incorrect, should be %u",
|
||||||
|
blks, count);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*blkcnt += count;
|
*blkcnt += count;
|
||||||
@ -693,7 +719,7 @@ int subdirblocks(uchar device, uint keyblk, struct pd_dirent *ent,
|
|||||||
if (!dorecurse)
|
if (!dorecurse)
|
||||||
checkblock(keyblk, "Directory");
|
checkblock(keyblk, "Directory");
|
||||||
if (readdiskblock(device, keyblk, buf) == -1) {
|
if (readdiskblock(device, keyblk, buf) == -1) {
|
||||||
printf(" Error reading keyblock %u\n", keyblk);
|
err(NONFATAL, "Error reading keyblock %u", keyblk);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*blkcnt = 1;
|
*blkcnt = 1;
|
||||||
@ -703,25 +729,29 @@ int subdirblocks(uchar device, uint keyblk, struct pd_dirent *ent,
|
|||||||
uint parblk = hdr->parptr[0] + 256U * hdr->parptr[1];
|
uint parblk = hdr->parptr[0] + 256U * hdr->parptr[1];
|
||||||
|
|
||||||
if (parblk != blocknum) {
|
if (parblk != blocknum) {
|
||||||
printf(" Bad parent block %u", parblk);
|
err(NONFATAL, "Bad parent block %u, should be %u",
|
||||||
printf(", should be %u\n", blocknum);
|
parblk, blocknum);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
if (parentry != blkentries) {
|
if (parentry != blkentries) {
|
||||||
printf(" Bad parent block entry %u", parentry);
|
err(NONFATAL, "Bad parent block entry %u, should be %u",
|
||||||
printf(", should be %u\n", blkentries);
|
parentry, blkentries);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
if (parentlen != 0x27)
|
if (parentlen != 0x27)
|
||||||
puts(" Bad parent entry length");
|
err(NONFATAL, "Bad parent entry length");
|
||||||
char *dirname = buf + 0x05;
|
char *dirname = buf + 0x05;
|
||||||
if (strncmp(dirname, ent->name, NMLEN))
|
if (strncmp(dirname, ent->name, NMLEN)) {
|
||||||
puts(" Subdirectory name mismatch");
|
err(NONFATAL,"Subdirectory name mismatch");
|
||||||
|
// TODO: FIX MODE
|
||||||
|
}
|
||||||
|
|
||||||
blocknum = buf[0x02] + 256U * buf[0x03];
|
blocknum = buf[0x02] + 256U * buf[0x03];
|
||||||
while (blocknum) {
|
while (blocknum) {
|
||||||
if (!dorecurse)
|
if (!dorecurse)
|
||||||
checkblock(blocknum, "Directory");
|
checkblock(blocknum, "Directory");
|
||||||
if (readdiskblock(device, blocknum, buf) == -1) {
|
if (readdiskblock(device, blocknum, buf) == -1) {
|
||||||
printf(" Error reading dir block %u\n", blocknum);
|
err(NONFATAL, "Error reading dir block %u", blocknum);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
++(*blkcnt);
|
++(*blkcnt);
|
||||||
@ -737,10 +767,8 @@ int subdirblocks(uchar device, uint keyblk, struct pd_dirent *ent,
|
|||||||
*/
|
*/
|
||||||
void enqueuesubdir(uint blocknum, uint subdiridx) {
|
void enqueuesubdir(uint blocknum, uint subdiridx) {
|
||||||
struct dirblk *p = (struct dirblk*)malloc(sizeof(struct dirblk));
|
struct dirblk *p = (struct dirblk*)malloc(sizeof(struct dirblk));
|
||||||
if (!p) {
|
if (!p)
|
||||||
puts("** Unable to allocate memory **");
|
err(FATALALLOC, "** Unable to allocate memory **");
|
||||||
exit(3);
|
|
||||||
}
|
|
||||||
p->blocknum = blocknum;
|
p->blocknum = blocknum;
|
||||||
static struct dirblk *prev;
|
static struct dirblk *prev;
|
||||||
if (subdiridx == 0) { /* First subdir is inserted at head of list */
|
if (subdiridx == 0) { /* First subdir is inserted at head of list */
|
||||||
@ -760,23 +788,22 @@ void enqueuesubdir(uint blocknum, uint subdiridx) {
|
|||||||
* blocknum is the block number of the first block of the directory
|
* blocknum is the block number of the first block of the directory
|
||||||
*/
|
*/
|
||||||
int readdir(uint device, uint blocknum) {
|
int readdir(uint device, uint blocknum) {
|
||||||
|
uint errsbefore = errcount;
|
||||||
uint blkcnt = 1;
|
uint blkcnt = 1;
|
||||||
uint hdrblknum = blocknum;
|
uint hdrblknum = blocknum;
|
||||||
|
|
||||||
numfiles = 0;
|
numfiles = 0;
|
||||||
|
|
||||||
blocks = (struct block*)malloc(sizeof(struct block));
|
blocks = (struct block*)malloc(sizeof(struct block));
|
||||||
if (!blocks) {
|
if (!blocks)
|
||||||
puts("** Unable to allocate memory **");
|
err(FATALALLOC, "** Unable to allocate memory **");
|
||||||
exit(3);
|
|
||||||
}
|
|
||||||
struct block *curblk = blocks;
|
struct block *curblk = blocks;
|
||||||
curblk->next = NULL;
|
curblk->next = NULL;
|
||||||
curblk->blocknum = blocknum;
|
curblk->blocknum = blocknum;
|
||||||
|
|
||||||
checkblock(blocknum, "Directory");
|
checkblock(blocknum, "Directory");
|
||||||
if (readdiskblock(device, blocknum, curblk->data) == -1) {
|
if (readdiskblock(device, blocknum, curblk->data) == -1) {
|
||||||
printf("Error reading dir block %d\n", blkcnt);
|
err(NONFATAL, "Error reading dir block %d", blkcnt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +818,8 @@ int readdir(uint device, uint blocknum) {
|
|||||||
hdr->vers, hdr->minvers, hdr->typ_len & 0x0f);
|
hdr->vers, hdr->minvers, hdr->typ_len & 0x0f);
|
||||||
|
|
||||||
hline();
|
hline();
|
||||||
printf("Directory %s (%d entries)\n", currdir, filecount);
|
printf("Directory %s (%u", currdir, filecount);
|
||||||
|
printf(" %s)\n", filecount == 1 ? "entry" : "entries");
|
||||||
hline();
|
hline();
|
||||||
|
|
||||||
/* Copy pointers and header to sorteddata[], zero the rest */
|
/* Copy pointers and header to sorteddata[], zero the rest */
|
||||||
@ -800,11 +828,11 @@ int readdir(uint device, uint blocknum) {
|
|||||||
|
|
||||||
#ifdef CHECK
|
#ifdef CHECK
|
||||||
if (entsz != 0x27) {
|
if (entsz != 0x27) {
|
||||||
puts("Error - bad entry size");
|
err(NONFATAL, "Error - bad entry size");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (entperblk != 0x0d) {
|
if (entperblk != 0x0d) {
|
||||||
puts("Error - bad entries/block");
|
err(NONFATAL, "Error - bad entries/block");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -903,8 +931,9 @@ int readdir(uint device, uint blocknum) {
|
|||||||
uint keyblk = ent->keyptr[0] + 256U * ent->keyptr[1];
|
uint keyblk = ent->keyptr[0] + 256U * ent->keyptr[1];
|
||||||
uint hdrblk = ent->hdrptr[0] + 256U * ent->hdrptr[1];
|
uint hdrblk = ent->hdrptr[0] + 256U * ent->hdrptr[1];
|
||||||
if (hdrblk != hdrblknum) {
|
if (hdrblk != hdrblknum) {
|
||||||
printf(" Header ptr %u should be %u\n",
|
err(NONFATAL, "Header ptr %u, should be %u",
|
||||||
hdrblk, hdrblknum);
|
hdrblk, hdrblknum);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
uint count;
|
uint count;
|
||||||
switch (ent->typ_len & 0xf0) {
|
switch (ent->typ_len & 0xf0) {
|
||||||
@ -939,20 +968,23 @@ int readdir(uint device, uint blocknum) {
|
|||||||
forkblocks(device, keyblk, &count);
|
forkblocks(device, keyblk, &count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf(" %s: unexpected storage type 0x%x\n",
|
err(NONFATAL,
|
||||||
namebuf, ent->typ_len & 0xf0);
|
"%s: unexpected storage type 0x%x",
|
||||||
|
namebuf, ent->typ_len & 0xf0);
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
if (blks != count) {
|
if (blks != count) {
|
||||||
if (count != 0) {
|
if (count != 0) {
|
||||||
printf(" Size %u is incorrect", blks);
|
err(NONFATAL,
|
||||||
printf(", should be %u\n", count);
|
"Size %u is incorrect, "
|
||||||
|
"should be %u", blks, count);
|
||||||
|
// TODO: FIX MODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
++numfiles;
|
++numfiles;
|
||||||
if (numfiles == MAXFILES) {
|
if (numfiles == MAXFILES) {
|
||||||
puts("** Too many files! **");
|
err(NONFATAL, "** Too many files! **");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
++entries;
|
++entries;
|
||||||
@ -964,10 +996,9 @@ int readdir(uint device, uint blocknum) {
|
|||||||
}
|
}
|
||||||
curblk->next =
|
curblk->next =
|
||||||
(struct block*)malloc(sizeof(struct block));
|
(struct block*)malloc(sizeof(struct block));
|
||||||
if (!curblk->next) {
|
if (!curblk->next)
|
||||||
puts("** Unable to allocate memory **");
|
err(FATALALLOC,
|
||||||
exit(3);
|
"** Unable to allocate memory **");
|
||||||
}
|
|
||||||
curblk = curblk->next;
|
curblk = curblk->next;
|
||||||
curblk->next = NULL;
|
curblk->next = NULL;
|
||||||
curblk->blocknum = blocknum;
|
curblk->blocknum = blocknum;
|
||||||
@ -975,8 +1006,8 @@ int readdir(uint device, uint blocknum) {
|
|||||||
checkblock(blocknum, "Directory");
|
checkblock(blocknum, "Directory");
|
||||||
if ( readdiskblock(device, blocknum,
|
if ( readdiskblock(device, blocknum,
|
||||||
curblk->data) == -1) {
|
curblk->data) == -1) {
|
||||||
printf(" Error reading dir block %d\n",
|
err(NONFATAL,"Error reading dir block %d",
|
||||||
blkcnt);
|
blkcnt);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Copy ptrs to sorteddata[], zero the rest */
|
/* Copy ptrs to sorteddata[], zero the rest */
|
||||||
@ -989,9 +1020,12 @@ int readdir(uint device, uint blocknum) {
|
|||||||
idx += entsz;
|
idx += entsz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filecount != entries)
|
if (filecount != entries) {
|
||||||
printf("Filecount %u wrong, should be %u\n", filecount, entries);
|
err(NONFATAL, "Filecount %u wrong, should be %u",
|
||||||
return 0; // TODO: THIS SHOULD BE NUMBER OF ERRORS
|
filecount, entries);
|
||||||
|
// TODO: FIX MODE
|
||||||
|
}
|
||||||
|
return errcount - errsbefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1183,8 +1217,7 @@ void sortlist(char s) {
|
|||||||
cmp_eof_desc);
|
cmp_eof_desc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
puts("Invalid sort option");
|
err(FATALBADARG, "Invalid sort option");
|
||||||
exit(2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,7 +1226,6 @@ void sortlist(char s) {
|
|||||||
*/
|
*/
|
||||||
void printlist(void) {
|
void printlist(void) {
|
||||||
hline();
|
hline();
|
||||||
printf("numfiles=%u\n", numfiles);
|
|
||||||
fputs("Dirblk Entry Type : Name : Blocks EOF ", stdout);
|
fputs("Dirblk Entry Type : Name : Blocks EOF ", stdout);
|
||||||
if (do_ctime)
|
if (do_ctime)
|
||||||
puts("Created");
|
puts("Created");
|
||||||
@ -1240,8 +1272,8 @@ uint blockidxtoblocknum(uint idx) {
|
|||||||
void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) {
|
void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) {
|
||||||
|
|
||||||
if (dodebug) {
|
if (dodebug) {
|
||||||
printf(" from dirblk %03u entry %02u\n", srcblk, srcent);
|
printf(" from dirblk %03u entry %02u", srcblk, srcent);
|
||||||
printf(" to dirblk %03u entry %02u\n", dstblk, dstent);
|
printf(" to dirblk %03u entry %02u", dstblk, dstent);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint parentblk = blockidxtoblocknum(dstblk);
|
uint parentblk = blockidxtoblocknum(dstblk);
|
||||||
@ -1306,7 +1338,7 @@ int writedir(uchar device) {
|
|||||||
struct block *i = blocks;
|
struct block *i = blocks;
|
||||||
while (i) {
|
while (i) {
|
||||||
if(writediskblock(device, i->blocknum, i->sorteddata) == -1) {
|
if(writediskblock(device, i->blocknum, i->sorteddata) == -1) {
|
||||||
printf("Can't write block %u\n", i->blocknum);
|
err(NONFATAL, "Can't write block %u", i->blocknum);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
@ -1328,42 +1360,42 @@ void freeblocks(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void usage(void) {
|
void usage(void) {
|
||||||
prerr("usage: sortdir [-s xxx] [-n x] [-rDwcvVh] path\n");
|
printf("usage: sortdir [-s xxx] [-n x] [-rDwcvVh] path\n\n");
|
||||||
prerr(" Options: -s xxx Directory sort options");
|
printf(" Options: -s xxx Directory sort options\n");
|
||||||
prerr(" -n x Filename upper/lower case options");
|
printf(" -n x Filename upper/lower case options\n");
|
||||||
prerr(" -r Recursive descent");
|
printf(" -r Recursive descent\n");
|
||||||
prerr(" -D Whole-disk mode (implies -r)");
|
printf(" -D Whole-disk mode (implies -r)\n");
|
||||||
prerr(" -w Enable writing to disk");
|
printf(" -w Enable writing to disk\n");
|
||||||
prerr(" -c Use creation time rather than modification");
|
printf(" -c Use create time rather than modify time\n");
|
||||||
prerr(" -v Verbose output");
|
printf(" -v Verbose output\n");
|
||||||
prerr(" -V Verbose debugging output");
|
printf(" -V Verbose debugging output\n");
|
||||||
prerr(" -h This help");
|
printf(" -h This help\n");
|
||||||
prerr("");
|
printf("\n");
|
||||||
prerr("Upper/lower case option x:");
|
printf("Upper/lower case option x:\n");
|
||||||
prerr(" l convert filenames to lower case eg: read.me");
|
printf(" l convert filenames to lower case eg: read.me\n");
|
||||||
prerr(" u convert filenames to upper case eg: READ.ME");
|
printf(" u convert filenames to upper case eg: READ.ME\n");
|
||||||
prerr(" i convert filenames to initial upper case eg: Read.me");
|
printf(" i convert filenames to initial upper case eg: Read.me\n");
|
||||||
prerr(" c convert filenames to camel case eg: Read.Me");
|
printf(" c convert filenames to camel case eg: Read.Me\n");
|
||||||
prerr("");
|
printf("\n");
|
||||||
prerr("Directory sort options xxx, is a list of fields on which to");
|
printf("Directory sort options xxx, is a list of fields on which\n");
|
||||||
prerr("sort. The sort options are processed left-to-right.");
|
printf("to sort. The sort options are processed left-to-right.\n");
|
||||||
prerr(" n sort by filename ascending");
|
printf(" n sort by filename ascending\n");
|
||||||
prerr(" N sort by filename descending");
|
printf(" N sort by filename descending\n");
|
||||||
prerr(" d sort by modification (or creation [-c]) date ascending");
|
printf(" d sort by modify (or create [-c]) date ascending\n");
|
||||||
prerr(" D sort by modification (or creation [-c]) date descending");
|
printf(" D sort by modify (or create [-c]) date descending\n");
|
||||||
prerr(" t sort by type ascending");
|
printf(" t sort by type ascending\n");
|
||||||
prerr(" T sort by type descending");
|
printf(" T sort by type descending\n");
|
||||||
prerr(" f sort folders (directories) to top");
|
printf(" f sort folders (directories) to top\n");
|
||||||
prerr(" F sort folders (directories) to bottom");
|
printf(" F sort folders (directories) to bottom\n");
|
||||||
prerr(" b sort by blocks used ascending");
|
printf(" b sort by blocks used ascending\n");
|
||||||
prerr(" B sort by blocks used descending");
|
printf(" B sort by blocks used descending\n");
|
||||||
prerr(" e sort by EOF position ascending");
|
printf(" e sort by EOF position ascending\n");
|
||||||
prerr(" E sort by EOF position descending");
|
printf(" E sort by EOF position descending\n");
|
||||||
prerr("");
|
printf("\n");
|
||||||
prerr("e.g.: sortdir -w -s nf .");
|
printf("e.g.: sortdir -w -s nf .\n");
|
||||||
prerr("Will sort the current directory first by name (ascending),");
|
printf("Will sort the current directory first by name (ascending),\n");
|
||||||
prerr("then sort directories to the top, and will write the sorted");
|
printf("then sort directories to the top, and will write the\n");
|
||||||
prerr("directory to disk.");
|
printf("sorted directory to disk.\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1373,19 +1405,19 @@ void usage(void) {
|
|||||||
*/
|
*/
|
||||||
void processdir(uint device, uint blocknum) {
|
void processdir(uint device, uint blocknum) {
|
||||||
flushall();
|
flushall();
|
||||||
uchar err = readdir(device, blocknum);
|
uchar errs = readdir(device, blocknum);
|
||||||
if (doverbose) {
|
if (doverbose) {
|
||||||
printlist();
|
printlist();
|
||||||
}
|
}
|
||||||
if (err) {
|
if (errs) {
|
||||||
puts("Error scanning directory, will not sort");
|
printf("Error scanning directory, will not sort\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (strlen(sortopts) > 0) {
|
if (strlen(sortopts) > 0) {
|
||||||
for (uchar i=0; i<strlen(sortopts); ++i) {
|
for (uchar i=0; i<strlen(sortopts); ++i) {
|
||||||
if (doverbose) {
|
if (doverbose) {
|
||||||
printf("Sorting - order '%c' ...\n",
|
printf("Sorting - order '%c' ...\n",
|
||||||
sortopts[i]);
|
sortopts[i]);
|
||||||
}
|
}
|
||||||
sortlist(sortopts[i]);
|
sortlist(sortopts[i]);
|
||||||
}
|
}
|
||||||
@ -1395,7 +1427,7 @@ void processdir(uint device, uint blocknum) {
|
|||||||
printlist();
|
printlist();
|
||||||
}
|
}
|
||||||
if (dowrite)
|
if (dowrite)
|
||||||
err = writedir(device);
|
errs = writedir(device);
|
||||||
else if (doverbose)
|
else if (doverbose)
|
||||||
puts("Not writing to disk without -w");
|
puts("Not writing to disk without -w");
|
||||||
}
|
}
|
||||||
@ -1421,10 +1453,12 @@ void checkfreeandused(void) {
|
|||||||
continue;
|
continue;
|
||||||
if (isfree(i)) {
|
if (isfree(i)) {
|
||||||
if (isused(i))
|
if (isused(i))
|
||||||
printf("Blk %u used, marked free\n", i);
|
err(NONFATAL,
|
||||||
|
"Block %u used, marked free", i);
|
||||||
} else {
|
} else {
|
||||||
if (!isused(i))
|
if (!isused(i))
|
||||||
printf("Blk %u unused, not marked free\n", i);
|
err(NONFATAL,
|
||||||
|
"Block %u unused, not marked free", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1494,6 +1528,6 @@ int main(int argc, char *argv[]) {
|
|||||||
checkfreeandused();
|
checkfreeandused();
|
||||||
free(freelist);
|
free(freelist);
|
||||||
free(usedlist);
|
free(usedlist);
|
||||||
return 0;
|
err(FINISHED, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user