Annotation of researchv10no/cmd/u9fs/u9fs.cold, revision 1.1.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:                if(rf->fd->offset != rhdr.offset){
                    532:                        seekdir(rf->fd->dir, 0);
                    533:                        for(n=0; n<rhdr.offset; ){
                    534:                                de = readdir(rf->fd->dir);
                    535:                                if(de == 0)
                    536:                                        break;
                    537:                                if(de->d_ino==0 || de->d_name[0]==0)
                    538:                                        continue;
                    539:                                if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
                    540:                                        continue;
                    541:                                n += DIRLEN;
                    542:                        }
                    543:                }
                    544:                for(n=0; n<rhdr.count; ){
                    545:                        de = readdir(rf->fd->dir);
                    546:                        if(de == 0)
                    547:                                break;
                    548:                        if(de->d_ino==0 || de->d_name[0]==0)
                    549:                                continue;
                    550:                        if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0)
                    551:                                continue;
                    552:                        strncpy(d.name, de->d_name, NAMELEN-1);
                    553:                        d.name[NAMELEN-1] = 0;
                    554:                        path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1);
                    555:                        sprintf(path, "%s/%s", f->path, de->d_name);
                    556:                        memset(&stbuf, 0, sizeof stbuf);
                    557:                        if(stat(path, &stbuf) < 0){
                    558:                                fprintf(stderr, "dir: bad path %s\n", path);
                    559:                                /* but continue... probably a bad symlink */
                    560:                        }
                    561:                        free(path);
                    562:                        strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN);
                    563:                        strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN);
                    564:                        d.qid.path = qid(&stbuf);
                    565:                        d.qid.vers = vers(&stbuf);
                    566:                        d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777);
                    567:                        d.atime = stbuf.st_atime;
                    568:                        d.mtime = stbuf.st_mtime;
                    569:                        d.len.l.hlength = 0;
                    570:                        d.len.l.length = stbuf.st_size;
                    571:                        convD2M(&d, rdata+n);
                    572:                        n += DIRLEN;
                    573:                }
                    574:        }else{
                    575:                errno = 0;
                    576:                if(rf->fd->offset != rhdr.offset){
                    577:                        rf->fd->offset = rhdr.offset;
                    578:                        if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
                    579:                                errjmp(sys_errlist[errno]);
                    580:                }
                    581:                n = read(rf->fd->fd, rdata, rhdr.count);
                    582:                if(n < 0)
                    583:                        errjmp(sys_errlist[errno]);
                    584:        }
                    585:        rf->fd->offset += n;
                    586:        thdr.count = n;
                    587:        thdr.data = rdata;
                    588: }
                    589: 
                    590: void
                    591: rwrite(void)
                    592: {
                    593:        Rfile *rf;
                    594:        int n;
                    595: 
                    596:        rf = rfilefid();
                    597:        if(rf->fd == 0)
                    598:                errjmp(Enotopen);
                    599:        if(rhdr.count > sizeof rdata)
                    600:                errjmp(Etoolarge);
                    601:        errno = 0;
                    602:        if(rf->fd->offset != rhdr.offset){
                    603:                rf->fd->offset = rhdr.offset;
                    604:                if(lseek(rf->fd->fd, rhdr.offset, 0) < 0)
                    605:                        errjmp(sys_errlist[errno]);
                    606:        }
                    607:        n = write(rf->fd->fd, rhdr.data, rhdr.count);
                    608:        if(n < 0)
                    609:                errjmp(sys_errlist[errno]);
                    610:        rf->fd->offset += n;
                    611:        thdr.count = n;
                    612: }
                    613: 
                    614: void
                    615: rstat(void)
                    616: {
                    617:        Rfile *rf;
                    618:        File *f;
                    619:        Dir d;
                    620: 
                    621:        rf = rfilefid();
                    622:        f = rf->file;
                    623:        errjmp(dostat(f, 0));
                    624:        strncpy(d.name, f->name, NAMELEN);
                    625:        strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN);
                    626:        strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN);
                    627:        d.qid = f->qid;
                    628:        d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777);
                    629:        d.atime = f->stbuf.st_atime;
                    630:        d.mtime = f->stbuf.st_mtime;
                    631:        d.len.l.hlength = 0;
                    632:        d.len.l.length = f->stbuf.st_size;
                    633:        convD2M(&d, thdr.stat);
                    634: }
                    635: 
                    636: void
                    637: rwstat(void)
                    638: {
                    639:        Rfile *rf;
                    640:        File *f;
                    641:        Dir d;
                    642:        Pass *p;
                    643:        char *path, *dir, name[NAMELEN];
                    644: 
                    645:        rf = rfilefid();
                    646:        f = rf->file;
                    647:        errjmp(dostat(f, 0));
                    648:        convM2D(rhdr.stat, &d);
                    649:        errno = 0;
                    650:        if(rf->uid != f->stbuf.st_uid)
                    651:                errjmp(Eowner);
                    652:        if(strcmp(d.name, f->name) != 0){
                    653:                parentwrperm(rf);
                    654:                dir = bldpath(f->path, "..", name);
                    655:                path = erealloc(0, strlen(dir)+1+strlen(d.name)+1);
                    656:                sprintf(path, "%s/%s", dir, d.name);
                    657:                if(link(f->path, path) < 0){
                    658:                        free(path);
                    659:                        errjmp(sys_errlist[errno]);
                    660:                }
                    661:                if(unlink(f->path) < 0){
                    662:                        free(path);
                    663:                        errjmp(sys_errlist[errno]);
                    664:                }
                    665:                free(f->path);
                    666:                free(f->name);
                    667:                f->path = path;
                    668:                f->name = estrdup(d.name);
                    669:        }
                    670:        if((d.mode&0777) != (f->stbuf.st_mode&0777)){
                    671:                if(chmod(f->path, d.mode&0777) < 0)
                    672:                        errjmp(sys_errlist[errno]);
                    673:                f->stbuf.st_mode &= ~0777;
                    674:                f->stbuf.st_mode |= d.mode&0777;
                    675:        }
                    676:        p = name2pass(gid, d.gid);
                    677:        if(p == 0)
                    678:                errjmp(Eunknown);
                    679:        if(p->id != f->stbuf.st_gid){
                    680:                if(chown(f->path, f->stbuf.st_uid, p->id) < 0)
                    681:                        errjmp(sys_errlist[errno]);
                    682:                f->stbuf.st_gid = p->id;
                    683:        }
                    684: }
                    685: 
                    686: void
                    687: rclunk(int rm)
                    688: {
                    689:        int ret;
                    690:        char *err;
                    691:        Rfile *rf;
                    692:        File *f;
                    693:        Fd *fd;
                    694: 
                    695:        err = 0;
                    696:        rf = rfilefid();
                    697:        f = rf->file;
                    698:        if(rm){
                    699:                parentwrperm(rf);
                    700:                if(f->qid.path & CHDIR)
                    701:                        ret = rmdir(f->path);
                    702:                else
                    703:                        ret = unlink(f->path);
                    704:                if(ret)
                    705:                        err = sys_errlist[errno];
                    706:        }else if(rf->rclose){   /* ignore errors */
                    707:                if(f->qid.path & CHDIR)
                    708:                        rmdir(f->path);
                    709:                else
                    710:                        unlink(f->path);
                    711:        }
                    712:                
                    713:        rf->busy = 0;
                    714:        if(--f->ref == 0){
                    715:                free(f->path);
                    716:                free(f->name);
                    717:                free(f);
                    718:        }
                    719:        fd = rf->fd;
                    720:        if(fd){
                    721:                if(fd->ref <= 0)
                    722:                        error("clunk fd count");
                    723:                if(--fd->ref == 0){
                    724:                        if(fd->fd)
                    725:                                close(fd->fd);
                    726:                        if(fd->dir)
                    727:                                closedir(fd->dir);
                    728:                        free(fd);
                    729:                }
                    730:                rf->fd = 0;
                    731:        }
                    732:        if(err)
                    733:                errjmp(err);
                    734: }
                    735: 
                    736: char*
                    737: bldpath(char *a, char *elem, char *name)
                    738: {
                    739:        char *path, *p;
                    740: 
                    741:        if(strcmp(elem, "..") == 0){
                    742:                if(strcmp(a, "/") == 0){
                    743:                        path = estrdup(a);
                    744:                        strcpy(name, a);
                    745:                }else{
                    746:                        p = strrchr(a, '/');
                    747:                        if(p == 0){
                    748:                                fprintf(stderr, "path: '%s'\n", path);
                    749:                                error("malformed path 1");
                    750:                        }
                    751:                        if(p == a)      /* reduced to "/" */
                    752:                                p++;
                    753:                        path = erealloc(0, (p-a)+1);
                    754:                        memmove(path, a, (p-a));
                    755:                        path[(p-a)] = 0;
                    756:                        if(strcmp(path, "/") == 0)
                    757:                                p = path;
                    758:                        else{
                    759:                                p = strrchr(path, '/');
                    760:                                if(p == 0){
                    761:                                        fprintf(stderr, "path: '%s'\n", path);
                    762:                                        error("malformed path 2");
                    763:                                }
                    764:                                p++;
                    765:                        }
                    766:                        strcpy(name, p);
                    767:                }
                    768:        }else{
                    769:                if(strcmp(a, "/") == 0)
                    770:                        a = "";
                    771:                path = erealloc(0, strlen(a)+1+strlen(elem)+1);
                    772:                sprintf(path, "%s/%s", a, elem);
                    773:                strcpy(name, elem);
                    774:        }
                    775:        if(strlen(name) >= NAMELEN)
                    776:                error("bldpath: name too long");
                    777:        return path;
                    778: }
                    779: 
                    780: char*
                    781: dostat(File *f, char *elem)
                    782: {
                    783:        char *path;
                    784:        struct stat stbuf;
                    785:        char name[NAMELEN];
                    786: 
                    787:        if(elem)
                    788:                path = bldpath(f->path, elem, name);
                    789:        else
                    790:                path = f->path;
                    791:        errno = 0;
                    792:        if(stat(path, &stbuf) < 0)
                    793:                return sys_errlist[errno];
                    794:        if(elem){
                    795:                free(f->path);
                    796:                f->path = path;
                    797:                f->name = estrdup(name);
                    798:        }
                    799:        f->qid.path = qid(&stbuf);
                    800:        f->qid.vers = vers(&stbuf);
                    801:        f->stbuf = stbuf;
                    802:        return 0;
                    803: }
                    804: 
                    805: int
                    806: omode(int m)
                    807: {
                    808:        switch(m){
                    809:        case 0:         /* OREAD */
                    810:        case 3:         /* OEXEC */
                    811:                return 0;
                    812:        case 1:         /* OWRITE */
                    813:                return 1;
                    814:        case 2:         /* ORDWR */
                    815:                return 2;
                    816:        }
                    817:        errjmp(Emode);
                    818:        return 0;
                    819: }
                    820: 
                    821: void
                    822: sendmsg(char *err)
                    823: {
                    824:        int n;
                    825: 
                    826:        if(err){
                    827:                thdr.type = Rerror;
                    828:                strncpy(thdr.ename, err, ERRLEN);
                    829:        }
                    830:        DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr)));
                    831:        n = convS2M(&thdr, tdata);
                    832:        if(n == 0)
                    833:                error("bad sendmsg format");
                    834:        if(write(1, tdata, n) != n)
                    835:                error("write error");
                    836: }
                    837: 
                    838: 
                    839: int
                    840: okfid(int fid)
                    841: {
                    842:        enum{ Delta=10 };
                    843: 
                    844:        if(fid < 0){
                    845:                fprintf(stderr, "u9fs: negative fid %d\n", fid);
                    846:                return 0;
                    847:        }
                    848:        if(fid >= nrfilealloc){
                    849:                fid += Delta;
                    850:                rfile = erealloc(rfile, fid*sizeof(Rfile));
                    851:                memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile));
                    852:                nrfilealloc = fid;
                    853:        }
                    854:        return 1;
                    855: }
                    856: 
                    857: Rfile*
                    858: rfilefid(void)
                    859: {
                    860:        Rfile *rf;
                    861: 
                    862:        if(!okfid(rhdr.fid))
                    863:                errjmp(Ebadfid);
                    864:        rf = &rfile[rhdr.fid];
                    865:        if(rf->busy == 0)
                    866:                errjmp(Ebadfid);
                    867:        if(rf->file->ref <= 0)
                    868:                error("ref count");
                    869:        return rf;
                    870: }
                    871: 
                    872: void
                    873: perm(Rfile *rf, int mask, struct stat *st)
                    874: {
                    875:        if(st == 0)
                    876:                st = &rf->file->stbuf;
                    877:        /* plan 9 access semantics; simpler and more sensible */
                    878:        if(rf->uid == st->st_uid)
                    879:                if((st->st_mode>>6) & mask)
                    880:                        return;
                    881:        if(rf->gid == st->st_gid)
                    882:                if((st->st_mode>>3) & mask)
                    883:                        return;
                    884:        if((st->st_mode>>0) & mask)
                    885:                return;
                    886:        errjmp(Eperm);
                    887: }
                    888: 
                    889: void
                    890: parentwrperm(Rfile *rf)
                    891: {
                    892:        Rfile trf;
                    893:        struct stat st;
                    894:        char *dirp, dir[512];
                    895: 
                    896:        dirp = bldpath(rf->file->path, "..", dir);
                    897:        if(strlen(dirp) < sizeof dir){  /* ugly: avoid leaving dirp allocated */
                    898:                strcpy(dir, dirp);
                    899:                free(dirp);
                    900:                dirp = dir;
                    901:        }
                    902:        if(stat(dirp, &st) < 0)
                    903:                errjmp(Eperm);
                    904:        trf.uid = rf->uid;
                    905:        trf.gid = rf->gid;
                    906:        perm(&trf, 2, &st);
                    907: }
                    908: 
                    909: File*
                    910: newfile(void)
                    911: {
                    912:        File *f;
                    913: 
                    914:        f = erealloc(0, sizeof(File));
                    915:        memset(f, 0, sizeof(File));
                    916:        f->ref = 1;
                    917:        return f;
                    918: }
                    919: 
                    920: /*
                    921:  * qids: directory bit, seven bits of device, 24 bits of inode
                    922:  */
                    923: Ulong
                    924: vers(struct stat *st)
                    925: {
                    926:        return st->st_mtime;
                    927: }
                    928: 
                    929: Ulong
                    930: qid(struct stat *st)
                    931: {
                    932:        static int nqdev;
                    933:        static Uchar *qdev;
                    934:        Ulong q;
                    935:        int dev;
                    936: 
                    937:        if(qdev == 0){
                    938:                qdev = erealloc(0, 65536U);
                    939:                memset(qdev, 0, 65536U);
                    940:        }
                    941:        q = 0;
                    942:        if((st->st_mode&S_IFMT) ==  S_IFDIR)
                    943:                q = CHDIR;
                    944:        dev = st->st_dev & 0xFFFFUL;
                    945:        if(qdev[dev] == 0){
                    946:                if(++nqdev >= 128)
                    947:                        error("too many devices");
                    948:                qdev[dev] = nqdev;
                    949:        }
                    950:        q |= qdev[dev]<<24;
                    951:        q |= st->st_ino & 0x00FFFFFFUL;
                    952:        return q;
                    953: }
                    954: 
                    955: Pass*
                    956: name2pass(Pass **pw, char *name)
                    957: {
                    958:        int i;
                    959:        Pass *p;
                    960: 
                    961:        for(i=0; i<256; i++)
                    962:                for(p = pw[i]; p; p = p->next)
                    963:                        if(strcmp(name, p->name) == 0)
                    964:                                return p;
                    965:        return 0;
                    966: }
                    967: 
                    968: char*
                    969: id2name(Pass **pw, int id)
                    970: {
                    971:        int i;
                    972:        Pass *p;
                    973:        char *s;
                    974:        static char buf[8];
                    975: 
                    976:        s = 0;
                    977:        /* use last on list == first in file */
                    978:        i = (id&0xFF) ^ ((id>>8)&0xFF);
                    979:        for(p = pw[i]; p; p = p->next)
                    980:                if(p->id == id)
                    981:                        s = p->name;
                    982:        if(s)
                    983:                return s;
                    984:        sprintf(buf, "%d", id);
                    985:        return buf;
                    986: }
                    987: 
                    988: void
                    989: freepass(Pass **pass)
                    990: {
                    991:        int i;
                    992:        Pass *p, *np;
                    993: 
                    994:        for(i=0; i<256; i++){
                    995:                for(p = pass[i]; p; p = np){
                    996:                        np = p->next;
                    997:                        free(p);
                    998:                }
                    999:                pass[i] = 0; 
                   1000:        }
                   1001: }
                   1002: 
                   1003: void
                   1004: getpwdf(void)
                   1005: {
                   1006:        static mtime;
                   1007:        struct stat stbuf;
                   1008:        struct passwd *pw;
                   1009:        int i;
                   1010:        Pass *p;
                   1011: 
                   1012:        if(stat("/etc/passwd", &stbuf) < 0)
                   1013:                error("can't read /etc/passwd");
                   1014:        if(stbuf.st_mtime <= mtime)
                   1015:                return;
                   1016:        freepass(uid);
                   1017:        while(pw = getpwent()){
                   1018:                i = pw->pw_uid;
                   1019:                i = (i&0xFF) ^ ((i>>8)&0xFF);
                   1020:                p = erealloc(0, sizeof(Pass));
                   1021:                p->next = uid[i];
                   1022:                uid[i] = p;
                   1023:                p->id = pw->pw_uid;
                   1024:                p->gid = pw->pw_gid;
                   1025:                p->name = estrdup(pw->pw_name);
                   1026:        }
                   1027:        setpwent();
                   1028:        endpwent();
                   1029: }
                   1030: 
                   1031: void
                   1032: getgrpf(void)
                   1033: {
                   1034:        static mtime;
                   1035:        struct stat stbuf;
                   1036:        struct group *pw;
                   1037:        int i;
                   1038:        Pass *p;
                   1039: 
                   1040:        if(stat("/etc/group", &stbuf) < 0)
                   1041:                error("can't read /etc/group");
                   1042:        if(stbuf.st_mtime <= mtime)
                   1043:                return;
                   1044:        freepass(gid);
                   1045:        while(pw = getgrent()){
                   1046:                i = pw->gr_gid;
                   1047:                i = (i&0xFF) ^ ((i>>8)&0xFF);
                   1048:                p = erealloc(0, sizeof(Pass));
                   1049:                p->next = gid[i];
                   1050:                gid[i] = p;
                   1051:                p->id = pw->gr_gid;
                   1052:                p->gid = 0;
                   1053:                p->name = estrdup(pw->gr_name);
                   1054:        }
                   1055:        setgrent();
                   1056:        endgrent();
                   1057: }
                   1058: 
                   1059: void
                   1060: error(char *s)
                   1061: {
                   1062:        fprintf(stderr, "u9fs: %s\n", s);
                   1063:        perror("unix error");
                   1064:        exit(1);
                   1065: }
                   1066: 
                   1067: void
                   1068: errjmp(char *s)
                   1069: {
                   1070:        if(s == 0)
                   1071:                return;
                   1072:        sendmsg(s);
                   1073:        longjmp(loopjmp, 1);
                   1074: }
                   1075: 
                   1076: void*
                   1077: erealloc(void *p, unsigned n)
                   1078: {
                   1079:        if(p == 0)
                   1080:                p = malloc(n);
                   1081:        else
                   1082:                p = realloc(p, n);
                   1083:        if(p == 0)
                   1084:                error("realloc fail");
                   1085:        return p;
                   1086: }
                   1087: 
                   1088: char*
                   1089: estrdup(char *p)
                   1090: {
                   1091:        p = strdup(p);
                   1092:        if(p == 0)
                   1093:                error("strdup fail");
                   1094:        return p;
                   1095: }
                   1096: 
                   1097: #ifdef SOCKETS
                   1098: void
                   1099: remotehostname(void)
                   1100: {
                   1101:        struct sockaddr_in sock;
                   1102:        struct hostent *hp;
                   1103:        int len;
                   1104:        int on = 1;
                   1105: 
                   1106:        len = sizeof sock;
                   1107:        if(getpeername(0, &sock, &len) < 0)
                   1108:                error("getpeername");
                   1109:        hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr),
                   1110:                sock.sin_family);
                   1111:        if(hp == 0)
                   1112:                error("gethostbyaddr");
                   1113:        strcpy(bsdhost, hp->h_name);
                   1114:        fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid());
                   1115: 
                   1116:        setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
                   1117: }
                   1118: #endif

unix.superglobalmegacorp.com

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