devroot.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       devroot.c (4237B)
       ---
            1 #include        "u.h"
            2 #include        "lib.h"
            3 #include        "mem.h"
            4 #include        "dat.h"
            5 #include        "fns.h"
            6 #include        "error.h"
            7 
            8 enum
            9 {
           10         Qdir = 0,
           11         Qboot = 0x1000,
           12 
           13         Nrootfiles = 32,
           14         Nbootfiles = 32,
           15 };
           16 
           17 typedef struct Dirlist Dirlist;
           18 struct Dirlist
           19 {
           20         uint base;
           21         Dirtab *dir;
           22         uchar **data;
           23         int ndir;
           24         int mdir;
           25 };
           26 
           27 static Dirtab rootdir[Nrootfiles] = {
           28         "#/",                {Qdir, 0, QTDIR},        0,                DMDIR|0555,
           29         "boot",        {Qboot, 0, QTDIR},        0,                DMDIR|0555,
           30 };
           31 static uchar *rootdata[Nrootfiles];
           32 static Dirlist rootlist = 
           33 {
           34         0,
           35         rootdir,
           36         rootdata,
           37         2,
           38         Nrootfiles
           39 };
           40 
           41 static Dirtab bootdir[Nbootfiles] = {
           42         "boot",        {Qboot, 0, QTDIR},        0,                DMDIR|0555,
           43 };
           44 static uchar *bootdata[Nbootfiles];
           45 static Dirlist bootlist =
           46 {
           47         Qboot,
           48         bootdir,
           49         bootdata,
           50         1,
           51         Nbootfiles
           52 };
           53 
           54 /*
           55  *  add a file to the list
           56  */
           57 static void
           58 addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm)
           59 {
           60         Dirtab *d;
           61 
           62         if(l->ndir >= l->mdir)
           63                 panic("too many root files");
           64         l->data[l->ndir] = contents;
           65         d = &l->dir[l->ndir];
           66         strcpy(d->name, name);
           67         d->length = len;
           68         d->perm = perm;
           69         d->qid.type = 0;
           70         d->qid.vers = 0;
           71         d->qid.path = ++l->ndir + l->base;
           72         if(perm & DMDIR)
           73                 d->qid.type |= QTDIR;
           74 }
           75 
           76 /*
           77  *  add a root file
           78  */
           79 void
           80 addbootfile(char *name, uchar *contents, ulong len)
           81 {
           82         addlist(&bootlist, name, contents, len, 0555);
           83 }
           84 
           85 /*
           86  *  add a root directory
           87  */
           88 static void
           89 addrootdir(char *name)
           90 {
           91         addlist(&rootlist, name, nil, 0, DMDIR|0555);
           92 }
           93 
           94 static void
           95 rootreset(void)
           96 {
           97         addrootdir("bin");
           98         addrootdir("dev");
           99         addrootdir("env");
          100         addrootdir("fd");
          101         addrootdir("mnt");
          102         addrootdir("net");
          103         addrootdir("net.alt");
          104         addrootdir("proc");
          105         addrootdir("root");
          106         addrootdir("srv");
          107 }
          108 
          109 static Chan*
          110 rootattach(char *spec)
          111 {
          112         return devattach('/', spec);
          113 }
          114 
          115 static int
          116 rootgen(Chan *c, char *name, Dirtab *dt, int i, int s, Dir *dp)
          117 {
          118         int t;
          119         Dirtab *d;
          120         Dirlist *l;
          121 
          122         switch((int)c->qid.path){
          123         case Qdir:
          124                 if(s == DEVDOTDOT){
          125                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
          126                         return 1;
          127                 }
          128                 return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
          129         case Qboot:
          130                 if(s == DEVDOTDOT){
          131                         devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
          132                         return 1;
          133                 }
          134                 return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
          135         default:
          136                 if(s == DEVDOTDOT){
          137                         if((int)c->qid.path < Qboot)
          138                                 devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
          139                         else
          140                                 devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
          141                         return 1;
          142                 }
          143                 if(s != 0)
          144                         return -1;
          145                 if((int)c->qid.path < Qboot){
          146                         t = c->qid.path-1;
          147                         l = &rootlist;
          148                 }else{
          149                         t = c->qid.path - Qboot - 1;
          150                         l = &bootlist;
          151                 }
          152                 if(t >= l->ndir)
          153                         return -1;
          154 if(t < 0){
          155 print("rootgen %llud %d %d\n", c->qid.path, s, t);
          156 panic("whoops");
          157 }
          158                 d = &l->dir[t];
          159                 devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
          160                 return 1;
          161         }
          162 }
          163 
          164 static Walkqid*
          165 rootwalk(Chan *c, Chan *nc, char **name, int nname)
          166 {
          167         return devwalk(c,  nc, name, nname, nil, 0, rootgen);
          168 }
          169 
          170 static int
          171 rootstat(Chan *c, uchar *dp, int n)
          172 {
          173         return devstat(c, dp, n, nil, 0, rootgen);
          174 }
          175 
          176 static Chan*
          177 rootopen(Chan *c, int omode)
          178 {
          179         return devopen(c, omode, nil, 0, devgen);
          180 }
          181 
          182 /*
          183  * sysremove() knows this is a nop
          184  */
          185 static void
          186 rootclose(Chan *c)
          187 {
          188 }
          189 
          190 static long
          191 rootread(Chan *c, void *buf, long n, vlong off)
          192 {
          193         ulong t;
          194         Dirtab *d;
          195         Dirlist *l;
          196         uchar *data;
          197         ulong offset = off;
          198 
          199         t = c->qid.path;
          200         switch(t){
          201         case Qdir:
          202         case Qboot:
          203                 return devdirread(c, buf, n, nil, 0, rootgen);
          204         }
          205 
          206         if(t<Qboot)
          207                 l = &rootlist;
          208         else{
          209                 t -= Qboot;
          210                 l = &bootlist;
          211         }
          212 
          213         t--;
          214         if(t >= l->ndir)
          215                 error(Egreg);
          216 
          217         d = &l->dir[t];
          218         data = l->data[t];
          219         if(offset >= d->length)
          220                 return 0;
          221         if(offset+n > d->length)
          222                 n = d->length - offset;
          223 #ifdef asdf
          224 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n", 
          225                 t, buf, data, offset, offset, n,
          226                 ((ulong*)(data+offset))[0],
          227                 ((ulong*)(data+offset))[1],
          228                 ((ulong*)(data+offset))[2]);
          229 #endif
          230         memmove(buf, data+offset, n);
          231         return n;
          232 }
          233 
          234 static long
          235 rootwrite(Chan *c, void *v, long l, vlong vl)
          236 {
          237         error(Egreg);
          238         return 0;
          239 }
          240 
          241 Dev rootdevtab = {
          242         '/',
          243         "root",
          244 
          245         rootreset,
          246         devinit,
          247         devshutdown,
          248         rootattach,
          249         rootwalk,
          250         rootstat,
          251         rootopen,
          252         devcreate,
          253         rootclose,
          254         rootread,
          255         devbread,
          256         rootwrite,
          257         devbwrite,
          258         devremove,
          259         devwstat,
          260 };
          261