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

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

unix.superglobalmegacorp.com

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