kernel: add devskel for pc and pc64
This commit is contained in:
parent
df92301d8f
commit
f4840cdba5
4 changed files with 274 additions and 0 deletions
35
sys/man/3/skel
Normal file
35
sys/man/3/skel
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
.TH SKEL 3
|
||||||
|
.SH NAME
|
||||||
|
skel \- skeleton builder
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B bind #z/\fIskel\fR
|
||||||
|
.I dir
|
||||||
|
.PP
|
||||||
|
.B bind #zd/\fIskel\fR
|
||||||
|
.I dir
|
||||||
|
.PP
|
||||||
|
.B bind #ze/
|
||||||
|
.I dir
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
This device serves a single child directory with a single empty child
|
||||||
|
file. The name of these files is determined by the first walk away
|
||||||
|
from the root. After which, the hierarchy for that attached session
|
||||||
|
becomes stable. The
|
||||||
|
.B d
|
||||||
|
attach option causes the child file to be an empty directory. The
|
||||||
|
.B e
|
||||||
|
attach option presents a completly empty root directory.
|
||||||
|
.SH EXAMPLES
|
||||||
|
Skeleton files can be used for constructing arbitrary bind targets.
|
||||||
|
.EX
|
||||||
|
.IP
|
||||||
|
bind -b '#zd/newroot' /
|
||||||
|
bind '#zd/bin' /newroot
|
||||||
|
bind '#z/walk' /newroot/bin
|
||||||
|
bind /bin/walk /newroot/bin/walk
|
||||||
|
bind /newroot /
|
||||||
|
walk /
|
||||||
|
.EE
|
||||||
|
.SH SOURCE
|
||||||
|
.B /sys/src/9/port/devskel.c
|
|
@ -18,6 +18,7 @@ dev
|
||||||
kprof
|
kprof
|
||||||
fs
|
fs
|
||||||
dtracy
|
dtracy
|
||||||
|
skel
|
||||||
|
|
||||||
ether netif
|
ether netif
|
||||||
bridge netif log
|
bridge netif log
|
||||||
|
|
|
@ -41,6 +41,7 @@ dev
|
||||||
segment
|
segment
|
||||||
vmx
|
vmx
|
||||||
dtracy
|
dtracy
|
||||||
|
skel
|
||||||
|
|
||||||
link
|
link
|
||||||
# devpccard pci
|
# devpccard pci
|
||||||
|
|
237
sys/src/9/port/devskel.c
Normal file
237
sys/src/9/port/devskel.c
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#include "u.h"
|
||||||
|
#include "../port/lib.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fns.h"
|
||||||
|
#include "../port/error.h"
|
||||||
|
|
||||||
|
#include "netif.h"
|
||||||
|
|
||||||
|
typedef struct Skel Skel;
|
||||||
|
struct Skel {
|
||||||
|
int ref;
|
||||||
|
QLock lk;
|
||||||
|
char name[KNAMELEN];
|
||||||
|
char mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
QLock lk;
|
||||||
|
ulong path;
|
||||||
|
} skelalloc;
|
||||||
|
|
||||||
|
enum{
|
||||||
|
Qroot,
|
||||||
|
Qdir,
|
||||||
|
Qskel,
|
||||||
|
};
|
||||||
|
|
||||||
|
static Chan*
|
||||||
|
skelattach(char *spec)
|
||||||
|
{
|
||||||
|
Chan *c;
|
||||||
|
Skel *f;
|
||||||
|
uvlong path;
|
||||||
|
|
||||||
|
c = devattach('z', spec);
|
||||||
|
|
||||||
|
f = smalloc(sizeof *f);
|
||||||
|
if(spec != nil && spec[0] != '\0' && strchr("de", spec[0]) != nil)
|
||||||
|
f->mode = spec[0];
|
||||||
|
else
|
||||||
|
f->mode = 'f';
|
||||||
|
|
||||||
|
f->ref = 1;
|
||||||
|
|
||||||
|
qlock(&skelalloc.lk);
|
||||||
|
path = skelalloc.path++;
|
||||||
|
qunlock(&skelalloc.lk);
|
||||||
|
|
||||||
|
mkqid(&c->qid, NETQID(path, Qroot), 0, QTDIR);
|
||||||
|
c->aux = f;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
step(Chan *c, Dir *dp, int direction)
|
||||||
|
{
|
||||||
|
Skel *f;
|
||||||
|
Qid qid;
|
||||||
|
ulong perm;
|
||||||
|
uvlong path;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
perm = 0555|DMDIR;
|
||||||
|
path = NETTYPE(c->qid.path);
|
||||||
|
f = c->aux;
|
||||||
|
name = f->name;
|
||||||
|
|
||||||
|
path += direction;
|
||||||
|
if(!f->name[0] && path != Qroot)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch(path){
|
||||||
|
case Qroot:
|
||||||
|
mkqid(&qid, Qroot, 0, QTDIR);
|
||||||
|
name = "#z";
|
||||||
|
break;
|
||||||
|
case Qdir:
|
||||||
|
mkqid(&qid, Qdir, 0, QTDIR);
|
||||||
|
break;
|
||||||
|
case Qskel:
|
||||||
|
switch(f->mode){
|
||||||
|
case 'd':
|
||||||
|
mkqid(&qid, Qskel, 0, QTDIR);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
default:
|
||||||
|
mkqid(&qid, Qskel, 0, QTFILE);
|
||||||
|
perm = 0666;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qid.path = NETQID(NETID(c->qid.path), qid.path);
|
||||||
|
devdir(c, qid, name, 0, eve, perm, dp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
skelgen(Chan *c, char *name, Dirtab *, int, int s, Dir *dp)
|
||||||
|
{
|
||||||
|
Skel *f;
|
||||||
|
|
||||||
|
f = c->aux;
|
||||||
|
//First walk away from root
|
||||||
|
if(name && !f->name[0] && f->mode != 'e' && NETTYPE(c->qid.path) == Qroot)
|
||||||
|
utfecpy(f->name, &f->name[sizeof f->name-1], name);
|
||||||
|
|
||||||
|
if(s != DEVDOTDOT)
|
||||||
|
s++;
|
||||||
|
|
||||||
|
return step(c, dp, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Walkqid*
|
||||||
|
skelwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||||
|
{
|
||||||
|
Walkqid *wq;
|
||||||
|
Skel *f;
|
||||||
|
|
||||||
|
f = c->aux;
|
||||||
|
qlock(&f->lk);
|
||||||
|
if(waserror()){
|
||||||
|
qunlock(&f->lk);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
|
||||||
|
wq = devwalk(c, nc, name, nname, nil, 0, skelgen);
|
||||||
|
if(wq != nil && wq->clone != nil && wq->clone != c){
|
||||||
|
if(f->ref <= 0)
|
||||||
|
panic("devskel ref");
|
||||||
|
f->ref++;
|
||||||
|
}
|
||||||
|
qunlock(&f->lk);
|
||||||
|
poperror();
|
||||||
|
return wq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chan*
|
||||||
|
skelopen(Chan *c, int omode)
|
||||||
|
{
|
||||||
|
if(!(c->qid.type & QTDIR))
|
||||||
|
error(Eperm);
|
||||||
|
if(omode != OREAD)
|
||||||
|
error(Ebadarg);
|
||||||
|
|
||||||
|
c->mode = omode;
|
||||||
|
c->flag |= COPEN;
|
||||||
|
c->offset = 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
skelclose(Chan *c)
|
||||||
|
{
|
||||||
|
Skel *f;
|
||||||
|
|
||||||
|
f = c->aux;
|
||||||
|
qlock(&f->lk);
|
||||||
|
f->ref--;
|
||||||
|
if(f->ref == 0){
|
||||||
|
qunlock(&f->lk);
|
||||||
|
free(f);
|
||||||
|
} else
|
||||||
|
qunlock(&f->lk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
skelread(Chan *c, void *va, long n, vlong)
|
||||||
|
{
|
||||||
|
Skel *f;
|
||||||
|
long nout;
|
||||||
|
|
||||||
|
if(!(c->qid.type & QTDIR))
|
||||||
|
error(Eperm);
|
||||||
|
|
||||||
|
f = c->aux;
|
||||||
|
qlock(&f->lk);
|
||||||
|
if(waserror()){
|
||||||
|
qunlock(&f->lk);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
nout = devdirread(c, va, n, nil, 0, skelgen);
|
||||||
|
qunlock(&f->lk);
|
||||||
|
poperror();
|
||||||
|
return nout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
skelwrite(Chan *, void *, long, vlong)
|
||||||
|
{
|
||||||
|
error(Eperm);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
skelstat(Chan *c, uchar *db, int n)
|
||||||
|
{
|
||||||
|
Skel *f;
|
||||||
|
Dir dir;
|
||||||
|
|
||||||
|
f = c->aux;
|
||||||
|
qlock(&f->lk);
|
||||||
|
step(c, &dir, 0);
|
||||||
|
qunlock(&f->lk);
|
||||||
|
|
||||||
|
n = convD2M(&dir, db, n);
|
||||||
|
if(n < BIT16SZ)
|
||||||
|
error(Eshortstat);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dev skeldevtab = {
|
||||||
|
'z',
|
||||||
|
"skel",
|
||||||
|
|
||||||
|
devreset,
|
||||||
|
devinit,
|
||||||
|
devshutdown,
|
||||||
|
skelattach,
|
||||||
|
skelwalk,
|
||||||
|
skelstat,
|
||||||
|
skelopen,
|
||||||
|
devcreate,
|
||||||
|
skelclose,
|
||||||
|
skelread,
|
||||||
|
devbread,
|
||||||
|
skelwrite,
|
||||||
|
devbwrite,
|
||||||
|
devremove,
|
||||||
|
devwstat,
|
||||||
|
};
|
Loading…
Reference in a new issue