Annotation of MiNT/src/filesys.c, revision 1.1.1.6

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1990,1991,1992 Eric R. Smith.
                      4: 
1.1.1.5   root        5: Copyright 1992,1993,1994 Atari Corp.
1.1.1.3   root        6: 
                      7: All rights reserved.
1.1       root        8: 
                      9: */
                     10: 
                     11: 
                     12: 
                     13: /*
                     14: 
                     15:  * various file system interface things
                     16: 
                     17:  */
                     18: 
                     19: 
                     20: 
                     21: #include "mint.h"
                     22: 
                     23: 
                     24: 
1.1.1.3   root       25: #define PATH2COOKIE_DB(x) TRACE(x)
                     26: 
                     27: 
                     28: 
1.1       root       29: FILESYS *active_fs;
                     30: 
                     31: FILESYS *drives[NUM_DRIVES];
                     32: 
1.1.1.3   root       33: extern FILESYS tos_filesys;    /* declaration needed for debugging only */
                     34: 
1.1       root       35: 
                     36: 
1.1.1.2   root       37: /* "aliased" drives are different names
                     38: 
                     39:  * for real drives/directories
                     40: 
                     41:  * if drive d is an alias for c:\usr,
                     42: 
                     43:  * then alias_drv[3] == 2 (the real
                     44: 
                     45:  * drive) and aliases has bit (1L << 3)
                     46: 
                     47:  * set.
                     48: 
                     49:  * NOTE: if aliasdrv[d] is 0, then d is not an aliased drive,
                     50: 
                     51:  * otherwise d is aliased to drive aliasdrv[d]-1
                     52: 
                     53:  * (e.g. if drive A: is aliased to B:\FOO, then
                     54: 
                     55:  * aliasdrv[0] == 'B'-'A'+1 == 2). Always remember to
                     56: 
                     57:  * compensate for the extra 1 when dereferencing aliasdrv!
                     58: 
                     59:  */
                     60: 
                     61: int    aliasdrv[NUM_DRIVES];
                     62: 
                     63: 
                     64: 
1.1       root       65: FILEPTR *flist;                /* a list of free file pointers */
                     66: 
                     67: 
                     68: 
                     69: /* vector of valid drives, according to GEMDOS */
                     70: 
                     71: /* note that this isn't necessarily the same as what the BIOS thinks of
                     72: 
                     73:  * as valid
                     74: 
                     75:  */
                     76: 
                     77: long dosdrvs;
                     78: 
                     79: 
                     80: 
                     81: /*
                     82: 
                     83:  * Initialize a specific drive. This is called whenever a new drive
                     84: 
                     85:  * is accessed, or when media change occurs on an old drive.
                     86: 
                     87:  * Assumption: at this point, active_fs is a valid pointer
                     88: 
                     89:  * to a list of file systems.
                     90: 
                     91:  */
                     92: 
                     93: 
                     94: 
                     95: /* table of processes holding locks on drives */
                     96: 
                     97: extern PROC *dlockproc[];      /* in dosdir.c */
                     98: 
                     99: 
                    100: 
                    101: void
                    102: 
                    103: init_drive(i)
                    104: 
                    105:        int i;
                    106: 
                    107: {
                    108: 
                    109:        long r;
                    110: 
                    111:        FILESYS *fs;
                    112: 
                    113:        fcookie root_dir;
                    114: 
                    115: 
                    116: 
1.1.1.2   root      117:        TRACE(("init_drive(%c)", i+'A'));
1.1       root      118: 
                    119: 
                    120: 
                    121:        drives[i] = 0;          /* no file system */
                    122: 
                    123:        if (i >= 0 && i < NUM_DRIVES) {
                    124: 
                    125:                if (dlockproc[i]) return;
                    126: 
                    127:        }
                    128: 
                    129: 
                    130: 
                    131:        for (fs = active_fs; fs; fs = fs->next) {
                    132: 
                    133:                r = (*fs->root)(i, &root_dir);
                    134: 
                    135:                if (r == 0) {
                    136: 
                    137:                        drives[i] = root_dir.fs;
                    138: 
1.1.1.3   root      139:                        release_cookie(&root_dir);
                    140: 
1.1       root      141:                        break;
                    142: 
                    143:                }
                    144: 
                    145:        }
                    146: 
                    147: }
                    148: 
                    149: 
                    150: 
                    151: /*
                    152: 
                    153:  * initialize the file system
                    154: 
                    155:  */
                    156: 
                    157: 
                    158: 
                    159: #define NUMFPS 40      /* initial number of file pointers */
                    160: 
                    161: 
                    162: 
                    163: void
                    164: 
                    165: init_filesys()
                    166: 
                    167: {
                    168: 
                    169:        static FILEPTR initial[NUMFPS+1];
                    170: 
                    171:        int i;
                    172: 
                    173:        extern FILESYS tos_filesys, bios_filesys, pipe_filesys,
                    174: 
                    175:                proc_filesys, uni_filesys;
                    176: 
                    177: 
                    178: 
                    179: /* get the vector of connected GEMDOS drives */
                    180: 
                    181:        dosdrvs = Dsetdrv(Dgetdrv()) | drvmap();
                    182: 
                    183: 
                    184: 
                    185: /* set up some initial file pointers */
                    186: 
                    187:        for (i = 0; i < NUMFPS; i++) {
                    188: 
                    189:                initial[i].devinfo = (ulong) (&initial[i+1]);
                    190: 
                    191:        }
                    192: 
                    193:        initial[NUMFPS].devinfo = 0;
                    194: 
                    195:        flist = initial;
                    196: 
                    197: 
                    198: 
                    199: /* set up the file systems */
                    200: 
                    201:        tos_filesys.next = 0;
                    202: 
                    203:        bios_filesys.next = &tos_filesys;
                    204: 
                    205:        pipe_filesys.next = &bios_filesys;
                    206: 
                    207:        proc_filesys.next = &pipe_filesys;
                    208: 
                    209:        uni_filesys.next = &proc_filesys;
                    210: 
                    211: 
                    212: 
                    213:        active_fs = &uni_filesys;
                    214: 
                    215: 
                    216: 
                    217: /* initialize the BIOS file system */
                    218: 
                    219:        biosfs_init();
                    220: 
                    221: 
                    222: 
                    223: /* initialize the unified file system */
                    224: 
                    225:        unifs_init();
                    226: 
                    227: }
                    228: 
                    229: 
                    230: 
                    231: /*
                    232: 
                    233:  * load file systems from disk
                    234: 
                    235:  * this routine is called after process 0 is set up, but before any user
                    236: 
                    237:  * processes are run
                    238: 
                    239:  *
                    240: 
                    241:  * NOTE that a number of directory changes take place here: we look first
                    242: 
1.1.1.4   root      243:  * in the current directory, then in the directory \mint.
1.1       root      244: 
                    245:  */
                    246: 
                    247: 
                    248: 
1.1.1.2   root      249: typedef FILESYS * ARGS_ON_STACK (*FSFUNC) P_((struct kerinfo *));
1.1       root      250: 
                    251: 
                    252: 
1.1.1.4   root      253: /* uk: made this lie outside of functions, as load_filesys() and
                    254: 
                    255:  *     load_devdriver() need access to it.
                    256: 
                    257:  */
                    258: 
                    259: #define NPATHS 3
                    260: 
1.1.1.6 ! root      261: static const char *const ext_paths[NPATHS] = {"", "\\MINT", "\\MULTITOS"};
1.1.1.4   root      262: 
                    263: 
                    264: 
1.1       root      265: void
                    266: 
                    267: load_filesys()
                    268: 
                    269: {
                    270: 
                    271:        long r;
                    272: 
                    273:        BASEPAGE *b;
                    274: 
                    275:        FILESYS *fs;
                    276: 
                    277:        FSFUNC initf;
                    278: 
                    279:        static DTABUF dta;
                    280: 
                    281:        int i;
                    282: 
                    283:        extern struct kerinfo kernelinfo; /* in main.c */
                    284: 
1.1.1.2   root      285:        char curpath[PATH_MAX];
                    286: 
1.1.1.3   root      287:        MEMREGION *xfsreg;
                    288: 
1.1       root      289: 
                    290: 
                    291:        curproc->dta = &dta;
                    292: 
1.1.1.2   root      293:        d_getpath(curpath,0);
                    294: 
1.1       root      295: 
                    296: 
                    297:        for (i = 0; i < NPATHS; i++) {
                    298: 
1.1.1.4   root      299:            if (*ext_paths[i]) {
1.1.1.2   root      300: 
                    301: /* don't bother checking the current directory twice! */
                    302: 
1.1.1.4   root      303:                    if (!stricmp(ext_paths[i],curpath))
1.1.1.2   root      304: 
                    305:                        r = -1;
                    306: 
                    307:                    else
                    308: 
1.1.1.4   root      309:                        r = d_setpath(ext_paths[i]);
1.1.1.2   root      310: 
                    311:            }
                    312: 
                    313:            else
                    314: 
                    315:                    r = 0;
                    316: 
                    317: 
                    318: 
                    319:            if (r == 0)
                    320: 
                    321:                    r = f_sfirst("*.xfs", 0);
1.1       root      322: 
                    323: 
                    324: 
                    325:            while (r == 0) {
                    326: 
                    327:                b = (BASEPAGE *)p_exec(3, dta.dta_name, (char *)"", (char *)0);
                    328: 
                    329:                if ( ((long)b) < 0 ) {
                    330: 
1.1.1.2   root      331:                        DEBUG(("Error loading file system %s", dta.dta_name));
                    332: 
                    333:                        r = f_snext();
1.1       root      334: 
                    335:                        continue;
                    336: 
                    337:                }
                    338: 
                    339:        /* we leave a little bit of slop at the end of the loaded stuff */
                    340: 
                    341:                m_shrink(0, (virtaddr)b, 512 + b->p_tlen + b->p_dlen + b->p_blen);
                    342: 
                    343:                initf = (FSFUNC)b->p_tbase;
                    344: 
1.1.1.2   root      345:                TRACE(("initializing %s", dta.dta_name));
1.1       root      346: 
1.1.1.2   root      347:                fs = (*initf)(&kernelinfo);
1.1       root      348: 
                    349: 
                    350: 
                    351:                if (fs) {
                    352: 
1.1.1.2   root      353:                        TRACE(("%s loaded OK", dta.dta_name));
1.1       root      354: 
1.1.1.3   root      355:        /* put the loaded XFS into super accesible memory */
                    356: 
                    357:                        xfsreg = addr2region( (long) b );
                    358: 
                    359:                        mark_region(xfsreg, PROT_S);
                    360: 
1.1.1.4   root      361: 
                    362: 
1.1.1.3   root      363:        /* link it into the list of drivers */
                    364: 
1.1.1.4   root      365:        /* uk: but only if it has not installed itself via Dcntl()
                    366: 
                    367:         *     after checking if file system is already installed,
                    368: 
                    369:         *     so we know for sure that each file system in at most
                    370: 
                    371:         *     once in the chain (important for removal!)
                    372: 
                    373:         * also note: this doesn't preclude loading two different
                    374: 
                    375:         * instances of the same file system driver, e.g. it's perfectly
                    376: 
                    377:         * OK to have a "cdromy1.xfs" and "cdromz2.xfs"; the check below
                    378: 
                    379:         * just makes sure that a given instance of a file system is
                    380: 
                    381:         * installed at most once. I.e., it prevents cdromy1.xfs from being
                    382: 
                    383:         * installed twice.
                    384: 
                    385:         */
1.1       root      386: 
1.1.1.4   root      387:                        if ((FILESYS*)1L != fs) {
                    388: 
                    389:                                FILESYS *f = active_fs;
                    390: 
                    391:                                for (;  f;  f = f->next)
                    392: 
                    393:                                        if (f == fs)
                    394: 
                    395:                                                break;
                    396: 
                    397:                                if (!f) {   /* we ran completly through the list */
                    398: 
                    399:                                        fs->next = active_fs;
                    400: 
                    401:                                        active_fs = fs;
                    402: 
                    403:                                }
                    404: 
                    405:                        }
1.1       root      406: 
                    407:                } else {
                    408: 
1.1.1.2   root      409:                        DEBUG(("%s returned null", dta.dta_name));
1.1       root      410: 
1.1.1.3   root      411:                        m_free((virtaddr)b);
                    412: 
1.1       root      413:                }
                    414: 
                    415:                r = f_snext();
                    416: 
                    417:            }
                    418: 
                    419:        }
                    420: 
                    421: 
                    422: 
1.1.1.4   root      423: #if 0
                    424: 
1.1       root      425: /* here, we invalidate all old drives EXCEPT for ones we're already using (at
                    426: 
                    427:  * this point, only the bios devices should be open)
                    428: 
                    429:  * this gives newly loaded file systems a chance to replace the
                    430: 
                    431:  * default tosfs.c
                    432: 
                    433:  */
                    434: 
                    435:        for (i = 0; i < NUM_DRIVES; i++) {
                    436: 
                    437:                if (d_lock(1, i) == 0)  /* lock if possible */
                    438: 
                    439:                        d_lock(0, i);   /* and then unlock */
                    440: 
                    441:        }
                    442: 
1.1.1.4   root      443: #endif
                    444: 
1.1       root      445: }
                    446: 
                    447: 
                    448: 
1.1.1.4   root      449: 
                    450: 
                    451: /*
                    452: 
                    453:  * uk: load device driver in files called *.xdd (external device driver)
                    454: 
                    455:  *     from disk
                    456: 
                    457:  * maybe this should go into biosfs.c ??
                    458: 
                    459:  *
                    460: 
                    461:  * this routine is called after process 0 is set up, but before any user
                    462: 
                    463:  * processes are run, but before the loadable file systems come in,
                    464: 
                    465:  * so they can make use of external device drivers
                    466: 
                    467:  *
                    468: 
                    469:  * NOTE that a number of directory changes take place here: we look first
                    470: 
                    471:  * in the current directory, then in the directory \mint, and finally
                    472: 
                    473:  * the d_lock() calls force us into the root directory.
                    474: 
                    475:  * ??? what d_lock() calls ???
                    476: 
                    477:  */
                    478: 
                    479: 
                    480: 
                    481: typedef DEVDRV * ARGS_ON_STACK (*DEVFUNC) P_((struct kerinfo *));
                    482: 
                    483: 
                    484: 
                    485: #define DEV_SELFINST  ((DEVDRV*)1L)  /* dev driver did dcntl() already */
                    486: 
                    487: 
                    488: 
                    489: void
                    490: 
                    491: load_devdriver()
                    492: 
                    493: {
                    494: 
                    495:        long r;
                    496: 
                    497:        BASEPAGE *b;
                    498: 
                    499:        DEVDRV *dev;
                    500: 
                    501:        DEVFUNC initf;
                    502: 
                    503:        struct dev_descr the_dev;
                    504: 
                    505:        static DTABUF dta;
                    506: 
                    507:        int i;
                    508: 
                    509:        extern struct kerinfo kernelinfo; /* in main.c */
                    510: 
                    511:        char curpath[PATH_MAX];
                    512: 
                    513:        char dev_name[PATH_MAX];  /* a bit long, but one never knows... */
                    514: 
                    515:        char ch, *p;
                    516: 
                    517:        MEMREGION *xddreg;
                    518: 
                    519: 
                    520: 
                    521: 
                    522: 
                    523:        curproc->dta = &dta;
                    524: 
                    525:        d_getpath(curpath,0);
                    526: 
                    527: 
                    528: 
                    529:        for (i = 0; i < NPATHS; i++) {
                    530: 
                    531:            if (*ext_paths[i]) {
                    532: 
                    533: /* don't bother checking the current directory twice! */
                    534: 
                    535:                    if (!stricmp(ext_paths[i],curpath))
                    536: 
                    537:                        r = -1;
                    538: 
                    539:                    else
                    540: 
                    541:                        r = d_setpath(ext_paths[i]);
                    542: 
                    543:            }
                    544: 
                    545:            else
                    546: 
                    547:                    r = 0;
                    548: 
                    549: 
                    550: 
                    551:            if (r == 0)
                    552: 
                    553:                    r = f_sfirst("*.xdd", 0);
                    554: 
                    555: 
                    556: 
                    557:            while (r == 0) {
                    558: 
                    559:                b = (BASEPAGE *)p_exec(3, dta.dta_name, (char *)"", (char *)0);
                    560: 
                    561:                if ( ((long)b) < 0 ) {
                    562: 
                    563:                        DEBUG(("Error loading device driver %s", dta.dta_name));
                    564: 
                    565:                        r = f_snext();
                    566: 
                    567:                        continue;
                    568: 
                    569:                }
                    570: 
                    571:        /* we leave a little bit of slop at the end of the loaded stuff */
                    572: 
                    573:                m_shrink(0, (virtaddr)b, 512 + b->p_tlen + b->p_dlen + b->p_blen);
                    574: 
                    575:                initf = (DEVFUNC)b->p_tbase;
                    576: 
                    577:                TRACE(("initializing %s", dta.dta_name));
                    578: 
                    579:                dev = (*initf)(&kernelinfo);
                    580: 
                    581: 
                    582: 
                    583:                if (dev) {
                    584: 
                    585:                        if (DEV_SELFINST != dev) {
                    586: 
                    587:        /* we need to install the device driver ourselves */
                    588: 
                    589:                                the_dev.driver = dev;
                    590: 
                    591:                                the_dev.dinfo = 0;
                    592: 
                    593:                                the_dev.flags = 0;
                    594: 
                    595:                                the_dev.tty = (struct tty*)0L;
                    596: 
                    597:                                the_dev.reserved[0] = the_dev.reserved[1] = 0;
                    598: 
1.1.1.6 ! root      599:                                the_dev.reserved[2] = 0;
1.1.1.4   root      600: 
                    601:                                p = dta.dta_name;
                    602: 
1.1.1.5   root      603:        /* copy the dev. driver name, converting to lower case */
                    604: 
                    605:                                while (*p && *p != '.') {
                    606: 
                    607:                                        *p = tolower(*p);
                    608: 
                    609:                                        p++;
                    610: 
                    611:                                }
1.1.1.4   root      612: 
                    613:                                ch = *p;
                    614: 
                    615:                                *p = '\0';  /* we dont want the extension */
                    616: 
                    617:                                strcpy(dev_name, "u:\\dev\\");
                    618: 
                    619:                                strcat(dev_name, dta.dta_name);
                    620: 
                    621:                                *p = ch;
                    622: 
                    623:                                r = d_cntl(DEV_INSTALL, dev_name, (long)&the_dev);
                    624: 
                    625:                                if (r <= 0) {
                    626: 
                    627:                                        DEBUG(("Error installing device driver %s", dta.dta_name));
                    628: 
                    629:                                        r = f_snext();
                    630: 
                    631:                                        continue;
                    632: 
                    633:                                }
                    634: 
                    635:                        }
                    636: 
                    637:                        TRACE(("%s loaded OK", dta.dta_name));
                    638: 
                    639:        /* put the loaded XDD into super accesible memory */
                    640: 
                    641:                        xddreg = addr2region( (long) b );
                    642: 
                    643:                        mark_region(xddreg, PROT_S);
                    644: 
                    645:                } else {
                    646: 
                    647:                        DEBUG(("%s returned null", dta.dta_name));
                    648: 
                    649:                        m_free((virtaddr)b);
                    650: 
                    651:                }
                    652: 
                    653:                r = f_snext();
                    654: 
                    655:            }
                    656: 
                    657:        }
                    658: 
                    659: }
                    660: 
                    661:  
                    662: 
                    663: 
                    664: 
1.1       root      665: void
                    666: 
                    667: close_filesys()
                    668: 
                    669: {
                    670: 
                    671:        PROC *p;
                    672: 
                    673:        FILEPTR *f;
                    674: 
                    675:        int i;
                    676: 
                    677: 
                    678: 
1.1.1.2   root      679:        TRACE(("close_filesys"));
1.1       root      680: 
                    681: /* close every open file */
                    682: 
                    683:        for (p = proclist; p; p = p->gl_next) {
                    684: 
                    685:                for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                    686: 
                    687:                        if ( (f = p->handle[i]) != 0) {
                    688: 
                    689:                                if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q)
                    690: 
                    691:                                        ALERT("Open file for dead process?");
                    692: 
                    693:                                do_pclose(p, f);
                    694: 
                    695:                        }
                    696: 
                    697:                }
                    698: 
                    699:        }
                    700: 
                    701: }
                    702: 
                    703: 
                    704: 
                    705: /*
                    706: 
                    707:  * "media change" routine: called when a media change is detected on device
                    708: 
                    709:  * d, which may or may not be a BIOS device. All handles associated with
                    710: 
                    711:  * the device are closed, and all directories invalidated. This routine
                    712: 
                    713:  * does all the dirty work, and is called automatically when
                    714: 
                    715:  * disk_changed detects a media change.
                    716: 
                    717:  */
                    718: 
                    719: 
                    720: 
1.1.1.2   root      721: void ARGS_ON_STACK 
1.1       root      722: 
                    723: changedrv(d)
                    724: 
                    725:        unsigned d;
                    726: 
                    727: {
                    728: 
                    729:        PROC *p;
                    730: 
                    731:        int i;
                    732: 
                    733:        FILEPTR *f;
                    734: 
                    735:        FILESYS *fs;
                    736: 
1.1.1.6 ! root      737:        SHTEXT *stext, **old;
1.1.1.3   root      738: 
                    739:        extern SHTEXT *text_reg;        /* in mem.c */
                    740: 
1.1       root      741:        DIR *dirh;
                    742: 
                    743:        fcookie dir;
                    744: 
1.1.1.5   root      745:        int warned = (d & 0xf000) == PROC_RDEV_BASE;
1.1       root      746: 
1.1.1.2   root      747:        long r;
                    748: 
                    749: 
                    750: 
                    751: /* if an aliased drive, change the *real* device */
                    752: 
                    753:        if (d < NUM_DRIVES && aliasdrv[d]) {
                    754: 
                    755:                d = aliasdrv[d] - 1;    /* see NOTE above */
                    756: 
                    757:        }
1.1       root      758: 
                    759: 
                    760: 
                    761: /* re-initialize the device, if it was a BIOS device */
                    762: 
                    763:        if (d < NUM_DRIVES) {
                    764: 
                    765:                fs = drives[d];
                    766: 
                    767:                if (fs) {
                    768: 
                    769:                        (void)(*fs->dskchng)(d);
                    770: 
                    771:                }
                    772: 
                    773:                init_drive(d);
                    774: 
                    775:        }
                    776: 
                    777: 
                    778: 
                    779:        for (p = proclist; p; p = p->gl_next) {
                    780: 
                    781:        /* invalidate all open files on this device */
                    782: 
                    783:                for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                    784: 
1.1.1.6 ! root      785:                        if (((f = p->handle[i]) != 0) &&
        !           786: 
        !           787:                                (f != (FILEPTR *)1) && (f->fc.dev == d)) {
1.1       root      788: 
                    789:                            if (!warned) {
                    790: 
                    791:                                ALERT(
                    792: 
                    793: "Files were open on a changed drive (0x%x)!", d);
                    794: 
                    795:                                warned++;
                    796: 
                    797:                            }
                    798: 
                    799: 
                    800: 
                    801: /* we set f->dev to NULL to indicate to do_pclose that this is an
                    802: 
                    803:  * emergency close, and that it shouldn't try to make any
                    804: 
                    805:  * calls to the device driver since the file has gone away
                    806: 
                    807:  */
                    808: 
                    809:                            f->dev = NULL;
                    810: 
                    811:                            (void)do_pclose(p, f);
                    812: 
1.1.1.2   root      813: /* we could just zero the handle, but this could lead to confusion if
                    814: 
                    815:  * a process doesn't realize that there's been a media change, Fopens
                    816: 
                    817:  * a new file, and gets the same handle back. So, we force the
                    818: 
                    819:  * handle to point to /dev/null.
                    820: 
                    821:  */
                    822: 
                    823:                            p->handle[i] =
                    824: 
                    825:                                do_open("U:\\DEV\\NULL", O_RDWR, 0, (XATTR *)0);
1.1       root      826: 
                    827:                        }
                    828: 
                    829:                }
                    830: 
                    831: 
                    832: 
                    833:        /* terminate any active directory searches on the drive */
                    834: 
                    835:                for (i = 0; i < NUM_SEARCH; i++) {
                    836: 
1.1.1.2   root      837:                        dirh = &p->srchdir[i];
1.1       root      838: 
1.1.1.4   root      839:                        if (p->srchdta[i] && dirh->fc.fs && dirh->fc.dev == d) {
1.1       root      840: 
1.1.1.2   root      841:                                TRACE(("closing search for process %d", p->pid));
                    842: 
1.1.1.3   root      843:                                release_cookie(&dirh->fc);
                    844: 
1.1       root      845:                                dirh->fc.fs = 0;
                    846: 
1.1.1.2   root      847:                                p->srchdta[i] = 0;
1.1       root      848: 
                    849:                        }
                    850: 
                    851:                }
                    852: 
                    853: 
                    854: 
1.1.1.4   root      855:                for (dirh = p->searches; dirh; dirh = dirh->next) {
                    856: 
                    857:                    /* If this search is on the changed drive, release
                    858: 
                    859:                       the cookie, but do *not* free it, since the
                    860: 
                    861:                       user could later call closedir on it. */
                    862: 
                    863:                        if (dirh->fc.fs && dirh->fc.dev == d) {
                    864: 
                    865:                                release_cookie (&dirh->fc);
                    866: 
                    867:                                dirh->fc.fs = 0;
                    868: 
                    869:                        }
                    870: 
                    871:                }
                    872: 
                    873:                    
                    874: 
1.1       root      875:                if (d >= NUM_DRIVES) continue;
                    876: 
                    877: 
                    878: 
                    879:        /* change any active directories on the device to the (new) root */
                    880: 
                    881:                fs = drives[d];
                    882: 
                    883:                if (fs) {
                    884: 
                    885:                        r = (*fs->root)(d, &dir);
                    886: 
                    887:                        if (r != E_OK) dir.fs = 0;
                    888: 
                    889:                } else {
                    890: 
                    891:                        dir.fs = 0; dir.dev = d;
                    892: 
                    893:                }
                    894: 
                    895: 
                    896: 
                    897:                for (i = 0; i < NUM_DRIVES; i++) {
                    898: 
1.1.1.3   root      899:                        if (p->root[i].dev == d) {
                    900: 
                    901:                                release_cookie(&p->root[i]);
1.1       root      902: 
1.1.1.3   root      903:                                dup_cookie(&p->root[i], &dir);
                    904: 
                    905:                        }
1.1       root      906: 
1.1.1.3   root      907:                        if (p->curdir[i].dev == d) {
1.1       root      908: 
1.1.1.3   root      909:                                release_cookie(&p->curdir[i]);
                    910: 
                    911:                                dup_cookie(&p->curdir[i], &dir);
                    912: 
                    913:                        }
                    914: 
                    915:                }
                    916: 
                    917:                release_cookie(&dir);
                    918: 
                    919:        }
                    920: 
                    921: 
                    922: 
                    923: /* free any file descriptors associated with shared text regions */
                    924: 
1.1.1.6 ! root      925:        for (old = &text_reg; 0 != (stext = *old);) {
1.1.1.3   root      926: 
                    927:                f = stext->f;
                    928: 
                    929:                if (f->fc.dev == d) {
                    930: 
                    931:                        f->dev = NULL;
                    932: 
                    933:                        do_pclose(rootproc, f);
                    934: 
                    935:                        stext->f = 0;
1.1       root      936: 
1.1.1.6 ! root      937: /* free region if unattached */
        !           938: 
        !           939:                        if (stext->text->links == 0xffff) {
        !           940: 
        !           941:                                stext->text->links = 0;
        !           942: 
        !           943:                                stext->text->mflags &= ~(M_SHTEXT|M_SHTEXT_T);
        !           944: 
        !           945:                                free_region(stext->text);
        !           946: 
        !           947:                                *old = stext->next;
        !           948: 
        !           949:                                kfree(stext);
        !           950: 
        !           951:                                continue;
        !           952: 
        !           953:                        }
        !           954: 
        !           955: /* else clear `sticky bit' */
        !           956: 
        !           957:                        stext->text->mflags &= ~M_SHTEXT_T;
        !           958: 
1.1       root      959:                }
                    960: 
1.1.1.6 ! root      961:                old = &stext->next;
        !           962: 
1.1       root      963:        }
                    964: 
                    965: }
                    966: 
                    967: 
                    968: 
                    969: /*
                    970: 
                    971:  * check for media change: if the drive has changed, call changedrv to
                    972: 
                    973:  * invalidate any open files and file handles associated with it, and
                    974: 
                    975:  * call the file system's media change routine.
                    976: 
1.1.1.4   root      977:  * returns: 0 if no change, 1 if change, negative number for error
1.1       root      978: 
                    979:  */
                    980: 
                    981: 
                    982: 
                    983: int
                    984: 
                    985: disk_changed(d)
                    986: 
                    987:        int d;
                    988: 
                    989: {
                    990: 
                    991:        short r;
                    992: 
                    993:        FILESYS *fs;
                    994: 
                    995:        static char tmpbuf[8192];
                    996: 
                    997: 
                    998: 
                    999: /* for now, only check BIOS devices */
                   1000: 
                   1001:        if (d < 0 || d >= NUM_DRIVES)
                   1002: 
                   1003:                return 0;
                   1004: 
1.1.1.2   root     1005: /* watch out for aliased drives */
                   1006: 
                   1007:        if (aliasdrv[d]) {
                   1008: 
                   1009:                d = aliasdrv[d] - 1;
                   1010: 
                   1011:                if (d < 0 || d >= NUM_DRIVES)
                   1012: 
                   1013:                        return 0;
                   1014: 
                   1015:        }
                   1016: 
1.1       root     1017: 
                   1018: 
                   1019: /* has the drive been initialized yet? If not, then initialize it and return
                   1020: 
                   1021:  * "no change"
                   1022: 
                   1023:  */
                   1024: 
1.1.1.2   root     1025:        fs = drives[d];
                   1026: 
                   1027:        if (!fs) {
1.1       root     1028: 
1.1.1.2   root     1029:                TRACE(("drive %c not yet initialized", d+'A'));
1.1       root     1030: 
                   1031:                changedrv(d);
                   1032: 
                   1033:                return 0;
                   1034: 
                   1035:        }
                   1036: 
                   1037: 
                   1038: 
                   1039: /* We have to do this stuff no matter what, because someone may have installed
                   1040: 
                   1041:  * vectors to force a media change...
                   1042: 
                   1043:  * PROBLEM: AHDI may get upset if the drive isn't valid.
                   1044: 
                   1045:  * SOLUTION: don't change the default PSEUDODRIVES setting!
                   1046: 
                   1047:  */
                   1048: 
1.1.1.4   root     1049: 
                   1050: 
                   1051: TRACE(("calling mediach(%d)",d));
                   1052: 
                   1053:        r = (int)mediach(d);
                   1054: 
                   1055: TRACE(("mediach(%d) == %d", d, r));
                   1056: 
                   1057: 
                   1058: 
1.1.1.5   root     1059:        if (r < 0) {
                   1060: 
                   1061: /* KLUDGE: some .XFS drivers don't install BIOS vectors, and so we'll
                   1062: 
                   1063:  * always get EUNDEV back from them. This isn't recommended (since there
                   1064: 
                   1065:  * are other programs than MiNT that may ask for BIOS functions from
                   1066: 
                   1067:  * any installed drives). This is a temporary work-around until those
                   1068: 
                   1069:  * .XFSes are changed to either install BIOS vectors or to use the
                   1070: 
                   1071:  * new U: Dcntl() calls to install themselves.
                   1072: 
                   1073:  * Note that EUNDEV must be tested for drives A-C, or else booting may
                   1074: 
                   1075:  * not work properly.
                   1076: 
                   1077:  */
                   1078: 
                   1079:                if (d > 2 && r == EUNDEV)
                   1080: 
1.1.1.6 ! root     1081:                        return 0;       /* assume no change */
1.1.1.5   root     1082: 
                   1083:                else
                   1084: 
                   1085:                        return r;
                   1086: 
                   1087:        }
1.1       root     1088: 
                   1089:        if (r == 1) {           /* drive _may_ have changed */
                   1090: 
                   1091:                r = rwabs(0, tmpbuf, 1, 0, d, 0L);      /* check the BIOS */
                   1092: 
                   1093:                if (r != E_CHNG) {                      /* nope, no change */
                   1094: 
1.1.1.4   root     1095:                        TRACE(("rwabs returned %d", r));
                   1096: 
                   1097:                        return (r < 0) ? r : 0;
1.1       root     1098: 
                   1099:                }
                   1100: 
                   1101:                r = 2;                  /* drive was definitely changed */
                   1102: 
                   1103:        }
                   1104: 
                   1105:        if (r == 2) {
                   1106: 
1.1.1.4   root     1107:                TRACE(("definite media change"));
                   1108: 
1.1       root     1109:                fs = drives[d];         /* get filesystem associated with drive */
                   1110: 
                   1111:                if ((*fs->dskchng)(d)) { /* does the fs agree that it changed? */
                   1112: 
1.1.1.2   root     1113:                        drives[d] = 0;
                   1114: 
1.1       root     1115:                        changedrv(d);   /* yes -- do the change */
                   1116: 
                   1117:                        return 1;
                   1118: 
                   1119:                }
                   1120: 
                   1121:        }
                   1122: 
                   1123:        return 0;
                   1124: 
                   1125: }
                   1126: 
                   1127: 
                   1128: 
                   1129: /*
                   1130: 
                   1131:  * routines for parsing path names
                   1132: 
                   1133:  */
                   1134: 
                   1135: 
                   1136: 
                   1137: #define DIRSEP(p) ((p) == '\\')
                   1138: 
                   1139: 
                   1140: 
                   1141: /*
                   1142: 
                   1143:  * relpath2cookie converts a TOS file name into a file cookie representing
                   1144: 
                   1145:  * the directory the file resides in, and a character string representing
                   1146: 
                   1147:  * the name of the file in that directory. The character string is
                   1148: 
                   1149:  * copied into the "lastname" array. If lastname is NULL, then the cookie
                   1150: 
                   1151:  * returned actually represents the file, instead of just the directory
                   1152: 
                   1153:  * the file is in.
                   1154: 
                   1155:  *
                   1156: 
                   1157:  * note that lastname, if non-null, should be big enough to contain all the
                   1158: 
                   1159:  * characters in "path", since if the file system doesn't want the kernel
                   1160: 
                   1161:  * to do path name parsing we may end up just copying path to lastname
                   1162: 
                   1163:  * and returning the current or root directory, as appropriate
                   1164: 
                   1165:  *
                   1166: 
                   1167:  * "relto" is the directory relative to which the search should start.
                   1168: 
                   1169:  * if you just want the current directory, use path2cookie instead.
                   1170: 
                   1171:  *
                   1172: 
                   1173:  */
                   1174: 
                   1175: 
                   1176: 
                   1177: #define MAX_LINKS 4
                   1178: 
                   1179: 
                   1180: 
                   1181: long
                   1182: 
                   1183: relpath2cookie(relto, path, lastname, res, depth)
                   1184: 
                   1185:        fcookie *relto;
                   1186: 
                   1187:        const char *path;
                   1188: 
                   1189:        char *lastname;
                   1190: 
                   1191:        fcookie *res;
                   1192: 
                   1193:        int depth;
                   1194: 
                   1195: {
                   1196: 
1.1.1.3   root     1197:        fcookie dir;
1.1       root     1198: 
                   1199:        int drv;
                   1200: 
                   1201:        int len;
                   1202: 
                   1203:        char c, *s;
                   1204: 
                   1205:        XATTR xattr;
                   1206: 
                   1207:        static char newpath[16] = "U:\\DEV\\";
                   1208: 
                   1209:        char temp2[PATH_MAX];
                   1210: 
                   1211:        char linkstuff[PATH_MAX];
                   1212: 
1.1.1.3   root     1213:        long r;
1.1       root     1214: 
                   1215: 
                   1216: 
                   1217: /* dolast: 0 == return a cookie for the directory the file is in
                   1218: 
                   1219:  *         1 == return a cookie for the file itself, don't follow links
                   1220: 
                   1221:  *        2 == return a cookie for whatever the file points at
                   1222: 
                   1223:  */
                   1224: 
                   1225:        int dolast = 0;
                   1226: 
                   1227:        int i = 0;
                   1228: 
                   1229: 
                   1230: 
                   1231:        if (!lastname) {
                   1232: 
                   1233:                dolast = 1;
                   1234: 
                   1235:                lastname = temp2;
                   1236: 
                   1237:        } else if (lastname == follow_links) {
                   1238: 
                   1239:                dolast = 2;
                   1240: 
                   1241:                lastname = temp2;
                   1242: 
                   1243:        }
                   1244: 
                   1245: 
                   1246: 
                   1247:        *lastname = 0;
                   1248: 
                   1249: 
                   1250: 
1.1.1.3   root     1251: PATH2COOKIE_DB(("relpath2cookie(%s, dolast=%d, depth=%d)", path, dolast, depth));
                   1252: 
                   1253: 
                   1254: 
                   1255:        if (depth > MAX_LINKS) {
                   1256: 
                   1257:                DEBUG(("Too many symbolic links"));
                   1258: 
                   1259:                return ELOOP;
                   1260: 
                   1261:        }
                   1262: 
1.1       root     1263: /* special cases: CON:, AUX:, etc. should be converted to U:\DEV\CON,
                   1264: 
                   1265:  * U:\DEV\AUX, etc.
                   1266: 
                   1267:  */
                   1268: 
                   1269:        if (strlen(path) == 4 && path[3] == ':') {
                   1270: 
                   1271:                strncpy(newpath+7, path, 3);
                   1272: 
                   1273:                path = newpath;
                   1274: 
                   1275:        }
                   1276: 
                   1277: 
                   1278: 
                   1279: /* first, check for a drive letter */
                   1280: 
                   1281: /* BUG: a '\' at the start of a symbolic link is relative to the current
                   1282: 
                   1283:  * drive of the process, not the drive the link is located on
                   1284: 
                   1285:  */
                   1286: 
1.1.1.3   root     1287:        if (path[1] == ':') {
1.1       root     1288: 
                   1289:                c = path[0];
                   1290: 
                   1291:                if (c >= 'a' && c <= 'z')
                   1292: 
                   1293:                        drv = c - 'a';
                   1294: 
                   1295:                else if (c >= 'A' && c <= 'Z')
                   1296: 
                   1297:                        drv = c - 'A';
                   1298: 
                   1299:                else
                   1300: 
                   1301:                        goto nodrive;
                   1302: 
                   1303:                path += 2;
                   1304: 
                   1305:                i = 1;          /* remember that we saw a drive letter */
                   1306: 
                   1307:        } else {
                   1308: 
                   1309: nodrive:
                   1310: 
                   1311:                drv = curproc->curdrv;
                   1312: 
                   1313:        }
                   1314: 
                   1315: 
                   1316: 
                   1317: /* see if the path is rooted from '\\' */
                   1318: 
                   1319:        if (DIRSEP(*path)) {
                   1320: 
                   1321:                while(DIRSEP(*path))path++;
                   1322: 
1.1.1.3   root     1323:                dup_cookie(&dir, &curproc->root[drv]);
1.1       root     1324: 
                   1325:        } else {
                   1326: 
                   1327:                if (i)  {       /* an explicit drive letter was given */
                   1328: 
1.1.1.3   root     1329:                        dup_cookie(&dir, &curproc->curdir[drv]);
1.1       root     1330: 
                   1331:                }
                   1332: 
                   1333:                else
                   1334: 
1.1.1.3   root     1335:                        dup_cookie(&dir, relto);
1.1       root     1336: 
                   1337:        }
                   1338: 
                   1339: 
                   1340: 
                   1341:        if (!dir.fs) {
                   1342: 
                   1343:                changedrv(dir.dev);
                   1344: 
1.1.1.3   root     1345:                dup_cookie(&dir, &curproc->root[drv]);
1.1       root     1346: 
                   1347:        }
                   1348: 
                   1349: 
                   1350: 
                   1351:        if (!dir.fs) {
                   1352: 
1.1.1.3   root     1353:                DEBUG(("path2cookie: no file system: returning EDRIVE"));
1.1       root     1354: 
                   1355:                return EDRIVE;
                   1356: 
                   1357:        }
                   1358: 
                   1359: 
                   1360: 
1.1.1.3   root     1361:        /* here's where we come when we've gone across a mount point */
1.1       root     1362: 
1.1.1.3   root     1363:        
1.1       root     1364: 
1.1.1.3   root     1365: restart_mount:
1.1       root     1366: 
                   1367: 
                   1368: 
1.1.1.3   root     1369:        if (!*path) {           /* nothing more to do */
1.1       root     1370: 
1.1.1.3   root     1371: PATH2COOKIE_DB(("relpath2cookie: no more path, returning 0"));
1.1       root     1372: 
1.1.1.3   root     1373:                *res = dir;
1.1       root     1374: 
1.1.1.3   root     1375:                return 0;
                   1376: 
                   1377:        }
1.1       root     1378: 
                   1379: 
                   1380: 
                   1381: /* see if there has been a disk change; if so, return E_CHNG.
                   1382: 
                   1383:  * path2cookie will restart the search automatically; other functions
                   1384: 
                   1385:  * that call relpath2cookie directly will have to fail gracefully
                   1386: 
                   1387:  */
                   1388: 
1.1.1.4   root     1389:        if ((r = disk_changed(dir.dev)) != 0) {
1.1       root     1390: 
1.1.1.3   root     1391:                release_cookie(&dir);
                   1392: 
1.1.1.4   root     1393:                if (r > 0) r = E_CHNG;
                   1394: 
                   1395: PATH2COOKIE_DB(("relpath2cookie: returning %d", r));
1.1.1.3   root     1396: 
1.1.1.4   root     1397:                return r;
1.1       root     1398: 
                   1399:        }
                   1400: 
                   1401: 
                   1402: 
1.1.1.3   root     1403: 
                   1404: 
1.1       root     1405:        if (dir.fs->fsflags & FS_KNOPARSE) {
                   1406: 
                   1407:                if (!dolast) {
                   1408: 
1.1.1.3   root     1409: PATH2COOKIE_DB(("fs is a KNOPARSE, nothing to do"));
                   1410: 
1.1       root     1411:                        strncpy(lastname, path, PATH_MAX-1);
                   1412: 
                   1413:                        lastname[PATH_MAX - 1] = 0;
                   1414: 
                   1415:                        r = 0;
                   1416: 
1.1.1.3   root     1417:                        *res = dir;
                   1418: 
1.1       root     1419:                } else {
                   1420: 
1.1.1.3   root     1421: PATH2COOKIE_DB(("fs is a KNOPARSE, calling lookup"));
                   1422: 
1.1       root     1423:                        r = (*dir.fs->lookup)(&dir, path, res);
                   1424: 
1.1.1.3   root     1425:                        if (r == EMOUNT) {      /* hmmm... a ".." at a mount point, maybe */
1.1       root     1426: 
1.1.1.3   root     1427:                                fcookie mounteddir;
1.1       root     1428: 
1.1.1.3   root     1429:                                r = (*dir.fs->root)(dir.dev, &mounteddir);
1.1       root     1430: 
1.1.1.3   root     1431:                                if (r == 0 && drv == UNIDRV) {
1.1       root     1432: 
1.1.1.3   root     1433:                                        if (dir.fs == mounteddir.fs &&
1.1       root     1434: 
1.1.1.3   root     1435:                                            dir.index == mounteddir.index &&
1.1       root     1436: 
1.1.1.3   root     1437:                                            dir.dev == mounteddir.dev) {
1.1       root     1438: 
1.1.1.3   root     1439:                                                release_cookie(&dir);
1.1       root     1440: 
1.1.1.3   root     1441:                                                release_cookie(&mounteddir);
1.1       root     1442: 
1.1.1.3   root     1443:                                                dup_cookie(&dir, &curproc->root[UNIDRV]);
1.1       root     1444: 
1.1.1.3   root     1445:                                                TRACE(("path2cookie: restarting from mount point"));
1.1       root     1446: 
1.1.1.3   root     1447:                                                goto restart_mount;
1.1       root     1448: 
1.1.1.3   root     1449:                                        }
1.1       root     1450: 
1.1.1.3   root     1451:                                } else {
1.1       root     1452: 
1.1.1.3   root     1453:                                        if (r == 0)
1.1       root     1454: 
1.1.1.3   root     1455:                                                release_cookie(&mounteddir);
1.1       root     1456: 
1.1.1.3   root     1457:                                        r = 0;
1.1       root     1458: 
1.1.1.3   root     1459:                                }
1.1       root     1460: 
1.1.1.3   root     1461:                        }
1.1       root     1462: 
1.1.1.3   root     1463:                        release_cookie(&dir);
1.1       root     1464: 
1.1.1.3   root     1465:                }
1.1       root     1466: 
1.1.1.3   root     1467:                PATH2COOKIE_DB(("relpath2cookie: returning %ld", r));
1.1       root     1468: 
1.1.1.3   root     1469:                return r;
1.1       root     1470: 
1.1.1.3   root     1471:        }
1.1       root     1472: 
                   1473: 
                   1474: 
                   1475: 
                   1476: 
1.1.1.3   root     1477: /* parse all but (possibly) the last component of the path name */
1.1       root     1478: 
1.1.1.3   root     1479: /* rules here: at the top of the loop, &dir is the cookie of
1.1       root     1480: 
1.1.1.3   root     1481:  * the directory we're in now, xattr is its attributes, and res is unset
1.1       root     1482: 
1.1.1.3   root     1483:  * at the end of the loop, &dir is unset, and either r is nonzero
1.1       root     1484: 
1.1.1.3   root     1485:  * (to indicate an error) or res is set to the final result
1.1       root     1486: 
1.1.1.3   root     1487:  */
1.1       root     1488: 
1.1.1.3   root     1489:        r = (dir.fs->getxattr)(&dir, &xattr);
1.1       root     1490: 
1.1.1.3   root     1491:        if (r) {
1.1       root     1492: 
1.1.1.3   root     1493:                DEBUG(("couldn't get directory attributes"));
1.1       root     1494: 
1.1.1.3   root     1495:                release_cookie(&dir);
1.1       root     1496: 
1.1.1.3   root     1497:                return EINTRN;
1.1       root     1498: 
1.1.1.3   root     1499:        }
1.1       root     1500: 
                   1501: 
                   1502: 
1.1.1.3   root     1503:        while (*path) {
1.1       root     1504: 
                   1505: 
                   1506: 
1.1.1.3   root     1507:        /* now we must have a directory, since there are more things in the path */
1.1       root     1508: 
1.1.1.3   root     1509:                if ((xattr.mode & S_IFMT) != S_IFDIR) {
1.1       root     1510: 
1.1.1.3   root     1511: PATH2COOKIE_DB(("relpath2cookie: not a directory, returning EPTHNF"));
1.1       root     1512: 
1.1.1.3   root     1513:                        release_cookie(&dir);
                   1514: 
                   1515:                        r = EPTHNF;
1.1       root     1516: 
                   1517:                        break;
                   1518: 
                   1519:                }
                   1520: 
1.1.1.3   root     1521:        /* we must also have search permission for the directory */
1.1       root     1522: 
1.1.1.3   root     1523:                if (denyaccess(&xattr, S_IXOTH)) {
1.1       root     1524: 
1.1.1.3   root     1525:                        DEBUG(("search permission in directory denied"));
1.1       root     1526: 
1.1.1.3   root     1527:                        release_cookie(&dir);
1.1       root     1528: 
1.1.1.3   root     1529:                        r = EPTHNF;
1.1       root     1530: 
1.1.1.3   root     1531:                        break;
1.1       root     1532: 
1.1.1.3   root     1533:                }
1.1       root     1534: 
                   1535: 
                   1536: 
1.1.1.3   root     1537:        /* if there's nothing left in the path, we can break here */
1.1       root     1538: 
1.1.1.3   root     1539:                if (!*path) {
1.1       root     1540: 
1.1.1.3   root     1541: PATH2COOKIE_DB(("relpath2cookie: no more path, breaking (1)"));
1.1       root     1542: 
1.1.1.3   root     1543:                        *res = dir;
1.1       root     1544: 
1.1.1.3   root     1545:                        break;
1.1       root     1546: 
1.1.1.3   root     1547:                }
1.1       root     1548: 
                   1549:        /* next, peel off the next name in the path */
                   1550: 
                   1551:                len = 0;
                   1552: 
                   1553:                s = lastname;
                   1554: 
                   1555:                c = *path;
                   1556: 
                   1557:                while (c && !DIRSEP(c)) {
                   1558: 
                   1559:                        if (len++ < PATH_MAX)
                   1560: 
                   1561:                                *s++ = c;
                   1562: 
                   1563:                        c = *++path;
                   1564: 
                   1565:                }
                   1566: 
                   1567:                *s = 0;
                   1568: 
                   1569: 
                   1570: 
1.1.1.3   root     1571:        /* if there are no more names in the path, and we don't want
                   1572: 
                   1573:         * to actually look up the last name, then we're done
                   1574: 
                   1575:         */
                   1576: 
                   1577:                if (dolast == 0 && !*path) {
1.1       root     1578: 
1.1.1.3   root     1579:                        *res = dir;
1.1       root     1580: 
1.1.1.3   root     1581: PATH2COOKIE_DB(("relpath2cookie: no more path, breaking (2)"));
1.1       root     1582: 
                   1583:                        break;
                   1584: 
1.1.1.3   root     1585:                }
                   1586: 
                   1587: 
                   1588: 
                   1589: 
                   1590: 
                   1591:        /* 
                   1592: 
                   1593:         * skip trailing slashes
                   1594: 
                   1595:         */
                   1596: 
                   1597:                while (DIRSEP(*path)) path++;
                   1598: 
                   1599: 
                   1600: 
                   1601: PATH2COOKIE_DB(("relpath2cookie: looking up [%s]", lastname));
                   1602: 
1.1       root     1603: 
                   1604: 
                   1605:                r = (*dir.fs->lookup)(&dir, lastname, res);
                   1606: 
1.1.1.3   root     1607:                if (r == EMOUNT) {
1.1       root     1608: 
1.1.1.3   root     1609:                        fcookie mounteddir;
1.1       root     1610: 
1.1.1.3   root     1611:                        r = (*dir.fs->root)(dir.dev, &mounteddir);
                   1612: 
                   1613:                        if (r == 0 && drv == UNIDRV) {
                   1614: 
                   1615:                                if (samefile(&dir, &mounteddir)) {
                   1616: 
                   1617:                                        release_cookie(&dir);
                   1618: 
                   1619:                                        release_cookie(&mounteddir);
                   1620: 
                   1621:                                        dup_cookie(&dir, &curproc->root[UNIDRV]);
                   1622: 
                   1623:                                        TRACE(("path2cookie: restarting from mount point"));
                   1624: 
                   1625:                                        goto restart_mount;
                   1626: 
                   1627:                                } else if (r == 0) {
                   1628: 
                   1629:                                        r = EINTRN;
                   1630: 
                   1631:                                        release_cookie(&mounteddir);
                   1632: 
                   1633:                                        release_cookie(&dir);
                   1634: 
                   1635:                                        break;
                   1636: 
                   1637:                                }
                   1638: 
                   1639:                        } else if (r == 0) {
                   1640: 
                   1641:                                release_cookie(&mounteddir);
                   1642: 
                   1643:                        } else {
                   1644: 
                   1645:                                release_cookie(&dir);
                   1646: 
                   1647:                                break;
                   1648: 
                   1649:                        }
                   1650: 
                   1651:                } else if (r) {
                   1652: 
1.1.1.5   root     1653:                        if (r == EFILNF && *path) {
                   1654: 
                   1655:                        /* the "file" we didn't find was treated as a directory */
                   1656: 
                   1657:                                r = EPTHNF;
                   1658: 
                   1659:                        }
                   1660: 
1.1.1.3   root     1661:                        release_cookie(&dir);
1.1       root     1662: 
                   1663:                        break;
                   1664: 
                   1665:                }
                   1666: 
                   1667: 
                   1668: 
1.1.1.3   root     1669:        /* check for a symbolic link */
                   1670: 
                   1671:                r = (res->fs->getxattr)(res, &xattr);
                   1672: 
                   1673:                if (r != 0) {
                   1674: 
                   1675:                        DEBUG(("path2cookie: couldn't get file attributes"));
                   1676: 
                   1677:                        release_cookie(&dir);
                   1678: 
                   1679:                        release_cookie(res);
                   1680: 
                   1681:                        break;
                   1682: 
                   1683:                }
                   1684: 
1.1       root     1685: 
                   1686: 
1.1.1.3   root     1687:        /* if the file is a link, and we're following links, follow it */
1.1       root     1688: 
1.1.1.3   root     1689:                if ( (xattr.mode & S_IFMT) == S_IFLNK && (*path || dolast > 1)) {
1.1       root     1690: 
1.1.1.3   root     1691:                        r = (res->fs->readlink)(res, linkstuff, PATH_MAX);
1.1       root     1692: 
1.1.1.3   root     1693:                        release_cookie(res);
1.1       root     1694: 
1.1.1.3   root     1695:                        if (r) {
1.1       root     1696: 
1.1.1.3   root     1697:                                DEBUG(("error reading symbolic link"));
1.1       root     1698: 
1.1.1.3   root     1699:                                release_cookie(&dir);
1.1       root     1700: 
1.1.1.3   root     1701:                                break;
1.1       root     1702: 
1.1.1.3   root     1703:                        }
1.1       root     1704: 
1.1.1.3   root     1705:                        r = relpath2cookie(&dir, linkstuff, follow_links, res,
1.1       root     1706: 
1.1.1.3   root     1707:                                                depth+1);
1.1       root     1708: 
1.1.1.3   root     1709:                        release_cookie(&dir);
                   1710: 
                   1711:                        if (r) {
                   1712: 
                   1713:                                DEBUG(("error following symbolic link"));
                   1714: 
                   1715:                                break;
1.1       root     1716: 
                   1717:                        }
                   1718: 
1.1.1.3   root     1719:                        dir = *res;
1.1       root     1720: 
1.1.1.3   root     1721:                        (void)(res->fs->getxattr)(res, &xattr);
                   1722: 
                   1723:                } else {
                   1724: 
                   1725:                        release_cookie(&dir);
                   1726: 
                   1727:                        dir = *res;
                   1728: 
                   1729:                }
1.1       root     1730: 
                   1731:        }
                   1732: 
                   1733: 
                   1734: 
1.1.1.3   root     1735:        PATH2COOKIE_DB(("relpath2cookie: returning %ld", r));
                   1736: 
1.1       root     1737:        return r;
                   1738: 
                   1739: }
                   1740: 
                   1741: 
                   1742: 
                   1743: #define MAX_TRYS 8
                   1744: 
                   1745: 
                   1746: 
                   1747: long
                   1748: 
                   1749: path2cookie(path, lastname, res)
                   1750: 
                   1751:        const char *path;
                   1752: 
                   1753:        char *lastname;
                   1754: 
                   1755:        fcookie *res;
                   1756: 
                   1757: {
                   1758: 
                   1759:        fcookie *dir;
                   1760: 
                   1761:        long r;
                   1762: 
                   1763: /* AHDI sometimes will keep insisting that a media change occured;
                   1764: 
1.1.1.3   root     1765:  * we limit the number of retrys to avoid hanging the system
1.1       root     1766: 
                   1767:  */
                   1768: 
                   1769:        int trycnt = 0;
                   1770: 
                   1771: 
                   1772: 
                   1773:        dir = &curproc->curdir[curproc->curdrv];
                   1774: 
                   1775: 
                   1776: 
                   1777:        do {
                   1778: 
1.1.1.3   root     1779:                r = relpath2cookie(dir, path, lastname, res, 0);
1.1       root     1780: 
                   1781:                if (r == E_CHNG)
                   1782: 
1.1.1.2   root     1783:                        DEBUG(("path2cookie: restarting due to media change"));
1.1       root     1784: 
                   1785:        } while (r == E_CHNG && trycnt++ < MAX_TRYS);
                   1786: 
                   1787: 
                   1788: 
                   1789:        return r;
                   1790: 
                   1791: }
                   1792: 
                   1793: 
                   1794: 
                   1795: /*
                   1796: 
1.1.1.3   root     1797:  * release_cookie: tell the file system owner that a cookie is no
                   1798: 
                   1799:  * longer in use by the kernel
                   1800: 
                   1801:  */
                   1802: 
                   1803: void
                   1804: 
                   1805: release_cookie(fc)
                   1806: 
                   1807:        fcookie *fc;
                   1808: 
                   1809: {
                   1810: 
                   1811:        FILESYS *fs;
                   1812: 
                   1813: 
                   1814: 
                   1815:        if (fc) {
                   1816: 
                   1817:                fs = fc->fs;
                   1818: 
                   1819:                if (fs && fs->release) {
                   1820: 
                   1821:                        (void)(*fs->release)(fc);
                   1822: 
                   1823:                }
                   1824: 
                   1825:        }
                   1826: 
                   1827: }
                   1828: 
                   1829: 
                   1830: 
                   1831: /*
                   1832: 
                   1833:  * Make a new cookie (newc) which is a duplicate of the old cookie
                   1834: 
                   1835:  * (oldc). This may be something the file system is interested in,
                   1836: 
                   1837:  * so we give it a chance to do the duplication; if it doesn't
                   1838: 
                   1839:  * want to, we just copy.
                   1840: 
                   1841:  */
                   1842: 
                   1843: 
                   1844: 
                   1845: void
                   1846: 
                   1847: dup_cookie(newc, oldc)
                   1848: 
                   1849:        fcookie *newc, *oldc;
                   1850: 
                   1851: {
                   1852: 
                   1853:        FILESYS *fs = oldc->fs;
                   1854: 
                   1855: 
                   1856: 
                   1857:        if (fs && fs->release && fs->dupcookie) {
                   1858: 
                   1859:                (void)(*fs->dupcookie)(newc, oldc);
                   1860: 
                   1861:        } else {
                   1862: 
                   1863:                *newc = *oldc;
                   1864: 
                   1865:        }
                   1866: 
                   1867: }
                   1868: 
                   1869: 
                   1870: 
                   1871: /*
                   1872: 
1.1       root     1873:  * new_fileptr, dispose_fileptr: allocate (deallocate) a file pointer
                   1874: 
                   1875:  */
                   1876: 
                   1877: 
                   1878: 
                   1879: FILEPTR *
                   1880: 
                   1881: new_fileptr()
                   1882: 
                   1883: {
                   1884: 
                   1885:        FILEPTR *f;
                   1886: 
                   1887: 
                   1888: 
1.1.1.2   root     1889:        if ((f = flist) != 0) {
1.1       root     1890: 
                   1891:                flist = f->next;
                   1892: 
                   1893:                f->next = 0;
                   1894: 
                   1895:                return f;
                   1896: 
                   1897:        }
                   1898: 
                   1899:        f = kmalloc(SIZEOF(FILEPTR));
                   1900: 
                   1901:        if (!f) {
                   1902: 
                   1903:                FATAL("new_fileptr: out of memory");
                   1904: 
                   1905:        }
                   1906: 
                   1907:        else {
                   1908: 
                   1909:                f->next = 0;
                   1910: 
                   1911:        }
                   1912: 
                   1913:        return f;
                   1914: 
                   1915: }
                   1916: 
                   1917: 
                   1918: 
                   1919: void
                   1920: 
                   1921: dispose_fileptr(f)
                   1922: 
                   1923:        FILEPTR *f;
                   1924: 
                   1925: {
                   1926: 
                   1927:        if (f->links != 0) {
                   1928: 
                   1929:                FATAL("dispose_fileptr: f->links == %d", f->links);
                   1930: 
                   1931:        }
                   1932: 
                   1933:        f->next = flist;
                   1934: 
                   1935:        flist = f;
                   1936: 
                   1937: }
                   1938: 
                   1939: 
                   1940: 
                   1941: /*
                   1942: 
                   1943:  * denyshare(list, f): "list" points at the first FILEPTR in a
                   1944: 
                   1945:  * chained list of open FILEPTRS referring to the same file;
                   1946: 
                   1947:  * f is a newly opened FILEPTR. Every FILEPTR in the given list is
                   1948: 
                   1949:  * checked to see if its "open" mode (in list->flags) is compatible with
                   1950: 
                   1951:  * the open mode in f->flags. If not (for example, if f was opened with
                   1952: 
                   1953:  * a "read" mode and some other file has the O_DENYREAD share mode),
                   1954: 
                   1955:  * then 1 is returned. If all the open FILEPTRs in the list are
                   1956: 
                   1957:  * compatible with f, then 0 is returned.
                   1958: 
                   1959:  * This is not as complicated as it sounds. In practice, just keep a
                   1960: 
                   1961:  * list of open FILEPTRs attached to each file, and put something like
                   1962: 
                   1963:  *     if (denyshare(thisfile->openfileptrlist, newfileptr))
                   1964: 
                   1965:  *             return EACCDN;
                   1966: 
                   1967:  * in the device open routine.
                   1968: 
                   1969:  */
                   1970: 
                   1971: 
                   1972: 
1.1.1.2   root     1973: int ARGS_ON_STACK 
1.1       root     1974: 
                   1975: denyshare(list, f)
                   1976: 
                   1977:        FILEPTR *list, *f;
                   1978: 
                   1979: {
                   1980: 
1.1.1.3   root     1981:        int newrm, newsm;       /* new read and sharing mode */
1.1       root     1982: 
1.1.1.3   root     1983:        int oldrm, oldsm;       /* read and sharing mode of already opened file */
1.1       root     1984: 
1.1.1.6 ! root     1985:        extern MEMREGION *tofreed;
        !          1986: 
        !          1987:        MEMREGION *m = tofreed;
        !          1988: 
1.1       root     1989:        int i;
                   1990: 
                   1991: 
                   1992: 
                   1993:        newrm = f->flags & O_RWMODE;
                   1994: 
                   1995:        newsm = f->flags & O_SHMODE;
                   1996: 
                   1997: 
                   1998: 
1.1.1.3   root     1999: /*
                   2000: 
                   2001:  * O_EXEC gets treated the same as O_RDONLY for our purposes
                   2002: 
                   2003:  */
                   2004: 
                   2005:        if (newrm == O_EXEC) newrm = O_RDONLY;
                   2006: 
                   2007: 
                   2008: 
                   2009: /* New meaning for O_COMPAT: deny write access to all _other_
                   2010: 
                   2011:  * processes.
                   2012: 
                   2013:  */
                   2014: 
                   2015: 
                   2016: 
1.1       root     2017:        for ( ; list; list = list->next) {
                   2018: 
                   2019:                oldrm = list->flags & O_RWMODE;
                   2020: 
1.1.1.3   root     2021:                if (oldrm == O_EXEC) oldrm = O_RDONLY;
                   2022: 
1.1       root     2023:                oldsm = list->flags & O_SHMODE;
                   2024: 
                   2025:                if (oldsm == O_DENYW || oldsm == O_DENYRW) {
                   2026: 
1.1.1.3   root     2027:                        if (newrm != O_RDONLY) {
1.1       root     2028: 
1.1.1.6 ! root     2029: /* conflict because of unattached shared text region? */
        !          2030: 
        !          2031:                                if (!m && NULL != (m = find_text_seg(list))) {
        !          2032: 
        !          2033:                                        if (m->links == 0xffff)
        !          2034: 
        !          2035:                                                continue;
        !          2036: 
        !          2037:                                        m = 0;
        !          2038: 
        !          2039:                                }
        !          2040: 
1.1.1.2   root     2041:                                DEBUG(("write access denied"));
1.1       root     2042: 
                   2043:                                return 1;
                   2044: 
                   2045:                        }
                   2046: 
                   2047:                }
                   2048: 
                   2049:                if (oldsm == O_DENYR || oldsm == O_DENYRW) {
                   2050: 
                   2051:                        if (newrm != O_WRONLY) {
                   2052: 
1.1.1.2   root     2053:                                DEBUG(("read access denied"));
1.1       root     2054: 
                   2055:                                return 1;
                   2056: 
                   2057:                        }
                   2058: 
                   2059:                }
                   2060: 
                   2061:                if (newsm == O_DENYW || newsm == O_DENYRW) {
                   2062: 
1.1.1.3   root     2063:                        if (oldrm != O_RDONLY) {
1.1       root     2064: 
1.1.1.2   root     2065:                                DEBUG(("couldn't deny writes"));
1.1       root     2066: 
                   2067:                                return 1;
                   2068: 
                   2069:                        }
                   2070: 
                   2071:                }
                   2072: 
                   2073:                if (newsm == O_DENYR || newsm == O_DENYRW) {
                   2074: 
                   2075:                        if (oldrm != O_WRONLY) {
                   2076: 
1.1.1.2   root     2077:                                DEBUG(("couldn't deny reads"));
1.1       root     2078: 
                   2079:                                return 1;
                   2080: 
                   2081:                        }
                   2082: 
                   2083:                }
                   2084: 
                   2085: /* If either sm == O_COMPAT, then we check to make sure
                   2086: 
                   2087:    that the file pointers are owned by the same process (O_COMPAT means
                   2088: 
1.1.1.3   root     2089:    "deny writes to any other processes"). This isn't quite the same
1.1       root     2090: 
1.1.1.3   root     2091:    as the Atari spec, which says O_COMPAT means "deny access to other
1.1       root     2092: 
1.1.1.3   root     2093:    processes." We should fix the spec.
1.1       root     2094: 
1.1.1.3   root     2095:  */
1.1       root     2096: 
1.1.1.3   root     2097:                if ((newsm == O_COMPAT && newrm != O_RDONLY && oldrm != O_RDONLY) ||
1.1       root     2098: 
1.1.1.3   root     2099:                    (oldsm == O_COMPAT && newrm != O_RDONLY)) {
1.1       root     2100: 
                   2101:                        for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                   2102: 
                   2103:                                if (curproc->handle[i] == list)
                   2104: 
                   2105:                                        goto found;
                   2106: 
                   2107:                        }
                   2108: 
                   2109:                /* old file pointer is not open by this process */
                   2110: 
1.1.1.3   root     2111:                        DEBUG(("O_COMPAT file was opened for writing by another process"));
1.1       root     2112: 
                   2113:                        return 1;
                   2114: 
                   2115:                found:
                   2116: 
                   2117:                        ;       /* everything is OK */
                   2118: 
                   2119:                }
                   2120: 
                   2121:        }
                   2122: 
1.1.1.6 ! root     2123: /* cannot close shared text regions file here... have open do it. */
        !          2124: 
        !          2125:        if (m)
        !          2126: 
        !          2127:                tofreed = m;
        !          2128: 
1.1       root     2129:        return 0;
                   2130: 
                   2131: }
                   2132: 
                   2133: 
                   2134: 
                   2135: /*
                   2136: 
                   2137:  * denyaccess(XATTR *xattr, unsigned perm): checks to see if the access
                   2138: 
                   2139:  * specified by perm (which must be some combination of S_IROTH, S_IWOTH,
                   2140: 
                   2141:  * and S_IXOTH) should be granted to the current process
                   2142: 
                   2143:  * on a file with the given extended attributes. Returns 0 if access
                   2144: 
                   2145:  * by the current process is OK, 1 if not.
                   2146: 
                   2147:  */
                   2148: 
                   2149: 
                   2150: 
                   2151: int
                   2152: 
1.1.1.6 ! root     2153: ngroupmatch(group)
        !          2154: 
        !          2155:        int group;
        !          2156: 
        !          2157: {
        !          2158: 
        !          2159:        int i;
        !          2160: 
        !          2161: 
        !          2162: 
        !          2163:        for (i=0; i<curproc->ngroups; i++)
        !          2164: 
        !          2165:                if (curproc->ngroup[i] == group)
        !          2166: 
        !          2167:                        return 1;
        !          2168: 
        !          2169: 
        !          2170: 
        !          2171:        return 0;
        !          2172: 
        !          2173: }
        !          2174: 
        !          2175: 
        !          2176: 
        !          2177: int
        !          2178: 
1.1       root     2179: denyaccess(xattr, perm)
                   2180: 
                   2181:        XATTR *xattr;
                   2182: 
                   2183:        unsigned perm;
                   2184: 
                   2185: {
                   2186: 
                   2187:        unsigned mode;
                   2188: 
                   2189: 
                   2190: 
                   2191: /* the super-user can do anything! */
                   2192: 
                   2193:        if (curproc->euid == 0)
                   2194: 
                   2195:                return 0;
                   2196: 
                   2197: 
                   2198: 
                   2199:        mode = xattr->mode;
                   2200: 
                   2201:        if (curproc->euid == xattr->uid)
                   2202: 
                   2203:                perm = perm << 6;
                   2204: 
                   2205:        else if (curproc->egid == xattr->gid)
                   2206: 
                   2207:                perm = perm << 3;
                   2208: 
1.1.1.6 ! root     2209:        else if (ngroupmatch(xattr->gid))
        !          2210: 
        !          2211:                perm = perm << 3;
        !          2212: 
        !          2213: 
        !          2214: 
1.1       root     2215:        if ((mode & perm) != perm) return 1;    /* access denied */
                   2216: 
                   2217:        return 0;
                   2218: 
                   2219: }
                   2220: 
                   2221: 
                   2222: 
                   2223: /*
                   2224: 
                   2225:  * Checks a lock against a list of locks to see if there is a conflict.
                   2226: 
                   2227:  * This is a utility to be used by file systems, somewhat like denyshare
                   2228: 
                   2229:  * above. Returns 0 if there is no conflict, or a pointer to the
                   2230: 
                   2231:  * conflicting LOCK structure if there is.
                   2232: 
                   2233:  *
                   2234: 
                   2235:  * Conflicts occur for overlapping locks if the process id's are
                   2236: 
                   2237:  * different and if at least one of the locks is a write lock.
                   2238: 
                   2239:  *
                   2240: 
                   2241:  * NOTE: we assume before being called that the locks have been converted
                   2242: 
                   2243:  * so that l_start is absolute. not relative to the current position or
                   2244: 
                   2245:  * end of file.
                   2246: 
                   2247:  */
                   2248: 
                   2249: 
                   2250: 
1.1.1.2   root     2251: LOCK * ARGS_ON_STACK 
1.1       root     2252: 
                   2253: denylock(list, lck)
                   2254: 
                   2255:        LOCK *list, *lck;
                   2256: 
                   2257: {
                   2258: 
                   2259:        LOCK *t;
                   2260: 
                   2261:        unsigned long tstart, tend;
                   2262: 
                   2263:        unsigned long lstart, lend;
                   2264: 
                   2265:        int pid = curproc->pid;
                   2266: 
                   2267:        int ltype;
                   2268: 
                   2269: 
                   2270: 
                   2271:        ltype = lck->l.l_type;
                   2272: 
                   2273:        lstart = lck->l.l_start;
                   2274: 
                   2275: 
                   2276: 
                   2277:        if (lck->l.l_len == 0)
                   2278: 
1.1.1.2   root     2279:                lend = 0xffffffffL;
1.1       root     2280: 
                   2281:        else
                   2282: 
1.1.1.3   root     2283:                lend = lstart + lck->l.l_len - 1;
1.1       root     2284: 
                   2285: 
                   2286: 
                   2287:        for (t = list; t; t = t->next) {
                   2288: 
                   2289:                tstart = t->l.l_start;
                   2290: 
                   2291:                if (t->l.l_len == 0)
                   2292: 
1.1.1.2   root     2293:                        tend = 0xffffffffL;
1.1       root     2294: 
                   2295:                else
                   2296: 
1.1.1.3   root     2297:                        tend = tstart + t->l.l_len - 1;
1.1       root     2298: 
                   2299: 
                   2300: 
                   2301:        /* look for overlapping locks */
                   2302: 
                   2303:                if (tstart <= lstart && tend >= lstart && t->l.l_pid != pid &&
                   2304: 
                   2305:                    (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
                   2306: 
                   2307:                        break;
                   2308: 
                   2309:                if (lstart <= tstart && lend >= tstart && t->l.l_pid != pid &&
                   2310: 
                   2311:                    (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
                   2312: 
                   2313:                        break;
                   2314: 
                   2315:        }
                   2316: 
                   2317:        return t;
                   2318: 
                   2319: }
                   2320: 
                   2321: 
                   2322: 
                   2323: /*
                   2324: 
                   2325:  * check to see that a file is a directory, and that write permission
                   2326: 
                   2327:  * is granted; return an error code, or 0 if everything is ok.
                   2328: 
                   2329:  */
                   2330: 
                   2331: long
                   2332: 
                   2333: dir_access(dir, perm)
                   2334: 
                   2335:        fcookie *dir;
                   2336: 
                   2337:        unsigned perm;
                   2338: 
                   2339: {
                   2340: 
                   2341:        XATTR xattr;
                   2342: 
                   2343:        long r;
                   2344: 
                   2345: 
                   2346: 
                   2347:        r = (*dir->fs->getxattr)(dir, &xattr);
                   2348: 
1.1.1.3   root     2349:        if (r) {
                   2350: 
                   2351:                DEBUG(("dir_access: file system returned %ld", r));
                   2352: 
                   2353:                return r;
                   2354: 
                   2355:        }
1.1       root     2356: 
                   2357:        if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
                   2358: 
1.1.1.2   root     2359:                DEBUG(("file is not a directory"));
1.1       root     2360: 
                   2361:                return EPTHNF;
                   2362: 
                   2363:        }
                   2364: 
                   2365:        if (denyaccess(&xattr, perm)) {
                   2366: 
1.1.1.2   root     2367:                DEBUG(("no permission for directory"));
1.1       root     2368: 
                   2369:                return EACCDN;
                   2370: 
                   2371:        }
                   2372: 
                   2373:        return 0;
                   2374: 
                   2375: }
                   2376: 
                   2377: 
                   2378: 
                   2379: /*
                   2380: 
                   2381:  * returns 1 if the given name contains a wildcard character 
                   2382: 
                   2383:  */
                   2384: 
                   2385: 
                   2386: 
                   2387: int
                   2388: 
                   2389: has_wild(name)
                   2390: 
                   2391:        const char *name;
                   2392: 
                   2393: {
                   2394: 
                   2395:        char c;
                   2396: 
                   2397: 
                   2398: 
1.1.1.2   root     2399:        while ((c = *name++) != 0) {
1.1       root     2400: 
                   2401:                if (c == '*' || c == '?') return 1;
                   2402: 
                   2403:        }
                   2404: 
                   2405:        return 0;
                   2406: 
                   2407: }
                   2408: 
                   2409: 
                   2410: 
                   2411: /*
                   2412: 
                   2413:  * void copy8_3(dest, src): convert a file name (src) into DOS 8.3 format
                   2414: 
                   2415:  * (in dest). Note the following things:
                   2416: 
                   2417:  * if a field has less than the required number of characters, it is
                   2418: 
                   2419:  * padded with blanks
                   2420: 
                   2421:  * a '*' means to pad the rest of the field with '?' characters
                   2422: 
                   2423:  * special things to watch for:
                   2424: 
                   2425:  *     "." and ".." are more or less left alone
                   2426: 
                   2427:  *     "*.*" is recognized as a special pattern, for which dest is set
                   2428: 
                   2429:  *     to just "*"
                   2430: 
                   2431:  * Long names are truncated. Any extensions after the first one are
                   2432: 
                   2433:  * ignored, i.e. foo.bar.c -> foo.bar, foo.c.bar->foo.c.
                   2434: 
                   2435:  */
                   2436: 
                   2437: 
                   2438: 
                   2439: void
                   2440: 
                   2441: copy8_3(dest, src)
                   2442: 
                   2443:        char *dest;
                   2444: 
                   2445:        const char *src;
                   2446: 
                   2447: {
                   2448: 
                   2449:        char fill = ' ', c;
                   2450: 
                   2451:        int i;
                   2452: 
                   2453: 
                   2454: 
                   2455:        if (src[0] == '.') {
                   2456: 
                   2457:                if (src[1] == 0) {
                   2458: 
                   2459:                        strcpy(dest, ".       .   ");
                   2460: 
                   2461:                        return;
                   2462: 
                   2463:                }
                   2464: 
                   2465:                if (src[1] == '.' && src[2] == 0) {
                   2466: 
                   2467:                        strcpy(dest, "..      .   ");
                   2468: 
                   2469:                        return;
                   2470: 
                   2471:                }
                   2472: 
                   2473:        }
                   2474: 
                   2475:        if (src[0] == '*' && src[1] == '.' && src[2] == '*' && src[3] == 0) {
                   2476: 
                   2477:                dest[0] = '*';
                   2478: 
                   2479:                dest[1] = 0;
                   2480: 
                   2481:                return;
                   2482: 
                   2483:        }
                   2484: 
                   2485: 
                   2486: 
                   2487:        for (i = 0; i < 8; i++) {
                   2488: 
                   2489:                c = *src++;
                   2490: 
                   2491:                if (!c || c == '.') break;
                   2492: 
                   2493:                if (c == '*') {
                   2494: 
                   2495:                        fill = c = '?';
                   2496: 
                   2497:                }
                   2498: 
                   2499:                *dest++ = toupper(c);
                   2500: 
                   2501:        }
                   2502: 
                   2503:        while (i++ < 8) {
                   2504: 
                   2505:                *dest++ = fill;
                   2506: 
                   2507:        }
                   2508: 
                   2509:        *dest++ = '.';
                   2510: 
                   2511:        i = 0;
                   2512: 
                   2513:        fill = ' ';
                   2514: 
                   2515:        while (c && c != '.')
                   2516: 
                   2517:                c = *src++;
                   2518: 
                   2519: 
                   2520: 
                   2521:        if (c) {
                   2522: 
                   2523:                for( ;i < 3; i++) {
                   2524: 
                   2525:                        c = *src++;
                   2526: 
                   2527:                        if (!c || c == '.') break;
                   2528: 
                   2529:                        if (c == '*')
                   2530: 
                   2531:                                c = fill = '?';
                   2532: 
                   2533:                        *dest++ = toupper(c);
                   2534: 
                   2535:                }
                   2536: 
                   2537:        }
                   2538: 
                   2539:        while (i++ < 3)
                   2540: 
                   2541:                *dest++ = fill;
                   2542: 
1.1.1.2   root     2543:        *dest = 0;
1.1       root     2544: 
                   2545: }
                   2546: 
                   2547: 
                   2548: 
                   2549: /*
                   2550: 
                   2551:  * int pat_match(name, patrn): returns 1 if "name" matches the template in
                   2552: 
                   2553:  * "patrn", 0 if not. "patrn" is assumed to have been expanded in 8.3
                   2554: 
                   2555:  * format by copy8_3; "name" need not be. Any '?' characters in patrn
                   2556: 
                   2557:  * will match any character in name. Note that if "patrn" has a '*' as
                   2558: 
                   2559:  * the first character, it will always match; this will happen only if
                   2560: 
                   2561:  * the original pattern (before copy8_3 was applied) was "*.*".
                   2562: 
                   2563:  *
                   2564: 
                   2565:  * BUGS: acts a lot like the silly TOS pattern matcher.
                   2566: 
                   2567:  */
                   2568: 
                   2569: 
                   2570: 
                   2571: int
                   2572: 
                   2573: pat_match(name, template)
                   2574: 
                   2575:        const char *name, *template;
                   2576: 
                   2577: {
                   2578: 
                   2579:        register char *s, c;
                   2580: 
                   2581:        char expname[TOS_NAMELEN+1];
                   2582: 
                   2583: 
                   2584: 
                   2585:        if (*template == '*') return 1;
                   2586: 
                   2587:        copy8_3(expname, name);
                   2588: 
                   2589: 
                   2590: 
                   2591:        s = expname;
                   2592: 
1.1.1.2   root     2593:        while ((c = *template++) != 0) {
1.1       root     2594: 
                   2595:                if (c != *s && c != '?')
                   2596: 
                   2597:                        return 0;
                   2598: 
                   2599:                s++;
                   2600: 
                   2601:        }
                   2602: 
                   2603:        return 1;
                   2604: 
                   2605: }
                   2606: 
                   2607: 
                   2608: 
                   2609: /*
                   2610: 
                   2611:  * int samefile(fcookie *a, fcookie *b): returns 1 if the two cookies
                   2612: 
                   2613:  * refer to the same file or directory, 0 otherwise
                   2614: 
                   2615:  */
                   2616: 
                   2617: 
                   2618: 
                   2619: int
                   2620: 
                   2621: samefile(a, b)
                   2622: 
                   2623:        fcookie *a, *b;
                   2624: 
                   2625: {
                   2626: 
                   2627:        if (a->fs == b->fs && a->dev == b->dev && a->index == b->index)
                   2628: 
                   2629:                return 1;
                   2630: 
                   2631:        return 0;
                   2632: 
                   2633: }
                   2634: 

unix.superglobalmegacorp.com

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