Annotation of MiNT/src/dosdir.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: /* DOS directory functions */
        !            10: 
        !            11: 
        !            12: 
        !            13: #include "mint.h"
        !            14: 
        !            15: 
        !            16: 
        !            17: /* change to a new drive: should always return a map of valid drives */
        !            18: 
        !            19: 
        !            20: 
        !            21: long
        !            22: 
        !            23: d_setdrv(d)
        !            24: 
        !            25:        int d;
        !            26: 
        !            27: {
        !            28: 
        !            29:        long r;
        !            30: 
        !            31:        extern long dosdrvs;    /* in filesys.c */
        !            32: 
        !            33: 
        !            34: 
        !            35:        r = drvmap() | dosdrvs | PSEUDODRVS;
        !            36: 
        !            37: 
        !            38: 
        !            39:        TRACE("Dsetdrv(%d)", d);
        !            40: 
        !            41:        if (d < 0 || d >= NUM_DRIVES || (r & (1L << d)) == 0) {
        !            42: 
        !            43:                DEBUG("Dsetdrv: invalid drive %d", d);
        !            44: 
        !            45:                return r;
        !            46: 
        !            47:        }
        !            48: 
        !            49: 
        !            50: 
        !            51:        curproc->base->p_defdrv = curproc->curdrv = d;
        !            52: 
        !            53:        return r;
        !            54: 
        !            55: }
        !            56: 
        !            57: 
        !            58: 
        !            59: long
        !            60: 
        !            61: d_getdrv()
        !            62: 
        !            63: {
        !            64: 
        !            65:        TRACE("Dgetdrv");
        !            66: 
        !            67:        return curproc->curdrv;
        !            68: 
        !            69: }
        !            70: 
        !            71: 
        !            72: 
        !            73: long
        !            74: 
        !            75: d_free(buf, d)
        !            76: 
        !            77:        long *buf;
        !            78: 
        !            79:        int d;
        !            80: 
        !            81: {
        !            82: 
        !            83:        fcookie *dir;
        !            84: 
        !            85: 
        !            86: 
        !            87:        TRACE("Dfree(%d)", d);
        !            88: 
        !            89: 
        !            90: 
        !            91: /* drive 0 means current drive, otherwise it's d-1 */
        !            92: 
        !            93:        if (d)
        !            94: 
        !            95:                d = d-1;
        !            96: 
        !            97:        else
        !            98: 
        !            99:                d = curproc->curdrv;
        !           100: 
        !           101: 
        !           102: 
        !           103:        if (d < 0 || d >= NUM_DRIVES)
        !           104: 
        !           105:                return EDRIVE;
        !           106: 
        !           107: 
        !           108: 
        !           109: /* check for a media change -- we don't care much either way, but it
        !           110: 
        !           111:  * does keep the results more accurate
        !           112: 
        !           113:  */
        !           114: 
        !           115:        (void)disk_changed(d);
        !           116: 
        !           117: 
        !           118: 
        !           119: /* use current directory, not root, since it's more likely that
        !           120: 
        !           121:  * programs are interested in the latter (this makes U: work much
        !           122: 
        !           123:  * better)
        !           124: 
        !           125:  */
        !           126: 
        !           127:        dir = &curproc->curdir[d];
        !           128: 
        !           129:        if (!dir->fs) {
        !           130: 
        !           131:                DEBUG("Dfree: bad drive");
        !           132: 
        !           133:                return EDRIVE;
        !           134: 
        !           135:        }
        !           136: 
        !           137: 
        !           138: 
        !           139:        return (*dir->fs->dfree)(dir, buf);
        !           140: 
        !           141: }
        !           142: 
        !           143: 
        !           144: 
        !           145: /* temp1 is a convenient place for path2fs puts the last component of
        !           146: 
        !           147:  *   the path name
        !           148: 
        !           149:  */
        !           150: 
        !           151: 
        !           152: 
        !           153: extern char temp1[PATH_MAX];   /* in filesys.c */
        !           154: 
        !           155: 
        !           156: 
        !           157: long
        !           158: 
        !           159: d_create(path)
        !           160: 
        !           161:        const char *path;
        !           162: 
        !           163: {
        !           164: 
        !           165:        fcookie dir;
        !           166: 
        !           167:        long r;
        !           168: 
        !           169: 
        !           170: 
        !           171:        TRACE("Dcreate(%s)", path);
        !           172: 
        !           173: 
        !           174: 
        !           175:        r = path2cookie(path, temp1, &dir);
        !           176: 
        !           177:        if (r) {
        !           178: 
        !           179:                DEBUG("Dcreate(%s): returning %ld", path, r);
        !           180: 
        !           181:                return r;       /* an error occured */
        !           182: 
        !           183:        }
        !           184: 
        !           185: /* check for write permission on the directory */
        !           186: 
        !           187:        r = dir_access(&dir, S_IWOTH);
        !           188: 
        !           189:        if (r) {
        !           190: 
        !           191:                DEBUG("Dcreate(%s): access to directory denied",path);
        !           192: 
        !           193:                return r;
        !           194: 
        !           195:        }
        !           196: 
        !           197:        return (*dir.fs->mkdir)(&dir, temp1, DEFAULT_DIRMODE & ~curproc->umask);
        !           198: 
        !           199: }
        !           200: 
        !           201: 
        !           202: 
        !           203: long
        !           204: 
        !           205: d_delete(path)
        !           206: 
        !           207:        const char *path;
        !           208: 
        !           209: {
        !           210: 
        !           211:        fcookie parentdir, targdir;
        !           212: 
        !           213:        long r;
        !           214: 
        !           215:        PROC *p;
        !           216: 
        !           217:        int i;
        !           218: 
        !           219:        XATTR xattr;
        !           220: 
        !           221: 
        !           222: 
        !           223:        TRACE("Ddelete(%s)", path);
        !           224: 
        !           225: 
        !           226: 
        !           227:        r = path2cookie(path, temp1, &parentdir);
        !           228: 
        !           229: 
        !           230: 
        !           231:        if (r) {
        !           232: 
        !           233:                DEBUG("Ddelete(%s): error %lx", path, r);
        !           234: 
        !           235:                return r;
        !           236: 
        !           237:        }
        !           238: 
        !           239: /* check for write permission on the directory which the target
        !           240: 
        !           241:  * is located
        !           242: 
        !           243:  */
        !           244: 
        !           245:        if (r = dir_access(&parentdir, S_IWOTH)) {
        !           246: 
        !           247:                DEBUG("Ddelete(%s): access to directory denied", path);
        !           248: 
        !           249:                return r;
        !           250: 
        !           251:        }
        !           252: 
        !           253: 
        !           254: 
        !           255: /* now get the info on the file itself */
        !           256: 
        !           257: 
        !           258: 
        !           259:        r = relpath2cookie(&parentdir, temp1, NULL, &targdir, 0);
        !           260: 
        !           261:        if (r || (r = (*targdir.fs->getxattr)(&targdir, &xattr))) {
        !           262: 
        !           263:                DEBUG("Ddelete: error %ld on %s", r, path);
        !           264: 
        !           265:                return r;
        !           266: 
        !           267:        }
        !           268: 
        !           269: 
        !           270: 
        !           271: /* if the "directory" is a symbolic link, really unlink it */
        !           272: 
        !           273:        if ( (xattr.mode & S_IFMT) == S_IFLNK ) {
        !           274: 
        !           275:                return (*parentdir.fs->remove)(&parentdir, temp1);
        !           276: 
        !           277:        }
        !           278: 
        !           279:        if ( (xattr.mode & S_IFMT) != S_IFDIR ) {
        !           280: 
        !           281:                DEBUG("Ddelete: %s is not a directory", path);
        !           282: 
        !           283:                return EPTHNF;
        !           284: 
        !           285:        }
        !           286: 
        !           287: 
        !           288: 
        !           289: /* don't delete anyone else's root or current directory */
        !           290: 
        !           291:        for (p = proclist; p; p = p->gl_next) {
        !           292: 
        !           293:                if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
        !           294: 
        !           295:                        continue;
        !           296: 
        !           297:                for (i = 0; i < NUM_DRIVES; i++) {
        !           298: 
        !           299:                        if (samefile(&targdir, &p->root[i])) {
        !           300: 
        !           301:                                DEBUG("Ddelete: directory %s is a root directory",
        !           302: 
        !           303:                                        path);
        !           304: 
        !           305:                                return EACCDN;
        !           306: 
        !           307:                        } else if (samefile(&targdir, &p->curdir[i])) {
        !           308: 
        !           309:                                if (i == p->curdrv && p != curproc)
        !           310: 
        !           311:                                        DEBUG("Ddelete: directory %s is in use",
        !           312: 
        !           313:                                                path);
        !           314: 
        !           315:                                else {
        !           316: 
        !           317:                                        p->curdir[i] = p->root[i];
        !           318: 
        !           319:                                } 
        !           320: 
        !           321:                        }
        !           322: 
        !           323:                }
        !           324: 
        !           325:        }
        !           326: 
        !           327: 
        !           328: 
        !           329:        return (*parentdir.fs->rmdir)(&parentdir, temp1);
        !           330: 
        !           331: }
        !           332: 
        !           333: 
        !           334: 
        !           335: long
        !           336: 
        !           337: d_setpath(path)
        !           338: 
        !           339:        const char *path;
        !           340: 
        !           341: {
        !           342: 
        !           343:        fcookie dir;
        !           344: 
        !           345:        int drv = curproc->curdrv;
        !           346: 
        !           347:        int i;
        !           348: 
        !           349:        char c;
        !           350: 
        !           351:        long r;
        !           352: 
        !           353:        XATTR xattr;
        !           354: 
        !           355: 
        !           356: 
        !           357:        TRACE("Dsetpath(%s)", path);
        !           358: 
        !           359: 
        !           360: 
        !           361:        r = path2cookie(path, follow_links, &dir);
        !           362: 
        !           363: 
        !           364: 
        !           365:        if (r) {
        !           366: 
        !           367:                DEBUG("Dsetpath(%s): returning %ld", path, r);
        !           368: 
        !           369:                return r;
        !           370: 
        !           371:        }
        !           372: 
        !           373: 
        !           374: 
        !           375:        if (path[0] && path[1] == ':') {
        !           376: 
        !           377:                c = *path;
        !           378: 
        !           379:                if (c >= 'a' && c <= 'z')
        !           380: 
        !           381:                        drv = c-'a';
        !           382: 
        !           383:                else if (c >= 'A' && c <= 'Z')
        !           384: 
        !           385:                        drv = c-'A';
        !           386: 
        !           387:        }
        !           388: 
        !           389: 
        !           390: 
        !           391:        r = (*dir.fs->getxattr)(&dir, &xattr);
        !           392: 
        !           393: 
        !           394: 
        !           395:        if (r < 0) {
        !           396: 
        !           397:                DEBUG("Dsetpath: file '%s': attributes not found", path);
        !           398: 
        !           399:                return r;
        !           400: 
        !           401:        }
        !           402: 
        !           403: 
        !           404: 
        !           405:        if (!(xattr.attr & FA_DIR)) {
        !           406: 
        !           407:                DEBUG("Dsetpath(%s): not a directory",path);
        !           408: 
        !           409:                return EPTHNF;
        !           410: 
        !           411:        }
        !           412: 
        !           413: 
        !           414: 
        !           415: /*
        !           416: 
        !           417:  * watch out for symbolic links; if c:\foo is a link to d:\bar, then
        !           418: 
        !           419:  * "cd c:\foo" should also change the drive to d:
        !           420: 
        !           421:  */
        !           422: 
        !           423:        if (drv != UNIDRV && dir.dev != curproc->root[drv].dev) {
        !           424: 
        !           425:                for (i = 0; i < NUM_DRIVES; i++) {
        !           426: 
        !           427:                        if (curproc->root[i].dev == dir.dev &&
        !           428: 
        !           429:                            curproc->root[i].fs == dir.fs) {
        !           430: 
        !           431:                                if (drv == curproc->curdrv)
        !           432: 
        !           433:                                        curproc->curdrv = i;
        !           434: 
        !           435:                                drv = i;
        !           436: 
        !           437:                                break;
        !           438: 
        !           439:                        }
        !           440: 
        !           441:                }
        !           442: 
        !           443:        }
        !           444: 
        !           445:        curproc->curdir[drv] = dir;
        !           446: 
        !           447:        return 0;
        !           448: 
        !           449: }
        !           450: 
        !           451: 
        !           452: 
        !           453: long
        !           454: 
        !           455: d_getpath(path, drv)
        !           456: 
        !           457:        char *path;
        !           458: 
        !           459:        int drv;
        !           460: 
        !           461: {
        !           462: 
        !           463:        fcookie *dir, *root;
        !           464: 
        !           465: 
        !           466: 
        !           467:        TRACE("Dgetpath(%c)", drv + '@');
        !           468: 
        !           469:        if (drv < 0 || drv > NUM_DRIVES)
        !           470: 
        !           471:                return EDRIVE;
        !           472: 
        !           473: 
        !           474: 
        !           475:        drv = (drv == 0) ? curproc->curdrv : drv-1;
        !           476: 
        !           477: 
        !           478: 
        !           479:        root = &curproc->root[drv];
        !           480: 
        !           481: 
        !           482: 
        !           483:        if (!root->fs) {        /* maybe not initialized yet? */
        !           484: 
        !           485:                changedrv(drv);
        !           486: 
        !           487:                root = &curproc->curdir[drv];
        !           488: 
        !           489:                if (!root->fs)
        !           490: 
        !           491:                        return EDRIVE;
        !           492: 
        !           493:        }
        !           494: 
        !           495:        dir = &curproc->curdir[drv];
        !           496: 
        !           497: 
        !           498: 
        !           499:        return (*root->fs->getname)(root, dir, path);
        !           500: 
        !           501: }
        !           502: 
        !           503: 
        !           504: 
        !           505: long
        !           506: 
        !           507: f_setdta(dta)
        !           508: 
        !           509:        DTABUF *dta;
        !           510: 
        !           511: {
        !           512: 
        !           513: 
        !           514: 
        !           515:        TRACE("Fsetdta: %lx", dta);
        !           516: 
        !           517:        curproc->dta = dta;
        !           518: 
        !           519:        curproc->base->p_dta = (char *)dta;
        !           520: 
        !           521:        return 0;
        !           522: 
        !           523: }
        !           524: 
        !           525: 
        !           526: 
        !           527: long
        !           528: 
        !           529: f_getdta()
        !           530: 
        !           531: {
        !           532: 
        !           533:        long r;
        !           534: 
        !           535: 
        !           536: 
        !           537:        r = (long)curproc->dta;
        !           538: 
        !           539:        TRACE("Fgetdta: returning %lx", r);
        !           540: 
        !           541:        return r;
        !           542: 
        !           543: }
        !           544: 
        !           545: 
        !           546: 
        !           547: /*
        !           548: 
        !           549:  * Fsfirst/next are actually implemented in terms of opendir/readdir/closedir.
        !           550: 
        !           551:  */
        !           552: 
        !           553: 
        !           554: 
        !           555: long
        !           556: 
        !           557: f_sfirst(path, attrib)
        !           558: 
        !           559:        const char *path;
        !           560: 
        !           561:        int attrib;
        !           562: 
        !           563: {
        !           564: 
        !           565:        char *s, *slash;
        !           566: 
        !           567:        FILESYS *fs;
        !           568: 
        !           569:        fcookie dir, newdir;
        !           570: 
        !           571:        DTABUF *dta;
        !           572: 
        !           573:        DIR *dirh;
        !           574: 
        !           575:        XATTR xattr;
        !           576: 
        !           577:        long r;
        !           578: 
        !           579:        int i, havelabel;
        !           580: 
        !           581: 
        !           582: 
        !           583: /* a special hack just for ksh0.4 -- it uses '/' in a search where
        !           584: 
        !           585:  * '\' was better. Note that normally we shouldn't go around changing
        !           586: 
        !           587:  * the strings that people send us!
        !           588: 
        !           589:  */
        !           590: 
        !           591:        if (curproc->domain == DOM_MINT && !strncmp(path, "x:/*.", 5))
        !           592: 
        !           593:                ((char *)path)[2] = '\\';
        !           594: 
        !           595: 
        !           596: 
        !           597:        TRACE("Fsfirst(%s, %x)", path, attrib);
        !           598: 
        !           599: 
        !           600: 
        !           601:        r = path2cookie(path, temp1, &dir);
        !           602: 
        !           603: 
        !           604: 
        !           605:        if (r) {
        !           606: 
        !           607:                DEBUG("Fsfirst(%s): path2cookie returned %ld", path, r);
        !           608: 
        !           609:                return r;
        !           610: 
        !           611:        }
        !           612: 
        !           613: 
        !           614: 
        !           615: /*
        !           616: 
        !           617:  * we need to split the last name (which may be a pattern) off from
        !           618: 
        !           619:  * the rest of the path, even if FS_KNOPARSE is true
        !           620: 
        !           621:  */
        !           622: 
        !           623:        slash = 0;
        !           624: 
        !           625:        s = temp1;
        !           626: 
        !           627:        while (*s) {
        !           628: 
        !           629:                if (*s == '\\')
        !           630: 
        !           631:                        slash = s;
        !           632: 
        !           633:                s++;
        !           634: 
        !           635:        }
        !           636: 
        !           637: 
        !           638: 
        !           639:        if (slash) {
        !           640: 
        !           641:                *slash++ = 0;   /* slash now points to a name or pattern */
        !           642: 
        !           643:                r = relpath2cookie(&dir, temp1, follow_links, &newdir, 0);
        !           644: 
        !           645:                if (r) {
        !           646: 
        !           647:                        DEBUG("Fsfirst(%s): lookup returned %ld", path, r);
        !           648: 
        !           649:                        return r;
        !           650: 
        !           651:                }
        !           652: 
        !           653:                dir = newdir;
        !           654: 
        !           655:        } else {
        !           656: 
        !           657:                slash = temp1;
        !           658: 
        !           659:        }
        !           660: 
        !           661: 
        !           662: 
        !           663: /* BUG? what if there really is an empty file name? */
        !           664: 
        !           665:        if (!*slash) {
        !           666: 
        !           667:                DEBUG("Fsfirst: empty pattern");
        !           668: 
        !           669:                return EFILNF;
        !           670: 
        !           671:        }
        !           672: 
        !           673: 
        !           674: 
        !           675:        fs = dir.fs;
        !           676: 
        !           677:        dta = curproc->dta;
        !           678: 
        !           679: 
        !           680: 
        !           681: /* Now, see if we can find a DIR slot for the search. We use the following
        !           682: 
        !           683:  * heuristics to try to avoid destroying a slot:
        !           684: 
        !           685:  * (1) if the search doesn't use wildcards, don't bother with a slot
        !           686: 
        !           687:  * (2) if an existing slot was for the same DTA address, re-use it
        !           688: 
        !           689:  * (3) if there's a free slot, re-use it. Slots are freed when the
        !           690: 
        !           691:  *     corresponding search is terminated.
        !           692: 
        !           693:  */
        !           694: 
        !           695: 
        !           696: 
        !           697:        for (i = 0; i < NUM_SEARCH; i++) {
        !           698: 
        !           699:                if (curproc->srchdta[i] == dta) {
        !           700: 
        !           701:                        dirh = &curproc->srchdir[i];
        !           702: 
        !           703:                        if (dirh->fc.fs) {
        !           704: 
        !           705:                                (*dirh->fc.fs->closedir)(dirh);
        !           706: 
        !           707:                                dirh->fc.fs = 0;
        !           708: 
        !           709:                        }
        !           710: 
        !           711:                        curproc->srchdta[i] = 0; /* slot is now free */
        !           712: 
        !           713:                }
        !           714: 
        !           715:        }
        !           716: 
        !           717: 
        !           718: 
        !           719: /* copy the pattern over into dta_pat into TOS 8.3 form */
        !           720: 
        !           721: /* remember that "slash" now points at the pattern (it follows the last \,
        !           722: 
        !           723:    if any)
        !           724: 
        !           725:  */
        !           726: 
        !           727:        copy8_3(dta->dta_pat, slash);
        !           728: 
        !           729: 
        !           730: 
        !           731: /* if attrib & FA_LABEL, read the volume label */
        !           732: 
        !           733: /* BUG: the label date and time are wrong. Does it matter?
        !           734: 
        !           735:  */
        !           736: 
        !           737:        havelabel = 0;
        !           738: 
        !           739:        if (attrib & FA_LABEL) {
        !           740: 
        !           741:                r = (*fs->readlabel)(&dir, dta->dta_name, TOS_NAMELEN);
        !           742: 
        !           743:                dta->dta_attrib = FA_LABEL;
        !           744: 
        !           745:                dta->dta_time = dta->dta_date = 0;
        !           746: 
        !           747:                dta->dta_size = 0;
        !           748: 
        !           749:                dta->magic = EVALID;
        !           750: 
        !           751:                if (r == 0 && !pat_match(dta->dta_name, dta->dta_pat))
        !           752: 
        !           753:                        r = EFILNF;
        !           754: 
        !           755:                if (attrib == FA_LABEL)
        !           756: 
        !           757:                        return r;
        !           758: 
        !           759:                else if (r == 0)
        !           760: 
        !           761:                        havelabel = 1;
        !           762: 
        !           763:        }
        !           764: 
        !           765: 
        !           766: 
        !           767:        if (!havelabel && has_wild(slash) == 0) { /* no wild cards in pattern */
        !           768: 
        !           769:                r = relpath2cookie(&dir, slash, follow_links, &newdir, 0);
        !           770: 
        !           771:                if (r == 0) {
        !           772: 
        !           773:                        r = (*newdir.fs->getxattr)(&newdir, &xattr);
        !           774: 
        !           775:                }
        !           776: 
        !           777:                if (r) {
        !           778: 
        !           779:                        DEBUG("Fsfirst(%s): couldn't get file attributes",path);
        !           780: 
        !           781:                        return r;
        !           782: 
        !           783:                }
        !           784: 
        !           785:                dta->magic = EVALID;
        !           786: 
        !           787:                dta->dta_attrib = xattr.attr;
        !           788: 
        !           789:                dta->dta_time = xattr.mtime;
        !           790: 
        !           791:                dta->dta_date = xattr.mdate;
        !           792: 
        !           793:                dta->dta_size = xattr.size;
        !           794: 
        !           795:                strncpy(dta->dta_name, slash, TOS_NAMELEN-1);
        !           796: 
        !           797:                dta->dta_name[TOS_NAMELEN-1] = 0;
        !           798: 
        !           799:                if (curproc->domain == DOM_TOS &&
        !           800: 
        !           801:                    !(fs->fsflags & FS_CASESENSITIVE))
        !           802: 
        !           803:                        strupr(dta->dta_name);
        !           804: 
        !           805: 
        !           806: 
        !           807:                return 0;
        !           808: 
        !           809:        }
        !           810: 
        !           811: 
        !           812: 
        !           813: /* There is a wild card. Try to find a slot for an opendir/readdir
        !           814: 
        !           815:  * search. NOTE: we also come here if we were asked to search for
        !           816: 
        !           817:  * volume labels and found one.
        !           818: 
        !           819:  */
        !           820: 
        !           821:        for (i = 0; i < NUM_SEARCH; i++) {
        !           822: 
        !           823:                if (curproc->srchdta[i] == 0)
        !           824: 
        !           825:                        break;
        !           826: 
        !           827:        }
        !           828: 
        !           829:        if (i == NUM_SEARCH) {
        !           830: 
        !           831:                int oldest = 0; int oldtime = curproc->srchtim[0];
        !           832: 
        !           833: 
        !           834: 
        !           835:                DEBUG("Fsfirst(%s): having to re-use a directory slot!",path);
        !           836: 
        !           837:                for (i = 1; i < NUM_SEARCH; i++) {
        !           838: 
        !           839:                        if (curproc->srchtim[i] < oldtime) {
        !           840: 
        !           841:                                oldest = i;
        !           842: 
        !           843:                                oldtime = curproc->srchtim[i];
        !           844: 
        !           845:                        }
        !           846: 
        !           847:                }
        !           848: 
        !           849:        /* OK, close this directory for re-use */
        !           850: 
        !           851:                i = oldest;
        !           852: 
        !           853:                dirh = &curproc->srchdir[i];
        !           854: 
        !           855:                if (dirh->fc.fs) {
        !           856: 
        !           857:                        (*dirh->fc.fs->closedir)(dirh);
        !           858: 
        !           859:                        dirh->fc.fs = 0;
        !           860: 
        !           861:                }
        !           862: 
        !           863:                curproc->srchdta[i] = 0;
        !           864: 
        !           865:        }
        !           866: 
        !           867: 
        !           868: 
        !           869: /* check to see if we have read permission on the directory (and make
        !           870: 
        !           871:  * sure that it really is a directory!
        !           872: 
        !           873:  */
        !           874: 
        !           875:        r = dir_access(&dir, S_IROTH);
        !           876: 
        !           877:        if (r) {
        !           878: 
        !           879:                DEBUG("Fsfirst(%s): access to directory denied",path);
        !           880: 
        !           881:                return r;
        !           882: 
        !           883:        }
        !           884: 
        !           885: 
        !           886: 
        !           887: /* set up the directory for a search */
        !           888: 
        !           889:        dirh = &curproc->srchdir[i];
        !           890: 
        !           891:        dirh->fc = dir;
        !           892: 
        !           893:        dirh->index = 0;
        !           894: 
        !           895:        dirh->flags = TOS_SEARCH;
        !           896: 
        !           897:        r = (*dir.fs->opendir)(dirh, dirh->flags);
        !           898: 
        !           899:        if (r != 0) {
        !           900: 
        !           901:                DEBUG("Fsfirst(%s): couldn't open directory (error %ld)",
        !           902: 
        !           903:                        path, r);
        !           904: 
        !           905:                return r;
        !           906: 
        !           907:        }
        !           908: 
        !           909: 
        !           910: 
        !           911: /* mark the slot as in-use */
        !           912: 
        !           913:        curproc->srchdta[i] = dta;
        !           914: 
        !           915: 
        !           916: 
        !           917: /* set up the DTA for Fsnext */
        !           918: 
        !           919:        dta->index = i;
        !           920: 
        !           921:        dta->magic = SVALID;
        !           922: 
        !           923:        dta->dta_sattrib = attrib;
        !           924: 
        !           925: 
        !           926: 
        !           927: /* OK, now basically just do Fsnext, except that instead of ENMFIL we
        !           928: 
        !           929:  * return EFILNF.
        !           930: 
        !           931:  * NOTE: If we already have found a volume label from the search above,
        !           932: 
        !           933:  * then we skip the f_snext and just return that.
        !           934: 
        !           935:  */
        !           936: 
        !           937:        if (havelabel)
        !           938: 
        !           939:                return 0;
        !           940: 
        !           941: 
        !           942: 
        !           943:        r = f_snext();
        !           944: 
        !           945:        if (r == ENMFIL) r = EFILNF;
        !           946: 
        !           947:        if (r)
        !           948: 
        !           949:                TRACE("Fsfirst: returning %ld", r);
        !           950: 
        !           951:        return r;
        !           952: 
        !           953: }
        !           954: 
        !           955: 
        !           956: 
        !           957: /*
        !           958: 
        !           959:  * Counter for Fsfirst/Fsnext, so that we know which search slots are
        !           960: 
        !           961:  * least recently used. This is updated once per second by the code
        !           962: 
        !           963:  * in timeout.c.
        !           964: 
        !           965:  * BUG: 1/second is pretty low granularity
        !           966: 
        !           967:  */
        !           968: 
        !           969: 
        !           970: 
        !           971: long searchtime;
        !           972: 
        !           973: 
        !           974: 
        !           975: long
        !           976: 
        !           977: f_snext()
        !           978: 
        !           979: {
        !           980: 
        !           981:        static char buf[TOS_NAMELEN+1];
        !           982: 
        !           983:        DTABUF *dta = curproc->dta;
        !           984: 
        !           985:        FILESYS *fs;
        !           986: 
        !           987:        fcookie fc;
        !           988: 
        !           989:        int i;
        !           990: 
        !           991:        DIR *dirh;
        !           992: 
        !           993:        long r;
        !           994: 
        !           995:        XATTR xattr;
        !           996: 
        !           997: 
        !           998: 
        !           999:        TRACE("Fsnext");
        !          1000: 
        !          1001: 
        !          1002: 
        !          1003:        if (dta->magic == EVALID) {
        !          1004: 
        !          1005:                DEBUG("Fsnext: DTA marked a failing search");
        !          1006: 
        !          1007:                return ENMFIL;
        !          1008: 
        !          1009:        }
        !          1010: 
        !          1011:        if (dta->magic != SVALID) {
        !          1012: 
        !          1013:                DEBUG("Fsnext: dta incorrectly set up");
        !          1014: 
        !          1015:                return EINVFN;
        !          1016: 
        !          1017:        }
        !          1018: 
        !          1019: 
        !          1020: 
        !          1021:        i = dta->index;
        !          1022: 
        !          1023:        dirh = &curproc->srchdir[i];
        !          1024: 
        !          1025:        curproc->srchtim[i] = searchtime;
        !          1026: 
        !          1027: 
        !          1028: 
        !          1029:        fs = dirh->fc.fs;
        !          1030: 
        !          1031:        if (!fs)                /* oops -- the directory got closed somehow */
        !          1032: 
        !          1033:                return EINTRN;
        !          1034: 
        !          1035: 
        !          1036: 
        !          1037: /* BUG: f_snext and readdir should check for disk media changes */
        !          1038: 
        !          1039: 
        !          1040: 
        !          1041:        for(;;) {
        !          1042: 
        !          1043:                r = (*fs->readdir)(dirh, buf, TOS_NAMELEN+1, &fc);
        !          1044: 
        !          1045: 
        !          1046: 
        !          1047:                if (r == ENAMETOOLONG) {
        !          1048: 
        !          1049:                        DEBUG("Fsnext: name too long");
        !          1050: 
        !          1051:                        continue;       /* TOS programs never see these names */
        !          1052: 
        !          1053:                }
        !          1054: 
        !          1055:                if (r != 0) {
        !          1056: 
        !          1057: baderror:
        !          1058: 
        !          1059:                        (void)(*fs->closedir)(dirh);
        !          1060: 
        !          1061:                        dirh->fc.fs = 0;
        !          1062: 
        !          1063:                        curproc->srchdta[i] = 0;
        !          1064: 
        !          1065:                        dta->magic = EVALID;
        !          1066: 
        !          1067:                        if (r != ENMFIL)
        !          1068: 
        !          1069:                                DEBUG("Fsnext: returning %ld", r);
        !          1070: 
        !          1071:                        return r;
        !          1072: 
        !          1073:                }
        !          1074: 
        !          1075: 
        !          1076: 
        !          1077:                if (!pat_match(buf, dta->dta_pat))
        !          1078: 
        !          1079:                        continue;       /* different patterns */
        !          1080: 
        !          1081: 
        !          1082: 
        !          1083:        /* check for search attributes */
        !          1084: 
        !          1085:                r = (*fc.fs->getxattr)(&fc, &xattr);
        !          1086: 
        !          1087:                if (r) {
        !          1088: 
        !          1089:                        DEBUG("Fsnext: couldn't get file attributes");
        !          1090: 
        !          1091:                        goto baderror;
        !          1092: 
        !          1093:                }
        !          1094: 
        !          1095:        /* if the file is a symbolic link, try to find what it's linked to */
        !          1096: 
        !          1097:                if ( (xattr.mode & S_IFMT) == S_IFLNK ) {
        !          1098: 
        !          1099:                        char linkedto[PATH_MAX];
        !          1100: 
        !          1101:                        r = (*fc.fs->readlink)(&fc, linkedto, PATH_MAX);
        !          1102: 
        !          1103:                        if (r == 0) {
        !          1104: 
        !          1105:                        /* the "1" tells relpath2cookie that we read a link */
        !          1106: 
        !          1107:                            r = relpath2cookie(&dirh->fc, linkedto,
        !          1108: 
        !          1109:                                        follow_links, &fc, 1);
        !          1110: 
        !          1111:                            if (r == 0)
        !          1112: 
        !          1113:                                r = (*fc.fs->getxattr)(&fc, &xattr);
        !          1114: 
        !          1115:                        }
        !          1116: 
        !          1117:                        if (r) {
        !          1118: 
        !          1119:                                DEBUG("Fsnext: couldn't follow link: error %ld",
        !          1120: 
        !          1121:                                        r);
        !          1122: 
        !          1123:                        }
        !          1124: 
        !          1125:                }
        !          1126: 
        !          1127: 
        !          1128: 
        !          1129:        /* silly TOS rules for matching attributes */
        !          1130: 
        !          1131:                if (xattr.attr == 0) break;
        !          1132: 
        !          1133:                if (xattr.attr & 0x21) break;
        !          1134: 
        !          1135:                if (dta->dta_sattrib & xattr.attr)
        !          1136: 
        !          1137:                        break;
        !          1138: 
        !          1139:        }
        !          1140: 
        !          1141: 
        !          1142: 
        !          1143: /* here, we have a match */
        !          1144: 
        !          1145:        dta->dta_attrib = xattr.attr;
        !          1146: 
        !          1147:        dta->dta_time = xattr.mtime;
        !          1148: 
        !          1149:        dta->dta_date = xattr.mdate;
        !          1150: 
        !          1151:        dta->dta_size = xattr.size;
        !          1152: 
        !          1153:        strcpy(dta->dta_name, buf);
        !          1154: 
        !          1155: 
        !          1156: 
        !          1157:        if (curproc->domain == DOM_TOS && !(fs->fsflags & FS_CASESENSITIVE)) {
        !          1158: 
        !          1159:                strupr(dta->dta_name);
        !          1160: 
        !          1161:        }
        !          1162: 
        !          1163:        return 0;
        !          1164: 
        !          1165: }
        !          1166: 
        !          1167: 
        !          1168: 
        !          1169: long
        !          1170: 
        !          1171: f_attrib(name, rwflag, attr)
        !          1172: 
        !          1173:        const char *name;
        !          1174: 
        !          1175:        int rwflag;
        !          1176: 
        !          1177:        int attr;
        !          1178: 
        !          1179: {
        !          1180: 
        !          1181:        fcookie fc;
        !          1182: 
        !          1183:        XATTR xattr;
        !          1184: 
        !          1185:        long r;
        !          1186: 
        !          1187: 
        !          1188: 
        !          1189:        TRACE("Fattrib(%s, %d)", name, attr);
        !          1190: 
        !          1191: 
        !          1192: 
        !          1193:        r = path2cookie(name, (char *)0, &fc);
        !          1194: 
        !          1195: 
        !          1196: 
        !          1197:        if (r) {
        !          1198: 
        !          1199:                DEBUG("Fattrib(%s): error %ld", name, r);
        !          1200: 
        !          1201:                return r;
        !          1202: 
        !          1203:        }
        !          1204: 
        !          1205: 
        !          1206: 
        !          1207:        r = (*fc.fs->getxattr)(&fc, &xattr);
        !          1208: 
        !          1209: 
        !          1210: 
        !          1211:        if (r) {
        !          1212: 
        !          1213:                DEBUG("Fattrib(%s): getxattr returned %ld", name, r);
        !          1214: 
        !          1215:                return r;
        !          1216: 
        !          1217:        }
        !          1218: 
        !          1219: 
        !          1220: 
        !          1221:        if (rwflag) {
        !          1222: 
        !          1223:                if (attr & (FA_LABEL|FA_DIR)) {
        !          1224: 
        !          1225:                        DEBUG("Fattrib(%s): illegal attributes specified",name);
        !          1226: 
        !          1227:                        return EACCDN;
        !          1228: 
        !          1229:                } else if (curproc->euid && curproc->euid != xattr.uid) {
        !          1230: 
        !          1231:                        DEBUG("Fattrib(%s): not the file's owner",name);
        !          1232: 
        !          1233:                        return EACCDN;
        !          1234: 
        !          1235:                } else if (xattr.attr & (FA_LABEL|FA_DIR)) {
        !          1236: 
        !          1237:                        DEBUG("Fattrib(%s): file is a volume label "
        !          1238: 
        !          1239:                              "or directory",name);
        !          1240: 
        !          1241:                        return EACCDN;
        !          1242: 
        !          1243:                }
        !          1244: 
        !          1245:                return (*fc.fs->chattr)(&fc, attr);
        !          1246: 
        !          1247:        } else {
        !          1248: 
        !          1249:                return xattr.attr;
        !          1250: 
        !          1251:        }
        !          1252: 
        !          1253: }
        !          1254: 
        !          1255: 
        !          1256: 
        !          1257: long
        !          1258: 
        !          1259: f_delete(name)
        !          1260: 
        !          1261:        const char *name;
        !          1262: 
        !          1263: {
        !          1264: 
        !          1265:        fcookie dir;
        !          1266: 
        !          1267:        long r;
        !          1268: 
        !          1269: 
        !          1270: 
        !          1271:        TRACE("Fdelete(%s)", name);
        !          1272: 
        !          1273: 
        !          1274: 
        !          1275:        r = path2cookie(name, temp1, &dir);
        !          1276: 
        !          1277: 
        !          1278: 
        !          1279:        if (r) {
        !          1280: 
        !          1281:                DEBUG("Fdelete: error %ld", r);
        !          1282: 
        !          1283:                return r;
        !          1284: 
        !          1285:        }
        !          1286: 
        !          1287: 
        !          1288: 
        !          1289: /* check for write permission on directory */
        !          1290: 
        !          1291:        r = dir_access(&dir, S_IWOTH);
        !          1292: 
        !          1293:        if (r) {
        !          1294: 
        !          1295:                DEBUG("Fdelete(%s): write access to directory denied",name);
        !          1296: 
        !          1297:                return r;
        !          1298: 
        !          1299:        }
        !          1300: 
        !          1301: /* BUG: we should check here for a read-only file */
        !          1302: 
        !          1303:        return (*dir.fs->remove)(&dir,temp1);
        !          1304: 
        !          1305: }
        !          1306: 
        !          1307: 
        !          1308: 
        !          1309: long
        !          1310: 
        !          1311: f_rename(junk, old, new)
        !          1312: 
        !          1313:        int junk;               /* ignored, for TOS compatibility */
        !          1314: 
        !          1315:        const char *old, *new;
        !          1316: 
        !          1317: {
        !          1318: 
        !          1319:        fcookie olddir, newdir, oldfil;
        !          1320: 
        !          1321:        XATTR xattr;
        !          1322: 
        !          1323:        char temp2[PATH_MAX];
        !          1324: 
        !          1325:        long r;
        !          1326: 
        !          1327: 
        !          1328: 
        !          1329:        TRACE("Frename(%s, %s)", old, new);
        !          1330: 
        !          1331: 
        !          1332: 
        !          1333:        r = path2cookie(old, temp2, &olddir);
        !          1334: 
        !          1335:        if (r) {
        !          1336: 
        !          1337:                DEBUG("Frename(%s,%s): error parsing old name",old,new);
        !          1338: 
        !          1339:                return r;
        !          1340: 
        !          1341:        }
        !          1342: 
        !          1343: /* check for permissions on the old file
        !          1344: 
        !          1345:  * GEMDOS doesn't allow rename if the file is FA_RDONLY
        !          1346: 
        !          1347:  * we enforce this restriction only on regular files; processes,
        !          1348: 
        !          1349:  * directories, and character special files can be renamed at will
        !          1350: 
        !          1351:  */
        !          1352: 
        !          1353:        r = relpath2cookie(&olddir, temp2, follow_links, &oldfil, 0);
        !          1354: 
        !          1355:        if (r) {
        !          1356: 
        !          1357:                DEBUG("Frename(%s,%s): old file not found",old,new);
        !          1358: 
        !          1359:                return r;
        !          1360: 
        !          1361:        }
        !          1362: 
        !          1363:        r = (*oldfil.fs->getxattr)(&oldfil, &xattr);
        !          1364: 
        !          1365:        if (r ||
        !          1366: 
        !          1367:            ((xattr.mode & S_IFMT) == S_IFREG && (xattr.attr & FA_RDONLY)) )
        !          1368: 
        !          1369:        {
        !          1370: 
        !          1371:                DEBUG("Frename(%s,%s): access to old file not granted",old,new);
        !          1372: 
        !          1373:                return EACCDN;
        !          1374: 
        !          1375:        }
        !          1376: 
        !          1377:        r = path2cookie(new, temp1, &newdir);
        !          1378: 
        !          1379:        if (r) {
        !          1380: 
        !          1381:                DEBUG("Frename(%s,%s): error parsing new name",old,new);
        !          1382: 
        !          1383:                return r;
        !          1384: 
        !          1385:        }
        !          1386: 
        !          1387: 
        !          1388: 
        !          1389:        if (newdir.fs != olddir.fs) {
        !          1390: 
        !          1391:                DEBUG("Frename(%s,%s): different file systems",old,new);
        !          1392: 
        !          1393:                return EXDEV;   /* cross device rename */
        !          1394: 
        !          1395:        }
        !          1396: 
        !          1397: 
        !          1398: 
        !          1399: /* check for write permission on both directories */
        !          1400: 
        !          1401:        r = dir_access(&olddir, S_IWOTH);
        !          1402: 
        !          1403:        if (!r) r = dir_access(&newdir, S_IWOTH);
        !          1404: 
        !          1405:        if (r) {
        !          1406: 
        !          1407:                DEBUG("Frename(%s,%s): access to a directory denied",old,new);
        !          1408: 
        !          1409:                return r;
        !          1410: 
        !          1411:        }
        !          1412: 
        !          1413:        return (*newdir.fs->rename)(&olddir, temp2, &newdir, temp1);
        !          1414: 
        !          1415: }
        !          1416: 
        !          1417: 
        !          1418: 
        !          1419: /*
        !          1420: 
        !          1421:  * GEMDOS extension: Dpathconf(name, which)
        !          1422: 
        !          1423:  * returns information about filesystem-imposed limits; "name" is the name
        !          1424: 
        !          1425:  * of a file or directory about which the limit information is requested;
        !          1426: 
        !          1427:  * "which" is the limit requested, as follows:
        !          1428: 
        !          1429:  *     -1      max. value of "which" allowed
        !          1430: 
        !          1431:  *     0       internal limit on open files, if any
        !          1432: 
        !          1433:  *     1       max. number of links to a file  {LINK_MAX}
        !          1434: 
        !          1435:  *     2       max. path name length           {PATH_MAX}
        !          1436: 
        !          1437:  *     3       max. file name length           {NAME_MAX}
        !          1438: 
        !          1439:  *     4       no. of bytes in atomic write to FIFO {PIPE_BUF}
        !          1440: 
        !          1441:  *     5       file name truncation rules
        !          1442: 
        !          1443:  *     6       file name case translation rules
        !          1444: 
        !          1445:  *
        !          1446: 
        !          1447:  * unlimited values are returned as 0x7fffffffL
        !          1448: 
        !          1449:  *
        !          1450: 
        !          1451:  * see also Sysconf() in dos.c
        !          1452: 
        !          1453:  */
        !          1454: 
        !          1455: 
        !          1456: 
        !          1457: long
        !          1458: 
        !          1459: d_pathconf(name, which)
        !          1460: 
        !          1461:        const char *name;
        !          1462: 
        !          1463:        int which;
        !          1464: 
        !          1465: {
        !          1466: 
        !          1467:        fcookie dir;
        !          1468: 
        !          1469:        long r;
        !          1470: 
        !          1471: 
        !          1472: 
        !          1473:        r = path2cookie(name, (char *)0, &dir);
        !          1474: 
        !          1475:        if (r) {
        !          1476: 
        !          1477:                DEBUG("Dpathconf(%s): bad path",name);
        !          1478: 
        !          1479:                return r;
        !          1480: 
        !          1481:        }
        !          1482: 
        !          1483:        r = (*dir.fs->pathconf)(&dir, which);
        !          1484: 
        !          1485:        if (which == DP_CASE && r == EINVFN) {
        !          1486: 
        !          1487:        /* backward compatibility with old .XFS files */
        !          1488: 
        !          1489:                return (dir.fs->fsflags & FS_CASESENSITIVE) ? DP_CASESENS :
        !          1490: 
        !          1491:                                DP_CASEINSENS;
        !          1492: 
        !          1493:        }
        !          1494: 
        !          1495:        return r;
        !          1496: 
        !          1497: }
        !          1498: 
        !          1499: 
        !          1500: 
        !          1501: /*
        !          1502: 
        !          1503:  * GEMDOS extension: Opendir/Readdir/Rewinddir/Closedir offer a new,
        !          1504: 
        !          1505:  * POSIX-like alternative to Fsfirst/Fsnext, and as a bonus allow for
        !          1506: 
        !          1507:  * arbitrary length file names
        !          1508: 
        !          1509:  */
        !          1510: 
        !          1511: 
        !          1512: 
        !          1513: long
        !          1514: 
        !          1515: d_opendir(name, flag)
        !          1516: 
        !          1517:        const char *name;
        !          1518: 
        !          1519:        int flag;
        !          1520: 
        !          1521: {
        !          1522: 
        !          1523:        DIR *dirh;
        !          1524: 
        !          1525:        fcookie dir;
        !          1526: 
        !          1527:        long r;
        !          1528: 
        !          1529: 
        !          1530: 
        !          1531:        r = path2cookie(name, follow_links, &dir);
        !          1532: 
        !          1533:        if (r) {
        !          1534: 
        !          1535:                DEBUG("Dopendir(%s): error %ld", name, r);
        !          1536: 
        !          1537:                return r;
        !          1538: 
        !          1539:        }
        !          1540: 
        !          1541:        r = dir_access(&dir, S_IROTH);
        !          1542: 
        !          1543:        if (r) {
        !          1544: 
        !          1545:                DEBUG("Dopendir(%s): read permission denied", name);
        !          1546: 
        !          1547:                return r;
        !          1548: 
        !          1549:        }
        !          1550: 
        !          1551: 
        !          1552: 
        !          1553:        dirh = (DIR *)umalloc(SIZEOF(DIR));
        !          1554: 
        !          1555:        if (!dirh) return ENSMEM;
        !          1556: 
        !          1557: 
        !          1558: 
        !          1559:        dirh->fc = dir;
        !          1560: 
        !          1561:        dirh->index = 0;
        !          1562: 
        !          1563:        dirh->flags = flag;
        !          1564: 
        !          1565:        r = (*dir.fs->opendir)(dirh, flag);
        !          1566: 
        !          1567:        if (r) {
        !          1568: 
        !          1569:                DEBUG("d_opendir(%s): opendir returned %ld", name, r);
        !          1570: 
        !          1571:                ufree(dirh);
        !          1572: 
        !          1573:                return r;
        !          1574: 
        !          1575:        }
        !          1576: 
        !          1577:        return (long)dirh;
        !          1578: 
        !          1579: }
        !          1580: 
        !          1581: 
        !          1582: 
        !          1583: long
        !          1584: 
        !          1585: d_readdir(len, handle, buf)
        !          1586: 
        !          1587:        int len;
        !          1588: 
        !          1589:        long handle;
        !          1590: 
        !          1591:        char *buf;
        !          1592: 
        !          1593: {
        !          1594: 
        !          1595:        DIR *dirh = (DIR *)handle;
        !          1596: 
        !          1597:        fcookie fc;
        !          1598: 
        !          1599: 
        !          1600: 
        !          1601:        if (!dirh->fc.fs)
        !          1602: 
        !          1603:                return EIHNDL;
        !          1604: 
        !          1605:        return (*dirh->fc.fs->readdir)(dirh, buf, len, &fc);
        !          1606: 
        !          1607: }
        !          1608: 
        !          1609: 
        !          1610: 
        !          1611: long
        !          1612: 
        !          1613: d_rewind(handle)
        !          1614: 
        !          1615:        long handle;
        !          1616: 
        !          1617: {
        !          1618: 
        !          1619:        DIR *dirh = (DIR *)handle;
        !          1620: 
        !          1621: 
        !          1622: 
        !          1623:        if (!dirh->fc.fs)
        !          1624: 
        !          1625:                return EIHNDL;
        !          1626: 
        !          1627:        return (*dirh->fc.fs->rewinddir)(dirh);
        !          1628: 
        !          1629: }
        !          1630: 
        !          1631: 
        !          1632: 
        !          1633: long
        !          1634: 
        !          1635: d_closedir(handle)
        !          1636: 
        !          1637:        long handle;
        !          1638: 
        !          1639: {
        !          1640: 
        !          1641:        long r;
        !          1642: 
        !          1643:        DIR *dirh = (DIR *)handle;
        !          1644: 
        !          1645: 
        !          1646: 
        !          1647:        if (!dirh->fc.fs)
        !          1648: 
        !          1649:                return EIHNDL;
        !          1650: 
        !          1651:        r = (*dirh->fc.fs->closedir)(dirh);
        !          1652: 
        !          1653:        dirh->fc.fs = 0;
        !          1654: 
        !          1655: 
        !          1656: 
        !          1657:        if (r) {
        !          1658: 
        !          1659:                DEBUG("Dclosedir: error %ld", r);
        !          1660: 
        !          1661:        }
        !          1662: 
        !          1663:        ufree(dirh);
        !          1664: 
        !          1665:        return r;
        !          1666: 
        !          1667: }
        !          1668: 
        !          1669: 
        !          1670: 
        !          1671: /*
        !          1672: 
        !          1673:  * GEMDOS extension: Fxattr gets extended attributes for a file. "flag"
        !          1674: 
        !          1675:  * is 0 if symbolic links are to be followed (like stat), 1 if not (like
        !          1676: 
        !          1677:  * lstat).
        !          1678: 
        !          1679:  */
        !          1680: 
        !          1681: 
        !          1682: 
        !          1683: long
        !          1684: 
        !          1685: f_xattr(flag, name, xattr)
        !          1686: 
        !          1687:        int flag;
        !          1688: 
        !          1689:        const char *name;
        !          1690: 
        !          1691:        XATTR *xattr;
        !          1692: 
        !          1693: {
        !          1694: 
        !          1695:        fcookie fc;
        !          1696: 
        !          1697:        long r;
        !          1698: 
        !          1699: 
        !          1700: 
        !          1701:        TRACE("Fxattr(%d, %s)", flag, name);
        !          1702: 
        !          1703: 
        !          1704: 
        !          1705:        r = path2cookie(name, flag ? (char *)0 : follow_links, &fc);
        !          1706: 
        !          1707:        if (r) {
        !          1708: 
        !          1709:                DEBUG("Fxattr(%s): path2cookie returned %ld", name, r);
        !          1710: 
        !          1711:                return r;
        !          1712: 
        !          1713:        }
        !          1714: 
        !          1715:        r = (*fc.fs->getxattr)(&fc, xattr);
        !          1716: 
        !          1717:        if (r) {
        !          1718: 
        !          1719:                DEBUG("Fxattr(%s): returning %ld", name, r);
        !          1720: 
        !          1721:        }
        !          1722: 
        !          1723:        return r;
        !          1724: 
        !          1725: }
        !          1726: 
        !          1727: 
        !          1728: 
        !          1729: /*
        !          1730: 
        !          1731:  * GEMDOS extension: Flink(old, new) creates a hard link named "new"
        !          1732: 
        !          1733:  * to the file "old".
        !          1734: 
        !          1735:  */
        !          1736: 
        !          1737: 
        !          1738: 
        !          1739: long
        !          1740: 
        !          1741: f_link(old, new)
        !          1742: 
        !          1743:        const char *old, *new;
        !          1744: 
        !          1745: {
        !          1746: 
        !          1747:        fcookie olddir, newdir;
        !          1748: 
        !          1749:        char temp2[PATH_MAX];
        !          1750: 
        !          1751:        long r;
        !          1752: 
        !          1753: 
        !          1754: 
        !          1755:        TRACE("Flink(%s, %s)", old, new);
        !          1756: 
        !          1757: 
        !          1758: 
        !          1759:        r = path2cookie(old, temp2, &olddir);
        !          1760: 
        !          1761:        if (r) {
        !          1762: 
        !          1763:                DEBUG("Flink(%s,%s): error parsing old name",old,new);
        !          1764: 
        !          1765:                return r;
        !          1766: 
        !          1767:        }
        !          1768: 
        !          1769:        r = path2cookie(new, temp1, &newdir);
        !          1770: 
        !          1771:        if (r) {
        !          1772: 
        !          1773:                DEBUG("Flink(%s,%s): error parsing new name",old,new);
        !          1774: 
        !          1775:                return r;
        !          1776: 
        !          1777:        }
        !          1778: 
        !          1779: 
        !          1780: 
        !          1781:        if (newdir.fs != olddir.fs) {
        !          1782: 
        !          1783:                DEBUG("Flink(%s,%s): different file systems",old,new);
        !          1784: 
        !          1785:                return EXDEV;   /* cross device link */
        !          1786: 
        !          1787:        }
        !          1788: 
        !          1789: 
        !          1790: 
        !          1791: /* check for write permission on the destination directory */
        !          1792: 
        !          1793: 
        !          1794: 
        !          1795:        r = dir_access(&newdir, S_IWOTH);
        !          1796: 
        !          1797:        if (r) {
        !          1798: 
        !          1799:                DEBUG("Flink(%s,%s): access to directory denied",old,new);
        !          1800: 
        !          1801:                return r;
        !          1802: 
        !          1803:        }
        !          1804: 
        !          1805:        return (*newdir.fs->hardlink)(&olddir, temp2, &newdir, temp1);
        !          1806: 
        !          1807: }
        !          1808: 
        !          1809: 
        !          1810: 
        !          1811: /*
        !          1812: 
        !          1813:  * GEMDOS extension: Fsymlink(old, new): create a symbolic link named
        !          1814: 
        !          1815:  * "new" that contains the path "old".
        !          1816: 
        !          1817:  */
        !          1818: 
        !          1819: 
        !          1820: 
        !          1821: long
        !          1822: 
        !          1823: f_symlink(old, new)
        !          1824: 
        !          1825:        const char *old, *new;
        !          1826: 
        !          1827: {
        !          1828: 
        !          1829:        fcookie newdir;
        !          1830: 
        !          1831:        long r;
        !          1832: 
        !          1833: 
        !          1834: 
        !          1835:        TRACE("Fsymlink(%s, %s)", old, new);
        !          1836: 
        !          1837: 
        !          1838: 
        !          1839:        r = path2cookie(new, temp1, &newdir);
        !          1840: 
        !          1841:        if (r) {
        !          1842: 
        !          1843:                DEBUG("Fsymlink(%s,%s): error parsing %s", old,new,new);
        !          1844: 
        !          1845:                return r;
        !          1846: 
        !          1847:        }
        !          1848: 
        !          1849:        r = dir_access(&newdir, S_IWOTH);
        !          1850: 
        !          1851:        if (r) {
        !          1852: 
        !          1853:                DEBUG("Fsymlink(%s,%s): access to directory denied",old,new);
        !          1854: 
        !          1855:                return r;
        !          1856: 
        !          1857:        }
        !          1858: 
        !          1859:        return (*newdir.fs->symlink)(&newdir, temp1, old);
        !          1860: 
        !          1861: }
        !          1862: 
        !          1863: 
        !          1864: 
        !          1865: /*
        !          1866: 
        !          1867:  * GEMDOS extension: Freadlink(buflen, buf, linkfile):
        !          1868: 
        !          1869:  * read the contents of the symbolic link "linkfile" into the buffer
        !          1870: 
        !          1871:  * "buf", which has length "buflen".
        !          1872: 
        !          1873:  */
        !          1874: 
        !          1875: 
        !          1876: 
        !          1877: long
        !          1878: 
        !          1879: f_readlink(buflen, buf, linkfile)
        !          1880: 
        !          1881:        int buflen;
        !          1882: 
        !          1883:        char *buf;
        !          1884: 
        !          1885:        const char *linkfile;
        !          1886: 
        !          1887: {
        !          1888: 
        !          1889:        fcookie file;
        !          1890: 
        !          1891:        long r;
        !          1892: 
        !          1893:        XATTR xattr;
        !          1894: 
        !          1895: 
        !          1896: 
        !          1897:        TRACE("Freadlink(%s)", linkfile);
        !          1898: 
        !          1899: 
        !          1900: 
        !          1901:        r = path2cookie(linkfile, (char *)0, &file);
        !          1902: 
        !          1903:        if (r) {
        !          1904: 
        !          1905:                DEBUG("Freadlink: unable to find %s", linkfile);
        !          1906: 
        !          1907:                return r;
        !          1908: 
        !          1909:        }
        !          1910: 
        !          1911:        r = (*file.fs->getxattr)(&file, &xattr);
        !          1912: 
        !          1913:        if (r) {
        !          1914: 
        !          1915:                DEBUG("Freadlink: unable to get attributes for %s", linkfile);
        !          1916: 
        !          1917:                return r;
        !          1918: 
        !          1919:        }
        !          1920: 
        !          1921:        if ( (xattr.mode & S_IFMT) == S_IFLNK )
        !          1922: 
        !          1923:                return (*file.fs->readlink)(&file, buf, buflen);
        !          1924: 
        !          1925: 
        !          1926: 
        !          1927:        DEBUG("Freadlink: %s is not a link", linkfile);
        !          1928: 
        !          1929:        return EACCDN;
        !          1930: 
        !          1931: }
        !          1932: 
        !          1933: 
        !          1934: 
        !          1935: /*
        !          1936: 
        !          1937:  * GEMDOS extension: Dcntl(): do file system specific functions
        !          1938: 
        !          1939:  */
        !          1940: 
        !          1941: 
        !          1942: 
        !          1943: long
        !          1944: 
        !          1945: d_cntl(cmd, name, arg)
        !          1946: 
        !          1947:        int cmd;
        !          1948: 
        !          1949:        const char *name;
        !          1950: 
        !          1951:        long arg;
        !          1952: 
        !          1953: {
        !          1954: 
        !          1955:        fcookie dir;
        !          1956: 
        !          1957:        long r;
        !          1958: 
        !          1959: 
        !          1960: 
        !          1961:        TRACE("Dcntl(cmd=%x, file=%s, arg=%lx)", cmd, name, arg);
        !          1962: 
        !          1963: 
        !          1964: 
        !          1965:        r = path2cookie(name, temp1, &dir);
        !          1966: 
        !          1967:        if (r) {
        !          1968: 
        !          1969:                DEBUG("Dcntl: couldn't find %s", name);
        !          1970: 
        !          1971:                return r;
        !          1972: 
        !          1973:        }
        !          1974: 
        !          1975:        return (*dir.fs->fscntl)(&dir, temp1, cmd, arg);
        !          1976: 
        !          1977: }
        !          1978: 
        !          1979: 
        !          1980: 
        !          1981: /*
        !          1982: 
        !          1983:  * GEMDOS extension: Fchown(name, uid, gid) changes the user and group
        !          1984: 
        !          1985:  * ownerships of a file to "uid" and "gid" respectively.
        !          1986: 
        !          1987:  */
        !          1988: 
        !          1989: 
        !          1990: 
        !          1991: long
        !          1992: 
        !          1993: f_chown(name, uid, gid)
        !          1994: 
        !          1995:        const char *name;
        !          1996: 
        !          1997:        int uid, gid;
        !          1998: 
        !          1999: {
        !          2000: 
        !          2001:        fcookie fc;
        !          2002: 
        !          2003:        XATTR xattr;
        !          2004: 
        !          2005:        long r;
        !          2006: 
        !          2007: 
        !          2008: 
        !          2009:        TRACE("Fchown(%s, %d, %d)", name, uid, gid);
        !          2010: 
        !          2011: 
        !          2012: 
        !          2013:        r = path2cookie(name, follow_links, &fc);
        !          2014: 
        !          2015:        if (r) {
        !          2016: 
        !          2017:                DEBUG("Fchown(%s): error %ld", name, r);
        !          2018: 
        !          2019:                return r;
        !          2020: 
        !          2021:        }
        !          2022: 
        !          2023: 
        !          2024: 
        !          2025: /* MiNT acts like _POSIX_CHOWN_RESTRICTED: a non-privileged process can
        !          2026: 
        !          2027:  * only change the ownership of a file that is owned by this user, to
        !          2028: 
        !          2029:  * the effective group id of the process
        !          2030: 
        !          2031:  */
        !          2032: 
        !          2033:        if (curproc->euid) {
        !          2034: 
        !          2035:                if (curproc->egid != gid) return EACCDN;
        !          2036: 
        !          2037:                r = (*fc.fs->getxattr)(&fc, &xattr);
        !          2038: 
        !          2039:                if (r) {
        !          2040: 
        !          2041:                        DEBUG("Fchown(%s): unable to get file attributes",name);
        !          2042: 
        !          2043:                        return r;
        !          2044: 
        !          2045:                }
        !          2046: 
        !          2047:                if (xattr.uid != curproc->euid || xattr.uid != uid) {
        !          2048: 
        !          2049:                        DEBUG("Fchown(%s): not the file's owner",name);
        !          2050: 
        !          2051:                        return EACCDN;
        !          2052: 
        !          2053:                }
        !          2054: 
        !          2055:        }
        !          2056: 
        !          2057:        return (*fc.fs->chown)(&fc, uid, gid);
        !          2058: 
        !          2059: }
        !          2060: 
        !          2061: 
        !          2062: 
        !          2063: /*
        !          2064: 
        !          2065:  * GEMDOS extension: Fchmod(file, mode) changes a file's access
        !          2066: 
        !          2067:  * permissions.
        !          2068: 
        !          2069:  */
        !          2070: 
        !          2071: 
        !          2072: 
        !          2073: long
        !          2074: 
        !          2075: f_chmod(name, mode)
        !          2076: 
        !          2077:        const char *name;
        !          2078: 
        !          2079:        unsigned mode;
        !          2080: 
        !          2081: {
        !          2082: 
        !          2083:        fcookie fc;
        !          2084: 
        !          2085:        long r;
        !          2086: 
        !          2087:        XATTR xattr;
        !          2088: 
        !          2089: 
        !          2090: 
        !          2091:        TRACE("Fchmod(%s, %o)", name, mode);
        !          2092: 
        !          2093:        r = path2cookie(name, follow_links, &fc);
        !          2094: 
        !          2095:        if (r) {
        !          2096: 
        !          2097:                DEBUG("Fchmod(%s): error %ld", name, r);
        !          2098: 
        !          2099:                return r;
        !          2100: 
        !          2101:        }
        !          2102: 
        !          2103:        r = (*fc.fs->getxattr)(&fc, &xattr);
        !          2104: 
        !          2105:        if (r) {
        !          2106: 
        !          2107:                DEBUG("Fchmod(%s): couldn't get file attributes",name);
        !          2108: 
        !          2109:                return r;
        !          2110: 
        !          2111:        }
        !          2112: 
        !          2113:        if (curproc->euid && curproc->euid != xattr.uid) {
        !          2114: 
        !          2115:                DEBUG("Fchmod(%s): not the file's owner",name);
        !          2116: 
        !          2117:                return EACCDN;
        !          2118: 
        !          2119:        }
        !          2120: 
        !          2121:        r = (*fc.fs->chmode)(&fc, mode & ~S_IFMT);
        !          2122: 
        !          2123:        if (r) DEBUG("Fchmod: error %ld", r);
        !          2124: 
        !          2125:        return r;
        !          2126: 
        !          2127: }
        !          2128: 
        !          2129: 
        !          2130: 
        !          2131: /*
        !          2132: 
        !          2133:  * GEMDOS extension: Dlock(mode, dev): locks or unlocks access to
        !          2134: 
        !          2135:  * a BIOS device. "mode" is 0 for unlock, 1 for lock; "dev" is a
        !          2136: 
        !          2137:  * BIOS device (0 for A:, 1 for B:, etc.).
        !          2138: 
        !          2139:  * Returns: 0 if the operation was successful
        !          2140: 
        !          2141:  *          EACCDN if a lock attempt is made on a drive that is being
        !          2142: 
        !          2143:  *            used
        !          2144: 
        !          2145:  *         ELOCKED if the drive is locked by another process
        !          2146: 
        !          2147:  *         ENSLOCK if a program attempts to unlock a drive it
        !          2148: 
        !          2149:  *            hasn't locked.
        !          2150: 
        !          2151:  */
        !          2152: 
        !          2153: 
        !          2154: 
        !          2155: PROC *dlockproc[NUM_DRIVES];
        !          2156: 
        !          2157: 
        !          2158: 
        !          2159: long
        !          2160: 
        !          2161: d_lock(mode, dev)
        !          2162: 
        !          2163:        int mode, dev;
        !          2164: 
        !          2165: {
        !          2166: 
        !          2167:        PROC *p;
        !          2168: 
        !          2169:        FILEPTR *f;
        !          2170: 
        !          2171:        int i;
        !          2172: 
        !          2173:        DIR *dirh;
        !          2174: 
        !          2175: 
        !          2176: 
        !          2177:        TRACE("Dlock(%x,%c:)", mode, dev+'A');
        !          2178: 
        !          2179:        if (dev < 0 || dev >= NUM_DRIVES) return EDRIVE;
        !          2180: 
        !          2181: 
        !          2182: 
        !          2183:        if ( (mode&1) == 0) {   /* unlock */
        !          2184: 
        !          2185:                if (dlockproc[dev] == curproc) {
        !          2186: 
        !          2187:                        dlockproc[dev] = 0;
        !          2188: 
        !          2189:                        changedrv(dev);
        !          2190: 
        !          2191:                        return 0;
        !          2192: 
        !          2193:                }
        !          2194: 
        !          2195:                DEBUG("Dlock: no such lock");
        !          2196: 
        !          2197:                return ENSLOCK;
        !          2198: 
        !          2199:        }
        !          2200: 
        !          2201: 
        !          2202: 
        !          2203: /* code for locking */
        !          2204: 
        !          2205: /* is the drive already locked? */
        !          2206: 
        !          2207:        if (dlockproc[dev]) {
        !          2208: 
        !          2209:                DEBUG("Dlock: drive already locked");
        !          2210: 
        !          2211:                return (dlockproc[dev] == curproc) ? 0 : ELOCKED;
        !          2212: 
        !          2213:        }
        !          2214: 
        !          2215: /* see if the drive is in use */
        !          2216: 
        !          2217:        for (p = proclist; p; p = p->gl_next) {
        !          2218: 
        !          2219:                if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
        !          2220: 
        !          2221:                        continue;
        !          2222: 
        !          2223:                for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
        !          2224: 
        !          2225:                        if ( ((f = p->handle[i]) != 0) && (f->fc.dev == dev) ) {
        !          2226: 
        !          2227:                DEBUG("Dlock: process %d has an open handle on the drive", p->pid);
        !          2228: 
        !          2229:                                return EACCDN;
        !          2230: 
        !          2231:                        }
        !          2232: 
        !          2233:                }
        !          2234: 
        !          2235:                for (i = 0; i < NUM_SEARCH; i++) {
        !          2236: 
        !          2237:                        dirh = &curproc->srchdir[i];
        !          2238: 
        !          2239:                        if (dirh && dirh->fc.fs && dirh->fc.dev == dev) {
        !          2240: 
        !          2241:                DEBUG("Dlock: process %d has an open directory on the drive",p->pid);
        !          2242: 
        !          2243:                                return EACCDN;
        !          2244: 
        !          2245:                        }
        !          2246: 
        !          2247:                }
        !          2248: 
        !          2249:        }
        !          2250: 
        !          2251: 
        !          2252: 
        !          2253: /* if we reach here, the drive is not in use */
        !          2254: 
        !          2255: /* we lock it by setting dlockproc and by setting all root and current
        !          2256: 
        !          2257:  * directories referring to the device to a null file system
        !          2258: 
        !          2259:  */
        !          2260: 
        !          2261:        for (p = proclist; p; p = p->gl_next) {
        !          2262: 
        !          2263:                for (i = 0; i < NUM_DRIVES; i++) {
        !          2264: 
        !          2265:                        if (p->root[i].dev == dev)
        !          2266: 
        !          2267:                                p->root[i].fs = 0;
        !          2268: 
        !          2269:                        if (p->curdir[i].dev == dev)
        !          2270: 
        !          2271:                                p->curdir[i].fs = 0;
        !          2272: 
        !          2273:                }
        !          2274: 
        !          2275:        }
        !          2276: 
        !          2277: 
        !          2278: 
        !          2279:        dlockproc[dev] = curproc;
        !          2280: 
        !          2281:        return 0;
        !          2282: 
        !          2283: }
        !          2284: 

unix.superglobalmegacorp.com

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