#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/fcall.h>
#include <9pm/ns.h>
/* Qid is (2*fd + (file is ctl))+1 */
static int
dupqidgen(Qid *qid, int s)
{
Chan *c;
if(s == DEVDOTDOT || s == DEVDOT)
return 1;
s--;
if(waserror())
return -1;
c = fd2chan(s/2, -1);
cclose(c);
poperror();
mkqid(qid, s+1, 0, QTFILE);
return 1;
}
static int
dupqidstat(Qid q, uchar *edir, int nedir)
{
int fd;
char buf[20];
Chan *c;
Dir d;
static int perm[] = { 0400, 0200, 0600, 0 };
devdir(&d);
d.qid = q;
switch((long)q.path){
case 0:
d.name = "/";
d.mode = DMDIR|0555;
break;
default:
fd = (q.path-1)/2;
if((q.path-1)&1){
d.mode = 0400;
sprint(buf, "%dctl", fd);
}else{
if(!waserror()){
c = fd2chan(fd, -1);
cclose(c);
poperror();
d.mode = perm[c->omode];
}else
d.mode = 0600;
sprint(buf, "%d", fd);
}
d.name = buf;
break;
}
return convD2M(&d, edir, nedir);
}
static int
dupgen(Qid q, int i, uchar *edir, int nedir)
{
switch(dupqidgen(&q, i)){
case -1:
return -1;
case 0:
return 0;
default:
return dupqidstat(q, edir, nedir);
}
}
static Chan*
dupopen(Chan *c, Mnt *mnt, char *path, int omode)
{
Chan *f;
int fd, twicefd;
c->qid = devqid(mnt, path);
if(c->qid.type & QTDIR){
if(omode != 0)
error(Eisdir);
c->omode = 0;
return c;
}
if(c->qid.type & QTAUTH)
error(Eperm);
twicefd = c->qid.path - 1;
fd = twicefd/2;
if((twicefd & 1) == 0){
/* fd file */
f = fd2chan(fd, omode);
cclose(c);
c = f;
}
return c;
}
static int
procqidwidth(Chan *c)
{
char buf[32];
return sprint(buf, "%lud", c->qid.vers);
}
int
procfdprint(Chan *c, int fd, int w, char *s, int ns)
{
int n;
if(w == 0)
w = procqidwidth(c);
n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
fd,
&"r w rw"[(c->omode&3)<<1],
c->mnt->dev->dc, c->mnt->id,
c->qid.path, w, c->qid.vers, c->qid.type,
c->iounit, c->offset, c->path);
return n;
}
static long
duppread(Chan *c, void *va, long n, vlong offset)
{
char *a = va;
char buf[256];
int fd, twicefd;
if(c->qid.type == QTDIR)
return devdirread(c, a, n, offset);
twicefd = c->qid.path - 1;
fd = twicefd/2;
if(twicefd & 1){
c = fd2chan(fd, -1);
procfdprint(c, fd, 0, buf, sizeof buf);
cclose(c);
return readstr(offset, va, n, buf);
}
error("dupread");
return 0;
}
static long
duppwrite(Chan *c, void *va, long n, vlong offset)
{
USED(c);
USED(va);
USED(n);
USED(offset);
error("duppwrite");
return -1;
}
Dev devdup =
{
(Rune)'d',
devchdir,
devclunk,
devcreate,
devfstat,
devfwstat,
dupopen,
duppread,
duppwrite,
devread,
devremove,
devseek,
devstat,
devwrite,
devwstat,
devattach,
devserves,
dupgen,
};
syntax highlighted by Code2HTML, v. 0.9.1