Annotation of researchv10no/cmd/u9fs/u9fs.c, revision 1.1

1.1     ! root        1: #include "u.h"
        !             2: #include <sys/types.h>
        !             3: #include <sys/stat.h>
        !             4: #include "libc.h"
        !             5: #include "9p.h"
        !             6: #include "stdio.h"
        !             7: #include "setjmp.h"
        !             8: #include "pwd.h"
        !             9: #include "grp.h"
        !            10: 
        !            11: #define        DBG(f)
        !            12: 
        !            13: struct group *getgrent(void);
        !            14: struct passwd *getpwent(void);
        !            15: 
        !            16: #ifdef SYSV
        !            17: #      include <dirent.h>
        !            18: #      define  DTYPE   struct dirent
        !            19: #      define SOCKETS
        !            20: #endif
        !            21: #ifdef V10
        !            22: #      include <ndir.h>
        !            23: #      define  DTYPE   struct direct
        !            24: #endif
        !            25: #ifdef BSD
        !            26: #      include <sys/dir.h>
        !            27: #      define  DTYPE   struct direct
        !            28: #      define  SOCKETS
        !            29: #endif
        !            30: #ifdef SOCKETS
        !            31: #      define sendmsg  __sendmsg
        !            32: #      include <sys/socket.h>
        !            33: #      include <netinet/in.h>
        !            34: #      include <netdb.h>
        !            35: #      undef sendmsg
        !            36:        char    bsdhost[256];
        !            37:        void    remotehostname(void);
        !            38: #endif
        !            39: 
        !            40: typedef struct File    File;
        !            41: typedef struct Rfile   Rfile;
        !            42: typedef struct Fd      Fd;
        !            43: typedef struct Pass    Pass;
        !            44: 
        !            45: struct Fd{
        !            46:        int             ref;
        !            47:        Ulong           offset;
        !            48:        int             fd;
        !            49:        DIR             *dir;
        !            50: };
        !            51: 
        !            52: struct Rfile{
        !            53:        int             busy;
        !            54:        int             uid;
        !            55:        int             gid;
        !            56:        int             rclose;
        !            57:        File            *file;
        !            58:        Fd              *fd;
        !            59: };
        !            60: 
        !            61: struct File{
        !            62:        int             ref;
        !            63:        char            *path;
        !            64:        char            *name;
        !            65:        Qid             qid;
        !            66:        struct stat     stbuf;
        !            67: };
        !            68: 
        !            69: struct Pass{
        !            70:        int             id;
        !            71:        int             gid;
        !            72:        char            *name;
        !            73:        Pass            *next;
        !            74: };
        !            75: 
        !            76: char   data[2][MAXMSG+MAXFDATA];
        !            77: char   tdata[MAXMSG+MAXFDATA];
        !            78: char   rdata[MAXFDATA];
        !            79: Fcall  rhdr;
        !            80: Fcall  thdr;
        !            81: Rfile  *rfile;
        !            82: File   *file0;
        !            83: int    nrfilealloc;
        !            84: jmp_buf        loopjmp;
        !            85: Pass*  uid[256];
        !            86: Pass*  gid[256];
        !            87: int    devallowed;
        !            88: int    connected;
        !            89: 
        !            90: void   io(void);
        !            91: void   error(char*);
        !            92: char   *mfmt(Fcall*);
        !            93: void   sendmsg(char*);
        !            94: int    okfid(int);
        !            95: Rfile* rfilefid(void);
        !            96: File*  newfile(void);
        !            97: void*  erealloc(void*, unsigned);
        !            98: char*  estrdup(char*);
        !            99: char*  dostat(File*, char*);
        !           100: char*  bldpath(char*, char*, char*);
        !           101: Ulong  qid(struct stat*);
        !           102: Ulong  vers(struct stat*);
        !           103: void   errjmp(char*);
        !           104: int    omode(int);
        !           105: char*  id2name(Pass**, int);
        !           106: Pass*  name2pass(Pass**, char*);
        !           107: void   getpwdf(void);
        !           108: void   getgrpf(void);
        !           109: void   perm(Rfile*, int, struct stat*);
        !           110: void   parentwrperm(Rfile*);
        !           111: 
        !           112: void   rsession(void);
        !           113: void   rattach(void);
        !           114: void   rflush(void);
        !           115: void   rclone(void);
        !           116: void   rwalk(void);
        !           117: void   ropen(void);
        !           118: void   rcreate(void);
        !           119: void   rread(void);
        !           120: void   rwrite(void);
        !           121: void   rclunk(int);
        !           122: void   rstat(void);
        !           123: void   rwstat(void);
        !           124: void   rclwalk(void);
        !           125: 
        !           126: char   Eauth[] =       "authentication failed";
        !           127: char   Eperm[] =       "permission denied";
        !           128: char   Ebadfid[] =     "fid unknown or out of range";
        !           129: char   Efidactive[] =  "fid already in use";
        !           130: char   Eopen[] =       "file is open";
        !           131: char   Emode[] =       "invalid open mode";
        !           132: char   Especial[] =    "no access to special file";
        !           133: char   Especial0[] =   "already attached without access to special files";
        !           134: char   Especial1[] =   "already attached with access to special files";
        !           135: char   Enotopen[] =    "file is not open";
        !           136: char   Etoolarge[] =   "i/o count too large";
        !           137: char   Ebaddir[] =     "i/o error on directory";
        !           138: char   Eunknown[] =    "unknown user or group";
        !           139: char   Euid[] =        "can't set uid";
        !           140: char   Egid[] =        "can't set gid";
        !           141: char   Eowner[] =      "not owner";
        !           142: 
        !           143: int
        !           144: main(int argc, char *argv[])
        !           145: {
        !           146:        freopen(LOG, "a", stderr);
        !           147:        setbuf(stderr, (void*)0);
        !           148:        DBG(fprintf(stderr, "u9fs\nkill %d\n", getpid()));
        !           149:        if(argc > 1)
        !           150:                if(chroot(argv[1]) == -1)
        !           151:                        error("chroot failed");
        !           152: 
        !           153: #      ifdef SOCKETS
        !           154:        remotehostname();
        !           155: #      endif
        !           156: 
        !           157:        io();
        !           158:        return 0;
        !           159: }
        !           160: 
        !           161: void
        !           162: io(void)
        !           163: {
        !           164:        int m;
        !           165:        static int toggle, ndata;
        !           166:        char *datap;
        !           167: 
        !           168:        /*
        !           169:         * TCP does not preserve record boundaries; this dance works around
        !           170:         * the problem.
        !           171:         */
        !           172:        setjmp(loopjmp);
        !           173: 
        !           174:        /*
        !           175:         * Invariant: data[toggle] has ndata bytes already
        !           176:         */
        !           177:     loop:
        !           178:        datap = data[toggle];
        !           179:        toggle ^= 1;
        !           180:        for(;;){
        !           181:                if(ndata){
        !           182:                        m = convM2S(datap, &rhdr, ndata);
        !           183:                        /* m is number of bytes more than a full message */
        !           184:                        if(m >= 0){
        !           185:                                memmove(data[toggle], datap+(ndata-m), m);
        !           186:                                ndata = m;
        !           187:                                break;
        !           188:                        }
        !           189:                }
        !           190:                m = read(0, datap+ndata, (MAXMSG+MAXFDATA)-ndata);
        !           191:                if(m <= 0)
        !           192:                        error("read");
        !           193:                ndata += m;
        !           194:        }
        !           195: 
        !           196:        thdr.type = rhdr.type+1;
        !           197:        thdr.tag = rhdr.tag;
        !           198:        thdr.fid = rhdr.fid;
        !           199:        DBG(fprintf(stderr, ">> %s\n", mfmt(&rhdr)));
        !           200:        switch(rhdr.type){
        !           201:        case Tnop:
        !           202:        case Tflush:    /* this is a synchronous fs; easy */
        !           203:                break;
        !           204:        case Tsession:
        !           205:                rsession();
        !           206:                break;
        !           207:        case Tattach:
        !           208:                rattach();
        !           209:                break;
        !           210:        case Tclone:
        !           211:                rclone();
        !           212:                break;
        !           213:        case Twalk:
        !           214:                rwalk();
        !           215:                break;
        !           216:        case Tstat:
        !           217:                rstat();
        !           218:                break;
        !           219:        case Twstat:
        !           220:                rwstat();
        !           221:                break;
        !           222:        case Topen:
        !           223:                ropen();
        !           224:                break;
        !           225:        case Tcreate:
        !           226:                rcreate();
        !           227:                break;
        !           228:        case Tread:
        !           229:                rread();
        !           230:                break;
        !           231:        case Twrite:
        !           232:                rwrite();
        !           233:                break;
        !           234:        case Tclunk:
        !           235:                rclunk(0);
        !           236:                break;
        !           237:        case Tremove:
        !           238:                rclunk(1);
        !           239:                break;
        !           240:        default:
        !           241:                fprintf(stderr, "unknown message %s\n", mfmt(&rhdr));
        !           242:                error("bad message");
        !           243:        }
        !           244:        sendmsg(0);
        !           245:        goto loop;
        !           246: }
        !           247: 
        !           248: void
        !           249: rsession(void)
        !           250: {
        !           251:        memset(thdr.authid, 0, sizeof(thdr.authid));
        !           252:        memset(thdr.authdom, 0, sizeof(thdr.authdom));
        !           253:        memset(thdr.chal, 0, sizeof(thdr.chal));
        !           254: }
        !           255: 
        !           256: void
        !           257: rattach(void)
        !           258: {
        !           259:        Rfile *rf;
        !           260:        char *err;
        !           261:        Pass *p;
        !           262: 
        !           263:        err = 0;
        !           264:        if(file0 == 0){
        !           265:                file0 = newfile();
        !           266:                file0->ref++;           /* one extra to hold it up */   
        !           267:                file0->path = estrdup("/");
        !           268:                file0->name = estrdup("/");
        !           269:                errjmp(dostat(file0, 0));
        !           270:        }
        !           271:        if(!okfid(rhdr.fid))
        !           272:                errjmp(Ebadfid);
        !           273:        if(strncmp(rhdr.aname, "device", 6) == 0){
        !           274:                if(connected && !devallowed)
        !           275:                        errjmp(Especial0);
        !           276:                devallowed = 1;
        !           277:        }else{
        !           278:                if(connected && devallowed)
        !           279:                        errjmp(Especial1);
        !           280:        }
        !           281:        getpwdf();
        !           282:        getgrpf();
        !           283:        rf = &rfile[rhdr.fid];
        !           284:        if(rf->busy)
        !           285:                errjmp(Efidactive);
        !           286:        rf->busy = 1;
        !           287:        rf->rclose = 0;
        !           288:        rf->file = file0;
        !           289:        file0->ref++;
        !           290:        p = name2pass(uid, rhdr.uname);
        !           291:        if(p == 0)
        !           292:                errjmp(Eunknown);
        !           293:        if(p->id == 0)
        !           294:                errjmp(Eperm);
        !           295: #      ifdef SOCKETS
        !           296:        if(ruserok(bsdhost, 0, rhdr.uname, rhdr.uname) < 0)
        !           297:                errjmp(Eperm);
        !           298: #      endif
        !           299:        rf->uid = p->id;
        !           300:        rf->gid = p->gid;
        !           301:        thdr.qid = file0->qid;
        !           302:        connected = 1;
        !           303: }
        !           304: 
        !           305: void
        !           306: rclone(void)
        !           307: {
        !           308:        Rfile *rf, *nrf;
        !           309:        File *f;
        !           310: 
        !           311:        rfilefid();
        !           312:        if(!okfid(rhdr.newfid))
        !           313:                errjmp(Ebadfid);
        !           314:        rf = &rfile[rhdr.fid];
        !           315:        nrf = &rfile[rhdr.newfid];
        !           316:        f = rf->file;
        !           317:        if(nrf->busy)
        !           318:                errjmp(Efidactive);
        !           319:        nrf->busy = 1;
        !           320:        nrf->file = f;
        !           321:        f->ref++;
        !           322:        nrf->fd = rf->fd;
        !           323:        nrf->uid = rf->uid;
        !           324:        nrf->gid = rf->gid;
        !           325:        nrf->rclose = rf->rclose;
        !           326:        if(nrf->fd){
        !           327:                if(nrf->fd->ref == 0)
        !           328:                        error("clone fd count");
        !           329:                nrf->fd->ref++;
        !           330:        }
        !           331: }
        !           332: 
        !           333: void
        !           334: rwalk(void)
        !           335: {
        !           336:        char *err;
        !           337:        Rfile *rf;
        !           338:        File *of, *f;
        !           339: 
        !           340:        rf = rfilefid();
        !           341:        if(rf->fd)
        !           342:                errjmp(Eopen);
        !           343:        of = rf->file;
        !           344:        perm(rf, 1, 0);
        !           345:        f = newfile();
        !           346:        f->path = estrdup(of->path);
        !           347:        err = dostat(f, rhdr.name);
        !           348:        if(err){
        !           349:                f->ref = 0;
        !           350:                free(f->path);
        !           351:                errjmp(err);
        !           352:        }
        !           353:        if(of->ref <= 0)
        !           354:                error("walk ref count");
        !           355:        if(--of->ref == 0){
        !           356:                free(of->path);
        !           357:                free(of->name);
        !           358:                free(of);
        !           359:        }
        !           360:        rf->file = f;
        !           361:        thdr.qid = f->qid;
        !           362: }
        !           363: 
        !           364: void
        !           365: ropen(void)
        !           366: {
        !           367:        Rfile *rf;
        !           368:        File *f;
        !           369:        int fd;
        !           370:        DIR *dir;
        !           371:        int m, trunc;
        !           372: 
        !           373:        rf = rfilefid();
        !           374:        f = rf->file;
        !           375:        if(rf->fd)
        !           376:                error("open already open");
        !           377:        if(!devallowed && (f->stbuf.st_mode & S_IFCHR))
        !           378:                errjmp(Especial);
        !           379:        m = rhdr.mode & (16|3);
        !           380:        trunc = m & 16; /* OTRUNC */
        !           381:        switch(m){
        !           382:        case 0:
        !           383:                perm(rf, 4, 0);
        !           384:                break;
        !           385:        case 1:
        !           386:        case 1|16:
        !           387:                perm(rf, 2, 0);
        !           388:                break;
        !           389:        case 2: 
        !           390:        case 0|16:
        !           391:        case 2|16:
        !           392:                perm(rf, 4, 0);
        !           393:                perm(rf, 2, 0);
        !           394:                break;
        !           395:        case 3:
        !           396:                perm(rf, 1, 0);
        !           397:                break;
        !           398:        default:
        !           399:                errjmp(Emode);
        !           400:        }
        !           401:        
        !           402:        m = omode(m & 3);
        !           403:        errno = 0;
        !           404:        if(f->qid.path & CHDIR){
        !           405:                if(rhdr.mode != 0)              /* OREAD */
        !           406:                        errjmp(Eperm);
        !           407:                dir = opendir(f->path);
        !           408:                if(dir == 0)
        !           409:                        errjmp(sys_errlist[errno]);
        !           410:                fd = 0;
        !           411:        }else{
        !           412:                if(trunc){
        !           413:                        fd = creat(f->path, 0666);
        !           414:                        if(fd >= 0)
        !           415:                                if(m != 1){
        !           416:                                        close(fd);
        !           417:                                        fd = open(f->path, m);
        !           418:                                }
        !           419:                }else
        !           420:                        fd = open(f->path, m);
        !           421:                if(fd < 0)
        !           422:                        errjmp(sys_errlist[errno]);
        !           423:                dir = 0;
        !           424:        }
        !           425:        rf->rclose = rhdr.mode & 64;    /* ORCLOSE */
        !           426:        rf->fd = erealloc(0, sizeof(Fd));
        !           427:        rf->fd->ref = 1;
        !           428:        rf->fd->fd = fd;
        !           429:        rf->fd->dir = dir;
        !           430:        rf->fd->offset = 0;
        !           431:        thdr.qid = f->qid;
        !           432: }
        !           433: 
        !           434: void
        !           435: rcreate(void)
        !           436: {
        !           437:        Rfile *rf;
        !           438:        File *f, *of;
        !           439:        char *path, *err;
        !           440:        int fd;
        !           441:        int m;
        !           442:        char name[NAMELEN];
        !           443: 
        !           444:        rf = rfilefid();
        !           445:        if(rf->fd)
        !           446:                errjmp(Eopen);
        !           447:        perm(rf, 2, 0);
        !           448:        path = bldpath(rf->file->path, rhdr.name, name);
        !           449:        m = omode(rhdr.mode&3);
        !           450:        errno = 0;
        !           451:        if(rhdr.perm & CHDIR){
        !           452:                if(m){
        !           453:                        free(path);
        !           454:                        errjmp(Eperm);
        !           455:                }
        !           456:                fd = mkdir(path, 0777);
        !           457:                if(fd < 0){
        !           458:                        free(path);
        !           459:                        errjmp(sys_errlist[errno]);
        !           460:                }
        !           461:                fd = open(path, 0);
        !           462:                free(path);
        !           463:                if(fd >= 0){
        !           464:                        fchmod(fd, rhdr.perm&0777);
        !           465:                        fchown(fd, rf->uid, rf->gid);
        !           466:                }
        !           467:        }else{
        !           468:                fd = creat(path, 0666);
        !           469:                if(fd >= 0){
        !           470:                        if(m != 1){
        !           471:                                close(fd);
        !           472:                                fd = open(path, m);
        !           473:                        }
        !           474:                        fchmod(fd, rhdr.perm&0777);
        !           475:                        fchown(fd, rf->uid, rf->gid);
        !           476:                }
        !           477:                free(path);
        !           478:                if(fd < 0)
        !           479:                        errjmp(sys_errlist[errno]);
        !           480:        }
        !           481:        f = newfile();
        !           482:        of = rf->file;  
        !           483:        f->path = estrdup(of->path);
        !           484:        err = dostat(f, rhdr.name);
        !           485:        if(err){
        !           486:                free(f->path);
        !           487:                free(f->name);
        !           488:                free(f);
        !           489:                errjmp(err);
        !           490:        }
        !           491:        if(!devallowed && (f->stbuf.st_mode & S_IFCHR)){
        !           492:                free(f->path);
        !           493:                free(f->name);
        !           494:                free(f);
        !           495:                errjmp(Especial);
        !           496:        }
        !           497:        if(--of->ref == 0){
        !           498:                free(of->path);
        !           499:                free(of->name);
        !           500:                free(of);
        !           501:        }
        !           502:        rf->file = f;
        !           503:        rf->rclose = rhdr.mode & 64;    /* ORCLOSE */
        !           504:        rf->fd = erealloc(0, sizeof(Fd));
        !           505:        rf->fd->ref = 1;
        !           506:        rf->fd->fd = fd;
        !           507:        rf->fd->dir = 0;
        !           508:        rf->fd->offset = 0;
        !           509:        thdr.qid = f->qid;
        !           510: }
        !           511: 
        !           512: void
        !           513: rread(void)
        !           514: {
        !           515:        Rfile *rf;
        !           516:        File *f;
        !           517:        long n;
        !           518:        DTYPE *de;
        !           519:        Dir d;
        !           520:        struct stat stbuf;
        !           521:        char *path;
        !           522: 
        !           523:        rf = rfilefid();
        !           524:        if(rf->fd == 0)
        !           525:                errjmp(Enotopen);
        !           526:        if(rhdr.count > sizeof rdata)
        !           527:                errjmp(Etoolarge);
        !           528:        f = rf->file;
        !           529:        if(rf->fd->dir){
        !           530:                errno = 0;
        !           531:                rhdr.count = (rhdr.count/DIRLEN)*DIRLEN;
        !           532:                if(rf->fd->offset != rhdr.offset){
        !           533:                        seekdir(rf->fd->dir, 0);
        !           534:                        for(n=0; n<rhdr.offset; ){
        !           535:                                de = readdir(rf->fd->dir);
        !           536:                                if(de == 0)
        !           537:                                        break;
        !           538:                                if(de->d_ino==0 || de->d_name[0]==0)
        !           539:                                        continue;
        !           540:                                if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
        !           541:                                        continue;
        !           542:                                n += DIRLEN;
        !           543:                        }
        !           544:                }
        !           545:                for(n=0; n<rhdr.count; ){
        !           546:                        de = readdir(rf->fd->dir);
        !           547:                        if(de == 0)
        !           548:                                break;
        !           549:                        if(de->d_ino==0 || de->d_name[0]==0)
        !           550:                                continue;
        !           551:                        if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
        !           552:                                continue;
        !           553:                        strncpy(d.name, de->d_name, NAMELEN-1);
        !           554:                        d.name[NAMELEN-1] = 0;
        !           555:                        path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1);
        !           556:                        sprintf(path, "%s/%s", f->path, de->d_name);
        !           557:                        memset(&stbuf, 0, sizeof stbuf);
        !           558:                        if(stat(path, &stbuf) < 0){
        !           559:                                fprintf(stderr, "dir: bad path %s\n", path);
        !           560:                                /* but continue... probably a bad symlink */
        !           561:                        }
        !           562:                        free(path);
        !           563:                        strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN);
        !           564:                        strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN);
        !           565:                        d.qid.path = qid(&stbuf);
        !           566:                        d.qid.vers = vers(&stbuf);
        !           567:                        d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777);
        !           568:                        d.atime = stbuf.st_atime;
        !           569:                        d.mtime = stbuf.st_mtime;
        !           570:                        d.len.l.hlength = 0;
        !           571:                        d.len.l.length = stbuf.st_size;
        !           572:                        convD2M(&d, rdata+n);
        !           573:                        n += DIRLEN;
        !           574:                }
        !           575:        }else{
        !           576:                errno = 0;
        !           577:                if(rf->fd->offset != rhdr.offset){
        !           578:                        rf->fd->offset = rhdr.offset;
        !           579:                        if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
        !           580:                                errjmp(sys_errlist[errno]);
        !           581:                }
        !           582:                n = read(rf->fd->fd, rdata, rhdr.count);
        !           583:                if(n < 0)
        !           584:                        errjmp(sys_errlist[errno]);
        !           585:        }
        !           586:        rf->fd->offset += n;
        !           587:        thdr.count = n;
        !           588:        thdr.data = rdata;
        !           589: }
        !           590: 
        !           591: void
        !           592: rwrite(void)
        !           593: {
        !           594:        Rfile *rf;
        !           595:        int n;
        !           596: 
        !           597:        rf = rfilefid();
        !           598:        if(rf->fd == 0)
        !           599:                errjmp(Enotopen);
        !           600:        if(rhdr.count > sizeof rdata)
        !           601:                errjmp(Etoolarge);
        !           602:        errno = 0;
        !           603:        if(rf->fd->offset != rhdr.offset){
        !           604:                rf->fd->offset = rhdr.offset;
        !           605:                if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
        !           606:                        errjmp(sys_errlist[errno]);
        !           607:        }
        !           608:        n = write(rf->fd->fd, rhdr.data, rhdr.count);
        !           609:        if(n < 0)
        !           610:                errjmp(sys_errlist[errno]);
        !           611:        rf->fd->offset += n;
        !           612:        thdr.count = n;
        !           613: }
        !           614: 
        !           615: void
        !           616: rstat(void)
        !           617: {
        !           618:        Rfile *rf;
        !           619:        File *f;
        !           620:        Dir d;
        !           621: 
        !           622:        rf = rfilefid();
        !           623:        f = rf->file;
        !           624:        errjmp(dostat(f, 0));
        !           625:        strncpy(d.name, f->name, NAMELEN);
        !           626:        strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN);
        !           627:        strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN);
        !           628:        d.qid = f->qid;
        !           629:        d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777);
        !           630:        d.atime = f->stbuf.st_atime;
        !           631:        d.mtime = f->stbuf.st_mtime;
        !           632:        d.len.l.hlength = 0;
        !           633:        d.len.l.length = f->stbuf.st_size;
        !           634:        convD2M(&d, thdr.stat);
        !           635: }
        !           636: 
        !           637: void
        !           638: rwstat(void)
        !           639: {
        !           640:        Rfile *rf;
        !           641:        File *f;
        !           642:        Dir d;
        !           643:        Pass *p;
        !           644:        char *path, *dir, name[NAMELEN];
        !           645: 
        !           646:        rf = rfilefid();
        !           647:        f = rf->file;
        !           648:        errjmp(dostat(f, 0));
        !           649:        convM2D(rhdr.stat, &d);
        !           650:        errno = 0;
        !           651:        if(rf->uid != f->stbuf.st_uid)
        !           652:                errjmp(Eowner);
        !           653:        if(strcmp(d.name, f->name) != 0){
        !           654:                parentwrperm(rf);
        !           655:                dir = bldpath(f->path, "..", name);
        !           656:                path = erealloc(0, strlen(dir)+1+strlen(d.name)+1);
        !           657:                sprintf(path, "%s/%s", dir, d.name);
        !           658:                if(link(f->path, path) < 0){
        !           659:                        free(path);
        !           660:                        errjmp(sys_errlist[errno]);
        !           661:                }
        !           662:                if(unlink(f->path) < 0){
        !           663:                        free(path);
        !           664:                        errjmp(sys_errlist[errno]);
        !           665:                }
        !           666:                free(f->path);
        !           667:                free(f->name);
        !           668:                f->path = path;
        !           669:                f->name = estrdup(d.name);
        !           670:        }
        !           671:        if((d.mode&0777) != (f->stbuf.st_mode&0777)){
        !           672:                if(chmod(f->path, d.mode&0777) < 0)
        !           673:                        errjmp(sys_errlist[errno]);
        !           674:                f->stbuf.st_mode &= ~0777;
        !           675:                f->stbuf.st_mode |= d.mode&0777;
        !           676:        }
        !           677:        p = name2pass(gid, d.gid);
        !           678:        if(p == 0)
        !           679:                errjmp(Eunknown);
        !           680:        if(p->id != f->stbuf.st_gid){
        !           681:                if(chown(f->path, f->stbuf.st_uid, p->id) < 0)
        !           682:                        errjmp(sys_errlist[errno]);
        !           683:                f->stbuf.st_gid = p->id;
        !           684:        }
        !           685: }
        !           686: 
        !           687: void
        !           688: rclunk(int rm)
        !           689: {
        !           690:        int ret;
        !           691:        char *err;
        !           692:        Rfile *rf;
        !           693:        File *f;
        !           694:        Fd *fd;
        !           695: 
        !           696:        err = 0;
        !           697:        rf = rfilefid();
        !           698:        f = rf->file;
        !           699:        if(rm){
        !           700:                parentwrperm(rf);
        !           701:                if(f->qid.path & CHDIR)
        !           702:                        ret = rmdir(f->path);
        !           703:                else
        !           704:                        ret = unlink(f->path);
        !           705:                if(ret)
        !           706:                        err = sys_errlist[errno];
        !           707:        }else if(rf->rclose){   /* ignore errors */
        !           708:                if(f->qid.path & CHDIR)
        !           709:                        rmdir(f->path);
        !           710:                else
        !           711:                        unlink(f->path);
        !           712:        }
        !           713:                
        !           714:        rf->busy = 0;
        !           715:        if(--f->ref == 0){
        !           716:                free(f->path);
        !           717:                free(f->name);
        !           718:                free(f);
        !           719:        }
        !           720:        fd = rf->fd;
        !           721:        if(fd){
        !           722:                if(fd->ref <= 0)
        !           723:                        error("clunk fd count");
        !           724:                if(--fd->ref == 0){
        !           725:                        if(fd->fd)
        !           726:                                close(fd->fd);
        !           727:                        if(fd->dir)
        !           728:                                closedir(fd->dir);
        !           729:                        free(fd);
        !           730:                }
        !           731:                rf->fd = 0;
        !           732:        }
        !           733:        if(err)
        !           734:                errjmp(err);
        !           735: }
        !           736: 
        !           737: char*
        !           738: bldpath(char *a, char *elem, char *name)
        !           739: {
        !           740:        char *path, *p;
        !           741: 
        !           742:        if(strcmp(elem, "..") == 0){
        !           743:                if(strcmp(a, "/") == 0){
        !           744:                        path = estrdup(a);
        !           745:                        strcpy(name, a);
        !           746:                }else{
        !           747:                        p = strrchr(a, '/');
        !           748:                        if(p == 0){
        !           749:                                fprintf(stderr, "path: '%s'\n", path);
        !           750:                                error("malformed path 1");
        !           751:                        }
        !           752:                        if(p == a)      /* reduced to "/" */
        !           753:                                p++;
        !           754:                        path = erealloc(0, (p-a)+1);
        !           755:                        memmove(path, a, (p-a));
        !           756:                        path[(p-a)] = 0;
        !           757:                        if(strcmp(path, "/") == 0)
        !           758:                                p = path;
        !           759:                        else{
        !           760:                                p = strrchr(path, '/');
        !           761:                                if(p == 0){
        !           762:                                        fprintf(stderr, "path: '%s'\n", path);
        !           763:                                        error("malformed path 2");
        !           764:                                }
        !           765:                                p++;
        !           766:                        }
        !           767:                        strcpy(name, p);
        !           768:                }
        !           769:        }else{
        !           770:                if(strcmp(a, "/") == 0)
        !           771:                        a = "";
        !           772:                path = erealloc(0, strlen(a)+1+strlen(elem)+1);
        !           773:                sprintf(path, "%s/%s", a, elem);
        !           774:                strcpy(name, elem);
        !           775:        }
        !           776:        if(strlen(name) >= NAMELEN)
        !           777:                error("bldpath: name too long");
        !           778:        return path;
        !           779: }
        !           780: 
        !           781: char*
        !           782: dostat(File *f, char *elem)
        !           783: {
        !           784:        char *path;
        !           785:        struct stat stbuf;
        !           786:        char name[NAMELEN];
        !           787: 
        !           788:        if(elem)
        !           789:                path = bldpath(f->path, elem, name);
        !           790:        else
        !           791:                path = f->path;
        !           792:        errno = 0;
        !           793:        if(stat(path, &stbuf) < 0)
        !           794:                return sys_errlist[errno];
        !           795:        if(elem){
        !           796:                free(f->path);
        !           797:                f->path = path;
        !           798:                f->name = estrdup(name);
        !           799:        }
        !           800:        f->qid.path = qid(&stbuf);
        !           801:        f->qid.vers = vers(&stbuf);
        !           802:        f->stbuf = stbuf;
        !           803:        return 0;
        !           804: }
        !           805: 
        !           806: int
        !           807: omode(int m)
        !           808: {
        !           809:        switch(m){
        !           810:        case 0:         /* OREAD */
        !           811:        case 3:         /* OEXEC */
        !           812:                return 0;
        !           813:        case 1:         /* OWRITE */
        !           814:                return 1;
        !           815:        case 2:         /* ORDWR */
        !           816:                return 2;
        !           817:        }
        !           818:        errjmp(Emode);
        !           819:        return 0;
        !           820: }
        !           821: 
        !           822: void
        !           823: sendmsg(char *err)
        !           824: {
        !           825:        int n;
        !           826: 
        !           827:        if(err){
        !           828:                thdr.type = Rerror;
        !           829:                strncpy(thdr.ename, err, ERRLEN);
        !           830:        }
        !           831:        DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr)));
        !           832:        n = convS2M(&thdr, tdata);
        !           833:        if(n == 0)
        !           834:                error("bad sendmsg format");
        !           835:        if(write(1, tdata, n) != n)
        !           836:                error("write error");
        !           837: }
        !           838: 
        !           839: 
        !           840: int
        !           841: okfid(int fid)
        !           842: {
        !           843:        enum{ Delta=10 };
        !           844: 
        !           845:        if(fid < 0){
        !           846:                fprintf(stderr, "u9fs: negative fid %d\n", fid);
        !           847:                return 0;
        !           848:        }
        !           849:        if(fid >= nrfilealloc){
        !           850:                fid += Delta;
        !           851:                rfile = erealloc(rfile, fid*sizeof(Rfile));
        !           852:                memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile));
        !           853:                nrfilealloc = fid;
        !           854:        }
        !           855:        return 1;
        !           856: }
        !           857: 
        !           858: Rfile*
        !           859: rfilefid(void)
        !           860: {
        !           861:        Rfile *rf;
        !           862: 
        !           863:        if(!okfid(rhdr.fid))
        !           864:                errjmp(Ebadfid);
        !           865:        rf = &rfile[rhdr.fid];
        !           866:        if(rf->busy == 0)
        !           867:                errjmp(Ebadfid);
        !           868:        if(rf->file->ref <= 0)
        !           869:                error("ref count");
        !           870:        return rf;
        !           871: }
        !           872: 
        !           873: void
        !           874: perm(Rfile *rf, int mask, struct stat *st)
        !           875: {
        !           876:        if(st == 0)
        !           877:                st = &rf->file->stbuf;
        !           878:        /* plan 9 access semantics; simpler and more sensible */
        !           879:        if(rf->uid == st->st_uid)
        !           880:                if((st->st_mode>>6) & mask)
        !           881:                        return;
        !           882:        if(rf->gid == st->st_gid)
        !           883:                if((st->st_mode>>3) & mask)
        !           884:                        return;
        !           885:        if((st->st_mode>>0) & mask)
        !           886:                return;
        !           887:        errjmp(Eperm);
        !           888: }
        !           889: 
        !           890: void
        !           891: parentwrperm(Rfile *rf)
        !           892: {
        !           893:        Rfile trf;
        !           894:        struct stat st;
        !           895:        char *dirp, dir[512];
        !           896: 
        !           897:        dirp = bldpath(rf->file->path, "..", dir);
        !           898:        if(strlen(dirp) < sizeof dir){  /* ugly: avoid leaving dirp allocated */
        !           899:                strcpy(dir, dirp);
        !           900:                free(dirp);
        !           901:                dirp = dir;
        !           902:        }
        !           903:        if(stat(dirp, &st) < 0)
        !           904:                errjmp(Eperm);
        !           905:        trf.uid = rf->uid;
        !           906:        trf.gid = rf->gid;
        !           907:        perm(&trf, 2, &st);
        !           908: }
        !           909: 
        !           910: File*
        !           911: newfile(void)
        !           912: {
        !           913:        File *f;
        !           914: 
        !           915:        f = erealloc(0, sizeof(File));
        !           916:        memset(f, 0, sizeof(File));
        !           917:        f->ref = 1;
        !           918:        return f;
        !           919: }
        !           920: 
        !           921: /*
        !           922:  * qids: directory bit, seven bits of device, 24 bits of inode
        !           923:  */
        !           924: Ulong
        !           925: vers(struct stat *st)
        !           926: {
        !           927:        return st->st_mtime;
        !           928: }
        !           929: 
        !           930: Ulong
        !           931: qid(struct stat *st)
        !           932: {
        !           933:        static int nqdev;
        !           934:        static Uchar *qdev;
        !           935:        Ulong q;
        !           936:        int dev;
        !           937: 
        !           938:        if(qdev == 0){
        !           939:                qdev = erealloc(0, 65536U);
        !           940:                memset(qdev, 0, 65536U);
        !           941:        }
        !           942:        q = 0;
        !           943:        if((st->st_mode&S_IFMT) ==  S_IFDIR)
        !           944:                q = CHDIR;
        !           945:        dev = st->st_dev & 0xFFFFUL;
        !           946:        if(qdev[dev] == 0){
        !           947:                if(++nqdev >= 128)
        !           948:                        error("too many devices");
        !           949:                qdev[dev] = nqdev;
        !           950:        }
        !           951:        q |= qdev[dev]<<24;
        !           952:        q |= st->st_ino & 0x00FFFFFFUL;
        !           953:        return q;
        !           954: }
        !           955: 
        !           956: Pass*
        !           957: name2pass(Pass **pw, char *name)
        !           958: {
        !           959:        int i;
        !           960:        Pass *p;
        !           961: 
        !           962:        for(i=0; i<256; i++)
        !           963:                for(p = pw[i]; p; p = p->next)
        !           964:                        if(strcmp(name, p->name) == 0)
        !           965:                                return p;
        !           966:        return 0;
        !           967: }
        !           968: 
        !           969: char*
        !           970: id2name(Pass **pw, int id)
        !           971: {
        !           972:        int i;
        !           973:        Pass *p;
        !           974:        char *s;
        !           975:        static char buf[8];
        !           976: 
        !           977:        s = 0;
        !           978:        /* use last on list == first in file */
        !           979:        i = (id&0xFF) ^ ((id>>8)&0xFF);
        !           980:        for(p = pw[i]; p; p = p->next)
        !           981:                if(p->id == id)
        !           982:                        s = p->name;
        !           983:        if(s)
        !           984:                return s;
        !           985:        sprintf(buf, "%d", id);
        !           986:        return buf;
        !           987: }
        !           988: 
        !           989: void
        !           990: freepass(Pass **pass)
        !           991: {
        !           992:        int i;
        !           993:        Pass *p, *np;
        !           994: 
        !           995:        for(i=0; i<256; i++){
        !           996:                for(p = pass[i]; p; p = np){
        !           997:                        np = p->next;
        !           998:                        free(p);
        !           999:                }
        !          1000:                pass[i] = 0; 
        !          1001:        }
        !          1002: }
        !          1003: 
        !          1004: void
        !          1005: getpwdf(void)
        !          1006: {
        !          1007:        static mtime;
        !          1008:        struct stat stbuf;
        !          1009:        struct passwd *pw;
        !          1010:        int i;
        !          1011:        Pass *p;
        !          1012: 
        !          1013:        if(stat("/etc/passwd", &stbuf) < 0)
        !          1014:                error("can't read /etc/passwd");
        !          1015:        if(stbuf.st_mtime <= mtime)
        !          1016:                return;
        !          1017:        freepass(uid);
        !          1018:        while(pw = getpwent()){
        !          1019:                i = pw->pw_uid;
        !          1020:                i = (i&0xFF) ^ ((i>>8)&0xFF);
        !          1021:                p = erealloc(0, sizeof(Pass));
        !          1022:                p->next = uid[i];
        !          1023:                uid[i] = p;
        !          1024:                p->id = pw->pw_uid;
        !          1025:                p->gid = pw->pw_gid;
        !          1026:                p->name = estrdup(pw->pw_name);
        !          1027:        }
        !          1028:        setpwent();
        !          1029:        endpwent();
        !          1030: }
        !          1031: 
        !          1032: void
        !          1033: getgrpf(void)
        !          1034: {
        !          1035:        static mtime;
        !          1036:        struct stat stbuf;
        !          1037:        struct group *pw;
        !          1038:        int i;
        !          1039:        Pass *p;
        !          1040: 
        !          1041:        if(stat("/etc/group", &stbuf) < 0)
        !          1042:                error("can't read /etc/group");
        !          1043:        if(stbuf.st_mtime <= mtime)
        !          1044:                return;
        !          1045:        freepass(gid);
        !          1046:        while(pw = getgrent()){
        !          1047:                i = pw->gr_gid;
        !          1048:                i = (i&0xFF) ^ ((i>>8)&0xFF);
        !          1049:                p = erealloc(0, sizeof(Pass));
        !          1050:                p->next = gid[i];
        !          1051:                gid[i] = p;
        !          1052:                p->id = pw->gr_gid;
        !          1053:                p->gid = 0;
        !          1054:                p->name = estrdup(pw->gr_name);
        !          1055:        }
        !          1056:        setgrent();
        !          1057:        endgrent();
        !          1058: }
        !          1059: 
        !          1060: void
        !          1061: error(char *s)
        !          1062: {
        !          1063:        fprintf(stderr, "u9fs: %s\n", s);
        !          1064:        perror("unix error");
        !          1065:        exit(1);
        !          1066: }
        !          1067: 
        !          1068: void
        !          1069: errjmp(char *s)
        !          1070: {
        !          1071:        if(s == 0)
        !          1072:                return;
        !          1073:        sendmsg(s);
        !          1074:        longjmp(loopjmp, 1);
        !          1075: }
        !          1076: 
        !          1077: void*
        !          1078: erealloc(void *p, unsigned n)
        !          1079: {
        !          1080:        if(p == 0)
        !          1081:                p = malloc(n);
        !          1082:        else
        !          1083:                p = realloc(p, n);
        !          1084:        if(p == 0)
        !          1085:                error("realloc fail");
        !          1086:        return p;
        !          1087: }
        !          1088: 
        !          1089: char*
        !          1090: estrdup(char *p)
        !          1091: {
        !          1092:        p = strdup(p);
        !          1093:        if(p == 0)
        !          1094:                error("strdup fail");
        !          1095:        return p;
        !          1096: }
        !          1097: 
        !          1098: #ifdef SOCKETS
        !          1099: void
        !          1100: remotehostname(void)
        !          1101: {
        !          1102:        struct sockaddr_in sock;
        !          1103:        struct hostent *hp;
        !          1104:        int len;
        !          1105:        int on = 1;
        !          1106: 
        !          1107:        len = sizeof sock;
        !          1108:        if(getpeername(0, &sock, &len) < 0)
        !          1109:                error("getpeername");
        !          1110:        hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr),
        !          1111:                sock.sin_family);
        !          1112:        if(hp == 0)
        !          1113:                error("gethostbyaddr");
        !          1114:        strcpy(bsdhost, hp->h_name);
        !          1115:        fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid());
        !          1116: 
        !          1117:        setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
        !          1118: }
        !          1119: #endif

unix.superglobalmegacorp.com

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