Annotation of MiNT/src/tosfs.c, revision 1.1

1.1     ! root        1: /*
        !             2: 
        !             3: Copyright 1991,1992 Eric R. Smith. All rights reserved.
        !             4: 
        !             5: */
        !             6: 
        !             7: 
        !             8: 
        !             9: /* a VERY simple tosfs.c 
        !            10: 
        !            11:  * this one is extremely brain-damaged, but will serve OK for a
        !            12: 
        !            13:  * skeleton in which to put a "real" tosfs.c
        !            14: 
        !            15:  */
        !            16: 
        !            17: 
        !            18: 
        !            19: #include "mint.h"
        !            20: 
        !            21: 
        !            22: 
        !            23: /* search mask for anything OTHER THAN a volume label */
        !            24: 
        !            25: #define FILEORDIR 0x37
        !            26: 
        !            27: 
        !            28: 
        !            29: #ifndef Flock
        !            30: 
        !            31: /* this may need to be adjusted for your compiler/library */
        !            32: 
        !            33: extern long gemdos();
        !            34: 
        !            35: #define Flock(handle, mode, start, len) gemdos(0x5c, handle, mode, start, len)
        !            36: 
        !            37: #endif
        !            38: 
        !            39: 
        !            40: 
        !            41: char tmpbuf[PATH_MAX+1];
        !            42: 
        !            43: 
        !            44: 
        !            45: static long    tos_root        P_((int drv, fcookie *fc));
        !            46: 
        !            47: static long    tos_lookup      P_((fcookie *dir, const char *name, fcookie *fc));
        !            48: 
        !            49: static long    tos_getxattr    P_((fcookie *fc, XATTR *xattr));
        !            50: 
        !            51: static long    tos_chattr      P_((fcookie *fc, int attrib));
        !            52: 
        !            53: static long    tos_chown       P_((fcookie *fc, int uid, int gid));
        !            54: 
        !            55: static long    tos_chmode      P_((fcookie *fc, unsigned mode));
        !            56: 
        !            57: static long    tos_mkdir       P_((fcookie *dir, const char *name, unsigned mode));
        !            58: 
        !            59: static long    tos_rmdir       P_((fcookie *dir, const char *name));
        !            60: 
        !            61: static long    tos_remove      P_((fcookie *dir, const char *name));
        !            62: 
        !            63: static long    tos_getname     P_((fcookie *root, fcookie *dir, char *pathname));
        !            64: 
        !            65: static long    tos_rename      P_((fcookie *olddir, char *oldname,
        !            66: 
        !            67:                                    fcookie *newdir, const char *newname));
        !            68: 
        !            69: static long    tos_opendir     P_((DIR *dirh, int flags));
        !            70: 
        !            71: static long    tos_readdir     P_((DIR *dirh, char *nm, int nmlen, fcookie *));
        !            72: 
        !            73: static long    tos_rewinddir   P_((DIR *dirh));
        !            74: 
        !            75: static long    tos_closedir    P_((DIR *dirh));
        !            76: 
        !            77: static long    tos_pathconf    P_((fcookie *dir, int which));
        !            78: 
        !            79: static long    tos_dfree       P_((fcookie *dir, long *buf));
        !            80: 
        !            81: static long    tos_writelabel  P_((fcookie *dir, const char *name));
        !            82: 
        !            83: static long    tos_readlabel   P_((fcookie *dir, char *name, int namelen));
        !            84: 
        !            85: 
        !            86: 
        !            87: static long    tos_creat       P_((fcookie *dir, const char *name, unsigned mode,
        !            88: 
        !            89:                                    int attrib, fcookie *fc));
        !            90: 
        !            91: static DEVDRV *        tos_getdev      P_((fcookie *fc, long *devsp));
        !            92: 
        !            93: static long    tos_open        P_((FILEPTR *f));
        !            94: 
        !            95: static long    tos_write       P_((FILEPTR *f, const char *buf, long bytes));
        !            96: 
        !            97: static long    tos_read        P_((FILEPTR *f, char *buf, long bytes));
        !            98: 
        !            99: static long    tos_lseek       P_((FILEPTR *f, long where, int whence));
        !           100: 
        !           101: static long    tos_ioctl       P_((FILEPTR *f, int mode, void *buf));
        !           102: 
        !           103: static long    tos_datime      P_((FILEPTR *f, short *time, int rwflag));
        !           104: 
        !           105: static long    tos_close       P_((FILEPTR *f, int pid));
        !           106: 
        !           107: static long    tos_dskchng     P_((int drv));
        !           108: 
        !           109: 
        !           110: 
        !           111: /* some routines from biosfs.c */
        !           112: 
        !           113: extern long    null_select     P_((FILEPTR *f, long p, int mode));
        !           114: 
        !           115: extern void    null_unselect   P_((FILEPTR *f, long p, int mode));
        !           116: 
        !           117: 
        !           118: 
        !           119: DEVDRV tos_device = {
        !           120: 
        !           121:        tos_open, tos_write, tos_read, tos_lseek, tos_ioctl, tos_datime,
        !           122: 
        !           123:        tos_close, null_select, null_unselect
        !           124: 
        !           125: };
        !           126: 
        !           127: 
        !           128: 
        !           129: FILESYS tos_filesys = {
        !           130: 
        !           131:        (FILESYS *)0,
        !           132: 
        !           133:        FS_KNOPARSE | FS_NOXBIT,
        !           134: 
        !           135:        tos_root,
        !           136: 
        !           137:        tos_lookup, tos_creat, tos_getdev, tos_getxattr,
        !           138: 
        !           139:        tos_chattr, tos_chown, tos_chmode,
        !           140: 
        !           141:        tos_mkdir, tos_rmdir, tos_remove, tos_getname, tos_rename,
        !           142: 
        !           143:        tos_opendir, tos_readdir, tos_rewinddir, tos_closedir,
        !           144: 
        !           145:        tos_pathconf, tos_dfree, tos_writelabel, tos_readlabel,
        !           146: 
        !           147:        nosymlink, noreadlink, nohardlink, nofscntl, tos_dskchng
        !           148: 
        !           149: };
        !           150: 
        !           151: 
        !           152: 
        !           153: /* some utility functions and variables: see end of file */
        !           154: 
        !           155: static DTABUF  *lastdta;       /* last DTA buffer we asked TOS about */
        !           156: 
        !           157: static DTABUF  foo;
        !           158: 
        !           159: static void do_setdta P_((DTABUF *dta));
        !           160: 
        !           161: static int executable_extension P_((char *));
        !           162: 
        !           163: 
        !           164: 
        !           165: /* this array keeps track of which drives have been changed */
        !           166: 
        !           167: /* a nonzero entry means that the corresponding drive has been changed,
        !           168: 
        !           169:  * but GEMDOS doesn't know it yet
        !           170: 
        !           171:  */
        !           172: 
        !           173: static char drvchanged[NUM_DRIVES];
        !           174: 
        !           175: 
        !           176: 
        !           177: /* force TOS to see a media change */
        !           178: 
        !           179: static void force_mediach P_((int drv));
        !           180: 
        !           181: static long Newgetbpb P_((int));
        !           182: 
        !           183: static long Newmediach P_((int));
        !           184: 
        !           185: static long Newrwabs P_((int, void *, int, int, int, long));
        !           186: 
        !           187: 
        !           188: 
        !           189: #define NUM_INDICES 128
        !           190: 
        !           191: #define MIN_AGE 8
        !           192: 
        !           193: 
        !           194: 
        !           195: struct tindex {
        !           196: 
        !           197:        char *name;             /* full path name */
        !           198: 
        !           199:        FILEPTR *open;          /* fileptrs for this file; OR
        !           200: 
        !           201:                                 * count of number of open directories
        !           202: 
        !           203:                                 */
        !           204: 
        !           205:        LOCK *locks;            /* locks on this file */
        !           206: 
        !           207: /* file status */
        !           208: 
        !           209:        long  size;
        !           210: 
        !           211:        short time;
        !           212: 
        !           213:        short date;
        !           214: 
        !           215:        short attr;
        !           216: 
        !           217:        short valid;            /* 1 if the above status is still valid */
        !           218: 
        !           219:        short stamp;            /* age of this index, for garbage collection */
        !           220: 
        !           221: } gl_ti[NUM_INDICES];
        !           222: 
        !           223: 
        !           224: 
        !           225: /* temporary index for files found by readdir */
        !           226: 
        !           227: static struct tindex tmpindex;
        !           228: 
        !           229: static char tmpiname[PATH_MAX];
        !           230: 
        !           231: 
        !           232: 
        !           233: static struct tindex *tstrindex P_((char *s));
        !           234: 
        !           235: static int tfullpath P_((char *result, struct tindex *base, const char *name));
        !           236: 
        !           237: static struct tindex *garbage_collect P_((void));
        !           238: 
        !           239: 
        !           240: 
        !           241: static short tclock;           /* #calls to tfullpath since last garbage
        !           242: 
        !           243:                                   collection */
        !           244: 
        !           245: 
        !           246: 
        !           247: /* some extra flags for the attr field */
        !           248: 
        !           249: 
        !           250: 
        !           251: /*
        !           252: 
        !           253:  * is a string the name of a file with executable extension?
        !           254: 
        !           255:  */
        !           256: 
        !           257: #define FA_EXEC 0x4000
        !           258: 
        !           259: /*
        !           260: 
        !           261:  * should the file be deleted when it is closed?
        !           262: 
        !           263:  */
        !           264: 
        !           265: #define FA_DELETE 0x2000
        !           266: 
        !           267: 
        !           268: 
        !           269: /*
        !           270: 
        !           271:  * NOTE: call executable_extension only on a DTA name returned from
        !           272: 
        !           273:  * Fsfirst(), not on an arbitrary path
        !           274: 
        !           275:  */
        !           276: 
        !           277: 
        !           278: 
        !           279: static int
        !           280: 
        !           281: executable_extension(s)
        !           282: 
        !           283:        char *s;
        !           284: 
        !           285: {
        !           286: 
        !           287:        while (*s && *s != '.') s++;
        !           288: 
        !           289:        if (!*s) return 0;
        !           290: 
        !           291:        s++;
        !           292: 
        !           293:        if (s[0] == 'T') {
        !           294: 
        !           295:                return (s[1] == 'T' && s[2] == 'P') ||
        !           296: 
        !           297:                       (s[1] == 'O' && s[2] == 'S');
        !           298: 
        !           299:        }
        !           300: 
        !           301:        if (s[0] == 'P')
        !           302: 
        !           303:                return s[1] == 'R' && s[2] == 'G';
        !           304: 
        !           305:        if (s[0] == 'A')
        !           306: 
        !           307:                return s[1] == 'P' && s[2] == 'P';
        !           308: 
        !           309:        if (s[0] == 'G')
        !           310: 
        !           311:                return s[1] == 'T' && s[2] == 'P';
        !           312: 
        !           313:        return 0;
        !           314: 
        !           315: }
        !           316: 
        !           317: 
        !           318: 
        !           319: /*
        !           320: 
        !           321:  * Look in the table of tos indices to see if an index corresponding
        !           322: 
        !           323:  * to this file name already exists. If so, mark it as being used
        !           324: 
        !           325:  * and return it. If not, find an empty slot and make an index for
        !           326: 
        !           327:  * this string. If no empty slots exist, garbage collect and
        !           328: 
        !           329:  * try again.
        !           330: 
        !           331:  *
        !           332: 
        !           333:  * This routine is pretty dumb; we really should use a hash table
        !           334: 
        !           335:  * of some sort
        !           336: 
        !           337:  */
        !           338: 
        !           339: 
        !           340: 
        !           341: static struct tindex *tstrindex(s)
        !           342: 
        !           343:        char *s;
        !           344: 
        !           345: {
        !           346: 
        !           347:        int i;
        !           348: 
        !           349:        char *r;
        !           350: 
        !           351:        struct tindex *t, *free = 0;
        !           352: 
        !           353: 
        !           354: 
        !           355:        assert(s != 0);
        !           356: 
        !           357:        t = gl_ti;
        !           358: 
        !           359:        for (i = 0; i < NUM_INDICES; i++, t++) {
        !           360: 
        !           361:                if (t->name && !stricmp(t->name, s)) {
        !           362: 
        !           363:                        t->stamp = tclock;      /* update use time */
        !           364: 
        !           365:                        return t;
        !           366: 
        !           367:                }
        !           368: 
        !           369:                else if (!t->name && !free)
        !           370: 
        !           371:                        free = t;
        !           372: 
        !           373:        }
        !           374: 
        !           375:        if (!free) {
        !           376: 
        !           377:                free = garbage_collect();
        !           378: 
        !           379:        }
        !           380: 
        !           381:        if (!free) {
        !           382: 
        !           383:                FATAL("tosfs: unable to get a file name index");
        !           384: 
        !           385:        }
        !           386: 
        !           387:        r = kmalloc((long)strlen(s)+1);
        !           388: 
        !           389:        if (!r) {
        !           390: 
        !           391:                FATAL("tosfs: unable to allocate space for a file name");
        !           392: 
        !           393:        }
        !           394: 
        !           395:        strcpy(r, s);
        !           396: 
        !           397:        free->name = r;
        !           398: 
        !           399:        free->stamp = tclock;
        !           400: 
        !           401:        free->open = 0;
        !           402: 
        !           403:        free->locks = 0;
        !           404: 
        !           405: 
        !           406: 
        !           407: /* check to see if this file was recently returned by opendir() */
        !           408: 
        !           409:        if (tmpindex.valid && tclock - tmpindex.stamp < MIN_AGE &&
        !           410: 
        !           411:            !stricmp(free->name, tmpindex.name)) {
        !           412: 
        !           413:                free->size = tmpindex.size;
        !           414: 
        !           415:                free->time = tmpindex.time;
        !           416: 
        !           417:                free->date = tmpindex.date;
        !           418: 
        !           419:                free->attr = tmpindex.attr;
        !           420: 
        !           421:                free->valid = 1;
        !           422: 
        !           423:                tmpindex.valid = 0;
        !           424: 
        !           425:        } else
        !           426: 
        !           427:                free->valid = 0;
        !           428: 
        !           429:        return free;
        !           430: 
        !           431: }
        !           432: 
        !           433: 
        !           434: 
        !           435: /*
        !           436: 
        !           437:  * garbage collection routine: for any TOS index older than MIN_AGE,
        !           438: 
        !           439:  * check through all current processes to see if it's in use. If
        !           440: 
        !           441:  * not, free the corresponding string.
        !           442: 
        !           443:  * Returns: a pointer to a newly freed index, or NULL.
        !           444: 
        !           445:  */
        !           446: 
        !           447: 
        !           448: 
        !           449: /* it's unlikely that the kernel would need to hold onto a file cookie
        !           450: 
        !           451:    for longer than this many calls to tstrindex() without first
        !           452: 
        !           453:    saving the cookie in a directory or file pointer
        !           454: 
        !           455:  */
        !           456: 
        !           457: 
        !           458: 
        !           459: static struct tindex *
        !           460: 
        !           461: garbage_collect()
        !           462: 
        !           463: {
        !           464: 
        !           465:        struct tindex *free, *t;
        !           466: 
        !           467:        fcookie *fc, *gc;
        !           468: 
        !           469:        PROC *p;
        !           470: 
        !           471:        int i, j;
        !           472: 
        !           473:        int age;
        !           474: 
        !           475: 
        !           476: 
        !           477:        free = 0;
        !           478: 
        !           479:        t = gl_ti;
        !           480: 
        !           481:        for (i = 0; i < NUM_INDICES; i++,t++) {
        !           482: 
        !           483:                if (!t->name) continue;
        !           484: 
        !           485:                age = tclock - t->stamp;
        !           486: 
        !           487:                t->stamp = 0;
        !           488: 
        !           489:                assert(age >= 0);
        !           490: 
        !           491:                if (age > MIN_AGE) {
        !           492: 
        !           493:                /* see if any process is using this index */
        !           494: 
        !           495:                        if (t->open)
        !           496: 
        !           497:                                goto found_index;
        !           498: 
        !           499:                        for (p = proclist; p; p = p->gl_next) {
        !           500: 
        !           501:                                fc = p->curdir;
        !           502: 
        !           503:                                gc = p->root;
        !           504: 
        !           505:                                for (j = 0; j < NUM_DRIVES; j++,fc++,gc++) {
        !           506: 
        !           507:                                        if (( fc->fs == &tos_filesys &&
        !           508: 
        !           509:                                              fc->index == (long)t ) ||
        !           510: 
        !           511:                                            ( gc->fs == &tos_filesys &&
        !           512: 
        !           513:                                              gc->index == (long)t ) )
        !           514: 
        !           515:                                                goto found_index;
        !           516: 
        !           517:                                }
        !           518: 
        !           519:                        }
        !           520: 
        !           521:                /* here, we couldn't find the index in use by any proc. */
        !           522: 
        !           523:                        kfree(t->name);
        !           524: 
        !           525:                        t->name = 0;
        !           526: 
        !           527:                        if (!free)
        !           528: 
        !           529:                                free = t;
        !           530: 
        !           531:                found_index:
        !           532: 
        !           533:                        ;
        !           534: 
        !           535:                } else {
        !           536: 
        !           537:        /* make sure that future garbage collections might look at this file */
        !           538: 
        !           539:                        t->stamp = -age;
        !           540: 
        !           541:                }
        !           542: 
        !           543:        }
        !           544: 
        !           545: 
        !           546: 
        !           547:        tclock = 0;     /* reset the clock */
        !           548: 
        !           549:        tmpindex.valid = 0; /* expire the temporary Fsfirst buffer */
        !           550: 
        !           551:        return free;
        !           552: 
        !           553: }
        !           554: 
        !           555: 
        !           556: 
        !           557: #define DIRSEP(c) ((c) == '\\')
        !           558: 
        !           559: 
        !           560: 
        !           561: static int
        !           562: 
        !           563: tfullpath(result, basei, path)
        !           564: 
        !           565:        char *result;
        !           566: 
        !           567:        struct tindex *basei;
        !           568: 
        !           569:        const char *path;
        !           570: 
        !           571: {
        !           572: 
        !           573: #define TNMTEMP 32
        !           574: 
        !           575:        char *n, name[TNMTEMP+1];
        !           576: 
        !           577:        int dom;
        !           578: 
        !           579:        int namelen, pathlen;
        !           580: 
        !           581:        char *base = basei->name;
        !           582: 
        !           583:        int r = 0;
        !           584: 
        !           585: 
        !           586: 
        !           587:        basei->stamp = ++tclock;
        !           588: 
        !           589:        if (tclock > 10000) {
        !           590: 
        !           591:        /* garbage collect every so often whether we need it or not */
        !           592: 
        !           593:                (void)garbage_collect();
        !           594: 
        !           595:        }
        !           596: 
        !           597:        if (!*path) {
        !           598: 
        !           599:                strncpy(result, base, PATH_MAX-1);
        !           600: 
        !           601:                return r;
        !           602: 
        !           603:        }
        !           604: 
        !           605: 
        !           606: 
        !           607:        dom = curproc->domain;
        !           608: 
        !           609: 
        !           610: 
        !           611:        strncpy(result, base, PATH_MAX-1);
        !           612: 
        !           613: 
        !           614: 
        !           615:        pathlen = strlen(result);
        !           616: 
        !           617: 
        !           618: 
        !           619: /* now path is relative to what's currently in "result" */
        !           620: 
        !           621: 
        !           622: 
        !           623:        while(*path) {
        !           624: 
        !           625: /* get next name in path */
        !           626: 
        !           627:                n = name; namelen = 0;
        !           628: 
        !           629:                while (*path && !DIRSEP(*path)) {
        !           630: 
        !           631: /* BUG: we really should to the translation to DOS 8.3
        !           632: 
        !           633:  * format *here*, so that really long names are truncated
        !           634: 
        !           635:  * correctly.
        !           636: 
        !           637:  */
        !           638: 
        !           639:                        if (namelen < TNMTEMP) {
        !           640: 
        !           641:                                *n++ = toupper(*path); path++; namelen++;
        !           642: 
        !           643:                        }
        !           644: 
        !           645:                        else
        !           646: 
        !           647:                                path++;
        !           648: 
        !           649:                }
        !           650: 
        !           651:                *n++ = 0;
        !           652: 
        !           653:                while (DIRSEP(*path)) path++;
        !           654: 
        !           655: /* check for "." and ".." */
        !           656: 
        !           657:                if (!strcmp(name, ".")) continue;
        !           658: 
        !           659:                if (!strcmp(name, "..")) {
        !           660: 
        !           661:                        n = strrchr(result, '\\');
        !           662: 
        !           663:                        if (n) {
        !           664: 
        !           665:                                *n = 0;
        !           666: 
        !           667:                                pathlen = n - result;
        !           668: 
        !           669:                        }
        !           670: 
        !           671:                        else r = EMOUNT;
        !           672: 
        !           673:                        continue;
        !           674: 
        !           675:                }
        !           676: 
        !           677:                if (pathlen + namelen < PATH_MAX - 1) {
        !           678: 
        !           679:                        strcat(result, "\\");
        !           680: 
        !           681:                        pathlen++;
        !           682: 
        !           683: 
        !           684: 
        !           685:        /* make sure the name is restricted to DOS 8.3 format */
        !           686: 
        !           687:                        for (base = result; *base; base++)
        !           688: 
        !           689:                                ;
        !           690: 
        !           691:                        n = name;
        !           692: 
        !           693:                        namelen = 0;
        !           694: 
        !           695:                        while (*n && *n != '.' && namelen++ < 8) {
        !           696: 
        !           697:                                *base++ = *n++;
        !           698: 
        !           699:                                pathlen++;
        !           700: 
        !           701:                        }
        !           702: 
        !           703:                        while (*n && *n != '.') n++;
        !           704: 
        !           705:                        if (*n == '.' && *(n+1) != 0) {
        !           706: 
        !           707:                                *base++ = *n++;
        !           708: 
        !           709:                                pathlen++;
        !           710: 
        !           711:                                namelen = 0;
        !           712: 
        !           713:                                while (*n && namelen++ < 3) {
        !           714: 
        !           715:                                        *base++ = *n++;
        !           716: 
        !           717:                                        pathlen++;
        !           718: 
        !           719:                                }
        !           720: 
        !           721:                        }
        !           722: 
        !           723:                        *base = 0;
        !           724: 
        !           725:                }
        !           726: 
        !           727:        }
        !           728: 
        !           729:        return r;
        !           730: 
        !           731: }
        !           732: 
        !           733: 
        !           734: 
        !           735: static long
        !           736: 
        !           737: tos_root(drv, fc)
        !           738: 
        !           739:        int drv;
        !           740: 
        !           741:        fcookie *fc;
        !           742: 
        !           743: {
        !           744: 
        !           745:        struct tindex *ti;
        !           746: 
        !           747: 
        !           748: 
        !           749:        ksprintf(tmpbuf, "%c:", drv+'A');
        !           750: 
        !           751:        fc->fs = &tos_filesys;
        !           752: 
        !           753:        fc->dev = drv;
        !           754: 
        !           755:        ti = tstrindex(tmpbuf);
        !           756: 
        !           757:        ti->size = ti->date = ti->time = 0;
        !           758: 
        !           759:        ti->attr = FA_DIR;
        !           760: 
        !           761:        ti->valid = 1;
        !           762: 
        !           763:        fc->index = (long)ti;
        !           764: 
        !           765: 
        !           766: 
        !           767: /* if the drive has changed, make sure GEMDOS knows it! */
        !           768: 
        !           769:        if (drvchanged[drv]) {
        !           770: 
        !           771:                force_mediach(drv);
        !           772: 
        !           773:        }
        !           774: 
        !           775:        return 0;
        !           776: 
        !           777: }
        !           778: 
        !           779: 
        !           780: 
        !           781: static long
        !           782: 
        !           783: tos_lookup(dir, name, fc)
        !           784: 
        !           785:        fcookie *dir;
        !           786: 
        !           787:        const char *name;
        !           788: 
        !           789:        fcookie *fc;
        !           790: 
        !           791: {
        !           792: 
        !           793:        long r;
        !           794: 
        !           795:        struct tindex *ti = (struct tindex *)dir->index;
        !           796: 
        !           797: 
        !           798: 
        !           799:        r = tfullpath(tmpbuf, ti, name);
        !           800: 
        !           801: 
        !           802: 
        !           803: /* if the name is empty or otherwise trivial, just return the directory */
        !           804: 
        !           805:        if (!strcmp(ti->name, tmpbuf)) {
        !           806: 
        !           807:                *fc = *dir;
        !           808: 
        !           809:                return r;
        !           810: 
        !           811:        }
        !           812: 
        !           813: 
        !           814: 
        !           815: /* is there already an index for this file?? If so, is it up to date?? */
        !           816: 
        !           817:        ti = tstrindex(tmpbuf);
        !           818: 
        !           819:        if (!ti->valid) {
        !           820: 
        !           821:                if (tmpbuf[1] == ':' && tmpbuf[2] == 0) {
        !           822: 
        !           823:                        /* a root directory -- lookup always succeeds */
        !           824: 
        !           825:                        foo.dta_size = 0;
        !           826: 
        !           827:                        foo.dta_date = foo.dta_time = 0;
        !           828: 
        !           829:                        foo.dta_attrib = FA_DIR;
        !           830: 
        !           831:                        foo.dta_name[0] = 0;
        !           832: 
        !           833:                } else {
        !           834: 
        !           835:                        do_setdta(&foo);
        !           836: 
        !           837:                        r = Fsfirst(tmpbuf, FILEORDIR);
        !           838: 
        !           839:                        if (r) {
        !           840: 
        !           841: DEBUG("tos_lookup: Fsfirst(%s) returned %ld", tmpbuf, r);
        !           842: 
        !           843:                                return r;
        !           844: 
        !           845:                        }
        !           846: 
        !           847:                }
        !           848: 
        !           849:                ti->size = foo.dta_size;
        !           850: 
        !           851:                ti->date = foo.dta_date;
        !           852: 
        !           853:                ti->time = foo.dta_time;
        !           854: 
        !           855:                ti->attr = foo.dta_attrib;
        !           856: 
        !           857:                if (executable_extension(foo.dta_name))
        !           858: 
        !           859:                        ti->attr |= FA_EXEC;
        !           860: 
        !           861:                ti->valid = 1;
        !           862: 
        !           863:        }
        !           864: 
        !           865:        fc->fs = &tos_filesys;
        !           866: 
        !           867:        fc->index = (long)ti;
        !           868: 
        !           869:        fc->dev = dir->dev;
        !           870: 
        !           871:        return r;
        !           872: 
        !           873: }
        !           874: 
        !           875: 
        !           876: 
        !           877: static long
        !           878: 
        !           879: tos_getxattr(fc, xattr)
        !           880: 
        !           881:        fcookie *fc;
        !           882: 
        !           883:        XATTR *xattr;
        !           884: 
        !           885: {
        !           886: 
        !           887:        struct tindex *ti = (struct tindex *)fc->index;
        !           888: 
        !           889:        long r;
        !           890: 
        !           891:        static long junkindex = 0;
        !           892: 
        !           893: 
        !           894: 
        !           895:        xattr->index = junkindex++;
        !           896: 
        !           897:        xattr->dev = fc->dev;
        !           898: 
        !           899:        xattr->nlink = 1;
        !           900: 
        !           901:        xattr->uid = xattr->gid = 0;
        !           902: 
        !           903: 
        !           904: 
        !           905:        ti->stamp = ++tclock;
        !           906: 
        !           907:        if (!ti->valid) {
        !           908: 
        !           909:                do_setdta(&foo);
        !           910: 
        !           911:                if (ti->name[2] == 0) {         /* a root directory */
        !           912: 
        !           913: /* actually, this can also happen if a program tries to open a file
        !           914: 
        !           915:  * with an empty name... so we should fail gracefully
        !           916: 
        !           917:  */
        !           918: 
        !           919: TRACE("tosfs: a root directory became invalid??");
        !           920: 
        !           921:                        goto around;
        !           922: 
        !           923:                }
        !           924: 
        !           925:        
        !           926: 
        !           927:                r = Fsfirst(ti->name, FILEORDIR);
        !           928: 
        !           929:                if (r < 0)
        !           930: 
        !           931:                        FATAL("tosfs: search error on [%s]", ti->name);
        !           932: 
        !           933:                ti->size = foo.dta_size;
        !           934: 
        !           935:                ti->date = foo.dta_date;
        !           936: 
        !           937:                ti->time = foo.dta_time;
        !           938: 
        !           939:                ti->attr = foo.dta_attrib;
        !           940: 
        !           941:                if (executable_extension(foo.dta_name))
        !           942: 
        !           943:                        ti->attr |= FA_EXEC;
        !           944: 
        !           945: around:
        !           946: 
        !           947:                ti->valid = 1;
        !           948: 
        !           949:        }
        !           950: 
        !           951:        xattr->size = ti->size;
        !           952: 
        !           953: 
        !           954: 
        !           955: /* BUG: blksize isn't accurate if the sector size is not 512 */
        !           956: 
        !           957:        xattr->blksize = 1024;
        !           958: 
        !           959:        xattr->nblocks = (xattr->size + 1023) / 1024;
        !           960: 
        !           961:        xattr->mdate = xattr->cdate = xattr->adate = ti->date;
        !           962: 
        !           963:        xattr->mtime = xattr->ctime = xattr->atime = ti->time;
        !           964: 
        !           965:        xattr->mode = (ti->attr & FA_DIR) ? (S_IFDIR | DEFAULT_DIRMODE) :
        !           966: 
        !           967:                         (S_IFREG | DEFAULT_MODE);
        !           968: 
        !           969: 
        !           970: 
        !           971:        if (ti->attr & FA_RDONLY) {
        !           972: 
        !           973:                xattr->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
        !           974: 
        !           975:        }
        !           976: 
        !           977: 
        !           978: 
        !           979:        if (ti->attr & FA_EXEC) {
        !           980: 
        !           981:                xattr->mode |= (S_IXUSR|S_IXGRP|S_IXOTH);
        !           982: 
        !           983:        }
        !           984: 
        !           985:        xattr->attr = ti->attr & 0xff;
        !           986: 
        !           987:        return 0;
        !           988: 
        !           989: }
        !           990: 
        !           991: 
        !           992: 
        !           993: static long
        !           994: 
        !           995: tos_chattr(fc, attrib)
        !           996: 
        !           997:        fcookie *fc;
        !           998: 
        !           999:        int attrib;
        !          1000: 
        !          1001: {
        !          1002: 
        !          1003:        struct tindex *ti = (struct tindex *)fc->index;
        !          1004: 
        !          1005: 
        !          1006: 
        !          1007:        if (ti->attr & FA_DIR) {
        !          1008: 
        !          1009:                DEBUG("error: attempt to change attributes of a directory");
        !          1010: 
        !          1011:                return EACCDN;
        !          1012: 
        !          1013:        }
        !          1014: 
        !          1015:        ti->valid = 0;
        !          1016: 
        !          1017:        (void)tfullpath(tmpbuf, ti, "");
        !          1018: 
        !          1019:        return Fattrib(tmpbuf, 1, attrib);
        !          1020: 
        !          1021: }
        !          1022: 
        !          1023: 
        !          1024: 
        !          1025: static long
        !          1026: 
        !          1027: tos_chown(dir, uid, gid)
        !          1028: 
        !          1029:        fcookie *dir;
        !          1030: 
        !          1031:        int uid, gid;
        !          1032: 
        !          1033: {
        !          1034: 
        !          1035:        return EINVFN;
        !          1036: 
        !          1037: }
        !          1038: 
        !          1039: 
        !          1040: 
        !          1041: static long
        !          1042: 
        !          1043: tos_chmode(fc, mode)
        !          1044: 
        !          1045:        fcookie *fc;
        !          1046: 
        !          1047:        unsigned mode;
        !          1048: 
        !          1049: {
        !          1050: 
        !          1051:        int oldattr, newattr;
        !          1052: 
        !          1053:        long r;
        !          1054: 
        !          1055:        struct tindex *ti = (struct tindex *)fc->index;
        !          1056: 
        !          1057: 
        !          1058: 
        !          1059:        oldattr = Fattrib(ti->name, 0, 0);
        !          1060: 
        !          1061:        if (oldattr < 0)
        !          1062: 
        !          1063:                return oldattr;
        !          1064: 
        !          1065: 
        !          1066: 
        !          1067:        ti->valid = 0;
        !          1068: 
        !          1069: 
        !          1070: 
        !          1071:        if (!(mode & S_IWUSR))
        !          1072: 
        !          1073:                newattr = oldattr | FA_RDONLY;
        !          1074: 
        !          1075:        else
        !          1076: 
        !          1077:                newattr = oldattr & ~FA_RDONLY;
        !          1078: 
        !          1079:        if (newattr != oldattr)
        !          1080: 
        !          1081:                r = Fattrib(ti->name, 1, newattr);
        !          1082: 
        !          1083:        else
        !          1084: 
        !          1085:                r = 0;
        !          1086: 
        !          1087:        return (r < 0) ? r : 0;
        !          1088: 
        !          1089: }
        !          1090: 
        !          1091: 
        !          1092: 
        !          1093: static long
        !          1094: 
        !          1095: tos_mkdir(dir, name, mode)
        !          1096: 
        !          1097:        fcookie *dir;
        !          1098: 
        !          1099:        const char *name;
        !          1100: 
        !          1101:        unsigned mode;          /* ignored under TOS */
        !          1102: 
        !          1103: {
        !          1104: 
        !          1105:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
        !          1106: 
        !          1107:        tmpindex.valid = 0;
        !          1108: 
        !          1109: 
        !          1110: 
        !          1111:        return Dcreate(tmpbuf);
        !          1112: 
        !          1113: }
        !          1114: 
        !          1115: 
        !          1116: 
        !          1117: static long
        !          1118: 
        !          1119: tos_rmdir(dir, name)
        !          1120: 
        !          1121:        fcookie *dir;
        !          1122: 
        !          1123:        const char *name;
        !          1124: 
        !          1125: {
        !          1126: 
        !          1127:        struct tindex *ti;
        !          1128: 
        !          1129: 
        !          1130: 
        !          1131:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
        !          1132: 
        !          1133:        ti = tstrindex(tmpbuf);
        !          1134: 
        !          1135:        ti->valid = 0;
        !          1136: 
        !          1137: 
        !          1138: 
        !          1139:        return Ddelete(tmpbuf);
        !          1140: 
        !          1141: }
        !          1142: 
        !          1143: 
        !          1144: 
        !          1145: static long
        !          1146: 
        !          1147: tos_remove(dir, name)
        !          1148: 
        !          1149:        fcookie *dir;
        !          1150: 
        !          1151:        const char *name;
        !          1152: 
        !          1153: {
        !          1154: 
        !          1155:        struct tindex *ti;
        !          1156: 
        !          1157: 
        !          1158: 
        !          1159:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
        !          1160: 
        !          1161: 
        !          1162: 
        !          1163:        ti = tstrindex(tmpbuf);
        !          1164: 
        !          1165:        if (ti->open) {
        !          1166: 
        !          1167:                DEBUG("tos_remove: file is open, will be deleted later");
        !          1168: 
        !          1169:                if (ti->attr & FA_RDONLY)
        !          1170: 
        !          1171:                        return EACCDN;
        !          1172: 
        !          1173:                ti->attr |= FA_DELETE;
        !          1174: 
        !          1175:                return 0;
        !          1176: 
        !          1177:        }
        !          1178: 
        !          1179:        ti->valid = 0;
        !          1180: 
        !          1181:        return Fdelete(tmpbuf);
        !          1182: 
        !          1183: }
        !          1184: 
        !          1185: 
        !          1186: 
        !          1187: static long
        !          1188: 
        !          1189: tos_getname(root, dir, pathname)
        !          1190: 
        !          1191:        fcookie *root, *dir;
        !          1192: 
        !          1193:        char *pathname;
        !          1194: 
        !          1195: {
        !          1196: 
        !          1197:        ksprintf(pathname, "%s", ((struct tindex *)dir->index)->name +
        !          1198: 
        !          1199:                                strlen(((struct tindex*)root->index)->name) );
        !          1200: 
        !          1201:        if (curproc->domain == DOM_MINT)
        !          1202: 
        !          1203:                strlwr(pathname);
        !          1204: 
        !          1205: 
        !          1206: 
        !          1207:        return 0;
        !          1208: 
        !          1209: }
        !          1210: 
        !          1211: 
        !          1212: 
        !          1213: static long
        !          1214: 
        !          1215: tos_rename(olddir, oldname, newdir, newname)
        !          1216: 
        !          1217:        fcookie *olddir;
        !          1218: 
        !          1219:        char *oldname;
        !          1220: 
        !          1221:        fcookie *newdir;
        !          1222: 
        !          1223:        const char *newname;
        !          1224: 
        !          1225: {
        !          1226: 
        !          1227:        char newbuf[128];
        !          1228: 
        !          1229:        struct tindex *ti;
        !          1230: 
        !          1231:        long r;
        !          1232: 
        !          1233: 
        !          1234: 
        !          1235:        (void)tfullpath(tmpbuf, (struct tindex *)olddir->index, oldname);
        !          1236: 
        !          1237:        (void)tfullpath(newbuf, (struct tindex *)newdir->index, newname);
        !          1238: 
        !          1239:        r = Frename(0, tmpbuf, newbuf);
        !          1240: 
        !          1241:        if (r == 0) {
        !          1242: 
        !          1243:                ti = tstrindex(tmpbuf);
        !          1244: 
        !          1245:                kfree(ti->name);
        !          1246: 
        !          1247:                ti->name = kmalloc((long)strlen(newbuf)+1);
        !          1248: 
        !          1249:                if (!ti->name) {
        !          1250: 
        !          1251:                        FATAL("tosfs: unable to allocate space for a name");
        !          1252: 
        !          1253:                }
        !          1254: 
        !          1255:                strcpy(ti->name, newbuf);
        !          1256: 
        !          1257:                ti->valid = 0;
        !          1258: 
        !          1259:        }
        !          1260: 
        !          1261:        return r;
        !          1262: 
        !          1263: }
        !          1264: 
        !          1265: 
        !          1266: 
        !          1267: #define DIR_FLAG(x)    (x->fsstuff[0])
        !          1268: 
        !          1269: #define STARTSEARCH    0       /* opendir() was just called */
        !          1270: 
        !          1271: #define INSEARCH       1       /* readdir() has been called at least once */
        !          1272: 
        !          1273: #define NMFILE         2       /* no more files to read */
        !          1274: 
        !          1275: 
        !          1276: 
        !          1277: #define DIR_DTA(x)     ((DTABUF *)(x->fsstuff + 2))
        !          1278: 
        !          1279: #define DIR_NAME(x)    (x->fsstuff + 32)
        !          1280: 
        !          1281: 
        !          1282: 
        !          1283: /*
        !          1284: 
        !          1285:  * The directory functions are a bit tricky. What we do is have
        !          1286: 
        !          1287:  * opendir() do Fsfirst; the first readdir() picks up this name,
        !          1288: 
        !          1289:  * subsequent readdir()'s have to do Fsnext
        !          1290: 
        !          1291:  */
        !          1292: 
        !          1293: 
        !          1294: 
        !          1295: static long
        !          1296: 
        !          1297: tos_opendir(dirh, flags)
        !          1298: 
        !          1299:        DIR *dirh;
        !          1300: 
        !          1301:        int flags;
        !          1302: 
        !          1303: {
        !          1304: 
        !          1305:        long r;
        !          1306: 
        !          1307:        struct tindex *t = (struct tindex *)dirh->fc.index;
        !          1308: 
        !          1309: 
        !          1310: 
        !          1311:        (void)tfullpath(tmpbuf, t, "*.*");
        !          1312: 
        !          1313: 
        !          1314: 
        !          1315:        do_setdta(DIR_DTA(dirh));
        !          1316: 
        !          1317: 
        !          1318: 
        !          1319:        r = Fsfirst(tmpbuf, FILEORDIR);
        !          1320: 
        !          1321: 
        !          1322: 
        !          1323:        if (r == 0) {
        !          1324: 
        !          1325:                t->open++;
        !          1326: 
        !          1327:                DIR_FLAG(dirh) = STARTSEARCH;
        !          1328: 
        !          1329:                return 0;
        !          1330: 
        !          1331:        } else if (r == EFILNF) {
        !          1332: 
        !          1333:                t->open++;
        !          1334: 
        !          1335:                DIR_FLAG(dirh) = NMFILE;
        !          1336: 
        !          1337:                return 0;
        !          1338: 
        !          1339:        }
        !          1340: 
        !          1341:        return r;
        !          1342: 
        !          1343: }
        !          1344: 
        !          1345: 
        !          1346: 
        !          1347: static long
        !          1348: 
        !          1349: tos_readdir(dirh, name, namelen, fc)
        !          1350: 
        !          1351:        DIR *dirh;
        !          1352: 
        !          1353:        char *name;
        !          1354: 
        !          1355:        int namelen;
        !          1356: 
        !          1357:        fcookie *fc;
        !          1358: 
        !          1359: {
        !          1360: 
        !          1361:        static long index = 0;
        !          1362: 
        !          1363:        long ret;
        !          1364: 
        !          1365:        int giveindex = dirh->flags == 0;
        !          1366: 
        !          1367:        struct tindex *ti;
        !          1368: 
        !          1369:        DTABUF *dta = DIR_DTA(dirh);
        !          1370: 
        !          1371: 
        !          1372: 
        !          1373: again:
        !          1374: 
        !          1375:        if (DIR_FLAG(dirh) == NMFILE)
        !          1376: 
        !          1377:                return ENMFIL;
        !          1378: 
        !          1379: 
        !          1380: 
        !          1381:        if (DIR_FLAG(dirh) == STARTSEARCH) {
        !          1382: 
        !          1383:                DIR_FLAG(dirh) = INSEARCH;
        !          1384: 
        !          1385:        } else {
        !          1386: 
        !          1387:                assert(DIR_FLAG(dirh) == INSEARCH);
        !          1388: 
        !          1389:                do_setdta(dta);
        !          1390: 
        !          1391:                ret = Fsnext();
        !          1392: 
        !          1393:                if (ret) {
        !          1394: 
        !          1395:                        DIR_FLAG(dirh) = NMFILE;
        !          1396: 
        !          1397:                        return ret;
        !          1398: 
        !          1399:                }
        !          1400: 
        !          1401:        }
        !          1402: 
        !          1403: 
        !          1404: 
        !          1405: /* don't return volume labels from readdir */
        !          1406: 
        !          1407:        if (dta->dta_attrib == FA_LABEL) goto again;
        !          1408: 
        !          1409: 
        !          1410: 
        !          1411:        fc->fs = &tos_filesys;
        !          1412: 
        !          1413:        fc->dev = dirh->fc.dev;
        !          1414: 
        !          1415: 
        !          1416: 
        !          1417:        (void)tfullpath(tmpiname, (struct tindex *)dirh->fc.index, DIR_NAME(dirh));
        !          1418: 
        !          1419: 
        !          1420: 
        !          1421:        ti = &tmpindex;
        !          1422: 
        !          1423:        ti->name = tmpiname;
        !          1424: 
        !          1425:        ti->valid = 1;
        !          1426: 
        !          1427:        ti->size = dta->dta_size;
        !          1428: 
        !          1429:        ti->date = dta->dta_date;
        !          1430: 
        !          1431:        ti->time = dta->dta_time;
        !          1432: 
        !          1433:        ti->attr = dta->dta_attrib;
        !          1434: 
        !          1435:        ti->stamp = tclock;
        !          1436: 
        !          1437:        if (executable_extension(dta->dta_name))
        !          1438: 
        !          1439:                ti->attr |= FA_EXEC;
        !          1440: 
        !          1441:        fc->index = (long)ti;
        !          1442: 
        !          1443: 
        !          1444: 
        !          1445:        if (giveindex) {
        !          1446: 
        !          1447:                namelen -= sizeof(long);
        !          1448: 
        !          1449:                if (namelen <= 0) return ERANGE;
        !          1450: 
        !          1451:                *((long *)name) = index++;
        !          1452: 
        !          1453:                name += sizeof(long);
        !          1454: 
        !          1455:        }
        !          1456: 
        !          1457:        strncpy(name, DIR_NAME(dirh), namelen-1);
        !          1458: 
        !          1459:        name[namelen-1] = 0;
        !          1460: 
        !          1461:        if (curproc->domain == DOM_MINT) {
        !          1462: 
        !          1463:                strlwr(name);
        !          1464: 
        !          1465:        }
        !          1466: 
        !          1467:        if (strlen(DIR_NAME(dirh)) >= namelen)
        !          1468: 
        !          1469:                return ENAMETOOLONG;
        !          1470: 
        !          1471:        else
        !          1472: 
        !          1473:                return 0;
        !          1474: 
        !          1475: }
        !          1476: 
        !          1477: 
        !          1478: 
        !          1479: static long
        !          1480: 
        !          1481: tos_rewinddir(dirh)
        !          1482: 
        !          1483:        DIR *dirh;
        !          1484: 
        !          1485: {
        !          1486: 
        !          1487:        struct tindex *ti = (struct tindex *)dirh->fc.index;
        !          1488: 
        !          1489:        long r;
        !          1490: 
        !          1491: 
        !          1492: 
        !          1493:        (void)tfullpath(tmpbuf, ti, "*.*");
        !          1494: 
        !          1495:        do_setdta(DIR_DTA(dirh));
        !          1496: 
        !          1497:        r = Fsfirst(tmpbuf, FILEORDIR);
        !          1498: 
        !          1499:        if (r == 0) {
        !          1500: 
        !          1501:                DIR_FLAG(dirh) = STARTSEARCH;
        !          1502: 
        !          1503:        } else {
        !          1504: 
        !          1505:                DIR_FLAG(dirh) = NMFILE;
        !          1506: 
        !          1507:        }
        !          1508: 
        !          1509:        return r;
        !          1510: 
        !          1511: }
        !          1512: 
        !          1513: 
        !          1514: 
        !          1515: static long
        !          1516: 
        !          1517: tos_closedir(dirh)
        !          1518: 
        !          1519:        DIR *dirh;
        !          1520: 
        !          1521: {
        !          1522: 
        !          1523:        struct tindex *t = (struct tindex *)dirh->fc.index;
        !          1524: 
        !          1525: 
        !          1526: 
        !          1527:        assert(t->open);
        !          1528: 
        !          1529:        --t->open;
        !          1530: 
        !          1531:        DIR_FLAG(dirh) = NMFILE;
        !          1532: 
        !          1533:        return 0;
        !          1534: 
        !          1535: }
        !          1536: 
        !          1537: 
        !          1538: 
        !          1539: static long
        !          1540: 
        !          1541: tos_pathconf(dir, which)
        !          1542: 
        !          1543:        fcookie *dir;
        !          1544: 
        !          1545:        int which;
        !          1546: 
        !          1547: {
        !          1548: 
        !          1549:        switch(which) {
        !          1550: 
        !          1551:        case -1:
        !          1552: 
        !          1553:                return DP_MAXREQ;
        !          1554: 
        !          1555:        case DP_IOPEN:
        !          1556: 
        !          1557:                return 60;      /* we can only keep about this many open */
        !          1558: 
        !          1559:        case DP_MAXLINKS:
        !          1560: 
        !          1561:                 return 1;      /* no hard links */
        !          1562: 
        !          1563:        case DP_PATHMAX:
        !          1564: 
        !          1565:                return PATH_MAX;
        !          1566: 
        !          1567:        case DP_NAMEMAX:
        !          1568: 
        !          1569:                return 8+3+1;
        !          1570: 
        !          1571:        case DP_ATOMIC:
        !          1572: 
        !          1573:                return 512;     /* we can write at least a sector atomically */
        !          1574: 
        !          1575:        case DP_TRUNC:
        !          1576: 
        !          1577:                return DP_DOSTRUNC;     /* DOS style file names */
        !          1578: 
        !          1579:        case DP_CASE:
        !          1580: 
        !          1581:                return DP_CASECONV;     /* names converted to upper case */
        !          1582: 
        !          1583:        default:
        !          1584: 
        !          1585:                return EINVFN;
        !          1586: 
        !          1587:        }
        !          1588: 
        !          1589: }
        !          1590: 
        !          1591: 
        !          1592: 
        !          1593: long
        !          1594: 
        !          1595: tos_dfree(dir, buf)
        !          1596: 
        !          1597:        fcookie *dir;
        !          1598: 
        !          1599:        long *buf;
        !          1600: 
        !          1601: {
        !          1602: 
        !          1603:        return Dfree(buf, (dir->dev)+1);
        !          1604: 
        !          1605: }
        !          1606: 
        !          1607: 
        !          1608: 
        !          1609: /*
        !          1610: 
        !          1611:  * writelabel: creates a volume label
        !          1612: 
        !          1613:  * readlabel: reads a volume label
        !          1614: 
        !          1615:  * both of these are only guaranteed to work in the root directory
        !          1616: 
        !          1617:  */
        !          1618: 
        !          1619: 
        !          1620: 
        !          1621: /*
        !          1622: 
        !          1623:  * BUG: this should first delete any old labels, so that it will
        !          1624: 
        !          1625:  * work with TOS <1.4
        !          1626: 
        !          1627:  */
        !          1628: 
        !          1629: 
        !          1630: 
        !          1631: long
        !          1632: 
        !          1633: tos_writelabel(dir, name)
        !          1634: 
        !          1635:        fcookie *dir;
        !          1636: 
        !          1637:        const char *name;
        !          1638: 
        !          1639: {
        !          1640: 
        !          1641:        long r;
        !          1642: 
        !          1643:        struct tindex *ti;
        !          1644: 
        !          1645: 
        !          1646: 
        !          1647:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
        !          1648: 
        !          1649:        r = Fcreate(tmpbuf, FA_LABEL);
        !          1650: 
        !          1651:        if (r < 0) return r;
        !          1652: 
        !          1653:        (void)Fclose(r);
        !          1654: 
        !          1655:        ti = tstrindex(tmpbuf);
        !          1656: 
        !          1657:        ti->valid = 0;
        !          1658: 
        !          1659:        return 0;
        !          1660: 
        !          1661: }
        !          1662: 
        !          1663: 
        !          1664: 
        !          1665: long
        !          1666: 
        !          1667: tos_readlabel(dir, name, namelen)
        !          1668: 
        !          1669:        fcookie *dir;
        !          1670: 
        !          1671:        char *name;
        !          1672: 
        !          1673:        int namelen;
        !          1674: 
        !          1675: {
        !          1676: 
        !          1677:        long r;
        !          1678: 
        !          1679:        struct tindex *ti = (struct tindex *)dir->index;
        !          1680: 
        !          1681: 
        !          1682: 
        !          1683:        if (ti->name[2] != 0)           /* not a root directory? */
        !          1684: 
        !          1685:                return EFILNF;
        !          1686: 
        !          1687: 
        !          1688: 
        !          1689:        (void)tfullpath(tmpbuf, ti, "*.*");
        !          1690: 
        !          1691:        do_setdta(&foo);
        !          1692: 
        !          1693:        r = Fsfirst(tmpbuf, FA_LABEL);
        !          1694: 
        !          1695:        if (r)
        !          1696: 
        !          1697:                return r;
        !          1698: 
        !          1699:        strncpy(name, foo.dta_name, namelen-1);
        !          1700: 
        !          1701:        return (strlen(foo.dta_name) < namelen) ? 0 : ENAMETOOLONG;
        !          1702: 
        !          1703: }
        !          1704: 
        !          1705: 
        !          1706: 
        !          1707: /*
        !          1708: 
        !          1709:  * TOS creat: this doesn't actually create the file, rather it
        !          1710: 
        !          1711:  * sets up a (fake) index for the file that will be used by
        !          1712: 
        !          1713:  * the later tos_open call.
        !          1714: 
        !          1715:  */
        !          1716: 
        !          1717: 
        !          1718: 
        !          1719: static long
        !          1720: 
        !          1721: tos_creat(dir, name, mode, attrib, fc)
        !          1722: 
        !          1723:        fcookie *dir;
        !          1724: 
        !          1725:        const char *name;
        !          1726: 
        !          1727:        unsigned mode;
        !          1728: 
        !          1729:        int attrib;
        !          1730: 
        !          1731:        fcookie *fc;
        !          1732: 
        !          1733: {
        !          1734: 
        !          1735:        struct tindex *ti;
        !          1736: 
        !          1737: 
        !          1738: 
        !          1739:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
        !          1740: 
        !          1741: 
        !          1742: 
        !          1743:        ti = tstrindex(tmpbuf);
        !          1744: 
        !          1745:        ti->size = 0;
        !          1746: 
        !          1747:        ti->date = datestamp;
        !          1748: 
        !          1749:        ti->time = timestamp;
        !          1750: 
        !          1751:        ti->attr = attrib;
        !          1752: 
        !          1753:        ti->valid = 1;
        !          1754: 
        !          1755: 
        !          1756: 
        !          1757:        fc->fs = &tos_filesys;
        !          1758: 
        !          1759:        fc->index = (long)ti;
        !          1760: 
        !          1761:        fc->dev = dir->dev;
        !          1762: 
        !          1763:        return 0;
        !          1764: 
        !          1765: }
        !          1766: 
        !          1767:        
        !          1768: 
        !          1769: /*
        !          1770: 
        !          1771:  * TOS device driver
        !          1772: 
        !          1773:  */
        !          1774: 
        !          1775: 
        !          1776: 
        !          1777: static DEVDRV *
        !          1778: 
        !          1779: tos_getdev(fc, devsp)
        !          1780: 
        !          1781:        fcookie *fc;
        !          1782: 
        !          1783:        long *devsp;
        !          1784: 
        !          1785: {
        !          1786: 
        !          1787:        return &tos_device;
        !          1788: 
        !          1789: }
        !          1790: 
        !          1791: 
        !          1792: 
        !          1793: static long
        !          1794: 
        !          1795: tos_open(f)
        !          1796: 
        !          1797:        FILEPTR *f;
        !          1798: 
        !          1799: {
        !          1800: 
        !          1801:        struct tindex *ti;
        !          1802: 
        !          1803:        int mode = f->flags;
        !          1804: 
        !          1805:        int tosmode;
        !          1806: 
        !          1807:        long r;
        !          1808: 
        !          1809:        extern int flk;         /* in main.c, set if _FLK cookie already present */
        !          1810: 
        !          1811: 
        !          1812: 
        !          1813:        ti = (struct tindex *)(f->fc.index);
        !          1814: 
        !          1815:        assert(ti != 0);
        !          1816: 
        !          1817: 
        !          1818: 
        !          1819:        ti->stamp = ++tclock;
        !          1820: 
        !          1821:        ti->valid = 0;
        !          1822: 
        !          1823: 
        !          1824: 
        !          1825: /* TEMPORARY HACK: change all modes to O_RDWR for files opened in
        !          1826: 
        !          1827:  * compatibility sharing mode. This is silly, but
        !          1828: 
        !          1829:  * allows broken TOS programs that write to read-only handles to continue
        !          1830: 
        !          1831:  * to work (it also helps file sharing, by making the realistic assumption
        !          1832: 
        !          1833:  * that any open TOS file can be written to). Eventually,
        !          1834: 
        !          1835:  * this should be tuneable by the user somehow.
        !          1836: 
        !          1837:  * ALSO: change O_COMPAT opens into O_DENYNONE; again, this may be temporary.
        !          1838: 
        !          1839:  */
        !          1840: 
        !          1841:        if ( (mode & O_SHMODE) == O_COMPAT ) {
        !          1842: 
        !          1843:                f->flags = (mode & ~(O_RWMODE|O_SHMODE)) | O_RDWR | O_DENYNONE;
        !          1844: 
        !          1845:        }
        !          1846: 
        !          1847: 
        !          1848: 
        !          1849: /* check to see that nobody has opened this file already in an
        !          1850: 
        !          1851:  * incompatible mode
        !          1852: 
        !          1853:  */
        !          1854: 
        !          1855:        if (denyshare(ti->open, f)) {
        !          1856: 
        !          1857:                TRACE("tos_open: file sharing denied");
        !          1858: 
        !          1859:                return EACCDN;
        !          1860: 
        !          1861:        }
        !          1862: 
        !          1863: 
        !          1864: 
        !          1865: /*
        !          1866: 
        !          1867:  * now open the file; if O_TRUNC was specified, actually
        !          1868: 
        !          1869:  * create the file anew.
        !          1870: 
        !          1871:  * BUG: O_TRUNC without O_CREAT doesn't work right. The kernel doesn't
        !          1872: 
        !          1873:  * use this mode, anyways
        !          1874: 
        !          1875:  */
        !          1876: 
        !          1877: 
        !          1878: 
        !          1879:        if (mode & O_TRUNC) {
        !          1880: 
        !          1881:                if (ti->open) {
        !          1882: 
        !          1883:                        DEBUG("tos_open: attempt to truncate an open file");
        !          1884: 
        !          1885:                        return EACCDN;
        !          1886: 
        !          1887:                }
        !          1888: 
        !          1889:                r = Fcreate(ti->name, ti->attr);
        !          1890: 
        !          1891:        } else {
        !          1892: 
        !          1893:                if (flk)
        !          1894: 
        !          1895:                        tosmode = mode & (O_RWMODE|O_SHMODE);
        !          1896: 
        !          1897:                else
        !          1898: 
        !          1899:                        tosmode = (mode & O_RWMODE);
        !          1900: 
        !          1901:                if (tosmode == O_EXEC) tosmode = O_RDONLY;
        !          1902: 
        !          1903: 
        !          1904: 
        !          1905:                r = Fopen(ti->name, tosmode );
        !          1906: 
        !          1907:                if (r == EFILNF && (mode & O_CREAT))
        !          1908: 
        !          1909:                        r = Fcreate(ti->name, ti->attr);
        !          1910: 
        !          1911:        }
        !          1912: 
        !          1913: 
        !          1914: 
        !          1915:        if (r < 0) {
        !          1916: 
        !          1917: /* get rid of the index for the file, since it doesn't exist */
        !          1918: 
        !          1919:                kfree(ti->name);
        !          1920: 
        !          1921:                ti->name = 0;
        !          1922: 
        !          1923:                ti->valid = 0;
        !          1924: 
        !          1925:                return r;
        !          1926: 
        !          1927:        }
        !          1928: 
        !          1929: 
        !          1930: 
        !          1931:        f->devinfo = r;
        !          1932: 
        !          1933: 
        !          1934: 
        !          1935:        f->next = ti->open;
        !          1936: 
        !          1937:        ti->open = f;
        !          1938: 
        !          1939:        return 0;
        !          1940: 
        !          1941: }
        !          1942: 
        !          1943: 
        !          1944: 
        !          1945: static long
        !          1946: 
        !          1947: tos_write(f, buf, bytes)
        !          1948: 
        !          1949:        FILEPTR *f; const char *buf; long bytes;
        !          1950: 
        !          1951: {
        !          1952: 
        !          1953:        struct tindex *ti = (struct tindex *)f->fc.index;
        !          1954: 
        !          1955: 
        !          1956: 
        !          1957:        ti->valid = 0;
        !          1958: 
        !          1959:        return Fwrite((int)f->devinfo, bytes, buf);
        !          1960: 
        !          1961: }
        !          1962: 
        !          1963: 
        !          1964: 
        !          1965: static long
        !          1966: 
        !          1967: tos_read(f, buf, bytes)
        !          1968: 
        !          1969:        FILEPTR *f; char *buf; long bytes;
        !          1970: 
        !          1971: {
        !          1972: 
        !          1973:        return Fread((int)f->devinfo, bytes, buf);
        !          1974: 
        !          1975: }
        !          1976: 
        !          1977: 
        !          1978: 
        !          1979: static long
        !          1980: 
        !          1981: tos_lseek(f, where, whence)
        !          1982: 
        !          1983:        FILEPTR *f; long where; int whence;
        !          1984: 
        !          1985: {
        !          1986: 
        !          1987:        long r;
        !          1988: 
        !          1989: 
        !          1990: 
        !          1991:        r = Fseek(where, (int)f->devinfo, whence);
        !          1992: 
        !          1993:        return r;
        !          1994: 
        !          1995: }
        !          1996: 
        !          1997: 
        !          1998: 
        !          1999: static long
        !          2000: 
        !          2001: tos_ioctl(f, mode, buf)
        !          2002: 
        !          2003:        FILEPTR *f; int mode; void *buf;
        !          2004: 
        !          2005: {
        !          2006: 
        !          2007:        LOCK t, *lck, **old;
        !          2008: 
        !          2009:        struct flock *fl;
        !          2010: 
        !          2011:        long r;
        !          2012: 
        !          2013:        struct tindex *ti;
        !          2014: 
        !          2015:        extern int flk;         /* set in main.c if _FLK already installed */
        !          2016: 
        !          2017: 
        !          2018: 
        !          2019:        if (mode == FIONREAD || mode == FIONWRITE) {
        !          2020: 
        !          2021:                *((long *)buf) = 1;
        !          2022: 
        !          2023:                return 0;
        !          2024: 
        !          2025:        }
        !          2026: 
        !          2027:        else if (mode == F_SETLK || mode == F_GETLK) {
        !          2028: 
        !          2029:                fl = ((struct flock *)buf);
        !          2030: 
        !          2031:                t.l = *fl;
        !          2032: 
        !          2033:                switch(t.l.l_whence) {
        !          2034: 
        !          2035:                case 0:
        !          2036: 
        !          2037:                        break;
        !          2038: 
        !          2039:                case 1:         /* SEEK_CUR */
        !          2040: 
        !          2041:                        r = Fseek(0L, (int)f->devinfo, 1);
        !          2042: 
        !          2043:                        t.l.l_start += r;
        !          2044: 
        !          2045:                        break;
        !          2046: 
        !          2047:                case 2:
        !          2048: 
        !          2049:                        r = Fseek(0L, (int)f->devinfo, 1);
        !          2050: 
        !          2051:                        t.l.l_start = Fseek(t.l.l_start, (int)f->devinfo, 2);
        !          2052: 
        !          2053:                        (void)Fseek(r, (int)f->devinfo, 0);
        !          2054: 
        !          2055:                        break;
        !          2056: 
        !          2057:                default:
        !          2058: 
        !          2059:                        DEBUG("Invalid value for l_whence");
        !          2060: 
        !          2061:                        return EINVFN;
        !          2062: 
        !          2063:                }
        !          2064: 
        !          2065: /* BUG: can't lock a file starting at >2gigabytes from the beginning */
        !          2066: 
        !          2067:                if (t.l.l_start < 0) t.l.l_start = 0;
        !          2068: 
        !          2069:                t.l.l_whence = 0;
        !          2070: 
        !          2071:                ti = (struct tindex *)f->fc.index;
        !          2072: 
        !          2073: 
        !          2074: 
        !          2075:                if (mode == F_GETLK) {
        !          2076: 
        !          2077:                        lck = denylock(ti->locks, &t);
        !          2078: 
        !          2079:                        if (lck)
        !          2080: 
        !          2081:                                *fl = lck->l;
        !          2082: 
        !          2083:                        else
        !          2084: 
        !          2085:                                fl->l_type = F_UNLCK;
        !          2086: 
        !          2087:                        return 0;
        !          2088: 
        !          2089:                }
        !          2090: 
        !          2091: 
        !          2092: 
        !          2093:                if (t.l.l_type == F_UNLCK) {
        !          2094: 
        !          2095:                /* try to find the lock */
        !          2096: 
        !          2097:                        old = &ti->locks;
        !          2098: 
        !          2099:                        lck = *old;
        !          2100: 
        !          2101:                        while (lck) {
        !          2102: 
        !          2103:                                if (lck->l.l_pid == curproc->pid &&
        !          2104: 
        !          2105:                                    lck->l.l_start == t.l.l_start &&
        !          2106: 
        !          2107:                                    lck->l.l_len == t.l.l_len) {
        !          2108: 
        !          2109:                /* found it -- remove the lock */
        !          2110: 
        !          2111:                                        *old = lck->next;
        !          2112: 
        !          2113:                                        TRACE("tosfs: unlocked %s: %ld + %ld",
        !          2114: 
        !          2115:                                                ti->name, t.l.l_start, t.l.l_len);
        !          2116: 
        !          2117:                                        kfree(lck);
        !          2118: 
        !          2119:                                        if (flk)
        !          2120: 
        !          2121:                                            (void)Flock((int)f->devinfo, 1,
        !          2122: 
        !          2123:                                                        t.l.l_start, t.l.l_len);
        !          2124: 
        !          2125:                                        break;
        !          2126: 
        !          2127:                                }
        !          2128: 
        !          2129:                                old = &lck->next;
        !          2130: 
        !          2131:                                lck = lck->next;
        !          2132: 
        !          2133:                        }
        !          2134: 
        !          2135:                        return lck ?  0 : ENSLOCK;
        !          2136: 
        !          2137:                }
        !          2138: 
        !          2139:                TRACE("tosfs: lock %s: %ld + %ld", ti->name,
        !          2140: 
        !          2141:                        t.l.l_start, t.l.l_len);
        !          2142: 
        !          2143:        /* see if there's a conflicting lock */
        !          2144: 
        !          2145:                lck = denylock(ti->locks, &t);
        !          2146: 
        !          2147:                if (lck) {
        !          2148: 
        !          2149:                        DEBUG("tosfs: lock conflicts with one held by %d",
        !          2150: 
        !          2151:                                lck->l.l_pid);
        !          2152: 
        !          2153:                        return ELOCKED;
        !          2154: 
        !          2155:                }
        !          2156: 
        !          2157:        /* if not, add this lock to the list */
        !          2158: 
        !          2159:                lck = kmalloc(SIZEOF(LOCK));
        !          2160: 
        !          2161:                if (!lck) return ENSMEM;
        !          2162: 
        !          2163:        /* see if other _FLK code might object */
        !          2164: 
        !          2165:                if (flk) {
        !          2166: 
        !          2167:                        r = Flock((int)f->devinfo, 0, t.l.l_start, t.l.l_len);
        !          2168: 
        !          2169:                        if (r) {
        !          2170: 
        !          2171:                                kfree(lck);
        !          2172: 
        !          2173:                                return r;
        !          2174: 
        !          2175:                        }
        !          2176: 
        !          2177:                }
        !          2178: 
        !          2179:                lck->l = t.l;
        !          2180: 
        !          2181:                lck->l.l_pid = curproc->pid;
        !          2182: 
        !          2183:                lck->next = ti->locks;
        !          2184: 
        !          2185:                ti->locks = lck;
        !          2186: 
        !          2187:        /* mark the file as being locked */
        !          2188: 
        !          2189:                f->flags |= O_LOCK;
        !          2190: 
        !          2191:                return 0;
        !          2192: 
        !          2193:        }
        !          2194: 
        !          2195:        return EINVFN;
        !          2196: 
        !          2197: }
        !          2198: 
        !          2199: 
        !          2200: 
        !          2201: static long
        !          2202: 
        !          2203: tos_datime(f, timeptr, rwflag)
        !          2204: 
        !          2205:        FILEPTR *f;
        !          2206: 
        !          2207:        short *timeptr;
        !          2208: 
        !          2209:        int rwflag;
        !          2210: 
        !          2211: {
        !          2212: 
        !          2213:        if (rwflag) {
        !          2214: 
        !          2215:                struct tindex *ti = (struct tindex *)f->fc.index;
        !          2216: 
        !          2217:                ti->valid = 0;
        !          2218: 
        !          2219:        }
        !          2220: 
        !          2221:        return Fdatime(timeptr, (int)f->devinfo, rwflag);
        !          2222: 
        !          2223: }
        !          2224: 
        !          2225: 
        !          2226: 
        !          2227: static long
        !          2228: 
        !          2229: tos_close(f, pid)
        !          2230: 
        !          2231:        FILEPTR *f;
        !          2232: 
        !          2233:        int pid;
        !          2234: 
        !          2235: {
        !          2236: 
        !          2237:        LOCK *lck, **oldl;
        !          2238: 
        !          2239:        struct tindex *t;
        !          2240: 
        !          2241:        FILEPTR **old, *p;
        !          2242: 
        !          2243:        long r = 0;
        !          2244: 
        !          2245:        extern int flk;         /* set in main.c */
        !          2246: 
        !          2247: 
        !          2248: 
        !          2249:        t = (struct tindex *)(f->fc.index);
        !          2250: 
        !          2251: /* if this handle was locked, remove any locks held by the process
        !          2252: 
        !          2253:  */
        !          2254: 
        !          2255:        if (f->flags & O_LOCK) {
        !          2256: 
        !          2257:                TRACE("tos_close: releasing locks (file mode: %x)", f->flags);
        !          2258: 
        !          2259:                oldl = &t->locks;
        !          2260: 
        !          2261:                lck = *oldl;
        !          2262: 
        !          2263:                while (lck) {
        !          2264: 
        !          2265:                        if (lck->l.l_pid == pid) {
        !          2266: 
        !          2267:                                *oldl = lck->next;
        !          2268: 
        !          2269:                                if (flk)
        !          2270: 
        !          2271:                                        (void)Flock((int)f->devinfo, 1,
        !          2272: 
        !          2273:                                                lck->l.l_start, lck->l.l_len);
        !          2274: 
        !          2275:                                kfree(lck);
        !          2276: 
        !          2277:                        } else {
        !          2278: 
        !          2279:                                oldl = &lck->next;
        !          2280: 
        !          2281:                        }
        !          2282: 
        !          2283:                        lck = *oldl;
        !          2284: 
        !          2285:                }
        !          2286: 
        !          2287:        }
        !          2288: 
        !          2289: 
        !          2290: 
        !          2291:        if (f->links <= 0) {
        !          2292: 
        !          2293: /* remove f from the list of open file pointers on this index */
        !          2294: 
        !          2295:                t->valid = 0;
        !          2296: 
        !          2297:                old = &t->open;
        !          2298: 
        !          2299:                p = t->open;
        !          2300: 
        !          2301:                while (p && p != f) {
        !          2302: 
        !          2303:                        old = &p->next;
        !          2304: 
        !          2305:                        p = p->next;
        !          2306: 
        !          2307:                }
        !          2308: 
        !          2309:                assert(p);
        !          2310: 
        !          2311:                *old = f->next;
        !          2312: 
        !          2313:                f->next = 0;
        !          2314: 
        !          2315:                r = Fclose((int)f->devinfo);
        !          2316: 
        !          2317: 
        !          2318: 
        !          2319: /* if the file was marked for deletion, delete it */
        !          2320: 
        !          2321:                if (!t->open) {
        !          2322: 
        !          2323:                        if (t->attr & FA_DELETE) {
        !          2324: 
        !          2325:                                (void)Fdelete(t->name);
        !          2326: 
        !          2327:                                t->name = 0;
        !          2328: 
        !          2329:                        }
        !          2330: 
        !          2331:                }
        !          2332: 
        !          2333:        }
        !          2334: 
        !          2335:        return r;
        !          2336: 
        !          2337: }
        !          2338: 
        !          2339: 
        !          2340: 
        !          2341: /*
        !          2342: 
        !          2343:  * check for disk change: called by the kernel if Mediach returns a
        !          2344: 
        !          2345:  * non-zero value
        !          2346: 
        !          2347:  */
        !          2348: 
        !          2349: 
        !          2350: 
        !          2351: long
        !          2352: 
        !          2353: tos_dskchng(drv)
        !          2354: 
        !          2355:        int drv;
        !          2356: 
        !          2357: {
        !          2358: 
        !          2359:        char dlet;
        !          2360: 
        !          2361:        int i;
        !          2362: 
        !          2363:        struct tindex *ti;
        !          2364: 
        !          2365: 
        !          2366: 
        !          2367:        dlet = 'A' + drv;
        !          2368: 
        !          2369:        ti = gl_ti;
        !          2370: 
        !          2371:        for (i = 0; i < NUM_INDICES; i++, ti++) {
        !          2372: 
        !          2373:                if (ti->name[0] == dlet) {
        !          2374: 
        !          2375:                        kfree(ti->name);
        !          2376: 
        !          2377:                        ti->name = 0;
        !          2378: 
        !          2379:                }
        !          2380: 
        !          2381:        }
        !          2382: 
        !          2383: /*
        !          2384: 
        !          2385:  * OK, make sure that GEMDOS knows to look for a change if we
        !          2386: 
        !          2387:  * ever use this drive again.
        !          2388: 
        !          2389:  */
        !          2390: 
        !          2391:        drvchanged[drv] = 1;
        !          2392: 
        !          2393:        return 1;
        !          2394: 
        !          2395: }
        !          2396: 
        !          2397: 
        !          2398: 
        !          2399: /*
        !          2400: 
        !          2401:  * utility function: sets the TOS DTA, and also records what directory
        !          2402: 
        !          2403:  * this was in. This is just to save us a call into the kernel if the
        !          2404: 
        !          2405:  * correct DTA has already been set.
        !          2406: 
        !          2407:  */
        !          2408: 
        !          2409: 
        !          2410: 
        !          2411: static void
        !          2412: 
        !          2413: do_setdta(dta)
        !          2414: 
        !          2415:        DTABUF *dta;
        !          2416: 
        !          2417: {
        !          2418: 
        !          2419:        if (dta != lastdta) {
        !          2420: 
        !          2421:                Fsetdta(dta);
        !          2422: 
        !          2423:                lastdta = dta;
        !          2424: 
        !          2425:        }
        !          2426: 
        !          2427: }
        !          2428: 
        !          2429: 
        !          2430: 
        !          2431: /*
        !          2432: 
        !          2433:  * routines for forcing a media change on drive "drv"
        !          2434: 
        !          2435:  */
        !          2436: 
        !          2437: 
        !          2438: 
        !          2439: static int chdrv;
        !          2440: 
        !          2441: 
        !          2442: 
        !          2443: /* new Getbpb function: when this is called, all the other
        !          2444: 
        !          2445:  * vectors can be un-installed
        !          2446: 
        !          2447:  */
        !          2448: 
        !          2449: 
        !          2450: 
        !          2451: static long (*Oldgetbpb) P_((int));
        !          2452: 
        !          2453: static long (*Oldmediach) P_((int));
        !          2454: 
        !          2455: static long (*Oldrwabs) P_((int, void *, int, int, int, long));
        !          2456: 
        !          2457: 
        !          2458: 
        !          2459: static long
        !          2460: 
        !          2461: Newgetbpb(d)
        !          2462: 
        !          2463:        int d;
        !          2464: 
        !          2465: {
        !          2466: 
        !          2467:        if (d == chdrv) {
        !          2468: 
        !          2469:                *((Func *)0x472L) = Oldgetbpb;
        !          2470: 
        !          2471:                *((Func *)0x476L) = Oldrwabs;
        !          2472: 
        !          2473:                *((Func *)0x47eL) = Oldmediach;
        !          2474: 
        !          2475:        }
        !          2476: 
        !          2477:        return (*Oldgetbpb)(d);
        !          2478: 
        !          2479: }
        !          2480: 
        !          2481: 
        !          2482: 
        !          2483: static long
        !          2484: 
        !          2485: Newmediach(d)
        !          2486: 
        !          2487:        int d;
        !          2488: 
        !          2489: {
        !          2490: 
        !          2491:        if (d == chdrv)
        !          2492: 
        !          2493:                return 2;
        !          2494: 
        !          2495:        return (*Oldmediach)(d);
        !          2496: 
        !          2497: }
        !          2498: 
        !          2499: 
        !          2500: 
        !          2501: static long
        !          2502: 
        !          2503: Newrwabs(d, buf, a, b, c, l)
        !          2504: 
        !          2505:        int d;
        !          2506: 
        !          2507:        void *buf;
        !          2508: 
        !          2509:        int a, b, c;
        !          2510: 
        !          2511:        long l;
        !          2512: 
        !          2513: {
        !          2514: 
        !          2515:        if (d == chdrv)
        !          2516: 
        !          2517:                return E_CHNG;
        !          2518: 
        !          2519:        return (*Oldrwabs)(d, buf, a, b, c, l);
        !          2520: 
        !          2521: }
        !          2522: 
        !          2523: 
        !          2524: 
        !          2525: static void
        !          2526: 
        !          2527: force_mediach(d)
        !          2528: 
        !          2529:        int d;
        !          2530: 
        !          2531: {
        !          2532: 
        !          2533:        long r;
        !          2534: 
        !          2535:        static char fname[] = "X:\\.INF";
        !          2536: 
        !          2537: 
        !          2538: 
        !          2539:        TRACE("tosfs: disk change drive %c", d+'A');
        !          2540: 
        !          2541: 
        !          2542: 
        !          2543:        chdrv = d;
        !          2544: 
        !          2545:        Oldrwabs = *((Func *)0x476L);
        !          2546: 
        !          2547:        if (Oldrwabs == Newrwabs) {
        !          2548: 
        !          2549:                ALERT("tosfs: error in media change code");
        !          2550: 
        !          2551:        } else {
        !          2552: 
        !          2553:                *((Func *)0x476L) = Newrwabs;
        !          2554: 
        !          2555:                Oldmediach = *((Func *)0x47eL);
        !          2556: 
        !          2557:                *((Func *)0x47eL) = Newmediach;
        !          2558: 
        !          2559:                Oldgetbpb = *((Func *)0x472L);
        !          2560: 
        !          2561:                *((Func *)0x472L) = Newgetbpb;
        !          2562: 
        !          2563:        }
        !          2564: 
        !          2565: 
        !          2566: 
        !          2567:        fname[0] = d + 'A';
        !          2568: 
        !          2569:        r = Fopen(fname, 0);
        !          2570: 
        !          2571:        if (r >= 0) (void)Fclose(r);
        !          2572: 
        !          2573: 
        !          2574: 
        !          2575:        drvchanged[d] = 0;
        !          2576: 
        !          2577: }
        !          2578: 

unix.superglobalmegacorp.com

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