Annotation of MiNT/src/tosfs.c, revision 1.1.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.