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