diff options
Diffstat (limited to 'plpnfsd')
| -rw-r--r-- | plpnfsd/builtins.h | 33 | ||||
| -rw-r--r-- | plpnfsd/main.cc | 67 | ||||
| -rw-r--r-- | plpnfsd/mp_inode.c | 52 | ||||
| -rw-r--r-- | plpnfsd/mp_main.c | 78 | ||||
| -rw-r--r-- | plpnfsd/mp_mount.c | 82 | ||||
| -rw-r--r-- | plpnfsd/mp_pfs_ops.c | 443 | ||||
| -rw-r--r-- | plpnfsd/rfsv_api.h | 4 | 
7 files changed, 542 insertions, 217 deletions
diff --git a/plpnfsd/builtins.h b/plpnfsd/builtins.h new file mode 100644 index 0000000..64b2823 --- /dev/null +++ b/plpnfsd/builtins.h @@ -0,0 +1,33 @@ +/* + * $Id$ + */ + +#ifndef _BUILTINS_H_ +#define _BUILTINS_H_ + +typedef struct builtin_node_t { +	char *name; +	unsigned long flags; +	long attr; +	long size; +	long (*getsize)(struct builtin_node_t *node); +	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); +} builtin_node; + +#define BF_EXISTS_ALWAYS 1 +#define BF_NOCACHE       2 + +/** + * Register a builtin handler for an entry in /proc + */ +extern int register_builtin(builtin_node *); + +/** + * Deregister a previously registered handler. + */ +extern int unregister_builtin(char *); + +#endif /* _BUILTINS_H_ */ + diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc index 04e4936..ca31a26 100644 --- a/plpnfsd/main.cc +++ b/plpnfsd/main.cc @@ -16,7 +16,9 @@  #include "bool.h"  #include "rfsv.h" +#include "rpcs.h"  #include "rfsvfactory.h" +#include "rpcsfactory.h"  #include "bufferstore.h"  #include "bufferarray.h"  #include "ppsocket.h" @@ -31,12 +33,59 @@ static long  a_handle;  static long  a_offset;  static long  a_openmode; +static rpcs *r; +static rpcsfactory *rp; +static bufferStore owner; + +long rpcs_isalive() { +	long s; + +	if (!r) { +		if (!(r = rp->create(true))) +			return 0; +	} +	s = r->getStatus(); +	if (s == rfsv::E_PSI_FILE_DISC) +		r->reconnect(); +	return (r->getStatus() == rfsv::E_PSI_GEN_NONE); +} + +long rpcs_ownerRead(builtin_node *, char *buf, unsigned long  offset, long len) { + +	if (offset >= (owner.getLen() - 1)) +		return 0; +	const char *s = owner.getString(offset); +	int sl = strlen(s); +	if (sl > len) +		sl = len; +	strncpy(buf, s, sl); +	return sl; +} + +long rpcs_ownerSize(builtin_node *) { +	Enum<rfsv::errs> res; +	bufferArray a; + +	if (!rpcs_isalive()) +		return 0; +	res = r->getOwnerInfo(a); +	owner.init(); +	if (res == rfsv::E_PSI_GEN_NONE) { +		while (!a.empty()) { +			owner.addString(a.pop().getString()); +			owner.addByte('\n'); +		} +	} +	owner.addByte(0); +	return owner.getLen() - 1; +} +  long rfsv_isalive() {  	if (!a) {  		if (!(a = rf->create(true)))  			return 0;  	} -	return (a->getStatus() == 0); +	return (a->getStatus() == rfsv::E_PSI_GEN_NONE);  }  long rfsv_dir(const char *file, dentry **e) { @@ -287,6 +336,7 @@ void usage()  int main(int argc, char**argv) {  	ppsocket *skt; +	ppsocket *skt2;  	char *user = 0L;  	char *mdir = DMOUNTPOINT;  	int sockNum = DPORT; @@ -313,16 +363,25 @@ int main(int argc, char**argv) {  	if (!skt->connect(NULL, sockNum)) {  		cerr << "plpnfsd: could not connect to ncpd" << endl;  		status = 1; -	} else { +	} +	skt2 = new ppsocket(); +	if (!skt2->connect(NULL, sockNum)) { +		cerr << "plpnfsd: could not connect to ncpd" << endl; +		status = 1; +	} +	if (status == 0) {  		rf = new rfsvfactory(skt); +		rp = new rpcsfactory(skt2);  		a = rf->create(true); +		r = rp->create(true);  		openlog("plpnfsd", LOG_PID|LOG_CONS, LOG_DAEMON); -		if (a != NULL) +		if ((a != NULL) && (r != NULL))  			syslog(LOG_INFO, "connected, status is %d", status);  		else -			syslog(LOG_INFO, "could not create rfsv object, connect delayed"); +			syslog(LOG_INFO, "could not create rfsv or rpcs object, connect delayed");  		status = mp_main(verbose, mdir, user);  		delete a; +		delete r;  	}  	exit(status);  } diff --git a/plpnfsd/mp_inode.c b/plpnfsd/mp_inode.c index e52d5ae..2432dda 100644 --- a/plpnfsd/mp_inode.c +++ b/plpnfsd/mp_inode.c @@ -180,22 +180,21 @@ unsigned inode;  }  struct cache * -add_cache(root, inode, fp) -struct cache **root; -unsigned inode; -fattr *fp; -{ +add_cache(struct cache **root, unsigned int inode, fattr *fp) {  	struct cache *cp;  	if (debug)  		debuglog("add_cache %d\n", inode);  	cp = (struct cache *) malloc(sizeof(*cp)); -	cp->inode = inode; -	cp->attr = *fp; -	cp->dcache = 0; -	cp->actual_size = fp->size; -	cp->next = *root; -	*root = cp; +	if (cp != NULL) { +		cp->stamp = time(0); +		cp->inode = inode; +		cp->attr = *fp; +		cp->dcache = 0; +		cp->actual_size = fp->size; +		cp->next = *root; +		*root = cp; +	}  	return cp;  } @@ -247,10 +246,7 @@ unsigned int off, len;  }  void -rem_cache(root, inode) -struct cache **root; -unsigned inode; -{ +rem_cache(struct cache **root, unsigned int inode) {  	struct cache *cp, **cpp;  	if (debug) @@ -265,18 +261,24 @@ unsigned inode;  	free(cp);  } -void -clean_cache(root) -struct cache **root; -{ -	struct cache *cp, *cpn; +time_t cache_keep = 30; -	for (cp = *root; cp; cp = cpn) { -		cpn = cp->next; -		clean_dcache(cp); -		free(cp); +void +clean_cache(struct cache **root) { +	struct cache **cp = root; +	time_t now = time(0); + +	while (*cp) { +		if (force_cache_clean || ((now - (*cp)->stamp) > cache_keep)) { +			struct cache *old = *cp; +			if (debug) +				debuglog("clean_cache %d\n", (*cp)->inode); +			*cp = (*cp)->next; +			clean_dcache(old); +			free(old); +		} else +			cp = &(*cp)->next;  	} -	*root = 0;  }  char * diff --git a/plpnfsd/mp_main.c b/plpnfsd/mp_main.c index 80e3d82..e83e15a 100644 --- a/plpnfsd/mp_main.c +++ b/plpnfsd/mp_main.c @@ -16,6 +16,7 @@  #include <signal.h>  #include <fcntl.h>  #include <pwd.h> +#include <grp.h>  #include <stdarg.h>  #include <syslog.h>  #include <errno.h> @@ -40,6 +41,8 @@  extern void nfs_program_2();  int debug, exiting, query_cache = 0; +time_t devcache_keep = 120; +time_t devcache_stamp = 0;  fattr root_fattr =  { @@ -110,6 +113,59 @@ infolog(char *fmt, ...)  	return 0;  } +int force_cache_clean = 0; + +int set_owner(char *user, int logstdio) { +	struct passwd *pw = NULL; + +	if (user && *user) { +		if (!(pw = getpwnam(user))) { +			if (logstdio) +				fprintf(stderr, "User %s not found.\n", user); +			else +				errorlog("User %s not found.\n", user); +			endpwent(); +			return 1; +		} +		if (getuid() && pw->pw_uid != getuid()) { +			if (logstdio) +				fprintf(stderr, "Only root can set owner to someone other.\n"); +			else +				errorlog("Only root can set owner to someone other.\n"); +			endpwent(); +			return 1; +		} +	} else { +		if (!logstdio) { +			errorlog("Request to change owner with empty argument.\n"); +			return 1; +		} +		if (!(pw = getpwuid(getuid()))) { +			fprintf(stderr, "You don't exist, go away!\n"); +			endpwent(); +			return 1; +		} +	} +	if (pw) { +		if ((root_fattr.uid != pw->pw_uid) || (root_fattr.gid != pw->pw_gid)) { +			struct group *g = getgrgid(pw->pw_gid); +			char *gname = (g && g->gr_name && *(g->gr_name)) ? g->gr_name : "???"; + +			root_fattr.uid = pw->pw_uid; +			root_fattr.gid = pw->pw_gid; +			if (logstdio) +				printf("Owner set to %s.%s\n", pw->pw_name, gname); +			else +				infolog("Owner set to %s.%s\n", pw->pw_name, gname); +			endgrent(); +			force_cache_clean = 1; +			cache_flush(); +		} +	} +	endpwent(); +	return 0; +} +  int  mp_main(int verbose, char *dir, char *user)  { @@ -123,30 +179,22 @@ mp_main(int verbose, char *dir, char *user)  	int i; -	if (!(user = (char *) getenv("USER"))) -		user = (char *) getenv("logname"); -	if (user && *user) { -		if (!(pw = getpwnam(user))) { -			fprintf(stderr, "User %s not found.\n", user); -			return 1; -		} -	} else if (!(pw = getpwuid(getuid()))) { +	if (!(pw = getpwuid(getuid()))) {  		fprintf(stderr, "You don't exist, go away!\n");  		return 1;  	} -	if (getuid() && pw->pw_uid != getuid()) { -		fprintf(stderr, "%s? You must be kidding...\n", user); -		return 1; +	if (!user) { +		if (!(user = (char *) getenv("USER"))) +			user = (char *) getenv("logname");  	} -	root_fattr.uid = pw->pw_uid; -	root_fattr.gid = pw->pw_gid;  	endpwent(); - +	if (set_owner(user, 1)) +		return 1;  	gettimeofday(&tv, &tz);  	debug = verbose;  	if (debug) -		printf("plpnfsd: version %s, mounting on %s\n", VERSION, dir); +		printf("plpnfsd: version %s, mounting on %s ...\n", VERSION, dir);  	/* Check if mountdir is empty (or else you can overmount e.g /etc)  	   It is done here, because exit hangs, if hardware flowcontrol is diff --git a/plpnfsd/mp_mount.c b/plpnfsd/mp_mount.c index da5d2c8..b2fd3c8 100644 --- a/plpnfsd/mp_mount.c +++ b/plpnfsd/mp_mount.c @@ -139,9 +139,7 @@ hup_handler SIGARG  	exiting = 5;  }; -static void -doexit() -{ +static void doexit() {  #ifndef DONT_UPDATE_MTAB  	FILE *fpin, *fpout;  #if defined(sun) && defined(__SVR4) @@ -216,6 +214,45 @@ doexit()  	exit(0);  } +void cache_flush() { +	struct cache *cp; +	struct dcache *dcp; + +	/* +	 * Solaris sends blocks in a way which is not very pleasent +	 * for us. It sends blocks 0,1,2,3,4,5,6, then 9,10,11 and +	 * do on. A little bit later block 7 and 8 arrives. This "bit" +	 * is more that 2 seconds, it is about 6 seconds. It occurs, +	 * if we're rewriting a file. We set MAXWRITE to 15, meaning +	 * that we are waiting for 30 seconds to receive the missing +	 * blocks. +	 */ + +#define MAXWRITE 15 + +	int doclean = 1; +	for (cp = attrcache; cp; cp = cp->next) +		for (dcp = cp->dcache; dcp; dcp = dcp->next) +			if (dcp->towrite) { +				debuglog("waiting for block %d in %s to write (%d)\n", +					       dcp->offset, get_num(cp->inode)->name, dcp->towrite); +				if (++dcp->towrite <= MAXWRITE) +					doclean = 0;	/* Wait with cleaning */ +			} +	if (doclean || force_cache_clean) { +		for (cp = attrcache; cp; cp = cp->next) +			for (dcp = cp->dcache; dcp; dcp = dcp->next) +				if (dcp->towrite) +					errorlog("PLPNFSD WARNING: file %s block at %d not written\n", +					       get_num(cp->inode)->name, dcp->offset); +		clean_cache(&attrcache); +		if (force_cache_clean || ((time(0) - devcache_stamp) > devcache_keep)) +			query_cache = 0;	/* clear the GETDENTS "cache". */ +		rfsv_closecached(); +		force_cache_clean = 0; +	} +} +  void  mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh)  { @@ -515,7 +552,7 @@ mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh)  	}  /*** Third part: let's go */ -	infolog("to stop the server do \"ls %s/exit\".\n", mntdir); +	infolog("to stop the server do \"echo stop > %s/proc/exit\".\n", mntdir);  #if defined(sun) && !defined(__SVR4)  	dtbsize = _rpc_dtablesize(); @@ -535,8 +572,6 @@ mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh)  	for (;;) {  		fd_set readfd;  		struct timeval tv; -		struct cache *cp; -		struct dcache *dcp;  		readfd = svc_fdset;  		tv.tv_sec = 2; @@ -553,46 +588,21 @@ mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh)  		if (exiting)  			doexit(); -		/* -		 * Solaris sends blocks in a way which is not very pleasent -		 * for us. It sends blocks 0,1,2,3,4,5,6, then 9,10,11 and -		 * do on. A little bit later block 7 and 8 arrives. This "bit" -		 * is more that 2 seconds, it is about 6 seconds. It occurs, -		 * if we're rewriting a file. We set MAXWRITE to 15, meaning -		 * that we are waiting for 30 seconds to receive the missing -		 * blocks. -		 */ +		cache_flush(); -#define MAXWRITE 15 -		doclean = 1; -		for (cp = attrcache; cp; cp = cp->next) -			for (dcp = cp->dcache; dcp; dcp = dcp->next) -				if (dcp->towrite) { -					debuglog("waiting for block %d in %s to write (%d)\n", -						       dcp->offset, get_num(cp->inode)->name, dcp->towrite); -					if (++dcp->towrite <= MAXWRITE) -						doclean = 0;	/* Wait with cleaning */ -				}  		ret = rfsv_isalive();  		if (isalive) {  			if (!ret) {  				debuglog("Disconnected...\n");  				doclean = 1; +				root_fattr.mtime.seconds = time(0);  			}  		} else { -			if (ret) +			if (ret) {  				debuglog("Connected...\n"); +				root_fattr.mtime.seconds = time(0); +			}  		}  		isalive = ret; -		if (doclean) { -			for (cp = attrcache; cp; cp = cp->next) -				for (dcp = cp->dcache; dcp; dcp = dcp->next) -					if (dcp->towrite) -						errorlog("PLPNFSD WARNING: file %s block at %d not written\n", -						       get_num(cp->inode)->name, dcp->offset); -			clean_cache(&attrcache); -			query_cache = 0;	/* clear the GETDENTS "cache". */ -			rfsv_closecached(); -		}  	}  } diff --git a/plpnfsd/mp_pfs_ops.c b/plpnfsd/mp_pfs_ops.c index 71ed2e9..a222776 100644 --- a/plpnfsd/mp_pfs_ops.c +++ b/plpnfsd/mp_pfs_ops.c @@ -9,6 +9,7 @@  #include "OSdefs.h"  #include <stdio.h>  #include <ctype.h> +#include <pwd.h>  #if defined(__SVR4) || defined(__GLIBC__)  #include <stdlib.h>  #include <unistd.h> @@ -17,9 +18,125 @@  #include "nfs_prot.h"  #include "mp.h"  #include "rfsv_api.h" +#include "builtins.h"  static device *devices; -struct cache *attrcache; +struct cache *attrcache = NULL; + +long param_read(builtin_node *node, char *buf, unsigned long offset, long len) { +	char tmp[10]; +	unsigned long val = 0; + +	if (!strcmp(node->name, "acache")) +		val = cache_keep; +	if (!strcmp(node->name, "dcache")) +		val = devcache_keep; +	if (!strcmp(node->name, "debuglevel")) +		val = debug; +	sprintf(tmp, "%ld\n", val); +	if (offset >= strlen(tmp)) +		return 0; +	strncpy(buf, &tmp[offset], len); +	return strlen(buf); +} + +long param_write(builtin_node *node, char *buf, unsigned long offset, long len) { +	unsigned long val; + +	if (len > 1 && offset == 0) { +		int res = sscanf(buf, "%ld", &val); +		if (res == 1) { +			if (!strcmp(node->name, "acache")) +				cache_keep = val; +			if (!strcmp(node->name, "dcache")) +				devcache_keep = val; +			if (!strcmp(node->name, "debuglevel")) { +				if (val != debug) { +					if (val > debug) +						debug = val; +					debuglog("Set debug level to %d\n", val); +					debug = val; +				} +			} +		} +	} +	return len; +} + +long param_getsize(builtin_node *node) { +	char tmp[10]; +	return param_read(node, tmp, 0, sizeof(tmp)); +} + +long exit_write(builtin_node *node, char *buf, unsigned long offset, long len) { +	if (len >= 4 && offset == 0) { +		if (!strncmp(buf, "stop", 4)) +			exiting = 5; /* Lets try it 5 times (10 sec) */ +	} +	return len; +} + +long exit_read(builtin_node *node, char *buf, unsigned long offset, long len) { +	if (offset > 4) +		return 0; +	if ((len + offset) > 5) +		len = 5 - offset; +	strncpy(buf, "----\n", len); +	return strlen(buf); +} + +long user_write(builtin_node *node, char *buf, unsigned long offset, long len) { +	char tmp[256]; +	if (len > 1 && offset == 0) { +		char *p; + +		if (len > (sizeof(tmp) - 1)) +			len = sizeof(tmp) - 1; +		strncpy(tmp, buf, len); +		debuglog("pwrite: %d\n", len); +		tmp[len] = '\0'; +		if ((p = strchr(tmp, '\n'))) +			*p = '\0'; +		set_owner(tmp, 0); +	} +	return len; +} + +long user_read(builtin_node *node, char *buf, unsigned long offset, long len) { +	struct passwd *pw = getpwuid(root_fattr.uid); +	char tmp[255]; + +	if (pw) +		sprintf(tmp, "%s\n", pw->pw_name); +	else +		sprintf(tmp, "???\n"); +	endpwent(); +	if (offset >= strlen(tmp)) +		return 0; +	strncpy(buf, &tmp[offset], len); +	return strlen(buf); +} + +long user_getsize(builtin_node *node) { +	char tmp[255]; +	return user_read(node, tmp, 0, sizeof(tmp)); +} + +static long generic_sattr(builtin_node *p, unsigned long sa, unsigned long da) { +	p->attr |= sa; +	p->attr &= ~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 }, +}; +static int num_builtins = sizeof(builtins) / sizeof(builtin_node);  /*   * Nfsd returned NFSERR_STALE if the psion wasn't present, but I didn't like @@ -139,7 +256,7 @@ attr2pattr(long oattr, long nattr, long *psisattr, long *psidattr)  }  static void -dpattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode) +pattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode)  {  	bzero((char *) fp, sizeof(*fp)); @@ -166,7 +283,7 @@ dpattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode)  		 * work properly  		 */  		if (psiattr & PSI_A_READ) -		fp->mode |= 0400;		/* File readable (?) */ +			fp->mode |= 0400;	/* File readable (?) */  		if (!(psiattr & PSI_A_RDONLY))  			fp->mode |= 0200;	/* File writeable  */  		/* fp->mode |= 0100;		   File executable */ @@ -191,59 +308,6 @@ dpattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode)  	fp->mtime.seconds = fp->ctime.seconds = fp->atime.seconds;  } -static void -pattr2attr(long psiattr, long size, long ftime, fattr *fp, unsigned char *fh) -{ -	bzero((char *) fp, sizeof(*fp)); - -	if (psiattr & PSI_A_DIR) { -		fp->type = NFDIR; -		fp->mode = NFSMODE_DIR | 0700; -		/* -		 * Damned filesystem. -		 * We have to count the number of subdirectories -		 * on the psion. -		 */ -		fp->nlink = 0; -		fp->size = BLOCKSIZE; -		fp->blocks = 1; -	} else { -		fp->type = NFREG; -		fp->mode = NFSMODE_REG; -		fp->nlink = 1; -		fp->size = size; -		fp->blocks = (fp->size + BLOCKSIZE - 1) / BLOCKSIZE; - -		/* -		 * Following flags have to be set in order to let backups -		 * work properly -		 */ -		if (psiattr & PSI_A_READ) -		fp->mode |= 0400;		/* File readable (?) */ -		if (!(psiattr & PSI_A_RDONLY)) -			fp->mode |= 0200;	/* File writeable  */ -		/* fp->mode |= 0100;		   File executable */ -		if (!(psiattr & PSI_A_HIDDEN)) -			fp->mode |= 0004;	/* Not Hidden  <-> world read */ -		if (psiattr & PSI_A_SYSTEM) -			fp->mode |= 0002;	/* System      <-> world write */ -		if (psiattr & PSI_A_VOLUME) -			fp->mode |= 0001;	/* Volume      <-> world exec */ -		if (psiattr & PSI_A_ARCHIVE) -			fp->mode |= 0020;	/* Modified    <-> group write */ -	/*		fp->mode |= 0040;	 Byte        <-> group read */ -	/*		fp->mode |= 0010;	 Text        <-> group exec */ -	} - -	fp->uid = root_fattr.uid; -	fp->gid = root_fattr.gid; -	fp->blocksize = BLOCKSIZE; -	fp->fileid = fh2inode((char *) fh); -	fp->rdev = fp->fsid = FID; -	fp->atime.seconds = ftime; -	fp->mtime.seconds = fp->ctime.seconds = fp->atime.seconds; -} -  static int  query_devices()  { @@ -258,10 +322,12 @@ query_devices()  		free(dp);  	}  	devices = 0; +	debuglog("RFSV drivelist\n");  	if (rfsv_drivelist(&link_count, &devices))  		return 1;  	query_cache = 1; -	root_fattr.nlink = link_count; +	devcache_stamp = time(0); +	root_fattr.nlink = link_count + 1;  	return 0;  } @@ -272,7 +338,15 @@ mp_dircount(p_inode *inode, long *count)  	long ret;  	*count = 0; -	debuglog("dircount: dir\n"); +	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; +	} +	debuglog("RFSV dir %s\n", inode->name);  	if ((ret = rfsv_dir(dirname(inode->name), &e)))  		return ret;  	while (e) { @@ -285,7 +359,7 @@ mp_dircount(p_inode *inode, long *count)  		ni = get_nam(build_path(inode->name, bp))->inode;  		free(e->name);  		if (!search_cache(attrcache, ni)) { -			dpattr2attr(e->attr, e->size, e->time, &fp, ni); +			pattr2attr(e->attr, e->size, e->time, &fp, ni);  			if (rfsv_isalive())  				add_cache(&attrcache, ni, &fp);  		} @@ -308,6 +382,7 @@ nfsproc_getattr_2(struct nfs_fh *fh)  	long psize;  	long ptime;  	long dcount; +	int builtin = 0;  	int l;  	debuglog("getattr:'%s',%d\n", inode->name, inode->inode); @@ -316,6 +391,7 @@ 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; @@ -326,6 +402,7 @@ nfsproc_getattr_2(struct nfs_fh *fh)  			fp->nlink = dcount + 2;  			cp->attr = *fp;  		} +#endif  		return &res;  	}  	l = strlen(inode->name); @@ -334,9 +411,18 @@ nfsproc_getattr_2(struct nfs_fh *fh)  		/* It's the root inode */  		debuglog("getattr:root inode (%#o)\n", root_fattr.mode); -		if (query_devices())	/* root inode is always there */ -			root_fattr.nlink = 2; +		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; @@ -367,13 +453,31 @@ nfsproc_getattr_2(struct nfs_fh *fh)  			}  		}  	} else { -		debuglog("getattr:fileordir\n"); -		/* It's a normal file/dir */ -		if (rfsv_getattr(inode->name, &pattr, &psize, &ptime)) { -			res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; -			return &res; +		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; +				ptime = time(0); +				res.status = NFS_OK; +				builtin = 1; +				if (builtins[i].flags && BF_NOCACHE) +					builtin++; +				break; +			}  		} -		pattr2attr(pattr, psize, ptime, fp, (unsigned char *) fh->data); + +		if (!builtin) { +			debuglog("getattr:fileordir\n"); +			/* It's a normal file/dir */ +			debuglog("RFSV getattr %s\n", inode->name); +			if (rfsv_getattr(inode->name, &pattr, &psize, &ptime)) { +				res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; +				return &res; +			} +		} +		pattr2attr(pattr, psize, ptime, fp, fh2inode((char *) fh->data));  		if (fp->type == NFDIR) {  			if (mp_dircount(inode, &dcount)) {  				res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; @@ -384,7 +488,7 @@ nfsproc_getattr_2(struct nfs_fh *fh)  			fp->nlink = dcount + 2;  		}  	} -	if (rfsv_isalive()) +	if (rfsv_isalive() && builtin < 2)  		add_cache(&attrcache, inode->inode, fp);  	return &res;  } @@ -404,18 +508,6 @@ nfsproc_lookup_2(diropargs *da)  	}  	debuglog("lookup: in '%s'(%d) searching '%s'\n",  		       inode->name, inode->inode, da->name); - -	if (inode->inode == root_fattr.fileid && !strcmp(da->name, "exit")) { -		exiting = 5;	/* Lets try it 5 times (10 sec) */ -		res.status = NFSERR_EXIST; -		return &res; -	} -	if (inode->inode == root_fattr.fileid && !strcmp(da->name, "debug")) { -		debug = (debug + 1) & 3;	/* debug level of 0,1,2 & 3 */ -		debuglog("Set debug level to %d\n", debug); -		res.status = NFSERR_EXIST; -		return &res; -	}  	if (!strcmp(da->name, "."))  		inode2fh(fh2inode(da->dir.data), fp);  	else if (!strcmp(da->name, "..")) @@ -510,15 +602,17 @@ nfsproc_readdir_2(readdirargs *ra)  	debuglog("readdir: %s, cookie:%x, count:%d\n",  		       inode->name, searchinode, ra->count); -/* . & .. */ +	/* . & .. */  	addentry(ra, &cp, &searchinode, inode->inode, ".");  	addentry(ra, &cp, &searchinode, getpinode(inode), "..");  	if (inode->inode == root_fattr.fileid) {	/* Root directory */  		device *dp; +		addentry(ra, &cp, &searchinode, get_nam("/proc")->inode, "proc");  		if (query_devices()) { -			res.status = NO_PSION; +			res.readdirres_u.reply.eof = ra->count == RA_MAXCOUNT ? 0 : 1; +			res.status = NFS_OK;  			return &res;  		}  		for (dp = devices; dp; dp = dp->next) { @@ -529,25 +623,35 @@ nfsproc_readdir_2(readdirargs *ra)  	} else {  		dentry *e = NULL;  		debuglog("nfsdir: dir\n"); -		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; - -			bp = filname(e->name); -			ni = get_nam(build_path(inode->name, bp))->inode; -			addentry(ra, &cp, &searchinode, ni, (char *) bp); -			free(e->name); -			dpattr2attr(e->attr, e->size, e->time, &fp, ni); -			if (rfsv_isalive()) -				add_cache(&attrcache, ni, &fp); -			o = e; -			e = e->next; -			free(o); +		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); +				} +		} else { +			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; +	 +				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); +			}  		}  	} @@ -562,6 +666,8 @@ nfsproc_setattr_2(sattrargs *sa)  	static struct attrstat res;  	p_inode *inode = get_num(fh2inode(sa->file.data));  	fattr *fp; +	int bi; +	int builtin = 0;  	if (!inode) {  		debuglog("setattr: stale fh\n"); @@ -574,13 +680,28 @@ 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))) { +			builtin = 1; +			break; +		} +	} +  	if ((fp->type == NFREG) &&  	    (sa->attributes.size != -1) &&  	    (sa->attributes.size != fp->size)) { -		debuglog("setattr truncating to %d bytes\n", sa->attributes.size); -		if (rfsv_setsize(inode->name, sa->attributes.size) != 0) { -			res.status = rfsv_isalive() ? NFSERR_ROFS : NO_PSION; -			return &res; +		debuglog("RFSV setsize %s %d\n", inode->name, sa->attributes.size); +		if (builtin) { +			if (builtins[bi].attr & PSI_A_RDONLY) { +				res.status = NFSERR_ACCES; +				return &res; +			} +		} else { +			if (rfsv_setsize(inode->name, sa->attributes.size) != 0) { +				// FIXME: more different error codes +				res.status = rfsv_isalive() ? NFSERR_ROFS : NO_PSION; +				return &res; +			}  		}  		fp->size = sa->attributes.size;  		rem_cache(&attrcache, inode->inode); @@ -588,7 +709,8 @@ nfsproc_setattr_2(sattrargs *sa)  			add_cache(&attrcache, inode->inode, fp);  	}  	if ((sa->attributes.mtime.seconds != fp->mtime.seconds) && -	    (sa->attributes.mtime.seconds != -1)) { +	    (sa->attributes.mtime.seconds != -1) && !builtin) { +		debuglog("RFSV setmtime %s %d\n", inode->name, sa->attributes.mtime.seconds);  		if (rfsv_setmtime(inode->name, sa->attributes.mtime.seconds)) {  			res.status = (rfsv_isalive()) ? NFSERR_ACCES : NO_PSION;  			return &res; @@ -602,13 +724,21 @@ nfsproc_setattr_2(sattrargs *sa)  	    (sa->attributes.mode != -1)) {  		long psisattr, psidattr;  		attr2pattr(sa->attributes.mode, fp->mode, &psisattr, &psidattr); -		if (rfsv_setattr(inode->name, psisattr, psidattr)) { -			res.status = (rfsv_isalive()) ? NFSERR_ACCES : NO_PSION; -			return &res; +		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)) { +				res.status = NFSERR_ACCES; +				return &res; +			} +		} else { +			if (rfsv_setattr(inode->name, psisattr, psidattr)) { +				res.status = (rfsv_isalive()) ? NFSERR_ACCES : NO_PSION; +				return &res; +			}  		}  		fp->mode = sa->attributes.mode;  		rem_cache(&attrcache, inode->inode); -		if (rfsv_isalive()) +		if (rfsv_isalive() && !builtin)  			add_cache(&attrcache, inode->inode, fp);  	}  	res.status = NFS_OK; @@ -629,10 +759,13 @@ remove_it(diropargs *da, int isdir)  	}  	debuglog("remove_it: in %s: %s (%d)\n", inode->name, da->name, isdir); -	if (isdir) +	if (isdir) { +		debuglog("RFSV rmdir %s\n", build_path(inode->name, da->name));  		rfsv_res = rfsv_rmdir(build_path(inode->name, da->name)); -	else +	} else { +		debuglog("RFSV remove %s\n", build_path(inode->name, da->name));  		rfsv_res = rfsv_remove(build_path(inode->name, da->name)); +	}  	if (rfsv_res != 0) {  		res = rfsv_isalive() ? NFSERR_ACCES : NO_PSION;  		return &res; @@ -672,8 +805,8 @@ nfsproc_rename_2(renameargs *ra)  	c = *ldata + 1;  	old = build_path(from->name, ra->from.name); -	debuglog("Rename: %s -> %s\n", old, ldata + 1);  	res = NFS_OK; +	debuglog("RFSV rename %s -> %s\n", old, ldata + 1);  	if (rfsv_rename(old, ldata + 1)) {  		res = (rfsv_isalive()) ? NFSERR_ACCES : NO_PSION;  		return &res; @@ -740,7 +873,9 @@ nfsproc_read_2(struct readargs *ra)  	long pattr;  	long psize;  	long ptime; -	int len; +	int len = 0; +	int bi; +	int builtin = 0;  	if (!inode) {  		debuglog("read: stale fh\n"); @@ -760,40 +895,57 @@ nfsproc_read_2(struct readargs *ra)  		return &res;  	} -	if(rfsv_read(rop, ra->offset, -		ra->count, inode->name) < 0) { -		res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; -		return &res; +	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); +				builtin = 1; +				break; +			} +		}  	} +	if (!builtin) { +		if (rfsv_read(rop, ra->offset, +			ra->count, inode->name) < 0) { +			res.status = rfsv_isalive() ? NFSERR_NOENT : NO_PSION; +			return &res; +		} +	}  	fp = &res.readres_u.reply.attributes; -	if(!cp)	// Problem: if an epoc process is enlarging the file, we wont recognize it -	  { -	    rfsv_getattr(inode->name, &pattr, &psize, &ptime); -	    pattr2attr(pattr, psize, ptime, fp, (unsigned char *) ra->file.data); -	    cp = add_cache(&attrcache, inode->inode, fp); -          } -	else -	  { -	    *fp = cp->attr; -	  } - +	if (!cp) { +		// 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; +			ptime = time(0); +		} else +			rfsv_getattr(inode->name, &pattr, &psize, &ptime); +		pattr2attr(pattr, psize, ptime, fp, fh2inode((char *)ra->file.data)); +		cp = add_cache(&attrcache, inode->inode, fp); +	} else { +		*fp = cp->attr; +	} -  	len = cp->actual_size - ra->offset;  	if (len > ra->count)  		len = ra->count;  	if (cp->actual_size < ra->offset)  		len = 0;  	if (debug > 1) -		debuglog("Read: filesize %d read %d @ %d\n", cp->actual_size,len,ra->offset); -	res.readres_u.reply.data.data_len = len; -	res.readres_u.reply.data.data_val = (char *) rop; - +		debuglog("Read: filesize %d read %d @ %d\n", cp->actual_size, len, ra->offset);  	if (len) {  		dcp = add_dcache(cp, ra->offset, ra->count, rop);  		dcp->towrite = 0;	/* don't write it back */  	} +	if (builtin) +		rem_cache(&attrcache, inode->inode); +	res.readres_u.reply.data.data_len = len; +	res.readres_u.reply.data.data_val = (char *) rop; +  	res.status = NFS_OK;  	return &res;  } @@ -881,7 +1033,8 @@ nfsproc_write_2(writeargs *wa)  	struct dcache *dcp;  	fattr *fp;  	struct attrstat *gres; -	int len, dlen, doff; +	int len = 0; +	int i, dlen, doff;  	if (!inode) {  		debuglog("write: stale fh\n"); @@ -901,8 +1054,11 @@ nfsproc_write_2(writeargs *wa)  			return &res;  		}  		cp = search_cache(attrcache, inode->inode); -		if (!cp) -			abort(); +		if (!cp) { +			errorlog("nfsproc_write_2: cache is NULL\n"); +			res.status = NFSERR_IO; +			return &res; +		}  	}  	fp = &cp->attr;  	if (fp->size < doff + dlen) @@ -912,6 +1068,17 @@ 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; @@ -932,6 +1099,8 @@ nfsproc_write_2(writeargs *wa)  		debuglog("writing off: %d, len: %d, act: %d\n",  			       dcp->offset, dcp->len, cp->actual_size); +		debuglog("RFSV write %s\n", inode->name); +  		if (rfsv_write(dcp->data, dcp->offset, dcp->len, inode->name) != dcp->len) {  			debuglog("write: dump failed\n");  			res.status = rfsv_isalive() ? NFSERR_NOSPC : NO_PSION; diff --git a/plpnfsd/rfsv_api.h b/plpnfsd/rfsv_api.h index 14c26d5..b780735 100644 --- a/plpnfsd/rfsv_api.h +++ b/plpnfsd/rfsv_api.h @@ -9,6 +9,7 @@  #define _rfsv_api_h_  #include "mp.h" +#include "builtins.h"  extern long rfsv_dir(const char *name, dentry **e);  extern long rfsv_mkdir(const char *name); @@ -29,6 +30,9 @@ extern long rfsv_statdev(char letter);  extern long rfsv_isalive();  extern long rfsv_closecached(void); +extern long rpcs_ownerRead(builtin_node *, char *buf, unsigned long  offset, long len); +extern long rpcs_ownerSize(builtin_node *); +  /* File attributes, C-style */  #define	PSI_A_RDONLY		0x0001  #define	PSI_A_HIDDEN		0x0002  | 
