From 286c6d60fa96e53c7b261a60ca8abe680197c6c3 Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Thu, 10 Aug 2000 19:36:14 +0000 Subject: Added man pages by John Lines (john+plpman@paladin.demon.co.uk). Started support for procfs-like extension in plpnfsd. --- configure.in | 9 ++ doc/Makefile.am | 13 ++ doc/ncpd.man.in | 89 +++++++++++ doc/plpftp.man.in | 46 ++++++ doc/plpnfsd.man.in | 76 +++++++++ include/mp.h | 121 +++++--------- lib/rpcsfactory.cc | 7 +- plpnfsd/builtins.h | 33 ++++ plpnfsd/main.cc | 67 +++++++- plpnfsd/mp_inode.c | 52 +++--- plpnfsd/mp_main.c | 78 +++++++-- plpnfsd/mp_mount.c | 82 +++++----- plpnfsd/mp_pfs_ops.c | 443 +++++++++++++++++++++++++++++++++++---------------- plpnfsd/rfsv_api.h | 4 + 14 files changed, 818 insertions(+), 302 deletions(-) create mode 100644 doc/ncpd.man.in create mode 100644 doc/plpftp.man.in create mode 100644 doc/plpnfsd.man.in create mode 100644 plpnfsd/builtins.h diff --git a/configure.in b/configure.in index d042094..a7e2ca6 100644 --- a/configure.in +++ b/configure.in @@ -13,6 +13,8 @@ dnl checks for programs AC_AIX AC_PROG_MAKE_SET AC_CHECK_COMPILERS +AC_PROG_AWK +AC_PATH_PROG(SED,sed) CFLAGS="-O" test "$GCC" = yes && CFLAGS="-O2 -Wall" @@ -84,6 +86,7 @@ AC_ARG_WITH(serial, ] ) AC_DEFINE_UNQUOTED(DDEV,"$DDEV") +AC_SUBST(DDEV) AC_ARG_WITH(speed, [ --with-speed=SPEED override default serial speed [115200]], @@ -94,6 +97,7 @@ AC_ARG_WITH(speed, ] ) AC_DEFINE_UNQUOTED(DSPEED,$DSPEED) +AC_SUBST(DSPEED) AC_ARG_WITH(port, [ --with-port=PORT override default port [7501]], @@ -104,6 +108,7 @@ AC_ARG_WITH(port, ] ) AC_DEFINE_UNQUOTED(DPORT,$DPORT) +AC_SUBST(DPORT) AC_ARG_WITH(drive, [ --with-drive=DRIVE override default Psion drive [AUTO]], @@ -134,6 +139,7 @@ AC_ARG_WITH(mountdir, ] ) AC_DEFINE_UNQUOTED(DMOUNTPOINT,"$DMOUNTPOINT") +AC_SUBST(DMOUNTPOINT) AC_OUTPUT( @@ -146,4 +152,7 @@ AC_OUTPUT( doc/api/Makefile include/config.h etc/psion + doc/ncpd.man + doc/plpnfsd.man + doc/plpftp.man ) diff --git a/doc/Makefile.am b/doc/Makefile.am index 10e4f47..c989bbf 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1 +1,14 @@ SUBDIRS = api + +EXTRA_DIST = ncpd.man.in plpnfsd.man.in plpftp.man.in + +man_MANS = ncpd.8 plpnfsd.8 plpftp.1 + +%.1: %.man + MANDATE=`grep CHECKIN $< | $(AWK) '{print $$4}'` ; \ + $(SED) -e "s%@MANDATE@%$$MANDATE%g" $< > $@ + +%.8: %.man + MANDATE=`grep CHECKIN $< | $(AWK) '{print $$4}'` ; \ + $(SED) -e "s%@MANDATE@%$$MANDATE%g" $< > $@ + diff --git a/doc/ncpd.man.in b/doc/ncpd.man.in new file mode 100644 index 0000000..86e99ef --- /dev/null +++ b/doc/ncpd.man.in @@ -0,0 +1,89 @@ +.\" Manual page for ncpd +.\" $Id$ +.\" CHECKIN $Date$ +.\" +.\" Process this file with +.\" groff -man -Tascii ncpd.8 for ASCII output, or +.\" groff -man -Tps ncpd.8 for PostScript output +.\" +.TH ncpd 8 "@MANDATE@" "plptools @VERSION@" "System Administration" +.SH NAME +ncpd \- Daemon which handles the serial link to a Psion +.SH SYNOPSIS +.B ncpd +.B [-V] +.BI "[-v " logclass ] +.B [-d] +.BI "[-p " port ] +.BI "[-s " device ] +.BI "[-b " baudrate ] + +.SH DESCRIPTION +ncpd is the daemon which handles the serial link to your Psion. +It listens at port @DPORT@ for local connections and provides +basic PLP/NCP services for plpnfsd and plpftp. It autoconnects +to the psion, even after unplugging/switching off therefore it +can run always in background (if you have a spare serial-device) + +.SH OPTIONS +.TP +.B \-V +Display the version and exit +.TP +.BI "\-v " logclass +Increase the logging level of the program. the possible values for logclass +are: +.TP +.I nl +Set NCP debug level to LOG +.TP +.I nd +Set NCP debug level to DEBUG +.TP +.I ll +Set Link debug level to LOG +.TP +.I ld +Set Link debug level to DEBUG +.TP +.I pl +Set Packet debug level to LOG +.TP +.I pd +Set Packet debug level to DEBUG +.TP +.I ph +Set Packet debug level to HANDSHAKE +.TP +.I m +Set overall debug level to verbose +.TP +.I all +Turn on all the above logging on. + +.TP +.B \-d +Do not background the daemon. +.TP +.BI "\-p " port +Specify the port to listen on - by default this is @DPORT@ +.TP +.BI "\-s " device +Specify the serial device to use to connect to the Psion - this defaults to +@DDEV@ +.TP +.BI "\-b " baudrate +Specify the baud rate to use for the serial connection - this defaults to +@DSPEED@ baud. + +.SH SEE ALSO +plpftp(1), plpnfsd(8) + +.SH AUTHOR +Fritz Elfert +Heavily based on p3nfsd by Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) +and +plp_1_7 by Philip Proudman (phil@proudman51.freeserve.co.uk) +Patches from Matt Gumbley (matt@gumbley.demon.co.uk) +Man page by John Lines (john+plpman@paladin.demon.co.uk) + diff --git a/doc/plpftp.man.in b/doc/plpftp.man.in new file mode 100644 index 0000000..cc12b35 --- /dev/null +++ b/doc/plpftp.man.in @@ -0,0 +1,46 @@ +.\" Manual page for plpftp +.\" $Id$ +.\" CHECKIN $Date$ +.\" +.\" Process this file with +.\" groff -man -Tascii plpftp.1 for ASCII output, or +.\" groff -man -Tps plpftp.1 for PostScript output +.\" +.TH plpftp 1 "@MANDATE@" "plptools @VERSION@" local +.SH NAME +plpftp \- FTP-like program for manipulating files on the Psion. +.SH SYNOPSIS +.B plpftp +.BI "[-p " port ] +.BI "[ " ftpcommand " [" parameters ]] + +.SH DESCRIPTION + +plpftp provides an ftp style interface for the psion. It requires the ncpd to +be running already to provide access to the serial port. + +plpftp has online help. To see the available commands start the program and +enter "help". + +.SH OPTIONS + +.TP +.BI "\-p " port +Specify the port to connect to (e.g. The port where ncpd is listening on) - +by default this is @DPORT@ +.TP +.I ftpcommand parameters +Allows you to specify an plpftp command on the command line. If specified, +plpftp enters non interactive mode and terminates after executing the +command. + +.SH SEE ALSO +ncpd(8), plpncpd(8) + +.SH AUTHOR +Fritz Elfert +Heavily based on p3nfsd by Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) +and +plp_1_7 by Philip Proudman (phil@proudman51.freeserve.co.uk) +Man page by John Lines (john+plpman@paladin.demon.co.uk) + diff --git a/doc/plpnfsd.man.in b/doc/plpnfsd.man.in new file mode 100644 index 0000000..d1b1057 --- /dev/null +++ b/doc/plpnfsd.man.in @@ -0,0 +1,76 @@ +.\" Manual page for plpnfsd +.\" $Id$ +.\" CHECKIN $Date$ +.\" +.\" Process this file with +.\" groff -man -Tascii plpnfsd.8 for ASCII output, or +.\" groff -man -Tps plpnfsd.8 for PostScript output +.\" +.TH plpnfsd 8 "@MANDATE@" "plptools @VERSION@" "System Administration" +.SH NAME +plpnfsd \- Daemon to mount a Psion an nfs like filesystem +.SH SYNOPSIS +.B plpnfsd +.B [-V] +.B [-v] +.BI "[-p " port ] +.BI "[-d " mountdir ] +.BI "[-u " user ] + +.SH DESCRIPTION +plpnfsd is a daemon, which provides NFS-like access to your Psion. +It automatically makes the psion's filesystems available below +an NFS-mounted directory (default /mnt/psion). +By default, plpnfsd is installed suid-root, so any normal user +can start it and get's the mounted directory owned by himself. +As this program is usually used on single-user machines, this +does not hurt security. Like the others, this program +auto-reconnects after a link-failure, so you can keep the +psion mounted all the time, even when it is not connected. +Due to Rudolf Koenig's clever error-handling, you don't need to +worry about blocked io-processes if the psion isn't available. +You simply will get an "device not configured" error, when +accessing a file on a previously connected psion which has been +disconnected. After that, the mount-point will appear empty. +As soon as the psion is connected again, the subdirectories +will reappear. (possibly with a few secs delay) + + +.SH OPTIONS +.TP +.B \-V +Display the version and exit +.TP +.B \-v +Produce verbose logging output. Can be specified more than once to increase the +debug level (up to 3 times) + +.TP +.BI "\-p " port +Specify the port to connect to (e.g. the port where ncpd is listening on) - by +default this is +.I @DPORT@. +.TP +.BI "\-d " mountdir +Specify the directory to mount the psion file system on. This defaults +to +.I @DMOUNTPOINT@ +.TP +.BI "\-u " user +Specify the user who will own the psion files. This defaults to the user +who is running plpnfsd. If the user running plpnfsd is +.I root +, s/he may +also specify a different user. + +.SH SEE ALSO +ncpd(8), plpftp(1) + +.SH AUTHOR +Fritz Elfert +Heavily based on p3nfsd by Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) +and +plp_1_7 by Philip Proudman (phil@proudman51.freeserve.co.uk) +Patches from Matt Gumbley (matt@gumbley.demon.co.uk) +Man page by John Lines (john+plpman@paladin.demon.co.uk) + diff --git a/include/mp.h b/include/mp.h index 125ad80..0ca5501 100644 --- a/include/mp.h +++ b/include/mp.h @@ -8,44 +8,22 @@ #include "fparam.h" #include "nfs_prot.h" -#define PFS_OP_CREATE 0x01 -#define PFS_OP_GETATTR 0x02 -#define PFS_OP_MKDIR 0x03 -#define PFS_OP_READ 0x04 -#define PFS_OP_READDIR 0x05 -#define PFS_OP_REMOVE 0x06 -#define PFS_OP_RENAME 0x07 -#define PFS_OP_RMDIR 0x08 -#define PFS_OP_SETATTR 0x09 -#define PFS_OP_WRITE 0x0a -#define PFS_OP_GETDEVS 0x0b -/* The same as getattr without the stat (for linkcount purposes */ -#define PFS_OP_STATDEV 0x0c - -/* Only for the new nfsc */ -#define PFS_OP_TTYDATA 0x0d -#define PFS_OP_EXEC 0x0e -#define PFS_OP_ECHO 0x0f -#define PREFIX 0x80 - -typedef struct p_inode -{ - int inode; - char *name; - struct p_inode *nextnam, *nextnum; +typedef struct p_inode { + int inode; + char *name; + struct p_inode *nextnam, *nextnum; } p_inode; -/* +/** * Description of a Psion-Device */ -typedef struct p_device -{ - char *name; /* Volume-Name */ - char letter; /* Drive-Number (zero-based, i.e. 0 = A, 1 = B, 2 = C ...) */ - long attrib; /* Device-Attribs */ - long total; /* Total capacity in bytes */ - long free; /* Free space in bytes */ - struct p_device *next; +typedef struct p_device { + char *name; /* Volume-Name */ + char letter; /* Drive-Number (zero-based, i.e. 0 = A, 1 = B, 2 = C ...) */ + long attrib; /* Device-Attribs */ + long total; /* Total capacity in bytes */ + long free; /* Free space in bytes */ + struct p_device *next; } device; /* @@ -61,36 +39,39 @@ typedef struct p_dentry struct p_dentry *next; } dentry; -/* data cache */ -struct dcache -{ - struct dcache *next; - unsigned char *data; - unsigned int offset, len; - int towrite; +/** + * data cache + */ +struct dcache { + struct dcache *next; + unsigned char *data; + unsigned int offset, len; + int towrite; }; -/* attribute cache */ -struct cache -{ - struct cache *next; - unsigned int inode; - int actual_size; - struct dcache *dcache; - fattr attr; +/** + * attribute cache + */ +struct cache { + struct cache *next; + time_t stamp; + unsigned int inode; + int actual_size; + struct dcache *dcache; + fattr attr; }; -struct entrycache -{ - int inode; - entry *head; - struct entrycache *next; -}; +extern int debug; +extern int exiting; +extern int query_cache; +extern int force_cache_clean; -extern int debug, gmtoffset, exiting, psion_alive, dowakeup, - query_cache, series5; extern fattr root_fattr; -extern struct cache *datacache, *attrcache; +extern struct cache *attrcache; + +extern time_t cache_keep; +extern time_t devcache_keep; +extern time_t devcache_stamp; #ifdef __SVR4 #define bzero(a,b) memset(a,0,b) @@ -105,10 +86,8 @@ extern char *index(), *rindex(), *strdup(); #endif -#define THE_END (struct entry *)-1 #define PBUFSIZE 8192 -#define TIMEOUT -54 #define BLOCKSIZE 512 #define FID 7 /* File system id */ @@ -128,14 +107,8 @@ extern char *index(), *rindex(), *strdup(); extern void usleep __P((int usec)); # endif #endif - -/* mp_serial.c */ -int init_serial __P((char *dev, int speed)); -int fd_is_still_alive __P((int fd, int wake)); -void reset_serial __P((int fd)); - -/* crc.c */ -int docrc16 __P((unsigned char *, int)); +extern int set_owner(char *user, int logstdio); +extern void cache_flush(void); /* mp_mount.c */ void mount_and_run __P((char *dir, void (*proc)(), nfs_fh *root_fh)); @@ -164,17 +137,6 @@ extern struct dcache *add_dcache __P((struct cache *, unsigned int, unsigned int extern void clean_dcache __P((struct cache *)); extern struct dcache *search_dcache __P((struct cache *, unsigned int, unsigned int)); -/* mp_xmit.c */ -int sendop __P((int cmd, char *fname, char *rest, int restlen)); -int getstr __P((char *str)); -int getanswer __P((void)); -int sendcmd __P((int cmd, char *fname, char *rest, int restlen)); -int getcount __P((unsigned char *str, int num)); -int senddata __P((char *p, int len)); -void long2pstr __P((unsigned int l, unsigned char *s)); -void short2pstr __P((unsigned int l, unsigned char *s)); -unsigned int pstr2long __P((unsigned char *s)); - /* mp_pfs_ops.c */ extern void *nfsproc_null_2 __P((void)); extern void *nfsproc_root_2 __P((void)); @@ -197,7 +159,6 @@ extern struct readlinkres *nfsproc_readlink_2 __P((struct nfs_fh *fh)); extern int mp_main(int, char *, char *); -extern int logsyslog; extern int debuglog(char *fmt, ...); extern int errorlog(char *fmt, ...); extern int infolog(char *fmt, ...); diff --git a/lib/rpcsfactory.cc b/lib/rpcsfactory.cc index 520335e..869c6c5 100644 --- a/lib/rpcsfactory.cc +++ b/lib/rpcsfactory.cc @@ -37,7 +37,7 @@ #include "bufferstore.h" #include "ppsocket.h" -rpcsfactory::rpcsfactory(ppsocket *_skt) //: serNum(0) +rpcsfactory::rpcsfactory(ppsocket *_skt) { skt = _skt; } @@ -58,7 +58,6 @@ rpcs * rpcsfactory::create(bool reconnect) cerr << "rpcsfactory::create couldn't send version request" << endl; else { skt->closeSocket(); - // serNum = 0; skt->reconnect(); } return NULL; @@ -72,13 +71,11 @@ rpcs * rpcsfactory::create(bool reconnect) } if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) { skt->closeSocket(); - // serNum = 0; skt->reconnect(); return NULL; } // Invalid protocol version - cerr << "rpcsfactory::create received odd protocol version from -ncpd! (" << a << ")" << endl; + cerr << "rpcsfactory::create received odd protocol version from ncpd! (" << a << ")" << endl; } else { cerr << "rpcsfactory::create sent, response not 1" << endl; } 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 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 #include #include +#include #include #include #include @@ -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 #include +#include #if defined(__SVR4) || defined(__GLIBC__) #include #include @@ -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 -- cgit v1.2.3