From 55cd25850a312a0b61192ba455908a8bcfe0152b Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Mon, 9 Oct 2000 19:14:34 +0000 Subject: Added process-stuff in procfs. Added a check for a protocol "psion" in /etc/services --- plpnfsd/builtins.h | 25 ++- plpnfsd/main.cc | 129 ++++++++++++++ plpnfsd/mp_pfs_ops.c | 468 +++++++++++++++++++++++++++++++++++++++++---------- plpnfsd/rfsv_api.h | 1 + 4 files changed, 532 insertions(+), 91 deletions(-) diff --git a/plpnfsd/builtins.h b/plpnfsd/builtins.h index 64b2823..644f18b 100644 --- a/plpnfsd/builtins.h +++ b/plpnfsd/builtins.h @@ -5,7 +5,21 @@ #ifndef _BUILTINS_H_ #define _BUILTINS_H_ +struct builtin_node_t; + +typedef struct builtin_child_t { + struct builtin_child_t *next; + struct builtin_node_t *node; +} builtin_child; + +/** + * Support for procfs-like builtin virtual files/directories + */ typedef struct builtin_node_t { + struct builtin_node_t *next; + struct builtin_node_t *parent; + builtin_child *childs; + char *private_data; char *name; unsigned long flags; long attr; @@ -14,20 +28,27 @@ typedef struct builtin_node_t { long (*read)(struct builtin_node_t *node, char *buf, unsigned long offset, long len); long (*write)(struct builtin_node_t *node, char *buf, unsigned long offset, long len); long (*sattr)(struct builtin_node_t *node, unsigned long sa, unsigned long da); + long (*getlinks)(struct builtin_node_t *node); + long (*getdents)(struct builtin_node_t *node, dentry **entries); } builtin_node; #define BF_EXISTS_ALWAYS 1 #define BF_NOCACHE 2 +#define BF_ISPROCESS 4 /** * Register a builtin handler for an entry in /proc */ -extern int register_builtin(builtin_node *); +builtin_node *register_builtin(char *parent, builtin_node *node); /** * Deregister a previously registered handler. */ -extern int unregister_builtin(char *); +extern int unregister_builtin(builtin_node *); + +extern char *builtin_path(builtin_node *node); +extern long generic_getlinks(builtin_node *node); +extern long generic_getdents(builtin_node *node, dentry **entries); #endif /* _BUILTINS_H_ */ diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc index ca31a26..da515f5 100644 --- a/plpnfsd/main.cc +++ b/plpnfsd/main.cc @@ -80,6 +80,127 @@ long rpcs_ownerSize(builtin_node *) { return owner.getLen() - 1; } +static long psread(builtin_node *node, char *buf, unsigned long offset, long len) { + char *s = (char *)node->private_data; + + if (!s) + return 0; + if (offset >= ((unsigned long)node->size - 1)) + return 0; + s += offset; + int sl = node->size - offset; + if (sl > len) + sl = len; + strncpy(buf, s, sl); + return sl; +} + +long rpcs_ps() { + Enum res; + bufferArray psbuf; + + if (!rpcs_isalive()) + return -1; + res = r->queryDrive('C', psbuf); + if (res != rfsv::E_PSI_GEN_NONE) + return -1; + while (!psbuf.empty()) { + builtin_node *dn; + builtin_node *fn1; + builtin_node *fn2; + builtin_node *bn; + char bname[40]; + + bufferStore bs = psbuf.pop(); + bufferStore bs2 = psbuf.pop(); + sprintf(bname, "%d", bs.getWord(0)); + + dn = (builtin_node *)malloc(sizeof(builtin_node)); + if (!dn) + return -1; + fn1 = (builtin_node *)malloc(sizeof(builtin_node)); + if (!fn1) { + free(dn); + return -1; + } + fn2 = (builtin_node *)malloc(sizeof(builtin_node)); + if (!fn2) { + free(fn1); + free(dn); + return -1; + } + memset(dn, 0, sizeof(builtin_node)); + memset(fn1, 0, sizeof(builtin_node)); + memset(fn2, 0, sizeof(builtin_node)); + + /** + * Directory, named by the PID + */ + dn->flags = BF_ISPROCESS; + dn->name = bname; + dn->attr = PSI_A_DIR; + dn->getlinks = generic_getlinks; + dn->getdents = generic_getdents; + + fn1->name = "cmd"; + fn1->attr = PSI_A_READ | PSI_A_RDONLY; + fn1->private_data = (char *)malloc(strlen(bs.getString(2))+2); + if (!fn1->private_data) { + free(fn1); + free(fn2); + free(dn); + return -1; + } + fn1->read = psread; + sprintf(fn1->private_data, "%s\n", bs.getString(2)); + fn1->size = strlen(fn1->private_data); + + fn2->name = "args"; + fn2->attr = PSI_A_READ | PSI_A_RDONLY; + fn2->private_data = (char *)malloc(strlen(bs2.getString())+2); + if (!fn2->private_data) { + free(fn1->private_data); + free(fn1); + free(fn2); + free(dn); + return -1; + } + fn2->read = psread; + sprintf(fn2->private_data, "%s\n", bs2.getString()); + fn2->size = strlen(fn2->private_data); + + if (!(bn = register_builtin("proc", dn))) { + free(fn1->private_data); + free(fn1); + free(fn2->private_data); + free(fn2); + free(dn); + return -1; + } + strcpy(bname, builtin_path(bn)); + if (!register_builtin(bname, fn1)) { + free(fn1->private_data); + free(fn1); + free(fn2->private_data); + free(fn2); + unregister_builtin(bn); + free(dn); + return -1; + } + if (!register_builtin(bname, fn2)) { + free(fn2->private_data); + free(fn2); + unregister_builtin(bn); + free(dn); + return -1; + } + free(fn1); + free(fn2); + free(dn); + } + return 0; +} + long rfsv_isalive() { if (!a) { if (!(a = rf->create(true))) @@ -343,6 +464,11 @@ int main(int argc, char**argv) { int verbose = 0; int status = 0; + struct servent *se = getservbyname("psion", "tcp"); + endservent(); + if (se != 0L) + sockNum = ntohs(se->s_port); + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-p") && i + 1 < argc) { sockNum = atoi(argv[++i]); @@ -352,12 +478,15 @@ int main(int argc, char**argv) { user = argv[++i]; } else if (!strcmp(argv[i], "-v")) { verbose++; + } else if (!strcmp(argv[i], "-D")) { + debug++; } else if (!strcmp(argv[i], "-V")) { cout << "plpnfsd version " << VERSION << endl; exit(0); } else usage(); } + signal(SIGPIPE, SIG_IGN); skt = new ppsocket(); if (!skt->connect(NULL, sockNum)) { diff --git a/plpnfsd/mp_pfs_ops.c b/plpnfsd/mp_pfs_ops.c index a222776..35bae4a 100644 --- a/plpnfsd/mp_pfs_ops.c +++ b/plpnfsd/mp_pfs_ops.c @@ -128,15 +128,291 @@ static long generic_sattr(builtin_node *p, unsigned long sa, unsigned long da) { return 0; } -static builtin_node builtins[] = { - { "owner", 0, PSI_A_READ | PSI_A_RDONLY, 0, rpcs_ownerSize, rpcs_ownerRead, NULL, NULL }, - { "debuglevel", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr }, - { "acache", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr }, - { "dcache", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr }, - { "unixowner", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, user_getsize, user_read, user_write, NULL }, - { "exit", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 5, NULL, exit_read, exit_write, NULL }, +long generic_getlinks(builtin_node *node) { + builtin_child *cp = node->childs; + long ncount = 0; + + while (cp) { + if ((cp->node->flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) + ncount++; + cp = cp->next; + } + return ncount; +} + +long generic_getdents(builtin_node *node, dentry **e) { + builtin_child *cp = node->childs; + + while (cp) { + if ((cp->node->flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) { + dentry *tmp = (dentry *)malloc(sizeof(dentry)); + if (!tmp) + return -1; + tmp->time = time(0); + tmp->size = cp->node->getsize ? cp->node->getsize(cp->node) : cp->node->size; + tmp->attr = cp->node->attr; + tmp->name = strdup(cp->node->name); + tmp->next = *e; + *e = tmp; + } + cp = cp->next; + } + return 0; +} + +static builtin_node *builtins = NULL; +static void dump_proctree(builtin_node *n); + +static void clear_procs(builtin_child **childs) { + builtin_child **cp = childs; + + debuglog("Before clear_procs\n"); + dump_proctree(builtins); + while (*cp) { + if ((*cp)->node->flags & BF_ISPROCESS) { + builtin_child *tmp = *cp; + *cp = (*cp)->next; + unregister_builtin(tmp->node); + free(tmp); + } else + cp = &((*cp)->next); + } + debuglog("After clear_procs\n"); + dump_proctree(builtins); +} + +static time_t procs_stamp = 0; +static long procs_keep = 10; + +static long proc_getlinks(builtin_node *node) { + builtin_child *cp; + long ncount = 0; + + if ((time(0) - procs_stamp) > procs_keep) { + debuglog("PROCESSLIST\n"); + clear_procs(&node->childs); + rpcs_ps(); + procs_stamp = time(0); + debuglog("After rpcs_ps\n"); + dump_proctree(builtins); + } + cp = node->childs; + while (cp) { + if ((cp->node->flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) + ncount++; + cp = cp->next; + } + return ncount; +} + +static long proc_getdents(builtin_node *node, dentry **e) { + builtin_child *cp = node->childs; + + while (cp) { + if ((cp->node->flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) { + dentry *tmp = (dentry *)malloc(sizeof(dentry)); + if (!tmp) + return -1; + tmp->time = time(0); + tmp->size = cp->node->getsize ? cp->node->getsize(cp->node) : cp->node->size; + tmp->attr = cp->node->attr; + tmp->name = strdup(cp->node->name); + tmp->next = *e; + *e = tmp; + } + cp = cp->next; + } + return 0; +} + + +static builtin_node proc_node = { + NULL, NULL, NULL, NULL, "proc", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_DIR, 0, NULL, NULL, NULL, NULL, proc_getlinks, proc_getdents }; -static int num_builtins = sizeof(builtins) / sizeof(builtin_node); + +static builtin_node fixed_builtins[] = { + { NULL, NULL, NULL, NULL, "owner", 0, PSI_A_READ | PSI_A_RDONLY, 0, rpcs_ownerSize, rpcs_ownerRead, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, "debuglevel", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr, NULL, NULL }, + { NULL, NULL, NULL, NULL, "acache", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr, NULL, NULL }, + { NULL, NULL, NULL, NULL, "dcache", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, param_getsize, param_read, param_write, generic_sattr, NULL, NULL }, + { NULL, NULL, NULL, NULL, "unixowner", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 0, user_getsize, user_read, user_write, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, "exit", BF_EXISTS_ALWAYS|BF_NOCACHE, PSI_A_READ, 5, NULL, exit_read, exit_write, NULL, NULL, NULL }, +}; +static int num_fixed_builtins = sizeof(fixed_builtins) / sizeof(builtin_node); + +static void dump_proctree(builtin_node *n) { + while (n) { + if (n->name) + debuglog("node@%p, \"%s\"\n", n, n->name); + else + debuglog("node@%p, \"(null)\"\n", n); + if (n->childs) { + builtin_child *c = n->childs; + debuglog("Childs:\n"); + while (c) { + if (c->node) + debuglog(" %s\n", c->node->name ? c->node->name : "(null)"); + c = c->next; + } + } + if (n->parent) + debuglog("Parent: %s\n", n->parent->name); + n = n->next; + } +} + +static int add_child(builtin_child **childs, builtin_node *node) { + builtin_child *newc = malloc(sizeof(builtin_child)); + if (!newc) { + errorlog("Out of memory in add_child %s\n", node->name); + return -1; + } + newc->next = *childs; + newc->node = node; + *childs = newc; + return 0; +} + +static int remove_child(builtin_child **childs, builtin_node *node) { + builtin_child **cp = childs; + + if (debug) + debuglog("remove_child %s\n", node->name); + while (*cp) { + if ((*cp)->node == node) { + builtin_child *tmp = *cp; + *cp = (*cp)->next; + free(tmp); + return 0; + } + cp = &((*cp)->next); + } + return -1; +} + +char *builtin_path(builtin_node *node) { + static char tmp[1024]; + char tmp2[1024]; + + strcpy(tmp, node->name); + node = node->parent; + while (node) { + sprintf(tmp2, "%s\\%s", node->name, tmp); + strcpy(tmp, tmp2); + node = node->parent; + } + return tmp; +} + +int unregister_builtin(builtin_node *node) { + builtin_child *cp = node->childs; + builtin_node **n; + + /** + * Unlink and free childs. + */ + if (debug) + debuglog("unregister_builtin %s\n", node->name); + + while (cp) { + builtin_child *old = cp; + cp->node->parent = 0L; + unregister_builtin(cp->node); + cp = cp->next; + free(old); + } + /** + * Unlink ourselves from parent child list. + */ + if (node->parent) + remove_child(&node->parent->childs, node); + n = &builtins; + while (*n) { + if (*n == node) { + *n = node->next; + break; + } else + n = &(*n)->next; + } + if (node->name) + free(node->name); + if (node->private_data) + free(node->private_data); + free(node); + return 0; +} + +builtin_node *register_builtin(char *parent, builtin_node *node) { + builtin_node *bn; + builtin_node *parent_node = 0L; + + debuglog("register_builtin node=%p\n", node); + if (!node) { + errorlog("register_builtin called with NULL node\n"); + return NULL; + } + if (!node->name) { + errorlog("register_builtin called without name\n"); + return NULL; + } + if (parent) { + debuglog("register_builtin parent: %s\n", parent); + for (bn = builtins; bn; bn = bn->next) { + debuglog("cmp parent: %s %s\n", builtin_path(bn), parent); + if (!strcmp(builtin_path(bn), parent)) { + debuglog("cmp parent found bn=%s\n", bn->name); + break; + } + } + if (!bn) { + errorlog("register_builtin for %s called with nonexistent parent %s\n", node->name, parent); + return NULL; + } + parent_node = bn; + } + bn = malloc(sizeof(builtin_node)); + if (!bn) { + errorlog("out of memory while registering builtin %s\n", node->name); + return NULL; + } + memset(bn, 0, sizeof(builtin_node)); + bn->name = strdup(node->name); + if (!bn->name) { + errorlog("out of memory while registering builtin %s\n", node->name); + free(bn); + return NULL; + } + if (parent_node) + debuglog("register_builtin %s in %s\n", node->name, builtin_path(parent_node)); + else + debuglog("register_builtin %s\n", node->name); + bn->parent = parent_node; + bn->flags = node->flags; + bn->attr = node->attr; + bn->size = node->size; + bn->getsize = node->getsize; + bn->read = node->read; + bn->write = node->write; + bn->sattr = node->sattr; + bn->getlinks = node->getlinks; + bn->getdents = node->getdents; + bn->private_data = node->private_data; + if (parent_node) { + debuglog("Add child %s in %s\n", bn->name, bn->parent->name); + if (add_child(&(parent_node->childs), bn)) { + errorlog("Couldn't add child %s\n", bn->name); + free(bn->name); + free(bn); + return NULL; + } + } + bn->next = builtins; + builtins = bn; + debuglog("After register_builtin\n"); + dump_proctree(builtins); + debuglog("register_builtin new node=%p\n", bn); + return bn; +} /* * Nfsd returned NFSERR_STALE if the psion wasn't present, but I didn't like @@ -308,12 +584,25 @@ pattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode) fp->mtime.seconds = fp->ctime.seconds = fp->atime.seconds; } +static int proc_top = 0; + static int query_devices() { device *dp, *np; int link_count = 2; /* set the root link count */ + if (!proc_top) { + int i; + if (register_builtin(NULL, &proc_node)) { + for (i = 0; i < num_fixed_builtins; i++) + if (register_builtin(proc_node.name, &fixed_builtins[i])) + proc_top++; + } else + errorlog("Couldn't register /proc\n"); + if (proc_top != num_fixed_builtins) + proc_top = 0; + } if (query_cache) return 0; for (dp = devices; dp; dp = np) { @@ -336,15 +625,16 @@ mp_dircount(p_inode *inode, long *count) { dentry *e = NULL; long ret; + builtin_node *bn; *count = 0; debuglog("dircount: %s\n", inode->name); - if (!strcmp(inode->name, "proc")) { - int i; - for (i = 0; i < num_builtins; i++) - if ((builtins[i].flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) - (*count)++; - return 0; + for (bn = builtins; bn; bn = bn->next) { + if ((!strcmp(builtin_path(bn), inode->name) && (bn->attr & PSI_A_DIR))) { + if (bn->getlinks) + *count = bn->getlinks(bn); + return 0; + } } debuglog("RFSV dir %s\n", inode->name); if ((ret = rfsv_dir(dirname(inode->name), &e))) @@ -391,18 +681,6 @@ nfsproc_getattr_2(struct nfs_fh *fh) if ((cp = search_cache(attrcache, inode->inode))) { debuglog("getattr: cache hit\n"); *fp = cp->attr; /* gotcha */ -#if 0 - if (fp->type == NFDIR) { - if (mp_dircount(inode, &dcount)) { - res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; - return &res; - } - if (fp->nlink != (dcount + 2)) - fp->mtime.seconds = time(0); - fp->nlink = dcount + 2; - cp->attr = *fp; - } -#endif return &res; } l = strlen(inode->name); @@ -414,15 +692,6 @@ nfsproc_getattr_2(struct nfs_fh *fh) if (query_devices()) /* root inode and proc is always there */ root_fattr.nlink = 3; *fp = root_fattr; - } else if (l == 4 && (!strcmp(inode->name, "proc"))) { - debuglog("getattr:proc (%#o)\n", root_fattr.mode); - *fp = root_fattr; - fp->fileid = inode->inode; - fp->type = NFDIR; - mp_dircount(inode, &dcount); - if (fp->nlink != (dcount + 2)) - fp->mtime.seconds = time(0); - fp->nlink = dcount + 2; } else if (l == 2 && inode->name[1] == ':') { debuglog("getattr:device\n"); res.status = NO_PSION; @@ -453,16 +722,19 @@ nfsproc_getattr_2(struct nfs_fh *fh) } } } else { - int i; - - for (i = 0; i < num_builtins; i++) { - if (!strcmp(inode->name, build_path("proc", builtins[i].name))) { - pattr = builtins[i].attr; - psize = (builtins[i].getsize != NULL) ? builtins[i].getsize(&builtins[i]) : builtins[i].size; + builtin_node *bn; + + for (bn = builtins; bn; bn = bn->next) { + if (!strcmp(inode->name, builtin_path(bn))) { + pattr = bn->attr; + if (pattr & PSI_A_DIR) + psize = 0; + else + psize = (bn->getsize) ? bn->getsize(bn) : bn->size; ptime = time(0); res.status = NFS_OK; builtin = 1; - if (builtins[i].flags && BF_NOCACHE) + if (bn->flags && BF_NOCACHE) builtin++; break; } @@ -621,37 +893,44 @@ nfsproc_readdir_2(readdirargs *ra) addentry(ra, &cp, &searchinode, get_nam(dp->name)->inode, n); } } else { + builtin_node *bn; + int builtin = 0; dentry *e = NULL; debuglog("nfsdir: dir\n"); - if (!strcmp(inode->name, "proc")) { - int i; - for (i = 0; i < num_builtins; i++) - if ((builtins[i].flags & BF_EXISTS_ALWAYS) || rfsv_isalive()) { - int ni = get_nam(build_path(inode->name, builtins[i].name))->inode; - addentry(ra, &cp, &searchinode, ni, builtins[i].name); + + for (bn = builtins; bn ; bn = bn->next) + if (!strcmp(inode->name, builtin_path(bn))) { + if (bn->attr & PSI_A_DIR) { + if (bn->getdents) + bn->getdents(bn, &e); + builtin = 1; + } else { + res.status = NFSERR_NOTDIR; + return &res; } - } else { + } + if (!builtin) { debuglog("RFSV dir2 %s\n", inode->name); if (rfsv_dir(dirname(inode->name), &e)) { res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; return &res; } - while (e) { - fattr fp; - dentry *o; - int ni; + } + while (e) { + fattr fp; + dentry *o; + int ni; - bp = filname(e->name); - ni = get_nam(build_path(inode->name, bp))->inode; - addentry(ra, &cp, &searchinode, ni, (char *) bp); - free(e->name); - pattr2attr(e->attr, e->size, e->time, &fp, ni); - if (rfsv_isalive()) - add_cache(&attrcache, ni, &fp); - o = e; - e = e->next; - free(o); - } + bp = filname(e->name); + ni = get_nam(build_path(inode->name, bp))->inode; + addentry(ra, &cp, &searchinode, ni, (char *) bp); + free(e->name); + pattr2attr(e->attr, e->size, e->time, &fp, ni); + if (rfsv_isalive()) + add_cache(&attrcache, ni, &fp); + o = e; + e = e->next; + free(o); } } @@ -666,7 +945,7 @@ nfsproc_setattr_2(sattrargs *sa) static struct attrstat res; p_inode *inode = get_num(fh2inode(sa->file.data)); fattr *fp; - int bi; + builtin_node *bn; int builtin = 0; if (!inode) { @@ -680,19 +959,18 @@ nfsproc_setattr_2(sattrargs *sa) return &res; fp = &res.attrstat_u.attributes; - for (bi = 0; bi < num_builtins; bi++) { - if (!strcmp(inode->name, build_path("proc", builtins[bi].name))) { + for (bn = builtins; bn; bn = bn->next) + if (!strcmp(inode->name, builtin_path(bn))) { builtin = 1; break; } - } if ((fp->type == NFREG) && (sa->attributes.size != -1) && (sa->attributes.size != fp->size)) { debuglog("RFSV setsize %s %d\n", inode->name, sa->attributes.size); if (builtin) { - if (builtins[bi].attr & PSI_A_RDONLY) { + if (bn->attr & PSI_A_RDONLY) { res.status = NFSERR_ACCES; return &res; } @@ -726,7 +1004,7 @@ nfsproc_setattr_2(sattrargs *sa) attr2pattr(sa->attributes.mode, fp->mode, &psisattr, &psidattr); debuglog("RFSV setattr %s %d %d\n", inode->name, psisattr, psidattr); if (builtin) { - if ((builtins[bi].sattr == NULL) || builtins[bi].sattr(&builtins[bi], psisattr, psidattr)) { + if ((bn->sattr == NULL) || bn->sattr(bn, psisattr, psidattr)) { res.status = NFSERR_ACCES; return &res; } @@ -874,7 +1152,7 @@ nfsproc_read_2(struct readargs *ra) long psize; long ptime; int len = 0; - int bi; + builtin_node *bn; int builtin = 0; if (!inode) { @@ -897,12 +1175,19 @@ nfsproc_read_2(struct readargs *ra) debuglog("RFSV read %s\n", inode->name); - for (bi = 0; bi < num_builtins; bi++) { - if (!strcmp(inode->name, build_path("proc", builtins[bi].name))) { - if (builtins[bi].read != NULL) { - len = builtins[bi].read(&builtins[bi], rop, ra->offset, ra->count); + for (bn = builtins; bn; bn = bn->next) { + if (!strcmp(inode->name, builtin_path(bn))) { + if (bn->attr & PSI_A_DIR) { + res.status = NFSERR_ISDIR; + return &res; + } + if (bn->read) { + len = bn->read(bn, rop, ra->offset, ra->count); builtin = 1; break; + } else { + res.status = NFSERR_IO; + return &res; } } } @@ -919,8 +1204,8 @@ nfsproc_read_2(struct readargs *ra) // Problem: if an epoc process is enlarging the file, we wont recognize it debuglog("RFSV getattr %s\n", inode->name); if (builtin) { - pattr = builtins[bi].attr; - psize = (builtins[bi].getsize != NULL) ? builtins[bi].getsize(&builtins[bi]) : builtins[bi].size; + pattr = bn->attr; + psize = (bn->getsize) ? bn->getsize(bn) : bn->size; ptime = time(0); } else rfsv_getattr(inode->name, &pattr, &psize, &ptime); @@ -1034,7 +1319,8 @@ nfsproc_write_2(writeargs *wa) fattr *fp; struct attrstat *gres; int len = 0; - int i, dlen, doff; + int dlen, doff; + builtin_node *bn; if (!inode) { debuglog("write: stale fh\n"); @@ -1046,6 +1332,21 @@ nfsproc_write_2(writeargs *wa) dlen = wa->data.data_len; doff = wa->offset; + for (bn = builtins; bn ; bn = bn->next) { + if (!strcmp(inode->name, builtin_path(bn))) { + if (bn->attr & PSI_A_DIR) + res.status = NFSERR_ISDIR; + else { + debuglog("builtin write %s %d@%d\n", inode->name, dlen, doff); + if (bn->write) { + int l = bn->write(bn, (unsigned char *)wa->data.data_val, doff, dlen); + res.status = (l == dlen) ? NFS_OK : NFSERR_IO; + } else + res.status = NFSERR_ACCES; + } + return &res; + } + } /* fetch attributes */ if ((cp = search_cache(attrcache, inode->inode)) == 0) { gres = nfsproc_getattr_2((struct nfs_fh *) wa->file.data); @@ -1068,17 +1369,6 @@ nfsproc_write_2(writeargs *wa) res.attrstat_u.attributes = *fp; - for (i = 0; i < num_builtins; i++) { - if (!strcmp(inode->name, build_path("proc", builtins[i].name))) { - debuglog("builtin write %s %d@%d\n", inode->name, dlen, doff); - if (builtins[i].write != NULL) { - int l = builtins[i].write(&builtins[i], (unsigned char *)wa->data.data_val, doff, dlen); - res.status = (l == dlen) ? NFS_OK : NFSERR_IO; - } else - res.status = NFSERR_ACCES; - return &res; - } - } if (addwritecache(cp, doff, dlen, (unsigned char *) wa->data.data_val)) { res.status = NFS_OK; return &res; diff --git a/plpnfsd/rfsv_api.h b/plpnfsd/rfsv_api.h index b780735..5a9072e 100644 --- a/plpnfsd/rfsv_api.h +++ b/plpnfsd/rfsv_api.h @@ -32,6 +32,7 @@ extern long rfsv_closecached(void); extern long rpcs_ownerRead(builtin_node *, char *buf, unsigned long offset, long len); extern long rpcs_ownerSize(builtin_node *); +extern long rpcs_ps(); /* File attributes, C-style */ #define PSI_A_RDONLY 0x0001 -- cgit v1.2.3