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