Annotation of researchv10no/cmd/u9fs/u9fs.c, 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:                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.