jehanne/sys/src/kern/port/devroot.c

262 lines
4.3 KiB
C

/* Copyright (C) Charles Forsyth
* See /doc/license/NOTICE.Plan9-9k.txt for details about the licensing.
*/
/* Portions of this file are Copyright (C) 2015-2018 Giacomo Tesio <giacomo@tesio.it>
* See /doc/license/gpl-2.0.txt for details about the licensing.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
enum
{
Qdir = 0,
Qboot = 0x1000,
Nrootfiles = 32,
Nbootfiles = 32,
};
typedef struct Dirlist Dirlist;
struct Dirlist
{
uint32_t base;
Dirtab *dir;
uint8_t **data;
int ndir;
int mdir;
};
static Dirtab rootdir[Nrootfiles] = {
"#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0500,
};
static uint8_t *rootdata[Nrootfiles];
static Dirlist rootlist =
{
0,
rootdir,
rootdata,
2,
Nrootfiles
};
static Dirtab bootdir[Nbootfiles] = {
"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555,
};
static uint8_t *bootdata[Nbootfiles];
static Dirlist bootlist =
{
Qboot,
bootdir,
bootdata,
1,
Nbootfiles
};
/*
* add a file to the list
*/
static void
addlist(Dirlist *l, char *name, uint8_t *contents, uint32_t len, int perm)
{
Dirtab *d;
if(l->ndir >= l->mdir)
panic("too many root files");
l->data[l->ndir] = contents;
d = &l->dir[l->ndir];
jehanne_strcpy(d->name, name);
d->length = len;
d->perm = perm;
d->qid.type = 0;
d->qid.vers = 0;
d->qid.path = ++l->ndir + l->base;
if(perm & DMDIR)
d->qid.type |= QTDIR;
}
/*
* add a /boot file
*/
void
addbootfile(char *name, uint8_t *contents, uint32_t len)
{
addlist(&bootlist, name, contents, len, 0500);
}
/*
* add a root directory
*/
static void
addrootdir(char *name)
{
addlist(&rootlist, name, nil, 0, DMDIR|0555);
}
static void
rootreset(void)
{
addrootdir("cmd");
addrootdir("dev");
addrootdir("env");
addrootdir("fd");
addrootdir("mnt");
addrootdir("n");
addrootdir("net");
addrootdir("net.alt");
addrootdir("proc");
addrootdir("root");
addrootdir("srv");
addrootdir("shr");
}
static Chan*
rootattach(Chan *c, Chan *ac, char *spec, int flags)
{
return devattach('/', spec);
}
static int
rootgen(Chan *c, char *name, Dirtab* _1, int _2, int s, Dir *dp)
{
int t;
Dirtab *d;
Dirlist *l;
switch((int)c->qid.path){
case Qdir:
if(s == DEVDOTDOT){
devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
return 1;
}
return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
case Qboot:
if(s == DEVDOTDOT){
devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
return 1;
}
return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
default:
if(s == DEVDOTDOT){
if((int)c->qid.path < Qboot)
devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
else
devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
return 1;
}
if(s != 0)
return -1;
if((int)c->qid.path < Qboot){
t = c->qid.path-1;
l = &rootlist;
}else{
t = c->qid.path - Qboot - 1;
l = &bootlist;
}
if(t >= l->ndir)
return -1;
if(t < 0){
jehanne_print("rootgen %#llux %d %d\n", c->qid.path, s, t);
panic("whoops");
}
d = &l->dir[t];
devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
return 1;
}
}
static Walkqid*
rootwalk(Chan *c, Chan *nc, char **name, int nname)
{
return devwalk(c, nc, name, nname, nil, 0, rootgen);
}
static long
rootstat(Chan *c, uint8_t *dp, long n)
{
return devstat(c, dp, n, nil, 0, rootgen);
}
static Chan*
rootopen(Chan *c, unsigned long omode)
{
return devopen(c, omode, nil, 0, devgen);
}
/*
* sysremove() knows this is a nop
*/
static void
rootclose(Chan* _1)
{
}
static long
rootread(Chan *c, void *buf, long n, int64_t off)
{
uint32_t t;
Dirtab *d;
Dirlist *l;
uint8_t *data;
uint32_t offset = off;
t = c->qid.path;
switch(t){
case Qdir:
case Qboot:
return devdirread(c, buf, n, nil, 0, rootgen);
}
if(t<Qboot)
l = &rootlist;
else{
t -= Qboot;
l = &bootlist;
}
t--;
if(t >= l->ndir)
error(Egreg);
d = &l->dir[t];
data = l->data[t];
if(offset >= d->length)
return 0;
if(offset+n > d->length)
n = d->length - offset;
jehanne_memmove(buf, data+offset, n);
return n;
}
static long
rootwrite(Chan* _1, void* _2, long _3, int64_t _4)
{
error(Egreg);
return 0;
}
Dev rootdevtab = {
'/',
"root",
rootreset,
devinit,
devshutdown,
rootattach,
rootwalk,
rootstat,
rootopen,
devcreate,
rootclose,
rootread,
devbread,
rootwrite,
devbwrite,
devremove,
devwstat,
};