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

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

unix.superglobalmegacorp.com

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