|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Unix file system handler for AmigaDOS
5: *
1.1.1.3 root 6: * Copyright 1996 Ed Hanway
7: * Copyright 1996, 1997 Bernd Schmidt
1.1 root 8: *
1.1.1.3 root 9: * Version 0.4: 970308
1.1 root 10: *
11: * Based on example code (c) 1988 The Software Distillery
12: * and published in Transactor for the Amiga, Volume 2, Issues 2-5.
13: * (May - August 1989)
14: *
15: * Known limitations:
16: * Does not support ACTION_INHIBIT (big deal).
1.1.1.6 root 17: * Does not support several 2.0+ packet types.
1.1 root 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.
1.1.1.3 root 22: * Could do tighter checks on malloc return values.
23: * Will probably fail spectacularly in some cases if the filesystem is
24: * modified at the same time by another process while UAE is running.
1.1 root 25: */
26:
27: #include "sysconfig.h"
28: #include "sysdeps.h"
29:
30: #include "config.h"
1.1.1.13 root 31: #include "threaddep/thread.h"
1.1 root 32: #include "options.h"
1.1.1.3 root 33: #include "uae.h"
1.1 root 34: #include "memory.h"
35: #include "custom.h"
1.1.1.13 root 36: #include "events.h"
1.1 root 37: #include "newcpu.h"
1.1.1.3 root 38: #include "filesys.h"
1.1 root 39: #include "autoconf.h"
40: #include "compiler.h"
1.1.1.4 root 41: #include "fsusage.h"
1.1.1.7 root 42: #include "native2amiga.h"
43: #include "scsidev.h"
44: #include "fsdb.h"
1.1 root 45:
1.1.1.3 root 46: /* #define TRACING_ENABLED */
47: #ifdef TRACING_ENABLED
1.1.1.4 root 48: #define TRACE(x) do { write_log x; } while(0)
1.1.1.3 root 49: #define DUMPLOCK(u,x) dumplock(u,x)
50: #else
51: #define TRACE(x)
52: #define DUMPLOCK(u,x)
53: #endif
54:
55: static long dos_errno(void)
1.1 root 56: {
1.1.1.3 root 57: int e = errno;
1.1 root 58:
1.1.1.4 root 59: switch (e) {
1.1.1.3 root 60: case ENOMEM: return ERROR_NO_FREE_STORE;
61: case EEXIST: return ERROR_OBJECT_EXISTS;
62: case EACCES: return ERROR_WRITE_PROTECTED;
1.1.1.11 root 63: case ENOENT: return ERROR_OBJECT_NOT_AROUND;
1.1.1.3 root 64: case ENOTDIR: return ERROR_OBJECT_WRONG_TYPE;
1.1.1.6 root 65: case ENOSPC: return ERROR_DISK_IS_FULL;
1.1.1.3 root 66: case EBUSY: return ERROR_OBJECT_IN_USE;
67: case EISDIR: return ERROR_OBJECT_WRONG_TYPE;
68: #if defined(ETXTBSY)
69: case ETXTBSY: return ERROR_OBJECT_IN_USE;
70: #endif
71: #if defined(EROFS)
72: case EROFS: return ERROR_DISK_WRITE_PROTECTED;
73: #endif
74: #if defined(ENOTEMPTY)
75: #if ENOTEMPTY != EEXIST
76: case ENOTEMPTY: return ERROR_DIRECTORY_NOT_EMPTY;
77: #endif
78: #endif
79:
80: default:
1.1.1.4 root 81: TRACE(("Unimplemented error %s\n", strerror(e)));
1.1.1.3 root 82: return ERROR_NOT_IMPLEMENTED;
83: }
1.1 root 84: }
85:
1.1.1.3 root 86: /*
87: * This _should_ be no issue for us, but let's rather use a guaranteed
88: * thread safe function if we have one.
1.1.1.4 root 89: * This used to be broken in glibc versions <= 2.0.1 (I think). I hope
90: * no one is using this these days.
91: * Michael Krause says it's also broken in libc5. ARRRGHHHHHH!!!!
1.1.1.3 root 92: */
93: #if 0 && defined HAVE_READDIR_R
94:
95: static struct dirent *my_readdir (DIR *dirstream, struct dirent *space)
96: {
97: struct dirent *loc;
98: if (readdir_r (dirstream, space, &loc) == 0) {
99: /* Success */
100: return loc;
101: }
102: return 0;
103: }
104:
105: #else
106: #define my_readdir(dirstream, space) readdir(dirstream)
107: #endif
108:
1.1.1.4 root 109: uaecptr filesys_initcode;
110: static uae_u32 fsdevname, filesys_configdev;
111:
1.1.1.3 root 112: #define FS_STARTUP 0
113: #define FS_GO_DOWN 1
114:
1.1 root 115: typedef struct {
116: char *devname; /* device name, e.g. UAE0: */
1.1.1.3 root 117: uaecptr devname_amiga;
118: uaecptr startup;
1.1 root 119: char *volname; /* volume name, e.g. CDROM, WORK, etc. */
120: char *rootdir; /* root unix directory */
121: int readonly; /* disallow write access? */
122: int devno;
1.1.1.3 root 123:
124: struct hardfiledata hf;
125:
126: /* Threading stuff */
127: smp_comm_pipe *unit_pipe, *back_pipe;
1.1.1.13 root 128: uae_thread_id tid;
1.1.1.3 root 129: struct _unit *volatile self;
1.1.1.4 root 130: /* Reset handling */
131: uae_sem_t reset_sync_sem;
132: int reset_state;
1.1 root 133: } UnitInfo;
134:
135: #define MAX_UNITS 20
136:
1.1.1.4 root 137: struct uaedev_mount_info {
138: int num_units;
139: UnitInfo ui[MAX_UNITS];
140: };
141:
142: static struct uaedev_mount_info *current_mountinfo;
143:
144: int nr_units (struct uaedev_mount_info *mountinfo)
145: {
146: return mountinfo->num_units;
147: }
148:
149: int is_hardfile (struct uaedev_mount_info *mountinfo, int unit_no)
150: {
151: return mountinfo->ui[unit_no].volname == 0;
152: }
153:
1.1.1.6 root 154: static void close_filesys_unit (UnitInfo *uip)
1.1.1.4 root 155: {
156: if (uip->hf.fd != 0)
157: fclose (uip->hf.fd);
158: if (uip->volname != 0)
159: free (uip->volname);
160: if (uip->devname != 0)
161: free (uip->devname);
162: if (uip->rootdir != 0)
163: free (uip->rootdir);
164: if (uip->unit_pipe)
165: free (uip->unit_pipe);
166: if (uip->back_pipe)
167: free (uip->back_pipe);
168:
169: uip->unit_pipe = 0;
170: uip->back_pipe = 0;
171:
172: uip->hf.fd = 0;
173: uip->volname = 0;
174: uip->devname = 0;
175: uip->rootdir = 0;
176: }
177:
178: char *get_filesys_unit (struct uaedev_mount_info *mountinfo, int nr,
179: char **volname, char **rootdir, int *readonly,
180: int *secspertrack, int *surfaces, int *reserved,
1.1.1.6 root 181: int *cylinders, int *size, int *blocksize)
1.1.1.4 root 182: {
183: UnitInfo *uip = mountinfo->ui + nr;
184:
185: if (nr >= mountinfo->num_units)
186: return "No slot allocated for this unit";
187:
188: *volname = uip->volname ? my_strdup (uip->volname) : 0;
189: *rootdir = uip->rootdir ? my_strdup (uip->rootdir) : 0;
190: *readonly = uip->readonly;
191: *secspertrack = uip->hf.secspertrack;
192: *surfaces = uip->hf.surfaces;
193: *reserved = uip->hf.reservedblocks;
194: *size = uip->hf.size;
195: *cylinders = uip->hf.nrcyls;
1.1.1.6 root 196: *blocksize = uip->hf.blocksize;
1.1.1.4 root 197: return 0;
198: }
199:
1.1.1.6 root 200: static char *set_filesys_unit_1 (struct uaedev_mount_info *mountinfo, int nr,
201: char *volname, char *rootdir, int readonly,
202: int secspertrack, int surfaces, int reserved,
203: int blocksize)
1.1 root 204: {
1.1.1.6 root 205: UnitInfo *ui = mountinfo->ui + nr;
1.1.1.4 root 206:
207: if (nr >= mountinfo->num_units)
208: return "No slot allocated for this unit";
1.1 root 209:
1.1.1.6 root 210: ui->hf.fd = 0;
211: ui->devname = 0;
212: ui->volname = 0;
213: ui->rootdir = 0;
214: ui->unit_pipe = 0;
215: ui->back_pipe = 0;
1.1.1.5 root 216:
1.1.1.3 root 217: if (volname != 0) {
1.1.1.6 root 218: ui->volname = my_strdup (volname);
219: ui->hf.fd = 0;
1.1.1.3 root 220: } else {
1.1.1.6 root 221: ui->volname = 0;
222: ui->hf.fd = fopen (rootdir, "r+b");
223: if (ui->hf.fd == 0) {
1.1.1.3 root 224: readonly = 1;
1.1.1.6 root 225: ui->hf.fd = fopen (rootdir, "rb");
1.1.1.3 root 226: }
1.1.1.6 root 227: if (ui->hf.fd == 0)
1.1.1.3 root 228: return "Hardfile not found";
1.1.1.4 root 229:
1.1.1.3 root 230: if (secspertrack < 1 || secspertrack > 32767
231: || surfaces < 1 || surfaces > 1023
1.1.1.6 root 232: || reserved < 0 || reserved > 1023
233: || (blocksize & (blocksize - 1)) != 0)
1.1.1.4 root 234: {
1.1.1.3 root 235: return "Bad hardfile geometry";
236: }
1.1.1.6 root 237: fseek (ui->hf.fd, 0, SEEK_END);
238: ui->hf.size = ftell (ui->hf.fd);
239: ui->hf.secspertrack = secspertrack;
240: ui->hf.surfaces = surfaces;
241: ui->hf.reservedblocks = reserved;
242: ui->hf.nrcyls = (ui->hf.size / blocksize) / (secspertrack * surfaces);
243: ui->hf.blocksize = blocksize;
244: }
245: ui->self = 0;
246: ui->reset_state = FS_STARTUP;
247: ui->rootdir = my_strdup (rootdir);
248: ui->readonly = readonly;
1.1 root 249:
1.1.1.3 root 250: return 0;
1.1 root 251: }
1.1.1.6 root 252:
253: char *set_filesys_unit (struct uaedev_mount_info *mountinfo, int nr,
254: char *volname, char *rootdir, int readonly,
255: int secspertrack, int surfaces, int reserved,
256: int blocksize)
257: {
258: UnitInfo ui = mountinfo->ui[nr];
259: char *result = set_filesys_unit_1 (mountinfo, nr, volname, rootdir, readonly,
260: secspertrack, surfaces, reserved, blocksize);
261: if (result)
262: mountinfo->ui[nr] = ui;
263: else
264: close_filesys_unit (&ui);
265:
266: return result;
267: }
268:
1.1.1.4 root 269: char *add_filesys_unit (struct uaedev_mount_info *mountinfo,
270: char *volname, char *rootdir, int readonly,
1.1.1.6 root 271: int secspertrack, int surfaces, int reserved,
272: int blocksize)
1.1.1.4 root 273: {
274: char *retval;
275: int nr = mountinfo->num_units;
276: UnitInfo *uip = mountinfo->ui + nr;
1.1 root 277:
1.1.1.4 root 278: if (nr >= MAX_UNITS)
279: return "Maximum number of file systems mounted";
280:
281: mountinfo->num_units++;
1.1.1.6 root 282: retval = set_filesys_unit_1 (mountinfo, nr, volname, rootdir, readonly,
283: secspertrack, surfaces, reserved, blocksize);
1.1.1.4 root 284: if (retval)
285: mountinfo->num_units--;
286: return retval;
287: }
288:
289: int kill_filesys_unit (struct uaedev_mount_info *mountinfo, int nr)
1.1.1.2 root 290: {
1.1.1.4 root 291: UnitInfo *uip = mountinfo->ui;
292: if (nr >= mountinfo->num_units || nr < 0)
1.1.1.2 root 293: return -1;
294:
1.1.1.6 root 295: close_filesys_unit (mountinfo->ui + nr);
1.1.1.4 root 296:
297: mountinfo->num_units--;
298: for (; nr < mountinfo->num_units; nr++) {
299: uip[nr] = uip[nr+1];
1.1.1.2 root 300: }
301: return 0;
302: }
303:
1.1.1.4 root 304: int move_filesys_unit (struct uaedev_mount_info *mountinfo, int nr, int to)
1.1.1.3 root 305: {
1.1.1.4 root 306: UnitInfo tmpui;
307: UnitInfo *uip = mountinfo->ui;
308:
309: if (nr >= mountinfo->num_units || nr < 0
310: || to >= mountinfo->num_units || to < 0
311: || to == nr)
312: return -1;
313: tmpui = uip[nr];
314: if (to > nr) {
315: int i;
316: for (i = nr; i < to; i++)
317: uip[i] = uip[i + 1];
318: } else {
319: int i;
320: for (i = nr; i > to; i--)
321: uip[i] = uip[i - 1];
322: }
323: uip[to] = tmpui;
324: return 0;
1.1.1.3 root 325: }
326:
1.1.1.4 root 327: int sprintf_filesys_unit (struct uaedev_mount_info *mountinfo, char *buffer, int num)
1.1.1.2 root 328: {
1.1.1.4 root 329: UnitInfo *uip = mountinfo->ui;
330: if (num >= mountinfo->num_units)
1.1.1.2 root 331: return -1;
1.1.1.4 root 332:
333: if (uip[num].volname != 0)
1.1.1.6 root 334: sprintf (buffer, "(DH%d:) Filesystem, %s: %s %s", num, uip[num].volname,
1.1.1.4 root 335: uip[num].rootdir, uip[num].readonly ? "ro" : "");
1.1.1.2 root 336: else
1.1.1.6 root 337: sprintf (buffer, "(DH%d:) Hardfile, \"%s\", size %d bytes", num,
1.1.1.4 root 338: uip[num].rootdir, uip[num].hf.size);
1.1.1.2 root 339: return 0;
340: }
341:
1.1.1.6 root 342: void write_filesys_config (struct uaedev_mount_info *mountinfo,
343: const char *unexpanded, const char *default_path, FILE *f)
1.1 root 344: {
1.1.1.4 root 345: UnitInfo *uip = mountinfo->ui;
1.1 root 346: int i;
1.1.1.4 root 347:
348: for (i = 0; i < mountinfo->num_units; i++) {
1.1.1.6 root 349: char *str;
350: str = cfgfile_subst_path (default_path, unexpanded, uip[i].rootdir);
1.1.1.4 root 351: if (uip[i].volname != 0) {
1.1.1.7 root 352: fprintf (f, "filesystem=%s,%s:%s\n", uip[i].readonly ? "ro" : "rw",
1.1.1.6 root 353: uip[i].volname, str);
1.1.1.3 root 354: } else {
1.1.1.12 root 355: fprintf (f, "hardfile=%s,%d,%d,%d,%d,%s\n",
356: uip[i].readonly ? "ro" : "rw", uip[i].hf.secspertrack,
1.1.1.6 root 357: uip[i].hf.surfaces, uip[i].hf.reservedblocks, 512, str);
1.1 root 358: }
1.1.1.6 root 359: free (str);
1.1 root 360: }
361: }
362:
1.1.1.4 root 363: struct uaedev_mount_info *alloc_mountinfo (void)
364: {
365: struct uaedev_mount_info *info;
366: info = (struct uaedev_mount_info *)malloc (sizeof *info);
1.1.1.6 root 367: /* memset (info, 0xaa, sizeof *info);*/
1.1.1.4 root 368: info->num_units = 0;
369: return info;
370: }
371:
372: struct uaedev_mount_info *dup_mountinfo (struct uaedev_mount_info *mip)
373: {
374: int i;
375: struct uaedev_mount_info *i2 = alloc_mountinfo ();
376:
377: memcpy (i2, mip, sizeof *i2);
378:
379: for (i = 0; i < i2->num_units; i++) {
380: UnitInfo *uip = i2->ui + i;
381: if (uip->volname)
382: uip->volname = my_strdup (uip->volname);
383: if (uip->rootdir)
384: uip->rootdir = my_strdup (uip->rootdir);
385: if (uip->hf.fd)
1.1.1.7 root 386: uip->hf.fd = fdopen ( dup (fileno (uip->hf.fd)), uip->readonly ? "rb" : "r+b");
1.1.1.4 root 387: }
388: return i2;
389: }
390:
391: void free_mountinfo (struct uaedev_mount_info *mip)
392: {
393: int i;
394: for (i = 0; i < mip->num_units; i++)
1.1.1.6 root 395: close_filesys_unit (mip->ui + i);
1.1.1.4 root 396: free (mip);
397: }
398:
399: struct hardfiledata *get_hardfile_data (int nr)
400: {
401: UnitInfo *uip = current_mountinfo->ui;
402: if (nr < 0 || nr >= current_mountinfo->num_units || uip[nr].volname != 0)
403: return 0;
404: return &uip[nr].hf;
405: }
406:
1.1 root 407: /* minimal AmigaDOS definitions */
408:
409: /* field offsets in DosPacket */
1.1.1.3 root 410: #define dp_Type 8
411: #define dp_Res1 12
412: #define dp_Res2 16
413: #define dp_Arg1 20
414: #define dp_Arg2 24
415: #define dp_Arg3 28
416: #define dp_Arg4 32
1.1 root 417:
418: /* result codes */
1.1.1.3 root 419: #define DOS_TRUE ((unsigned long)-1L)
1.1 root 420: #define DOS_FALSE (0L)
421:
1.1.1.13 root 422: /* Passed as type to Lock() */
423: #define SHARED_LOCK -2 /* File is readable by others */
424: #define ACCESS_READ -2 /* Synonym */
425: #define EXCLUSIVE_LOCK -1 /* No other access allowed */
426: #define ACCESS_WRITE -1 /* Synonym */
427:
1.1 root 428: /* packet types */
429: #define ACTION_CURRENT_VOLUME 7
430: #define ACTION_LOCATE_OBJECT 8
431: #define ACTION_RENAME_DISK 9
432: #define ACTION_FREE_LOCK 15
433: #define ACTION_DELETE_OBJECT 16
434: #define ACTION_RENAME_OBJECT 17
435: #define ACTION_COPY_DIR 19
436: #define ACTION_SET_PROTECT 21
437: #define ACTION_CREATE_DIR 22
438: #define ACTION_EXAMINE_OBJECT 23
439: #define ACTION_EXAMINE_NEXT 24
440: #define ACTION_DISK_INFO 25
441: #define ACTION_INFO 26
442: #define ACTION_FLUSH 27
443: #define ACTION_SET_COMMENT 28
444: #define ACTION_PARENT 29
445: #define ACTION_SET_DATE 34
446: #define ACTION_FIND_WRITE 1004
447: #define ACTION_FIND_INPUT 1005
448: #define ACTION_FIND_OUTPUT 1006
449: #define ACTION_END 1007
450: #define ACTION_SEEK 1008
451: #define ACTION_IS_FILESYSTEM 1027
452: #define ACTION_READ 'R'
453: #define ACTION_WRITE 'W'
454:
1.1.1.3 root 455: /* 2.0+ packet types */
456: #define ACTION_INHIBIT 31
457: #define ACTION_SET_FILE_SIZE 1022
458: #define ACTION_LOCK_RECORD 2008
459: #define ACTION_FREE_RECORD 2009
460: #define ACTION_SAME_LOCK 40
461: #define ACTION_CHANGE_MODE 1028
462: #define ACTION_FH_FROM_LOCK 1026
463: #define ACTION_COPY_DIR_FH 1030
464: #define ACTION_PARENT_FH 1031
465: #define ACTION_EXAMINE_FH 1034
466: #define ACTION_EXAMINE_ALL 1033
467: #define ACTION_MAKE_LINK 1021
468: #define ACTION_READ_LINK 1024
469: #define ACTION_FORMAT 1020
470: #define ACTION_IS_FILESYSTEM 1027
471: #define ACTION_ADD_NOTIFY 4097
472: #define ACTION_REMOVE_NOTIFY 4098
1.1 root 473:
1.1.1.3 root 474: #define DISK_TYPE 0x444f5301 /* DOS\1 */
1.1 root 475:
1.1.1.3 root 476: typedef struct {
477: uae_u32 uniq;
1.1.1.14! root 478: /* The directory we're going through. */
1.1.1.7 root 479: a_inode *aino;
1.1.1.14! root 480: /* The file we're going to look up next. */
! 481: a_inode *curr_file;
1.1.1.3 root 482: } ExamineKey;
1.1 root 483:
1.1.1.3 root 484: typedef struct key {
485: struct key *next;
1.1.1.7 root 486: a_inode *aino;
1.1.1.3 root 487: uae_u32 uniq;
488: int fd;
489: off_t file_pos;
490: } Key;
1.1 root 491:
1.1.1.3 root 492: /* Since ACTION_EXAMINE_NEXT is so braindamaged, we have to keep
493: * some of these around
494: */
495:
496: #define EXKEYS 100
497: #define MAX_AINO_HASH 128
1.1 root 498:
499: /* handler state info */
500:
501: typedef struct _unit {
502: struct _unit *next;
503:
504: /* Amiga stuff */
1.1.1.4 root 505: uaecptr dosbase;
506: uaecptr volume;
507: uaecptr port; /* Our port */
508: uaecptr locklist;
1.1 root 509:
510: /* Native stuff */
1.1.1.4 root 511: uae_s32 unit; /* unit number */
512: UnitInfo ui; /* unit startup info */
513: char tmpbuf3[256];
1.1.1.3 root 514:
515: /* Dummy message processing */
1.1.1.4 root 516: uaecptr dummy_message;
1.1.1.3 root 517: volatile unsigned int cmds_sent;
518: volatile unsigned int cmds_complete;
519: volatile unsigned int cmds_acked;
520:
521: /* ExKeys */
1.1.1.14! root 522: ExamineKey examine_keys[EXKEYS];
1.1.1.4 root 523: int next_exkey;
1.1.1.14! root 524: unsigned long total_locked_ainos;
1.1.1.3 root 525:
526: /* Keys */
1.1.1.4 root 527: struct key *keys;
528: uae_u32 key_uniq;
529: uae_u32 a_uniq;
1.1.1.3 root 530:
1.1.1.7 root 531: a_inode rootnode;
1.1.1.3 root 532: unsigned long aino_cache_size;
1.1.1.7 root 533: a_inode *aino_hash[MAX_AINO_HASH];
1.1.1.3 root 534: unsigned long nr_cache_hits;
535: unsigned long nr_cache_lookups;
1.1 root 536: } Unit;
537:
1.1.1.3 root 538: typedef uae_u8 *dpacket;
539: #define PUT_PCK_RES1(p,v) do { do_put_mem_long ((uae_u32 *)((p) + dp_Res1), (v)); } while (0)
540: #define PUT_PCK_RES2(p,v) do { do_put_mem_long ((uae_u32 *)((p) + dp_Res2), (v)); } while (0)
541: #define GET_PCK_TYPE(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Type))))
542: #define GET_PCK_RES1(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Res1))))
543: #define GET_PCK_RES2(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Res2))))
544: #define GET_PCK_ARG1(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Arg1))))
545: #define GET_PCK_ARG2(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Arg2))))
546: #define GET_PCK_ARG3(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Arg3))))
547: #define GET_PCK_ARG4(p) ((uae_s32)(do_get_mem_long ((uae_u32 *)((p) + dp_Arg4))))
1.1 root 548:
1.1.1.3 root 549: static char *bstr1 (uaecptr addr)
1.1 root 550: {
551: static char buf[256];
552: int i;
1.1.1.3 root 553: int n = get_byte(addr);
554: addr++;
555:
1.1.1.4 root 556: for (i = 0; i < n; i++, addr++)
1.1.1.3 root 557: buf[i] = get_byte(addr);
1.1 root 558: buf[i] = 0;
559: return buf;
560: }
561:
1.1.1.3 root 562: static char *bstr (Unit *unit, uaecptr addr)
563: {
564: int i;
565: int n = get_byte(addr);
566:
567: addr++;
1.1.1.4 root 568: for (i = 0; i < n; i++, addr++)
1.1.1.3 root 569: unit->tmpbuf3[i] = get_byte(addr);
570: unit->tmpbuf3[i] = 0;
571: return unit->tmpbuf3;
572: }
573:
574: static char *bstr_cut (Unit *unit, uaecptr addr)
575: {
576: char *p = unit->tmpbuf3;
577: int i, colon_seen = 0;
578: int n = get_byte (addr);
579:
580: addr++;
1.1.1.4 root 581: for (i = 0; i < n; i++, addr++) {
1.1.1.3 root 582: uae_u8 c = get_byte(addr);
583: unit->tmpbuf3[i] = c;
584: if (c == '/' || (c == ':' && colon_seen++ == 0))
585: p = unit->tmpbuf3 + i + 1;
586: }
587: unit->tmpbuf3[i] = 0;
588: return p;
589: }
590:
591: static Unit *units = 0;
1.1 root 592: static int unit_num = 0;
593:
594: static Unit*
1.1.1.4 root 595: find_unit (uaecptr port)
1.1 root 596: {
597: Unit* u;
1.1.1.4 root 598: for (u = units; u; u = u->next)
599: if (u->port == port)
1.1 root 600: break;
601:
602: return u;
603: }
1.1.1.7 root 604:
1.1.1.3 root 605: static void prepare_for_open (char *name)
606: {
607: #if 0
608: struct stat statbuf;
609: int mode;
610:
611: if (-1 == stat (name, &statbuf))
612: return;
613:
614: mode = statbuf.st_mode;
615: mode |= S_IRUSR;
616: mode |= S_IWUSR;
617: mode |= S_IXUSR;
618: chmod (name, mode);
619: #endif
620: }
621:
1.1.1.7 root 622: static void de_recycle_aino (Unit *unit, a_inode *aino)
1.1 root 623: {
1.1.1.3 root 624: if (aino->next == 0 || aino == &unit->rootnode)
625: return;
626: aino->next->prev = aino->prev;
627: aino->prev->next = aino->next;
628: aino->next = aino->prev = 0;
629: unit->aino_cache_size--;
630: }
631:
1.1.1.7 root 632: static void dispose_aino (Unit *unit, a_inode **aip, a_inode *aino)
633: {
634: int hash = aino->uniq % MAX_AINO_HASH;
635: if (unit->aino_hash[hash] == aino)
636: unit->aino_hash[hash] = 0;
637:
638: if (aino->dirty && aino->parent)
639: fsdb_dir_writeback (aino->parent);
640:
641: *aip = aino->sibling;
642: if (aino->comment)
643: free (aino->comment);
644: free (aino->nname);
645: free (aino->aname);
646: free (aino);
647: }
648:
1.1.1.9 root 649: static void recycle_aino (Unit *unit, a_inode *new_aino)
1.1.1.3 root 650: {
1.1.1.9 root 651: if (new_aino->dir || new_aino->shlock > 0
652: || new_aino->elock || new_aino == &unit->rootnode)
1.1.1.3 root 653: /* Still in use */
654: return;
655:
1.1.1.14! root 656: TRACE (("Recycling; cache size %d, total_locked %d\n",
! 657: unit->aino_cache_size, unit->total_locked_ainos));
! 658: if (unit->aino_cache_size > 500 + unit->total_locked_ainos) {
1.1.1.3 root 659: /* Reap a few. */
660: int i = 0;
661: while (i < 50) {
1.1.1.7 root 662: a_inode **aip;
1.1.1.3 root 663: aip = &unit->rootnode.prev->parent->child;
664: for (;;) {
1.1.1.9 root 665: a_inode *aino = *aip;
1.1.1.3 root 666: if (aino == 0)
667: break;
668:
1.1.1.14! root 669: /* Not recyclable if next == 0 (i.e., not chained into
! 670: recyclable list), or if parent directory is being
! 671: ExNext()ed. */
! 672: if (aino->next == 0 || aino->parent->locked_children)
1.1.1.3 root 673: aip = &aino->sibling;
674: else {
675: if (aino->shlock > 0 || aino->elock)
676: write_log ("panic: freeing locked a_inode!\n");
677:
1.1.1.7 root 678: de_recycle_aino (unit, aino);
679: dispose_aino (unit, aip, aino);
680: i++;
1.1.1.3 root 681: }
682: }
683: }
684: #if 0
685: {
686: char buffer[40];
687: sprintf (buffer, "%d ainos reaped.\n", i);
1.1.1.14! root 688: TRACE ((buffer));
1.1.1.3 root 689: }
690: #endif
691: }
1.1.1.9 root 692:
693: /* Chain it into circular list. */
694: new_aino->next = unit->rootnode.next;
695: new_aino->prev = &unit->rootnode;
696: new_aino->prev->next = new_aino;
697: new_aino->next->prev = new_aino;
698: unit->aino_cache_size++;
1.1.1.3 root 699: }
1.1 root 700:
1.1.1.7 root 701: static void update_child_names (Unit *unit, a_inode *a, a_inode *parent)
1.1.1.3 root 702: {
703: int l0 = strlen (parent->nname) + 2;
1.1 root 704:
1.1.1.3 root 705: while (a != 0) {
706: char *name_start;
707: char *new_name;
1.1.1.13 root 708: char dirsep[2] = { FSDB_DIR_SEPARATOR, '\0' };
709:
1.1.1.3 root 710: a->parent = parent;
1.1.1.13 root 711: name_start = strrchr (a->nname, FSDB_DIR_SEPARATOR);
1.1.1.3 root 712: if (name_start == 0) {
713: write_log ("malformed file name");
714: }
715: name_start++;
716: new_name = (char *)xmalloc (strlen (name_start) + l0);
717: strcpy (new_name, parent->nname);
1.1.1.13 root 718: strcat (new_name, dirsep);
1.1.1.3 root 719: strcat (new_name, name_start);
720: free (a->nname);
721: a->nname = new_name;
722: if (a->child)
723: update_child_names (unit, a->child, a);
724: a = a->sibling;
1.1 root 725: }
1.1.1.3 root 726: }
1.1 root 727:
1.1.1.7 root 728: static void move_aino_children (Unit *unit, a_inode *from, a_inode *to)
1.1.1.3 root 729: {
730: to->child = from->child;
731: from->child = 0;
732: update_child_names (unit, to->child, to);
1.1 root 733: }
734:
1.1.1.7 root 735: static void delete_aino (Unit *unit, a_inode *aino)
1.1 root 736: {
1.1.1.7 root 737: a_inode **aip;
1.1.1.3 root 738: int hash;
739:
1.1.1.4 root 740: TRACE(("deleting aino %x\n", aino->uniq));
1.1.1.3 root 741:
1.1.1.7 root 742: aino->dirty = 1;
743: aino->deleted = 1;
1.1.1.3 root 744: de_recycle_aino (unit, aino);
1.1.1.14! root 745:
! 746: /* If any ExKeys are currently pointing at us, advance them. */
! 747: if (aino->parent->exnext_count > 0) {
! 748: int i;
! 749: for (i = 0; i < EXKEYS; i++) {
! 750: ExamineKey *k = unit->examine_keys + i;
! 751: if (k->uniq == 0)
! 752: continue;
! 753: if (k->aino == aino->parent) {
! 754: if (k->curr_file == aino)
! 755: k->curr_file = aino->sibling;
! 756: }
! 757: }
! 758: }
! 759:
1.1.1.3 root 760: aip = &aino->parent->child;
761: while (*aip != aino && *aip != 0)
762: aip = &(*aip)->sibling;
763: if (*aip != aino) {
764: write_log ("Couldn't delete aino.\n");
765: return;
766: }
1.1.1.7 root 767: dispose_aino (unit, aip, aino);
1.1 root 768: }
769:
1.1.1.7 root 770: static a_inode *lookup_sub (a_inode *dir, uae_u32 uniq)
1.1.1.3 root 771: {
1.1.1.7 root 772: a_inode **cp = &dir->child;
773: a_inode *c, *retval;
1.1.1.3 root 774:
775: for (;;) {
776: c = *cp;
777: if (c == 0)
778: return 0;
779:
780: if (c->uniq == uniq) {
781: retval = c;
782: break;
783: }
784: if (c->dir) {
1.1.1.7 root 785: a_inode *a = lookup_sub (c, uniq);
1.1.1.3 root 786: if (a != 0) {
787: retval = a;
788: break;
789: }
790: }
791: cp = &c->sibling;
792: }
793: *cp = c->sibling;
794: c->sibling = dir->child;
795: dir->child = c;
796: return retval;
797: }
798:
1.1.1.7 root 799: static a_inode *lookup_aino (Unit *unit, uae_u32 uniq)
1.1 root 800: {
1.1.1.7 root 801: a_inode *a;
1.1.1.3 root 802: int hash = uniq % MAX_AINO_HASH;
803:
804: if (uniq == 0)
805: return &unit->rootnode;
806: a = unit->aino_hash[hash];
807: if (a == 0 || a->uniq != uniq)
808: a = lookup_sub (&unit->rootnode, uniq);
809: else
810: unit->nr_cache_hits++;
811: unit->nr_cache_lookups++;
812: unit->aino_hash[hash] = a;
813: return a;
814: }
815:
1.1.1.7 root 816: char *build_nname (const char *d, const char *n)
817: {
818: char dsep[2] = { FSDB_DIR_SEPARATOR, '\0' };
819: char *p = (char *) xmalloc (strlen (d) + strlen (n) + 2);
820: strcpy (p, d);
821: strcat (p, dsep);
822: strcat (p, n);
823: return p;
824: }
825:
826: char *build_aname (const char *d, const char *n)
827: {
828: char *p = (char *) xmalloc (strlen (d) + strlen (n) + 2);
829: strcpy (p, d);
830: strcat (p, "/");
831: strcat (p, n);
832: return p;
833: }
834:
1.1.1.3 root 835: /* This gets called to translate an Amiga name that some program used to
1.1.1.7 root 836: * a name that we can use on the native filesystem. */
837: static char *get_nname (Unit *unit, a_inode *base, char *rel,
838: char **modified_rel)
1.1.1.3 root 839: {
1.1.1.7 root 840: char *found;
1.1.1.3 root 841: char *p = 0;
842:
1.1.1.7 root 843: *modified_rel = 0;
844:
845: /* If we have a mapping of some other aname to "rel", we must pretend
846: * it does not exist.
847: * This can happen for example if an Amiga program creates a
848: * file called ".". We can't represent this in our filesystem,
849: * so we create a special file "uae_xxx" and record the mapping
850: * aname "." -> nname "uae_xxx" in the database. Then, the Amiga
851: * program looks up "uae_xxx" (yes, it's contrived). The filesystem
852: * should not make the uae_xxx file visible to the Amiga side. */
853: if (fsdb_used_as_nname (base, rel))
854: return 0;
855: /* A file called "." (or whatever else is invalid on this filesystem)
856: * does not exist, as far as the Amiga side is concerned. */
857: if (fsdb_name_invalid (rel))
1.1.1.4 root 858: return 0;
859:
1.1.1.7 root 860: /* See if we have a file that has the same name as the aname we are
861: * looking for. */
862: found = fsdb_search_dir (base->nname, rel);
863: if (found == 0)
864: return found;
865: if (found == rel)
866: return build_nname (base->nname, rel);
867:
868: *modified_rel = found;
869: return build_nname (base->nname, found);
870: }
871:
872: static char *create_nname (Unit *unit, a_inode *base, char *rel)
873: {
874: char *p;
875:
876: /* We are trying to create a file called REL. */
877:
878: /* If the name is used otherwise in the directory (or globally), we
879: * need a new unique nname. */
880: if (fsdb_name_invalid (rel) || fsdb_used_as_nname (base, rel)) {
881: oh_dear:
882: p = fsdb_create_unique_nname (base, rel);
883: return p;
884: }
885: p = build_nname (base->nname, rel);
886:
887: /* Delete this code once we know everything works. */
888: if (access (p, R_OK) >= 0 || errno != ENOENT) {
889: write_log ("Filesystem in trouble... please report.\n");
890: free (p);
891: goto oh_dear;
1.1.1.3 root 892: }
893: return p;
894: }
895:
896: /*
897: * This gets called if an ACTION_EXAMINE_NEXT happens and we hit an object
898: * for which we know the name on the native filesystem, but no corresponding
899: * Amiga filesystem name.
900: * @@@ For DOS filesystems, it might make sense to declare the new name
901: * "weak", so that it can get overriden by a subsequent call to get_nname().
902: * That way, if someone does "dir :" and there is a file "foobar.inf", and
903: * someone else tries to open "foobar.info", get_nname() could maybe made to
904: * figure out that this is supposed to be the file "foobar.inf".
905: * DOS sucks...
906: */
1.1.1.7 root 907: static char *get_aname (Unit *unit, a_inode *base, char *rel)
1.1.1.3 root 908: {
1.1.1.7 root 909: return my_strdup (rel);
1.1.1.3 root 910: }
911:
1.1.1.7 root 912: static void init_child_aino (Unit *unit, a_inode *base, a_inode *aino)
1.1.1.3 root 913: {
914: aino->uniq = ++unit->a_uniq;
915: if (unit->a_uniq == 0xFFFFFFFF) {
916: write_log ("Running out of a_inodes (prepare for big trouble)!\n");
917: }
918: aino->shlock = 0;
919: aino->elock = 0;
920:
1.1.1.7 root 921: aino->dirty = 0;
922: aino->deleted = 0;
923:
1.1.1.14! root 924: /* For directories - this one isn't being ExNext()ed yet. */
! 925: aino->locked_children = 0;
! 926: aino->exnext_count = 0;
! 927: /* But the parent might be. */
! 928: if (base->exnext_count) {
! 929: unit->total_locked_ainos++;
! 930: base->locked_children++;
! 931: }
1.1.1.3 root 932: /* Update tree structure */
933: aino->parent = base;
934: aino->child = 0;
935: aino->sibling = base->child;
936: base->child = aino;
937: aino->next = aino->prev = 0;
1.1.1.7 root 938: }
1.1.1.3 root 939:
1.1.1.7 root 940: static a_inode *new_child_aino (Unit *unit, a_inode *base, char *rel)
941: {
942: char *modified_rel;
943: char *nn;
944: a_inode *aino;
945:
946: TRACE(("new_child_aino %s, %s\n", base->aname, rel));
947:
948: aino = fsdb_lookup_aino_aname (base, rel);
949: if (aino == 0) {
950: nn = get_nname (unit, base, rel, &modified_rel);
951: if (nn == 0)
952: return 0;
953:
1.1.1.11 root 954: aino = (a_inode *) xcalloc (sizeof (a_inode), 1);
1.1.1.7 root 955: if (aino == 0)
956: return 0;
957: aino->aname = modified_rel ? modified_rel : my_strdup (rel);
958: aino->nname = nn;
959:
960: aino->comment = 0;
961: aino->has_dbentry = 0;
962:
963: fsdb_fill_file_attrs (aino);
964: if (aino->dir)
965: fsdb_clean_dir (aino);
1.1.1.3 root 966: }
1.1.1.7 root 967: init_child_aino (unit, base, aino);
968:
969: recycle_aino (unit, aino);
970: TRACE(("created aino %x, lookup\n", aino->uniq));
971: return aino;
972: }
973:
974: static a_inode *create_child_aino (Unit *unit, a_inode *base, char *rel, int isdir)
975: {
1.1.1.11 root 976: a_inode *aino = (a_inode *) xcalloc (sizeof (a_inode), 1);
1.1.1.7 root 977: if (aino == 0)
978: return 0;
979:
980: aino->aname = my_strdup (rel);
981: aino->nname = create_nname (unit, base, rel);
982:
983: init_child_aino (unit, base, aino);
984: aino->amigaos_mode = 0;
985: aino->dir = isdir;
986:
987: aino->comment = 0;
988: aino->has_dbentry = 0;
989: aino->dirty = 1;
1.1.1.5 root 990:
1.1.1.3 root 991: recycle_aino (unit, aino);
1.1.1.7 root 992: TRACE(("created aino %x, create\n", aino->uniq));
1.1.1.3 root 993: return aino;
994: }
995:
1.1.1.7 root 996: static a_inode *lookup_child_aino (Unit *unit, a_inode *base, char *rel, uae_u32 *err)
1.1.1.3 root 997: {
1.1.1.7 root 998: a_inode *c = base->child;
1.1.1.3 root 999: int l0 = strlen (rel);
1000:
1001: if (base->dir == 0) {
1002: *err = ERROR_OBJECT_WRONG_TYPE;
1003: return 0;
1004: }
1005:
1006: while (c != 0) {
1007: int l1 = strlen (c->aname);
1.1.1.7 root 1008: if (l0 <= l1 && same_aname (rel, c->aname + l1 - l0)
1.1.1.3 root 1009: && (l0 == l1 || c->aname[l1-l0-1] == '/'))
1010: break;
1011: c = c->sibling;
1012: }
1013: if (c != 0)
1014: return c;
1.1.1.7 root 1015: c = new_child_aino (unit, base, rel);
1.1.1.3 root 1016: if (c == 0)
1.1.1.11 root 1017: *err = ERROR_OBJECT_NOT_AROUND;
1.1.1.3 root 1018: return c;
1019: }
1020:
1.1.1.7 root 1021: /* Different version because for this one, REL is an nname. */
1022: static a_inode *lookup_child_aino_for_exnext (Unit *unit, a_inode *base, char *rel, uae_u32 *err)
1.1.1.3 root 1023: {
1.1.1.7 root 1024: a_inode *c = base->child;
1.1.1.3 root 1025: int l0 = strlen (rel);
1026:
1027: *err = 0;
1028: while (c != 0) {
1029: int l1 = strlen (c->nname);
1.1.1.7 root 1030: /* Note: using strcmp here. */
1031: if (l0 <= l1 && strcmp (rel, c->nname + l1 - l0) == 0
1032: && (l0 == l1 || c->nname[l1-l0-1] == FSDB_DIR_SEPARATOR))
1.1.1.3 root 1033: break;
1034: c = c->sibling;
1035: }
1036: if (c != 0)
1037: return c;
1.1.1.7 root 1038: c = fsdb_lookup_aino_nname (base, rel);
1039: if (c == 0) {
1040: c = (a_inode *)malloc (sizeof (a_inode));
1041: if (c == 0) {
1042: *err = ERROR_NO_FREE_STORE;
1043: return 0;
1044: }
1045:
1046: c->nname = build_nname (base->nname, rel);
1.1.1.3 root 1047: c->aname = get_aname (unit, base, rel);
1.1.1.7 root 1048: c->comment = 0;
1049: c->has_dbentry = 0;
1050: fsdb_fill_file_attrs (c);
1051: if (c->dir)
1052: fsdb_clean_dir (c);
1.1.1.3 root 1053: }
1.1.1.7 root 1054: init_child_aino (unit, base, c);
1055:
1056: recycle_aino (unit, c);
1057: TRACE(("created aino %x, exnext\n", c->uniq));
1058:
1.1.1.3 root 1059: return c;
1060: }
1061:
1.1.1.7 root 1062: static a_inode *get_aino (Unit *unit, a_inode *base, const char *rel, uae_u32 *err)
1.1.1.3 root 1063: {
1064: char *tmp;
1065: char *p;
1.1.1.7 root 1066: a_inode *curr;
1.1.1.3 root 1067: int i;
1068:
1069: *err = 0;
1.1.1.4 root 1070: TRACE(("get_path(%s,%s)\n", base->aname, rel));
1.1.1.3 root 1071:
1072: /* root-relative path? */
1.1.1.4 root 1073: for (i = 0; rel[i] && rel[i] != '/' && rel[i] != ':'; i++)
1.1.1.3 root 1074: ;
1075: if (':' == rel[i])
1076: rel += i+1;
1077:
1078: tmp = my_strdup (rel);
1079: p = tmp;
1080: curr = base;
1081:
1.1.1.7 root 1082: while (*p) {
1.1.1.3 root 1083: /* start with a slash? go up a level. */
1084: if (*p == '/') {
1085: if (curr->parent != 0)
1086: curr = curr->parent;
1087: p++;
1088: } else {
1.1.1.7 root 1089: a_inode *next;
1.1.1.3 root 1090:
1091: char *component_end;
1092: component_end = strchr (p, '/');
1093: if (component_end != 0)
1094: *component_end = '\0';
1095: next = lookup_child_aino (unit, curr, p, err);
1096: if (next == 0) {
1097: /* if only last component not found, return parent dir. */
1.1.1.11 root 1098: if (*err != ERROR_OBJECT_NOT_AROUND || component_end != 0)
1.1.1.3 root 1099: curr = 0;
1100: /* ? what error is appropriate? */
1101: break;
1102: }
1103: curr = next;
1104: if (component_end)
1105: p = component_end+1;
1106: else
1107: break;
1108:
1109: }
1110: }
1111: free (tmp);
1112: return curr;
1113: }
1114:
1115: static uae_u32 startup_handler (void)
1116: {
1117: /* Just got the startup packet. It's in A4. DosBase is in A2,
1118: * our allocated volume structure is in D6, A5 is a pointer to
1119: * our port. */
1.1.1.7 root 1120: uaecptr rootnode = get_long (m68k_areg (regs, 2) + 34);
1121: uaecptr dos_info = get_long (rootnode + 24) << 2;
1.1.1.3 root 1122: uaecptr pkt = m68k_dreg (regs, 3);
1123: uaecptr arg2 = get_long (pkt + dp_Arg2);
1.1 root 1124: int i, namelen;
1.1.1.3 root 1125: char* devname = bstr1 (get_long (pkt + dp_Arg1) << 2);
1.1 root 1126: char* s;
1.1.1.4 root 1127: Unit *unit;
1.1.1.3 root 1128: UnitInfo *uinfo;
1.1 root 1129:
1130: /* find UnitInfo with correct device name */
1.1.1.4 root 1131: s = strchr (devname, ':');
1132: if (s)
1.1.1.3 root 1133: *s = '\0';
1.1 root 1134:
1.1.1.4 root 1135: for (i = 0; i < current_mountinfo->num_units; i++) {
1.1 root 1136: /* Hardfile volume name? */
1.1.1.4 root 1137: if (current_mountinfo->ui[i].volname == 0)
1.1 root 1138: continue;
1.1.1.3 root 1139:
1.1.1.4 root 1140: if (current_mountinfo->ui[i].startup == arg2)
1.1.1.3 root 1141: break;
1.1 root 1142: }
1.1.1.3 root 1143:
1.1.1.4 root 1144: if (i == current_mountinfo->num_units
1145: || access (current_mountinfo->ui[i].rootdir, R_OK) != 0)
1146: {
1147: write_log ("Failed attempt to mount device\n", devname);
1.1.1.3 root 1148: put_long (pkt + dp_Res1, DOS_FALSE);
1149: put_long (pkt + dp_Res2, ERROR_DEVICE_NOT_MOUNTED);
1150: return 1;
1.1 root 1151: }
1.1.1.4 root 1152: uinfo = current_mountinfo->ui + i;
1.1 root 1153:
1.1.1.11 root 1154: unit = (Unit *) xcalloc (sizeof (Unit), 1);
1.1 root 1155: unit->next = units;
1156: units = unit;
1.1.1.3 root 1157: uinfo->self = unit;
1.1 root 1158:
1159: unit->volume = 0;
1.1.1.7 root 1160: unit->port = m68k_areg (regs, 5);
1.1 root 1161: unit->unit = unit_num++;
1162:
1.1.1.3 root 1163: unit->ui.devname = uinfo->devname;
1164: unit->ui.volname = my_strdup (uinfo->volname); /* might free later for rename */
1165: unit->ui.rootdir = uinfo->rootdir;
1166: unit->ui.readonly = uinfo->readonly;
1167: unit->ui.unit_pipe = uinfo->unit_pipe;
1168: unit->ui.back_pipe = uinfo->back_pipe;
1169: unit->cmds_complete = 0;
1170: unit->cmds_sent = 0;
1171: unit->cmds_acked = 0;
1172: for (i = 0; i < EXKEYS; i++) {
1173: unit->examine_keys[i].aino = 0;
1.1.1.14! root 1174: unit->examine_keys[i].curr_file = 0;
1.1.1.3 root 1175: unit->examine_keys[i].uniq = 0;
1176: }
1.1.1.14! root 1177: unit->total_locked_ainos = 0;
1.1.1.3 root 1178: unit->next_exkey = 1;
1179: unit->keys = 0;
1180: unit->a_uniq = unit->key_uniq = 0;
1181:
1182: unit->rootnode.aname = uinfo->volname;
1183: unit->rootnode.nname = uinfo->rootdir;
1184: unit->rootnode.sibling = 0;
1185: unit->rootnode.next = unit->rootnode.prev = &unit->rootnode;
1186: unit->rootnode.uniq = 0;
1187: unit->rootnode.parent = 0;
1188: unit->rootnode.child = 0;
1189: unit->rootnode.dir = 1;
1190: unit->rootnode.amigaos_mode = 0;
1191: unit->rootnode.shlock = 0;
1192: unit->rootnode.elock = 0;
1.1.1.11 root 1193: unit->rootnode.comment = 0;
1194: unit->rootnode.has_dbentry = 0;
1.1.1.3 root 1195: unit->aino_cache_size = 0;
1196: for (i = 0; i < MAX_AINO_HASH; i++)
1197: unit->aino_hash[i] = 0;
1198:
1199: /* write_comm_pipe_int (unit->ui.unit_pipe, -1, 1);*/
1.1 root 1200:
1.1.1.4 root 1201: TRACE(("**** STARTUP volume %s\n", unit->ui.volname));
1.1 root 1202:
1203: /* fill in our process in the device node */
1.1.1.3 root 1204: put_long ((get_long (pkt + dp_Arg3) << 2) + 8, unit->port);
1.1.1.7 root 1205: unit->dosbase = m68k_areg (regs, 2);
1.1 root 1206:
1.1.1.3 root 1207: /* make new volume */
1208: unit->volume = m68k_areg (regs, 3) + 32;
1209: #ifdef UAE_FILESYS_THREADS
1210: unit->locklist = m68k_areg (regs, 3) + 8;
1211: #else
1212: unit->locklist = m68k_areg (regs, 3);
1213: #endif
1214: unit->dummy_message = m68k_areg (regs, 3) + 12;
1.1 root 1215:
1.1.1.3 root 1216: put_long (unit->dummy_message + 10, 0);
1217:
1218: put_long (unit->volume + 4, 2); /* Type = dt_volume */
1219: put_long (unit->volume + 12, 0); /* Lock */
1220: put_long (unit->volume + 16, 3800); /* Creation Date */
1221: put_long (unit->volume + 20, 0);
1222: put_long (unit->volume + 24, 0);
1223: put_long (unit->volume + 28, 0); /* lock list */
1224: put_long (unit->volume + 40, (unit->volume + 44) >> 2); /* Name */
1225: namelen = strlen (unit->ui.volname);
1226: put_byte (unit->volume + 44, namelen);
1.1.1.4 root 1227: for (i = 0; i < namelen; i++)
1.1.1.3 root 1228: put_byte (unit->volume + 45 + i, unit->ui.volname[i]);
1229:
1230: /* link into DOS list */
1.1.1.7 root 1231: put_long (unit->volume, get_long (dos_info + 4));
1.1.1.3 root 1232: put_long (dos_info + 4, unit->volume >> 2);
1233:
1234: put_long (unit->volume + 8, unit->port);
1235: put_long (unit->volume + 32, DISK_TYPE);
1.1 root 1236:
1.1.1.3 root 1237: put_long (pkt + dp_Res1, DOS_TRUE);
1.1.1.7 root 1238:
1239: fsdb_clean_dir (&unit->rootnode);
1240:
1.1.1.3 root 1241: return 0;
1.1 root 1242: }
1243:
1244: static void
1.1.1.4 root 1245: do_info (Unit *unit, dpacket packet, uaecptr info)
1.1 root 1246: {
1.1.1.4 root 1247: struct fs_usage fsu;
1248:
1249: if (get_fs_usage (unit->ui.rootdir, 0, &fsu) != 0) {
1.1.1.3 root 1250: PUT_PCK_RES1 (packet, DOS_FALSE);
1251: PUT_PCK_RES2 (packet, dos_errno ());
1.1.1.4 root 1252: return;
1.1 root 1253: }
1254:
1.1.1.4 root 1255: fsu.fsu_blocks >>= 1;
1256: fsu.fsu_bavail >>= 1;
1.1.1.7 root 1257: put_long (info, 0); /* errors */
1258: put_long (info + 4, unit->unit); /* unit number */
1259: put_long (info + 8, unit->ui.readonly ? 80 : 82); /* state */
1260: put_long (info + 12, fsu.fsu_blocks ); /* numblocks */
1261: put_long (info + 16, fsu.fsu_blocks - fsu.fsu_bavail); /* inuse */
1262: put_long (info + 20, 1024); /* bytesperblock */
1263: put_long (info + 24, DISK_TYPE); /* disk type */
1264: put_long (info + 28, unit->volume >> 2); /* volume node */
1265: put_long (info + 32, 0); /* inuse */
1.1.1.3 root 1266: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 1267: }
1268:
1269: static void
1.1.1.4 root 1270: action_disk_info (Unit *unit, dpacket packet)
1.1 root 1271: {
1.1.1.4 root 1272: TRACE(("ACTION_DISK_INFO\n"));
1.1.1.3 root 1273: do_info(unit, packet, GET_PCK_ARG1 (packet) << 2);
1.1 root 1274: }
1275:
1276: static void
1.1.1.4 root 1277: action_info (Unit *unit, dpacket packet)
1.1 root 1278: {
1.1.1.4 root 1279: TRACE(("ACTION_INFO\n"));
1.1.1.3 root 1280: do_info(unit, packet, GET_PCK_ARG2 (packet) << 2);
1.1 root 1281: }
1282:
1.1.1.4 root 1283: static void free_key (Unit *unit, Key *k)
1.1 root 1284: {
1285: Key *k1;
1.1.1.3 root 1286: Key *prev = 0;
1287: for (k1 = unit->keys; k1; k1 = k1->next) {
1288: if (k == k1) {
1.1.1.4 root 1289: if (prev)
1.1.1.3 root 1290: prev->next = k->next;
1291: else
1292: unit->keys = k->next;
1293: break;
1294: }
1295: prev = k1;
1.1 root 1296: }
1297:
1298: if (k->fd >= 0)
1.1.1.13 root 1299: close (k->fd);
1.1.1.3 root 1300:
1.1 root 1301: free(k);
1302: }
1303:
1.1.1.4 root 1304: static Key *lookup_key (Unit *unit, uae_u32 uniq)
1.1 root 1305: {
1306: Key *k;
1.1.1.3 root 1307: /* It's hardly worthwhile to optimize this - most of the time there are
1308: * only one or zero keys. */
1.1.1.4 root 1309: for (k = unit->keys; k; k = k->next) {
1.1.1.3 root 1310: if (uniq == k->uniq)
1311: return k;
1.1 root 1312: }
1.1.1.3 root 1313: write_log ("Error: couldn't find key!\n");
1314: #if 0
1.1 root 1315: exit(1);
1316: /* NOTREACHED */
1.1.1.3 root 1317: #endif
1318: /* There isn't much hope we will recover. Unix would kill the process,
1319: * AmigaOS gets killed by it. */
1320: write_log ("Better reset that Amiga - the system is messed up.\n");
1321: return 0;
1.1 root 1322: }
1323:
1.1.1.4 root 1324: static Key *new_key (Unit *unit)
1.1 root 1325: {
1.1.1.4 root 1326: Key *k = (Key *) xmalloc(sizeof(Key));
1.1.1.3 root 1327: k->uniq = ++unit->key_uniq;
1.1 root 1328: k->fd = -1;
1329: k->file_pos = 0;
1.1.1.3 root 1330: k->next = unit->keys;
1331: unit->keys = k;
1.1 root 1332:
1333: return k;
1334: }
1335:
1336: static void
1.1.1.4 root 1337: dumplock (Unit *unit, uaecptr lock)
1.1 root 1338: {
1.1.1.7 root 1339: a_inode *a;
1.1.1.4 root 1340: TRACE(("LOCK: 0x%lx", lock));
1341: if (!lock) {
1342: TRACE(("\n"));
1.1 root 1343: return;
1344: }
1.1.1.4 root 1345: TRACE(("{ next=0x%lx, mode=%ld, handler=0x%lx, volume=0x%lx, aino %lx ",
1.1.1.7 root 1346: get_long (lock) << 2, get_long (lock+8),
1347: get_long (lock+12), get_long (lock+16),
1348: get_long (lock + 4)));
1.1.1.3 root 1349: a = lookup_aino (unit, get_long (lock + 4));
1350: if (a == 0) {
1.1.1.4 root 1351: TRACE(("not found!"));
1.1.1.3 root 1352: } else {
1.1.1.4 root 1353: TRACE(("%s", a->nname));
1.1.1.3 root 1354: }
1.1.1.4 root 1355: TRACE((" }\n"));
1.1 root 1356: }
1357:
1.1.1.7 root 1358: static a_inode *find_aino (Unit *unit, uaecptr lock, const char *name, uae_u32 *err)
1.1 root 1359: {
1.1.1.7 root 1360: a_inode *a;
1.1 root 1361:
1.1.1.3 root 1362: if (lock) {
1.1.1.7 root 1363: a_inode *olda = lookup_aino (unit, get_long (lock + 4));
1.1.1.3 root 1364: if (olda == 0) {
1365: /* That's the best we can hope to do. */
1366: a = get_aino (unit, &unit->rootnode, name, err);
1.1 root 1367: } else {
1.1.1.4 root 1368: TRACE(("aino: 0x%08lx", (unsigned long int)olda->uniq));
1369: TRACE((" \"%s\"\n", olda->nname));
1.1.1.3 root 1370: a = get_aino (unit, olda, name, err);
1.1 root 1371: }
1372: } else {
1.1.1.3 root 1373: a = get_aino (unit, &unit->rootnode, name, err);
1.1 root 1374: }
1.1.1.3 root 1375: if (a) {
1.1.1.4 root 1376: TRACE(("aino=\"%s\"\n", a->nname));
1.1.1.3 root 1377: }
1378: return a;
1.1 root 1379: }
1380:
1.1.1.4 root 1381: static uaecptr make_lock (Unit *unit, uae_u32 uniq, long mode)
1.1 root 1382: {
1.1.1.3 root 1383: /* allocate lock from the list kept by the assembly code */
1384: uaecptr lock;
1.1 root 1385:
1.1.1.3 root 1386: lock = get_long (unit->locklist);
1387: put_long (unit->locklist, get_long (lock));
1388: lock += 4;
1.1 root 1389:
1.1.1.7 root 1390: put_long (lock + 4, uniq);
1391: put_long (lock + 8, mode);
1392: put_long (lock + 12, unit->port);
1393: put_long (lock + 16, unit->volume >> 2);
1.1 root 1394:
1395: /* prepend to lock chain */
1.1.1.7 root 1396: put_long (lock, get_long (unit->volume + 28));
1397: put_long (unit->volume + 28, lock >> 2);
1.1 root 1398:
1.1.1.3 root 1399: DUMPLOCK(unit, lock);
1.1 root 1400: return lock;
1401: }
1402:
1.1.1.4 root 1403: static void free_lock (Unit *unit, uaecptr lock)
1.1 root 1404: {
1.1.1.4 root 1405: if (! lock)
1.1 root 1406: return;
1407:
1.1.1.7 root 1408: if (lock == get_long (unit->volume + 28) << 2) {
1409: put_long (unit->volume + 28, get_long (lock));
1.1 root 1410: } else {
1.1.1.7 root 1411: uaecptr current = get_long (unit->volume + 28);
1.1.1.3 root 1412: uaecptr next = 0;
1.1.1.4 root 1413: while (current) {
1.1.1.7 root 1414: next = get_long (current << 2);
1.1.1.4 root 1415: if (lock == next << 2)
1.1 root 1416: break;
1417: current = next;
1418: }
1.1.1.7 root 1419: put_long (current << 2, get_long (lock));
1.1 root 1420: }
1.1.1.3 root 1421: lock -= 4;
1422: put_long (lock, get_long (unit->locklist));
1423: put_long (unit->locklist, lock);
1.1 root 1424: }
1425:
1426: static void
1.1.1.4 root 1427: action_lock (Unit *unit, dpacket packet)
1.1 root 1428: {
1.1.1.3 root 1429: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
1430: uaecptr name = GET_PCK_ARG2 (packet) << 2;
1431: long mode = GET_PCK_ARG3 (packet);
1.1.1.7 root 1432: a_inode *a;
1.1.1.3 root 1433: uae_u32 err;
1.1 root 1434:
1.1.1.13 root 1435: if (mode != SHARED_LOCK && mode != EXCLUSIVE_LOCK) {
1.1.1.4 root 1436: TRACE(("Bad mode.\n"));
1.1.1.13 root 1437: mode = SHARED_LOCK;
1.1.1.3 root 1438: }
1.1 root 1439:
1.1.1.4 root 1440: TRACE(("ACTION_LOCK(0x%lx, \"%s\", %d)\n", lock, bstr (unit, name), mode));
1.1.1.3 root 1441: DUMPLOCK(unit, lock);
1.1 root 1442:
1.1.1.3 root 1443: a = find_aino (unit, lock, bstr (unit, name), &err);
1.1.1.13 root 1444: if (err == 0 && (a->elock || (mode != SHARED_LOCK && a->shlock > 0))) {
1.1.1.3 root 1445: err = ERROR_OBJECT_IN_USE;
1.1 root 1446: }
1.1.1.3 root 1447: /* Lock() doesn't do access checks. */
1448: if (err != 0) {
1449: PUT_PCK_RES1 (packet, DOS_FALSE);
1450: PUT_PCK_RES2 (packet, err);
1451: return;
1452: }
1.1.1.13 root 1453: if (mode == SHARED_LOCK)
1.1.1.3 root 1454: a->shlock++;
1455: else
1456: a->elock = 1;
1457: de_recycle_aino (unit, a);
1458: PUT_PCK_RES1 (packet, make_lock (unit, a->uniq, mode) >> 2);
1.1 root 1459: }
1460:
1.1.1.4 root 1461: static void action_free_lock (Unit *unit, dpacket packet)
1.1 root 1462: {
1.1.1.3 root 1463: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
1.1.1.7 root 1464: a_inode *a;
1.1.1.4 root 1465: TRACE(("ACTION_FREE_LOCK(0x%lx)\n", lock));
1.1.1.3 root 1466: DUMPLOCK(unit, lock);
1.1 root 1467:
1.1.1.3 root 1468: a = lookup_aino (unit, get_long (lock + 4));
1469: if (a == 0) {
1470: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.11 root 1471: PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
1.1.1.3 root 1472: return;
1473: }
1474: if (a->elock)
1475: a->elock = 0;
1476: else
1477: a->shlock--;
1478: recycle_aino (unit, a);
1.1 root 1479: free_lock(unit, lock);
1480:
1.1.1.3 root 1481: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 1482: }
1483:
1484: static void
1.1.1.4 root 1485: action_dup_lock (Unit *unit, dpacket packet)
1.1 root 1486: {
1.1.1.3 root 1487: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
1.1.1.7 root 1488: a_inode *a;
1.1.1.4 root 1489: TRACE(("ACTION_DUP_LOCK(0x%lx)\n", lock));
1.1.1.3 root 1490: DUMPLOCK(unit, lock);
1.1 root 1491:
1.1.1.4 root 1492: if (!lock) {
1.1.1.3 root 1493: PUT_PCK_RES1 (packet, 0);
1.1 root 1494: return;
1495: }
1.1.1.3 root 1496: a = lookup_aino (unit, get_long (lock + 4));
1497: if (a == 0) {
1498: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.11 root 1499: PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
1.1.1.3 root 1500: return;
1.1 root 1501: }
1.1.1.3 root 1502: /* DupLock()ing exclusive locks isn't possible, says the Autodoc, but
1503: * at least the RAM-Handler seems to allow it. Let's see what happens
1504: * if we don't. */
1505: if (a->elock) {
1506: PUT_PCK_RES1 (packet, DOS_FALSE);
1507: PUT_PCK_RES2 (packet, ERROR_OBJECT_IN_USE);
1508: return;
1509: }
1510: a->shlock++;
1511: de_recycle_aino (unit, a);
1512: PUT_PCK_RES1 (packet, make_lock (unit, a->uniq, -2) >> 2);
1.1 root 1513: }
1514:
1515: /* convert time_t to/from AmigaDOS time */
1516: const int secs_per_day = 24 * 60 * 60;
1517: const int diff = (8 * 365 + 2) * (24 * 60 * 60);
1518:
1519: static void
1.1.1.4 root 1520: get_time (time_t t, long* days, long* mins, long* ticks)
1.1 root 1521: {
1522: /* time_t is secs since 1-1-1970 */
1523: /* days since 1-1-1978 */
1524: /* mins since midnight */
1525: /* ticks past minute @ 50Hz */
1526:
1527: t -= diff;
1528: *days = t / secs_per_day;
1529: t -= *days * secs_per_day;
1530: *mins = t / 60;
1531: t -= *mins * 60;
1532: *ticks = t * 50;
1533: }
1534:
1535: static time_t
1.1.1.4 root 1536: put_time (long days, long mins, long ticks)
1.1 root 1537: {
1538: time_t t;
1539: t = ticks / 50;
1540: t += mins * 60;
1541: t += days * secs_per_day;
1542: t += diff;
1543:
1544: return t;
1545: }
1546:
1.1.1.14! root 1547: static void free_exkey (Unit *unit, ExamineKey *ek)
1.1 root 1548: {
1.1.1.14! root 1549: if (--ek->aino->exnext_count == 0) {
! 1550: TRACE (("Freeing ExKey and reducing total_locked from %d by %d\n",
! 1551: unit->total_locked_ainos, ek->aino->locked_children));
! 1552: unit->total_locked_ainos -= ek->aino->locked_children;
! 1553: ek->aino->locked_children = 0;
! 1554: }
1.1.1.3 root 1555: ek->aino = 0;
1556: ek->uniq = 0;
1.1 root 1557: }
1558:
1.1.1.13 root 1559: static ExamineKey *lookup_exkey (Unit *unit, uae_u32 uniq)
1560: {
1561: ExamineKey *ek;
1562: int i;
1563:
1564: ek = unit->examine_keys;
1565: for (i = 0; i < EXKEYS; i++, ek++) {
1566: /* Did we find a free one? */
1567: if (ek->uniq == uniq)
1568: return ek;
1569: }
1570: write_log ("Houston, we have a BIG problem.\n");
1571: return 0;
1572: }
1573:
1.1.1.3 root 1574: /* This is so sick... who invented ACTION_EXAMINE_NEXT? What did he THINK??? */
1.1.1.7 root 1575: static ExamineKey *new_exkey (Unit *unit, a_inode *aino)
1.1 root 1576: {
1.1.1.3 root 1577: uae_u32 uniq;
1.1.1.14! root 1578: uae_u32 oldest = 0xFFFFFFFE;
1.1.1.3 root 1579: ExamineKey *ek, *oldest_ek = 0;
1580: int i;
1581:
1582: ek = unit->examine_keys;
1583: for (i = 0; i < EXKEYS; i++, ek++) {
1584: /* Did we find a free one? */
1585: if (ek->aino == 0)
1586: continue;
1587: if (ek->uniq < oldest)
1588: oldest = (oldest_ek = ek)->uniq;
1589: }
1590: ek = unit->examine_keys;
1591: for (i = 0; i < EXKEYS; i++, ek++) {
1592: /* Did we find a free one? */
1593: if (ek->aino == 0)
1594: goto found;
1595: }
1596: /* This message should usually be harmless. */
1597: write_log ("Houston, we have a problem.\n");
1.1.1.14! root 1598: free_exkey (unit, oldest_ek);
1.1.1.3 root 1599: ek = oldest_ek;
1600: found:
1601:
1602: uniq = unit->next_exkey;
1.1.1.14! root 1603: if (uniq >= 0xFFFFFFFE) {
1.1.1.3 root 1604: /* Things will probably go wrong, but most likely the Amiga will crash
1605: * before this happens because of something else. */
1606: uniq = 1;
1.1 root 1607: }
1.1.1.3 root 1608: unit->next_exkey = uniq+1;
1609: ek->aino = aino;
1.1.1.14! root 1610: ek->curr_file = 0;
1.1 root 1611: ek->uniq = uniq;
1612: return ek;
1613: }
1614:
1.1.1.14! root 1615: static void move_exkeys (Unit *unit, a_inode *from, a_inode *to)
! 1616: {
! 1617: int i;
! 1618: unsigned long tmp = 0;
! 1619: for (i = 0; i < EXKEYS; i++) {
! 1620: ExamineKey *k = unit->examine_keys + i;
! 1621: if (k->uniq == 0)
! 1622: continue;
! 1623: if (k->aino == from) {
! 1624: k->aino = to;
! 1625: tmp++;
! 1626: }
! 1627: }
! 1628: if (tmp != from->exnext_count)
! 1629: write_log ("filesys.c: Bug in ExNext bookkeeping. BAD.\n");
! 1630: to->exnext_count = from->exnext_count;
! 1631: to->locked_children = from->locked_children;
! 1632: from->exnext_count = 0;
! 1633: from->locked_children = 0;
! 1634: }
! 1635:
1.1 root 1636: static void
1.1.1.7 root 1637: get_fileinfo (Unit *unit, dpacket packet, uaecptr info, a_inode *aino)
1.1 root 1638: {
1639: struct stat statbuf;
1640: long days, mins, ticks;
1.1.1.3 root 1641: int i, n;
1642: char *x;
1643:
1644: /* No error checks - this had better work. */
1645: stat (aino->nname, &statbuf);
1646:
1647: if (aino->parent == 0) {
1648: x = unit->ui.volname;
1649: put_long (info + 4, 1);
1650: put_long (info + 120, 1);
1.1 root 1651: } else {
1.1.1.3 root 1652: /* AmigaOS docs say these have to contain the same value. */
1.1.1.7 root 1653: put_long (info + 4, aino->dir ? 2 : -3);
1654: put_long (info + 120, aino->dir ? 2 : -3);
1655: x = aino->aname;
1.1.1.3 root 1656: }
1.1.1.4 root 1657: TRACE(("name=\"%s\"\n", x));
1.1.1.7 root 1658: n = strlen (x);
1.1.1.3 root 1659: if (n > 106)
1660: n = 106;
1661: i = 8;
1.1.1.7 root 1662: put_byte (info + i, n); i++;
1663: while (n--)
1664: put_byte (info + i, *x), i++, x++;
1665: while (i < 108)
1666: put_byte (info + i, 0), i++;
1.1.1.3 root 1667:
1668: put_long (info + 116, aino->amigaos_mode);
1.1.1.7 root 1669: put_long (info + 124, statbuf.st_size);
1.1 root 1670: #ifdef HAVE_ST_BLOCKS
1.1.1.7 root 1671: put_long (info + 128, statbuf.st_blocks);
1.1 root 1672: #else
1.1.1.7 root 1673: put_long (info + 128, statbuf.st_size / 512 + 1);
1.1 root 1674: #endif
1.1.1.7 root 1675: get_time (statbuf.st_mtime, &days, &mins, &ticks);
1676: put_long (info + 132, days);
1677: put_long (info + 136, mins);
1678: put_long (info + 140, ticks);
1679: if (aino->comment == 0)
1680: put_long (info + 144, 0);
1681: else {
1682: TRACE(("comment=\"%s\"\n", aino->comment));
1683: i = 144;
1684: n = strlen (x = aino->comment);
1685: if (n > 78)
1686: n = 78;
1687: put_byte (info + i, n); i++;
1688: while (n--)
1689: put_byte (info + i, *x), i++, x++;
1690: while (i < 224)
1691: put_byte (info + i, 0), i++;
1692: }
1.1.1.3 root 1693: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 1694: }
1695:
1.1.1.4 root 1696: static void action_examine_object (Unit *unit, dpacket packet)
1.1 root 1697: {
1.1.1.3 root 1698: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
1699: uaecptr info = GET_PCK_ARG2 (packet) << 2;
1.1.1.7 root 1700: a_inode *aino = 0;
1.1 root 1701:
1.1.1.4 root 1702: TRACE(("ACTION_EXAMINE_OBJECT(0x%lx,0x%lx)\n", lock, info));
1.1.1.3 root 1703: DUMPLOCK(unit, lock);
1.1 root 1704:
1.1.1.3 root 1705: if (lock != 0)
1.1.1.7 root 1706: aino = lookup_aino (unit, get_long (lock + 4));
1.1.1.3 root 1707: if (aino == 0)
1708: aino = &unit->rootnode;
1709:
1710: get_fileinfo (unit, packet, info, aino);
1711: if (aino->dir) {
1.1.1.7 root 1712: put_long (info, 0xFFFFFFFF);
1.1.1.3 root 1713: } else
1.1.1.7 root 1714: put_long (info, 0);
1.1 root 1715: }
1716:
1.1.1.14! root 1717: /* Read a directory's contents, create a_inodes for each file, and
! 1718: mark them as locked in memory so that recycle_aino will not reap
! 1719: them.
! 1720: We do this to avoid problems with the host OS: we don't want to
! 1721: leave the directory open on the host side until all ExNext()s have
! 1722: finished - they may never finish! */
! 1723:
! 1724: static void populate_directory (Unit *unit, a_inode *base)
! 1725: {
! 1726: DIR *d = opendir (base->nname);
! 1727: a_inode *aino;
! 1728:
! 1729: for (aino = base->child; aino; aino = aino->sibling) {
! 1730: base->locked_children++;
! 1731: unit->total_locked_ainos++;
! 1732: }
! 1733: for (;;) {
! 1734: struct dirent de_space;
! 1735: struct dirent *de;
! 1736: uae_u32 err;
! 1737:
! 1738: /* Find next file that belongs to the Amiga fs (skipping things
! 1739: like "..", "." etc. */
! 1740: do {
! 1741: de = my_readdir (d, &de_space);
! 1742: } while (de && fsdb_name_invalid (de->d_name));
! 1743: if (! de)
! 1744: break;
! 1745: /* This calls init_child_aino, which will notice that the parent is
! 1746: being ExNext()ed, and it will increment the locked counts. */
! 1747: aino = lookup_child_aino_for_exnext (unit, base, de->d_name, &err);
! 1748: }
! 1749: closedir (d);
! 1750: }
! 1751:
! 1752: static void do_examine (Unit *unit, dpacket packet, ExamineKey *ek, uaecptr info)
! 1753: {
! 1754: a_inode *aino;
! 1755:
! 1756: if (ek->curr_file == 0)
! 1757: goto no_more_entries;
! 1758:
! 1759: get_fileinfo (unit, packet, info, ek->curr_file);
! 1760: ek->curr_file = ek->curr_file->sibling;
! 1761: return;
! 1762:
! 1763: no_more_entries:
! 1764: TRACE(("no more entries\n"));
! 1765: free_exkey (unit, ek);
! 1766: PUT_PCK_RES1 (packet, DOS_FALSE);
! 1767: PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES);
! 1768: }
! 1769:
1.1.1.4 root 1770: static void action_examine_next (Unit *unit, dpacket packet)
1.1 root 1771: {
1.1.1.3 root 1772: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
1773: uaecptr info = GET_PCK_ARG2 (packet) << 2;
1.1.1.7 root 1774: a_inode *aino = 0;
1.1.1.3 root 1775: ExamineKey *ek;
1776: uae_u32 uniq;
1.1 root 1777:
1.1.1.4 root 1778: TRACE(("ACTION_EXAMINE_NEXT(0x%lx,0x%lx)\n", lock, info));
1.1.1.3 root 1779: DUMPLOCK(unit, lock);
1.1 root 1780:
1.1.1.3 root 1781: if (lock != 0)
1.1.1.7 root 1782: aino = lookup_aino (unit, get_long (lock + 4));
1.1.1.3 root 1783: if (aino == 0)
1784: aino = &unit->rootnode;
1785:
1786: uniq = get_long (info);
1787: if (uniq == 0) {
1788: write_log ("ExNext called for a file! (Houston?)\n");
1.1.1.14! root 1789: goto no_more_entries;
! 1790: } else if (uniq == 0xFFFFFFFE)
! 1791: goto no_more_entries;
! 1792: else if (uniq == 0xFFFFFFFF) {
! 1793: ek = new_exkey (unit, aino);
! 1794: if (ek) {
! 1795: if (aino->exnext_count++ == 0)
! 1796: populate_directory (unit, aino);
! 1797: }
! 1798: ek->curr_file = aino->child;
1.1.1.3 root 1799: } else
1.1.1.7 root 1800: ek = lookup_exkey (unit, get_long (info));
1.1.1.3 root 1801: if (ek == 0) {
1802: write_log ("Couldn't find a matching ExKey. Prepare for trouble.\n");
1.1.1.14! root 1803: goto no_more_entries;
1.1.1.3 root 1804: }
1.1.1.7 root 1805: put_long (info, ek->uniq);
1806: do_examine (unit, packet, ek, info);
1.1.1.14! root 1807: return;
! 1808:
! 1809: no_more_entries:
! 1810: PUT_PCK_RES1 (packet, DOS_FALSE);
! 1811: PUT_PCK_RES2 (packet, ERROR_NO_MORE_ENTRIES);
1.1 root 1812: }
1813:
1.1.1.4 root 1814: static void do_find (Unit *unit, dpacket packet, int mode, int create, int fallback)
1.1 root 1815: {
1.1.1.3 root 1816: uaecptr fh = GET_PCK_ARG1 (packet) << 2;
1817: uaecptr lock = GET_PCK_ARG2 (packet) << 2;
1818: uaecptr name = GET_PCK_ARG3 (packet) << 2;
1.1.1.7 root 1819: a_inode *aino;
1.1 root 1820: Key *k;
1.1.1.3 root 1821: int fd;
1822: uae_u32 err;
1823: mode_t openmode;
1824: int aino_created = 0;
1825:
1.1.1.4 root 1826: TRACE(("ACTION_FIND_*(0x%lx,0x%lx,\"%s\",%d)\n", fh, lock, bstr (unit, name), mode));
1.1.1.3 root 1827: DUMPLOCK(unit, lock);
1828:
1829: aino = find_aino (unit, lock, bstr (unit, name), &err);
1830:
1.1.1.11 root 1831: if (aino == 0 || (err != 0 && err != ERROR_OBJECT_NOT_AROUND)) {
1.1.1.3 root 1832: /* Whatever it is, we can't handle it. */
1833: PUT_PCK_RES1 (packet, DOS_FALSE);
1834: PUT_PCK_RES2 (packet, err);
1835: return;
1836: }
1837: if (err == 0) {
1838: /* Object exists. */
1839: if (aino->dir) {
1840: PUT_PCK_RES1 (packet, DOS_FALSE);
1841: PUT_PCK_RES2 (packet, ERROR_OBJECT_WRONG_TYPE);
1842: return;
1843: }
1844: if (aino->elock || (create == 2 && aino->shlock > 0)) {
1845: PUT_PCK_RES1 (packet, DOS_FALSE);
1846: PUT_PCK_RES2 (packet, ERROR_OBJECT_IN_USE);
1847: return;
1848: }
1849: if (create == 2 && (aino->amigaos_mode & A_FIBF_DELETE) != 0) {
1850: PUT_PCK_RES1 (packet, DOS_FALSE);
1851: PUT_PCK_RES2 (packet, ERROR_DELETE_PROTECTED);
1852: return;
1853: }
1854: if (create != 2) {
1855: if ((((mode & aino->amigaos_mode) & A_FIBF_WRITE) != 0 || unit->ui.readonly)
1856: && fallback)
1857: {
1858: mode &= ~A_FIBF_WRITE;
1859: }
1860: /* Kick 1.3 doesn't check read and write access bits - maybe it would be
1861: * simpler just not to do that either. */
1862: if ((mode & A_FIBF_WRITE) != 0 && unit->ui.readonly) {
1863: PUT_PCK_RES1 (packet, DOS_FALSE);
1864: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1865: return;
1866: }
1867: if (((mode & aino->amigaos_mode) & A_FIBF_WRITE) != 0
1868: || mode == 0)
1869: {
1870: PUT_PCK_RES1 (packet, DOS_FALSE);
1871: PUT_PCK_RES2 (packet, ERROR_WRITE_PROTECTED);
1872: return;
1873: }
1874: if (((mode & aino->amigaos_mode) & A_FIBF_READ) != 0) {
1875: PUT_PCK_RES1 (packet, DOS_FALSE);
1876: PUT_PCK_RES2 (packet, ERROR_READ_PROTECTED);
1877: return;
1878: }
1879: }
1880: } else if (create == 0) {
1881: PUT_PCK_RES1 (packet, DOS_FALSE);
1882: PUT_PCK_RES2 (packet, err);
1.1 root 1883: return;
1.1.1.3 root 1884: } else {
1885: /* Object does not exist. aino points to containing directory. */
1.1.1.7 root 1886: aino = create_child_aino (unit, aino, my_strdup (bstr_cut (unit, name)), 0);
1.1.1.3 root 1887: if (aino == 0) {
1888: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.6 root 1889: PUT_PCK_RES2 (packet, ERROR_DISK_IS_FULL); /* best we can do */
1.1 root 1890: return;
1891: }
1.1.1.3 root 1892: aino_created = 1;
1.1 root 1893: }
1894:
1.1.1.3 root 1895: prepare_for_open (aino->nname);
1.1 root 1896:
1.1.1.3 root 1897: openmode = (((mode & A_FIBF_READ) == 0 ? O_WRONLY
1898: : (mode & A_FIBF_WRITE) == 0 ? O_RDONLY
1899: : O_RDWR)
1900: | (create ? O_CREAT : 0)
1901: | (create == 2 ? O_TRUNC : 0));
1902:
1903: fd = open (aino->nname, openmode | O_BINARY, 0777);
1904:
1905: if (fd < 0) {
1906: if (aino_created)
1907: delete_aino (unit, aino);
1908: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.7 root 1909: PUT_PCK_RES2 (packet, dos_errno ());
1.1 root 1910: return;
1911: }
1.1.1.3 root 1912: k = new_key (unit);
1913: k->fd = fd;
1914: k->aino = aino;
1.1 root 1915:
1.1.1.3 root 1916: put_long (fh+36, k->uniq);
1917: if (create == 2)
1918: aino->elock = 1;
1919: else
1920: aino->shlock++;
1921: de_recycle_aino (unit, aino);
1922: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 1923: }
1924:
1925: static void
1.1.1.6 root 1926: action_fh_from_lock (Unit *unit, dpacket packet)
1927: {
1928: uaecptr fh = GET_PCK_ARG1 (packet) << 2;
1929: uaecptr lock = GET_PCK_ARG2 (packet) << 2;
1.1.1.7 root 1930: a_inode *aino;
1.1.1.6 root 1931: Key *k;
1932: int fd;
1933: mode_t openmode;
1934: int mode;
1935:
1936: TRACE(("ACTION_FH_FROM_LOCK(0x%lx,0x%lx)\n",fh,lock));
1937: DUMPLOCK(unit,lock);
1938:
1939: if (!lock) {
1.1.1.7 root 1940: PUT_PCK_RES1 (packet, DOS_FALSE);
1941: PUT_PCK_RES2 (packet, 0);
1942: return;
1.1.1.6 root 1943: }
1944:
1945: aino = lookup_aino (unit, get_long (lock + 4));
1946: if (aino == 0)
1.1.1.7 root 1947: aino = &unit->rootnode;
1.1.1.6 root 1948: mode = aino->amigaos_mode; /* Use same mode for opened filehandle as existing Lock() */
1949:
1950: prepare_for_open (aino->nname);
1951:
1952: openmode = (((mode & A_FIBF_READ) == 0 ? O_WRONLY
1953: : (mode & A_FIBF_WRITE) == 0 ? O_RDONLY
1954: : O_RDWR));
1955:
1.1.1.8 root 1956: /* the files on CD really can have the write-bit set. */
1957: if (unit->ui.readonly)
1958: openmode = O_RDONLY;
1959:
1.1.1.6 root 1960: fd = open (aino->nname, openmode | O_BINARY, 0777);
1961:
1962: if (fd < 0) {
1963: PUT_PCK_RES1 (packet, DOS_FALSE);
1964: PUT_PCK_RES2 (packet, dos_errno());
1965: return;
1966: }
1967: k = new_key (unit);
1968: k->fd = fd;
1969: k->aino = aino;
1970:
1971: put_long (fh+36, k->uniq);
1972: /* I don't think I need to play with shlock count here, because I'm
1973: opening from an existing lock ??? */
1974:
1975: /* Is this right? I don't completely understand how this works. Do I
1976: also need to free_lock() my lock, since nobody else is going to? */
1977: de_recycle_aino (unit, aino);
1978: PUT_PCK_RES1 (packet, DOS_TRUE);
1979: /* PUT_PCK_RES2 (packet, k->uniq); - this shouldn't be necessary, try without it */
1980: }
1981:
1982: static void
1.1.1.4 root 1983: action_find_input (Unit *unit, dpacket packet)
1.1 root 1984: {
1.1.1.3 root 1985: do_find(unit, packet, A_FIBF_READ|A_FIBF_WRITE, 0, 1);
1.1 root 1986: }
1987:
1988: static void
1.1.1.4 root 1989: action_find_output (Unit *unit, dpacket packet)
1.1 root 1990: {
1.1.1.3 root 1991: if (unit->ui.readonly) {
1992: PUT_PCK_RES1 (packet, DOS_FALSE);
1993: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 1994: return;
1995: }
1.1.1.3 root 1996: do_find(unit, packet, A_FIBF_READ|A_FIBF_WRITE, 2, 0);
1.1 root 1997: }
1998:
1999: static void
1.1.1.4 root 2000: action_find_write (Unit *unit, dpacket packet)
1.1 root 2001: {
1.1.1.3 root 2002: if (unit->ui.readonly) {
2003: PUT_PCK_RES1 (packet, DOS_FALSE);
2004: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2005: return;
2006: }
1.1.1.3 root 2007: do_find(unit, packet, A_FIBF_READ|A_FIBF_WRITE, 1, 0);
1.1 root 2008: }
2009:
2010: static void
1.1.1.4 root 2011: action_end (Unit *unit, dpacket packet)
1.1 root 2012: {
2013: Key *k;
1.1.1.4 root 2014: TRACE(("ACTION_END(0x%lx)\n", GET_PCK_ARG1 (packet)));
1.1 root 2015:
1.1.1.3 root 2016: k = lookup_key (unit, GET_PCK_ARG1 (packet));
2017: if (k != 0) {
2018: if (k->aino->elock)
2019: k->aino->elock = 0;
2020: else
2021: k->aino->shlock--;
2022: recycle_aino (unit, k->aino);
2023: free_key (unit, k);
2024: }
2025: PUT_PCK_RES1 (packet, DOS_TRUE);
2026: PUT_PCK_RES2 (packet, 0);
1.1 root 2027: }
2028:
2029: static void
1.1.1.4 root 2030: action_read (Unit *unit, dpacket packet)
1.1 root 2031: {
1.1.1.3 root 2032: Key *k = lookup_key (unit, GET_PCK_ARG1 (packet));
2033: uaecptr addr = GET_PCK_ARG2 (packet);
2034: long size = (uae_s32)GET_PCK_ARG3 (packet);
1.1 root 2035: int actual;
2036:
1.1.1.3 root 2037: if (k == 0) {
2038: PUT_PCK_RES1 (packet, DOS_FALSE);
2039: /* PUT_PCK_RES2 (packet, EINVAL); */
2040: return;
2041: }
1.1.1.4 root 2042: TRACE(("ACTION_READ(%s,0x%lx,%ld)\n",k->aino->nname,addr,size));
1.1 root 2043: #ifdef RELY_ON_LOADSEG_DETECTION
1.1.1.3 root 2044: /* HACK HACK HACK HACK
1.1 root 2045: * Try to detect a LoadSeg() */
2046: if (k->file_pos == 0 && size >= 4) {
2047: unsigned char buf[4];
2048: off_t currpos = lseek(k->fd, 0, SEEK_CUR);
2049: read(k->fd, buf, 4);
2050: lseek(k->fd, currpos, SEEK_SET);
2051: if (buf[0] == 0 && buf[1] == 0 && buf[2] == 3 && buf[3] == 0xF3)
2052: possible_loadseg();
2053: }
2054: #endif
2055: if (valid_address (addr, size)) {
1.1.1.3 root 2056: uae_u8 *realpt;
1.1 root 2057: realpt = get_real_address (addr);
2058: actual = read(k->fd, realpt, size);
2059:
1.1.1.2 root 2060: if (actual == 0) {
1.1.1.3 root 2061: PUT_PCK_RES1 (packet, 0);
2062: PUT_PCK_RES2 (packet, 0);
1.1.1.2 root 2063: } else if (actual < 0) {
1.1.1.3 root 2064: PUT_PCK_RES1 (packet, 0);
2065: PUT_PCK_RES2 (packet, dos_errno());
1.1 root 2066: } else {
1.1.1.3 root 2067: PUT_PCK_RES1 (packet, actual);
1.1 root 2068: k->file_pos += actual;
2069: }
2070: } else {
2071: char *buf;
1.1.1.4 root 2072: write_log ("unixfs warning: Bad pointer passed for read: %08x\n", addr);
1.1 root 2073: /* ugh this is inefficient but easy */
2074: buf = (char *)malloc(size);
1.1.1.4 root 2075: if (!buf) {
1.1.1.3 root 2076: PUT_PCK_RES1 (packet, -1);
2077: PUT_PCK_RES2 (packet, ERROR_NO_FREE_STORE);
1.1 root 2078: return;
2079: }
2080: actual = read(k->fd, buf, size);
2081:
1.1.1.2 root 2082: if (actual < 0) {
1.1.1.3 root 2083: PUT_PCK_RES1 (packet, 0);
2084: PUT_PCK_RES2 (packet, dos_errno());
1.1 root 2085: } else {
2086: int i;
1.1.1.3 root 2087: PUT_PCK_RES1 (packet, actual);
1.1.1.4 root 2088: for (i = 0; i < actual; i++)
1.1 root 2089: put_byte(addr + i, buf[i]);
2090: k->file_pos += actual;
2091: }
1.1.1.4 root 2092: free (buf);
1.1 root 2093: }
2094: }
2095:
2096: static void
1.1.1.4 root 2097: action_write (Unit *unit, dpacket packet)
1.1 root 2098: {
1.1.1.3 root 2099: Key *k = lookup_key (unit, GET_PCK_ARG1 (packet));
2100: uaecptr addr = GET_PCK_ARG2 (packet);
2101: long size = GET_PCK_ARG3 (packet);
1.1 root 2102: char *buf;
2103: int i;
2104:
1.1.1.3 root 2105: if (k == 0) {
2106: PUT_PCK_RES1 (packet, DOS_FALSE);
2107: /* PUT_PCK_RES2 (packet, EINVAL); */
2108: return;
2109: }
1.1 root 2110:
1.1.1.4 root 2111: TRACE(("ACTION_WRITE(%s,0x%lx,%ld)\n",k->aino->nname,addr,size));
1.1.1.3 root 2112:
2113: if (unit->ui.readonly) {
2114: PUT_PCK_RES1 (packet, DOS_FALSE);
2115: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2116: return;
2117: }
2118:
2119: /* ugh this is inefficient but easy */
2120: buf = (char *)malloc(size);
1.1.1.3 root 2121: if (!buf) {
2122: PUT_PCK_RES1 (packet, -1);
2123: PUT_PCK_RES2 (packet, ERROR_NO_FREE_STORE);
1.1 root 2124: return;
2125: }
2126:
1.1.1.3 root 2127: for (i = 0; i < size; i++)
1.1 root 2128: buf[i] = get_byte(addr + i);
2129:
1.1.1.3 root 2130: PUT_PCK_RES1 (packet, write(k->fd, buf, size));
2131: if (GET_PCK_RES1 (packet) != size)
2132: PUT_PCK_RES2 (packet, dos_errno ());
2133: if (GET_PCK_RES1 (packet) >= 0)
2134: k->file_pos += GET_PCK_RES1 (packet);
1.1 root 2135:
1.1.1.4 root 2136: free (buf);
1.1 root 2137: }
2138:
2139: static void
1.1.1.4 root 2140: action_seek (Unit *unit, dpacket packet)
1.1 root 2141: {
1.1.1.4 root 2142: Key *k = lookup_key (unit, GET_PCK_ARG1 (packet));
1.1.1.3 root 2143: long pos = (uae_s32)GET_PCK_ARG2 (packet);
2144: long mode = (uae_s32)GET_PCK_ARG3 (packet);
1.1 root 2145: off_t res;
2146: long old;
2147: int whence = SEEK_CUR;
2148:
1.1.1.3 root 2149: if (k == 0) {
2150: PUT_PCK_RES1 (packet, -1);
2151: PUT_PCK_RES2 (packet, ERROR_INVALID_LOCK);
2152: return;
2153: }
1.1 root 2154:
1.1.1.3 root 2155: if (mode > 0) whence = SEEK_END;
2156: if (mode < 0) whence = SEEK_SET;
1.1 root 2157:
1.1.1.4 root 2158: TRACE(("ACTION_SEEK(%s,%d,%d)\n", k->aino->nname, pos, mode));
1.1.1.3 root 2159:
2160: old = lseek (k->fd, 0, SEEK_CUR);
2161: res = lseek (k->fd, pos, whence);
2162:
2163: if (-1 == res) {
2164: PUT_PCK_RES1 (packet, res);
2165: PUT_PCK_RES2 (packet, ERROR_SEEK_ERROR);
2166: } else
2167: PUT_PCK_RES1 (packet, old);
1.1 root 2168: k->file_pos = res;
2169: }
2170:
2171: static void
1.1.1.4 root 2172: action_set_protect (Unit *unit, dpacket packet)
1.1 root 2173: {
1.1.1.3 root 2174: uaecptr lock = GET_PCK_ARG2 (packet) << 2;
2175: uaecptr name = GET_PCK_ARG3 (packet) << 2;
2176: uae_u32 mask = GET_PCK_ARG4 (packet);
1.1.1.7 root 2177: a_inode *a;
1.1.1.3 root 2178: uae_u32 err;
1.1 root 2179:
1.1.1.4 root 2180: TRACE(("ACTION_SET_PROTECT(0x%lx,\"%s\",0x%lx)\n", lock, bstr (unit, name), mask));
1.1 root 2181:
1.1.1.3 root 2182: if (unit->ui.readonly) {
2183: PUT_PCK_RES1 (packet, DOS_FALSE);
2184: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2185: return;
2186: }
2187:
1.1.1.3 root 2188: a = find_aino (unit, lock, bstr (unit, name), &err);
2189: if (err != 0) {
2190: PUT_PCK_RES1 (packet, DOS_FALSE);
2191: PUT_PCK_RES2 (packet, err);
1.1 root 2192: return;
2193: }
2194:
1.1.1.7 root 2195: err = fsdb_set_file_attrs (a, mask);
1.1.1.3 root 2196: if (err != 0) {
2197: PUT_PCK_RES1 (packet, DOS_FALSE);
2198: PUT_PCK_RES2 (packet, err);
2199: } else {
2200: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1.1.2 root 2201: }
1.1.1.3 root 2202: }
1.1 root 2203:
1.1.1.7 root 2204: static void action_set_comment (Unit * unit, dpacket packet)
2205: {
2206: uaecptr lock = GET_PCK_ARG2 (packet) << 2;
2207: uaecptr name = GET_PCK_ARG3 (packet) << 2;
2208: uaecptr comment = GET_PCK_ARG4 (packet) << 2;
2209: char *commented;
2210: a_inode *a;
2211: uae_u32 err;
2212: long res1, res2;
2213:
2214: if (unit->ui.readonly) {
2215: PUT_PCK_RES1 (packet, DOS_FALSE);
2216: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
2217: return;
2218: }
2219:
2220: commented = bstr (unit, comment);
2221: commented = strlen (commented) > 0 ? my_strdup (commented) : 0;
2222: TRACE (("ACTION_SET_COMMENT(0x%lx,\"%s\")\n", lock, commented));
2223:
2224: a = find_aino (unit, lock, bstr (unit, name), &err);
2225: if (err != 0) {
2226: PUT_PCK_RES1 (packet, DOS_FALSE);
2227: PUT_PCK_RES2 (packet, err);
2228:
2229: maybe_free_and_out:
2230: if (commented)
2231: free (commented);
2232: return;
2233: }
2234: PUT_PCK_RES1 (packet, DOS_TRUE);
2235: PUT_PCK_RES2 (packet, 0);
2236: if (a->comment == 0 && commented == 0)
2237: goto maybe_free_and_out;
2238: if (a->comment != 0 && commented != 0 && strcmp (a->comment, commented) == 0)
2239: goto maybe_free_and_out;
2240: if (a->comment)
2241: free (a->comment);
2242: a->comment = commented;
2243: a->dirty = 1;
2244: }
2245:
1.1.1.3 root 2246: static void
1.1.1.4 root 2247: action_same_lock (Unit *unit, dpacket packet)
1.1.1.3 root 2248: {
2249: uaecptr lock1 = GET_PCK_ARG1 (packet) << 2;
2250: uaecptr lock2 = GET_PCK_ARG2 (packet) << 2;
1.1 root 2251:
1.1.1.4 root 2252: TRACE(("ACTION_SAME_LOCK(0x%lx,0x%lx)\n",lock1,lock2));
1.1.1.3 root 2253: DUMPLOCK(unit, lock1); DUMPLOCK(unit, lock2);
1.1 root 2254:
1.1.1.3 root 2255: if (!lock1 || !lock2) {
2256: PUT_PCK_RES1 (packet, lock1 == lock2 ? DOS_TRUE : DOS_FALSE);
1.1 root 2257: } else {
1.1.1.3 root 2258: PUT_PCK_RES1 (packet, get_long (lock1 + 4) == get_long (lock2 + 4) ? DOS_TRUE : DOS_FALSE);
1.1 root 2259: }
2260: }
2261:
2262: static void
1.1.1.6 root 2263: action_change_mode (Unit *unit, dpacket packet)
1.1 root 2264: {
1.1.1.6 root 2265: #define CHANGE_LOCK 0
2266: #define CHANGE_FH 1
2267: /* will be CHANGE_FH or CHANGE_LOCK value */
2268: long type = GET_PCK_ARG1 (packet);
2269: /* either a file-handle or lock */
2270: uaecptr object = GET_PCK_ARG2 (packet) << 2;
2271: /* will be EXCLUSIVE_LOCK/SHARED_LOCK if CHANGE_LOCK,
2272: * or MODE_OLDFILE/MODE_NEWFILE/MODE_READWRITE if CHANGE_FH */
2273: long mode = GET_PCK_ARG3 (packet);
1.1.1.8 root 2274: unsigned long uniq;
1.1.1.7 root 2275: a_inode *a = NULL, *olda = NULL;
1.1.1.6 root 2276: uae_u32 err = 0;
2277: TRACE(("ACTION_CHANGE_MODE(0x%lx,%d,%d)\n",object,type,mode));
1.1.1.13 root 2278:
1.1.1.6 root 2279: if (! object
2280: || (type != CHANGE_FH && type != CHANGE_LOCK))
2281: {
1.1.1.7 root 2282: PUT_PCK_RES1 (packet, DOS_FALSE);
2283: PUT_PCK_RES2 (packet, ERROR_INVALID_LOCK);
2284: return;
1.1.1.6 root 2285: }
1.1 root 2286:
1.1.1.6 root 2287: /* @@@ Brian: shouldn't this be good enough to support
2288: CHANGE_FH? */
2289: if (type == CHANGE_FH)
2290: mode = (mode == 1006 ? -1 : -2);
1.1.1.8 root 2291:
2292: if (type == CHANGE_LOCK)
1.1.1.13 root 2293: uniq = get_long (object + 4);
1.1.1.8 root 2294: else {
2295: Key *k = lookup_key (unit, object);
2296: if (!k) {
2297: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.11 root 2298: PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
1.1.1.8 root 2299: return;
2300: }
1.1.1.13 root 2301: uniq = k->aino->uniq;
1.1.1.8 root 2302: }
2303: a = lookup_aino (unit, uniq);
2304:
1.1.1.6 root 2305: if (! a)
2306: err = ERROR_INVALID_LOCK;
2307: else {
2308: if (mode == -1) {
2309: if (a->shlock > 1)
2310: err = ERROR_OBJECT_IN_USE;
2311: else {
2312: a->shlock = 0;
2313: a->elock = 1;
2314: }
2315: } else { /* Must be SHARED_LOCK == -2 */
2316: a->elock = 0;
2317: a->shlock++;
2318: }
1.1.1.13 root 2319: }
1.1.1.6 root 2320:
2321: if (err) {
1.1.1.7 root 2322: PUT_PCK_RES1 (packet, DOS_FALSE);
2323: PUT_PCK_RES2 (packet, err);
2324: return;
1.1.1.6 root 2325: } else {
1.1.1.7 root 2326: de_recycle_aino (unit, a);
2327: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1.1.3 root 2328: }
1.1.1.6 root 2329: }
1.1.1.3 root 2330:
1.1.1.6 root 2331: static void
1.1.1.8 root 2332: action_parent_common (Unit *unit, dpacket packet, unsigned long uniq)
1.1.1.6 root 2333: {
1.1.1.8 root 2334: a_inode *olda = lookup_aino (unit, uniq);
1.1.1.3 root 2335: if (olda == 0) {
2336: PUT_PCK_RES1 (packet, DOS_FALSE);
2337: PUT_PCK_RES2 (packet, ERROR_INVALID_LOCK);
2338: return;
2339: }
2340:
2341: if (olda->parent == 0) {
2342: PUT_PCK_RES1 (packet, 0);
2343: PUT_PCK_RES2 (packet, 0);
2344: return;
1.1 root 2345: }
1.1.1.3 root 2346: if (olda->parent->elock) {
2347: PUT_PCK_RES1 (packet, DOS_FALSE);
2348: PUT_PCK_RES2 (packet, ERROR_OBJECT_IN_USE);
2349: return;
2350: }
2351: olda->parent->shlock++;
2352: de_recycle_aino (unit, olda->parent);
2353: PUT_PCK_RES1 (packet, make_lock (unit, olda->parent->uniq, -2) >> 2);
1.1 root 2354: }
2355:
2356: static void
1.1.1.6 root 2357: action_parent_fh (Unit *unit, dpacket packet)
2358: {
1.1.1.8 root 2359: Key *k = lookup_key (unit, GET_PCK_ARG1 (packet));
2360: if (!k) {
1.1.1.7 root 2361: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.11 root 2362: PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
1.1.1.7 root 2363: return;
1.1.1.6 root 2364: }
1.1.1.8 root 2365: action_parent_common (unit, packet, k->aino->uniq);
1.1.1.6 root 2366: }
2367:
2368: static void
2369: action_parent (Unit *unit, dpacket packet)
2370: {
2371: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
2372:
2373: TRACE(("ACTION_PARENT(0x%lx)\n",lock));
2374:
2375: if (!lock) {
2376: PUT_PCK_RES1 (packet, 0);
2377: PUT_PCK_RES2 (packet, 0);
2378: return;
2379: }
2380: action_parent_common (unit, packet, get_long (lock + 4));
2381: }
2382:
2383: static void
1.1.1.4 root 2384: action_create_dir (Unit *unit, dpacket packet)
1.1 root 2385: {
1.1.1.3 root 2386: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
2387: uaecptr name = GET_PCK_ARG2 (packet) << 2;
1.1.1.7 root 2388: a_inode *aino;
1.1.1.3 root 2389: uae_u32 err;
1.1 root 2390:
1.1.1.4 root 2391: TRACE(("ACTION_CREATE_DIR(0x%lx,\"%s\")\n", lock, bstr (unit, name)));
1.1 root 2392:
1.1.1.3 root 2393: if (unit->ui.readonly) {
2394: PUT_PCK_RES1 (packet, DOS_FALSE);
2395: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2396: return;
2397: }
2398:
1.1.1.3 root 2399: aino = find_aino (unit, lock, bstr (unit, name), &err);
1.1.1.11 root 2400: if (aino == 0 || (err != 0 && err != ERROR_OBJECT_NOT_AROUND)) {
1.1.1.3 root 2401: PUT_PCK_RES1 (packet, DOS_FALSE);
2402: PUT_PCK_RES2 (packet, err);
1.1 root 2403: return;
2404: }
1.1.1.3 root 2405: if (err == 0) {
2406: /* Object exists. */
2407: PUT_PCK_RES1 (packet, DOS_FALSE);
2408: PUT_PCK_RES2 (packet, ERROR_OBJECT_EXISTS);
2409: return;
1.1 root 2410: }
1.1.1.3 root 2411: /* Object does not exist. aino points to containing directory. */
1.1.1.7 root 2412: aino = create_child_aino (unit, aino, my_strdup (bstr_cut (unit, name)), 1);
1.1.1.3 root 2413: if (aino == 0) {
2414: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.6 root 2415: PUT_PCK_RES2 (packet, ERROR_DISK_IS_FULL); /* best we can do */
1.1.1.3 root 2416: return;
2417: }
2418:
2419: if (mkdir (aino->nname, 0777) == -1) {
2420: PUT_PCK_RES1 (packet, DOS_FALSE);
2421: PUT_PCK_RES2 (packet, dos_errno());
2422: return;
2423: }
2424: aino->shlock = 1;
2425: de_recycle_aino (unit, aino);
2426: PUT_PCK_RES1 (packet, make_lock (unit, aino->uniq, -2) >> 2);
1.1 root 2427: }
2428:
2429: static void
1.1.1.4 root 2430: action_examine_fh (Unit *unit, dpacket packet)
1.1 root 2431: {
1.1.1.3 root 2432: Key *k;
1.1.1.7 root 2433: a_inode *aino = 0;
1.1.1.3 root 2434: uaecptr info = GET_PCK_ARG2 (packet) << 2;
1.1 root 2435:
1.1.1.6 root 2436: TRACE(("ACTION_EXAMINE_FH(0x%lx,0x%lx)\n",
2437: GET_PCK_ARG1 (packet), GET_PCK_ARG2 (packet) ));
1.1 root 2438:
1.1.1.3 root 2439: k = lookup_key (unit, GET_PCK_ARG1 (packet));
2440: if (k != 0)
2441: aino = k->aino;
2442: if (aino == 0)
2443: aino = &unit->rootnode;
2444:
2445: get_fileinfo (unit, packet, info, aino);
2446: if (aino->dir)
1.1.1.6 root 2447: put_long (info, 0xFFFFFFFF);
1.1.1.3 root 2448: else
1.1.1.6 root 2449: put_long (info, 0);
1.1.1.3 root 2450: }
2451:
2452: /* For a nice example of just how contradictory documentation can be, see the
2453: * Autodoc for DOS:SetFileSize and the Packets.txt description of this packet...
2454: * This implementation tries to mimic the behaviour of the Kick 3.1 ramdisk
2455: * (which seems to match the Autodoc description). */
2456: static void
1.1.1.4 root 2457: action_set_file_size (Unit *unit, dpacket packet)
1.1.1.3 root 2458: {
2459: Key *k, *k1;
2460: off_t offset = GET_PCK_ARG2 (packet);
2461: long mode = (uae_s32)GET_PCK_ARG3 (packet);
2462: int whence = SEEK_CUR;
1.1.1.13 root 2463:
1.1.1.3 root 2464: if (mode > 0) whence = SEEK_END;
2465: if (mode < 0) whence = SEEK_SET;
1.1 root 2466:
1.1.1.4 root 2467: TRACE(("ACTION_SET_FILE_SIZE(0x%lx, %d, 0x%x)\n", GET_PCK_ARG1 (packet), offset, mode));
1.1 root 2468:
1.1.1.3 root 2469: k = lookup_key (unit, GET_PCK_ARG1 (packet));
2470: if (k == 0) {
2471: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1.1.11 root 2472: PUT_PCK_RES2 (packet, ERROR_OBJECT_NOT_AROUND);
1.1 root 2473: return;
2474: }
1.1.1.3 root 2475:
2476: /* If any open files have file pointers beyond this size, truncate only
2477: * so far that these pointers do not become invalid. */
2478: for (k1 = unit->keys; k1; k1 = k1->next) {
2479: if (k != k1 && k->aino == k1->aino) {
2480: if (k1->file_pos > offset)
2481: offset = k1->file_pos;
2482: }
2483: }
2484:
2485: /* Write one then truncate: that should give the right size in all cases. */
2486: offset = lseek (k->fd, offset, whence);
2487: write (k->fd, /* whatever */(char *)&k1, 1);
2488: if (k->file_pos > offset)
2489: k->file_pos = offset;
2490: lseek (k->fd, k->file_pos, SEEK_SET);
2491:
1.1.1.6 root 2492: /* Brian: no bug here; the file _must_ be one byte too large after writing
2493: The write is supposed to guarantee that the file can't be smaller than
2494: the requested size, the truncate guarantees that it can't be larger.
2495: If we were to write one byte earlier we'd clobber file data. */
2496: if (truncate (k->aino->nname, offset) == -1) {
1.1.1.3 root 2497: PUT_PCK_RES1 (packet, DOS_FALSE);
2498: PUT_PCK_RES2 (packet, dos_errno ());
1.1 root 2499: return;
2500: }
1.1.1.3 root 2501:
2502: PUT_PCK_RES1 (packet, offset);
2503: PUT_PCK_RES2 (packet, 0);
1.1 root 2504: }
2505:
2506: static void
1.1.1.4 root 2507: action_delete_object (Unit *unit, dpacket packet)
1.1 root 2508: {
1.1.1.3 root 2509: uaecptr lock = GET_PCK_ARG1 (packet) << 2;
2510: uaecptr name = GET_PCK_ARG2 (packet) << 2;
1.1.1.7 root 2511: a_inode *a;
1.1.1.3 root 2512: uae_u32 err;
1.1 root 2513:
1.1.1.4 root 2514: TRACE(("ACTION_DELETE_OBJECT(0x%lx,\"%s\")\n", lock, bstr (unit, name)));
1.1 root 2515:
1.1.1.3 root 2516: if (unit->ui.readonly) {
2517: PUT_PCK_RES1 (packet, DOS_FALSE);
2518: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2519: return;
2520: }
2521:
1.1.1.3 root 2522: a = find_aino (unit, lock, bstr (unit, name), &err);
1.1 root 2523:
1.1.1.3 root 2524: if (err != 0) {
2525: PUT_PCK_RES1 (packet, DOS_FALSE);
2526: PUT_PCK_RES2 (packet, err);
1.1 root 2527: return;
2528: }
1.1.1.7 root 2529: if (a->amigaos_mode & A_FIBF_DELETE) {
2530: PUT_PCK_RES1 (packet, DOS_FALSE);
2531: PUT_PCK_RES2 (packet, ERROR_DELETE_PROTECTED);
2532: return;
2533: }
1.1.1.3 root 2534: if (a->shlock > 0 || a->elock) {
2535: PUT_PCK_RES1 (packet, DOS_FALSE);
2536: PUT_PCK_RES2 (packet, ERROR_OBJECT_IN_USE);
1.1 root 2537: return;
2538: }
1.1.1.3 root 2539: if (a->dir) {
1.1.1.11 root 2540: /* This should take care of removing the fsdb if no files remain. */
2541: fsdb_dir_writeback (a);
1.1.1.3 root 2542: if (rmdir (a->nname) == -1) {
2543: PUT_PCK_RES1 (packet, DOS_FALSE);
2544: PUT_PCK_RES2 (packet, dos_errno());
1.1 root 2545: return;
2546: }
2547: } else {
1.1.1.3 root 2548: if (unlink (a->nname) == -1) {
2549: PUT_PCK_RES1 (packet, DOS_FALSE);
2550: PUT_PCK_RES2 (packet, dos_errno());
1.1 root 2551: return;
2552: }
2553: }
1.1.1.3 root 2554: if (a->child != 0) {
2555: write_log ("Serious error in action_delete_object.\n");
2556: } else {
2557: delete_aino (unit, a);
2558: }
2559: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2560: }
2561:
2562: static void
1.1.1.4 root 2563: action_set_date (Unit *unit, dpacket packet)
1.1 root 2564: {
1.1.1.3 root 2565: uaecptr lock = GET_PCK_ARG2 (packet) << 2;
2566: uaecptr name = GET_PCK_ARG3 (packet) << 2;
2567: uaecptr date = GET_PCK_ARG4 (packet);
1.1.1.7 root 2568: a_inode *a;
1.1 root 2569: struct utimbuf ut;
1.1.1.3 root 2570: uae_u32 err;
1.1 root 2571:
1.1.1.4 root 2572: TRACE(("ACTION_SET_DATE(0x%lx,\"%s\")\n", lock, bstr (unit, name)));
1.1 root 2573:
1.1.1.4 root 2574: if (unit->ui.readonly) {
1.1.1.3 root 2575: PUT_PCK_RES1 (packet, DOS_FALSE);
2576: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2577: return;
2578: }
2579:
1.1.1.6 root 2580: ut.actime = ut.modtime = put_time(get_long (date), get_long (date + 4),
2581: get_long (date + 8));
1.1.1.3 root 2582: a = find_aino (unit, lock, bstr (unit, name), &err);
2583: if (err == 0 && utime (a->nname, &ut) == -1)
2584: err = dos_errno ();
2585: if (err != 0) {
2586: PUT_PCK_RES1 (packet, DOS_FALSE);
2587: PUT_PCK_RES2 (packet, err);
2588: } else
2589: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2590: }
2591:
2592: static void
1.1.1.4 root 2593: action_rename_object (Unit *unit, dpacket packet)
1.1 root 2594: {
1.1.1.3 root 2595: uaecptr lock1 = GET_PCK_ARG1 (packet) << 2;
2596: uaecptr name1 = GET_PCK_ARG2 (packet) << 2;
2597: uaecptr lock2 = GET_PCK_ARG3 (packet) << 2;
2598: uaecptr name2 = GET_PCK_ARG4 (packet) << 2;
1.1.1.7 root 2599: a_inode *a1, *a2;
1.1.1.3 root 2600: uae_u32 err1, err2;
1.1 root 2601:
1.1.1.4 root 2602: TRACE(("ACTION_RENAME_OBJECT(0x%lx,\"%s\",", lock1, bstr (unit, name1)));
2603: TRACE(("0x%lx,\"%s\")\n", lock2, bstr (unit, name2)));
1.1 root 2604:
1.1.1.4 root 2605: if (unit->ui.readonly) {
1.1.1.3 root 2606: PUT_PCK_RES1 (packet, DOS_FALSE);
2607: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2608: return;
2609: }
2610:
1.1.1.3 root 2611: a1 = find_aino (unit, lock1, bstr (unit, name1), &err1);
2612: if (err1 != 0) {
2613: PUT_PCK_RES1 (packet, DOS_FALSE);
2614: PUT_PCK_RES2 (packet, err1);
2615: return;
2616: }
1.1.1.7 root 2617: /* See whether the other name already exists in the filesystem. */
1.1.1.3 root 2618: a2 = find_aino (unit, lock2, bstr (unit, name2), &err2);
1.1.1.7 root 2619: if (a2 == a1) {
2620: /* Renaming to the same name, but possibly different case. */
2621: if (strcmp (a1->aname, bstr_cut (unit, name2)) == 0) {
2622: /* Exact match -> do nothing. */
2623: PUT_PCK_RES1 (packet, DOS_TRUE);
2624: return;
2625: }
2626: a2 = a2->parent;
1.1.1.11 root 2627: } else if (a2 == 0 || err2 != ERROR_OBJECT_NOT_AROUND) {
1.1.1.3 root 2628: PUT_PCK_RES1 (packet, DOS_FALSE);
2629: PUT_PCK_RES2 (packet, err2 == 0 ? ERROR_OBJECT_EXISTS : err2);
1.1 root 2630: return;
2631: }
1.1.1.7 root 2632:
2633: a2 = create_child_aino (unit, a2, bstr_cut (unit, name2), a1->dir);
1.1.1.3 root 2634: if (a2 == 0) {
2635: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.6 root 2636: PUT_PCK_RES2 (packet, ERROR_DISK_IS_FULL); /* best we can do */
1.1 root 2637: return;
2638: }
2639:
1.1.1.3 root 2640: /* @@@ what should we do if there are locks on a1? */
1.1.1.5 root 2641: if (-1 == rename (a1->nname, a2->nname)) {
1.1.1.3 root 2642: PUT_PCK_RES1 (packet, DOS_FALSE);
1.1.1.5 root 2643: PUT_PCK_RES2 (packet, dos_errno ());
1.1 root 2644: return;
2645: }
1.1.1.7 root 2646: a2->comment = a1->comment;
2647: a1->comment = 0;
2648: a2->amigaos_mode = a1->amigaos_mode;
1.1.1.14! root 2649: a2->uniq = a1->uniq;
! 2650: move_exkeys (unit, a1, a2);
1.1.1.3 root 2651: move_aino_children (unit, a1, a2);
2652: delete_aino (unit, a1);
2653: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2654: }
2655:
2656: static void
1.1.1.4 root 2657: action_current_volume (Unit *unit, dpacket packet)
1.1 root 2658: {
1.1.1.3 root 2659: PUT_PCK_RES1 (packet, unit->volume >> 2);
1.1 root 2660: }
2661:
2662: static void
1.1.1.4 root 2663: action_rename_disk (Unit *unit, dpacket packet)
1.1 root 2664: {
1.1.1.3 root 2665: uaecptr name = GET_PCK_ARG1 (packet) << 2;
1.1 root 2666: int i;
2667: int namelen;
2668:
1.1.1.4 root 2669: TRACE(("ACTION_RENAME_DISK(\"%s\")\n", bstr (unit, name)));
1.1 root 2670:
1.1.1.4 root 2671: if (unit->ui.readonly) {
1.1.1.3 root 2672: PUT_PCK_RES1 (packet, DOS_FALSE);
2673: PUT_PCK_RES2 (packet, ERROR_DISK_WRITE_PROTECTED);
1.1 root 2674: return;
2675: }
2676:
2677: /* get volume name */
1.1.1.3 root 2678: namelen = get_byte (name); name++;
2679: free (unit->ui.volname);
2680: unit->ui.volname = (char *) xmalloc (namelen + 1);
1.1.1.4 root 2681: for (i = 0; i < namelen; i++, name++)
1.1.1.3 root 2682: unit->ui.volname[i] = get_byte (name);
1.1 root 2683: unit->ui.volname[i] = 0;
2684:
1.1.1.3 root 2685: put_byte (unit->volume + 44, namelen);
1.1.1.4 root 2686: for (i = 0; i < namelen; i++)
1.1.1.3 root 2687: put_byte (unit->volume + 45 + i, unit->ui.volname[i]);
1.1 root 2688:
1.1.1.3 root 2689: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2690: }
2691:
2692: static void
1.1.1.4 root 2693: action_is_filesystem (Unit *unit, dpacket packet)
1.1 root 2694: {
1.1.1.3 root 2695: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2696: }
2697:
2698: static void
1.1.1.4 root 2699: action_flush (Unit *unit, dpacket packet)
1.1 root 2700: {
2701: /* sync(); */ /* pretty drastic, eh */
1.1.1.3 root 2702: PUT_PCK_RES1 (packet, DOS_TRUE);
1.1 root 2703: }
2704:
1.1.1.3 root 2705: /* We don't want multiple interrupts to be active at the same time. I don't
2706: * know whether AmigaOS takes care of that, but this does. */
2707: static uae_sem_t singlethread_int_sem;
2708:
2709: static uae_u32 exter_int_helper (void)
2710: {
1.1.1.4 root 2711: UnitInfo *uip = current_mountinfo->ui;
1.1.1.7 root 2712: uaecptr port;
1.1.1.3 root 2713: static int unit_no;
2714:
2715: switch (m68k_dreg (regs, 0)) {
2716: case 0:
2717: /* Determine whether a given EXTER interrupt is for us. */
2718: if (uae_int_requested) {
2719: if (uae_sem_trywait (&singlethread_int_sem) != 0)
2720: /* Pretend it isn't for us. We might get it again later. */
2721: return 0;
2722: /* Clear the interrupt flag _before_ we do any processing.
2723: * That way, we can get too many interrupts, but never not
2724: * enough. */
2725: uae_int_requested = 0;
2726: unit_no = 0;
2727: return 1;
2728: }
1.1 root 2729: return 0;
1.1.1.3 root 2730: case 1:
2731: /* Release a message_lock. This is called as soon as the message is
2732: * received by the assembly code. We use the opportunity to check
2733: * whether we have some locks that we can give back to the assembler
2734: * code.
2735: * Note that this is called from the main loop, unlike the other cases
2736: * in this switch statement which are called from the interrupt handler.
2737: */
1.1.1.7 root 2738: #ifdef UAE_FILESYS_THREADS
1.1.1.3 root 2739: {
2740: Unit *unit = find_unit (m68k_areg (regs, 5));
2741: unit->cmds_complete = unit->cmds_acked;
2742: while (comm_pipe_has_data (unit->ui.back_pipe)) {
2743: uaecptr locks, lockend;
2744: locks = read_comm_pipe_int_blocking (unit->ui.back_pipe);
2745: lockend = locks;
2746: while (get_long (lockend) != 0)
2747: lockend = get_long (lockend);
2748: put_long (lockend, get_long (m68k_areg (regs, 3)));
2749: put_long (m68k_areg (regs, 3), locks);
2750: }
2751: }
1.1.1.7 root 2752: #else
2753: write_log ("exter_int_helper should not be called with arg 1!\n");
2754: #endif
1.1 root 2755: break;
1.1.1.3 root 2756: case 2:
1.1.1.7 root 2757: /* Find work that needs to be done:
2758: * return d0 = 0: none
2759: * d0 = 1: PutMsg(), port in a0, message in a1
2760: * d0 = 2: Signal(), task in a1, signal set in d1
2761: * d0 = 3: ReplyMsg(), message in a1 */
2762:
2763: #ifdef SUPPORT_THREADS
2764: /* First, check signals/messages */
2765: while (comm_pipe_has_data (&native2amiga_pending)) {
2766: switch (read_comm_pipe_int_blocking (&native2amiga_pending)) {
2767: case 0: /* Signal() */
2768: m68k_areg (regs, 1) = read_comm_pipe_u32_blocking (&native2amiga_pending);
2769: m68k_dreg (regs, 1) = read_comm_pipe_u32_blocking (&native2amiga_pending);
2770: return 2;
2771:
2772: case 1: /* PutMsg() */
2773: m68k_areg (regs, 0) = read_comm_pipe_u32_blocking (&native2amiga_pending);
2774: m68k_areg (regs, 1) = read_comm_pipe_u32_blocking (&native2amiga_pending);
2775: return 1;
2776:
2777: case 2: /* ReplyMsg() */
2778: m68k_areg (regs, 1) = read_comm_pipe_u32_blocking (&native2amiga_pending);
2779: return 3;
2780:
2781: default:
2782: write_log ("exter_int_helper: unknown native action\n");
2783: break;
2784: }
2785: }
2786: #endif
2787:
1.1.1.3 root 2788: /* Find some unit that needs a message sent, and return its port,
2789: * or zero if all are done.
2790: * Take care not to dereference self for units that didn't have their
2791: * startup packet sent. */
2792: for (;;) {
1.1.1.4 root 2793: if (unit_no >= current_mountinfo->num_units)
1.1.1.3 root 2794: return 0;
1.1.1.7 root 2795:
1.1.1.4 root 2796: if (uip[unit_no].self != 0
2797: && uip[unit_no].self->cmds_acked == uip[unit_no].self->cmds_complete
2798: && uip[unit_no].self->cmds_acked != uip[unit_no].self->cmds_sent)
1.1.1.3 root 2799: break;
2800: unit_no++;
2801: }
1.1.1.4 root 2802: uip[unit_no].self->cmds_acked = uip[unit_no].self->cmds_sent;
1.1.1.7 root 2803: port = uip[unit_no].self->port;
2804: if (port) {
2805: m68k_areg (regs, 0) = port;
2806: m68k_areg (regs, 1) = find_unit (port)->dummy_message;
2807: unit_no++;
2808: return 1;
1.1.1.3 root 2809: }
1.1 root 2810: break;
1.1.1.3 root 2811: case 4:
2812: /* Exit the interrupt, and release the single-threading lock. */
2813: uae_sem_post (&singlethread_int_sem);
1.1 root 2814: break;
2815:
1.1.1.3 root 2816: default:
2817: write_log ("Shouldn't happen in exter_int_helper.\n");
1.1 root 2818: break;
1.1.1.3 root 2819: }
2820: return 0;
2821: }
1.1 root 2822:
1.1.1.3 root 2823: static int handle_packet (Unit *unit, dpacket pck)
2824: {
2825: uae_s32 type = GET_PCK_TYPE (pck);
2826: PUT_PCK_RES2 (pck, 0);
2827: switch (type) {
1.1.1.4 root 2828: case ACTION_LOCATE_OBJECT: action_lock (unit, pck); break;
2829: case ACTION_FREE_LOCK: action_free_lock (unit, pck); break;
2830: case ACTION_COPY_DIR: action_dup_lock (unit, pck); break;
2831: case ACTION_DISK_INFO: action_disk_info (unit, pck); break;
2832: case ACTION_INFO: action_info (unit, pck); break;
2833: case ACTION_EXAMINE_OBJECT: action_examine_object (unit, pck); break;
2834: case ACTION_EXAMINE_NEXT: action_examine_next (unit, pck); break;
2835: case ACTION_FIND_INPUT: action_find_input (unit, pck); break;
2836: case ACTION_FIND_WRITE: action_find_write (unit, pck); break;
2837: case ACTION_FIND_OUTPUT: action_find_output (unit, pck); break;
2838: case ACTION_END: action_end (unit, pck); break;
2839: case ACTION_READ: action_read (unit, pck); break;
2840: case ACTION_WRITE: action_write (unit, pck); break;
2841: case ACTION_SEEK: action_seek (unit, pck); break;
2842: case ACTION_SET_PROTECT: action_set_protect (unit, pck); break;
1.1.1.7 root 2843: case ACTION_SET_COMMENT: action_set_comment (unit, pck); break;
1.1.1.4 root 2844: case ACTION_SAME_LOCK: action_same_lock (unit, pck); break;
2845: case ACTION_PARENT: action_parent (unit, pck); break;
2846: case ACTION_CREATE_DIR: action_create_dir (unit, pck); break;
2847: case ACTION_DELETE_OBJECT: action_delete_object (unit, pck); break;
2848: case ACTION_RENAME_OBJECT: action_rename_object (unit, pck); break;
2849: case ACTION_SET_DATE: action_set_date (unit, pck); break;
2850: case ACTION_CURRENT_VOLUME: action_current_volume (unit, pck); break;
2851: case ACTION_RENAME_DISK: action_rename_disk (unit, pck); break;
2852: case ACTION_IS_FILESYSTEM: action_is_filesystem (unit, pck); break;
2853: case ACTION_FLUSH: action_flush (unit, pck); break;
1.1.1.3 root 2854:
2855: /* 2.0+ packet types */
1.1.1.4 root 2856: case ACTION_SET_FILE_SIZE: action_set_file_size (unit, pck); break;
2857: case ACTION_EXAMINE_FH: action_examine_fh (unit, pck); break;
1.1.1.6 root 2858: case ACTION_FH_FROM_LOCK: action_fh_from_lock (unit, pck); break;
2859: case ACTION_CHANGE_MODE: action_change_mode (unit, pck); break;
2860: case ACTION_PARENT_FH: action_parent_fh (unit, pck); break;
1.1.1.3 root 2861:
2862: /* unsupported packets */
2863: case ACTION_LOCK_RECORD:
2864: case ACTION_FREE_RECORD:
2865: case ACTION_COPY_DIR_FH:
2866: case ACTION_EXAMINE_ALL:
2867: case ACTION_MAKE_LINK:
2868: case ACTION_READ_LINK:
2869: case ACTION_FORMAT:
2870: case ACTION_ADD_NOTIFY:
2871: case ACTION_REMOVE_NOTIFY:
2872: default:
1.1.1.4 root 2873: TRACE(("*** UNSUPPORTED PACKET %ld\n", type));
1.1.1.3 root 2874: return 0;
2875: }
2876: return 1;
2877: }
1.1 root 2878:
1.1.1.3 root 2879: #ifdef UAE_FILESYS_THREADS
1.1.1.13 root 2880: static void *filesys_thread (void *unit_v)
1.1.1.3 root 2881: {
2882: UnitInfo *ui = (UnitInfo *)unit_v;
2883: for (;;) {
2884: uae_u8 *pck;
2885: uae_u8 *msg;
2886: uae_u32 morelocks;
2887: int i;
2888:
2889: pck = (uae_u8 *)read_comm_pipe_pvoid_blocking (ui->unit_pipe);
2890: msg = (uae_u8 *)read_comm_pipe_pvoid_blocking (ui->unit_pipe);
2891: morelocks = (uae_u32)read_comm_pipe_int_blocking (ui->unit_pipe);
2892:
1.1.1.4 root 2893: if (ui->reset_state == FS_GO_DOWN) {
1.1.1.3 root 2894: if (pck != 0)
2895: continue;
2896: /* Death message received. */
1.1.1.4 root 2897: uae_sem_post (&ui->reset_sync_sem);
2898: /* Die. */
2899: return 0;
1.1.1.3 root 2900: }
1.1 root 2901:
1.1.1.3 root 2902: put_long (get_long (morelocks), get_long (ui->self->locklist));
2903: put_long (ui->self->locklist, morelocks);
2904: if (! handle_packet (ui->self, pck)) {
2905: PUT_PCK_RES1 (pck, DOS_FALSE);
2906: PUT_PCK_RES2 (pck, ERROR_ACTION_NOT_KNOWN);
2907: }
2908: /* Mark the packet as processed for the list scan in the assembly code. */
2909: do_put_mem_long ((uae_u32 *)(msg + 4), -1);
2910: /* Acquire the message lock, so that we know we can safely send the
2911: * message. */
2912: ui->self->cmds_sent++;
2913: /* The message is sent by our interrupt handler, so make sure an interrupt
2914: * happens. */
2915: uae_int_requested = 1;
2916: /* Send back the locks. */
2917: if (get_long (ui->self->locklist) != 0)
1.1.1.7 root 2918: write_comm_pipe_int (ui->back_pipe, (int)(get_long (ui->self->locklist)), 0);
1.1.1.3 root 2919: put_long (ui->self->locklist, 0);
2920: }
2921: return 0;
2922: }
2923: #endif
1.1 root 2924:
1.1.1.3 root 2925: /* Talk about spaghetti code... */
1.1.1.4 root 2926: static uae_u32 filesys_handler (void)
1.1.1.3 root 2927: {
2928: Unit *unit = find_unit (m68k_areg (regs, 5));
2929: uaecptr packet_addr = m68k_dreg (regs, 3);
2930: uaecptr message_addr = m68k_areg (regs, 4);
2931: uae_u8 *pck;
2932: uae_u8 *msg;
2933: if (! valid_address (packet_addr, 36) || ! valid_address (message_addr, 14)) {
2934: write_log ("Bad address passed for packet.\n");
2935: goto error2;
2936: }
2937: pck = get_real_address (packet_addr);
2938: msg = get_real_address (message_addr);
2939:
1.1.1.4 root 2940: #if 0
1.1.1.3 root 2941: if (unit->reset_state == FS_GO_DOWN)
2942: /* You might as well queue it, if you live long enough */
2943: return 1;
1.1.1.4 root 2944: #endif
1.1.1.3 root 2945:
2946: do_put_mem_long ((uae_u32 *)(msg + 4), -1);
2947: if (!unit || !unit->volume) {
2948: write_log ("Filesystem was not initialized.\n");
2949: goto error;
2950: }
2951: #ifdef UAE_FILESYS_THREADS
2952: {
2953: /* Get two more locks and hand them over to the other thread. */
2954: uae_u32 morelocks;
2955: morelocks = get_long (m68k_areg (regs, 3));
2956: put_long (m68k_areg (regs, 3), get_long (get_long (morelocks)));
2957: put_long (get_long (morelocks), 0);
2958:
2959: /* The packet wasn't processed yet. */
2960: do_put_mem_long ((uae_u32 *)(msg + 4), 0);
2961: write_comm_pipe_pvoid (unit->ui.unit_pipe, (void *)pck, 0);
2962: write_comm_pipe_pvoid (unit->ui.unit_pipe, (void *)msg, 0);
2963: write_comm_pipe_int (unit->ui.unit_pipe, (int)morelocks, 1);
2964: /* Don't reply yet. */
2965: return 1;
2966: }
2967: #endif
1.1 root 2968:
1.1.1.3 root 2969: if (! handle_packet (unit, pck)) {
2970: error:
2971: PUT_PCK_RES1 (pck, DOS_FALSE);
2972: PUT_PCK_RES2 (pck, ERROR_ACTION_NOT_KNOWN);
2973: }
1.1.1.4 root 2974: TRACE(("reply: %8lx, %ld\n", GET_PCK_RES1 (pck), GET_PCK_RES2 (pck)));
1.1 root 2975:
1.1.1.3 root 2976: error2:
1.1 root 2977:
1.1.1.3 root 2978: return 0;
2979: }
1.1 root 2980:
1.1.1.11 root 2981: static int current_deviceno = 0;
1.1.1.13 root 2982: static int current_cdrom = 0;
1.1.1.11 root 2983:
2984: static void reset_uaedevices (void)
2985: {
2986: current_deviceno = 0;
1.1.1.13 root 2987: current_cdrom = 0;
1.1.1.11 root 2988: }
2989:
2990: static int get_new_device (char **devname, uaecptr *devname_amiga, int cdrom)
2991: {
1.1.1.13 root 2992: int result;
1.1.1.11 root 2993: char buffer[80];
2994:
1.1.1.13 root 2995: if (cdrom) {
2996: sprintf (buffer, "CD%d", current_cdrom);
2997: result = current_cdrom++;
2998: } else {
2999: sprintf (buffer, "DH%d", current_deviceno);
3000: result = current_deviceno++;
3001: }
1.1.1.11 root 3002:
3003: *devname_amiga = ds (*devname = my_strdup (buffer));
1.1.1.13 root 3004: return result;
1.1.1.11 root 3005: }
3006:
1.1.1.4 root 3007: void filesys_start_threads (void)
3008: {
3009: UnitInfo *uip;
3010: int i;
3011:
3012: current_mountinfo = dup_mountinfo (currprefs.mountinfo);
3013:
3014: reset_uaedevices ();
3015:
3016: uip = current_mountinfo->ui;
3017: for (i = 0; i < current_mountinfo->num_units; i++) {
3018: uip[i].unit_pipe = 0;
1.1.1.11 root 3019: uip[i].devno = get_new_device (&uip[i].devname, &uip[i].devname_amiga, 0);
1.1.1.4 root 3020:
3021: #ifdef UAE_FILESYS_THREADS
3022: if (! is_hardfile (current_mountinfo, i)) {
3023: uip[i].unit_pipe = (smp_comm_pipe *)xmalloc (sizeof (smp_comm_pipe));
3024: uip[i].back_pipe = (smp_comm_pipe *)xmalloc (sizeof (smp_comm_pipe));
3025: init_comm_pipe (uip[i].unit_pipe, 50, 3);
3026: init_comm_pipe (uip[i].back_pipe, 50, 1);
1.1.1.13 root 3027: uae_start_thread (filesys_thread, (void *)(uip + i), &uip[i].tid);
1.1.1.4 root 3028: }
3029: #endif
3030: }
3031: }
3032:
1.1.1.3 root 3033: void filesys_reset (void)
3034: {
3035: Unit *u, *u1;
1.1 root 3036:
1.1.1.4 root 3037: /* We get called once from customreset at the beginning of the program
3038: * before filesys_start_threads has been called. Survive that. */
3039: if (current_mountinfo == 0)
3040: return;
1.1 root 3041:
1.1.1.4 root 3042: for (u = units; u; u = u1) {
1.1.1.3 root 3043: u1 = u->next;
3044: free (u);
1.1 root 3045: }
1.1.1.3 root 3046: unit_num = 0;
3047: units = 0;
1.1.1.4 root 3048:
3049: free_mountinfo (current_mountinfo);
3050: current_mountinfo = 0;
1.1.1.3 root 3051: }
1.1 root 3052:
1.1.1.3 root 3053: void filesys_prepare_reset (void)
3054: {
1.1.1.4 root 3055: UnitInfo *uip = current_mountinfo->ui;
3056: Unit *u;
1.1.1.3 root 3057: int i;
1.1 root 3058:
1.1.1.3 root 3059: #ifdef UAE_FILESYS_THREADS
1.1.1.4 root 3060: for (i = 0; i < current_mountinfo->num_units; i++) {
3061: if (uip[i].unit_pipe != 0) {
3062: uae_sem_init (&uip[i].reset_sync_sem, 0, 0);
3063: uip[i].reset_state = FS_GO_DOWN;
1.1.1.3 root 3064: /* send death message */
1.1.1.4 root 3065: write_comm_pipe_int (uip[i].unit_pipe, 0, 0);
3066: write_comm_pipe_int (uip[i].unit_pipe, 0, 0);
3067: write_comm_pipe_int (uip[i].unit_pipe, 0, 1);
3068: uae_sem_wait (&uip[i].reset_sync_sem);
1.1.1.3 root 3069: }
3070: }
3071: #endif
3072: u = units;
3073: while (u != 0) {
3074: while (u->rootnode.next != &u->rootnode) {
1.1.1.13 root 3075: a_inode *b;
1.1.1.7 root 3076: a_inode *a = u->rootnode.next;
1.1.1.3 root 3077: u->rootnode.next = a->next;
1.1.1.13 root 3078: de_recycle_aino (u, a);
3079: dispose_aino (u, &b, a);
1.1.1.3 root 3080: }
3081: u = u->next;
3082: }
1.1 root 3083: }
3084:
1.1.1.4 root 3085: static uae_u32 filesys_diagentry (void)
1.1 root 3086: {
1.1.1.7 root 3087: uaecptr resaddr = m68k_areg (regs, 2) + 0x10;
3088: uaecptr start = resaddr;
3089: uaecptr residents, tmp;
1.1.1.3 root 3090:
1.1.1.4 root 3091: TRACE (("filesystem: diagentry called\n"));
1.1.1.3 root 3092:
1.1.1.7 root 3093: filesys_configdev = m68k_areg (regs, 3);
1.1.1.3 root 3094:
3095: do_put_mem_long ((uae_u32 *)(filesysory + 0x2100), EXPANSION_explibname);
3096: do_put_mem_long ((uae_u32 *)(filesysory + 0x2104), filesys_configdev);
3097: do_put_mem_long ((uae_u32 *)(filesysory + 0x2108), EXPANSION_doslibname);
1.1.1.4 root 3098: do_put_mem_long ((uae_u32 *)(filesysory + 0x210c), current_mountinfo->num_units);
1.1.1.3 root 3099:
3100: uae_sem_init (&singlethread_int_sem, 0, 1);
1.1 root 3101: if (ROM_hardfile_resid != 0) {
3102: /* Build a struct Resident. This will set up and initialize
3103: * the uae.device */
1.1.1.7 root 3104: put_word (resaddr + 0x0, 0x4AFC);
3105: put_long (resaddr + 0x2, resaddr);
3106: put_long (resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
3107: put_word (resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
3108: put_word (resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
3109: put_long (resaddr + 0xE, ROM_hardfile_resname);
3110: put_long (resaddr + 0x12, ROM_hardfile_resid);
3111: put_long (resaddr + 0x16, ROM_hardfile_init); /* calls filesys_init */
1.1 root 3112: }
3113: resaddr += 0x1A;
1.1.1.7 root 3114: tmp = resaddr;
3115:
1.1.1.2 root 3116: /* The good thing about this function is that it always gets called
3117: * when we boot. So we could put all sorts of stuff that wants to be done
1.1.1.7 root 3118: * here.
3119: * We can simply add more Resident structures here. Although the Amiga OS
3120: * only knows about the one at address DiagArea + 0x10, we scan for other
3121: * Resident structures and call InitResident() for them at the end of the
3122: * diag entry. */
3123:
3124: resaddr = scsidev_startup(resaddr);
3125: native2amiga_startup();
3126:
3127: /* scan for Residents and return pointer to array of them */
3128: residents = resaddr;
3129: while (tmp < residents && tmp > start) {
3130: if (get_word (tmp) == 0x4AFC &&
3131: get_long (tmp + 0x2) == tmp) {
3132: put_word (resaddr, 0x227C); /* movea.l #tmp,a1 */
3133: put_long (resaddr + 2, tmp);
3134: put_word (resaddr + 6, 0x7200); /* moveq.l #0,d1 */
3135: put_long (resaddr + 8, 0x4EAEFF9A); /* jsr -$66(a6) ; InitResident */
3136: resaddr += 12;
3137: tmp = get_long (tmp + 0x6);
3138: } else {
3139: tmp++;
3140: }
3141: }
3142: put_word (resaddr, 0x7001); /* moveq.l #1,d0 */
3143: put_word (resaddr + 2, RTS);
1.1 root 3144:
1.1.1.7 root 3145: m68k_areg (regs, 0) = residents;
1.1.1.3 root 3146: return 1;
1.1 root 3147: }
3148:
1.1.1.3 root 3149: /* Remember a pointer AmigaOS gave us so we can later use it to identify
3150: * which unit a given startup message belongs to. */
1.1.1.4 root 3151: static uae_u32 filesys_dev_remember (void)
1.1.1.3 root 3152: {
3153: int unit_no = m68k_dreg (regs, 6);
3154: uaecptr devicenode = m68k_areg (regs, 3);
3155:
1.1.1.4 root 3156: current_mountinfo->ui[unit_no].startup = get_long (devicenode + 28);
1.1.1.3 root 3157: return devicenode;
3158: }
3159:
3160: /* Fill in per-unit fields of a parampacket */
1.1.1.4 root 3161: static uae_u32 filesys_dev_storeinfo (void)
1.1.1.3 root 3162: {
1.1.1.4 root 3163: UnitInfo *uip = current_mountinfo->ui;
1.1.1.3 root 3164: int unit_no = m68k_dreg (regs, 6);
3165: uaecptr parmpacket = m68k_areg (regs, 0);
3166:
1.1.1.4 root 3167: put_long (parmpacket, current_mountinfo->ui[unit_no].devname_amiga);
3168: put_long (parmpacket + 4, is_hardfile (current_mountinfo, unit_no) ? ROM_hardfile_resname : fsdevname);
3169: put_long (parmpacket + 8, uip[unit_no].devno);
1.1.1.3 root 3170: put_long (parmpacket + 12, 0); /* Device flags */
3171: put_long (parmpacket + 16, 16); /* Env. size */
1.1.1.6 root 3172: put_long (parmpacket + 20, uip[unit_no].hf.blocksize >> 2); /* longwords per block */
1.1.1.3 root 3173: put_long (parmpacket + 24, 0); /* unused */
1.1.1.4 root 3174: put_long (parmpacket + 28, uip[unit_no].hf.surfaces); /* heads */
1.1.1.3 root 3175: put_long (parmpacket + 32, 0); /* unused */
1.1.1.4 root 3176: put_long (parmpacket + 36, uip[unit_no].hf.secspertrack); /* sectors per track */
3177: put_long (parmpacket + 40, uip[unit_no].hf.reservedblocks); /* reserved blocks */
1.1.1.3 root 3178: put_long (parmpacket + 44, 0); /* unused */
3179: put_long (parmpacket + 48, 0); /* interleave */
3180: put_long (parmpacket + 52, 0); /* lowCyl */
1.1.1.4 root 3181: put_long (parmpacket + 56, uip[unit_no].hf.nrcyls - 1); /* hiCyl */
1.1.1.6 root 3182: put_long (parmpacket + 60, 50); /* Number of buffers */
1.1.1.3 root 3183: put_long (parmpacket + 64, 0); /* Buffer mem type */
3184: put_long (parmpacket + 68, 0x7FFFFFFF); /* largest transfer */
3185: put_long (parmpacket + 72, ~1); /* addMask (?) */
3186: put_long (parmpacket + 76, (uae_u32)-1); /* bootPri */
3187: put_long (parmpacket + 80, 0x444f5300); /* DOS\0 */
3188: put_long (parmpacket + 84, 0); /* pad */
3189:
1.1.1.4 root 3190: return is_hardfile (current_mountinfo, unit_no);
1.1 root 3191: }
3192:
1.1.1.3 root 3193: void filesys_install (void)
1.1 root 3194: {
3195: int i;
1.1.1.3 root 3196: uaecptr loop;
3197:
1.1.1.4 root 3198: TRACE (("Installing filesystem\n"));
1.1 root 3199:
3200: ROM_filesys_resname = ds("UAEunixfs.resource");
1.1.1.3 root 3201: ROM_filesys_resid = ds("UAE unixfs 0.4");
1.1 root 3202:
1.1.1.4 root 3203: fsdevname = ds ("uae.device"); /* does not really exist */
1.1 root 3204:
3205: ROM_filesys_diagentry = here();
1.1.1.7 root 3206: calltrap (deftrap(filesys_diagentry));
3207: dw(0x4ED0); /* JMP (a0) - jump to code that inits Residents */
1.1.1.3 root 3208:
3209: loop = here ();
3210: /* Special trap for the assembly make_dev routine */
1.1.1.4 root 3211: org (0xF0FF20);
1.1.1.3 root 3212: calltrap (deftrap (filesys_dev_remember));
1.1.1.4 root 3213: dw (RTS);
1.1.1.3 root 3214:
1.1.1.4 root 3215: org (0xF0FF28);
1.1.1.3 root 3216: calltrap (deftrap (filesys_dev_storeinfo));
1.1.1.4 root 3217: dw (RTS);
1.1.1.3 root 3218:
1.1.1.4 root 3219: org (0xF0FF30);
1.1.1.3 root 3220: calltrap (deftrap (filesys_handler));
1.1.1.4 root 3221: dw (RTS);
1.1.1.3 root 3222:
1.1.1.4 root 3223: org (0xF0FF40);
1.1.1.3 root 3224: calltrap (deftrap (startup_handler));
1.1.1.4 root 3225: dw (RTS);
1.1.1.3 root 3226:
1.1.1.4 root 3227: org (0xF0FF50);
1.1.1.3 root 3228: calltrap (deftrap (exter_int_helper));
1.1.1.4 root 3229: dw (RTS);
1.1.1.3 root 3230:
3231: org (loop);
3232: }
3233:
3234: void filesys_install_code (void)
3235: {
1.1 root 3236: align(4);
3237:
1.1.1.3 root 3238: /* The last offset comes from the code itself, look for it near the top. */
3239: EXPANSION_bootcode = here () + 8 + 0x14;
3240: /* Ouch. Make sure this is _always_ a multiple of two bytes. */
1.1.1.7 root 3241: filesys_initcode = here() + 8 + 0x28;
1.1.1.3 root 3242: db(0x00); db(0x00); db(0x00); db(0x10); db(0x00); db(0x00); db(0x00); db(0x00);
1.1.1.7 root 3243: db(0x60); db(0x00); db(0x01); db(0xd4); db(0x00); db(0x00); db(0x01); db(0x3e);
3244: db(0x00); db(0x00); db(0x00); db(0x28); db(0x00); db(0x00); db(0x00); db(0xbc);
3245: db(0x00); db(0x00); db(0x00); db(0x14); db(0x43); db(0xfa); db(0x03); db(0x11);
1.1.1.3 root 3246: db(0x4e); db(0xae); db(0xff); db(0xa0); db(0x20); db(0x40); db(0x20); db(0x28);
3247: db(0x00); db(0x16); db(0x20); db(0x40); db(0x4e); db(0x90); db(0x4e); db(0x75);
1.1.1.7 root 3248: db(0x48); db(0xe7); db(0xff); db(0xfe); db(0x2c); db(0x78); db(0x00); db(0x04);
3249: db(0x2a); db(0x79); db(0x00); db(0xf0); db(0xff); db(0xfc); db(0x43); db(0xfa);
3250: db(0x02); db(0xfb); db(0x70); db(0x24); db(0x7a); db(0x00); db(0x4e); db(0xae);
3251: db(0xfd); db(0xd8); db(0x4a); db(0x80); db(0x66); db(0x0c); db(0x43); db(0xfa);
3252: db(0x02); db(0xeb); db(0x70); db(0x00); db(0x7a); db(0x01); db(0x4e); db(0xae);
3253: db(0xfd); db(0xd8); db(0x28); db(0x40); db(0x70); db(0x58); db(0x72); db(0x01);
3254: db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x26); db(0x40); db(0x7e); db(0x54);
3255: db(0x27); db(0xb5); db(0x78); db(0x00); db(0x78); db(0x00); db(0x59); db(0x87);
3256: db(0x64); db(0xf6); db(0x7c); db(0x00); db(0xbc); db(0xad); db(0x01); db(0x0c);
3257: db(0x64); db(0x14); db(0x20); db(0x4b); db(0x48); db(0xe7); db(0x02); db(0x10);
3258: db(0x7e); db(0x01); db(0x61); db(0x00); db(0x00); db(0xc2); db(0x4c); db(0xdf);
3259: db(0x08); db(0x40); db(0x52); db(0x86); db(0x60); db(0xe6); db(0x2c); db(0x78);
3260: db(0x00); db(0x04); db(0x22); db(0x4c); db(0x4e); db(0xae); db(0xfe); db(0x62);
3261: db(0x61); db(0x00); db(0x00); db(0x7c); db(0x2c); db(0x78); db(0x00); db(0x04);
1.1.1.3 root 3262: db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x80); db(0x72); db(0x03);
3263: db(0x74); db(0xf6); db(0x20); db(0x7c); db(0x00); db(0x20); db(0x00); db(0x00);
3264: db(0x90); db(0x88); db(0x65); db(0x0a); db(0x67); db(0x08); db(0x78); db(0x00);
3265: db(0x22); db(0x44); db(0x4e); db(0xae); db(0xfd); db(0x96); db(0x4c); db(0xdf);
1.1.1.7 root 3266: db(0x7f); db(0xff); db(0x4e); db(0x75); db(0x48); db(0xe7); db(0x00); db(0x20);
3267: db(0x70); db(0x00); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50);
3268: db(0x4a); db(0x80); db(0x67); db(0x3c); db(0x2c); db(0x78); db(0x00); db(0x04);
3269: db(0x70); db(0x02); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50);
3270: db(0x0c); db(0x80); db(0x00); db(0x00); db(0x00); db(0x01); db(0x6d); db(0x1e);
3271: db(0x6e); db(0x06); db(0x4e); db(0xae); db(0xfe); db(0x92); db(0x60); db(0xe8);
3272: db(0x0c); db(0x80); db(0x00); db(0x00); db(0x00); db(0x02); db(0x6e); db(0x08);
3273: db(0x20); db(0x01); db(0x4e); db(0xae); db(0xfe); db(0xbc); db(0x60); db(0xd8);
3274: db(0x4e); db(0xae); db(0xfe); db(0x86); db(0x60); db(0xd2); db(0x70); db(0x04);
3275: db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x50); db(0x70); db(0x01);
3276: db(0x4c); db(0xdf); db(0x04); db(0x00); db(0x4e); db(0x75); db(0x2c); db(0x78);
3277: db(0x00); db(0x04); db(0x70); db(0x1a); db(0x22); db(0x3c); db(0x00); db(0x01);
3278: db(0x00); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40);
3279: db(0x41); db(0xfa); db(0x01); db(0xf6); db(0x23); db(0x48); db(0x00); db(0x0a);
3280: db(0x41); db(0xfa); db(0xff); db(0x92); db(0x23); db(0x48); db(0x00); db(0x0e);
3281: db(0x41); db(0xfa); db(0xff); db(0x8a); db(0x23); db(0x48); db(0x00); db(0x12);
3282: db(0x70); db(0x0d); db(0x4e); db(0xee); db(0xff); db(0x58); db(0x2a); db(0x79);
3283: db(0x00); db(0xf0); db(0xff); db(0xfc); db(0x4e); db(0xb9); db(0x00); db(0xf0);
3284: db(0xff); db(0x28); db(0x26); db(0x00); db(0xc0); db(0x85); db(0x66); db(0x00);
3285: db(0xff); db(0x6a); db(0x2c); db(0x4c); db(0x4e); db(0xae); db(0xff); db(0x70);
3286: db(0x26); db(0x40); db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x20);
3287: db(0x70); db(0x00); db(0x27); db(0x40); db(0x00); db(0x08); db(0x27); db(0x40);
3288: db(0x00); db(0x10); db(0x27); db(0x40); db(0x00); db(0x20); db(0x4a); db(0x83);
3289: db(0x66); db(0x1c); db(0x27); db(0x7c); db(0x00); db(0x00); db(0x0f); db(0xa0);
3290: db(0x00); db(0x14); db(0x43); db(0xfa); db(0xfe); db(0x80); db(0x20); db(0x09);
3291: db(0xe4); db(0x88); db(0x27); db(0x40); db(0x00); db(0x20); db(0x27); db(0x7c);
3292: db(0xff); db(0xff); db(0xff); db(0xff); db(0x00); db(0x24); db(0x4a); db(0x87);
3293: db(0x67); db(0x36); db(0x2c); db(0x78); db(0x00); db(0x04); db(0x70); db(0x14);
3294: db(0x72); db(0x00); db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x22); db(0x40);
3295: db(0x70); db(0x00); db(0x22); db(0x80); db(0x23); db(0x40); db(0x00); db(0x04);
3296: db(0x33); db(0x40); db(0x00); db(0x0e); db(0x30); db(0x3c); db(0x10); db(0xff);
3297: db(0x90); db(0x06); db(0x33); db(0x40); db(0x00); db(0x08); db(0x23); db(0x6d);
3298: db(0x01); db(0x04); db(0x00); db(0x0a); db(0x23); db(0x4b); db(0x00); db(0x10);
3299: db(0x41); db(0xec); db(0x00); db(0x4a); db(0x4e); db(0xee); db(0xfe); db(0xf2);
3300: db(0x20); db(0x4b); db(0x72); db(0x00); db(0x22); db(0x41); db(0x70); db(0xff);
3301: db(0x2c); db(0x4c); db(0x4e); db(0xee); db(0xff); db(0x6a); db(0x2c); db(0x78);
3302: db(0x00); db(0x04); db(0x70); db(0x00); db(0x22); db(0x40); db(0x4e); db(0xae);
3303: db(0xfe); db(0xda); db(0x20); db(0x40); db(0x4b); db(0xe8); db(0x00); db(0x5c);
3304: db(0x43); db(0xfa); db(0x01); db(0x3d); db(0x70); db(0x00); db(0x4e); db(0xae);
3305: db(0xfd); db(0xd8); db(0x24); db(0x40); db(0x20); db(0x3c); db(0x00); db(0x00);
3306: db(0x00); db(0x9d); db(0x22); db(0x3c); db(0x00); db(0x01); db(0x00); db(0x01);
3307: db(0x4e); db(0xae); db(0xff); db(0x3a); db(0x26); db(0x40); db(0x7c); db(0x00);
3308: db(0x26); db(0x86); db(0x27); db(0x46); db(0x00); db(0x04); db(0x27); db(0x46);
3309: db(0x00); db(0x08); db(0x7a); db(0x00); db(0x20); db(0x4d); db(0x4e); db(0xae);
3310: db(0xfe); db(0x80); db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x8c);
3311: db(0x28); db(0x40); db(0x26); db(0x2c); db(0x00); db(0x0a); db(0x70); db(0x00);
3312: db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x40); db(0x60); db(0x76);
1.1.1.3 root 3313: db(0x20); db(0x4d); db(0x4e); db(0xae); db(0xfe); db(0x80); db(0x20); db(0x4d);
3314: db(0x4e); db(0xae); db(0xfe); db(0x8c); db(0x28); db(0x40); db(0x26); db(0x2c);
1.1.1.7 root 3315: db(0x00); db(0x0a); db(0x66); db(0x38); db(0x70); db(0x01); db(0x4e); db(0xb9);
3316: db(0x00); db(0xf0); db(0xff); db(0x50); db(0x45); db(0xeb); db(0x00); db(0x04);
3317: db(0x20); db(0x52); db(0x20); db(0x08); db(0x67); db(0xda); db(0x22); db(0x50);
3318: db(0x20); db(0x40); db(0x20); db(0x28); db(0x00); db(0x04); db(0x6a); db(0x16);
3319: db(0x48); db(0xe7); db(0x00); db(0xc0); db(0x28); db(0x68); db(0x00); db(0x0a);
3320: db(0x61); db(0x42); db(0x53); db(0x85); db(0x4c); db(0xdf); db(0x03); db(0x00);
3321: db(0x24); db(0x89); db(0x20); db(0x49); db(0x60); db(0xdc); db(0x24); db(0x48);
3322: db(0x20); db(0x49); db(0x60); db(0xd6); db(0x0c); db(0x85); db(0x00); db(0x00);
3323: db(0x00); db(0x14); db(0x65); db(0x00); db(0x00); db(0x0a); db(0x70); db(0x01);
3324: db(0x29); db(0x40); db(0x00); db(0x04); db(0x60); db(0x0e); db(0x61); db(0x2a);
3325: db(0x4e); db(0xb9); db(0x00); db(0xf0); db(0xff); db(0x30); db(0x4a); db(0x80);
3326: db(0x67); db(0x0c); db(0x52); db(0x85); db(0x28); db(0xab); db(0x00); db(0x04);
3327: db(0x27); db(0x4c); db(0x00); db(0x04); db(0x60); db(0x8a); db(0x28); db(0x43);
3328: db(0x61); db(0x02); db(0x60); db(0x84); db(0x22); db(0x54); db(0x20); db(0x6c);
3329: db(0x00); db(0x04); db(0x29); db(0x4d); db(0x00); db(0x04); db(0x4e); db(0xee);
3330: db(0xfe); db(0x92); db(0x2f); db(0x05); db(0x7a); db(0xfc); db(0x24); db(0x53);
3331: db(0x2e); db(0x0a); db(0x22); db(0x0a); db(0x67); db(0x00); db(0x00); db(0x0c);
1.1.1.3 root 3332: db(0x52); db(0x85); db(0x67); db(0x1e); db(0x22); db(0x4a); db(0x24); db(0x52);
1.1.1.7 root 3333: db(0x60); db(0xf0); db(0x52); db(0x85); db(0x67); db(0x3c); db(0x24); db(0x47);
1.1.1.3 root 3334: db(0x70); db(0x18); db(0x72); db(0x01); db(0x4e); db(0xae); db(0xff); db(0x3a);
3335: db(0x52); db(0x46); db(0x24); db(0x40); db(0x24); db(0x87); db(0x2e); db(0x0a);
3336: db(0x60); db(0xe8); db(0x20); db(0x12); db(0x67); db(0x24); db(0x20); db(0x40);
3337: db(0x20); db(0x10); db(0x67); db(0x1e); db(0x20); db(0x40); db(0x20); db(0x10);
3338: db(0x67); db(0x18); db(0x70); db(0x00); db(0x22); db(0x80); db(0x22); db(0x4a);
3339: db(0x24); db(0x51); db(0x70); db(0x18); db(0x4e); db(0xae); db(0xff); db(0x2e);
1.1.1.7 root 3340: db(0x06); db(0x86); db(0x00); db(0x01); db(0x00); db(0x00); db(0x20); db(0x0a);
1.1.1.3 root 3341: db(0x66); db(0xec); db(0x26); db(0x87); db(0x2a); db(0x1f); db(0x4e); db(0x75);
3342: db(0x55); db(0x41); db(0x45); db(0x20); db(0x66); db(0x69); db(0x6c); db(0x65);
3343: db(0x73); db(0x79); db(0x73); db(0x74); db(0x65); db(0x6d); db(0x00); db(0x64);
3344: db(0x6f); db(0x73); db(0x2e); db(0x6c); db(0x69); db(0x62); db(0x72); db(0x61);
3345: db(0x72); db(0x79); db(0x00); db(0x65); db(0x78); db(0x70); db(0x61); db(0x6e);
3346: db(0x73); db(0x69); db(0x6f); db(0x6e); db(0x2e); db(0x6c); db(0x69); db(0x62);
1.1.1.7 root 3347: db(0x72); db(0x61); db(0x72); db(0x79); db(0x00); db(0x00); db(0x00); db(0x00);
3348: db(0x00); db(0x00); db(0x03); db(0xf2);
1.1 root 3349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.