|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Unix file system handler for AmigaDOS
5: *
6: * (c) 1996 Ed Hanway
7: *
8: * Version 0.1: 28-Jan-1996
9: *
10: * Based on example code (c) 1988 The Software Distillery
11: * and published in Transactor for the Amiga, Volume 2, Issues 2-5.
12: * (May - August 1989)
13: *
14: * Known limitations:
15: * Does not support ACTION_INHIBIT (big deal).
16: * Does not support any 2.0+ packet types (except ACTION_SAME_LOCK)
17: * Does not actually enforce exclusive locks.
18: * Does not support removable volumes.
19: * May not return the correct error code in some cases.
20: * Does not check for sane values passed by AmigaDOS. May crash the emulation
21: * if passed garbage values.
22: *
23: * TODO someday:
24: * Support booting.
25: * Implement real locking using flock. Needs test cases.
26: */
27:
28: #include <stdio.h>
29: #include <stdlib.h>
30: #include <string.h>
31: #include <strings.h>
32: #include <assert.h>
33:
34: #ifdef __unix
35: #include <unistd.h>
36: #include <fcntl.h>
37: #include <sys/vfs.h>
38: #include <sys/types.h>
39: #include <sys/stat.h>
40: #ifndef __linux
41: #include <sys/statfs.h>
42: #endif
43: #include <dirent.h>
44: #include <utime.h>
45: #include <errno.h>
46: #endif
47:
48: #include "config.h"
49: #include "amiga.h"
50: #include "options.h"
51: #include "events.h"
52: #include "memory.h"
53: #include "custom.h"
54: #include "newcpu.h"
55: #include "xwin.h"
56: #include "autoconf.h"
57: #include "filesys.h"
58:
59: #define MAKE_CASE_INSENSITIVE
60:
61: typedef struct {
62: char *devname; /* device name, e.g. UAE0: */
63: char *volname; /* volume name, e.g. CDROM, WORK, etc. */
64: char *rootdir; /* root unix directory */
65: bool readonly; /* disallow write access? */
66: } UnitInfo;
67:
68: #define MAX_UNITS 20
69: static int num_units = 0;
70: static UnitInfo ui[MAX_UNITS];
71:
72: static ULONG devnameaddr[100];
73:
74: static ULONG doslibname, fsdevname, filesysseglist;
75:
76: /* strdup missing? */
77: static char*
78: my_strdup(const char*s)
79: {
80: char*x = (char*)malloc(strlen(s) + 1);
81: strcpy(x, s);
82: return x;
83: }
84:
85:
86: void
87: add_filesys_unit(char *volname, char *rootdir, bool readonly)
88: {
89: UnitInfo* u;
90: static char buf[80];
91:
92: if (num_units >= MAX_UNITS) {
93: fprintf(stderr, "Maximum number of unix file systems mounted.\n");
94: return;
95: }
96:
97: u = &ui[num_units];
98: sprintf(buf, "UAE%d", num_units);
99: u->devname = my_strdup(buf);
100: u->volname = my_strdup(volname);
101: u->rootdir = my_strdup(rootdir);
102: u->readonly = readonly;
103:
104: num_units++;
105: }
106:
107: #ifdef TRACING_ENABLED
108: #define TRACE(x) printf x;
109: #define DUMPLOCK(x) dumplock(x)
110: #else
111: #define TRACE(x)
112: #define DUMPLOCK(x)
113: #endif
114:
115: /* minimal AmigaDOS definitions */
116:
117: /* field offsets in DosPacket */
118: #define dp_Type (8)
119: #define dp_Res1 (12)
120: #define dp_Res2 (16)
121: #define dp_Arg1 (20)
122: #define dp_Arg2 (24)
123: #define dp_Arg3 (28)
124: #define dp_Arg4 (32)
125:
126: /* result codes */
127: #define DOS_TRUE (-1L)
128: #define DOS_FALSE (0L)
129:
130: /* packet types */
131: #define ACTION_CURRENT_VOLUME 7
132: #define ACTION_LOCATE_OBJECT 8
133: #define ACTION_RENAME_DISK 9
134: #define ACTION_FREE_LOCK 15
135: #define ACTION_DELETE_OBJECT 16
136: #define ACTION_RENAME_OBJECT 17
137: #define ACTION_COPY_DIR 19
138: #define ACTION_SET_PROTECT 21
139: #define ACTION_CREATE_DIR 22
140: #define ACTION_EXAMINE_OBJECT 23
141: #define ACTION_EXAMINE_NEXT 24
142: #define ACTION_DISK_INFO 25
143: #define ACTION_INFO 26
144: #define ACTION_FLUSH 27
145: #define ACTION_SET_COMMENT 28
146: #define ACTION_PARENT 29
147: #define ACTION_SET_DATE 34
148: #define ACTION_SAME_LOCK 40
149: #define ACTION_FIND_WRITE 1004
150: #define ACTION_FIND_INPUT 1005
151: #define ACTION_FIND_OUTPUT 1006
152: #define ACTION_END 1007
153: #define ACTION_SEEK 1008
154: #define ACTION_IS_FILESYSTEM 1027
155: #define ACTION_READ 'R'
156: #define ACTION_WRITE 'W'
157:
158: #define DISK_TYPE (0x444f5301) /* DOS\1 */
159:
160: /* errors */
161: #define ERROR_NO_FREE_STORE 103
162: #define ERROR_OBJECT_IN_USE 202
163: #define ERROR_OBJECT_EXISTS 203
164: #define ERROR_DIR_NOT_FOUND 204
165: #define ERROR_OBJECT_NOT_FOUND 205
166: #define ERROR_ACTION_NOT_KNOWN 209
167: #define ERROR_OBJECT_WRONG_TYPE 212
168: #define ERROR_DISK_WRITE_PROTECTED 214
169: #define ERROR_DIRECTORY_NOT_EMPTY 216
170: #define ERROR_DEVICE_NOT_MOUNTED 218
171: #define ERROR_SEEK_ERROR 219
172: #define ERROR_DISK_FULL 221
173: #define ERROR_WRITE_PROTECTED 223
174: #define ERROR_NO_MORE_ENTRIES 232
175: #define ERROR_NOT_IMPLEMENTED 236
176:
177: static long dos_errno(void)
178: {
179: int e = errno;
180:
181: switch(e) {
182: case ENOMEM: return ERROR_NO_FREE_STORE;
183: case EEXIST: return ERROR_OBJECT_EXISTS;
184: case EISDIR: return ERROR_OBJECT_WRONG_TYPE;
185: case ETXTBSY: return ERROR_OBJECT_IN_USE;
186: case EACCES: return ERROR_WRITE_PROTECTED;
187: case ENOENT: return ERROR_OBJECT_NOT_FOUND;
188: case ENOTDIR: return ERROR_OBJECT_WRONG_TYPE;
189: case EROFS: return ERROR_DISK_WRITE_PROTECTED;
190: case ENOSPC: return ERROR_DISK_FULL;
191: case EBUSY: return ERROR_OBJECT_IN_USE;
192: case ENOTEMPTY: return ERROR_DIRECTORY_NOT_EMPTY;
193:
194: default:
195: TRACE(("Unimplemented error %s\n", strerror(e)));
196: return ERROR_NOT_IMPLEMENTED;
197: }
198: }
199:
200: /* handler state info */
201:
202: typedef struct _unit {
203: struct _unit *next;
204:
205: /* Amiga stuff */
206: CPTR dosbase;
207: CPTR volume;
208: CPTR port; /* Our port */
209:
210: /* Native stuff */
211: long unit; /* unit number */
212: UnitInfo ui; /* unit startup info */
213: } Unit;
214:
215: typedef struct {
216: CPTR addr; /* addr of real packet */
217: long type;
218: long res1;
219: long res2;
220: long arg1;
221: long arg2;
222: long arg3;
223: long arg4;
224: } DosPacket;
225:
226: static char *
227: bstr(CPTR addr)
228: {
229: static char buf[256];
230: int n = get_byte(addr++);
231: int i;
232: for(i = 0; i < n; i++)
233: buf[i] = get_byte(addr++);
234: buf[i] = 0;
235: return buf;
236: }
237:
238: static Unit *units = NULL;
239: static int unit_num = 0;
240:
241: static Unit*
242: find_unit(CPTR port)
243: {
244: Unit* u;
245: for(u = units; u; u = u->next)
246: if(u->port == port)
247: break;
248:
249: return u;
250: }
251:
252: static CPTR DosAllocMem(ULONG len)
253: {
254: ULONG i;
255: CPTR addr;
256:
257: regs.d[0] = len + 4;
258: regs.d[1] = 1; /* MEMF_PUBLIC */
259: addr = CallLib(regs.a[6], -198); /* AllocMem */
260:
261: if(addr) {
262: put_long(addr, len);
263: addr += 4;
264:
265: /* faster to clear memory here rather than use MEMF_CLEAR */
266: for(i = 0; i < len; i += 4)
267: put_long(addr + i, 0);
268: }
269:
270: return addr;
271: }
272:
273: static void DosFreeMem(CPTR addr)
274: {
275: addr -= 4;
276: regs.d[0] = get_long(addr) + 4;
277: regs.a[1] = addr;
278: CallLib(regs.a[6], -210); /* FreeMem */
279: }
280:
281: static void
282: startup(DosPacket* packet)
283: {
284: int i, namelen;
285: char* devname = bstr(packet->arg1 << 2);
286: char* s;
287: Unit* unit;
288:
289: /* find UnitInfo with correct device name */
290: s = strchr(devname, ':');
291: if(s) *s = '\0';
292: #if 0 /* Kick 1.3 send us a bogus string. */
293: for(i = 0; i < num_units; i++) {
294: if(0 == strcmp(ui[i].devname, devname))
295: break;
296: }
297: #endif
298:
299: i = 0;
300:
301: if(i == num_units || 0 != access(ui[i].rootdir, R_OK)) {
302: fprintf(stderr, "Failed attempt to mount device %s\n", devname);
303: packet->res1 = DOS_FALSE;
304: packet->res2 = ERROR_DEVICE_NOT_MOUNTED;
305: return;
306: }
307:
308: unit = (Unit *) malloc(sizeof(Unit));
309: unit->next = units;
310: units = unit;
311:
312: unit->volume = 0;
313: unit->port = regs.a[5];
314: unit->unit = unit_num++;
315:
316: unit->ui.devname = ui[i].devname;
317: unit->ui.volname = my_strdup(ui[i].volname); /* might free later for rename */
318: unit->ui.rootdir = ui[i].rootdir;
319: unit->ui.readonly = ui[i].readonly;
320:
321: TRACE(("**** STARTUP volume %s\n", unit->ui.volname));
322:
323: /* fill in our process in the device node */
324: put_long((packet->arg3 << 2) + 8, unit->port);
325:
326: /* open dos.library */
327: regs.d[0] = 0;
328: regs.a[1] = doslibname;
329: unit->dosbase = CallLib(regs.a[6], -552); /* OpenLibrary */
330:
331: {
332: CPTR rootnode = get_long(unit->dosbase + 34);
333: CPTR dos_info = get_long(rootnode + 24) << 2;
334: /* make new volume */
335: unit->volume = DosAllocMem(80 + 1 + 44);
336: put_long(unit->volume + 4, 2); /* Type = dt_volume */
337: put_long(unit->volume + 12, 0); /* Lock */
338: put_long(unit->volume + 16, 3800); /* Creation Date */
339: put_long(unit->volume + 20, 0);
340: put_long(unit->volume + 24, 0);
341: put_long(unit->volume + 28, 0); /* lock list */
342: put_long(unit->volume + 40, (unit->volume + 44) >> 2); /* Name */
343: namelen = strlen(unit->ui.volname);
344: put_byte(unit->volume + 44, namelen);
345: for(i = 0; i < namelen; i++)
346: put_byte(unit->volume + 45 + i, unit->ui.volname[i]);
347:
348: /* link into DOS list */
349: put_long(unit->volume, get_long(dos_info + 4));
350: put_long(dos_info + 4, unit->volume >> 2);
351: }
352:
353: put_long(unit->volume + 8, unit->port);
354: put_long(unit->volume + 32, DISK_TYPE);
355:
356: packet->res1 = DOS_TRUE;
357: }
358:
359: static void
360: do_info(Unit* unit, DosPacket* packet, CPTR info)
361: {
362: struct statfs statbuf;
363: #ifdef __linux
364: if(-1 == statfs(unit->ui.rootdir, &statbuf))
365: #else
366: if(-1 == statfs(unit->ui.rootdir, &statbuf, sizeof(struct statfs), 0))
367: #endif
368: {
369: packet->res1 = DOS_FALSE;
370: packet->res2 = dos_errno();
371: }
372:
373: put_long(info, 0); /* errors */
374: put_long(info + 4, unit->unit); /* unit number */
375: put_long(info + 8, unit->ui.readonly ? 80 : 82); /* state */
376: put_long(info + 12, statbuf.f_blocks); /* numblocks */
377: #ifdef __linux
378: put_long(info + 16, statbuf.f_blocks - statbuf.f_bavail); /* inuse */
379: #else
380: put_long(info + 16, statbuf.f_blocks - statbuf.f_bfree); /* inuse */
381: #endif
382: put_long(info + 20, statbuf.f_bsize); /* bytesperblock */
383: put_long(info + 24, DISK_TYPE); /* disk type */
384: put_long(info + 28, unit->volume >> 2); /* volume node */
385: put_long(info + 32, 0); /* inuse */
386: packet->res1 = DOS_TRUE;
387: }
388:
389: static void
390: action_disk_info(Unit* unit, DosPacket* packet)
391: {
392: TRACE(("ACTION_DISK_INFO\n"));
393: do_info(unit, packet, packet->arg1 << 2);
394: }
395:
396: static void
397: action_info(Unit* unit, DosPacket* packet)
398: {
399: TRACE(("ACTION_INFO\n"));
400: do_info(unit, packet, packet->arg2 << 2);
401: }
402:
403: typedef struct {
404: char *path;
405: int fd;
406: } Key;
407:
408: static void
409: free_key(Key*k)
410: {
411: free(k->path);
412: free(k);
413: }
414:
415: static void
416: dumplock(CPTR lock)
417: {
418: if(!lock) {
419: fprintf(stderr, "LOCK: 0x0\n");
420: return;
421: }
422: fprintf(stderr,
423: "LOCK: 0x%lx { next=0x%lx, key=%s, mode=%ld, handler=0x%lx, volume=0x%lx }\n",
424: lock,
425: get_long(lock)<<2, ((Key*)get_long(lock+4))->path, get_long(lock+8),
426: get_long(lock+12), get_long(lock+16));
427: }
428:
429: static char*
430: get_path(Unit* unit, const char *base, const char *rel)
431: {
432: static char buf[1024];
433: char *s = buf;
434: char *p;
435: char *r;
436:
437: int i;
438:
439: TRACE(("get_path(%s,%s)\n", base, rel));
440:
441: /* root-relative path? */
442: for(i = 0; rel[i] && rel[i] != '/' && rel[i] != ':'; i++);
443: if(':' == rel[i]) {
444: base = unit->ui.rootdir; rel += i+1;
445: }
446:
447: while(*base) {
448: *s++ = *base++;
449: }
450: p = s; /* start of relative path */
451: r = buf + strlen(unit->ui.rootdir); /* end of fixed path */
452:
453: while(*rel) {
454: /* start with a slash? go up a level. */
455: if('/' == *rel) {
456: while(s > r && '/' != *s)
457: s--;
458: rel++;
459: } else {
460: *s++ = '/';
461: while(*rel && '/' != *rel) {
462: *s++ = *rel++;
463: }
464: if('/' == *rel)
465: rel++;
466: }
467: }
468: *s = 0;
469:
470: #ifdef MAKE_CASE_INSENSITIVE
471: TRACE(("path=\"%s\"\n", buf));
472: /* go through each section of the path and if it does not exist,
473: * scan its directory for any case insensitive matches
474: */
475: while(*p) {
476: char *p2 = strchr(p+1, '/');
477: char oldp2;
478: if(!p2) {
479: p2 = p+1;
480: while(*p2) p2++;
481: }
482: oldp2 = *p2;
483: *p2 = '\0';
484: if(0 != access(buf, F_OK|R_OK)) {
485: DIR* dir;
486: struct dirent* de;
487:
488: /* does not exist -- check dir for case insensitive match */
489: *p++ = '\0'; /* was '/' */
490: dir = opendir(buf);
491: if (dir) {
492: while((de = readdir(dir))) {
493: if(0 == strcasecmp(de->d_name, p))
494: break;
495: }
496: if(de) {
497: strcpy(p, de->d_name);
498: }
499: closedir(dir);
500: }
501: *--p = '/';
502: }
503: *p2 = oldp2;
504: p = p2;
505: }
506: #endif
507: TRACE(("path=\"%s\"\n", buf));
508:
509: return my_strdup(buf);
510: }
511:
512: static Key*
513: make_key(Unit* unit, CPTR lock, const char *name)
514: {
515: Key *k = (Key*)malloc(sizeof(Key));
516:
517: k->fd = 0;
518:
519: if(!lock) {
520: k->path = get_path(unit, unit->ui.rootdir, name);
521: } else {
522: Key*oldk = (Key*)get_long(lock + 4);
523: TRACE(("key: 0x%08lx", (ULONG)oldk));
524: TRACE((" \"%s\"\n", oldk->path));
525: k->path = get_path(unit, oldk->path, name);
526: }
527:
528: TRACE(("key=\"%s\"\n", k->path));
529: return k;
530: }
531:
532: static Key*
533: dup_key(Key*k)
534: {
535: Key *newk = (Key*)malloc(sizeof(Key));
536: newk->path = my_strdup(k->path);
537: newk->fd = 0;
538: return newk;
539: }
540:
541: static CPTR
542: make_lock(Unit* unit, Key *key, long mode)
543: {
544: /* allocate lock */
545: CPTR lock = DosAllocMem(20);
546:
547: put_long(lock + 4, (ULONG) key);
548: put_long(lock + 8, mode);
549: put_long(lock + 12, unit->port);
550: put_long(lock + 16, unit->volume >> 2);
551:
552: /* prepend to lock chain */
553: put_long(lock, get_long(unit->volume + 28));
554: put_long(unit->volume + 28, lock >> 2);
555:
556: DUMPLOCK(lock);
557: return lock;
558: }
559:
560: static void
561: free_lock(Unit* unit, CPTR lock)
562: {
563: if(!lock)
564: return;
565:
566: if(lock == get_long(unit->volume + 28) << 2) {
567: put_long(unit->volume + 28, get_long(lock));
568: } else {
569: CPTR current = get_long(unit->volume + 28);
570: CPTR next = 0;
571: while(current) {
572: next = get_long(current << 2);
573: if(lock == next << 2)
574: break;
575: current = next;
576: }
577: put_long(current << 2, get_long(lock));
578: }
579: free_key((Key*)get_long(lock + 4));
580: DosFreeMem(lock);
581: }
582:
583: static void
584: action_lock(Unit* unit, DosPacket* packet)
585: {
586: CPTR lock = packet->arg1 << 2;
587: CPTR name = packet->arg2 << 2;
588: long mode = packet->arg3;
589: int access_mode = (mode == -2) ? R_OK : R_OK|W_OK;
590: Key *k;
591:
592: TRACE(("ACTION_LOCK(0x%lx, \"%s\", %d)\n",lock, bstr(name), mode));
593: DUMPLOCK(lock);
594:
595: k = make_key(unit, lock, bstr(name));
596:
597: if(k && 0 == access(k->path, access_mode)) {
598: packet->res1 = make_lock(unit, k, mode) >> 2;
599: } else {
600: if(k)
601: free_key(k);
602: packet->res1 = 0;
603: packet->res2 = ERROR_OBJECT_NOT_FOUND;
604: }
605: }
606:
607: static void
608: action_free_lock(Unit* unit, DosPacket* packet)
609: {
610: CPTR lock = packet->arg1 << 2;
611: TRACE(("ACTION_FREE_LOCK(0x%lx)\n", lock));
612: DUMPLOCK(lock);
613:
614: free_lock(unit, lock);
615:
616: packet->res1 = DOS_TRUE;
617: }
618:
619: static void
620: action_dup_lock(Unit* unit, DosPacket* packet)
621: {
622: CPTR lock = packet->arg1 << 2;
623:
624: TRACE(("ACTION_DUP_LOCK(0x%lx)\n", lock));
625: DUMPLOCK(lock);
626:
627: if(!lock) {
628: packet->res1 = 0;
629: return;
630: }
631:
632: {
633: CPTR oldkey = get_long(lock + 4);
634: CPTR oldmode = get_long(lock + 8);
635: packet->res1 = make_lock(unit, dup_key((Key*)oldkey), oldmode) >> 2;
636: }
637: }
638:
639: /* convert time_t to/from AmigaDOS time */
640: const int secs_per_day = 24 * 60 * 60;
641: const int diff = (8 * 365 + 2) * (24 * 60 * 60);
642:
643: static void
644: get_time(time_t t, long* days, long* mins, long* ticks)
645: {
646: /* time_t is secs since 1-1-1970 */
647: /* days since 1-1-1978 */
648: /* mins since midnight */
649: /* ticks past minute @ 50Hz */
650:
651: t -= diff;
652: *days = t / secs_per_day;
653: t -= *days * secs_per_day;
654: *mins = t / 60;
655: t -= *mins * 60;
656: *ticks = t * 50;
657: }
658:
659: static time_t
660: put_time(long days, long mins, long ticks)
661: {
662: time_t t;
663: t = ticks / 50;
664: t += mins * 60;
665: t += days * secs_per_day;
666: t += diff;
667:
668: return t;
669: }
670:
671:
672: typedef struct {
673: char *path;
674: DIR* dir;
675: } ExamineKey;
676:
677: /* Since ACTION_EXAMINE_NEXT is so braindamaged, we have to keep
678: * some of these around
679: */
680:
681: #define EXKEYS 100
682: static ExamineKey examine_keys[EXKEYS];
683: static int next_exkey = 0;
684:
685: static void
686: free_exkey(ExamineKey* ek)
687: {
688: free(ek->path);
689: ek->path = 0;
690: if(ek->dir)
691: closedir(ek->dir);
692: }
693:
694: static ExamineKey*
695: new_exkey(char *path)
696: {
697: ExamineKey* ek= &examine_keys[next_exkey++];
698: if(next_exkey==EXKEYS)
699: next_exkey = 0;
700: if(ek->path) {
701: free_exkey(ek);
702: }
703: ek->path = my_strdup(path);
704: ek->dir = 0;
705: return ek;
706: }
707:
708: static void
709: get_fileinfo(DosPacket* packet, CPTR info, char *buf)
710: {
711: struct stat statbuf;
712: long days, mins, ticks;
713:
714: if(-1 == stat(buf, &statbuf)) {
715: packet->res1 = DOS_FALSE;
716: packet->res2 = dos_errno();
717: } else {
718: put_long(info + 4, S_ISDIR(statbuf.st_mode) ? 2 : -3);
719: {
720: /* file name */
721: int i = 8;
722: int n;
723: char *x = strrchr(buf,'/');
724: if(x)
725: x++;
726: else
727: x = buf;
728: TRACE(("name=\"%s\"\n", x));
729: n = strlen(x);
730: if(n > 106) n = 106;
731: put_byte(info + i++, n);
732: while(n--)
733: put_byte(info + i++, *x++);
734: while(i < 108)
735: put_byte(info + i++, 0);
736: }
737: put_long(info + 116,
738: (S_IRUSR & statbuf.st_mode ? 0 : (1<<3)) |
739: (S_IWUSR & statbuf.st_mode ? 0 : (1<<2)) |
740: (S_IXUSR & statbuf.st_mode ? 0 : (1<<1)) |
741: (S_IWUSR & statbuf.st_mode ? 0 : (1<<0)));
742: put_long(info + 120, S_ISDIR(statbuf.st_mode) ? 2 : -3);
743: put_long(info + 124, statbuf.st_size);
744: put_long(info + 128, statbuf.st_blocks);
745: get_time(statbuf.st_mtime, &days, &mins, &ticks);
746: put_long(info + 132, days);
747: put_long(info + 136, mins);
748: put_long(info + 140, ticks);
749: put_long(info + 144, 0); /* no comment */
750: packet->res1 = DOS_TRUE;
751: }
752: }
753:
754: static void
755: do_examine(DosPacket* packet, ExamineKey* ek, CPTR info)
756: {
757: static char buf[1024];
758: struct dirent* de;
759:
760: if(!ek->dir) {
761: ek->dir = opendir(ek->path);
762: }
763: if(!ek->dir) {
764: free_exkey(ek);
765: packet->res1 = DOS_FALSE;
766: packet->res2 = ERROR_NO_MORE_ENTRIES;
767: return;
768: }
769:
770: de = readdir(ek->dir);
771:
772: while(de &&
773: (0 == strcmp(".", de->d_name) ||
774: 0 == strcmp("..", de->d_name)))
775: {
776: de = readdir(ek->dir);
777: }
778:
779: if(!de) {
780: TRACE(("no more entries\n"));
781: free_exkey(ek);
782: packet->res1 = DOS_FALSE;
783: packet->res2 = ERROR_NO_MORE_ENTRIES;
784: return;
785: }
786:
787: TRACE(("entry=\"%s\"\n", de->d_name));
788:
789: sprintf(buf, "%s/%s", ek->path, de->d_name);
790:
791: get_fileinfo(packet, info, buf);
792: }
793:
794: static void
795: action_examine_object(Unit* unit, DosPacket* packet)
796: {
797: CPTR lock = packet->arg1 << 2;
798: CPTR info = packet->arg2 << 2;
799: char *path;
800: ExamineKey* ek;
801:
802: TRACE(("ACTION_EXAMINE_OBJECT(0x%lx,0x%lx)\n", lock, info));
803: DUMPLOCK(lock);
804:
805: if(!lock) {
806: path = unit->ui.rootdir;
807: } else {
808: Key*k = (Key *)get_long(lock + 4);
809: path = k->path;
810: }
811:
812: get_fileinfo(packet, info, path);
813: ek = new_exkey(path);
814: put_long(info, (ULONG)ek);
815: }
816:
817: static void
818: action_examine_next(Unit* unit, DosPacket* packet)
819: {
820: CPTR lock = packet->arg1 << 2;
821: CPTR info = packet->arg2 << 2;
822:
823: TRACE(("ACTION_EXAMINE_NEXT(0x%lx,0x%lx)\n", lock, info));
824: DUMPLOCK(lock);
825:
826: do_examine(packet, (ExamineKey*)get_long(info), info);
827: }
828:
829: static void
830: do_find(Unit* unit, DosPacket* packet, mode_t mode)
831: {
832: CPTR fh = packet->arg1 << 2;
833: CPTR lock = packet->arg2 << 2;
834: CPTR name = packet->arg3 << 2;
835: Key *k;
836: struct stat st;
837:
838: TRACE(("ACTION_FIND_*(0x%lx,0x%lx,\"%s\",%d)\n",fh,lock,bstr(name),mode));
839: DUMPLOCK(lock);
840:
841: k = make_key(unit, lock, bstr(name));
842: if(!k) {
843: packet->res1 = DOS_FALSE;
844: packet->res2 = ERROR_NO_FREE_STORE;
845: return;
846: }
847:
848: /* Fixme: may not quite be right */
849: if (0 == stat (k->path, &st)) {
850: if (S_ISDIR (st.st_mode)) {
851: packet->res1 = DOS_FALSE;
852: packet->res2 = ERROR_OBJECT_WRONG_TYPE;
853: return;
854: }
855: }
856:
857: k->fd = open(k->path, mode, 0777);
858:
859: if(k->fd < 0) {
860: packet->res1 = DOS_FALSE;
861: packet->res2 = dos_errno();
862: free_key(k);
863: return;
864: }
865: success:
866: put_long(fh+36, (ULONG)k);
867:
868: packet->res1 = DOS_TRUE;
869: }
870:
871: static void
872: action_find_input(Unit* unit, DosPacket* packet)
873: {
874: do_find(unit, packet, O_RDONLY);
875: }
876:
877: static void
878: action_find_output(Unit* unit, DosPacket* packet)
879: {
880: if(unit->ui.readonly) {
881: packet->res1 = DOS_FALSE;
882: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
883: return;
884: }
885: do_find(unit, packet, O_WRONLY|O_CREAT|O_TRUNC);
886: }
887:
888: static void
889: action_find_write(Unit* unit, DosPacket* packet)
890: {
891: if(unit->ui.readonly) {
892: packet->res1 = DOS_FALSE;
893: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
894: return;
895: }
896: do_find(unit, packet, O_RDWR);
897: }
898:
899: static void
900: action_end(Unit* unit, DosPacket* packet)
901: {
902: Key*k;
903: TRACE(("ACTION_END(0x%lx)\n", packet->arg1));
904:
905: k = (Key*)(packet->arg1);
906: close(k->fd);
907: free_key(k);
908: packet->res1 = DOS_TRUE;
909: }
910:
911: static void
912: action_read(Unit* unit, DosPacket* packet)
913: {
914: Key*k = (Key*)(packet->arg1);
915: CPTR addr = packet->arg2;
916: long size = packet->arg3;
917: int actual;
918: char *buf;
919:
920: TRACE(("ACTION_READ(%s,0x%lx,%ld)\n",k->path,addr,size));
921:
922: /* ugh this is inefficient but easy */
923: buf = (char *)malloc(size);
924: if(!buf) {
925: packet->res1 = -1;
926: packet->res2 = ERROR_NO_FREE_STORE;
927: return;
928: }
929:
930: actual = read(k->fd, buf, size);
931:
932: packet->res1 = actual;
933:
934: if(actual > 0) {
935: int i;
936: unsigned char *bp = (unsigned char *)buf;
937: UWORD *realpt;
938: if (addr & 1) { /* Eeek! */
939: actual--;
940: put_byte(addr, *bp++);
941: addr++;
942: }
943: if (valid_address (addr, actual)) {
944: realpt = get_real_address (addr);
945: for (i = 0; i < (actual & ~1); i+=2) {
946: UWORD data = ((UWORD)(*bp++) << 8);
947: data |= *bp++;
948: *realpt++ = data;
949: }
950: if (actual & 1)
951: put_byte (addr + actual - 1, *bp);
952: } else {
953: /* fprintf (stderr, "unixfs warning: Bad pointer passed for read\n");*/
954: for(i = 0; i < actual; i++)
955: put_byte(addr + i, buf[i]);
956: }
957: } else {
958: packet->res2 = dos_errno();
959: }
960: free(buf);
961: }
962:
963: static void
964: action_write(Unit* unit, DosPacket* packet)
965: {
966: Key*k = (Key*)(packet->arg1);
967: CPTR addr = packet->arg2;
968: long size = packet->arg3;
969: char *buf;
970: int i;
971:
972: TRACE(("ACTION_WRITE(%s,0x%lx,%ld)\n",k->path,addr,size));
973:
974: if(unit->ui.readonly) {
975: packet->res1 = DOS_FALSE;
976: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
977: return;
978: }
979:
980: /* ugh this is inefficient but easy */
981: buf = (char *)malloc(size);
982: if(!buf) {
983: packet->res1 = -1;
984: packet->res2 = ERROR_NO_FREE_STORE;
985: return;
986: }
987:
988: for(i = 0; i < size; i++)
989: buf[i] = get_byte(addr + i);
990:
991: packet->res1 = write(k->fd, buf, size);
992: if(packet->res1 != size)
993: packet->res2 = dos_errno();
994:
995: free(buf);
996: }
997:
998: static void
999: action_seek(Unit* unit, DosPacket* packet)
1000: {
1001: Key* k = (Key*) (packet->arg1);
1002: long pos = packet->arg2;
1003: long mode = packet->arg3;
1004: off_t res;
1005: long old;
1006: int whence = SEEK_CUR;
1007: if(mode > 0) whence = SEEK_END;
1008: if(mode < 0) whence = SEEK_SET;
1009:
1010: TRACE(("ACTION_SEEK(%s,%d,%d)\n",k->path,pos,mode));
1011:
1012: old = lseek(k->fd, 0, SEEK_CUR);
1013: res = lseek(k->fd, pos, whence);
1014:
1015: if(-1 == res)
1016: packet->res1 = res;
1017: else
1018: packet->res1 = old;
1019: }
1020:
1021: static void
1022: action_set_protect(Unit* unit, DosPacket* packet)
1023: {
1024: CPTR lock = packet->arg2 << 2;
1025: CPTR name = packet->arg3 << 2;
1026: ULONG mask = packet->arg4;
1027: struct stat statbuf;
1028: mode_t mode;
1029: Key *k;
1030:
1031: TRACE(("ACTION_SET_PROTECT(0x%lx,\"%s\",0x%lx)\n",lock,bstr(name),mask));
1032:
1033: if(unit->ui.readonly) {
1034: packet->res1 = DOS_FALSE;
1035: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1036: return;
1037: }
1038:
1039: k = make_key(unit, lock, bstr(name));
1040: if(!k) {
1041: packet->res1 = DOS_FALSE;
1042: packet->res2 = ERROR_NO_FREE_STORE;
1043: return;
1044: }
1045:
1046: if(-1 == stat(k->path, &statbuf)) {
1047: free_key(k);
1048: packet->res1 = DOS_FALSE;
1049: packet->res2 = ERROR_OBJECT_NOT_FOUND;
1050: return;
1051: }
1052:
1053: mode = statbuf.st_mode;
1054:
1055: if(mask & (1 << 3))
1056: mode &= ~S_IRUSR;
1057: else
1058: mode |= S_IRUSR;
1059:
1060: if(mask & (1 << 2) || mask & (1 << 0))
1061: mode &= ~S_IWUSR;
1062: else
1063: mode |= S_IWUSR;
1064:
1065: if(mask & (1 << 1))
1066: mode &= ~S_IXUSR;
1067: else
1068: mode |= S_IXUSR;
1069:
1070: if(-1 == chmod(k->path, mode)) {
1071: packet->res1 = DOS_FALSE;
1072: packet->res2 = dos_errno();
1073: } else {
1074: packet->res1 = DOS_TRUE;
1075: }
1076: free_key(k);
1077: }
1078:
1079: static void
1080: action_same_lock(Unit* unit, DosPacket* packet)
1081: {
1082: CPTR lock1 = packet->arg1 << 2;
1083: CPTR lock2 = packet->arg2 << 2;
1084:
1085: TRACE(("ACTION_SAME_LOCK(0x%lx,0x%lx)\n",lock1,lock2));
1086: DUMPLOCK(lock1); DUMPLOCK(lock2);
1087:
1088: if(!lock1 || !lock2) {
1089: packet->res1 = (lock1 == lock2) ? DOS_TRUE : DOS_FALSE;
1090: } else {
1091: Key* key1 = (Key*) get_long(lock1 + 4);
1092: Key* key2 = (Key*) get_long(lock2 + 4);
1093: packet->res1 = (0 == strcmp(key1->path, key2->path)) ? DOS_TRUE : DOS_FALSE;
1094: }
1095: }
1096:
1097: static void
1098: action_parent(Unit* unit, DosPacket* packet)
1099: {
1100: CPTR lock = packet->arg1 << 2;
1101: Key*k;
1102:
1103: TRACE(("ACTION_PARENT(0x%lx)\n",lock));
1104:
1105: if(!lock) {
1106: packet->res1 = 0;
1107: packet->res2 = 0;
1108: return;
1109: }
1110:
1111: k = dup_key((Key*) get_long(lock + 4));
1112: if(0 == strcmp(k->path, unit->ui.rootdir)) {
1113: free_key(k);
1114: packet->res1 = 0;
1115: packet->res2 = 0;
1116: return;
1117: }
1118: {
1119: char *x = strrchr(k->path,'/');
1120: if(!x) {
1121: free_key(k);
1122: packet->res1 = 0;
1123: packet->res2 = 0;
1124: return;
1125: } else {
1126: *x = '\0';
1127: }
1128: }
1129: packet->res1 = make_lock(unit, k, -2) >> 2;
1130: }
1131:
1132: static void
1133: action_create_dir(Unit* unit, DosPacket* packet)
1134: {
1135: CPTR lock = packet->arg1 << 2;
1136: CPTR name = packet->arg2 << 2;
1137: Key* k;
1138:
1139: TRACE(("ACTION_CREATE_DIR(0x%lx,\"%s\")\n",lock,bstr(name)));
1140:
1141: if(unit->ui.readonly) {
1142: packet->res1 = DOS_FALSE;
1143: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1144: return;
1145: }
1146:
1147: k = make_key(unit, lock, bstr(name));
1148:
1149: if(!k) {
1150: packet->res1 = DOS_FALSE;
1151: packet->res2 = ERROR_NO_FREE_STORE;
1152: return;
1153: }
1154: if(-1 == mkdir(k->path, 0777)) {
1155: packet->res1 = DOS_FALSE;
1156: packet->res2 = dos_errno();
1157: free_key(k);
1158: return;
1159: }
1160: packet->res1 = make_lock(unit, k, -2) >> 2;
1161: }
1162:
1163: static void
1164: action_delete_object(Unit* unit, DosPacket* packet)
1165: {
1166: CPTR lock = packet->arg1 << 2;
1167: CPTR name = packet->arg2 << 2;
1168: Key* k;
1169: struct stat statbuf;
1170:
1171: TRACE(("ACTION_DELETE_OBJECT(0x%lx,\"%s\")\n",lock,bstr(name)));
1172:
1173: if(unit->ui.readonly) {
1174: packet->res1 = DOS_FALSE;
1175: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1176: return;
1177: }
1178:
1179: k = make_key(unit, lock, bstr(name));
1180:
1181: if(!k) {
1182: packet->res1 = DOS_FALSE;
1183: packet->res2 = ERROR_NO_FREE_STORE;
1184: return;
1185: }
1186: if(-1 == stat(k->path, &statbuf)) {
1187: packet->res1 = DOS_FALSE;
1188: packet->res2 = dos_errno();
1189: free_key(k);
1190: return;
1191: }
1192: if(S_ISDIR(statbuf.st_mode)) {
1193: if(-1 == rmdir(k->path)) {
1194: packet->res1 = DOS_FALSE;
1195: packet->res2 = dos_errno();
1196: free_key(k);
1197: return;
1198: }
1199: } else {
1200: if(-1 == unlink(k->path)) {
1201: packet->res1 = DOS_FALSE;
1202: packet->res2 = dos_errno();
1203: free_key(k);
1204: return;
1205: }
1206: }
1207: free_key(k);
1208: packet->res1 = DOS_TRUE;
1209: }
1210:
1211: static void
1212: action_set_date(Unit* unit, DosPacket* packet)
1213: {
1214: CPTR lock = packet->arg2 << 2;
1215: CPTR name = packet->arg3 << 2;
1216: CPTR date = packet->arg4;
1217: Key* k;
1218: struct utimbuf ut;
1219:
1220: TRACE(("ACTION_SET_DATE(0x%lx,\"%s\")\n",lock,bstr(name)));
1221:
1222: if(unit->ui.readonly) {
1223: packet->res1 = DOS_FALSE;
1224: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1225: return;
1226: }
1227:
1228: ut.actime = ut.modtime = put_time(get_long(date),get_long(date+4),get_long(date+8));
1229: k = make_key(unit, lock, bstr(name));
1230:
1231: if(!k) {
1232: packet->res1 = DOS_FALSE;
1233: packet->res2 = ERROR_NO_FREE_STORE;
1234: return;
1235: }
1236: if(-1 == utime(k->path, &ut)) {
1237: packet->res1 = DOS_FALSE;
1238: packet->res2 = dos_errno();
1239: free_key(k);
1240: return;
1241: }
1242: free_key(k);
1243: packet->res1 = DOS_TRUE;
1244: }
1245:
1246: static void
1247: action_rename_object(Unit* unit, DosPacket* packet)
1248: {
1249: CPTR lock1 = packet->arg1 << 2;
1250: CPTR name1 = packet->arg2 << 2;
1251: Key* k1;
1252: CPTR lock2 = packet->arg3 << 2;
1253: CPTR name2 = packet->arg4 << 2;
1254: Key* k2;
1255:
1256: TRACE(("ACTION_RENAME_OBJECT(0x%lx,\"%s\",",lock1,bstr(name1)));
1257: TRACE(("0x%lx,\"%s\")\n",lock2,bstr(name2)));
1258:
1259: if(unit->ui.readonly) {
1260: packet->res1 = DOS_FALSE;
1261: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1262: return;
1263: }
1264:
1265: k1 = make_key(unit, lock1, bstr(name1));
1266: if(!k1) {
1267: packet->res1 = DOS_FALSE;
1268: packet->res2 = ERROR_NO_FREE_STORE;
1269: return;
1270: }
1271: k2 = make_key(unit, lock2, bstr(name2));
1272: if(!k2) {
1273: free_key(k1);
1274: packet->res1 = DOS_FALSE;
1275: packet->res2 = ERROR_NO_FREE_STORE;
1276: return;
1277: }
1278:
1279: if(-1 == rename(k1->path, k2->path)) {
1280: packet->res1 = DOS_FALSE;
1281: packet->res2 = dos_errno();
1282: free_key(k1);
1283: free_key(k2);
1284: return;
1285: }
1286: free_key(k1);
1287: free_key(k2);
1288: packet->res1 = DOS_TRUE;
1289: }
1290:
1291: static void
1292: action_current_volume(Unit* unit, DosPacket* packet)
1293: {
1294: packet->res1 = unit->volume >> 2;
1295: }
1296:
1297: static void
1298: action_rename_disk(Unit* unit, DosPacket* packet)
1299: {
1300: CPTR name = packet->arg1 << 2;
1301: int i;
1302: int namelen;
1303:
1304: TRACE(("ACTION_RENAME_DISK(\"%s\")\n", bstr(name)));
1305:
1306: if(unit->ui.readonly) {
1307: packet->res1 = DOS_FALSE;
1308: packet->res2 = ERROR_DISK_WRITE_PROTECTED;
1309: return;
1310: }
1311:
1312: /* get volume name */
1313: namelen = get_byte(name++);
1314: free(unit->ui.volname);
1315: unit->ui.volname = (char *) malloc(namelen + 1);
1316: for(i = 0; i < namelen; i++)
1317: unit->ui.volname[i] = get_byte(name++);
1318: unit->ui.volname[i] = 0;
1319:
1320: put_byte(unit->volume + 44, namelen);
1321: for(i = 0; i < namelen; i++)
1322: put_byte(unit->volume + 45 + i, unit->ui.volname[i]);
1323:
1324: packet->res1 = DOS_TRUE;
1325: }
1326:
1327: static void
1328: action_is_filesystem(Unit* unit, DosPacket* packet)
1329: {
1330: packet->res1 = DOS_TRUE;
1331: }
1332:
1333: static void
1334: action_flush(Unit* unit, DosPacket* packet)
1335: {
1336: /* sync(); */ /* pretty drastic, eh */
1337: packet->res1 = DOS_TRUE;
1338: }
1339:
1340: static ULONG
1341: filesys_handler(void)
1342: {
1343: DosPacket packet;
1344: Unit *unit = find_unit(regs.a[5]);
1345:
1346: /* got DosPacket in A4 */
1347: packet.addr = regs.a[4];
1348: packet.type = get_long(packet.addr + dp_Type);
1349: packet.res1 = get_long(packet.addr + dp_Res1);
1350: packet.res2 = get_long(packet.addr + dp_Res2);
1351: packet.arg1 = get_long(packet.addr + dp_Arg1);
1352: packet.arg2 = get_long(packet.addr + dp_Arg2);
1353: packet.arg3 = get_long(packet.addr + dp_Arg3);
1354: packet.arg4 = get_long(packet.addr + dp_Arg4);
1355:
1356: if(!unit) {
1357: startup(&packet);
1358: put_long(packet.addr + dp_Res1, packet.res1);
1359: put_long(packet.addr + dp_Res2, packet.res2);
1360: return 0;
1361: }
1362:
1363: if(!unit->volume) {
1364: printf("no volume\n");
1365: return 0;
1366: }
1367:
1368: switch(packet.type) {
1369: case ACTION_LOCATE_OBJECT:
1370: action_lock(unit, &packet);
1371: break;
1372:
1373: case ACTION_FREE_LOCK:
1374: action_free_lock(unit, &packet);
1375: break;
1376:
1377: case ACTION_COPY_DIR:
1378: action_dup_lock(unit, &packet);
1379: break;
1380:
1381: case ACTION_DISK_INFO:
1382: action_disk_info(unit, &packet);
1383: break;
1384:
1385: case ACTION_INFO:
1386: action_info(unit, &packet);
1387: break;
1388:
1389: case ACTION_EXAMINE_OBJECT:
1390: action_examine_object(unit, &packet);
1391: break;
1392:
1393: case ACTION_EXAMINE_NEXT:
1394: action_examine_next(unit, &packet);
1395: break;
1396:
1397: case ACTION_FIND_INPUT:
1398: action_find_input(unit, &packet);
1399: break;
1400:
1401: case ACTION_FIND_WRITE:
1402: action_find_write(unit, &packet);
1403: break;
1404:
1405: case ACTION_FIND_OUTPUT:
1406: action_find_output(unit, &packet);
1407: break;
1408:
1409: case ACTION_END:
1410: action_end(unit, &packet);
1411: break;
1412:
1413: case ACTION_READ:
1414: action_read(unit, &packet);
1415: break;
1416:
1417: case ACTION_WRITE:
1418: action_write(unit, &packet);
1419: break;
1420:
1421: case ACTION_SEEK:
1422: action_seek(unit, &packet);
1423: break;
1424:
1425: case ACTION_SET_PROTECT:
1426: action_set_protect(unit, &packet);
1427: break;
1428:
1429: case ACTION_SAME_LOCK:
1430: action_same_lock(unit, &packet);
1431: break;
1432:
1433: case ACTION_PARENT:
1434: action_parent(unit, &packet);
1435: break;
1436:
1437: case ACTION_CREATE_DIR:
1438: action_create_dir(unit, &packet);
1439: break;
1440:
1441: case ACTION_DELETE_OBJECT:
1442: action_delete_object(unit, &packet);
1443: break;
1444:
1445: case ACTION_RENAME_OBJECT:
1446: action_rename_object(unit, &packet);
1447: break;
1448:
1449: case ACTION_SET_DATE:
1450: action_set_date(unit, &packet);
1451: break;
1452:
1453: case ACTION_CURRENT_VOLUME:
1454: action_current_volume(unit, &packet);
1455: break;
1456:
1457: case ACTION_RENAME_DISK:
1458: action_rename_disk(unit, &packet);
1459: break;
1460:
1461: case ACTION_IS_FILESYSTEM:
1462: action_is_filesystem(unit, &packet);
1463: break;
1464:
1465: case ACTION_FLUSH:
1466: action_flush(unit, &packet);
1467: break;
1468:
1469: default:
1470: TRACE(("*** UNSUPPORTED PACKET %ld\n", packet.type));
1471: packet.res1 = DOS_FALSE;
1472: packet.res2 = ERROR_ACTION_NOT_KNOWN;
1473: break;
1474: }
1475:
1476: put_long(packet.addr + dp_Res1, packet.res1);
1477: put_long(packet.addr + dp_Res2, packet.res2);
1478: TRACE(("reply: %8lx, %ld\n", packet.res1, packet.res2));
1479:
1480: return 0;
1481: }
1482:
1483: static ULONG
1484: filesys_init(void)
1485: {
1486: ULONG tmp1, tmp2;
1487: bool have36 = false;
1488: int i;
1489:
1490: regs.d[0] = 88; regs.d[1] = 1; /* MEMF_PUBLIC */
1491: tmp1 = CallLib (regs.a[6], -198); /* AllocMem() */
1492: if (tmp1 == 0) {
1493: fprintf(stderr, "Not enough memory for filesystem!\n");
1494: return 0;
1495: }
1496:
1497: /* Open expansion.lib */
1498: regs.d[0] = 36; /* Let's try this... */
1499: regs.a[1] = explibname;
1500: regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
1501: if (regs.a[4])
1502: have36 = true;
1503: else {
1504: regs.d[0] = 0;
1505: regs.a[1] = explibname;
1506: regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
1507: }
1508: put_long (tmp1+4, fsdevname);
1509: put_long (tmp1+12, 0); /* Device flags */
1510: put_long (tmp1+16, 16); /* Env. size */
1511: put_long (tmp1+20, 128); /* 512 bytes/block */
1512: put_long (tmp1+24, 0); /* unused */
1513: put_long (tmp1+28, 1); /* heads */
1514: put_long (tmp1+32, 1); /* unused */
1515: put_long (tmp1+36, 32); /* secs per track */
1516: put_long (tmp1+40, 1); /* reserved blocks */
1517: put_long (tmp1+44, 0); /* unused */
1518: put_long (tmp1+48, 0); /* interleave */
1519: put_long (tmp1+52, 0); /* lowCyl */
1520: put_long (tmp1+56, 511); /* upperCyl */
1521: put_long (tmp1+60, 0); /* Number of buffers */
1522: put_long (tmp1+64, 0); /* Buffer mem type */
1523: put_long (tmp1+68, 0x7FFFFFFF); /* largest transfer */
1524: put_long (tmp1+72, ~1); /* addMask (?) */
1525: put_long (tmp1+76, (ULONG)-1); /* bootPri */
1526: if (have36)
1527: put_long (tmp1+80, 0x444f5301); /* DOS\1 */
1528: else
1529: put_long (tmp1+80, 0x444f5300); /* DOS\0 */
1530:
1531: put_long (tmp1+84, 0); /* pad */
1532:
1533: /* re-use the same parameter packet to make each
1534: * dos node, which will then get tweaked
1535: */
1536: for(i = 0; i < num_units; i++) {
1537: put_long (tmp1, devnameaddr[i]);
1538: put_long (tmp1+8, i); /* Unit no. (not really necessary) */
1539: regs.a[0] = tmp1;
1540: tmp2 = CallLib (regs.a[4], -144); /* MakeDosNode() */
1541: put_long(tmp2+8, 0x0); /* dn_Task */
1542: put_long(tmp2+16, 0x0); /* dn_Handler */
1543: put_long(tmp2+20, 4000); /* dn_StackSize */
1544: put_long(tmp2+32, filesysseglist >> 2); /* dn_SegList */
1545: put_long(tmp2+36, (ULONG)-1); /* dn_GlobalVec */
1546:
1547: regs.a[0] = tmp2;
1548: regs.d[0] = (ULONG)-1;
1549: regs.a[1] = 0;
1550: regs.d[1] = 0;
1551: CallLib (regs.a[4], -150); /* AddDosNode() */
1552: }
1553:
1554: regs.a[1] = tmp1;
1555: regs.d[0] = 88;
1556: CallLib (regs.a[6], -210); /* FreeMem() */
1557:
1558: regs.a[1] = regs.a[4];
1559: CallLib (regs.a[6], -414); /* CloseLibrary() */
1560:
1561: return 0;
1562: }
1563:
1564: void
1565: filesys_install(void)
1566: {
1567: ULONG begin, end, resname, resid;
1568: int i;
1569:
1570: if(0 == num_units)
1571: return;
1572:
1573: resname = ds("UAEunixfs.resource");
1574: resid = ds("UAE unixfs 0.1");
1575:
1576: doslibname = ds("dos.library");
1577: fsdevname = ds("unixfs.device"); /* does not really exist */
1578:
1579: for(i = 0; i < num_units; i++) {
1580: devnameaddr[i] = ds(ui[i].devname);
1581: }
1582:
1583: begin = here();
1584: dw(0x4AFC); /* RTC_MATCHWORD */
1585: dl(begin); /* our start address */
1586: dl(0); /* Continue scan here */
1587: dw(0x0101); /* RTF_COLDSTART; Version 1 */
1588: dw(0x0805); /* NT_RESOURCE; pri 5 */
1589: dl(resname); /* name */
1590: dl(resid); /* ID */
1591: dl(here() + 4); /* Init area: directly after this */
1592:
1593: calltrap(deftrap(filesys_init)); dw(RTS);
1594:
1595: /* align */
1596: align(4);
1597: /* Fake seglist */
1598: dl(16);
1599: filesysseglist = here();
1600: dl(0); /* NextSeg */
1601:
1602: /* start of code */
1603:
1604: /* I don't trust calling functions that Wait() directly,
1605: * so here's a little bit of 68000 code to receive and send our
1606: * DosPackets
1607: */
1608: dw(0x2c79); dl(4); /* move.l $4,a6 */
1609: dw(0x2279); dl(0); /* move.l 0,a1 */
1610: dw(0x4eae); dw(0xfeda); /* jsr FindTask(a6) */
1611: dw(0x2040); /* move.l d0,a0 */
1612: dw(0x4be8); dw(0x005c); /* lea.l pr_MsgPort(a0),a5 */
1613: /* loop: */
1614: dw(0x204d); /* move.l a5,a0 */
1615: dw(0x4eae); dw(0xfe80); /* jsr WaitPort(a6) */
1616: dw(0x204d); /* move.l a5,a0 */
1617: dw(0x4eae); dw(0xfe8c); /* jsr GetMsg(a6) */
1618: dw(0x2840); /* move.l d0,a4 */
1619: dw(0x286c); dw(10); /* move.l LN_NAME(a4),a4 */
1620: calltrap(deftrap(filesys_handler));
1621: dw(0x226c); dw(0); /* move.l dp_Link(a4),a1 */
1622: dw(0x206c); dw(4); /* move.l dp_Port(a4),a0 */
1623: dw(0x294d); dw(4); /* move.l a5,dp_Port(a4) */
1624: dw(0x4eae); dw(0xfe92); /* jsr PutMsg(a6) */
1625: dw(0x60d6); /* bra.s loop */
1626:
1627: end = here();
1628: org(begin + 6);
1629: dl(end);
1630:
1631: org(end);
1632: }
1633:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.