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

1.1       root        1: /*
                      2: 
                      3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
                      4: 
                      5: */
                      6: 
                      7: 
                      8: 
                      9: /*
                     10: 
                     11:  * various file system interface things
                     12: 
                     13:  */
                     14: 
                     15: 
                     16: 
                     17: #include "mint.h"
                     18: 
                     19: 
                     20: 
                     21: FILESYS *active_fs;
                     22: 
                     23: FILESYS *drives[NUM_DRIVES];
                     24: 
                     25: 
                     26: 
                     27: FILEPTR *flist;                /* a list of free file pointers */
                     28: 
                     29: 
                     30: 
                     31: char follow_links[1];  /* dummy "name" used as a parameter to path2cookie */
                     32: 
                     33: 
                     34: 
                     35: /* vector of valid drives, according to GEMDOS */
                     36: 
                     37: /* note that this isn't necessarily the same as what the BIOS thinks of
                     38: 
                     39:  * as valid
                     40: 
                     41:  */
                     42: 
                     43: long dosdrvs;
                     44: 
                     45: 
                     46: 
                     47: /*
                     48: 
                     49:  * Initialize a specific drive. This is called whenever a new drive
                     50: 
                     51:  * is accessed, or when media change occurs on an old drive.
                     52: 
                     53:  * Assumption: at this point, active_fs is a valid pointer
                     54: 
                     55:  * to a list of file systems.
                     56: 
                     57:  */
                     58: 
                     59: 
                     60: 
                     61: /* table of processes holding locks on drives */
                     62: 
                     63: extern PROC *dlockproc[];      /* in dosdir.c */
                     64: 
                     65: 
                     66: 
                     67: void
                     68: 
                     69: init_drive(i)
                     70: 
                     71:        int i;
                     72: 
                     73: {
                     74: 
                     75:        long r;
                     76: 
                     77:        FILESYS *fs;
                     78: 
                     79:        fcookie root_dir;
                     80: 
                     81: 
                     82: 
                     83:        TRACE("init_drive(%c)", i+'A');
                     84: 
                     85: 
                     86: 
                     87:        drives[i] = 0;          /* no file system */
                     88: 
                     89:        if (i >= 0 && i < NUM_DRIVES) {
                     90: 
                     91:                if (dlockproc[i]) return;
                     92: 
                     93:        }
                     94: 
                     95: 
                     96: 
                     97:        for (fs = active_fs; fs; fs = fs->next) {
                     98: 
                     99:                r = (*fs->root)(i, &root_dir);
                    100: 
                    101:                if (r == 0) {
                    102: 
                    103:                        drives[i] = root_dir.fs;
                    104: 
                    105:                        break;
                    106: 
                    107:                }
                    108: 
                    109:        }
                    110: 
                    111: }
                    112: 
                    113: 
                    114: 
                    115: /*
                    116: 
                    117:  * initialize the file system
                    118: 
                    119:  */
                    120: 
                    121: 
                    122: 
                    123: #define NUMFPS 40      /* initial number of file pointers */
                    124: 
                    125: 
                    126: 
                    127: void
                    128: 
                    129: init_filesys()
                    130: 
                    131: {
                    132: 
                    133:        static FILEPTR initial[NUMFPS+1];
                    134: 
                    135:        long drv;
                    136: 
                    137:        int i;
                    138: 
                    139:        extern FILESYS tos_filesys, bios_filesys, pipe_filesys,
                    140: 
                    141:                proc_filesys, uni_filesys;
                    142: 
                    143: 
                    144: 
                    145: /* get the vector of connected GEMDOS drives */
                    146: 
                    147:        dosdrvs = Dsetdrv(Dgetdrv()) | drvmap();
                    148: 
                    149: 
                    150: 
                    151: /* set up some initial file pointers */
                    152: 
                    153:        for (i = 0; i < NUMFPS; i++) {
                    154: 
                    155:                initial[i].devinfo = (ulong) (&initial[i+1]);
                    156: 
                    157:        }
                    158: 
                    159:        initial[NUMFPS].devinfo = 0;
                    160: 
                    161:        flist = initial;
                    162: 
                    163: 
                    164: 
                    165: /* set up the file systems */
                    166: 
                    167:        tos_filesys.next = 0;
                    168: 
                    169:        bios_filesys.next = &tos_filesys;
                    170: 
                    171:        pipe_filesys.next = &bios_filesys;
                    172: 
                    173:        proc_filesys.next = &pipe_filesys;
                    174: 
                    175:        uni_filesys.next = &proc_filesys;
                    176: 
                    177: 
                    178: 
                    179:        active_fs = &uni_filesys;
                    180: 
                    181: 
                    182: 
                    183: /* initialize the BIOS file system */
                    184: 
                    185:        biosfs_init();
                    186: 
                    187: 
                    188: 
                    189: /* initialize the unified file system */
                    190: 
                    191:        unifs_init();
                    192: 
                    193: 
                    194: 
                    195:        drv = dosdrvs | PSEUDODRVS;
                    196: 
                    197: 
                    198: 
                    199: #if 0
                    200: 
                    201: /* now run through the systems and see who's interested in what drives */
                    202: 
                    203: /* THIS IS NOW DONE AUTOMAGICALLY IN path2cookie */
                    204: 
                    205:        for (i = 0; i < NUM_DRIVES; i++) {
                    206: 
                    207:                if ( drv & (1L << i) )
                    208: 
                    209:                        init_drive(i);
                    210: 
                    211:        }
                    212: 
                    213: #endif
                    214: 
                    215: }
                    216: 
                    217: 
                    218: 
                    219: /*
                    220: 
                    221:  * load file systems from disk
                    222: 
                    223:  * this routine is called after process 0 is set up, but before any user
                    224: 
                    225:  * processes are run
                    226: 
                    227:  *
                    228: 
                    229:  * NOTE that a number of directory changes take place here: we look first
                    230: 
                    231:  * in the current directory, then in the directory \mint, and finally
                    232: 
                    233:  * the d_lock() calls force us into the root directory.
                    234: 
                    235:  */
                    236: 
                    237: 
                    238: 
                    239: typedef FILESYS * (*FSFUNC) P_((struct kerinfo *));
                    240: 
                    241: 
                    242: 
                    243: void
                    244: 
                    245: load_filesys()
                    246: 
                    247: {
                    248: 
                    249:        long r;
                    250: 
                    251:        BASEPAGE *b;
                    252: 
                    253:        FILESYS *fs;
                    254: 
                    255:        FSFUNC initf;
                    256: 
                    257:        static DTABUF dta;
                    258: 
                    259:        int i;
                    260: 
                    261:        extern struct kerinfo kernelinfo; /* in main.c */
                    262: 
                    263: #define NPATHS 2
                    264: 
                    265:        static const char *paths[NPATHS] = {"", "\\mint"};
                    266: 
                    267: 
                    268: 
                    269:        curproc->dta = &dta;
                    270: 
                    271: 
                    272: 
                    273:        for (i = 0; i < NPATHS; i++) {
                    274: 
                    275:            if (*paths[i])
                    276: 
                    277:                    d_setpath(paths[i]);
                    278: 
                    279:            r = f_sfirst("*.xfs", 0);
                    280: 
                    281:            while (r == 0) {
                    282: 
                    283:                b = (BASEPAGE *)p_exec(3, dta.dta_name, (char *)"", (char *)0);
                    284: 
                    285:                if ( ((long)b) < 0 ) {
                    286: 
                    287:                        DEBUG("Error loading file system %s", dta.dta_name);
                    288: 
                    289:                        continue;
                    290: 
                    291:                }
                    292: 
                    293:        /* we leave a little bit of slop at the end of the loaded stuff */
                    294: 
                    295:                m_shrink(0, (virtaddr)b, 512 + b->p_tlen + b->p_dlen + b->p_blen);
                    296: 
                    297:                initf = (FSFUNC)b->p_tbase;
                    298: 
                    299:                fs = (*initf)(&kernelinfo);
                    300: 
                    301:                TRACE("initializing %s", dta.dta_name);
                    302: 
                    303: 
                    304: 
                    305:                if (fs) {
                    306: 
                    307:                        TRACE("%s loaded OK", dta.dta_name);
                    308: 
                    309:                        fs->next = active_fs;
                    310: 
                    311:                        active_fs = fs;
                    312: 
                    313:                } else {
                    314: 
                    315:                        DEBUG("%s returned null", dta.dta_name);
                    316: 
                    317:                }
                    318: 
                    319:                r = f_snext();
                    320: 
                    321:            }
                    322: 
                    323:        }
                    324: 
                    325: 
                    326: 
                    327: /* here, we invalidate all old drives EXCEPT for ones we're already using (at
                    328: 
                    329:  * this point, only the bios devices should be open)
                    330: 
                    331:  * this gives newly loaded file systems a chance to replace the
                    332: 
                    333:  * default tosfs.c
                    334: 
                    335:  */
                    336: 
                    337:        for (i = 0; i < NUM_DRIVES; i++) {
                    338: 
                    339:                if (d_lock(1, i) == 0)  /* lock if possible */
                    340: 
                    341:                        d_lock(0, i);   /* and then unlock */
                    342: 
                    343:        }
                    344: 
                    345: }
                    346: 
                    347: 
                    348: 
                    349: void
                    350: 
                    351: close_filesys()
                    352: 
                    353: {
                    354: 
                    355:        PROC *p;
                    356: 
                    357:        FILEPTR *f;
                    358: 
                    359:        int i;
                    360: 
                    361: 
                    362: 
                    363:        TRACE("close_filesys");
                    364: 
                    365: /* close every open file */
                    366: 
                    367:        for (p = proclist; p; p = p->gl_next) {
                    368: 
                    369:                for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                    370: 
                    371:                        if ( (f = p->handle[i]) != 0) {
                    372: 
                    373:                                if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q)
                    374: 
                    375:                                        ALERT("Open file for dead process?");
                    376: 
                    377:                                do_pclose(p, f);
                    378: 
                    379:                        }
                    380: 
                    381:                }
                    382: 
                    383:        }
                    384: 
                    385: }
                    386: 
                    387: 
                    388: 
                    389: /*
                    390: 
                    391:  * "media change" routine: called when a media change is detected on device
                    392: 
                    393:  * d, which may or may not be a BIOS device. All handles associated with
                    394: 
                    395:  * the device are closed, and all directories invalidated. This routine
                    396: 
                    397:  * does all the dirty work, and is called automatically when
                    398: 
                    399:  * disk_changed detects a media change.
                    400: 
                    401:  */
                    402: 
                    403: 
                    404: 
                    405: void
                    406: 
                    407: changedrv(d)
                    408: 
                    409:        unsigned d;
                    410: 
                    411: {
                    412: 
                    413:        PROC *p;
                    414: 
                    415:        int i;
                    416: 
                    417:        FILEPTR *f;
                    418: 
                    419:        FILESYS *fs;
                    420: 
                    421:        DIR *dirh;
                    422: 
                    423:        fcookie dir;
                    424: 
                    425:        int warned = (d & 0xf000) == PROC_BASE_DEV;
                    426: 
                    427:        int r;
                    428: 
                    429: 
                    430: 
                    431: /* re-initialize the device, if it was a BIOS device */
                    432: 
                    433:        if (d < NUM_DRIVES) {
                    434: 
                    435:                fs = drives[d];
                    436: 
                    437:                if (fs) {
                    438: 
                    439:                        (void)(*fs->dskchng)(d);
                    440: 
                    441:                }
                    442: 
                    443:                init_drive(d);
                    444: 
                    445:        }
                    446: 
                    447: 
                    448: 
                    449:        for (p = proclist; p; p = p->gl_next) {
                    450: 
                    451:        /* invalidate all open files on this device */
                    452: 
                    453:                for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                    454: 
                    455:                        if (((f = p->handle[i]) != 0) && (f->fc.dev == d)) {
                    456: 
                    457:                            if (!warned) {
                    458: 
                    459:                                ALERT(
                    460: 
                    461: "Files were open on a changed drive (0x%x)!", d);
                    462: 
                    463:                                warned++;
                    464: 
                    465:                            }
                    466: 
                    467: 
                    468: 
                    469: /* we set f->dev to NULL to indicate to do_pclose that this is an
                    470: 
                    471:  * emergency close, and that it shouldn't try to make any
                    472: 
                    473:  * calls to the device driver since the file has gone away
                    474: 
                    475:  */
                    476: 
                    477:                            f->dev = NULL;
                    478: 
                    479:                            (void)do_pclose(p, f);
                    480: 
                    481:                            p->handle[i] = 0;
                    482: 
                    483:                        }
                    484: 
                    485:                }
                    486: 
                    487: 
                    488: 
                    489:        /* terminate any active directory searches on the drive */
                    490: 
                    491:        /* BUG: This handles only Fsfirst/Fsnext searches! */
                    492: 
                    493:                for (i = 0; i < NUM_SEARCH; i++) {
                    494: 
                    495:                        dirh = &curproc->srchdir[i];
                    496: 
                    497:                        if (dirh->fc.fs && dirh->fc.dev == d) {
                    498: 
                    499:                                dirh->fc.fs = 0;
                    500: 
                    501:                                curproc->srchdta[i] = 0;
                    502: 
                    503:                        }
                    504: 
                    505:                }
                    506: 
                    507: 
                    508: 
                    509:                if (d >= NUM_DRIVES) continue;
                    510: 
                    511: 
                    512: 
                    513:        /* change any active directories on the device to the (new) root */
                    514: 
                    515:                fs = drives[d];
                    516: 
                    517:                if (fs) {
                    518: 
                    519:                        r = (*fs->root)(d, &dir);
                    520: 
                    521:                        if (r != E_OK) dir.fs = 0;
                    522: 
                    523:                } else {
                    524: 
                    525:                        dir.fs = 0; dir.dev = d;
                    526: 
                    527:                }
                    528: 
                    529: 
                    530: 
                    531:                for (i = 0; i < NUM_DRIVES; i++) {
                    532: 
                    533:                        if (p->root[i].dev == d)
                    534: 
                    535:                                p->root[i] = dir;
                    536: 
                    537:                        if (p->curdir[i].dev == d)
                    538: 
                    539:                                p->curdir[i] = dir;
                    540: 
                    541:                }
                    542: 
                    543:        }
                    544: 
                    545: }
                    546: 
                    547: 
                    548: 
                    549: /*
                    550: 
                    551:  * check for media change: if the drive has changed, call changedrv to
                    552: 
                    553:  * invalidate any open files and file handles associated with it, and
                    554: 
                    555:  * call the file system's media change routine.
                    556: 
                    557:  * returns: 0 if no change, 1 if change
                    558: 
                    559:  */
                    560: 
                    561: 
                    562: 
                    563: int
                    564: 
                    565: disk_changed(d)
                    566: 
                    567:        int d;
                    568: 
                    569: {
                    570: 
                    571:        short r;
                    572: 
                    573:        FILESYS *fs;
                    574: 
                    575:        static char tmpbuf[8192];
                    576: 
                    577: 
                    578: 
                    579: /* for now, only check BIOS devices */
                    580: 
                    581:        if (d < 0 || d >= NUM_DRIVES)
                    582: 
                    583:                return 0;
                    584: 
                    585: 
                    586: 
                    587: /* has the drive been initialized yet? If not, then initialize it and return
                    588: 
                    589:  * "no change"
                    590: 
                    591:  */
                    592: 
                    593:        if (!(fs = drives[d])) {
                    594: 
                    595:                TRACE("drive %c not yet initialized", d+'A');
                    596: 
                    597:                changedrv(d);
                    598: 
                    599:                return 0;
                    600: 
                    601:        }
                    602: 
                    603: 
                    604: 
                    605: /* We have to do this stuff no matter what, because someone may have installed
                    606: 
                    607:  * vectors to force a media change...
                    608: 
                    609:  * PROBLEM: AHDI may get upset if the drive isn't valid.
                    610: 
                    611:  * SOLUTION: don't change the default PSEUDODRIVES setting!
                    612: 
                    613:  */
                    614: 
                    615:        r = mediach(d);
                    616: 
                    617:        if (r == 1) {           /* drive _may_ have changed */
                    618: 
                    619:                r = rwabs(0, tmpbuf, 1, 0, d, 0L);      /* check the BIOS */
                    620: 
                    621:                if (r != E_CHNG) {                      /* nope, no change */
                    622: 
                    623:                        return 0;
                    624: 
                    625:                }
                    626: 
                    627:                r = 2;                  /* drive was definitely changed */
                    628: 
                    629:        }
                    630: 
                    631:        if (r == 2) {
                    632: 
                    633:                fs = drives[d];         /* get filesystem associated with drive */
                    634: 
                    635:                if ((*fs->dskchng)(d)) { /* does the fs agree that it changed? */
                    636: 
                    637:                        changedrv(d);   /* yes -- do the change */
                    638: 
                    639:                        return 1;
                    640: 
                    641:                }
                    642: 
                    643:        }
                    644: 
                    645:        return 0;
                    646: 
                    647: }
                    648: 
                    649: 
                    650: 
                    651: /*
                    652: 
                    653:  * routines for parsing path names
                    654: 
                    655:  */
                    656: 
                    657: 
                    658: 
                    659: char temp1[PATH_MAX];  /* temporary storage for file names */
                    660: 
                    661: 
                    662: 
                    663: #define DIRSEP(p) ((p) == '\\')
                    664: 
                    665: 
                    666: 
                    667: /*
                    668: 
                    669:  * relpath2cookie converts a TOS file name into a file cookie representing
                    670: 
                    671:  * the directory the file resides in, and a character string representing
                    672: 
                    673:  * the name of the file in that directory. The character string is
                    674: 
                    675:  * copied into the "lastname" array. If lastname is NULL, then the cookie
                    676: 
                    677:  * returned actually represents the file, instead of just the directory
                    678: 
                    679:  * the file is in.
                    680: 
                    681:  *
                    682: 
                    683:  * note that lastname, if non-null, should be big enough to contain all the
                    684: 
                    685:  * characters in "path", since if the file system doesn't want the kernel
                    686: 
                    687:  * to do path name parsing we may end up just copying path to lastname
                    688: 
                    689:  * and returning the current or root directory, as appropriate
                    690: 
                    691:  *
                    692: 
                    693:  * "relto" is the directory relative to which the search should start.
                    694: 
                    695:  * if you just want the current directory, use path2cookie instead.
                    696: 
                    697:  *
                    698: 
                    699:  * "depth" is used to control recursion in symbolic links; if it exceeds
                    700: 
                    701:  * MAX_LINKS, we return ELOOP.
                    702: 
                    703:  *
                    704: 
                    705:  * N.B.: "depth" is also overloaded to control whether drive letter
                    706: 
                    707:  * interpretation is performed; if drive == 0, it is assumed that
                    708: 
                    709:  * drive letters should _not_ be interpreted; if drive > 0, it
                    710: 
                    711:  * is assumed that they should be, since we are in this case following
                    712: 
                    713:  * a symbolic link.
                    714: 
                    715:  */
                    716: 
                    717: 
                    718: 
                    719: #define MAX_LINKS 4
                    720: 
                    721: 
                    722: 
                    723: long
                    724: 
                    725: relpath2cookie(relto, path, lastname, res, depth)
                    726: 
                    727:        fcookie *relto;
                    728: 
                    729:        const char *path;
                    730: 
                    731:        char *lastname;
                    732: 
                    733:        fcookie *res;
                    734: 
                    735:        int depth;
                    736: 
                    737: {
                    738: 
                    739:        static fcookie dir;
                    740: 
                    741:        int drv;
                    742: 
                    743:        int len;
                    744: 
                    745:        char c, *s;
                    746: 
                    747:        XATTR xattr;
                    748: 
                    749:        static char newpath[16] = "U:\\DEV\\";
                    750: 
                    751:        char temp2[PATH_MAX];
                    752: 
                    753:        char linkstuff[PATH_MAX];
                    754: 
                    755:        long r = 0;
                    756: 
                    757: 
                    758: 
                    759: /* dolast: 0 == return a cookie for the directory the file is in
                    760: 
                    761:  *         1 == return a cookie for the file itself, don't follow links
                    762: 
                    763:  *        2 == return a cookie for whatever the file points at
                    764: 
                    765:  */
                    766: 
                    767:        int dolast = 0;
                    768: 
                    769:        int i = 0;
                    770: 
                    771: 
                    772: 
                    773: TRACE("relpath2cookie(%s)", path);
                    774: 
                    775: 
                    776: 
                    777:        if (depth > MAX_LINKS) return ELOOP;
                    778: 
                    779: 
                    780: 
                    781:        if (!lastname) {
                    782: 
                    783:                dolast = 1;
                    784: 
                    785:                lastname = temp2;
                    786: 
                    787:        } else if (lastname == follow_links) {
                    788: 
                    789:                dolast = 2;
                    790: 
                    791:                lastname = temp2;
                    792: 
                    793:        }
                    794: 
                    795: 
                    796: 
                    797:        *lastname = 0;
                    798: 
                    799: 
                    800: 
                    801: /* special cases: CON:, AUX:, etc. should be converted to U:\DEV\CON,
                    802: 
                    803:  * U:\DEV\AUX, etc.
                    804: 
                    805:  */
                    806: 
                    807:        if (strlen(path) == 4 && path[3] == ':') {
                    808: 
                    809:                strncpy(newpath+7, path, 3);
                    810: 
                    811:                path = newpath;
                    812: 
                    813:        }
                    814: 
                    815: 
                    816: 
                    817: /* first, check for a drive letter */
                    818: 
                    819: /* BUG: a '\' at the start of a symbolic link is relative to the current
                    820: 
                    821:  * drive of the process, not the drive the link is located on
                    822: 
                    823:  */
                    824: 
                    825:        if (path[1] == ':' && depth > 0) {
                    826: 
                    827:                c = path[0];
                    828: 
                    829:                if (c >= 'a' && c <= 'z')
                    830: 
                    831:                        drv = c - 'a';
                    832: 
                    833:                else if (c >= 'A' && c <= 'Z')
                    834: 
                    835:                        drv = c - 'A';
                    836: 
                    837:                else
                    838: 
                    839:                        goto nodrive;
                    840: 
                    841:                path += 2;
                    842: 
                    843:                i = 1;          /* remember that we saw a drive letter */
                    844: 
                    845:        } else {
                    846: 
                    847: nodrive:
                    848: 
                    849:                drv = curproc->curdrv;
                    850: 
                    851:        }
                    852: 
                    853: 
                    854: 
                    855: /* see if the path is rooted from '\\' */
                    856: 
                    857:        if (DIRSEP(*path)) {
                    858: 
                    859:                while(DIRSEP(*path))path++;
                    860: 
                    861:                dir = curproc->root[drv];
                    862: 
                    863:        } else {
                    864: 
                    865:                if (i)  {       /* an explicit drive letter was given */
                    866: 
                    867:                        dir = curproc->curdir[drv];
                    868: 
                    869:                }
                    870: 
                    871:                else
                    872: 
                    873:                        dir = *relto;
                    874: 
                    875:        }
                    876: 
                    877: 
                    878: 
                    879:        if (!dir.fs) {
                    880: 
                    881:                changedrv(dir.dev);
                    882: 
                    883:                dir = curproc->root[drv];
                    884: 
                    885:        }
                    886: 
                    887: 
                    888: 
                    889:        if (!dir.fs) {
                    890: 
                    891:                DEBUG("path2cookie: no file system");
                    892: 
                    893:                return EDRIVE;
                    894: 
                    895:        }
                    896: 
                    897: 
                    898: 
                    899:        *res = dir;
                    900: 
                    901:        if (!*path) {           /* nothing more to do */
                    902: 
                    903:                return 0;
                    904: 
                    905:        }
                    906: 
                    907: 
                    908: 
                    909:        /* here's where we come when we've gone across a mount point */
                    910: 
                    911:        
                    912: 
                    913: restart_mount:
                    914: 
                    915: 
                    916: 
                    917: /* see if there has been a disk change; if so, return E_CHNG.
                    918: 
                    919:  * path2cookie will restart the search automatically; other functions
                    920: 
                    921:  * that call relpath2cookie directly will have to fail gracefully
                    922: 
                    923:  */
                    924: 
                    925:        if (disk_changed(dir.dev)) {
                    926: 
                    927:                return E_CHNG;
                    928: 
                    929:        }
                    930: 
                    931: 
                    932: 
                    933:        if (dir.fs->fsflags & FS_KNOPARSE) {
                    934: 
                    935:                if (!dolast) {
                    936: 
                    937:                        strncpy(lastname, path, PATH_MAX-1);
                    938: 
                    939:                        lastname[PATH_MAX - 1] = 0;
                    940: 
                    941:                        r = 0;
                    942: 
                    943:                } else {
                    944: 
                    945:                        r = (*dir.fs->lookup)(&dir, path, res);
                    946: 
                    947:                }
                    948: 
                    949:                goto check_for_mount;
                    950: 
                    951:        }
                    952: 
                    953: 
                    954: 
                    955: /* parse all but (possibly) the last component of the path name */
                    956: 
                    957: 
                    958: 
                    959:        for(;;) {
                    960: 
                    961:        /* if nothing left in path, and we don't care about links,
                    962: 
                    963:         * then we're finished
                    964: 
                    965:         */
                    966: 
                    967:                if (dolast < 2 && !*path) {
                    968: 
                    969:                        dir = *res;
                    970: 
                    971:                        break;
                    972: 
                    973:                }
                    974: 
                    975:        /* first, check to see if we're allowed to read this link/directory
                    976: 
                    977:         * NOTE: at this point, "res" contains the new 'directory', and
                    978: 
                    979:         * "dir" contains the old directory we were in (in case we need
                    980: 
                    981:         * to call relpath2cookie on a link)
                    982: 
                    983:         */
                    984: 
                    985:                r = (res->fs->getxattr)(res, &xattr);
                    986: 
                    987:                if (r != 0) {
                    988: 
                    989:                        DEBUG("path2cookie: couldn't get file attributes");
                    990: 
                    991:                        break;
                    992: 
                    993:                }
                    994: 
                    995:        /* if the "directory" is a link, follow it */
                    996: 
                    997:                i = depth;
                    998: 
                    999:                while ( (xattr.mode & S_IFMT) == S_IFLNK ) {
                   1000: 
                   1001:                        if (i++ > MAX_LINKS)
                   1002: 
                   1003:                                return ELOOP;
                   1004: 
                   1005:                        r = (res->fs->readlink)(res, linkstuff, PATH_MAX);
                   1006: 
                   1007:                        if (r) {
                   1008: 
                   1009:                                DEBUG("error reading symbolic link");
                   1010: 
                   1011:                                break;
                   1012: 
                   1013:                        }
                   1014: 
                   1015:                        r = relpath2cookie(&dir, linkstuff, follow_links, res,
                   1016: 
                   1017:                                                depth+1);
                   1018: 
                   1019:                        if (r) {
                   1020: 
                   1021:                                DEBUG("error following symbolic link");
                   1022: 
                   1023:                                break;
                   1024: 
                   1025:                        }
                   1026: 
                   1027:                        (void)(res->fs->getxattr)(res, &xattr);
                   1028: 
                   1029:                }
                   1030: 
                   1031: 
                   1032: 
                   1033:        /* if there's nothing left in the path, we can break here */
                   1034: 
                   1035:                if (!*path) {
                   1036: 
                   1037:                        dir = *res;
                   1038: 
                   1039:                        break;
                   1040: 
                   1041:                }
                   1042: 
                   1043: 
                   1044: 
                   1045:        /* the "directory" had better, in fact, be a directory */
                   1046: 
                   1047:                if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
                   1048: 
                   1049:                        return EPTHNF;
                   1050: 
                   1051:                }
                   1052: 
                   1053:        /* and we had better have search permission to it */
                   1054: 
                   1055:                if (denyaccess(&xattr, S_IXOTH)) {
                   1056: 
                   1057:                        DEBUG("search permission in directory denied");
                   1058: 
                   1059:                        return EPTHNF;
                   1060: 
                   1061:                }
                   1062: 
                   1063: 
                   1064: 
                   1065:                dir = *res;
                   1066: 
                   1067: 
                   1068: 
                   1069:        /* next, peel off the next name in the path */
                   1070: 
                   1071:                len = 0;
                   1072: 
                   1073:                s = lastname;
                   1074: 
                   1075:                c = *path;
                   1076: 
                   1077:                while (c && !DIRSEP(c)) {
                   1078: 
                   1079:                        if (len++ < PATH_MAX)
                   1080: 
                   1081:                                *s++ = c;
                   1082: 
                   1083:                        c = *++path;
                   1084: 
                   1085:                }
                   1086: 
                   1087:                *s = 0;
                   1088: 
                   1089:                while(DIRSEP(*path))path++;
                   1090: 
                   1091: 
                   1092: 
                   1093:        /* if there are no more names in the path, then we may be done */
                   1094: 
                   1095:                if (dolast == 0 && !*path)
                   1096: 
                   1097:                        break;
                   1098: 
                   1099: 
                   1100: 
                   1101:                r = (*dir.fs->lookup)(&dir, lastname, res);
                   1102: 
                   1103:                if (r) {                /* error? */
                   1104: 
                   1105:                        DEBUG("path2cookie: lookup returned %ld", r);
                   1106: 
                   1107:                        dir = *res;
                   1108: 
                   1109:                        break;
                   1110: 
                   1111:                }
                   1112: 
                   1113:        }
                   1114: 
                   1115: 
                   1116: 
                   1117: check_for_mount:
                   1118: 
                   1119: 
                   1120: 
                   1121:        if (r == EMOUNT) {      /* hmmm... a ".." at a mount point, maybe */
                   1122: 
                   1123:                fcookie mounteddir;
                   1124: 
                   1125:                r = (*dir.fs->root)(dir.dev, &mounteddir);
                   1126: 
                   1127:                if (r == 0 && drv == UNIDRV) {
                   1128: 
                   1129:                        if (dir.fs == mounteddir.fs &&
                   1130: 
                   1131:                            dir.index == mounteddir.index &&
                   1132: 
                   1133:                            dir.dev == mounteddir.dev) {
                   1134: 
                   1135:                                *res = dir = curproc->root[UNIDRV];
                   1136: 
                   1137:                        TRACE("path2cookie: restarting from mount point");
                   1138: 
                   1139:                                goto restart_mount;
                   1140: 
                   1141:                        }
                   1142: 
                   1143:                }
                   1144: 
                   1145:                else r = 0;
                   1146: 
                   1147:        }
                   1148: 
                   1149: 
                   1150: 
                   1151:        return r;
                   1152: 
                   1153: }
                   1154: 
                   1155: 
                   1156: 
                   1157: #define MAX_TRYS 8
                   1158: 
                   1159: 
                   1160: 
                   1161: long
                   1162: 
                   1163: path2cookie(path, lastname, res)
                   1164: 
                   1165:        const char *path;
                   1166: 
                   1167:        char *lastname;
                   1168: 
                   1169:        fcookie *res;
                   1170: 
                   1171: {
                   1172: 
                   1173:        fcookie *dir;
                   1174: 
                   1175:        long r;
                   1176: 
                   1177: /* AHDI sometimes will keep insisting that a media change occured;
                   1178: 
                   1179:  * we limit the number or retrys to avoid hanging the system
                   1180: 
                   1181:  */
                   1182: 
                   1183:        int trycnt = 0;
                   1184: 
                   1185: 
                   1186: 
                   1187:        dir = &curproc->curdir[curproc->curdrv];
                   1188: 
                   1189: 
                   1190: 
                   1191:        do {
                   1192: 
                   1193:        /* NOTE: depth == 1 is necessary; see the comments before relpath2cookie */
                   1194: 
                   1195:                r = relpath2cookie(dir, path, lastname, res, 1);
                   1196: 
                   1197:                if (r == E_CHNG)
                   1198: 
                   1199:                        DEBUG("path2cookie: restarting due to media change");
                   1200: 
                   1201:        } while (r == E_CHNG && trycnt++ < MAX_TRYS);
                   1202: 
                   1203: 
                   1204: 
                   1205:        return r;
                   1206: 
                   1207: }
                   1208: 
                   1209: 
                   1210: 
                   1211: /*
                   1212: 
                   1213:  * new_fileptr, dispose_fileptr: allocate (deallocate) a file pointer
                   1214: 
                   1215:  */
                   1216: 
                   1217: 
                   1218: 
                   1219: FILEPTR *
                   1220: 
                   1221: new_fileptr()
                   1222: 
                   1223: {
                   1224: 
                   1225:        FILEPTR *f;
                   1226: 
                   1227: 
                   1228: 
                   1229:        if ((f = flist)) {
                   1230: 
                   1231:                flist = f->next;
                   1232: 
                   1233:                f->next = 0;
                   1234: 
                   1235:                return f;
                   1236: 
                   1237:        }
                   1238: 
                   1239:        f = kmalloc(SIZEOF(FILEPTR));
                   1240: 
                   1241:        if (!f) {
                   1242: 
                   1243:                FATAL("new_fileptr: out of memory");
                   1244: 
                   1245:        }
                   1246: 
                   1247:        else {
                   1248: 
                   1249:                f->next = 0;
                   1250: 
                   1251:        }
                   1252: 
                   1253:        return f;
                   1254: 
                   1255: }
                   1256: 
                   1257: 
                   1258: 
                   1259: void
                   1260: 
                   1261: dispose_fileptr(f)
                   1262: 
                   1263:        FILEPTR *f;
                   1264: 
                   1265: {
                   1266: 
                   1267:        if (f->links != 0) {
                   1268: 
                   1269:                FATAL("dispose_fileptr: f->links == %d", f->links);
                   1270: 
                   1271:        }
                   1272: 
                   1273:        f->next = flist;
                   1274: 
                   1275:        flist = f;
                   1276: 
                   1277: }
                   1278: 
                   1279: 
                   1280: 
                   1281: /*
                   1282: 
                   1283:  * denyshare(list, f): "list" points at the first FILEPTR in a
                   1284: 
                   1285:  * chained list of open FILEPTRS referring to the same file;
                   1286: 
                   1287:  * f is a newly opened FILEPTR. Every FILEPTR in the given list is
                   1288: 
                   1289:  * checked to see if its "open" mode (in list->flags) is compatible with
                   1290: 
                   1291:  * the open mode in f->flags. If not (for example, if f was opened with
                   1292: 
                   1293:  * a "read" mode and some other file has the O_DENYREAD share mode),
                   1294: 
                   1295:  * then 1 is returned. If all the open FILEPTRs in the list are
                   1296: 
                   1297:  * compatible with f, then 0 is returned.
                   1298: 
                   1299:  * This is not as complicated as it sounds. In practice, just keep a
                   1300: 
                   1301:  * list of open FILEPTRs attached to each file, and put something like
                   1302: 
                   1303:  *     if (denyshare(thisfile->openfileptrlist, newfileptr))
                   1304: 
                   1305:  *             return EACCDN;
                   1306: 
                   1307:  * in the device open routine.
                   1308: 
                   1309:  */
                   1310: 
                   1311: 
                   1312: 
                   1313: int
                   1314: 
                   1315: denyshare(list, f)
                   1316: 
                   1317:        FILEPTR *list, *f;
                   1318: 
                   1319: {
                   1320: 
                   1321:        int newrm, newsm;
                   1322: 
                   1323:        int oldrm, oldsm;
                   1324: 
                   1325:        int i;
                   1326: 
                   1327: 
                   1328: 
                   1329:        newrm = f->flags & O_RWMODE;
                   1330: 
                   1331:        newsm = f->flags & O_SHMODE;
                   1332: 
                   1333: 
                   1334: 
                   1335:        for ( ; list; list = list->next) {
                   1336: 
                   1337:                oldrm = list->flags & O_RWMODE;
                   1338: 
                   1339:                oldsm = list->flags & O_SHMODE;
                   1340: 
                   1341:                if (oldsm == O_DENYW || oldsm == O_DENYRW) {
                   1342: 
                   1343:                        if (newrm != O_RDONLY) {
                   1344: 
                   1345:                                DEBUG("write access denied");
                   1346: 
                   1347:                                return 1;
                   1348: 
                   1349:                        }
                   1350: 
                   1351:                }
                   1352: 
                   1353:                if (oldsm == O_DENYR || oldsm == O_DENYRW) {
                   1354: 
                   1355:                        if (newrm != O_WRONLY) {
                   1356: 
                   1357:                                DEBUG("read access denied");
                   1358: 
                   1359:                                return 1;
                   1360: 
                   1361:                        }
                   1362: 
                   1363:                }
                   1364: 
                   1365:                if (newsm == O_DENYW || newsm == O_DENYRW) {
                   1366: 
                   1367:                        if (oldrm != O_RDONLY) {
                   1368: 
                   1369:                                DEBUG("couldn't deny writes");
                   1370: 
                   1371:                                return 1;
                   1372: 
                   1373:                        }
                   1374: 
                   1375:                }
                   1376: 
                   1377:                if (newsm == O_DENYR || newsm == O_DENYRW) {
                   1378: 
                   1379:                        if (oldrm != O_WRONLY) {
                   1380: 
                   1381:                                DEBUG("couldn't deny reads");
                   1382: 
                   1383:                                return 1;
                   1384: 
                   1385:                        }
                   1386: 
                   1387:                }
                   1388: 
                   1389: /* If either sm == O_COMPAT, then we check to make sure
                   1390: 
                   1391:    that the file pointers are owned by the same process (O_COMPAT means
                   1392: 
                   1393:    "deny access to any other processes"). Also, once a file is opened
                   1394: 
                   1395:    in compatibility mode, it can't be opened in any other mode.
                   1396: 
                   1397:  */
                   1398: 
                   1399:                if (newsm == O_COMPAT || oldsm == O_COMPAT) {
                   1400: 
                   1401:                        if (newsm != O_COMPAT || oldsm != O_COMPAT) {
                   1402: 
                   1403:                                DEBUG("O_COMPAT mode conflict");
                   1404: 
                   1405:                                return 1;
                   1406: 
                   1407:                        }
                   1408: 
                   1409:                        for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                   1410: 
                   1411:                                if (curproc->handle[i] == list)
                   1412: 
                   1413:                                        goto found;
                   1414: 
                   1415:                        }
                   1416: 
                   1417:                /* old file pointer is not open by this process */
                   1418: 
                   1419:                        DEBUG("O_COMPAT file was opened by another process");
                   1420: 
                   1421:                        return 1;
                   1422: 
                   1423:                found:
                   1424: 
                   1425:                        ;       /* everything is OK */
                   1426: 
                   1427:                }
                   1428: 
                   1429:        }
                   1430: 
                   1431:        return 0;
                   1432: 
                   1433: }
                   1434: 
                   1435: 
                   1436: 
                   1437: /*
                   1438: 
                   1439:  * denyaccess(XATTR *xattr, unsigned perm): checks to see if the access
                   1440: 
                   1441:  * specified by perm (which must be some combination of S_IROTH, S_IWOTH,
                   1442: 
                   1443:  * and S_IXOTH) should be granted to the current process
                   1444: 
                   1445:  * on a file with the given extended attributes. Returns 0 if access
                   1446: 
                   1447:  * by the current process is OK, 1 if not.
                   1448: 
                   1449:  */
                   1450: 
                   1451: 
                   1452: 
                   1453: int
                   1454: 
                   1455: denyaccess(xattr, perm)
                   1456: 
                   1457:        XATTR *xattr;
                   1458: 
                   1459:        unsigned perm;
                   1460: 
                   1461: {
                   1462: 
                   1463:        unsigned mode;
                   1464: 
                   1465: 
                   1466: 
                   1467: /* the super-user can do anything! */
                   1468: 
                   1469:        if (curproc->euid == 0)
                   1470: 
                   1471:                return 0;
                   1472: 
                   1473: 
                   1474: 
                   1475:        mode = xattr->mode;
                   1476: 
                   1477:        if (curproc->euid == xattr->uid)
                   1478: 
                   1479:                perm = perm << 6;
                   1480: 
                   1481:        else if (curproc->egid == xattr->gid)
                   1482: 
                   1483:                perm = perm << 3;
                   1484: 
                   1485:        if ((mode & perm) != perm) return 1;    /* access denied */
                   1486: 
                   1487:        return 0;
                   1488: 
                   1489: }
                   1490: 
                   1491: 
                   1492: 
                   1493: /*
                   1494: 
                   1495:  * Checks a lock against a list of locks to see if there is a conflict.
                   1496: 
                   1497:  * This is a utility to be used by file systems, somewhat like denyshare
                   1498: 
                   1499:  * above. Returns 0 if there is no conflict, or a pointer to the
                   1500: 
                   1501:  * conflicting LOCK structure if there is.
                   1502: 
                   1503:  *
                   1504: 
                   1505:  * Conflicts occur for overlapping locks if the process id's are
                   1506: 
                   1507:  * different and if at least one of the locks is a write lock.
                   1508: 
                   1509:  *
                   1510: 
                   1511:  * NOTE: we assume before being called that the locks have been converted
                   1512: 
                   1513:  * so that l_start is absolute. not relative to the current position or
                   1514: 
                   1515:  * end of file.
                   1516: 
                   1517:  */
                   1518: 
                   1519: 
                   1520: 
                   1521: LOCK *
                   1522: 
                   1523: denylock(list, lck)
                   1524: 
                   1525:        LOCK *list, *lck;
                   1526: 
                   1527: {
                   1528: 
                   1529:        LOCK *t;
                   1530: 
                   1531:        unsigned long tstart, tend;
                   1532: 
                   1533:        unsigned long lstart, lend;
                   1534: 
                   1535:        int pid = curproc->pid;
                   1536: 
                   1537:        int ltype;
                   1538: 
                   1539: 
                   1540: 
                   1541:        ltype = lck->l.l_type;
                   1542: 
                   1543:        lstart = lck->l.l_start;
                   1544: 
                   1545: 
                   1546: 
                   1547:        if (lck->l.l_len == 0)
                   1548: 
                   1549:                lend = 0xffffffff;
                   1550: 
                   1551:        else
                   1552: 
                   1553:                lend = lstart + lck->l.l_len;
                   1554: 
                   1555: 
                   1556: 
                   1557:        for (t = list; t; t = t->next) {
                   1558: 
                   1559:                tstart = t->l.l_start;
                   1560: 
                   1561:                if (t->l.l_len == 0)
                   1562: 
                   1563:                        tend = 0xffffffff;
                   1564: 
                   1565:                else
                   1566: 
                   1567:                        tend = tstart + t->l.l_len;
                   1568: 
                   1569: 
                   1570: 
                   1571:        /* look for overlapping locks */
                   1572: 
                   1573:                if (tstart <= lstart && tend >= lstart && t->l.l_pid != pid &&
                   1574: 
                   1575:                    (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
                   1576: 
                   1577:                        break;
                   1578: 
                   1579:                if (lstart <= tstart && lend >= tstart && t->l.l_pid != pid &&
                   1580: 
                   1581:                    (ltype == F_WRLCK || t->l.l_type == F_WRLCK))
                   1582: 
                   1583:                        break;
                   1584: 
                   1585:        }
                   1586: 
                   1587:        return t;
                   1588: 
                   1589: }
                   1590: 
                   1591: 
                   1592: 
                   1593: /*
                   1594: 
                   1595:  * check to see that a file is a directory, and that write permission
                   1596: 
                   1597:  * is granted; return an error code, or 0 if everything is ok.
                   1598: 
                   1599:  */
                   1600: 
                   1601: long
                   1602: 
                   1603: dir_access(dir, perm)
                   1604: 
                   1605:        fcookie *dir;
                   1606: 
                   1607:        unsigned perm;
                   1608: 
                   1609: {
                   1610: 
                   1611:        XATTR xattr;
                   1612: 
                   1613:        long r;
                   1614: 
                   1615: 
                   1616: 
                   1617:        r = (*dir->fs->getxattr)(dir, &xattr);
                   1618: 
                   1619:        if (r) return r;
                   1620: 
                   1621:        if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
                   1622: 
                   1623: DEBUG("file is not a directory");
                   1624: 
                   1625:                return EPTHNF;
                   1626: 
                   1627:        }
                   1628: 
                   1629:        if (denyaccess(&xattr, perm)) {
                   1630: 
                   1631: DEBUG("no permission for directory");
                   1632: 
                   1633:                return EACCDN;
                   1634: 
                   1635:        }
                   1636: 
                   1637:        return 0;
                   1638: 
                   1639: }
                   1640: 
                   1641: 
                   1642: 
                   1643: /*
                   1644: 
                   1645:  * returns 1 if the given name contains a wildcard character 
                   1646: 
                   1647:  */
                   1648: 
                   1649: 
                   1650: 
                   1651: int
                   1652: 
                   1653: has_wild(name)
                   1654: 
                   1655:        const char *name;
                   1656: 
                   1657: {
                   1658: 
                   1659:        char c;
                   1660: 
                   1661: 
                   1662: 
                   1663:        while (c = *name++) {
                   1664: 
                   1665:                if (c == '*' || c == '?') return 1;
                   1666: 
                   1667:        }
                   1668: 
                   1669:        return 0;
                   1670: 
                   1671: }
                   1672: 
                   1673: 
                   1674: 
                   1675: /*
                   1676: 
                   1677:  * void copy8_3(dest, src): convert a file name (src) into DOS 8.3 format
                   1678: 
                   1679:  * (in dest). Note the following things:
                   1680: 
                   1681:  * if a field has less than the required number of characters, it is
                   1682: 
                   1683:  * padded with blanks
                   1684: 
                   1685:  * a '*' means to pad the rest of the field with '?' characters
                   1686: 
                   1687:  * special things to watch for:
                   1688: 
                   1689:  *     "." and ".." are more or less left alone
                   1690: 
                   1691:  *     "*.*" is recognized as a special pattern, for which dest is set
                   1692: 
                   1693:  *     to just "*"
                   1694: 
                   1695:  * Long names are truncated. Any extensions after the first one are
                   1696: 
                   1697:  * ignored, i.e. foo.bar.c -> foo.bar, foo.c.bar->foo.c.
                   1698: 
                   1699:  */
                   1700: 
                   1701: 
                   1702: 
                   1703: void
                   1704: 
                   1705: copy8_3(dest, src)
                   1706: 
                   1707:        char *dest;
                   1708: 
                   1709:        const char *src;
                   1710: 
                   1711: {
                   1712: 
                   1713:        char fill = ' ', c;
                   1714: 
                   1715:        int i;
                   1716: 
                   1717: 
                   1718: 
                   1719:        if (src[0] == '.') {
                   1720: 
                   1721:                if (src[1] == 0) {
                   1722: 
                   1723:                        strcpy(dest, ".       .   ");
                   1724: 
                   1725:                        return;
                   1726: 
                   1727:                }
                   1728: 
                   1729:                if (src[1] == '.' && src[2] == 0) {
                   1730: 
                   1731:                        strcpy(dest, "..      .   ");
                   1732: 
                   1733:                        return;
                   1734: 
                   1735:                }
                   1736: 
                   1737:        }
                   1738: 
                   1739:        if (src[0] == '*' && src[1] == '.' && src[2] == '*' && src[3] == 0) {
                   1740: 
                   1741:                dest[0] = '*';
                   1742: 
                   1743:                dest[1] = 0;
                   1744: 
                   1745:                return;
                   1746: 
                   1747:        }
                   1748: 
                   1749: 
                   1750: 
                   1751:        for (i = 0; i < 8; i++) {
                   1752: 
                   1753:                c = *src++;
                   1754: 
                   1755:                if (!c || c == '.') break;
                   1756: 
                   1757:                if (c == '*') {
                   1758: 
                   1759:                        fill = c = '?';
                   1760: 
                   1761:                }
                   1762: 
                   1763:                *dest++ = toupper(c);
                   1764: 
                   1765:        }
                   1766: 
                   1767:        while (i++ < 8) {
                   1768: 
                   1769:                *dest++ = fill;
                   1770: 
                   1771:        }
                   1772: 
                   1773:        *dest++ = '.';
                   1774: 
                   1775:        i = 0;
                   1776: 
                   1777:        fill = ' ';
                   1778: 
                   1779:        while (c && c != '.')
                   1780: 
                   1781:                c = *src++;
                   1782: 
                   1783: 
                   1784: 
                   1785:        if (c) {
                   1786: 
                   1787:                for( ;i < 3; i++) {
                   1788: 
                   1789:                        c = *src++;
                   1790: 
                   1791:                        if (!c || c == '.') break;
                   1792: 
                   1793:                        if (c == '*')
                   1794: 
                   1795:                                c = fill = '?';
                   1796: 
                   1797:                        *dest++ = toupper(c);
                   1798: 
                   1799:                }
                   1800: 
                   1801:        }
                   1802: 
                   1803:        while (i++ < 3)
                   1804: 
                   1805:                *dest++ = fill;
                   1806: 
                   1807:        *dest++ = 0;
                   1808: 
                   1809: }
                   1810: 
                   1811: 
                   1812: 
                   1813: /*
                   1814: 
                   1815:  * int pat_match(name, patrn): returns 1 if "name" matches the template in
                   1816: 
                   1817:  * "patrn", 0 if not. "patrn" is assumed to have been expanded in 8.3
                   1818: 
                   1819:  * format by copy8_3; "name" need not be. Any '?' characters in patrn
                   1820: 
                   1821:  * will match any character in name. Note that if "patrn" has a '*' as
                   1822: 
                   1823:  * the first character, it will always match; this will happen only if
                   1824: 
                   1825:  * the original pattern (before copy8_3 was applied) was "*.*".
                   1826: 
                   1827:  *
                   1828: 
                   1829:  * BUGS: acts a lot like the silly TOS pattern matcher.
                   1830: 
                   1831:  */
                   1832: 
                   1833: 
                   1834: 
                   1835: int
                   1836: 
                   1837: pat_match(name, template)
                   1838: 
                   1839:        const char *name, *template;
                   1840: 
                   1841: {
                   1842: 
                   1843:        register char *s, c;
                   1844: 
                   1845:        char expname[TOS_NAMELEN+1];
                   1846: 
                   1847: 
                   1848: 
                   1849:        if (*template == '*') return 1;
                   1850: 
                   1851:        copy8_3(expname, name);
                   1852: 
                   1853: 
                   1854: 
                   1855:        s = expname;
                   1856: 
                   1857:        while (c = *template++) {
                   1858: 
                   1859:                if (c != *s && c != '?')
                   1860: 
                   1861:                        return 0;
                   1862: 
                   1863:                s++;
                   1864: 
                   1865:        }
                   1866: 
                   1867:        return 1;
                   1868: 
                   1869: }
                   1870: 
                   1871: 
                   1872: 
                   1873: /*
                   1874: 
                   1875:  * int samefile(fcookie *a, fcookie *b): returns 1 if the two cookies
                   1876: 
                   1877:  * refer to the same file or directory, 0 otherwise
                   1878: 
                   1879:  */
                   1880: 
                   1881: 
                   1882: 
                   1883: int
                   1884: 
                   1885: samefile(a, b)
                   1886: 
                   1887:        fcookie *a, *b;
                   1888: 
                   1889: {
                   1890: 
                   1891:        if (a->fs == b->fs && a->dev == b->dev && a->index == b->index)
                   1892: 
                   1893:                return 1;
                   1894: 
                   1895:        return 0;
                   1896: 
                   1897: }
                   1898: 

unix.superglobalmegacorp.com

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