diff options
| -rw-r--r-- | plpnfsd/builtins.h | 25 | ||||
| -rw-r--r-- | plpnfsd/main.cc | 129 | ||||
| -rw-r--r-- | plpnfsd/mp_pfs_ops.c | 468 | ||||
| -rw-r--r-- | 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<rfsv::errs> 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 | 
