aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2000-07-31 03:12:38 +0000
committerFritz Elfert <felfert@to.com>2000-07-31 03:12:38 +0000
commit7fb94ed43a814788cda019c1e77314abc1626339 (patch)
tree50b86a44e2809e6fbcdcd080f2a2dc4dbc37042e
parentfbb17061d3c622f0786a5d9ad41e8ccd95ef706c (diff)
downloadplptools-7fb94ed43a814788cda019c1e77314abc1626339.tar.gz
plptools-7fb94ed43a814788cda019c1e77314abc1626339.tar.bz2
plptools-7fb94ed43a814788cda019c1e77314abc1626339.zip
Applied mjg-0.6 patch.
Started adding kdoc compliant documentation comments. Added PsiTime
-rw-r--r--.cvsignore1
-rw-r--r--README4
-rw-r--r--README.0.6-mjg62
-rw-r--r--configure.in13
-rwxr-xr-xetc/psion.in8
-rw-r--r--include/defs.h.in6
-rw-r--r--include/linux-misc.h52
-rw-r--r--include/nfs_prot.h18
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/bufferarray.cc22
-rw-r--r--lib/bufferarray.h137
-rw-r--r--lib/bufferstore.cc46
-rw-r--r--lib/bufferstore.h223
-rw-r--r--lib/ppsocket.cc4
-rw-r--r--lib/psitime.cc117
-rw-r--r--lib/psitime.h198
-rw-r--r--lib/rfsv.h64
-rw-r--r--lib/rfsv16.cc432
-rw-r--r--lib/rfsv16.h3
-rw-r--r--lib/rfsv32.cc102
-rw-r--r--lib/rfsv32.h3
-rw-r--r--lib/rpcs.cc138
-rw-r--r--lib/rpcs.h306
-rw-r--r--lib/rpcs16.cc2
-rw-r--r--lib/rpcs16.h2
-rw-r--r--lib/rpcs32.cc125
-rw-r--r--lib/rpcs32.h8
-rw-r--r--lib/rpcsfactory.cc9
-rw-r--r--lib/rpcsfactory.h28
-rw-r--r--ncpd/link.cc6
-rw-r--r--ncpd/linkchan.cc6
-rw-r--r--ncpd/main.cc10
-rw-r--r--ncpd/mp_serial.c2
-rw-r--r--ncpd/ncp.cc2
-rw-r--r--ncpd/packet.cc28
-rw-r--r--ncpd/packet.h1
-rw-r--r--patches/README16
-rw-r--r--patches/mgetty-1.1.21-plp.diff40
-rw-r--r--plpftp/ftp.cc131
-rw-r--r--plpnfsd/main.cc18
-rw-r--r--plpnfsd/mp_mount.c3
-rw-r--r--plpnfsd/mp_pfs_ops.c48
-rw-r--r--plpnfsd/rfsv_api.h15
43 files changed, 2046 insertions, 419 deletions
diff --git a/.cvsignore b/.cvsignore
index 3d7dae3..b850d61 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -7,3 +7,4 @@ config.status
config.cache
config.log
plptools-*.tar.gz
+.vimsession
diff --git a/README b/README
index 2fd2b77..6ebbe3c 100644
--- a/README
+++ b/README
@@ -88,7 +88,9 @@
basic PLP/NCP services for the other two programs. It auto-
connects to the psion, even after unplugging/switching off
therefore it can run always in background (if you have a
- spare serial-device)
+ spare serial-device). If supplied, the -e option will cause ncpd to
+ automatically exit when the connection to the Psion is lost. This is useful
+ when used with a patch to mgetty (see the patches directory).
plpftp is a FTP-like program for manipulating files on the Psion.
diff --git a/README.0.6-mjg b/README.0.6-mjg
new file mode 100644
index 0000000..7e5c737
--- /dev/null
+++ b/README.0.6-mjg
@@ -0,0 +1,62 @@
+Patches to plptools-0.6, collected by Matt Gumbley
+--------------------------------------------------
+
+1) Compilation patches to enable builds on Solaris. ftp.cc and ppsocket.cc
+2) Christof Meerwald's patches so that ncpd can autoterminate (-e option), and
+ patch for mgetty PLP autodetection (in the new patches directory), also a
+ patch to make the connection more stable.
+3) Peter Cherriman's patch which fixes the "one hour out" bug, which "...is that
+ a file timestamp is sometimes different when you do a "ls -l" on a mounted
+ psion, than the timestamp listed by the properties box on the psion.
+
+ My previous fix, no longer worked when the daylight saving changed. Linux
+ stores timestamps internally as the number of seconds since the EPOC in
+ UTC(GMT). However the psion seems stores timestamps as the number of seconds
+ since the EPOC. However the EPOC in defined relative to the currently set
+ timezone on the psion.
+
+ My new fix takes into account the timezone and DST status provided by the
+ linux system, it now works in by GMT(UTC+0) and BST(UTC+0+DST), but I
+ haven't tested it very much in other timezones, but I think it works.
+
+ It provides the correct timestamps apart from files created within a hour
+ of a DST change, however this can't be helped due to the strange way the
+ psion stores timestamps and handles timezone and DST."
+4) Added --with-mountdir option to configure to allow the plpnfsd mount point
+ to be specified at build time. Default is /mnt/psion.
+5) Added /dev/psion at the start of the serial ports probed for.
+6) Peter Cherriman's patch that fixes compilation of ftp.cc on some platforms.
+7) Jim Hague's patches for SIBO, and later Linux Kernels, from Feb 2000.
+ My apologies to Jim for not merging these sooner. He says:
+
+ "I've been doing a little work on getting plptools working with my 3a. ...
+ I have plpftp working for file transfer and plpnsfd also working, at least
+ sufficiently to back up my 3a.
+
+ I have also modified the include files required for the Linux build so
+ that it works with a 2.2 series kernels with the NFSv3 patch applied;
+ actually, all I've done is copy the relevant bits of the old NFSv2 headers.
+
+ It all seems to work with my 3a, though compared to p3nfsd plpnsfd seems
+ very slow at listing directories - when time permits I shall take a
+ closer look.
+
+ In addition to my English 3a (v3.22F) I have also tried it on an Italian 3a
+ (v3.40F). The latter exhibits some curious behaviour - if you start ncpd,
+ run up plpftp and quit plpftp, the 3a closes its serial port down (drops
+ CTS and DSR) and seems to need a reset before it will re-open the serial
+ port. Again, when time permits I shall see if it does this when using
+ PsiWin."
+
+ Other parts of Jim's patch:
+ "Which reminds me - 0.6 doesn't seem to have working copyFromPsion and
+ copyToPsion. I've fixed it up and tidied up the retrieval of Owner
+ Infomation a little - 3as anyway send lots of \0\0\0\0\0, each of which
+ was being displayed in plpftp as a blank line. "
+
+ Jim's patch removes lots of diagnostics in the rfsv16 code, and looks like
+ it fixes lots of stuff I hadn't got round to <hides head in shame>.
+ Splendid.
+
+Last patch update: 18/07/00.
+
diff --git a/configure.in b/configure.in
index 19e8ed4..1d7c53e 100644
--- a/configure.in
+++ b/configure.in
@@ -61,7 +61,7 @@ AC_ARG_WITH(serial,
AC_MSG_RESULT(Overriding serial line: $DDEV)
],
[ AC_MSG_CHECKING(for default serial line)
- AC_FIND_CDEV(/dev/tty0p0 /dev/tty00 /dev/ttyS0 /dev/term/a /dev/ttyfa /dev/ttya /dev/tty0 /dev/ttyf1 /dev/cuaa1, DDEV)
+ AC_FIND_CDEV(/dev/psion /dev/tty0p0 /dev/tty00 /dev/ttyS0 /dev/term/a /dev/ttyfa /dev/ttya /dev/tty0 /dev/ttyf1 /dev/cuaa1, DDEV)
AC_MSG_RESULT($DDEV)
test "$DDEV" = "NO" && AC_MSG_ERROR(NO serial lines. Use --with-serial.)
]
@@ -108,6 +108,17 @@ AC_ARG_WITH(basedir,
)
AC_SUBST(DBASEDIR)
+AC_ARG_WITH(mountdir,
+ [ --with-mountdir=DDIR override default mount point [/mnt/psion]],
+ [ DDIR="$withval"
+ AC_MSG_RESULT(Overriding mount point: $DDIR) ],
+ [ DDIR="/mnt/psion"
+ AC_MSG_RESULT(Using default mount point: $DDIR)
+ ]
+)
+AC_SUBST(DDIR)
+
+
AC_OUTPUT(
Makefile
lib/Makefile
diff --git a/etc/psion.in b/etc/psion.in
index 558828f..8985d40 100755
--- a/etc/psion.in
+++ b/etc/psion.in
@@ -11,9 +11,17 @@
[ -f @prefix@/sbin/ncpd ] || exit 0
[ -f @prefix@/sbin/plpnfsd ] || exit 0
+MGETTY_HASPLP=false
+if grep -qs ^/PLP/ /etc/mgetty+sendfax/login.config ; then
+ MGETTY_HASPLP=true
+fi
+
# See how we were called.
case "$1" in
start)
+ if $MGETTY_HASPLP ; then
+ echo "NOT Starting ncpd because mgetty configured for PLP"
+ fi
echo -n "Starting Psion support: "
daemon @prefix@/sbin/ncpd
daemon @prefix@/sbin/plpnfsd
diff --git a/include/defs.h.in b/include/defs.h.in
index ce5f68d..012852e 100644
--- a/include/defs.h.in
+++ b/include/defs.h.in
@@ -17,10 +17,6 @@
#define DUSER "root"
-#ifndef DDIR
-# define DDIR "/mnt/psion"
-#endif
-
#ifndef PSIONHOSTNAME
# define PSIONHOSTNAME "localhost"
#endif
@@ -38,6 +34,8 @@
#define DPORT @DPORT@
#define DDRIVE "@DDRIVE@"
#define DBASEDIR "@DBASEDIR@"
+#define DDIR "@DDIR@"
+
/* Debugging */
diff --git a/include/linux-misc.h b/include/linux-misc.h
new file mode 100644
index 0000000..afe1895
--- /dev/null
+++ b/include/linux-misc.h
@@ -0,0 +1,52 @@
+/*
+ * Linux nfs_mount_data version 3 (as expected by mp_mount.c).
+ *
+ * We extract it here to avoid some rather nasty fiddling necessary
+ * to compile with v3 and v4 (the latter as found in the NFS v3 stuff).
+ */
+
+#ifndef LINUX_MISC_H
+#define LINUX_MISC_H
+
+/*
+ * WARNING! Do not delete or change the order of these fields. If
+ * a new field is required then add it to the end. The version field
+ * tracks which fields are present. This will ensure some measure of
+ * mount-to-kernel version compatibility. Some of these aren't used yet
+ * but here they are anyway.
+ */
+#define NFS_MOUNT_VERSION 3
+
+struct nfs_mount_data {
+ int version; /* 1 */
+ int fd; /* 1 */
+ struct nfs_fh root; /* 1 */
+ int flags; /* 1 */
+ int rsize; /* 1 */
+ int wsize; /* 1 */
+ int timeo; /* 1 */
+ int retrans; /* 1 */
+ int acregmin; /* 1 */
+ int acregmax; /* 1 */
+ int acdirmin; /* 1 */
+ int acdirmax; /* 1 */
+ struct sockaddr_in addr; /* 1 */
+ char hostname[256]; /* 1 */
+ int namlen; /* 2 */
+ unsigned int bsize; /* 3 */
+};
+
+/* bits in the flags field */
+
+#define NFS_MOUNT_SOFT 0x0001 /* 1 */
+#define NFS_MOUNT_INTR 0x0002 /* 1 */
+#define NFS_MOUNT_SECURE 0x0004 /* 1 */
+#define NFS_MOUNT_POSIX 0x0008 /* 1 */
+#define NFS_MOUNT_NOCTO 0x0010 /* 1 */
+#define NFS_MOUNT_NOAC 0x0020 /* 1 */
+#define NFS_MOUNT_TCP 0x0040 /* 2 */
+#define NFS_MOUNT_VER3 0x0080 /* 3 */
+#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
+#define NFS_MOUNT_NONLM 0x0200 /* 3 */
+
+#endif
diff --git a/include/nfs_prot.h b/include/nfs_prot.h
index 16cc31f..8bc490f 100644
--- a/include/nfs_prot.h
+++ b/include/nfs_prot.h
@@ -9,7 +9,6 @@
#endif
#ifdef linux
# include <sys/time.h>
-# include <linux/nfs.h>
#endif
#ifdef __sgi
# include <rpc/types.h>
@@ -42,7 +41,7 @@
#define NFSMODE_SOCK 0140000
#define NFSMODE_FIFO 0010000
-#if !defined(hpux) && !defined(linux) && !defined(__sgi)
+#if !defined(hpux) && !defined(__sgi)
enum nfsstat {
NFS_OK = 0,
NFSERR_PERM = 1,
@@ -63,16 +62,12 @@ enum nfsstat {
NFSERR_STALE = 70,
NFSERR_WFLUSH = 99
};
-#endif /* !hpux, linux */
+#endif /* !hpux, sgi */
-#ifdef linux
-typedef enum nfs_stat nfsstat;
-#else
typedef enum nfsstat nfsstat;
-#endif
bool_t xdr_nfsstat();
-#if !defined(hpux) && !defined(linux) && !defined(__sgi)
+#if !defined(hpux) && !defined(__sgi)
enum ftype {
NFNON = 0,
NFREG = 1,
@@ -85,7 +80,7 @@ enum ftype {
NFFIFO = 8
};
typedef enum ftype ftype;
-#endif /* !linux, hpux */
+#endif /* !hpux, sgi */
#ifdef __sgi
typedef enum nfsftype ftype;
@@ -94,17 +89,12 @@ typedef enum nfsftype ftype;
#ifdef hpux
typedef enum nfsftype ftype;
#endif
-#ifdef linux
-typedef enum nfs_ftype ftype;
-#endif
bool_t xdr_ftype();
-#ifndef linux
struct nfs_fh {
char data[NFS_FHSIZE];
};
-#endif
typedef struct nfs_fh nfs_fh;
bool_t xdr_nfs_fh();
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 08df502..ec7a840 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,9 +1,9 @@
lib_LTLIBRARIES = libplp.la
-libplp_la_LDFLAGS = --debug -version-info 1:0:0
+libplp_la_LDFLAGS = --debug -version-info 1:1:0
libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc \
rfsv16.cc rfsv32.cc rfsvfactory.cc log.cc rfsv.cc rpcs32.cc rpcs16.cc \
- rpcs.cc rpcsfactory.cc
+ rpcs.cc rpcsfactory.cc psitime.cc
EXTRA_DIST = bool.h bufferarray.h bufferstore.h iowatch.h ppsocket.h \
rfsv.h rfsv16.h rfsv32.h rfsvfactory.h log.h rpcs32.h rpcs16.h rpcs.h \
- rpcsfactory.h
+ rpcsfactory.h psitime.h
diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc
index 4e922ed..77a08c6 100644
--- a/lib/bufferarray.cc
+++ b/lib/bufferarray.cc
@@ -45,11 +45,11 @@ bufferArray::bufferArray(const bufferArray & a)
bufferArray::~bufferArray()
{
- delete[]buff;
+ delete []buff;
}
bufferStore bufferArray::
-popBuffer()
+pop()
{
bufferStore ret;
if (len > 0) {
@@ -63,7 +63,7 @@ popBuffer()
}
void bufferArray::
-pushBuffer(const bufferStore & b)
+append(const bufferStore & b)
{
if (len == lenAllocd) {
lenAllocd += ALLOC_MIN;
@@ -71,7 +71,7 @@ pushBuffer(const bufferStore & b)
for (long i = 0; i < len; i++) {
nb[i] = buff[i];
}
- delete[]buff;
+ delete []buff;
buff = nb;
}
buff[len++] = b;
@@ -84,7 +84,7 @@ push(const bufferStore & b)
lenAllocd += ALLOC_MIN;
bufferStore *nb = new bufferStore[lenAllocd];
for (long i = len; i > 0; i--) {
- nb[i] = buff[i-1];
+ nb[i] = buff[i - 1];
}
nb[0] = b;
delete[]buff;
@@ -92,18 +92,6 @@ push(const bufferStore & b)
len++;
}
-bufferStore bufferArray::
-pop()
-{
- return popBuffer();
-}
-
-void bufferArray::
-append(const bufferStore & b)
-{
- pushBuffer(b);
-}
-
long bufferArray::
length(void)
{
diff --git a/lib/bufferarray.h b/lib/bufferarray.h
index fbf26f1..7389ab6 100644
--- a/lib/bufferarray.h
+++ b/lib/bufferarray.h
@@ -4,35 +4,120 @@
#include "bool.h"
class bufferStore;
+/**
+ * An array of bufferStores
+ */
class bufferArray {
- public:
- bufferArray();
- bufferArray(const bufferArray &a);
- ~bufferArray();
- bufferArray &operator =(const bufferArray &a);
- bool empty() const;
-
- // this is NOT a real push as with a FIFO but
- // appends the bufferStore.
- void pushBuffer(const bufferStore& b);
- bufferStore popBuffer(void);
-
- // new API (push() now behaves like a FIFO, more operators
- bufferStore &operator [](const unsigned long index);
- bufferArray &operator +(const bufferStore &); // append
- bufferArray &operator +(const bufferArray &); // append
- bufferArray &operator +=(const bufferStore &b); // append
- bufferStore pop(void);
- void push(const bufferStore& b);
- void append(const bufferStore& b);
- long length(void);
- void clear(void);
+public:
+ /**
+ * constructs a new bufferArray.
+ * A minimum of @ref ALLOC_MIN
+ * elements is allocated.
+ */
+ bufferArray();
+
+ /**
+ * Constructs a new bufferArray.
+ *
+ * @param a The initial contents for this array.
+ */
+ bufferArray(const bufferArray &a);
+
+ /**
+ * Destroys the bufferArray.
+ */
+ ~bufferArray();
+
+ /**
+ * Copys the bufferArray.
+ */
+ bufferArray &operator =(const bufferArray &a);
+
+ /**
+ * Checks if this bufferArray is empty.
+ *
+ * @return true if the bufferArray is empty.
+ */
+ bool empty() const;
+
+ /**
+ * Retrieves the bufferStore at given index.
+ *
+ * @return The bufferStore at index.
+ */
+ bufferStore &operator [](const unsigned long index);
+
+ /**
+ * Appends a bufferStore.
+ */
+ bufferArray &operator +(const bufferStore &);
+
+ /**
+ * Concatenates two bufferArrays.
+ */
+ bufferArray &operator +(const bufferArray &);
+
+ /**
+ * Appends a bufferStore.
+ */
+ bufferArray &operator +=(const bufferStore &b);
+
+ /**
+ * Removes the first bufferStore.
+ *
+ * @return The removed bufferStore.
+ */
+ bufferStore pop(void);
+
+ /**
+ * Inserts a bufferStore at index 0.
+ *
+ * @param b The bufferStore to be inserted.
+ */
+ void push(const bufferStore& b);
+
+ /**
+ * Appends a bufferStore.
+ *
+ * @param b The bufferStore to be appended.
+ */
+ void append(const bufferStore& b);
+
+ /**
+ * Evaluates the current length.
+ *
+ * @return The current number of bufferStores
+ */
+ long length(void);
+
+ /**
+ * Empties the bufferArray.
+ */
+ void clear(void);
private:
- static const long ALLOC_MIN = 5;
- long len;
- long lenAllocd;
- bufferStore* buff;
+ /**
+ * Minimum number of bufferStores to
+ * allocate.
+ */
+ static const long ALLOC_MIN = 5;
+
+ /**
+ * The current number of bufferStores in
+ * this bufferArray.
+ */
+ long len;
+
+ /**
+ * The current number of bufferStores
+ * allocated.
+ */
+ long lenAllocd;
+
+ /**
+ * The content.
+ */
+ bufferStore* buff;
};
inline bool bufferArray::empty() const { return len == 0; }
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
index 842e666..7f2b49d 100644
--- a/lib/bufferstore.cc
+++ b/lib/bufferstore.cc
@@ -22,28 +22,30 @@
#include <stream.h>
// That should be iostream.h, but it won't build on Sun WorkShop C++ 5.0
#include <iomanip.h>
+#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "bufferstore.h"
bufferStore::bufferStore() {
lenAllocd = 0;
- buff = NULL;
+ buff = 0L;
len = 0;
start = 0;
}
bufferStore::bufferStore(const bufferStore &a) {
lenAllocd = (a.getLen() > MIN_LEN) ? a.getLen() : MIN_LEN;
- buff = new unsigned char [lenAllocd];
+ buff = (unsigned char *)malloc(lenAllocd);
len = a.getLen();
memcpy(buff, a.getString(0), len);
start = 0;
}
-bufferStore::bufferStore(const unsigned char*_buff, long _len) {
+bufferStore::bufferStore(const unsigned char *_buff, long _len) {
lenAllocd = (_len > MIN_LEN) ? _len : MIN_LEN;
- buff = new unsigned char [lenAllocd];
+ buff = (unsigned char *)malloc(lenAllocd);
len = _len;
memcpy(buff, _buff, len);
start = 0;
@@ -54,6 +56,7 @@ bufferStore &bufferStore::operator =(const bufferStore &a) {
len = a.getLen();
memcpy(buff, a.getString(0), len);
start = 0;
+ return *this;
}
void bufferStore::init() {
@@ -69,7 +72,8 @@ void bufferStore::init(const unsigned char*_buff, long _len) {
}
bufferStore::~bufferStore() {
- delete [] buff;
+ if (buff != 0L)
+ free(buff);
}
unsigned long bufferStore::getLen() const {
@@ -92,23 +96,26 @@ unsigned int bufferStore::getDWord(long pos) const {
}
const char* bufferStore::getString(long pos) const {
- return (const char*)buff+pos+start;
+ return (const char*)buff + pos + start;
}
ostream &operator<<(ostream &s, const bufferStore &m) {
- {
- for (int i = m.start; i < m.len; i++)
+ // save stream flags
+ ostream::fmtflags old = s.flags();
+
+ for (int i = m.start; i < m.len; i++)
s << hex << setw(2) << setfill('0') << (int)m.buff[i] << " ";
- }
+
+ // restore stream flags
+ s.flags(old);
s << "(";
- {
- for (int i = m.start; i < m.len; i++) {
- unsigned char c = m.buff[i];
- if (c>=' ' && c <= 'z') s << c;
- }
+
+ for (int i = m.start; i < m.len; i++) {
+ unsigned char c = m.buff[i];
+ s << (unsigned char)(isprint(c) ? c : '.');
}
- s<< ")" << dec << setw(0);
- return s;
+
+ return s << ")";
}
void bufferStore::discardFirstBytes(int n) {
@@ -119,12 +126,9 @@ void bufferStore::discardFirstBytes(int n) {
void bufferStore::checkAllocd(long newLen) {
if (newLen >= lenAllocd) {
do {
- lenAllocd = (lenAllocd < MIN_LEN)?MIN_LEN:(lenAllocd*2);
+ lenAllocd = (lenAllocd < MIN_LEN) ? MIN_LEN : (lenAllocd * 2);
} while (newLen >= lenAllocd);
- unsigned char* newBuff = new unsigned char [lenAllocd];
- memcpy(&newBuff[start], &buff[start], len - start);
- delete [] buff;
- buff = newBuff;
+ buff = (unsigned char *)realloc(buff, lenAllocd);
}
}
diff --git a/lib/bufferstore.h b/lib/bufferstore.h
index df216c0..cad32fa 100644
--- a/lib/bufferstore.h
+++ b/lib/bufferstore.h
@@ -4,48 +4,205 @@
#include "bool.h"
class ostream;
+/**
+ * A generic container for an array of bytes.
+ *
+ * bufferStore provides an array of bytes which
+ * can be accessed using various types.
+ */
class bufferStore {
public:
- bufferStore();
- bufferStore(const unsigned char *, long);
- ~bufferStore();
- bufferStore(const bufferStore &);
- bufferStore &operator =(const bufferStore &);
-
- // Reading Utils
- unsigned long getLen() const;
- unsigned char getByte(long pos) const;
- unsigned int getWord(long pos) const;
- unsigned int getDWord(long pos) const;
- const char* getString(long pos=0) const;
- void discardFirstBytes(int);
- friend ostream &operator<<(ostream &, const bufferStore &);
- bool empty() const;
-
- // Writing utils
- void init();
- void init(const unsigned char*, long);
- void addByte(unsigned char);
- void addWord(int);
- void addDWord(long);
- void addString(const char*);
- void addStringT(const char*);
- void addBytes(const unsigned char*, int);
- void addBuff(const bufferStore &, long maxLen=-1);
+ /**
+ * Constructs a new bufferStore.
+ */
+ bufferStore();
+
+ /**
+ * Constructs a new bufferStore and
+ * initializes its content.
+ *
+ * @param buf Pointer to data for initialization.
+ * @param len Length of data for initialization.
+ */
+ bufferStore(const unsigned char *, long);
+
+ /**
+ * Destroys a bufferStore instance.
+ */
+ ~bufferStore();
+
+ /**
+ * Constructs a new bufferStore and
+ * initializes its content.
+ *
+ * @param b A bufferStore, whose content is
+ * used for initialization.
+ */
+ bufferStore(const bufferStore &);
+
+ /**
+ * Copies a bufferStore.
+ */
+ bufferStore &operator =(const bufferStore &);
+
+ /**
+ * Retrieves the length of a bufferStore.
+ *
+ * @returns The current length of the contents
+ * in bytes.
+ */
+ unsigned long getLen() const;
+
+ /**
+ * Retrieves the byte at index <em>pos</em>.
+ *
+ * @param pos The index of the byte to retrieve.
+ *
+ * @returns The value of the byte at index <em>pos</em>
+ */
+ unsigned char getByte(long pos) const;
+
+ /**
+ * Retrieves the word at index <em>pos</em>.
+ *
+ * @param pos The index of the word to retrieve.
+ *
+ * @returns The value of the word at index <em>pos</em>
+ */
+ unsigned int getWord(long pos) const;
+
+ /**
+ * Retrieves the dword at index <em>pos</em>.
+ *
+ * @param pos The index of the dword to retrieve.
+ *
+ * @returns The value of the dword at index <em>pos</em>
+ */
+ unsigned int getDWord(long pos) const;
+
+ /**
+ * Retrieves the characters at index <em>pos</em>.
+ *
+ * @param pos The index of the characters to retrieve.
+ *
+ * @returns A pointer to characters at index <em>pos</em>
+ */
+ const char* getString(long pos=0) const;
+
+ /**
+ * Removes bytes from the start of the buffer.
+ *
+ * @param len Number of bytes to remove.
+ */
+ void discardFirstBytes(int);
+
+ /**
+ * Prints a dump of the content.
+ *
+ * Mainly used for debugging purposes.
+ *
+ * @param s The stream to write to.
+ * @param b The bufferStore do be dumped.
+ *
+ * @returns The stream.
+ */
+ friend ostream &operator<<(ostream &, const bufferStore &);
+
+ /**
+ * Tests if the bufferStore is empty.
+ *
+ * @returns true, if the bufferStore is empty.
+ * false, if it contains data.
+ */
+ bool empty() const;
+
+ /**
+ * Initializes the bufferStore.
+ *
+ * All data is removed, the length is
+ * reset to 0.
+ */
+ void init();
+
+ /**
+ * Initializes the bufferStore with
+ * a given data.
+ *
+ * @param buf Pointer to data to initialize from.
+ * @param len Length of data.
+ */
+ void init(const unsigned char*, long);
+
+ /**
+ * Appends a byte to the content of this instance.
+ *
+ * @param c The byte to append.
+ */
+ void addByte(unsigned char);
+
+ /**
+ * Appends a word to the content of this instance.
+ *
+ * @param w The word to append.
+ */
+ void addWord(int);
+
+ /**
+ * Appends a dword to the content of this instance.
+ *
+ * @param dw The dword to append.
+ */
+ void addDWord(long);
+
+ /**
+ * Appends a string to the content of this instance.
+ *
+ * The trailing zero byte is <em>not</em> copied
+ * to the content.
+ *
+ * @param s The string to append.
+ */
+ void addString(const char*);
+
+ /**
+ * Appends a string to the content of this instance.
+ *
+ * The trailing zero byte <em>is</em> copied
+ * to the content.
+ *
+ * @param s The string to append.
+ */
+ void addStringT(const char*);
+
+ /**
+ * Appends data to the content of this instance.
+ *
+ * @param buf The data to append.
+ * @param len Length of data.
+ */
+ void addBytes(const unsigned char*, int);
+
+ /**
+ * Appends data to the content of this instance.
+ *
+ * @param b The bufferStore whose content to append.
+ * @param maxLen Length of content.
+ */
+ void addBuff(const bufferStore &, long maxLen=-1);
private:
- void checkAllocd(long newLen);
+ void checkAllocd(long newLen);
- long len;
- long lenAllocd;
- long start;
- unsigned char* buff;
+ long len;
+ long lenAllocd;
+ long start;
+ unsigned char* buff;
- enum c { MIN_LEN = 300 };
+ enum c { MIN_LEN = 300 };
};
inline bool bufferStore::empty() const {
- return (len-start) == 0;
+ return (len-start) == 0;
}
#endif
diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc
index cb04919..1249f18 100644
--- a/lib/ppsocket.cc
+++ b/lib/ppsocket.cc
@@ -181,7 +181,11 @@ listen(char *Host, int Port)
ppsocket *ppsocket::
accept(char *Peer, int MaxLen)
{
+#ifdef sun
+ int len;
+#else
socklen_t len;
+#endif
ppsocket *accepted;
char *peer;
diff --git a/lib/psitime.cc b/lib/psitime.cc
new file mode 100644
index 0000000..95ba6da
--- /dev/null
+++ b/lib/psitime.cc
@@ -0,0 +1,117 @@
+
+#include "psitime.h"
+#include <stdlib.h>
+
+PsiTime::PsiTime(psi_timeval *_ptv, psi_timezone *_ptz) {
+ if (_ptv != 0L)
+ ptv = *_ptv;
+ if (_ptz != 0L) {
+ ptz = *_ptz;
+ ptzValid = true;
+ } else
+ ptzValid = false;
+ /* get our own timezone */
+ gettimeofday(NULL, &utz);
+ psi2unix();
+}
+
+PsiTime::~PsiTime() {
+}
+
+void PsiTime::setUnixTime(struct timeval *_utv) {
+ if (_utv != 0L)
+ utv = *_utv;
+ unix2psi();
+}
+
+void PsiTime::setUnixNow(void) {
+ gettimeofday(&utv, &utz);
+ unix2psi();
+}
+
+
+void PsiTime::setPsiTime(psi_timeval *_ptv) {
+ if (_ptv != 0L)
+ ptv = *_ptv;
+ psi2unix();
+}
+
+void PsiTime::setPsiZone(psi_timezone *_ptz) {
+ if (_ptz != 0L) {
+ ptz = *_ptz;
+ ptzValid = true;
+ }
+ psi2unix();
+}
+
+struct timeval &PsiTime::getTimeval(void) {
+ return utv;
+}
+
+time_t PsiTime::getTime(void) {
+ return utv.tv_sec;
+}
+
+psi_timeval &PsiTime::getPsiTimeval(void) {
+ return ptv;
+}
+
+ostream &operator<<(ostream &s, const PsiTime &t) {
+ const char *fmt = "%c";
+ char buf[100];
+ strftime(buf, sizeof(buf), fmt, localtime(&t.utv.tv_sec));
+ s << buf;
+ return s;
+}
+
+/**
+ * The difference between
+ * EPOC epoch (01.01.0001 00:00:00)
+ * and Unix epoch (01.01.1970 00:00:00)
+ * in microseconds.
+ */
+#define EPOCH_DIFF 0x00dcddb30f2f8000ULL
+
+static unsigned long long
+evalOffset(psi_timezone ptz, bool valid) {
+ unsigned long long offset = 0;
+
+ if (valid) {
+ offset = ptz.utc_offset;
+ if ((ptz.dst_zones & 0x40000000) || (ptz.dst_zones & ptz.home_zone))
+ offset += 3600;
+ } else {
+ const char *offstr = getenv("PSI_TZ");
+ if (offstr != 0L) {
+ char *err = 0L;
+ offset = strtoul(offstr, &err, 0);
+ if (err != 0L)
+ offset = 0;
+ }
+ }
+ offset *= 1000000;
+ return offset;
+}
+
+void PsiTime::psi2unix(void) {
+ unsigned long long micro = ptv.tv_high;
+ micro = (micro << 32) | ptv.tv_low;
+
+ /* Substract Psion's idea of UTC offset */
+ micro -= evalOffset(ptz, ptzValid);
+ micro -= EPOCH_DIFF;
+
+ utv.tv_sec = micro / 1000000;
+ utv.tv_usec = micro % 1000000;
+}
+
+void PsiTime::unix2psi(void) {
+ unsigned long long micro = utv.tv_sec * 1000000 + utv.tv_usec;
+
+ /* Add Psion's idea of UTC offset */
+ micro += EPOCH_DIFF;
+ micro += evalOffset(ptz, ptzValid);
+
+ ptv.tv_low = micro & 0x0ffffffff;
+ ptv.tv_high = (micro >> 32) & 0x0ffffffff;
+}
diff --git a/lib/psitime.h b/lib/psitime.h
new file mode 100644
index 0000000..6946fc1
--- /dev/null
+++ b/lib/psitime.h
@@ -0,0 +1,198 @@
+#ifndef _PSITIME_H_
+#define _PSITIME_H_
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <ostream.h>
+
+/**
+ * Holds a Psion time value.
+ * Psion time values are 64 bit
+ * integers describing the time
+ * since 01.01.0001 in microseconds.
+ */
+typedef struct psi_timeval_t {
+ /**
+ * Prints a psi_timeval in human readable format.
+ */
+ friend ostream &operator<<(ostream &o, const psi_timeval_t &ptv) {
+ ostream::fmtflags old = o.flags();
+ unsigned long long micro = ptv.tv_high;
+ micro = (micro << 32) | ptv.tv_low;
+ micro /= 1000000;
+ int s = micro % 60;
+ micro /= 60;
+ int m = micro % 60;
+ micro /= 60;
+ int h = micro % 24;
+ micro /= 24;
+ int d = micro % 365;
+ micro /= 365;
+ int y = micro;
+ o << dec;
+ if (y > 0)
+ o << y << " year" << ((y > 1) ? "s " : " ");
+ if (d > 0)
+ o << d << " day" << ((d > 1) ? "s " : " ");
+ if (h > 0)
+ o << h << " hour" << ((h != 1) ? "s " : " ");
+ if (m > 0)
+ o << m << " minute" << ((m != 1) ? "s " : " ");
+ o << s << " second" << ((s != 1) ? "s" : "");
+ o.flags(old);
+ return o;
+ }
+ /**
+ * The lower 32 bits
+ */
+ unsigned long tv_low;
+ /**
+ * The upper 32 bits
+ */
+ unsigned long tv_high;
+} psi_timeval;
+
+/**
+ * holds a Psion time zone description.
+ */
+typedef struct psi_timezone_t {
+ friend ostream &operator<<(ostream &s, const psi_timezone_t &ptz) {
+ ostream::fmtflags old = s.flags();
+ int h = ptz.utc_offset / 3600;
+ int m = ptz.utc_offset % 3600;
+ s << "offs: " << dec << h << "h";
+ if (m != 0)
+ s << ", " << m << "m";
+ s.flags(old);
+ return s;
+ }
+ unsigned long utc_offset;
+ unsigned long dst_zones;
+ unsigned long home_zone;
+} psi_timezone;
+
+/**
+ * Psion time related utility class.
+ *
+ * PsiTime provides easy access to the time format, used
+ * when communicating with a Psion. Internally, the time
+ * is always normalized to GMT. The time value can be set
+ * and retrieved in both Unix and Psion formats. This
+ * allows easy conversion between both formats.
+ * NOTE: For proper conversion, the current timezone of
+ * the Psion has to be set. For EPOC devices, the
+ * timezone can be evaluated using
+ * @ref rpcs::getMachineInfo. For SIBO devices,
+ * unfortunately there is no known method of retrieving
+ * this information. Therefore, if the timezone is
+ * <em>not</em> set, a fallback using the environment
+ * variable <em>PSI_TZ</em> is provided. Users should
+ * set this variable to the offset of their time zone
+ * in seconds.
+ */
+class PsiTime {
+public:
+ /**
+ * Contructs a new instance.
+ *
+ * @param _ptv A Psion time value for initialization.
+ * @param _ptz A Psion timezone for initialization.
+ */
+ PsiTime(psi_timeval *_ptv = 0L, psi_timezone *_ptz = 0L);
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param _utv A Unix time value for initialization.
+ * @param _utz A Unix timezone for initialization.
+ */
+ PsiTime(struct timeval *_utv = 0L, struct timezone *_utz = 0L);
+
+ /**
+ * Destroys the instance.
+ */
+ ~PsiTime();
+
+ /**
+ * Modifies the value of this instance.
+ *
+ * @param _ptv The new Psion time representation.
+ */
+ void setPsiTime(psi_timeval *_ptv);
+
+ /**
+ * Sets the Psion time zone of this instance.
+ *
+ * @param _ptz The new Psion time zone.
+ */
+ void setPsiZone(psi_timezone *_ptz);
+
+ /**
+ * Sets the value of this instance.
+ *
+ * @param _utv The new Unix time representation.
+ */
+ void setUnixTime(struct timeval *_utv);
+
+ /**
+ * Sets the value of this instance to the
+ * current time of the Unix machine.
+ */
+ void setUnixNow(void);
+
+ /**
+ * Retrieves the instance's current value
+ * in Unix time format.
+ *
+ * @returns The instance's current time as Unix struct timeval.
+ */
+ struct timeval &getTimeval(void);
+
+ /**
+ * Retrieves the instance's current value
+ * in Unix time format.
+ *
+ * @returns The instance's current time as Unix time_t.
+ */
+ time_t getTime(void);
+
+ /**
+ * Retrieves the instance's current value
+ * in Psion time format.
+ *
+ * @returns The instance's current time a Psion struct psi_timeval_t.
+ */
+ psi_timeval &getPsiTimeval(void);
+
+ /**
+ * Prints the instance's value in human readable format.
+ * This function uses the current locale setting for
+ * formatting the time.
+ *
+ * @param s The stream to be written.
+ * @param t The instance whose value should be displayed.
+ *
+ * @returns The stream.
+ */
+ friend ostream &operator<<(ostream &s, const PsiTime &t);
+
+ enum zone {
+ PSI_TZ_NONE = 0,
+ PSI_TZ_EUROPEAN = 1,
+ PSI_TZ_NORTHERN = 2,
+ PSI_TZ_SOUTHERN = 4,
+ PSI_TZ_HOME = 0x40000000,
+ };
+
+private:
+ void psi2unix(void);
+ void unix2psi(void);
+
+ psi_timeval ptv;
+ psi_timezone ptz;
+ struct timeval utv;
+ struct timezone utz;
+ bool ptzValid;
+};
+#endif
diff --git a/lib/rfsv.h b/lib/rfsv.h
index e6006ef..888db8a 100644
--- a/lib/rfsv.h
+++ b/lib/rfsv.h
@@ -5,12 +5,29 @@ class ppsocket;
class bufferStore;
class bufferArray;
-#define RFSV_SENDLEN 2000
+const unsigned long RFSV_SENDLEN = 2000;
+/**
+ * Defines the callback procedure for
+ * progress indication of copy operations.
+ */
typedef int (*cpCallback_t)(long);
// Abstract base class of RFSV ; 16-bit and 32-bit variants implement this
// interface
+/**
+ * Access remote file services of a Psion.
+ *
+ * rfsv provides an API for accessing file services
+ * of a Psion connected via ncpd. This class defines the
+ * interface and a small amount of common constants and
+ * methods. The majority of implementation is provided
+ * by @ref rfsv32 and @ref rfsv16, which implement the
+ * variations of the protocol for EPOC and SIBO respectively.
+ * Usually, the class @ref rfsvfactory is used to instantiate
+ * the correct variant depending on the remote machine,
+ * currently connected.
+ */
class rfsv {
public:
virtual ~rfsv() {}
@@ -46,20 +63,32 @@ class rfsv {
virtual long rename(const char *, const char *) = 0;
virtual long remove(const char *) = 0;
+ virtual long attr2std(long) = 0;
+ virtual long std2attr(long) = 0;
+
char *opErr(long);
+ /**
+ * The kown modes for seek.
+ */
enum seek_mode {
PSI_SEEK_SET = 1,
PSI_SEEK_CUR = 2,
PSI_SEEK_END = 3
};
+ /**
+ * The known modes for file open.
+ */
enum open_flags {
PSI_O_RDONLY = 00,
PSI_O_WRONLY = 01,
PSI_O_RDWR = 02,
};
+ /**
+ * The known modes for file creation.
+ */
enum open_mode {
PSI_O_CREAT = 0100,
PSI_O_EXCL = 0200,
@@ -67,6 +96,9 @@ class rfsv {
PSI_O_APPEND = 02000,
};
+ /**
+ * The known error codes.
+ */
enum errs {
E_PSI_GEN_NONE = 0,
E_PSI_GEN_FAIL = -1,
@@ -145,6 +177,36 @@ class rfsv {
// Special error code for "Operation not permitted in RFSV16"
E_PSI_NOT_SIBO = -200
};
+
+ /**
+ * The known file attributes
+ */
+ enum file_attribs {
+ /**
+ * Attributes, valid on both EPOC and SIBO.
+ */
+ PSI_A_RDONLY = 0x0001,
+ PSI_A_HIDDEN = 0x0002,
+ PSI_A_SYSTEM = 0x0004,
+ PSI_A_DIR = 0x0008,
+ PSI_A_ARCHIVE = 0x0010,
+ PSI_A_VOLUME = 0x0020,
+
+ /**
+ * Attributes, valid on EPOC only.
+ */
+ PSI_A_NORMAL = 0x0040,
+ PSI_A_TEMP = 0x0080,
+ PSI_A_COMPRESSED = 0x0100,
+
+ /**
+ * Attributes, valid on SIBO only.
+ */
+ PSI_A_READ = 0x0200,
+ PSI_A_EXEC = 0x0400,
+ PSI_A_STREAM = 0x0800,
+ PSI_A_TEXT = 0x1000
+ };
};
#endif
diff --git a/lib/rfsv16.cc b/lib/rfsv16.cc
index 9ee24f2..f71be9f 100644
--- a/lib/rfsv16.cc
+++ b/lib/rfsv16.cc
@@ -37,6 +37,8 @@
#include "ppsocket.h"
#include "bufferarray.h"
+#define RFSV16_MAXDATALEN 852 // 640
+
rfsv16::rfsv16(ppsocket *_skt) : serNum(0)
{
skt = _skt;
@@ -57,7 +59,6 @@ rfsv16::~rfsv16()
void rfsv16::
reconnect()
{
-cerr << "rfsv16::reconnect" << endl;
skt->closeSocket();
skt->reconnect();
serNum = 0;
@@ -68,7 +69,6 @@ cerr << "rfsv16::reconnect" << endl;
void rfsv16::
reset()
{
-cerr << "rfsv16::reset" << endl;
bufferStore a;
status = E_PSI_FILE_DISC;
a.addStringT(getConnectName());
@@ -91,7 +91,7 @@ getStatus()
const char *rfsv16::
getConnectName()
{
- return "SYS$RFSV.*";
+ return "SYS$RFSV";
}
int rfsv16::
@@ -148,14 +148,10 @@ fopen(long attr, const char *name, long &handle)
return E_PSI_FILE_DISC;
long res = getResponse(a);
- // cerr << "fopen, getword 0 is " << hex << setw(2) << a.getWord(0) << endl;
- // cerr << "fopen, getlen is " << hex << setw(2) << a.getLen() << endl;
- // cerr << "fopen, res is " << hex << setw(2) << res << endl;
- if (!res && a.getLen() == 4 && a.getWord(0) == 0) {
- handle = (long)a.getWord(2);
+ if (res == 0) {
+ handle = (long)a.getWord(0);
return 0;
}
- // cerr << "fopen: Unknown response (" << attr << "," << name << ") " << a <<endl;
return res;
}
@@ -163,24 +159,38 @@ fopen(long attr, const char *name, long &handle)
long rfsv16::
mktemp(long *handle, char *tmpname)
{
-cerr << "rfsv16::mktemp ***" << endl;
- return 0;
+ bufferStore a;
+
+ // FIXME: anything that calls fopen should NOT do the name
+ // conversion - it's just done here.
+
+ a.addWord(P_FUNIQUE);
+ a.addString("TMP");
+ a.addByte(0x00); // Needs to be manually Null-Terminated.
+ if (!sendCommand(OPENUNIQUE, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res == 0) {
+ *handle = a.getWord(0);
+ strcpy(tmpname, a.getString(2));
+ return 0;
+ }
+ return res;
}
// internal and external
long rfsv16::
fcreatefile(long attr, const char *name, long &handle)
{
-cerr << "rfsv16::fcreatefile ***" << endl;
- return 0;
+ return fopen(attr | P_FCREATE, name, handle);
}
// this is internal - not used by plpnfsd, unlike fcreatefile
long rfsv16::
freplacefile(long attr, const char *name, long &handle)
{
-cerr << "rfsv16::freplacefile ***" << endl;
- return 0;
+ return fopen(attr | P_FREPLACE, name, handle);
}
// internal
@@ -198,11 +208,7 @@ fclose(long fileHandle)
a.addWord(fileHandle & 0xFFFF);
if (!sendCommand(FCLOSE, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- if (!res && a.getLen() == 2)
- return (long)a.getWord(0);
- cerr << "fclose: Unknown response "<< a <<endl;
- return 1;
+ return getResponse(a);
}
long rfsv16::
@@ -224,7 +230,7 @@ dir(const char *dirName, bufferArray * files)
res = getResponse(a);
if (res)
break;
- a.discardFirstBytes(4); // Don't know what these mean!
+ a.discardFirstBytes(2); // Don't know what these mean!
while (a.getLen() > 16) {
int version = a.getWord(0);
if (version != 2) {
@@ -242,7 +248,7 @@ dir(const char *dirName, bufferArray * files)
temp.addDWord(size);
temp.addDWord((long)status);
temp.addStringT(s);
- files->pushBuffer(temp);
+ files->append(temp);
}
}
if ((short int)res == E_PSI_FILE_EOF)
@@ -300,15 +306,13 @@ cerr << "rfsv16::fgetmtime" << endl;
return E_PSI_FILE_DISC;
long res = getResponse(a);
- if (res != 0)
+ if (res != 0) {
+ cerr << "fgetmtime: Error " << res << " on file " << name << endl;
return res;
- if (a.getLen() == 2) {
- cerr << "fgetmtime: Error " << a.getWord(0) << " on file " << name << endl;
- return 1;
}
- else if (a.getLen() == 18 && a.getWord(0) == 0) {
- *mtime = a.getDWord(10);
- return a.getWord(0);
+ else if (a.getLen() == 16) {
+ *mtime = a.getDWord(8);
+ return res;
}
cerr << "fgetmtime: Unknown response (" << name << ") " << a <<endl;
return 1;
@@ -338,15 +342,13 @@ fgetattr(const char *name, long *attr)
return E_PSI_FILE_DISC;
long res = getResponse(a);
- if (res != 0)
+ if (res != 0) {
+ cerr << "fgetattr: Error " << res << " on file " << name << endl;
return res;
- if (a.getLen() == 2) {
- cerr << "fgetattr: Error " << a.getWord(0) << " on file " << name << endl;
- return 1;
}
- else if (a.getLen() == 18 && a.getWord(0) == 0) {
- *attr = (long)(a.getWord(4));
- return a.getWord(0);
+ else if (a.getLen() == 16) {
+ *attr = (long)(a.getWord(2));
+ return res;
}
cerr << "fgetattr: Unknown response (" << name << ") " << a <<endl;
return 1;
@@ -366,17 +368,15 @@ fgeteattr(const char *name, long *attr, long *size, long *time)
return E_PSI_FILE_DISC;
long res = getResponse(a);
- if (res != 0)
- return res;
- if (a.getLen() == 2) {
+ if (res != 0) {
cerr << "fgeteattr: Error " << a.getWord(0) << " on file " << name << endl;
- return 1;
+ return res;
}
- else if (a.getLen() == 18 && a.getWord(0) == 0) {
- *attr = (long)(a.getWord(4));
- *size = a.getDWord(6);
- *time = a.getDWord(10);
- return a.getWord(0);
+ else if (a.getLen() == 16) {
+ *attr = (long)(a.getWord(2));
+ *size = a.getDWord(4);
+ *time = a.getDWord(8);
+ return res;
}
cerr << "fgeteattr: Unknown response (" << name << ") " << a <<endl;
return 1;
@@ -429,7 +429,7 @@ dircount(const char *name, long *count)
res = getResponse(a);
if (res)
break;
- a.discardFirstBytes(4); // Don't know what these mean!
+ a.discardFirstBytes(2); // Don't know what these mean!
while (a.getLen() > 16) {
int version = a.getWord(0);
if (version != 2) {
@@ -475,7 +475,7 @@ devlist(long *devbits)
// Find the drive to FOPEN
char name[4] = { 'x', ':', '\\', '\0' } ;
- a.discardFirstBytes(8); // Result, fsys, dev, path, file, file, ending, flag
+ a.discardFirstBytes(6); // Result, fsys, dev, path, file, file, ending, flag
/* This leaves R E M : : M : \ */
name[0] = (char) a.getByte(5); // the M
long status = fopen(P_FDEVICE, name, fileHandle);
@@ -491,7 +491,6 @@ devlist(long *devbits)
res = getResponse(a);
if (res)
break;
- a.discardFirstBytes(2); // Result
int version = a.getWord(0);
if (version != 2) {
cerr << "devlist: not version 2" << endl;
@@ -551,7 +550,6 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
// cerr << "devinfo STATUSDEVICE res is " << dec << (signed short int) res << endl;
return NULL;
}
- a.discardFirstBytes(2); // Result
int type = a.getWord(2);
int changeable = a.getWord(4);
long size = a.getDWord(6);
@@ -571,14 +569,24 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
bool rfsv16::
sendCommand(enum commands cc, bufferStore & data)
{
+ if (status == E_PSI_FILE_DISC) {
+ reconnect();
+ if (status == E_PSI_FILE_DISC)
+ return FALSE;
+ }
+
bool result;
bufferStore a;
a.addWord(cc);
a.addWord(data.getLen());
a.addBuff(data);
result = skt->sendBufferStore(a);
+ if (!result) {
+ reconnect();
+ result = skt->sendBufferStore(a);
if (!result)
status = E_PSI_FILE_DISC;
+ }
return result;
}
@@ -589,17 +597,22 @@ getResponse(bufferStore & data)
// getWord(2) is the size field
// which is the body of the response not counting the command (002a) and
// the size word.
- if (skt->getBufferStore(data) == 1 &&
- data.getWord(0) == 0x2a &&
+ if (skt->getBufferStore(data) != 1) {
+ cerr << "rfsv16::getResponse: duff response. "
+ "getBufferStore failed." << endl;
+ } else if (data.getWord(0) == 0x2a &&
data.getWord(2) == data.getLen()-4) {
- data.discardFirstBytes(4);
- long ret = data.getWord(0);
+ long ret = (short)data.getWord(4);
+ data.discardFirstBytes(6);
return ret;
- } else
- status = E_PSI_FILE_DISC;
+ } else {
cerr << "rfsv16::getResponse: duff response. Size field:" <<
-data.getWord(2) << " Frame size:" << data.getLen()-4 << " Result field:" <<
-data.getWord(4) << endl;
+ data.getWord(2) << " Frame size:" <<
+ data.getLen()-4 << " Result field:" <<
+ data.getWord(4) << endl;
+ }
+
+ status = E_PSI_FILE_DISC;
return status;
}
@@ -614,61 +627,88 @@ cerr << "rfsv16::opErr 0x" << hex << setfill('0') << setw(4)
long rfsv16::
fread(long handle, unsigned char *buf, long len)
{
-cerr << "rfsv16::fread ***" << endl;
+ long res;
+ long count = 0;
+
+ while (count < len) {
bufferStore a;
- long remaining = len;
- // Read in blocks of 291 bytes; the maximum payload for an RFSV frame.
- // ( As seen in traces ) - this isn't optimal: RFSV can handle
- // fragmentation of frames, where only the first FREAD RESPONSE frame
- // has a RESPONSE (00 2A), SIZE and RESULT field. Every subsequent frame
+
+ // Read in blocks of 291 bytes; the maximum payload for
+ // an RFSV frame. ( As seen in traces ) - this isn't optimal:
+ // RFSV can handle fragmentation of frames, where only the
+ // first FREAD RESPONSE frame has a RESPONSE (00 2A), SIZE
+ // and RESULT field. Every subsequent frame
// just has data, 297 bytes (or less) of it.
- const int maxblock = 291;
- long readsofar = 0;
- while (remaining) {
- long thisblock = (remaining > maxblock) ? maxblock : remaining;
-cerr << "fread: " << dec << remaining << " bytes remain. This block is " << thisblock
-<< " bytes." << endl;
- a.init();
a.addWord(handle);
- a.addWord(thisblock);
+ a.addWord((len - count) > RFSV16_MAXDATALEN
+ ? RFSV16_MAXDATALEN
+ : (len - count));
sendCommand(FREAD, a);
- long res = getResponse(a);
- remaining -= a.getLen();
-// copy the data to buf
+ res = getResponse(a);
-cerr << "fread getResponse returned " << dec<< (signed short int) res << " data: " << a << dec <<endl;
- if (res) {
+ // The rest of the code treats a 0 return from here
+ // as meaning EOF, so we'll arrange for that to happen.
+ if (res == E_PSI_FILE_EOF)
+ return count;
+ else if (res < 0)
return res;
+
+ res = a.getLen();
+ memcpy(buf, a.getString(), res);
+ count += res;
+ buf += res;
}
- }
- return len;
+ return count;
}
long rfsv16::
fwrite(long handle, unsigned char *buf, long len)
{
-cerr << "rfsv16::fwrite ***" << endl;
- return 0;
+ long res;
+ long count = 0;
+
+ while (count < len) {
+ bufferStore a;
+ int nbytes;
+
+ // Write in blocks of 291 bytes; the maximum payload for
+ // an RFSV frame. ( As seen in traces ) - this isn't optimal:
+ // RFSV can handle fragmentation of frames, where only the
+ // first FREAD RESPONSE frame has a RESPONSE (00 2A), SIZE
+ // and RESULT field. Every subsequent frame
+ // just has data, 297 bytes (or less) of it.
+ nbytes = (len - count) > RFSV16_MAXDATALEN
+ ? RFSV16_MAXDATALEN
+ : (len - count);
+ a.addWord(handle);
+ a.addBytes(buf, nbytes);
+ sendCommand(FWRITE, a);
+ res = getResponse(a);
+ if (res != 0)
+ return res;
+
+ count += nbytes;
+ buf += nbytes;
+ }
+ return count;
}
long rfsv16::
copyFromPsion(const char *from, const char *to, cpCallback_t cb)
{
-cerr << "rfsv16::copyFromPsion" << endl;
long handle;
long res;
long len;
if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle)) != 0)
return res;
-cerr << "fopen response is " << dec << (signed short int)res << endl;
ofstream op(to);
if (!op) {
fclose(handle);
return -1;
}
do {
- unsigned char buf[2000];
+ unsigned char buf[RFSV_SENDLEN];
if ((len = fread(handle, buf, sizeof(buf))) > 0)
op.write(buf, len);
if (cb) {
@@ -681,13 +721,12 @@ cerr << "fopen response is " << dec << (signed short int)res << endl;
fclose(handle);
op.close();
- return len;
+ return len == E_PSI_FILE_EOF ? 0 : len;
}
long rfsv16::
copyToPsion(const char *from, const char *to, cpCallback_t cb)
{
-cerr << "rfsv16::copyToPsion" << endl;
long handle;
long res;
@@ -701,50 +740,30 @@ cerr << "rfsv16::copyToPsion" << endl;
return res;
}
unsigned char *buff = new unsigned char[RFSV_SENDLEN];
- int total = 0;
- while (ip && !ip.eof()) {
+ while (res >= 0 && ip && !ip.eof()) {
ip.read(buff, RFSV_SENDLEN);
- bufferStore tmp(buff, ip.gcount());
- int len = tmp.getLen();
- total += len;
- if (len == 0)
- break;
- bufferStore a;
- a.addDWord(handle);
- a.addBuff(tmp);
- if (!sendCommand(FWRITE, a)) { // FIXME: need to check params
- fclose(handle);
- ip.close();
- delete[]buff;
- return E_PSI_FILE_DISC;
+ res = fwrite(handle, buff, ip.gcount());
+ if (cb)
+ if (!cb(res)) {
+ res = E_PSI_FILE_CANCEL;
}
- res = getResponse(a);
- if (res) {
- fclose(handle);
- ip.close();
- delete[]buff;
- return res;
}
- if (cb) {
- if (!cb(len)) {
- fclose(handle);
- ip.close();
+
delete[]buff;
- return E_PSI_FILE_CANCEL;
- }
- }
- }
fclose(handle);
ip.close();
- delete[]buff;
return 0;
}
long rfsv16::
fsetsize(long handle, long size)
{
-cerr << "rfsv16::fsetsize ***" << endl;
- return 0;
+ bufferStore a;
+ a.addWord(handle);
+ a.addDWord(size);
+ if (!sendCommand(FSETEOF, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
}
/*
@@ -755,8 +774,92 @@ cerr << "rfsv16::fsetsize ***" << endl;
long rfsv16::
fseek(long handle, long pos, long mode)
{
-cerr << "rfsv16::fseek ***" << endl;
- return 0;
+ bufferStore a;
+ long res;
+ long savpos = 0;
+ long realpos;
+ long calcpos = 0;
+
+/*
+ seek-parameter for psion:
+ dword position
+ dword handle
+ dword mode
+ 1 = from start
+ 2 = from current pos
+ 3 = from end
+ ??no more?? 4 = sense recpos
+ ??no more?? 5 = set recpos
+ ??no more?? 6 = text-rewind
+ */
+
+ if ((mode < PSI_SEEK_SET) || (mode > PSI_SEEK_END))
+ return E_PSI_GEN_ARG;
+
+ if ((mode == PSI_SEEK_CUR) && (pos >= 0)) {
+ /* get and save current position */
+ a.init();
+ a.addWord(handle);
+ a.addDWord(0);
+ a.addWord(PSI_SEEK_CUR);
+ if (!sendCommand(FSEEK, a))
+ return E_PSI_FILE_DISC;
+ if ((res = getResponse(a)) != 0)
+ return res;
+ savpos = a.getDWord(0);
+ if (pos == 0)
+ return savpos;
+ }
+ if ((mode == PSI_SEEK_END) && (pos >= 0)) {
+ /* get and save end position */
+ a.init();
+ a.addWord(handle);
+ a.addDWord(0);
+ a.addWord(PSI_SEEK_END);
+ if (!sendCommand(FSEEK, a))
+ return E_PSI_FILE_DISC;
+ if ((res = getResponse(a)) != 0)
+ return res;
+ savpos = a.getDWord(0);
+ if (pos == 0)
+ return savpos;
+ }
+ /* Now the real seek */
+ a.addWord(handle);
+ a.addDWord(pos);
+ a.addWord(mode);
+ if (!sendCommand(FSEEK, a))
+ return E_PSI_FILE_DISC;
+ if ((res = getResponse(a)) != 0)
+ return res;
+ realpos = a.getDWord(0);
+ switch (mode) {
+ case PSI_SEEK_SET:
+ calcpos = pos;
+ break;
+ case PSI_SEEK_CUR:
+ calcpos = savpos + pos;
+ break;
+ case PSI_SEEK_END:
+ return realpos;
+ break;
+ }
+ if (calcpos > realpos) {
+ /* Beyond end of file */
+ res = fsetsize(handle, calcpos);
+ if (res != 0)
+ return res;
+ a.init();
+ a.addWord(handle);
+ a.addDWord(calcpos);
+ a.addWord(PSI_SEEK_SET);
+ if (!sendCommand(FSEEK, a))
+ return E_PSI_FILE_DISC;
+ if ((res = getResponse(a)) != 0)
+ return res;
+ realpos = a.getDWord(0);
+ }
+ return realpos;
}
long rfsv16::
@@ -771,11 +874,11 @@ mkdir(const char* dirName)
// and this needs sending in the length word.
sendCommand(MKDIR, a);
long res = getResponse(a);
- if (!res && a.getLen() == 2) {
+ if (!res) {
// Correct response
- return a.getWord(0);
+ return res;
}
- cerr << "Unknown response from mkdir "<< a <<endl;
+ cerr << "Unknown response from mkdir "<< res <<endl;
return 1;
}
@@ -806,11 +909,11 @@ cerr << "rfsv16::rename ***" << endl;
// and this needs sending in the length word.
sendCommand(RENAME, a);
long res = getResponse(a);
- if (!res && a.getLen() == 2) {
+ if (!res) {
// Correct response
- return a.getWord(0);
+ return res;
}
- cerr << "Unknown response from rename "<< a <<endl;
+ cerr << "Unknown response from rename "<< res <<endl;
return 1;
}
@@ -826,12 +929,85 @@ remove(const char* psionName)
// and this needs sending in the length word.
sendCommand(DELETE, a);
long res = getResponse(a);
- if (!res && a.getLen() == 2) {
+ if (!res) {
// Correct response
- return a.getWord(0);
+ return res;
}
- cerr << "Unknown response from delete "<< a <<endl;
+ cerr << "Unknown response from delete "<< res <<endl;
return 1;
}
+/*
+ * Translate SIBO attributes to standard attributes.
+ */
+long rfsv16::
+attr2std(long attr)
+{
+ long res = 0;
+
+ // Common attributes
+ if (!(attr & P_FAWRITE))
+ res |= PSI_A_RDONLY;
+ if (attr & P_FAHIDDEN)
+ res |= PSI_A_HIDDEN;
+ if (attr & P_FASYSTEM)
+ res |= PSI_A_SYSTEM;
+ if (attr & P_FADIR)
+ res |= PSI_A_DIR;
+ if (attr & P_FAMOD)
+ res |= PSI_A_ARCHIVE;
+ if (attr & P_FAVOLUME)
+ res |= PSI_A_VOLUME;
+
+ // SIBO-specific
+ if (attr & P_FAREAD)
+ res |= PSI_A_READ;
+ if (attr & P_FAEXEC)
+ res |= PSI_A_EXEC;
+ if (attr & P_FASTREAM)
+ res |= PSI_A_STREAM;
+ if (attr & P_FATEXT)
+ res |= PSI_A_TEXT;
+
+ // Do what we can for EPOC
+ res |= PSI_A_NORMAL;
+
+ return res;
+}
+
+/*
+ * Translate standard attributes to SIBO attributes.
+ */
+long rfsv16::
+std2attr(long attr)
+{
+ long res = 0;
+
+ // Common attributes
+ if (!(attr & PSI_A_RDONLY))
+ res |= P_FAWRITE;
+ if (attr & PSI_A_HIDDEN)
+ res |= P_FAHIDDEN;
+ if (attr & PSI_A_SYSTEM)
+ res |= P_FASYSTEM;
+ if (attr & PSI_A_DIR)
+ res |= P_FADIR;
+ if (attr & PSI_A_ARCHIVE)
+ res |= P_FAMOD;
+ if (attr & PSI_A_VOLUME)
+ res |= P_FAVOLUME;
+
+ // SIBO-specific
+ if (attr & PSI_A_READ)
+ res |= P_FAREAD;
+ if (attr & PSI_A_EXEC)
+ res |= P_FAEXEC;
+ if (attr & PSI_A_STREAM)
+ res |= P_FASTREAM;
+ if (attr & PSI_A_TEXT)
+ res |= P_FATEXT;
+
+ return res;
+}
+
diff --git a/lib/rfsv16.h b/lib/rfsv16.h
index 175e540..bb6a947 100644
--- a/lib/rfsv16.h
+++ b/lib/rfsv16.h
@@ -46,6 +46,9 @@ class rfsv16 : public rfsv {
char *opAttr(long);
long opMode(long);
+ long attr2std(long);
+ long std2attr(long);
+
private:
enum commands {
FOPEN = 0, // File Open
diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc
index 69136a3..3980eb9 100644
--- a/lib/rfsv32.cc
+++ b/lib/rfsv32.cc
@@ -203,8 +203,17 @@ micro2time(unsigned long microHi, unsigned long microLo)
micro /= 1000000;
micro -= pes;
micro += EPOCH_DIFF_SECS;
- micro -= EPOCH_2H;
- micro += 3600; /* 1 hour PJC */
+
+ /* Adjust for timezone and daylight saving time */
+ {
+ struct tm *t;
+ long date=micro;
+
+ t = localtime(&date);
+ micro += timezone; /* Adjust for timezone */
+ if (t->tm_isdst) micro -= (60*60); /* Adjust for DST */
+ }
+
return (long) micro;
}
@@ -216,8 +225,17 @@ time2micro(unsigned long time, unsigned long &microHi, unsigned long &microLo)
pes <<= 8;
micro += pes;
micro -= EPOCH_DIFF_SECS;
- micro += EPOCH_2H;
- micro -= 3600; /* 1 hour PJC */
+
+ /* Adjust for timezone and daylight saving time */
+ {
+ struct tm *t;
+ long date=time;
+
+ t = localtime(&date);
+ micro -= timezone; /* Adjust for timezone */
+ if (t->tm_isdst) micro += (60*60); /* Adjust for DST */
+ }
+
micro *= (unsigned long long)1000000;
microLo = (micro & (unsigned long long)0x0FFFFFFFF);
micro >>= 32;
@@ -263,7 +281,7 @@ dir(const char *name, bufferArray * files)
s.addByte(0);
while (d % 4)
d++;
- files->pushBuffer(s);
+ files->append(s);
d += shortLen;
while (d % 4)
d++;
@@ -495,8 +513,12 @@ sendCommand(enum commands cc, bufferStore & data)
serNum = 0;
a.addBuff(data);
result = skt->sendBufferStore(a);
+ if (!result) {
+ reconnect();
+ result = skt->sendBufferStore(a);
if (!result)
status = E_PSI_FILE_DISC;
+ }
return result;
}
@@ -888,3 +910,73 @@ err2psierr(long status)
}
return e2psi[status - E_EPOC_DIR_FULL];
}
+
+
+/*
+ * Translate EPOC attributes to standard attributes.
+ */
+long rfsv32::
+attr2std(long attr)
+{
+ long res = 0;
+
+ // Common attributes
+ if (attr & EPOC_ATTR_RONLY)
+ res |= PSI_A_RDONLY;
+ if (attr & EPOC_ATTR_HIDDEN)
+ res |= PSI_A_HIDDEN;
+ if (attr & EPOC_ATTR_SYSTEM)
+ res |= PSI_A_SYSTEM;
+ if (attr & EPOC_ATTR_DIRECTORY)
+ res |= PSI_A_DIR;
+ if (attr & EPOC_ATTR_ARCHIVE)
+ res |= PSI_A_ARCHIVE;
+ if (attr & EPOC_ATTR_VOLUME)
+ res |= PSI_A_VOLUME;
+
+ // EPOC-specific
+ if (attr & EPOC_ATTR_NORMAL)
+ res |= PSI_A_NORMAL;
+ if (attr & EPOC_ATTR_TEMPORARY)
+ res |= PSI_A_TEMP;
+ if (attr & EPOC_ATTR_COMPRESSED)
+ res |= PSI_A_COMPRESSED;
+
+ // Do what we can for SIBO
+ res |= PSI_A_READ;
+
+ return res;
+}
+
+/*
+ * Translate standard attributes to EPOC attributes.
+ */
+long rfsv32::
+std2attr(long attr)
+{
+ long res = 0;
+
+ // Common attributes
+ if (!(attr & PSI_A_RDONLY))
+ res |= EPOC_ATTR_RONLY;
+ if (attr & PSI_A_HIDDEN)
+ res |= EPOC_ATTR_HIDDEN;
+ if (attr & PSI_A_SYSTEM)
+ res |= EPOC_ATTR_SYSTEM;
+ if (attr & PSI_A_DIR)
+ res |= EPOC_ATTR_DIRECTORY;
+ if (attr & PSI_A_ARCHIVE)
+ res |= EPOC_ATTR_ARCHIVE;
+ if (attr & PSI_A_VOLUME)
+ res |= EPOC_ATTR_VOLUME;
+
+ // EPOC-specific
+ if (attr & PSI_A_NORMAL)
+ res |= EPOC_ATTR_NORMAL;
+ if (attr & PSI_A_TEMP)
+ res |= EPOC_ATTR_TEMPORARY;
+ if (attr & PSI_A_COMPRESSED)
+ res |= EPOC_ATTR_COMPRESSED;
+
+ return res;
+}
diff --git a/lib/rfsv32.h b/lib/rfsv32.h
index 8383e72..2aac5b9 100644
--- a/lib/rfsv32.h
+++ b/lib/rfsv32.h
@@ -44,6 +44,9 @@ class rfsv32 : public rfsv {
char *opAttr(long);
long opMode(long);
+ long attr2std(long);
+ long std2attr(long);
+
private:
enum file_attrib {
diff --git a/lib/rpcs.cc b/lib/rpcs.cc
index 5863c5b..79630cf 100644
--- a/lib/rpcs.cc
+++ b/lib/rpcs.cc
@@ -28,11 +28,21 @@
#include "ppsocket.h"
#include "bufferarray.h"
+static const char * const langstrings[] = {
+ "Test", "English", "French", "German", "Spanish", "Italian", "Swedish",
+ "Danish", "Norwegian", "Finnish", "American", "Swiss French",
+ "Swiss German", "Portugese", "Turkish", "Icelandic", "Russian",
+ "Hungarian", "Dutch", "Belgian Flemish", "Australian",
+ "Belgish French", "Austrian", "New Zealand",
+ "International French", "Czech", "Slovak", "Polish", "Slovenian",
+ 0L
+};
+
//
// public common API
//
void rpcs::
-reconnect()
+reconnect(void)
{
skt->closeSocket();
skt->reconnect();
@@ -40,7 +50,7 @@ reconnect()
}
void rpcs::
-reset()
+reset(void)
{
bufferStore a;
status = E_PSI_FILE_DISC;
@@ -54,13 +64,13 @@ reset()
}
long rpcs::
-getStatus()
+getStatus(void)
{
return status;
}
const char *rpcs::
-getConnectName()
+getConnectName(void)
{
return "SYS$RPCS";
}
@@ -68,16 +78,6 @@ getConnectName()
//
// protected internals
//
-char *rpcs::
-convertSlash(const char *name)
-{
- char *n = strdup(name);
- for (char *p = n; *p; p++)
- if (*p == '/')
- *p = '\\';
- return n;
-}
-
bool rpcs::
sendCommand(enum commands cc, bufferStore & data)
{
@@ -91,16 +91,21 @@ sendCommand(enum commands cc, bufferStore & data)
a.addByte(cc);
a.addBuff(data);
result = skt->sendBufferStore(a);
- if (!result)
- status = E_PSI_FILE_DISC;
+ if (!result) {
+ reconnect();
+ result = skt->sendBufferStore(a);
+ if (!result)
+ status = E_PSI_FILE_DISC;
+ }
return result;
}
-long rpcs::
+int rpcs::
getResponse(bufferStore & data)
{
if (skt->getBufferStore(data) == 1) {
- long ret = data.getByte(0);
+ char ret = data.getByte(0);
+ data.discardFirstBytes(1);
return ret;
} else
status = E_PSI_FILE_DISC;
@@ -113,12 +118,12 @@ getResponse(bufferStore & data)
int rpcs::
getNCPversion(int &major, int &minor)
{
+ int res;
bufferStore a;
+
if (!sendCommand(QUERY_NCP, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
if (a.getLen() != 2)
return E_PSI_GEN_FAIL;
@@ -131,6 +136,7 @@ int rpcs::
execProgram(const char *program, const char *args)
{
bufferStore a;
+
a.addStringT(program);
int l = strlen(program);
for (int i = 127; i > l; i--)
@@ -139,15 +145,14 @@ execProgram(const char *program, const char *args)
a.addStringT(args);
if (!sendCommand(EXEC_PROG, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
-cout << res << " " << a << endl;
- return res;
+ return getResponse(a);
}
int rpcs::
stopProgram(const char *program)
{
bufferStore a;
+
a.addStringT(program);
if (!sendCommand(STOP_PROG, a))
return E_PSI_FILE_DISC;
@@ -158,6 +163,7 @@ int rpcs::
queryProgram(const char *program)
{
bufferStore a;
+
a.addStringT(program);
if (!sendCommand(QUERY_PROG, a))
return E_PSI_FILE_DISC;
@@ -167,13 +173,13 @@ queryProgram(const char *program)
int rpcs::
formatOpen(const char *drive, int &handle, int &count)
{
+ int res;
bufferStore a;
+
a.addStringT(drive);
if (!sendCommand(FORMAT_OPEN, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
if (a.getLen() != 4)
return E_PSI_GEN_FAIL;
@@ -186,6 +192,7 @@ int rpcs::
formatRead(int handle)
{
bufferStore a;
+
a.addWord(handle);
if (!sendCommand(FORMAT_READ, a))
return E_PSI_FILE_DISC;
@@ -195,13 +202,13 @@ formatRead(int handle)
int rpcs::
getUniqueID(const char *device, long &id)
{
+ int res;
bufferStore a;
+
a.addStringT(device);
if (!sendCommand(GET_UNIQUEID, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
if (a.getLen() != 4)
return E_PSI_GEN_FAIL;
@@ -210,14 +217,14 @@ getUniqueID(const char *device, long &id)
}
int rpcs::
-getOwnerInfo(bufferArray &ret)
+getOwnerInfo(bufferArray &owner)
{
+ int res;
bufferStore a;
+
if (!sendCommand(GET_OWNERINFO, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
a.addByte(0);
int l = a.getLen();
@@ -225,13 +232,18 @@ getOwnerInfo(bufferArray &ret)
for (int i = 0; i < l; i++)
if (s[i] == 6)
s[i] = 0;
- ret.clear();
+ owner.clear();
while (l > 0) {
- bufferStore b;
- b.addStringT(s);
- ret += b;
- l -= (strlen(s) + 1);
- s += (strlen(s) + 1);
+ if (*s != '\0') {
+ bufferStore b;
+ b.addStringT(s);
+ owner += b;
+ l -= (strlen(s) + 1);
+ s += (strlen(s) + 1);
+ } else {
+ l--;
+ s++;
+ }
}
return res;
}
@@ -239,12 +251,12 @@ getOwnerInfo(bufferArray &ret)
int rpcs::
getMachineType(int &type)
{
+ int res;
bufferStore a;
+
if (!sendCommand(GET_MACHINETYPE, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
if (a.getLen() != 2)
return E_PSI_GEN_FAIL;
@@ -253,27 +265,25 @@ getMachineType(int &type)
}
int rpcs::
-fuser(const char *name, char *buf, int bufsize)
+fuser(const char *name, char *buf, int maxlen)
{
+ int res;
bufferStore a;
+ char *p;
+
a.addStringT(name);
if (!sendCommand(FUSER, a))
return E_PSI_FILE_DISC;
- long res = getResponse(a);
- a.discardFirstBytes(1);
- if (res)
+ if ((res = getResponse(a)))
return res;
- int len = ((int)a.getLen() > bufsize) ? bufsize - 1 : a.getLen();
- strncpy(buf, a.getString(0), len);
- buf[len] = '\0';
- char *p;
+ strncpy(buf, a.getString(0), maxlen - 1);
while ((p = strchr(buf, 6)))
- *p = '\n';
+ *p = '\0';
return res;
}
int rpcs::
-quitServer()
+quitServer(void)
{
bufferStore a;
if (!sendCommand(QUIT_SERVER, a))
@@ -281,3 +291,25 @@ quitServer()
return getResponse(a);
}
+const char *rpcs::
+languageString(int code) {
+ for (int i = 0; i <= code; i++)
+ if (langstrings[i] == 0L)
+ return "Unknown";
+ return langstrings[code];
+}
+
+const char *rpcs::
+batteryStatusString(int code) {
+ switch (code) {
+ case PSI_BATT_DEAD:
+ return "Empty";
+ case PSI_BATT_VERYLOW:
+ return "Very low";
+ case PSI_BATT_LOW:
+ return "Low";
+ case PSI_BATT_GOOD:
+ return "Good";
+ }
+ return "Unknown";
+}
diff --git a/lib/rpcs.h b/lib/rpcs.h
index cb71c88..3c569bb 100644
--- a/lib/rpcs.h
+++ b/lib/rpcs.h
@@ -1,37 +1,252 @@
#ifndef _rpcs_h_
#define _rpcs_h_
+#include "psitime.h"
+
class ppsocket;
class bufferStore;
class bufferArray;
+/**
+ * This struct holds the data returned
+ * by @ref rpcs::getMachineInfo.
+ */
+typedef struct machineInfo_t {
+ unsigned long machineType;
+ char machineName[17];
+ unsigned long long machineUID;
+ unsigned long countryCode;
+ char uiLanguage[32];
+
+ unsigned short romMajor;
+ unsigned short romMinor;
+ unsigned short romBuild;
+ unsigned long romSize;
+ bool romProgrammable;
+
+ unsigned long ramSize;
+ unsigned long ramFree;
+ unsigned long ramMaxFree;
+ unsigned long ramDiskSize;
+
+ unsigned long registrySize;
+ unsigned long displayWidth;
+ unsigned long displayHeight;
+
+ psi_timeval time;
+ psi_timezone tz;
+
+ psi_timeval mainBatteryInsertionTime;
+ unsigned long mainBatteryStatus;
+ psi_timeval mainBatteryUsedTime;
+ unsigned long mainBatteryCurrent;
+ unsigned long mainBatteryUsedPower;
+ unsigned long mainBatteryVoltage;
+ unsigned long mainBatteryMaxVoltage;
+
+ unsigned long backupBatteryStatus;
+ unsigned long backupBatteryVoltage;
+ unsigned long backupBatteryMaxVoltage;
+ psi_timeval backupBatteryUsedTime;
+
+ bool externalPower;
+} machineInfo;
+
+/**
+ * Remote procedure call services via PLP
+ *
+ * rpcs provides an interface for communicating
+ * with the Psion's remote procedure call
+ * service. The generic facilities for both,
+ * EPOC and SIBO are implemented here, while
+ * the facilities, unique to each of those
+ * variants are implemented in
+ * @ref rpcs32 or @ref rpcs16 respectively.
+ * These normally are instantiated by using
+ * @ref rpcsfactory.
+ */
class rpcs {
public:
+ /**
+ * Provides a virtual destructor.
+ */
virtual ~rpcs() {};
+
+ /**
+ * Initializes a connection to the remote
+ * machine.
+ */
void reset();
+
+ /**
+ * Attempts to re-establish a remote
+ * connection by first closing the socket,
+ * then connecting again to the ncpd daemon
+ * and finally calling @ref reset.
+ */
void reconnect();
+
+ /**
+ * Retrieves the current status of the
+ * connection.
+ *
+ * @returns The connection status.
+ */
long getStatus();
- // API idendical on SIBO and EPOC
- int getNCPversion(int &, int &);
- int execProgram(const char *, const char *);
+ /**
+ * Retrieves the version of the NCP protocol
+ * on the remote side.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices.
+ *
+ * @param major The major part of the NCP version.
+ * Valid only if returned with no error.
+ * @param minor The minor part of the NCP version.
+ * Valid only if returned with no error.
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
+ int getNCPversion(int &major, int &minor);
+
+ /**
+ * Starts execution of a program on the remote machine.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices.
+ *
+ * @param program The full path of the executable
+ * on the remote machine
+ * @param args The arguments for this program, separated
+ * by space.
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
+ int execProgram(const char *program, const char *args);
+
+ /**
+ * Requests termination of a program running on the
+ * remote machine.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices.
+ *
+ * @param program
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
int stopProgram(const char *);
int queryProgram(const char *);
int formatOpen(const char *, int &, int &);
int formatRead(int);
int getUniqueID(const char *, long &);
+
+ /**
+ * Retrieve owner information of the remote machine.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices.
+ *
+ * @param owner A bufferArray, containing the lines
+ * of the owner info upon return.
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
int getOwnerInfo(bufferArray &);
- int getMachineType(int &);
- int fuser(const char *, char *, int);
+
+ /**
+ * Retrieves the type of machine on the remote side
+ * as defined in @ref #machs.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices
+ *
+ * @param type The code describing the type of machine
+ * on the remote side is stored here on return.
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
+ int getMachineType(int &type);
+
+ /**
+ * Retrieves the name of a process, having a
+ * given file opened on the remote side.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices
+ *
+ * @param name The full path of a file to be checked
+ * for beeing used by a program.
+ * @param buf A buffer which gets filled with the
+ * program's name.
+ * @param maxlen The maximum capacity of the buffer.
+ */
+ int fuser(const char *name, char *buf, int maxlen);
+
+ /**
+ * Requests the remote server to terminate.
+ *
+ * This function is working with both SIBO and EPOC
+ * devices. There is usually no need to call this
+ * function, because the remote server is automatically
+ * stopped on disconnect.
+ *
+ * @returns A psion error code. 0 = Ok.
+ */
int quitServer(void);
+ /**
+ * Maps a language code to a human readable language name.
+ *
+ * @param code The language code to map.
+ *
+ * @returns The name of the language, represented by code, or
+ * "Unknown", if the code does not match one of the known
+ * languages.
+ */
+ const char *languageString(const int code);
+
+ /**
+ * Maps a battery status code to a human readable description.
+ *
+ * @param code The battary status code to map.
+ *
+ * @returns A descriptive text for the battery status, or
+ * "Unknown", if the code does not match a known
+ * battery status.
+ */
+ const char *batteryStatusString(const int code);
+
+
// API different on SIBO and EPOC
virtual int queryDrive(const char, bufferArray &) = 0;
- virtual int getCmdLine(const char *, char *, int) = 0;
+ /**
+ * Retrieves the command line of a running process.
+ *
+ * This function works with EPOC only. Using it with SIBO
+ * machines, returns always an error code E_PSI_NOT_SIBO.
+ *
+ * @param process Name of process. Format: processname.$pid
+ * @param ret The program name and arguments are returned here.
+ *
+ * @return Psion error code. 0 = Ok.
+ */
+ virtual int getCmdLine(const char *process, bufferStore &ret) = 0;
// API only existent on EPOC
// default-methods for SIBO here.
- virtual int getMachineInfo(void) { return E_PSI_NOT_SIBO;}
+ /**
+ * Retrieve general Information about the connected
+ * machine.
+ *
+ * This function works with EPOC only. Using it with SIBO
+ * machines, returns always an error code E_PSI_NOT_SIBO.
+ *
+ * @param machineInfo The struct holding all information on return.
+ * @return Psion error code. 0 = Ok.
+ */
+ virtual int getMachineInfo(machineInfo &) { return E_PSI_NOT_SIBO;}
virtual int closeHandle(int) { return E_PSI_NOT_SIBO;}
virtual int regOpenIter(void) { return E_PSI_NOT_SIBO;}
virtual int regReadIter(void) { return E_PSI_NOT_SIBO;}
@@ -46,13 +261,16 @@ class rpcs {
virtual int queryRead(void) { return E_PSI_NOT_SIBO;}
enum errs {
- E_PSI_GEN_NONE = 0,
+ E_PSI_GEN_NONE = 0,
E_PSI_GEN_FAIL = -1,
- E_PSI_FILE_DISC = -50,
+ E_PSI_FILE_DISC = -50,
// Special error code for "Operation not permitted in RPCS16"
- E_PSI_NOT_SIBO = -200
+ E_PSI_NOT_SIBO = -200
};
+ /**
+ * The known machine types.
+ */
enum machs {
PSI_MACH_UNKNOWN = 0,
PSI_MACH_PC = 1,
@@ -65,15 +283,44 @@ class rpcs {
PSI_MACH_S3C = 8,
PSI_MACH_S5 = 32,
PSI_MACH_WINC = 33,
-//TODO: Code for 5mx
+ // TODO: Code for 5mx
};
- protected:
+ /**
+ * The known interface languages.
+ */
+ enum languagecodes {
+ PSI_LANG_TEST = 0,
+ PSI_LANG_ENGLISH = 1,
+ PSI_LANG_FRENCH = 2,
+ PSI_LANG_GERMAN = 3,
+ };
+
+ /**
+ * The known battery states.
+ */
+ enum batterystates {
+ PSI_BATT_DEAD = 0,
+ PSI_BATT_VERYLOW = 1,
+ PSI_BATT_LOW = 2,
+ PSI_BATT_GOOD = 3,
+ };
- // Vars
+ protected:
+ /**
+ * The socket, used for communication
+ * with ncpd.
+ */
ppsocket *skt;
+
+ /**
+ * The current status of the connection.
+ */
long status;
+ /**
+ * The possible commands.
+ */
enum commands {
QUERY_NCP = 0x00,
EXEC_PROG = 0x01,
@@ -87,17 +334,38 @@ class rpcs {
GET_MACHINETYPE = 0x09,
GET_CMDLINE = 0x0a,
FUSER = 0x0b,
- CONFIG_OPEN = 0x66,
+ GET_MACHINE_INFO = 0x64,
+ REG_OPEN_ITER = 0x66,
+ REG_READ_ITER = 0x67,
+ REG_WRITE = 0x68,
+ REG_READ = 0x69,
+ REG_DELETE = 0x6a,
+ SET_TIME = 0x6b,
+ CONFIG_OPEN = 0x6c,
CONFIG_READ = 0x6d,
+ CONFIG_WRITE = 0x6e,
+ QUERY_OPEN = 0x6f,
+ QUERY_READ = 0x70,
QUIT_SERVER = 0xff
};
- // Communication
- bool sendCommand(enum commands, bufferStore &);
- long getResponse(bufferStore &);
+ /**
+ * Sends a command to the remote side.
+ *
+ * If communication fails, a reconnect is triggered
+ * and a second attempt to transmit the request
+ * is attempted. If that second attempt fails,
+ * the function returns an error an sets rpcs::status
+ * to E_PSI_FILE_DISC.
+ *
+ * @param cc The command to execute on the remote side.
+ * @param data Additional data for this command.
+ *
+ * @returns true on success, false on failure.
+ */
+ bool sendCommand(enum commands cc, bufferStore &data);
+ int getResponse(bufferStore &);
const char *getConnectName();
-
- char *convertSlash(const char *);
};
#endif
diff --git a/lib/rpcs16.cc b/lib/rpcs16.cc
index 2786ee8..a3af320 100644
--- a/lib/rpcs16.cc
+++ b/lib/rpcs16.cc
@@ -57,7 +57,7 @@ cout << dec << "qd: " << res << " " << a.getLen() << " a="<< a << endl;
}
int rpcs16::
-getCmdLine(const char *process, char *buf, int bufsize)
+getCmdLine(const char *process, bufferStore &ret)
{
return 0;
}
diff --git a/lib/rpcs16.h b/lib/rpcs16.h
index 14809ae..c803fff 100644
--- a/lib/rpcs16.h
+++ b/lib/rpcs16.h
@@ -12,7 +12,7 @@ class rpcs16 : public rpcs {
~rpcs16();
int queryDrive(const char, bufferArray &);
- int getCmdLine(const char *, char *, int);
+ int getCmdLine(const char *, bufferStore &);
};
#endif
diff --git a/lib/rpcs32.cc b/lib/rpcs32.cc
index d710b9c..74d5ca4 100644
--- a/lib/rpcs32.cc
+++ b/lib/rpcs32.cc
@@ -48,14 +48,16 @@ int rpcs32::
queryDrive(char drive, bufferArray &ret)
{
bufferStore a;
+ int res;
+
a.addByte(drive);
if (!sendCommand(rpcs::QUERY_DRIVE, a))
return rpcs::E_PSI_FILE_DISC;
- getResponse(a);
+ if ((res = getResponse(a)))
+ return res;
int l = a.getLen();
ret.clear();
-//cout << dec << "qd: " << a.getLen() << " a="<< a << endl;
- while (l > 1) {
+ while (l > 0) {
bufferStore b, c;
const char *s;
char *p;
@@ -66,8 +68,7 @@ queryDrive(char drive, bufferArray &ret)
sl = strlen(s) + 1;
l -= sl;
a.discardFirstBytes(sl);
- p = strstr(s, ".$");
- if (p) {
+ if ((p = strstr(s, ".$"))) {
*p = '\0'; p += 2;
sscanf(p, "%d", &pid);
} else
@@ -82,33 +83,125 @@ queryDrive(char drive, bufferArray &ret)
ret.push(c);
ret.push(b);
}
- return 0;
+ return res;
}
int rpcs32::
-getCmdLine(const char *process, char *buf, int bufsize)
+getCmdLine(const char *process, bufferStore &ret)
{
- return 0;
+ bufferStore a;
+ int res;
+
+ a.addStringT(process);
+ if (!sendCommand(rpcs::GET_CMDLINE, a))
+ return rpcs::E_PSI_FILE_DISC;
+ res = getResponse(a);
+ ret = a;
+ return res;
}
int rpcs32::
+getMachineInfo(machineInfo &mi)
+{
+ bufferStore a;
+ int res;
+
+ if (!sendCommand(rpcs::GET_MACHINE_INFO, a))
+ return rpcs::E_PSI_FILE_DISC;
+ if ((res = getResponse(a)))
+ return res;
+ if (a.getLen() != 256)
+ return E_PSI_GEN_FAIL;
+ mi.machineType = a.getDWord(0);
+ strncpy(mi.machineName, a.getString(16), 16);
+ mi.machineName[16] = '\0';
+ mi.machineUID = a.getDWord(44);
+ mi.machineUID <<= 32;
+ mi.machineUID |= a.getDWord(40);
+ mi.countryCode = a.getDWord(56);
+ strcpy(mi.uiLanguage, languageString(a.getDWord(164)));
+
+ mi.romMajor = a.getByte(4);
+ mi.romMinor = a.getByte(5);
+ mi.romBuild = a.getWord(6);
+ mi.romSize = a.getDWord(140);
+
+ mi.ramSize = a.getDWord(136);
+ mi.ramMaxFree = a.getDWord(144);
+ mi.ramFree = a.getDWord(148);
+ mi.ramDiskSize = a.getDWord(152);
+
+ mi.registrySize = a.getDWord(156);
+ mi.romProgrammable = (a.getDWord(160) != 0);
+
+ mi.displayWidth = a.getDWord(32);
+ mi.displayHeight = a.getDWord(36);
+
+ mi.time.tv_low = a.getDWord(48);
+ mi.time.tv_high = a.getDWord(52);
+
+ mi.tz.utc_offset = a.getDWord(60);
+ mi.tz.dst_zones = a.getDWord(64);
+ mi.tz.home_zone = a.getDWord(68);
+
+ mi.mainBatteryInsertionTime.tv_low = a.getDWord(72);
+ mi.mainBatteryInsertionTime.tv_high = a.getDWord(76);
+ mi.mainBatteryStatus = a.getDWord(80);
+ mi.mainBatteryUsedTime.tv_low = a.getDWord(84);
+ mi.mainBatteryUsedTime.tv_high = a.getDWord(88);
+ mi.mainBatteryCurrent = a.getDWord(92);
+ mi.mainBatteryUsedPower = a.getDWord(96);
+ mi.mainBatteryVoltage = a.getDWord(100);
+ mi.mainBatteryMaxVoltage = a.getDWord(104);
+
+ mi.backupBatteryStatus = a.getDWord(108);
+ mi.backupBatteryVoltage = a.getDWord(112);
+ mi.backupBatteryMaxVoltage = a.getDWord(116);
+ mi.backupBatteryUsedTime.tv_low = a.getDWord(124);
+ mi.backupBatteryUsedTime.tv_high = a.getDWord(128);
+
+ mi.externalPower = (a.getDWord(120) != 0);
+
+ return res;
+}
+
+static unsigned long hhh;
+
+int rpcs32::
configOpen(void)
{
bufferStore a;
-cout << "configOpen:" << endl;
+ int res;
+
if (!sendCommand(rpcs::CONFIG_OPEN, a))
return rpcs::E_PSI_FILE_DISC;
- getResponse(a);
-cout << a << endl;
+ res = getResponse(a);
+cout << "co: r=" << res << " a=" << a << endl;
+ hhh = a.getDWord(0);
+ return 0;
}
int rpcs32::
configRead(void)
{
bufferStore a;
-cout << "configRead:" << endl;
- if (!sendCommand(rpcs::CONFIG_READ, a))
- return rpcs::E_PSI_FILE_DISC;
- getResponse(a);
-cout << a << endl;
+ int res;
+ int l;
+ FILE *f;
+
+ f = fopen("blah", "w");
+ do {
+ a.init();
+ a.addDWord(hhh);
+ if (!sendCommand(rpcs::CONFIG_READ, a))
+ return rpcs::E_PSI_FILE_DISC;
+ if ((res = getResponse(a)))
+ return res;
+ l = a.getLen();
+ cout << "cr: " << l << endl;
+ fwrite(a.getString(0), 1, l, f);
+ } while (l > 0);
+ fclose(f);
+//cout << "cr: r=" << res << " a=" << a << endl;
+ return 0;
}
diff --git a/lib/rpcs32.h b/lib/rpcs32.h
index e33ef10..6c333b4 100644
--- a/lib/rpcs32.h
+++ b/lib/rpcs32.h
@@ -11,9 +11,11 @@ class rpcs32 : public rpcs {
~rpcs32();
int queryDrive(const char, bufferArray &);
- int getCmdLine(const char *, char *, int);
+ int getCmdLine(const char *, bufferStore &);
+ int getMachineInfo(machineInfo &);
+ int configOpen(void);
+ int configRead(void);
#if 0
- int getMachineInfo(void);
int closeHandle(int);
int regOpenIter(void);
int regReadIter(void);
@@ -21,10 +23,8 @@ class rpcs32 : public rpcs {
int regRead(void);
int regDelete(void);
int setTime(void);
-#endif
int configOpen(void);
int configRead(void);
-#if 0
int configWrite(void);
int queryOpen(void);
int queryRead(void);
diff --git a/lib/rpcsfactory.cc b/lib/rpcsfactory.cc
index 7358e56..4fe0bff 100644
--- a/lib/rpcsfactory.cc
+++ b/lib/rpcsfactory.cc
@@ -34,7 +34,7 @@
#include "bufferstore.h"
#include "ppsocket.h"
-rpcsfactory::rpcsfactory(ppsocket *_skt) : serNum(0)
+rpcsfactory::rpcsfactory(ppsocket *_skt) //: serNum(0)
{
skt = _skt;
}
@@ -52,9 +52,10 @@ rpcs * rpcsfactory::create(bool reconnect)
a.addStringT("NCP$INFO");
if (!skt->sendBufferStore(a)) {
if (!reconnect)
- cerr << "rpcsfactory::create couldn't send version request" << endl; else {
+ cerr << "rpcsfactory::create couldn't send version request" << endl;
+ else {
skt->closeSocket();
- serNum = 0;
+ // serNum = 0;
skt->reconnect();
}
return NULL;
@@ -68,7 +69,7 @@ rpcs * rpcsfactory::create(bool reconnect)
}
if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) {
skt->closeSocket();
- serNum = 0;
+ // serNum = 0;
skt->reconnect();
return NULL;
}
diff --git a/lib/rpcsfactory.h b/lib/rpcsfactory.h
index 17a2719..feffaee 100644
--- a/lib/rpcsfactory.h
+++ b/lib/rpcsfactory.h
@@ -5,15 +5,37 @@
class ppsocket;
+/**
+ * A factory for automatically instantiating the correct protocol
+ * variant depending on the connected Psion.
+ */
class rpcsfactory {
public:
+ /**
+ * Constructs a rpcsfactory.
+ *
+ * @param skt The socket to be used for connecting
+ * to the ncpd daemon.
+ */
rpcsfactory(ppsocket * skt);
- virtual rpcs * create(bool);
+
+ /**
+ * Creates a new rpsc instance.
+ *
+ * @param reconnect Set to true, if automatic reconnect
+ * should be performed on failure.
+ *
+ * @returns A pointer to a newly created rpcs instance or
+ * NULL on failure.
+ */
+ virtual rpcs * create(bool reconnect);
private:
- // Vars
+ /**
+ * The socket to be used for connecting to the
+ * ncpd daemon.
+ */
ppsocket *skt;
- int serNum;
};
#endif
diff --git a/ncpd/link.cc b/ncpd/link.cc
index c455324..d07b78b 100644
--- a/ncpd/link.cc
+++ b/ncpd/link.cc
@@ -90,7 +90,7 @@ send(const bufferStore & buff)
if (buff.getLen() > 300)
failed = true;
else
- sendQueue.pushBuffer(buff);
+ sendQueue += buff;
}
bufferArray link::
@@ -116,7 +116,7 @@ poll()
// Send ack
if (idLastGot != seq) {
idLastGot = seq;
- ret.pushBuffer(buff);
+ ret += buff;
} else {
if (verbose & LNK_DEBUG_LOG)
cout << "link: DUP\n";
@@ -177,7 +177,7 @@ poll()
} else {
if (!sendQueue.empty()) {
somethingToSend = true;
- toSend = sendQueue.popBuffer();
+ toSend = sendQueue.pop();
idSent++;
if (idSent > 7)
idSent = 0;
diff --git a/ncpd/linkchan.cc b/ncpd/linkchan.cc
index 4a2a4d4..f8e586f 100644
--- a/ncpd/linkchan.cc
+++ b/ncpd/linkchan.cc
@@ -60,7 +60,7 @@ ncpDataCallback(bufferStore & a)
<< srvName << "\"" << endl;
while (!registerStack.empty()) {
- se = registerStack.popBuffer();
+ se = registerStack.pop();
if (se.getWord(0) == ser) {
if (verbose & LINKCHAN_DEBUG_LOG)
cout << "linkchan: found ser=0x" << hex << setw(4) <<
@@ -68,7 +68,7 @@ ncpDataCallback(bufferStore & a)
" on stack -> callBack to waiting chan" << endl;
ncpDoRegisterAck((int)se.getWord(2));
} else
- newStack.pushBuffer(se);
+ newStack += se;
}
registerStack = newStack;
return;
@@ -111,7 +111,7 @@ Register(channel *ch)
stack.addWord(registerSer);
stack.addWord(ch->getNcpChannel());
- registerStack.pushBuffer(stack);
+ registerStack += stack;
a.addByte(0);
a.addWord(registerSer++);
a.addString(ch->getNcpConnectName());
diff --git a/ncpd/main.cc b/ncpd/main.cc
index 3a0ddb6..2c0fd3d 100644
--- a/ncpd/main.cc
+++ b/ncpd/main.cc
@@ -79,7 +79,7 @@ pollSocketConnections(int &numScp, socketChan ** scp)
void
usage()
{
- cerr << "Usage : ncpd [-V] [-v logclass] [-d] [-p <port>] [-s <device>] [-b <baudrate>]\n";
+ cerr << "Usage : ncpd [-V] [-v logclass] [-d] [-e] [-p <port>] [-s <device>] [-b <baudrate>]\n";
exit(1);
}
@@ -90,6 +90,7 @@ main(int argc, char **argv)
IOWatch iow;
int pid;
bool dofork = true;
+ bool autoexit = false;
// Command line parameter processing
int sockNum = DPORT;
@@ -120,7 +121,7 @@ main(int argc, char **argv)
if (!strcmp(argv[i], "pd"))
pverbose |= PKT_DEBUG_DUMP;
if (!strcmp(argv[i], "ph"))
- lverbose |= PKT_DEBUG_HANDSHAKE;
+ pverbose |= PKT_DEBUG_HANDSHAKE;
if (!strcmp(argv[i], "m"))
verbose = true;
if (!strcmp(argv[i], "all")) {
@@ -133,6 +134,8 @@ main(int argc, char **argv)
baudRate = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-d")) {
dofork = 0;
+ } else if (!strcmp(argv[i], "-e")) {
+ autoexit = true;
} else if (!strcmp(argv[i], "-V")) {
cout << "ncpd version " << VERSION << endl;
exit(0);
@@ -180,6 +183,9 @@ main(int argc, char **argv)
iow.watch(1, 0);
if (a->hasFailed()) {
+ if (autoexit)
+ break;
+
iow.watch(5, 0);
if (verbose)
cout << "ncp: restarting\n";
diff --git a/ncpd/mp_serial.c b/ncpd/mp_serial.c
index b153e77..05a014c 100644
--- a/ncpd/mp_serial.c
+++ b/ncpd/mp_serial.c
@@ -153,7 +153,7 @@ init_serial(const char *dev, int speed, int debug)
#endif
#if defined(sun) || defined(linux) || defined(__sgi) || defined(__NetBSD__)
ti.c_cflag = CS8 | HUPCL | clocal | CRTSCTS | CREAD;
- ti.c_iflag = IGNBRK | IGNPAR;
+ ti.c_iflag = IGNBRK | IGNPAR | IXON | IXOFF;
ti.c_cc[VMIN] = 1;
ti.c_cc[VTIME] = 0;
#endif
diff --git a/ncpd/ncp.cc b/ncpd/ncp.cc
index e1bf96a..1a5c317 100644
--- a/ncpd/ncp.cc
+++ b/ncpd/ncp.cc
@@ -113,7 +113,7 @@ poll()
bufferArray res(l->poll());
if (!res.empty()) {
do {
- bufferStore s = res.popBuffer();
+ bufferStore s = res.pop();
if (s.getLen() > 1) {
int channel = s.getByte(0);
s.discardFirstBytes(1);
diff --git a/ncpd/packet.cc b/ncpd/packet.cc
index 26823c8..53774d6 100644
--- a/ncpd/packet.cc
+++ b/ncpd/packet.cc
@@ -54,6 +54,7 @@ iow(_iow)
inPtr = inBuffer = new unsigned char[BUFFERLEN + 1];
outPtr = outBuffer = new unsigned char[BUFFERLEN + 1];
inLen = outLen = termLen = 0;
+ foundSync = 0;
esc = false;
crcIn = crcOut = 0;
@@ -87,7 +88,7 @@ void packet::
send(unsigned char type, const bufferStore & b)
{
if (verbose & PKT_DEBUG_LOG) {
- cout << "packet: >> ";
+ cout << "packet: type " << hex << (int) type << " >> ";
if (verbose & PKT_DEBUG_DUMP)
cout << b << endl;
else
@@ -185,7 +186,7 @@ get(unsigned char &type, bufferStore & ret)
if (verbose & PKT_DEBUG_LOG) {
cout << "packet: get ";
if (verbose & PKT_DEBUG_DUMP) {
- for (int i = 0; i < termLen; i++)
+ for (int i = foundSync - 3; i < termLen; i++)
cout << hex << setw(2) << setfill('0') << (int) inBuffer[i] << " ";
} else
cout << "len=" << dec << termLen;
@@ -193,6 +194,7 @@ get(unsigned char &type, bufferStore & ret)
}
inLen -= termLen;
termLen = 0;
+ foundSync = 0;
bool crcOk = (endPtr[0] == ((crcIn >> 8) & 0xff) && endPtr[1] == (crcIn & 0xff));
if (inLen > 0)
memmove(inBuffer, &endPtr[2], inLen);
@@ -218,15 +220,29 @@ terminated()
if (inLen < 6)
return false;
p = inBuffer + termLen;
- if (termLen == 0) {
+ if (!foundSync) {
+ while (!foundSync && (inLen - termLen >= 6))
+ {
+ termLen++;
if (*p++ != 0x16)
- return false;
+ continue;
+ termLen++;
if (*p++ != 0x10)
- return false;
+ continue;
+ termLen++;
if (*p++ != 0x02)
+ continue;
+ foundSync = termLen;
+ }
+ if (!foundSync)
return false;
+
+ if (verbose & PKT_DEBUG_LOG) {
+ if (foundSync != 3)
+ cout << "packet: terminated found sync at " << foundSync << endl;
+ }
esc = false;
- termLen = 3;
+ // termLen = 3;
crcIn = 0;
rcv.init();
}
diff --git a/ncpd/packet.h b/ncpd/packet.h
index 26d4282..5c4bb4f 100644
--- a/ncpd/packet.h
+++ b/ncpd/packet.h
@@ -63,6 +63,7 @@ class packet {
int inLen;
int outLen;
int termLen;
+ int foundSync;
int fd;
short int verbose;
bool esc;
diff --git a/patches/README b/patches/README
new file mode 100644
index 0000000..11b7c95
--- /dev/null
+++ b/patches/README
@@ -0,0 +1,16 @@
+The following patches may be applied to other programs to allow them to operate
+better with plptools.
+
+mgetty-1.1.21-plp.diff is from Christof Meerwald, and adds autodetection
+support for the PLP-protocol to mgetty - thus mgetty can autodetect a
+Psion connected to the serial port and execute ncpd (with the autoexit
+option). Having mgetty watch the serial port makes it a lot more easy to
+switch between a PLP (file transfer) and a PPP (TCP/IP) connection. Christof
+used the following login.conf for mgetty:
+
+/AutoPPP/ - - /usr/sbin/pppd
+/PLP/ - - /usr/sbin/ncpd -d -e
+* - - /bin/login @
+
+
+-- MJG
diff --git a/patches/mgetty-1.1.21-plp.diff b/patches/mgetty-1.1.21-plp.diff
new file mode 100644
index 0000000..943a173
--- /dev/null
+++ b/patches/mgetty-1.1.21-plp.diff
@@ -0,0 +1,40 @@
+diff -ur mgetty-1.1.21/logname.c mgetty-1.1.21.new/logname.c
+--- mgetty-1.1.21/logname.c Tue Sep 1 11:56:19 1998
++++ mgetty-1.1.21.new/logname.c Sat Jan 1 17:12:11 2000
+@@ -270,6 +270,9 @@
+ static int ppp_level = 0, ppp_escaped = 0;
+ char ppp_ch;
+ #endif
++#if 1
++ static int plp_level = 0;
++#endif
+
+ /* read character by character! */
+ tio_save = *tio;
+@@ -413,6 +416,26 @@
+ ppp_level = 0;
+ ppp_escaped = 0;
+ }
++#endif
++#if 1
++ if (ch == '\026')
++ {
++ plp_level = 1;
++ }
++ else if ((ch == '\020') && (plp_level == 1))
++ {
++ plp_level = 2;
++ }
++ else if ((ch == '\002') && (plp_level == 2))
++ {
++ strcpy (buf, "/PLP/");
++ i=5;
++ ch = '\r';
++ }
++ else
++ {
++ plp_level = 0;
++ }
+ #endif
+
+ #ifdef JANUS
diff --git a/plpftp/ftp.cc b/plpftp/ftp.cc
index 45ec2eb..b46e24a 100644
--- a/plpftp/ftp.cc
+++ b/plpftp/ftp.cc
@@ -25,9 +25,11 @@
#include <sys/types.h>
#include <dirent.h>
#include <stream.h>
+#include <fstream.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
+#include <stdio.h>
#include <iomanip.h>
#include <unistd.h>
#include <sys/time.h>
@@ -43,7 +45,6 @@
#if HAVE_LIBREADLINE
extern "C" {
-#include <stdio.h>
#include <readline/readline.h>
#if HAVE_LIBHISTORY
#include <readline/history.h>
@@ -53,7 +54,6 @@ extern "C" {
static char psionDir[1024];
static rfsv *comp_a;
-static rpcs *comp_r;
static int continueRunning;
@@ -184,6 +184,8 @@ sigint_handler2(int i) {
signal(SIGINT, sigint_handler2);
}
+const char *datefmt = "%c";
+
int ftp::
session(rfsv & a, rpcs & r, int xargc, char **xargv)
{
@@ -205,7 +207,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
}
if (!once) {
bufferArray b;
- if (!r.getOwnerInfo(b)) {
+ if (!(res = r.getOwnerInfo(b))) {
int machType;
r.getMachineType(machType);
cout << "Connected to ";
@@ -251,7 +253,8 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
while (!b.empty())
cout << " " << b.pop().getString() << endl;
cout << endl;
- }
+ } else
+ cerr << "OwnerInfo returned error " << res << endl;
}
if (!strcmp(DDRIVE, "AUTO")) {
@@ -334,9 +337,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
else {
// never used to do this
char dateBuff[100];
- struct tm *t;
- t = localtime(&time);
- strftime(dateBuff, 100, "%c", t);
+ strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&time));
cout << a.opAttr(attr);
cout << " " << dec << setw(10) << setfill(' ') << size;
cout << " " << dateBuff;
@@ -364,9 +365,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
errprint(res, a);
else {
char dateBuff[100];
- struct tm *t;
- t = localtime(&mtime);
- strftime(dateBuff, 100, "%c %Z", t);
+ strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&mtime));
cout << dateBuff << endl;
}
continue;
@@ -456,9 +455,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
long size = s.getDWord(4);
long attr = s.getDWord(8);
char dateBuff[100];
- struct tm *t;
- t = localtime(&date);
- strftime(dateBuff, 100, "%c", t);
+ strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&date));
cout << a.opAttr(attr);
cout << " " << dec << setw(10) << setfill(' ') << size;
cout << " " << dateBuff;
@@ -748,10 +745,14 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
continue;
}
// RPCS commands
- // if (!strcmp(argv[0], "xxx")) {
- // r.configOpen();
- // continue;
- // }
+ if (!strcmp(argv[0], "x")) {
+ r.configOpen();
+ continue;
+ }
+ if (!strcmp(argv[0], "y")) {
+ r.configRead();
+ continue;
+ }
if (!strcmp(argv[0], "run") && (argc >= 2)) {
char argbuf[1024];
char cmdbuf[1024];
@@ -772,6 +773,99 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv)
r.execProgram(cmdbuf, argbuf);
continue;
}
+ if (!strcmp(argv[0], "machinfo")) {
+ machineInfo mi;
+ if ((res = r.getMachineInfo(mi))) {
+ errprint(res, a);
+ continue;
+ }
+
+ cout << "General:" << endl;
+ cout << " Machine Type: " << mi.machineType << endl;
+ cout << " Machine Name: " << mi.machineName << endl;
+ cout << " Machine UID: " << hex << mi.machineUID << dec << endl;
+ cout << " UI Language: " << mi.uiLanguage << endl;
+ cout << "ROM:" << endl;
+ cout << " Version: " << mi.romMajor << "." << setw(2) << setfill('0') <<
+ mi.romMinor << "(" << mi.romBuild << ")" << endl;
+ cout << " Size: " << mi.romSize / 1024 << "k" << endl;
+ cout << " Programmable: " <<
+ (mi.romProgrammable ? "yes" : "no") << endl;
+ cout << "RAM:" << endl;
+ cout << " Size: " << mi.ramSize / 1024 << "k" << endl;
+ cout << " Free: " << mi.ramFree / 1024 << "k" << endl;
+ cout << " Free max: " << mi.ramMaxFree / 1024 << "k" << endl;
+ cout << "RAM disk size: " << mi.ramDiskSize / 1024 << "k" << endl;
+ cout << "Registry size: " << mi.registrySize << endl;
+ cout << "Display size: " << mi.displayWidth << "x" <<
+ mi.displayHeight << endl;
+ cout << "Time:" << endl;
+ PsiTime pt(&mi.time, &mi.tz);
+ cout << " Current time: " << pt << endl;
+ cout << " UTC offset: " << mi.tz.utc_offset << " seconds" << endl;
+ cout << " DST: " <<
+ (mi.tz.dst_zones & PsiTime::PSI_TZ_HOME ? "yes" : "no") << endl;
+ cout << " Timezone: " << mi.tz.home_zone << endl;
+ cout << " Country Code: " << mi.countryCode << endl;
+ cout << "Main battery:" << endl;
+ pt.setPsiTime(&mi.mainBatteryInsertionTime);
+ cout << " Changed at: " << pt << endl;
+ cout << " Used for: " << mi.mainBatteryUsedTime << endl;
+ cout << " Status: " <<
+ r.batteryStatusString(mi.mainBatteryStatus) << endl;
+ cout << " Current: " << mi.mainBatteryCurrent << " mA" << endl;
+ cout << " UsedPower: " << mi.mainBatteryUsedPower << " mAs" << endl;
+ cout << " Voltage: " << mi.mainBatteryVoltage << " mV" << endl;
+ cout << " Max. voltage: " << mi.mainBatteryMaxVoltage << " mV" << endl;
+ cout << "Backup battery:" << endl;
+ cout << " Status: " <<
+ r.batteryStatusString(mi.backupBatteryStatus) << endl;
+ cout << " Voltage: " << mi.backupBatteryVoltage << " mV" << endl;
+ cout << " Max. voltage: " << mi.backupBatteryMaxVoltage << " mV" << endl;
+ cout << " Used for: " << mi.backupBatteryUsedTime << endl;
+ continue;
+ }
+ if (!strcmp(argv[0], "runrestore") && (argc == 2)) {
+ ifstream ip(argv[1]);
+ if (!ip) {
+ cerr << "Could not read processlist " << argv[1] << endl;
+ continue;
+ }
+ while (!ip.eof()) {
+ char cmd[256];
+ char arg[256];
+ ip >> cmd >> arg;
+ if ((res = r.execProgram(cmd, arg))) {
+ cerr << "Could not start " << cmd << " " << arg << endl;
+ errprint(res, a);
+ }
+ }
+ ip.close();
+ continue;
+ }
+ if (!strcmp(argv[0], "killsave") && (argc == 2)) {
+ bufferArray tmp;
+ ofstream op(argv[1]);
+ if (!op) {
+ cerr << "Could not write processlist " << argv[1] << endl;
+ continue;
+ }
+ r.queryDrive('C', tmp);
+ while (!tmp.empty()) {
+ char pbuf[128];
+ bufferStore cmdargs;
+ bufferStore bs = tmp.pop();
+ int pid = bs.getWord(0);
+ const char *proc = bs.getString(2);
+ sprintf(pbuf, "%s.$%d", proc, pid);
+ bs = tmp.pop();
+ if (r.getCmdLine(pbuf, cmdargs) == 0)
+ op << cmdargs.getString(0) << " " << bs.getString(0) << endl;
+ r.stopProgram(pbuf);
+ }
+ op.close();
+ continue;
+ }
if (!strcmp(argv[0], "kill") && (argc >= 2)) {
bufferArray tmp, tmp2;
bool anykilled = false;
@@ -834,7 +928,8 @@ errprint(long errcode, rfsv & a) {
static char *all_commands[] = {
"pwd", "ren", "touch", "gtime", "test", "gattr", "sattr", "devs",
"dir", "ls", "dircnt", "cd", "lcd", "get", "put", "mget", "mput",
- "del", "rm", "mkdir", "rmdir", "prompt", "bye", "ps", "kill", "run", NULL
+ "del", "rm", "mkdir", "rmdir", "prompt", "bye",
+ "ps", "kill", "killsave", "runrestore", "run", "machinfo", NULL
};
static char *localfile_commands[] = {
diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc
index e322685..6bf0f01 100644
--- a/plpnfsd/main.cc
+++ b/plpnfsd/main.cc
@@ -46,14 +46,14 @@ long rfsv_dir(const char *file, dentry **e) {
ret = a->dir(&(*file), &entries);
while (!entries.empty()) {
bufferStore s;
- s = entries.popBuffer();
+ s = entries.pop();
tmp = *e;
*e = (dentry *)malloc(sizeof(dentry));
if (!*e)
return -1;
(*e)->time = s.getDWord(0);
(*e)->size = s.getDWord(4);
- (*e)->attr = s.getDWord(8);
+ (*e)->attr = a->attr2std(s.getDWord(8));
(*e)->name = strdup(s.getString(12));
(*e)->next = tmp;
}
@@ -138,7 +138,6 @@ static long rfsv_opencached(const char *name, long mode) {
}
long rfsv_read(char *buf, long offset, long len, char *name) {
- // FIXME: this might break on RFSV16?
long ret = 0;
if (!a)
@@ -161,7 +160,6 @@ long rfsv_read(char *buf, long offset, long len, char *name) {
}
long rfsv_write(char *buf, long offset, long len, char *name) {
- // FIXME: this might break on RFSV16?
long ret = 0;
if (!a)
@@ -196,7 +194,6 @@ long rfsv_setmtime(const char *name, long time) {
long rfsv_setsize(const char *name, long size) {
long ph;
long ret;
- // FIXME: this might break on RFSV16?
if (!a)
return -1;
@@ -215,14 +212,19 @@ long rfsv_setattr(const char *name, long sattr, long dattr) {
return -1;
if (a_filename && !strcmp(name, a_filename))
rfsv_closecached();
- long ret = a->fsetattr(name, dattr, sattr);
- return ret;
+ dattr = a->std2attr(dattr);
+ sattr = a->std2attr(sattr);
+ return a->fsetattr(name, dattr, sattr);
}
long rfsv_getattr(const char *name, long *attr, long *size, long *time) {
+ long res, psiattr;
+
if (!a)
return -1;
- return a->fgeteattr(&(*name), &(*attr), &(*size), &(*time));
+ res = a->fgeteattr(&(*name), &psiattr, &(*size), &(*time));
+ *attr = a->attr2std(psiattr);
+ return res;
}
long rfsv_statdev(char letter) {
diff --git a/plpnfsd/mp_mount.c b/plpnfsd/mp_mount.c
index f0a82d4..0f9e1e9 100644
--- a/plpnfsd/mp_mount.c
+++ b/plpnfsd/mp_mount.c
@@ -66,7 +66,7 @@ static char nfshost[128];
#ifndef __GLIBC__
#include <linux/fs.h> /* struct nfs_mount_data */
#endif
-#include <linux/nfs_mount.h> /* struct nfs_mount_data */
+#include "linux-misc.h" /* struct nfs_mount_data */
#include <arpa/inet.h> /* inet_addr() */
#endif
#ifdef _IBMR2
@@ -75,7 +75,6 @@ static char nfshost[128];
#include <sys/vmount.h>
#endif
-
#ifndef DONT_UPDATE_MTAB
#if defined(sun) && defined(__SVR4)
#include <sys/mnttab.h>
diff --git a/plpnfsd/mp_pfs_ops.c b/plpnfsd/mp_pfs_ops.c
index 669d435..71ed2e9 100644
--- a/plpnfsd/mp_pfs_ops.c
+++ b/plpnfsd/mp_pfs_ops.c
@@ -106,29 +106,35 @@ attr2pattr(long oattr, long nattr, long *psisattr, long *psidattr)
* work properly
*/
*psisattr = *psidattr = 0;
+ if ((oattr & 0400) != (nattr & 0400)) {
+ if (nattr & 0400) /* readable */
+ *psidattr |= PSI_A_READ;
+ else
+ *psisattr |= PSI_A_READ;
+ }
if ((oattr & 0200) != (nattr & 0200)) {
if (nattr & 0200) /* readonly */
- *psidattr |= 0x01;
+ *psidattr |= PSI_A_RDONLY;
else
- *psisattr |= 0x01;
+ *psisattr |= PSI_A_RDONLY;
}
if ((oattr & 0020) != (nattr & 0020)) {
if (nattr & 0020) /* group-write -> archive */
- *psisattr |= 0x20;
+ *psisattr |= PSI_A_ARCHIVE;
else
- *psidattr |= 0x20;
+ *psidattr |= PSI_A_ARCHIVE;
}
if ((oattr & 0004) != (nattr & 0004)) {
if (nattr & 0004) /* Not world-read -> hidden */
- *psidattr |= 0x02;
+ *psidattr |= PSI_A_HIDDEN;
else
- *psisattr |= 0x02;
+ *psisattr |= PSI_A_HIDDEN;
}
if ((oattr & 0002) != (nattr & 0002)) {
if (nattr & 0002) /* world-write -> system */
- *psisattr |= 0x04;
+ *psisattr |= PSI_A_SYSTEM;
else
- *psidattr |= 0x04;
+ *psidattr |= PSI_A_SYSTEM;
}
}
@@ -137,7 +143,7 @@ dpattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode)
{
bzero((char *) fp, sizeof(*fp));
- if (psiattr & 0x10) {
+ if (psiattr & PSI_A_DIR) {
fp->type = NFDIR;
fp->mode = NFSMODE_DIR | 0700;
/*
@@ -159,17 +165,18 @@ dpattr2attr(long psiattr, long size, long ftime, fattr *fp, int inode)
* 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 & 0x01))
+ if (!(psiattr & PSI_A_RDONLY))
fp->mode |= 0200; /* File writeable */
/* fp->mode |= 0100; File executable */
- if (!(psiattr & 0x02))
+ if (!(psiattr & PSI_A_HIDDEN))
fp->mode |= 0004; /* Not Hidden <-> world read */
- if (psiattr & 0x04)
+ if (psiattr & PSI_A_SYSTEM)
fp->mode |= 0002; /* System <-> world write */
- if (psiattr & 0x40)
+ if (psiattr & PSI_A_VOLUME)
fp->mode |= 0001; /* Volume <-> world exec */
- if (psiattr & 0x20)
+ if (psiattr & PSI_A_ARCHIVE)
fp->mode |= 0020; /* Modified <-> group write */
/* fp->mode |= 0040; Byte <-> group read */
/* fp->mode |= 0010; Text <-> group exec */
@@ -189,7 +196,7 @@ pattr2attr(long psiattr, long size, long ftime, fattr *fp, unsigned char *fh)
{
bzero((char *) fp, sizeof(*fp));
- if (psiattr & 0x10) {
+ if (psiattr & PSI_A_DIR) {
fp->type = NFDIR;
fp->mode = NFSMODE_DIR | 0700;
/*
@@ -211,17 +218,18 @@ pattr2attr(long psiattr, long size, long ftime, fattr *fp, unsigned char *fh)
* 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 & 0x01))
+ if (!(psiattr & PSI_A_RDONLY))
fp->mode |= 0200; /* File writeable */
/* fp->mode |= 0100; File executable */
- if (!(psiattr & 0x02))
+ if (!(psiattr & PSI_A_HIDDEN))
fp->mode |= 0004; /* Not Hidden <-> world read */
- if (psiattr & 0x04)
+ if (psiattr & PSI_A_SYSTEM)
fp->mode |= 0002; /* System <-> world write */
- if (psiattr & 0x40)
+ if (psiattr & PSI_A_VOLUME)
fp->mode |= 0001; /* Volume <-> world exec */
- if (psiattr & 0x20)
+ if (psiattr & PSI_A_ARCHIVE)
fp->mode |= 0020; /* Modified <-> group write */
/* fp->mode |= 0040; Byte <-> group read */
/* fp->mode |= 0010; Text <-> group exec */
diff --git a/plpnfsd/rfsv_api.h b/plpnfsd/rfsv_api.h
index d4a996b..14c26d5 100644
--- a/plpnfsd/rfsv_api.h
+++ b/plpnfsd/rfsv_api.h
@@ -29,4 +29,19 @@ extern long rfsv_statdev(char letter);
extern long rfsv_isalive();
extern long rfsv_closecached(void);
+/* File attributes, C-style */
+#define PSI_A_RDONLY 0x0001
+#define PSI_A_HIDDEN 0x0002
+#define PSI_A_SYSTEM 0x0004
+#define PSI_A_DIR 0x0008
+#define PSI_A_ARCHIVE 0x0010
+#define PSI_A_VOLUME 0x0020
+#define PSI_A_NORMAL 0x0040
+#define PSI_A_TEMP 0x0080
+#define PSI_A_COMPRESSED 0x0100
+#define PSI_A_READ 0x0200
+#define PSI_A_EXEC 0x0400
+#define PSI_A_STREAM 0x0800
+#define PSI_A_TEXT 0x1000
+
#endif