aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2000-08-10 19:36:14 +0000
committerFritz Elfert <felfert@to.com>2000-08-10 19:36:14 +0000
commit286c6d60fa96e53c7b261a60ca8abe680197c6c3 (patch)
tree4a2f6339002323cf5d432bfa81677cb7002c4904
parent68d5fd192fee358ad195c32b47333f8f87ae13f2 (diff)
downloadplptools-286c6d60fa96e53c7b261a60ca8abe680197c6c3.tar.gz
plptools-286c6d60fa96e53c7b261a60ca8abe680197c6c3.tar.bz2
plptools-286c6d60fa96e53c7b261a60ca8abe680197c6c3.zip
Added man pages by John Lines (john+plpman@paladin.demon.co.uk).
Started support for procfs-like extension in plpnfsd.
-rw-r--r--configure.in9
-rw-r--r--doc/Makefile.am13
-rw-r--r--doc/ncpd.man.in89
-rw-r--r--doc/plpftp.man.in46
-rw-r--r--doc/plpnfsd.man.in76
-rw-r--r--include/mp.h121
-rw-r--r--lib/rpcsfactory.cc7
-rw-r--r--plpnfsd/builtins.h33
-rw-r--r--plpnfsd/main.cc67
-rw-r--r--plpnfsd/mp_inode.c52
-rw-r--r--plpnfsd/mp_main.c78
-rw-r--r--plpnfsd/mp_mount.c82
-rw-r--r--plpnfsd/mp_pfs_ops.c443
-rw-r--r--plpnfsd/rfsv_api.h4
14 files changed, 818 insertions, 302 deletions
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<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