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