Annotation of uae/src/filesys.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.