|
|
researchv9-SUN3(old)
/* when the client reads directories, some work may be required */
#include "share.h"
file tfile;
int roottag;
unsigned char *slash;
openit()
{ int n;
if(!openfile()) {
if(client.namiflags != NBROOT)
client.errno = ENOENT;
return;
}
n = gimmefile();
if(n < 0)
return;
files[n].fd = tfile.fd;
files[n].flags = tfile.flags;
if(stat(nmbuf, &files[n].stb) < 0) {
client.errno = errno; /* must have been set? */
close(tfile.fd);
return; /* files[n].tag is 0 still */
}
checkdev(files[n].stb.st_dev);
files[n].tag = maketag(&files[n].stb);
if(setname(n))
return;
checkdupl(n);
retnami(n);
}
creatit()
{ int n, fd;
if((n = openfile()) && client.flags == NI_NXCREAT) {
client.errno = EEXIST;
close(tfile.fd);
return;
}
if(n) { /* exists, creat it */
if(writeperm())
return;
n = creat(nmbuf, (int)client.mode);
if(n >= 0)
close(n);
else {
client.errno = errno;
return;
}
n = gimmefile();
if(n < 0)
return;
files[n].fd = tfile.fd;
files[n].flags = tfile.flags;
if(stat(nmbuf, &files[n].stb) < 0) {
client.errno = errno;
close(tfile.fd);
return;
}
checkdev(files[n].stb.st_dev);
files[n].tag = maketag(&files[n].stb);
if(setname(n))
return;
checkdupl(n); /* here it is important too to get the new one */
retnami(n);
return;
}
/* doesn't exist, creat it */
if(client.namiflags == NBROOT)
return; /* can't creat the root (is errno set?) */
n = gimmefile();
if(n < 0)
return;
if(dirwriteperm())
return;
if((client.mode & S_IFMT)) { /* no symbolic links or mknods */
error("client: client.mode 0%o\n", client.mode);
client.errno = EXDEV;
return;
}
if((fd = creat(nmbuf, client.mode)) < 0) {
client.errno = errno;
return;
}
if(chown(nmbuf, clientuid(), clientgid()) < 0)
return;
files[n].fd = open(nmbuf, 2);
if(files[n].fd < 0) {
files[n].fd = open(nmbuf, 0);
if(files[n].fd < 0) {
client.errno = errno;
unlink(nmbuf);
close(fd);
return;
}
files[n].flags = 1;
}
close(fd); /* fd was write-only */
if(stat(nmbuf, &files[n].stb) < 0) { /* it was there a second ago */
client.errno = errno;
unlink(nmbuf);
close(files[n].fd);
return;
}
checkdev(files[n].stb.st_dev);
files[n].tag = maketag(&files[n].stb);
if(setname(n))
return;
retnami(n);
}
linkit()
{ int i, n;
if(dirwriteperm())
return;
if(openfile()) {
client.errno = EEXIST;
close(tfile.fd);
return;
}
for(i = 0; i < FILES; i++)
if(files[i].tag == client.ino)
break;
if(i >= FILES) { /* can't happen */
error("can't happen: linkit %s, no tag %x\n", nmbuf, client.ino);
client.errno = EXDEV; /* not really */
return;
}
debug("linking %s to %s\n", files[i].name, nmbuf);
n = link(files[i].name, nmbuf);
if(n < 0) {
debug("link errno %d\n", errno);
client.errno = errno;
}
}
mkdirit()
{ int n;
if(openfile()) {
client.errno = EEXIST;
close(tfile.fd); /* how does entry get tossed? */
return;
}
if(client.namiflags == NBROOT)
return;
if(dirwriteperm())
return;
if(mkdir(nmbuf, client.mode) < 0) {
client.errno = errno;
return;
}
if(chown(nmbuf, clientuid(), clientgid()) < 0)
return;
}
rmdirit()
{
if(!openfile()) {
client.errno = EEXIST;
return;
}
close(tfile.fd);
if(dirwriteperm())
return;
if(rmdir(nmbuf) < 0)
client.errno = errno;
else
client.errno = 0;
}
delit()
{
if(!openfile()) {
client.errno = ENOENT;
close(tfile.fd);
return;
}
if(client.namiflags == NBROOT)
return;
close(tfile.fd);
if(dirwriteperm())
return;
if((tfile.stb.st_mode & S_IFMT) != S_IFREG) {
client.errno = EISDIR;
return;
}
if(unlink(nmbuf) < 0)
client.errno = errno;
else
client.errno = 0;
}
openfile()
{ unsigned char *p;
static struct stat statb;
int i;
slash = 0;
for(p = nmbuf; *p; ) {
for(; *p == '/'; p++)
slash = p;
if(*p == 0)
break;
*--p = 0;
i = stat(nmbuf, &statb);
if(i < 0) {
debug("openfile: stat %s (%d)\n", nmbuf, errno);
client.errno = errno;
return(0);
}
if(searchperm())
return(0);
*p++ = '/';
checkdev(statb.st_dev);
if(maketag(&statb) == roottag && p[0] == '.' && p[1] == '.'
&& (p[2] == 0 || p[2] == '/')) {
client.namiflags = NBROOT;
client.used = 2 + (p - nmbuf) - nmoffset;
debug("openfile: root used %d offset %d\n", client.used,
nmoffset);
return(0);
}
while(*p && *p != '/')
p++;
}
i = stat(nmbuf, &statb);
if(i < 0)
return(0);
tfile.fd = -1;
tfile.flags = 0;
tfile.stb = statb;
tfile.fd = open(nmbuf, 2);
if(tfile.fd < 0) {
tfile.fd = open(nmbuf, 0);
if(tfile.fd < 0)
return(0);
tfile.flags = 1;
}
return(1);
}
retnami(n)
{ file *t = files + n;
client.tag = t->tag;
client.ino = t->stb.st_ino;
client.dev = hostdev(t->stb.st_dev);
debug("retnami dev 0x%x ino %d tag 0x%x %s\n", client.dev, client.ino,
client.tag, t->name);
client.mode = t->stb.st_mode;
client.used = 0; /* ? */
client.nlink = t->stb.st_nlink;
client.uid = hostuid(t->stb.st_uid);
client.gid = hostgid(t->stb.st_gid);
client.size = t->stb.st_size; /* watch it! */
if(cray && client.size >= 0x80000000)
client.size = 0x7fffffff;
/* fortunately all known hosts agree on time */
client.ta = t->stb.st_atime - dtime;
client.tc = t->stb.st_ctime - dtime;
client.tm = t->stb.st_mtime - dtime;
}
gimmefile()
{ int i;
for(i = 0; i < FILES; i++)
if(files[i].tag == 0)
break;
if(i >= FILES) {
error("out of file structs %d\n", i);
client.errno = ENFILE;
return(-1);
}
files[i].flags = 0;
files[i].pos = 0;
return(i);
}
/* is this really an error to recover from? */
setname(n)
{ unsigned char *p;
p = (unsigned char *)malloc(strlen(nmbuf) + 1);
if(p == NULL) {
error("out of space on %s\n", nmbuf);
client.errno = ENOSPC;
return(-1);
}
strcpy(p, nmbuf);
files[n].name = p;
return(0);
}
checkdupl(n)
{ int i;
unsigned char *x;
/* if it duplicates someone we've got, toss the old one, but use its tag */
for(i = 0; i < FILES; i++) {
if(i == n)
continue;
if(files[i].tag != files[n].tag)
continue;
debug("ok: creat found dup %s\n", nmbuf);
if(strlen(files[i].name) < strlen(files[n].name)) {
x = files[n].name;
files[n].name = files[i].name;
free(x);
}
else
free(files[i].name);
close(files[i].fd);
files[i].tag = 0;
}
/* update device translation if necessary */
checkdev(files[n].stb.st_dev);
}
dev *devs;
int devlen, ndev;
checkdev(n)
{ int i;
for(i = 0; i < ndev; i++)
if(devs[i].hdev == n)
return;
if(ndev >= devlen) {
if(!devlen)
devs = (dev *) malloc((devlen = 10) * sizeof(dev));
else {
devlen *= 2;
devs = (dev *) realloc((char *)devs, devlen * sizeof(dev));
error("reallocated devs to %d entries\n", devlen);
}
if(!devs)
fatal("alloc of %d devs failed!\n", devlen);
}
if(ndev >= 256)
fatal("%d devs? (too many)\n", ndev);
devs[ndev].hdev = n;
devs[ndev].cdev = hisdev | ndev;
debug("devs[%d] %x->%x\n", ndev, n, hisdev | ndev);
ndev++;
}
addroot()
{ int n;
n = gimmefile();
files[n].name = (unsigned char *)"/";
files[n].fd = open("/", 2);
if(files[n].fd < 0) {
files[n].fd = open("/", 0);
if(files[n].fd < 0)
fatal("can't open root, errno %d\n", errno);
files[n].flags = 1;
}
if(stat("/", &files[n].stb) < 0)
fatal("stat root errno %d\n", errno);
checkdev(files[n].stb.st_dev);
files[n].tag = maketag(&files[n].stb);
roottag = files[n].tag;
debug("root %d, tag 0x%x\n", n, files[n].tag);
if(files[n].stb.st_ino != ROOTINO) /* which ROOTINO is this? */
error("client and host probably don't agree on rootino %d\n",
files[n].stb.st_ino);
}
maketag(s)
struct stat *s;
{ int tag;
tag = (hostdev(s->st_dev) << 16) | s->st_ino;
debug("maketag (%x,%x)->%x\n", s->st_dev, s->st_ino, tag);
return(tag);
}
#if cray == 1
#include "signal.h"
int crapsig;
char sysbuf[256];
mkdir(s)
char *s;
{ int pid, ret = 0;
if(!crapsig++)
signal(SIGCLD, SIG_IGN);
sprintf(sysbuf, "mkdir %s", s);
if(strlen(sysbuf) >= sizeof(sysbuf))
fatal("sysbuf overflow %s\n", sysbuf);
if((pid = fork()) == 0) {
setuid(clientuid());
setgid(clientgid());
exit(system(sysbuf));
}
wait(&ret);
if(!ret)
return(0);
errno = EPERM; /* who knows? */
return(-1);
}
rmdir(s)
char *s;
{
if(!crapsig++)
signal(SIGCLD, SIG_IGN);
sprintf(sysbuf, "rmdir %s", s);
if(strlen(sysbuf) >= sizeof(sysbuf))
fatal("sysbuf overflow in rmdir %s\n", sysbuf);
if(system(sysbuf) == 0)
return(0);
errno = EPERM; /* ? */
return(-1);
}
fchmod()
{
fatal("!!!fchmod called\n");
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.