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

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

unix.superglobalmegacorp.com

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