|
|
1.1 ! root 1: /* ! 2: * readdisk ! 3: * ! 4: * Read files from Amiga disk files ! 5: * ! 6: * Copyright 1996 Bernd Schmidt ! 7: */ ! 8: ! 9: #include <sys/types.h> ! 10: #include <sys/stat.h> ! 11: #include <fcntl.h> ! 12: #include <unistd.h> ! 13: #include <errno.h> ! 14: ! 15: #include <stdio.h> ! 16: #include <stdlib.h> ! 17: #include <string.h> ! 18: ! 19: #include "amiga.h" ! 20: ! 21: unsigned char filemem[901120]; ! 22: ! 23: typedef struct afile ! 24: { ! 25: struct afile *sibling; ! 26: unsigned char *data; ! 27: ULONG size; ! 28: char name[32]; ! 29: } afile; ! 30: ! 31: typedef struct directory ! 32: { ! 33: struct directory *sibling; ! 34: struct directory *subdirs; ! 35: struct afile *files; ! 36: char name[32]; ! 37: } directory; ! 38: ! 39: static ULONG readlong (unsigned char *buffer, int pos) ! 40: { ! 41: return ((*(buffer + pos) << 24) + (*(buffer + pos + 1) << 16) ! 42: + (*(buffer + pos + 2) << 8) + *(buffer + pos + 3)); ! 43: } ! 44: ! 45: static afile *read_file (unsigned char *filebuf) ! 46: { ! 47: afile *a = (afile *)malloc(sizeof(afile)); ! 48: int sizeleft; ! 49: unsigned char *datapos; ! 50: ULONG numblocks, blockpos; ! 51: ! 52: /* BCPL strings... Yuk. */ ! 53: memset (a->name, 0, 32); ! 54: strncpy (a->name, (const char *)filebuf + 0x1B1, *(filebuf + 0x1B0)); ! 55: sizeleft = a->size = readlong (filebuf, 0x144); ! 56: a->data = (unsigned char *)malloc(a->size); ! 57: ! 58: numblocks = readlong (filebuf, 0x8); ! 59: blockpos = 0x134; ! 60: datapos = a->data; ! 61: while (numblocks) ! 62: { ! 63: unsigned char *databuf = filemem + 512*readlong (filebuf, blockpos); ! 64: int readsize = sizeleft > 488 ? 488 : sizeleft; ! 65: memcpy (datapos, databuf + 0x18, readsize); ! 66: datapos += readsize; ! 67: sizeleft -= readsize; ! 68: ! 69: blockpos -= 4; ! 70: numblocks--; ! 71: if (blockpos < 0x18 && numblocks) { ! 72: filebuf = filemem + 512*readlong (filebuf, 0x1F8); ! 73: if (!filebuf) { ! 74: fprintf(stderr, "Disk structure corrupted. Use DISKDOCTOR to correct it.\n"); ! 75: abort (); ! 76: } ! 77: } ! 78: } ! 79: return a; ! 80: } ! 81: ! 82: static directory *read_dir (unsigned char *dirbuf) ! 83: { ! 84: directory *d = (directory *)malloc(sizeof(directory)); ! 85: ULONG hashsize; ! 86: ULONG i; ! 87: ! 88: memset (d->name, 0, 32); ! 89: strncpy (d->name, (const char *)dirbuf + 0x1B1, *(dirbuf + 0x1B0)); ! 90: d->sibling = 0; ! 91: d->subdirs = 0; ! 92: d->files = 0; ! 93: hashsize = readlong (dirbuf, 0xc); ! 94: if (!hashsize) ! 95: hashsize = 72; ! 96: if (hashsize != 72) ! 97: fprintf(stderr, "Warning: Hash table with != 72 entries.\n"); ! 98: for (i = 0; i < hashsize; i++) { ! 99: ULONG subblock = readlong (dirbuf, 0x18 + 4*i); ! 100: while (subblock) { ! 101: directory *subdir; ! 102: afile *subfile; ! 103: unsigned char *subbuf = filemem + 512*subblock; ! 104: ! 105: switch (readlong (subbuf, 0x1FC)) { ! 106: case 0x00000002: ! 107: subdir = read_dir (subbuf); ! 108: subdir->sibling = d->subdirs; ! 109: d->subdirs = subdir; ! 110: break; ! 111: ! 112: case 0xFFFFFFFD: ! 113: subfile = read_file (subbuf); ! 114: subfile->sibling = d->files; ! 115: d->files = subfile; ! 116: break; ! 117: ! 118: default: ! 119: fprintf(stderr, "Disk structure corrupted. Use DISKDOCTOR to correct it.\n"); ! 120: abort (); ! 121: } ! 122: subblock = readlong (subbuf, 0x1F0); ! 123: } ! 124: } ! 125: return d; ! 126: } ! 127: ! 128: static void writedir(directory *dir) ! 129: { ! 130: directory *subdir; ! 131: afile *f; ! 132: ! 133: if (mkdir (dir->name, 0777) < 0 && errno != EEXIST) { ! 134: fprintf(stderr, "Could not create directory \"%s\". Giving up.\n", dir->name); ! 135: exit (20); ! 136: } ! 137: if (chdir (dir->name) < 0) { ! 138: fprintf(stderr, "Could not enter directory \"%s\". Giving up.\n", dir->name); ! 139: exit (20); ! 140: } ! 141: for (subdir = dir->subdirs; subdir; subdir = subdir->sibling) ! 142: writedir (subdir); ! 143: for (f = dir->files; f; f = f->sibling) { ! 144: int fd = creat (f->name, 0666); ! 145: if (fd < 0) { ! 146: fprintf(stderr, "Could not create file. Giving up.\n"); ! 147: exit (20); ! 148: } ! 149: write (fd, f->data, f->size); ! 150: close (fd); ! 151: } ! 152: chdir (".."); ! 153: } ! 154: ! 155: int main(int argc, char **argv) ! 156: { ! 157: directory *root; ! 158: FILE *inf; ! 159: if (argc < 2 || argc > 3) { ! 160: fprintf(stderr, "Usage: readdisk <file> [<destdir>]\n"); ! 161: exit (20); ! 162: } ! 163: inf = fopen(argv[1], "rb"); ! 164: if (inf == NULL) { ! 165: fprintf(stderr, "can't open file\n"); ! 166: exit (20); ! 167: } ! 168: fread(filemem, 1, 901120, inf); ! 169: ! 170: if (strncmp((const char *)filemem, "DOS\0", 4) != 0) { ! 171: fprintf(stderr, "Not a DOS disk.\n"); ! 172: exit (20); ! 173: } ! 174: root = read_dir (filemem + 880*512); ! 175: ! 176: if (argc == 3) ! 177: if (chdir (argv[2]) < 0) { ! 178: fprintf(stderr, "Couldn't change to %s. Giving up.\n", argv[2]); ! 179: exit (20); ! 180: } ! 181: writedir (root); ! 182: return 0; ! 183: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.