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