V10/netfs/serv/f11.c
/*
* file service routines for FILES-11 ODS-1
* in its modern instance, with subdirectories
*/
#include <rf.h>
#include "files11.h"
#include "f11.h"
#define NULL 0
#define HUGE 0x7fffffff
int diskfd;
struct homeblock home;
Fsfile indexf;
unsigned short dirtyp;
static htorf();
static char *itoa();
static int binchk();
char *r50toa();
char *malloc();
/*
* permission hacks
*/
#define UXOTHER 1
static Idmap gmap[] = { "other", UXOTHER, 0 };
/*
* init:
* install the root
*
* argv[1] == the file containing our filesystem
*/
Rfile *
fsinit(argc, argv)
int argc;
char **argv;
{
register Rfile *f;
register long firsthdr;
char *p;
p = "dir";
dirtyp = ator50(&p);
if (argc <= 1)
rfpanic("no files-11 filesystem specified\n");
if ((diskfd = open(argv[1], 0)) < 0) /* readonly for now */
rfpanic("%s: cannot open\n", argv[1]);
if (lseek(diskfd, (long)HOMEBLK * BLKSIZ, 0) < 0)
rfpanic("can't seek for home block\n");
if (read(diskfd, (char *)&home, sizeof(home)) != sizeof(home))
rfpanic("can't read homeblock\n");
if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL
|| (f->fs = malloc(sizeof(Fsfile))) == NULL)
rfpanic("no mem for root\n");
firsthdr = plong(home.H_iblb)+home.H_ibsz;
lseek(diskfd, (firsthdr + fidtob(FINDEX)) * BLKSIZ, 0);
if (read(diskfd, (char *)&indexf.h, sizeof(indexf.h)) != sizeof(indexf.h))
rfpanic("can't read index header\n");
indexf.lbase = HUGE;
if (gethdr(FROOT, &fsp(f)->h) == 0)
rfpanic("can't read root header\n");
htorf(f, &fsp(f)->h);
fsp(f)->parent = FROOT;
fsp(f)->lbase = HUGE;
fsp(f)->flags = FBIN;
fsp(f)->tboff = fsp(f)->tbno = fsp(f)->tuoff = 0;
rfgidmap = gmap;
return (f);
}
/*
* access a file
*/
Rfile *
fswalk(df, name)
Rfile *df;
char *name;
{
register Rfile *f;
unsigned short fid;
int binary;
binary = binchk(name);
if (strcmp(name, ".") == 0)
return (df);
else if (strcmp(name, "..") == 0) {
if (df->ino == FROOT) {
fserrno = 0; /* magic: popped out */
return (NULL);
}
fid = fsp(df)->parent;
} else if ((fid = f11walk(df, name)) == 0)
return (NULL);
if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) {
rflog("no mem\n");
fserrno = RFEINVAL;
return (NULL);
}
if ((f->fs = malloc(sizeof(Fsfile))) == NULL) {
free((char *)f);
rflog("no mem\n");
fserrno = RFEINVAL;
return (NULL);
}
fsp(f)->lbase = HUGE;
if (gethdr(fid, &fsp(f)->h) == 0) {
free((char *)f);
fserrno = RFEIO;
return (NULL);
}
if (fsp(f)->h.h_ident.i_fnam.f_typ == dirtyp)
fsp(f)->parent = fsp(df)->h.h_fnum;
htorf(f, &fsp(f)->h);
fsp(f)->tboff = fsp(f)->tbno = fsp(f)->tuoff = 0;
if (binary)
fsp(f)->flags = FBIN;
else if (fsp(f)->h.h_fcs.f_rtyp == RTVAR && fsp(f)->h.h_fcs.f_ratt & RTCR)
fsp(f)->flags = 0;
else
fsp(f)->flags = FBIN;
return (f);
}
/*
* see if filename is `binary': trailing % in name
* stamp it out if so
*/
static
binchk(name)
register char *name;
{
name += strlen(name);
if (*--name == '%') {
*name = 0;
return (1);
}
return (0);
}
/*
* discard a file reference
*/
int
fsdone(f)
Rfile *f;
{
free(f->fs);
free((char *)f);
return (0);
}
/*
* return file status
*/
fsstat(f)
register Rfile *f;
{
if (gethdr(fsp(f)->h.h_fnum, &fsp(f)->h) == 0) {
fserrno = RFEINVAL;
return (-1);
}
htorf(f, &fsp(f)->h);
return (0);
}
/*
* read
*/
int
fsread(f, off, buf, len)
Rfile *f;
long off;
char *buf;
int len;
{
if (fsp(f)->flags & FBIN)
return (binread(f, off, buf, len));
else
return (textread(f, off, buf, len));
}
int
binread(f, off, buf, len)
Rfile *f;
long off;
char *buf;
int len;
{
char bbuf[BLKSIZ];
int boff;
long bno;
int nread, r;
int ncpy;
nread = 0;
bno = off / BLKSIZ;
boff = off % BLKSIZ;
/*
* contract this loop later
*/
r = 0;
while (len > 0) {
if ((r = f11rblk(f, bno, bbuf)) <= 0)
break;
ncpy = BLKSIZ - boff;
ncpy = (len > ncpy) ? ncpy : len;
memcpy(buf, bbuf+boff, ncpy);
len -= ncpy;
buf += ncpy;
nread += ncpy;
boff = 0;
bno++;
}
if (nread || r >= 0)
return (nread);
fserrno = RFEIO;
return (-1);
}
int
textread(f, off, buf, len)
Rfile *f;
long off;
char *buf;
int len;
{
unsigned char bbuf[BLKSIZ];
int boff;
long bno;
int nread, r;
int ncpy;
int rlen;
unsigned char *p;
nread = 0;
if (off == fsp(f)->tuoff) {
bno = fsp(f)->tbno;
boff = fsp(f)->tboff;
} else if (off == 0) {
bno = 0;
boff = 0;
} else { /* wrong, but so what? */
bno = off / BLKSIZ;
boff = off % BLKSIZ;
}
if ((r = f11rblk(f, bno, bbuf)) <= 0)
goto out;
p = bbuf + boff;
while (len > 0) {
if (boff & 01) {
p++;
boff++;
}
if ((bno * BLKSIZ) + boff >= f->size)
break;
rlen = p[0] + (p[1]<<8);
if (rlen == -1) { /* skip to next block */
if ((r = f11rblk(f, ++bno, bbuf)) <= 0)
goto out;
p = bbuf;
boff = 0;
continue;
}
if (rlen + 1 > len) /* +1 for newline */
/* set a particular error here? */
break;
p += 2;
for (; rlen > 0; rlen -= ncpy) {
ncpy = &bbuf[BLKSIZ] - p;
if (ncpy > rlen)
ncpy = rlen;
memcpy(buf, p, ncpy);
p += ncpy;
boff = p - bbuf;
nread += ncpy;
buf += ncpy;
len -= ncpy;
if (ncpy < rlen) { /* next block */
if ((r = f11rblk(f, ++bno, bbuf)) <= 0)
goto out;
p = bbuf;
boff = 0;
}
}
*buf++ = '\n';
nread++;
len--;
if (boff > BLKSIZ - 2) { /* about to need new block */
if ((r = f11rblk(f, ++bno, bbuf)) <= 0)
goto out;
p = bbuf;
boff = 0;
}
}
out:
if (boff == BLKSIZ) {
boff = 0;
bno++;
}
if (nread) {
fsp(f)->tuoff = off + nread;
fsp(f)->tbno = bno;
fsp(f)->tboff = boff;
}
if (nread || r >= 0)
return (nread);
fserrno = RFEIO;
return (-1);
}
/*
* read directory --
* return ascii records: decimal `i-number', tab, filename, NUL
* filename is filname.typ.ver
* *offp gets new file offset for directory
*/
#define DENTSIZE (6+9+4+6+1) /* max len of a directory record */
int
fsdirread(f, off, buf, len, offp)
Rfile *f;
long off;
char *buf;
int len;
long *offp;
{
char bbuf[BLKSIZ];
register char *p;
register struct directory *dp;
struct directory *dend;
char *op;
int r;
long bno;
int boff;
bno = off / BLKSIZ;
if ((r = f11rblk(f, bno, bbuf)) <= 0) {
fserrno = RFEIO;
return (r);
}
boff = off % BLKSIZ;
dp = (struct directory *)bbuf + (boff/sizeof(struct directory));
dend = (struct directory *)&bbuf[BLKSIZ];
p = buf;
while (len >= DENTSIZE) {
while (dp < dend && dp->d_fid.f_num == 0)
dp++;
if (dp >= dend) {
bno++;
dp = (struct directory *)bbuf;
if ((r = f11rblk(f, bno, bbuf)) <= 0)
break;
}
op = p;
p = itoa(p, dp->d_fid.f_num);
*p++ = '\t';
p = r50toa(p, dp->d_fname.f_nam[0]);
p = r50toa(p, dp->d_fname.f_nam[1]);
p = r50toa(p, dp->d_fname.f_nam[2]);
while (p[-1] == ' ')
--p;
*p++ = '.';
p = r50toa(p, dp->d_fname.f_typ);
while (p[-1] == ' ')
--p;
*p++ = '.';
p = itoa(p, dp->d_fname.f_ver);
*p++ = 0;
len -= p - op;
dp++;
}
if (p == buf && r < 0) {
fserrno = RFEIO;
return (-1);
}
*offp = (bno * BLKSIZ) + (char *)dp - bbuf;
return (p - buf);
}
/*
* f11 to rf file attributes
* -- temporary permission hack:
* turn apparent f11 other to asserted unix other group
*/
#define F11OTHER (-1)
static
htorf(f, h)
register Rfile *f;
register struct header *h;
{
f->ino = h->h_fnum;
f->dev = 0;
f->mode = htouperm(h->h_fpro);
if (h->h_ident.i_fnam.f_typ != dirtyp)
f->type = RFTREG;
else {
f->mode |= (f->mode & 0444)>>2; /* copy `read' into `execute' */
f->type = RFTDIR;
}
f->nlink = 1;
f->uid = h->h_fown.u_prog;
f->gid = h->h_fown.u_proj;
if (f->gid == F11OTHER)
f->gid = UXOTHER;
f->rdev = 0;
f->size = hfilesize(h);
f->ta = 0;
f->tm = htoutime(h->h_ident.i_rvdt);
f->tc = htoutime(h->h_ident.i_crdt); /* wrong, but let it stand */
if (f->tm == 0)
f->tm = f->tc;
}
/*
* number to string
*/
static char digits[] = "0123456789";
static char *
itoa(s, n)
register char *s;
register unsigned int n;
{
register int d;
if ((d = n / 10) == 0)
*s++ = digits[n];
else {
s = itoa(s, d);
*s++ = digits[n % 10];
}
return (s);
}