aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
committerFritz Elfert <felfert@to.com>2000-01-17 11:49:41 +0000
commitab18114bfd38d4632c66401b5bc079241e27fab3 (patch)
tree14f9c1d5f020cf8ed2f205094ca9e2fc907bb969 /lib
parent6eceb82662300bf306e70bd943200665bc3c9bc3 (diff)
downloadplptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.gz
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.bz2
plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.zip
Release of plptools-0.5
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/bufferarray.cc97
-rw-r--r--lib/bufferarray.h21
-rw-r--r--lib/bufferstore.cc13
-rw-r--r--lib/bufferstore.h25
-rw-r--r--lib/ppsocket.cc21
-rw-r--r--lib/rfsv.cc158
-rw-r--r--lib/rfsv.h151
-rw-r--r--lib/rfsv16.cc836
-rw-r--r--lib/rfsv16.h127
-rw-r--r--lib/rfsv32.cc368
-rw-r--r--lib/rfsv32.h199
-rw-r--r--lib/rfsvfactory.cc86
-rw-r--r--lib/rfsvfactory.h20
-rw-r--r--lib/rpcs.cc283
-rw-r--r--lib/rpcs.h103
-rw-r--r--lib/rpcs16.cc63
-rw-r--r--lib/rpcs16.h18
-rw-r--r--lib/rpcs32.cc114
-rw-r--r--lib/rpcs32.h36
-rw-r--r--lib/rpcsfactory.cc85
-rw-r--r--lib/rpcsfactory.h20
22 files changed, 2524 insertions, 328 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 27d5ea4..08df502 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,5 +1,9 @@
lib_LTLIBRARIES = libplp.la
libplp_la_LDFLAGS = --debug -version-info 1:0:0
-libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc rfsv32.cc log.cc
-EXTRA_DIST = bool.h bufferarray.h bufferstore.h iowatch.h ppsocket.h rfsv32.h log.h
+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
+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
diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc
index 99b1811..4e922ed 100644
--- a/lib/bufferarray.cc
+++ b/lib/bufferarray.cc
@@ -2,6 +2,7 @@
// PLP - An implementation of the PSION link protocol
//
// Copyright (C) 1999 Philip Proudman
+// extensions Copyright (C) 2000 Fritz Elfert <felfert@to.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -20,7 +21,8 @@
// e-mail philip.proudman@btinternet.com
-#include <stdio.h>
+#include <stream.h>
+#include <iomanip.h>
#include "bufferstore.h"
#include "bufferarray.h"
@@ -28,7 +30,7 @@
bufferArray::bufferArray()
{
len = 0;
- lenAllocd = 5;
+ lenAllocd = ALLOC_MIN;
buff = new bufferStore[lenAllocd];
}
@@ -64,7 +66,7 @@ void bufferArray::
pushBuffer(const bufferStore & b)
{
if (len == lenAllocd) {
- lenAllocd += 5;
+ lenAllocd += ALLOC_MIN;
bufferStore *nb = new bufferStore[lenAllocd];
for (long i = 0; i < len; i++) {
nb[i] = buff[i];
@@ -74,3 +76,92 @@ pushBuffer(const bufferStore & b)
}
buff[len++] = b;
}
+
+void bufferArray::
+push(const bufferStore & b)
+{
+ if (len == lenAllocd)
+ lenAllocd += ALLOC_MIN;
+ bufferStore *nb = new bufferStore[lenAllocd];
+ for (long i = len; i > 0; i--) {
+ nb[i] = buff[i-1];
+ }
+ nb[0] = b;
+ delete[]buff;
+ buff = nb;
+ len++;
+}
+
+bufferStore bufferArray::
+pop()
+{
+ return popBuffer();
+}
+
+void bufferArray::
+append(const bufferStore & b)
+{
+ pushBuffer(b);
+}
+
+long bufferArray::
+length(void)
+{
+ return len;
+}
+
+void bufferArray::
+clear(void)
+{
+ len = 0;
+ lenAllocd = ALLOC_MIN;
+ delete []buff;
+ buff = new bufferStore[lenAllocd];
+}
+
+bufferArray &bufferArray::
+operator =(const bufferArray & a)
+{
+ delete []buff;
+ len = a.len;
+ lenAllocd = a.lenAllocd;
+ buff = new bufferStore[lenAllocd];
+ for (int i = 0; i < len; i++)
+ buff[i] = a.buff[i];
+ return *this;
+}
+
+bufferStore &bufferArray::
+operator [](const unsigned long index)
+{
+ return buff[index];
+}
+
+bufferArray &bufferArray::
+operator +(const bufferStore &a)
+{
+ append(a);
+ return *this;
+}
+
+bufferArray &bufferArray::
+operator +(const bufferArray &a)
+{
+ lenAllocd += a.lenAllocd;
+ bufferStore *nb = new bufferStore[lenAllocd];
+ for (int i = 0; i < len; i++)
+ nb[len + i] = buff[i];
+ for (int i = 0; i < a.len; i++)
+ nb[len + i] = a.buff[i];
+ len += a.len;
+ delete []buff;
+ buff = nb;
+ return *this;
+}
+
+bufferArray &bufferArray::
+operator +=(const bufferStore &a)
+{
+ append(a);
+ return *this;
+}
diff --git a/lib/bufferarray.h b/lib/bufferarray.h
index 4cb948e..fbf26f1 100644
--- a/lib/bufferarray.h
+++ b/lib/bufferarray.h
@@ -9,12 +9,27 @@ class bufferArray {
bufferArray();
bufferArray(const bufferArray &a);
~bufferArray();
- void operator =(const bufferArray &a);
-
+ bufferArray &operator =(const bufferArray &a);
bool empty() const;
- bufferStore popBuffer();
+
+ // 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);
+
private:
+ static const long ALLOC_MIN = 5;
long len;
long lenAllocd;
bufferStore* buff;
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
index 886b952..842e666 100644
--- a/lib/bufferstore.cc
+++ b/lib/bufferstore.cc
@@ -19,7 +19,8 @@
//
// e-mail philip.proudman@btinternet.com
-#include <stream.h>
+#include <stream.h>
+// That should be iostream.h, but it won't build on Sun WorkShop C++ 5.0
#include <iomanip.h>
#include <string.h>
@@ -48,7 +49,7 @@ bufferStore::bufferStore(const unsigned char*_buff, long _len) {
start = 0;
}
-void bufferStore::operator =(const bufferStore &a) {
+bufferStore &bufferStore::operator =(const bufferStore &a) {
checkAllocd(a.getLen());
len = a.getLen();
memcpy(buff, a.getString(0), len);
@@ -106,7 +107,7 @@ ostream &operator<<(ostream &s, const bufferStore &m) {
if (c>=' ' && c <= 'z') s << c;
}
}
- s<< ")";
+ s<< ")" << dec << setw(0);
return s;
}
@@ -144,6 +145,12 @@ void bufferStore::addStringT(const char* s) {
addByte(0);
}
+void bufferStore::addBytes(const unsigned char* s, int l) {
+ checkAllocd(len + l);
+ memcpy(&buff[len], s, l);
+ len += l;
+}
+
void bufferStore::addBuff(const bufferStore &s, long maxLen) {
long l = s.getLen();
checkAllocd(len + l);
diff --git a/lib/bufferstore.h b/lib/bufferstore.h
index 4840689..df216c0 100644
--- a/lib/bufferstore.h
+++ b/lib/bufferstore.h
@@ -7,10 +7,10 @@ class ostream;
class bufferStore {
public:
bufferStore();
- bufferStore(const unsigned char*buff, long len);
+ bufferStore(const unsigned char *, long);
~bufferStore();
- bufferStore(const bufferStore &a);
- void operator =(const bufferStore &a);
+ bufferStore(const bufferStore &);
+ bufferStore &operator =(const bufferStore &);
// Reading Utils
unsigned long getLen() const;
@@ -18,19 +18,20 @@ public:
unsigned int getWord(long pos) const;
unsigned int getDWord(long pos) const;
const char* getString(long pos=0) const;
- void discardFirstBytes(int n);
- friend ostream &operator<<(ostream &s, const bufferStore &m);
+ void discardFirstBytes(int);
+ friend ostream &operator<<(ostream &, const bufferStore &);
bool empty() const;
// Writing utils
void init();
- void init(const unsigned char*buff, long len);
- void addByte(unsigned char c);
- void addWord(int a);
- void addDWord(long a);
- void addString(const char* s);
- void addStringT(const char* s);
- void addBuff(const bufferStore &s, long maxLen=-1);
+ 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);
private:
void checkAllocd(long newLen);
diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc
index c51c557..cb04919 100644
--- a/lib/ppsocket.cc
+++ b/lib/ppsocket.cc
@@ -30,6 +30,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include "defs.h"
#include "bool.h"
@@ -126,7 +127,6 @@ printPeer()
bool ppsocket::
connect(char *Peer, int PeerPort, char *Host, int HostPort)
{
-
//****************************************************
//* If we aren't already bound set the host and bind *
//****************************************************
@@ -172,13 +172,16 @@ listen(char *Host, int Port)
m_LastError = lastErrorCode();
return (false);
}
+ // Our accept member function relies on non-blocking accepts,
+ // so set the flag here (rather than every time around the loop)
+ fcntl(m_Socket, F_SETFL, O_NONBLOCK);
return (true);
}
ppsocket *ppsocket::
accept(char *Peer, int MaxLen)
{
- unsigned int len;
+ socklen_t len;
ppsocket *accepted;
char *peer;
@@ -197,7 +200,6 @@ accept(char *Peer, int MaxLen)
//***********************
len = sizeof(struct sockaddr);
- fcntl(m_Socket, F_SETFL, O_NONBLOCK);
accepted->m_Socket =::accept(m_Socket, &accepted->m_PeerAddr, &len);
if (accepted->m_Socket == INVALID_SOCKET) {
@@ -209,6 +211,14 @@ accept(char *Peer, int MaxLen)
//* Got a connection so fill in the other attributes *
//****************************************************
+ // Make sure the new socket hasn't inherited O_NONBLOCK
+ // from the accept socket
+ int flags = fcntl( accepted->m_Socket, F_GETFL, 0 );
+ if( flags >= 0 ) {
+ flags &= ~O_NONBLOCK;
+ fcntl( accepted->m_Socket, F_SETFL, flags);
+ }
+
accepted->m_HostAddr = m_HostAddr;
accepted->m_Bound = true;
@@ -503,6 +513,11 @@ bindSocket(char *Host, int Port)
return (false);
}
}
+ // Set SO_REUSEADDR
+ int one = 1;
+ if (setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &one, sizeof(int)) < 0 )
+ cerr << "Warning: Unable to set SO_REUSEADDR option\n";
// If a host name was supplied then use it
if (!setHost(Host, Port)) {
return (false);
diff --git a/lib/rfsv.cc b/lib/rfsv.cc
new file mode 100644
index 0000000..3b9dc6a
--- /dev/null
+++ b/lib/rfsv.cc
@@ -0,0 +1,158 @@
+#include "rfsv.h"
+
+char *rfsv::
+opErr(long status)
+{
+ enum errs e = (enum errs) status;
+ switch (e) {
+ case E_PSI_GEN_NONE:
+ return "no error";
+ case E_PSI_GEN_FAIL:
+ return "general";
+ case E_PSI_GEN_ARG:
+ return "bad argument";
+ case E_PSI_GEN_OS:
+ return "OS error";
+ case E_PSI_GEN_NSUP:
+ return "not supported";
+ case E_PSI_GEN_UNDER:
+ return "numeric underflow";
+ case E_PSI_GEN_OVER:
+ return "numeric overflow";
+ case E_PSI_GEN_RANGE:
+ return "numeric exception";
+ case E_PSI_GEN_INUSE:
+ return "in use";
+ case E_PSI_GEN_NOMEMORY:
+ return "out of memory";
+ case E_PSI_GEN_NOSEGMENTS:
+ return "out of segments";
+ case E_PSI_GEN_NOSEM:
+ return "out of semaphores";
+ case E_PSI_GEN_NOPROC:
+ return "out of processes";
+ case E_PSI_GEN_OPEN:
+ return "already open";
+ case E_PSI_GEN_NOTOPEN:
+ return "not open";
+ case E_PSI_GEN_IMAGE:
+ return "bad image";
+ case E_PSI_GEN_RECEIVER:
+ return "receiver error";
+ case E_PSI_GEN_DEVICE:
+ return "device error";
+ case E_PSI_GEN_FSYS:
+ return "no filesystem";
+ case E_PSI_GEN_START:
+ return "not ready";
+ case E_PSI_GEN_NOFONT:
+ return "no font";
+ case E_PSI_GEN_TOOWIDE:
+ return "too wide";
+ case E_PSI_GEN_TOOMANY:
+ return "too many";
+ case E_PSI_FILE_EXIST:
+ return "file already exists";
+ case E_PSI_FILE_NXIST:
+ return "no such file";
+ case E_PSI_FILE_WRITE:
+ return "write error";
+ case E_PSI_FILE_READ:
+ return "read error";
+ case E_PSI_FILE_EOF:
+ return "end of file";
+ case E_PSI_FILE_FULL:
+ return "disk/serial read buffer full";
+ case E_PSI_FILE_NAME:
+ return "invalid name";
+ case E_PSI_FILE_ACCESS:
+ return "access denied";
+ case E_PSI_FILE_LOCKED:
+ return "ressource locked";
+ case E_PSI_FILE_DEVICE:
+ return "no such device";
+ case E_PSI_FILE_DIR:
+ return "no such directory";
+ case E_PSI_FILE_RECORD:
+ return "no such record";
+ case E_PSI_FILE_RDONLY:
+ return "file is read-only";
+ case E_PSI_FILE_INV:
+ return "invalid I/O operation";
+ case E_PSI_FILE_PENDING:
+ return "I/O pending (not yet completed)";
+ case E_PSI_FILE_VOLUME:
+ return "invalid volume name";
+ case E_PSI_FILE_CANCEL:
+ return "cancelled";
+ case E_PSI_FILE_ALLOC:
+ return "no memory for control block";
+ case E_PSI_FILE_DISC:
+ return "unit disconnected";
+ case E_PSI_FILE_CONNECT:
+ return "already connected";
+ case E_PSI_FILE_RETRAN:
+ return "retransmission threshold exceeded";
+ case E_PSI_FILE_LINE:
+ return "physical link failure";
+ case E_PSI_FILE_INACT:
+ return "inactivity timer expired";
+ case E_PSI_FILE_PARITY:
+ return "serial parity error";
+ case E_PSI_FILE_FRAME:
+ return "serial framing error";
+ case E_PSI_FILE_OVERRUN:
+ return "serial overrun error";
+ case E_PSI_MDM_CONFAIL:
+ return "modem cannot connect to remote modem";
+ case E_PSI_MDM_BUSY:
+ return "remote modem busy";
+ case E_PSI_MDM_NOANS:
+ return "remote modem did not answer";
+ case E_PSI_MDM_BLACKLIST:
+ return "number blacklisted by the modem";
+ case E_PSI_FILE_NOTREADY:
+ return "drive not ready";
+ case E_PSI_FILE_UNKNOWN:
+ return "unknown media";
+ case E_PSI_FILE_DIRFULL:
+ return "directory full";
+ case E_PSI_FILE_PROTECT:
+ return "write-protected";
+ case E_PSI_FILE_CORRUPT:
+ return "media corrupt";
+ case E_PSI_FILE_ABORT:
+ return "aborted operation";
+ case E_PSI_FILE_ERASE:
+ return "failed to erase flash media";
+ case E_PSI_FILE_INVALID:
+ return "invalid file for DBF system";
+ case E_PSI_GEN_POWER:
+ return "power failure";
+ case E_PSI_FILE_TOOBIG:
+ return "too big";
+ case E_PSI_GEN_DESCR:
+ return "bad descriptor";
+ case E_PSI_GEN_LIB:
+ return "bad entry point";
+ case E_PSI_FILE_NDISC:
+ return "could not diconnect";
+ case E_PSI_FILE_DRIVER:
+ return "bad driver";
+ case E_PSI_FILE_COMPLETION:
+ return "operation not completed";
+ case E_PSI_GEN_BUSY:
+ return "server busy";
+ case E_PSI_GEN_TERMINATED:
+ return "terminated";
+ case E_PSI_GEN_DIED:
+ return "died";
+ case E_PSI_FILE_HANDLE:
+ return "bad handle";
+ case E_PSI_NOT_SIBO:
+ return "invalid operation for RFSV16";
+ default:
+ return "Unknown error";
+ }
+}
+
diff --git a/lib/rfsv.h b/lib/rfsv.h
new file mode 100644
index 0000000..e6006ef
--- /dev/null
+++ b/lib/rfsv.h
@@ -0,0 +1,151 @@
+#ifndef _rfsv_h_
+#define _rfsv_h_
+
+class ppsocket;
+class bufferStore;
+class bufferArray;
+
+#define RFSV_SENDLEN 2000
+
+typedef int (*cpCallback_t)(long);
+
+// Abstract base class of RFSV ; 16-bit and 32-bit variants implement this
+// interface
+class rfsv {
+ public:
+ virtual ~rfsv() {}
+ virtual void reset() = 0;
+ virtual void reconnect() = 0;
+ virtual long getStatus() = 0;
+ virtual const char *getConnectName() = 0;
+ virtual long fopen(long, const char *, long &) = 0;
+ virtual long mktemp(long *, char *) = 0;
+ virtual long fcreatefile(long, const char *, long &) = 0;
+ virtual long freplacefile(long, const char *, long &) = 0;
+ virtual long fopendir(long, const char *, long &) = 0;
+ virtual long fclose(long) = 0;
+ virtual long dir(const char *, bufferArray *) = 0;
+ virtual long fgetmtime(const char *, long *) = 0;
+ virtual long fsetmtime(const char *, long) = 0;
+ virtual long fgetattr(const char *, long *) = 0;
+ virtual long fgeteattr(const char *, long *, long *, long *) =0;
+ virtual long fsetattr(const char *, long, long) = 0;
+ virtual long dircount(const char *, long *) = 0;
+ virtual long devlist(long *) = 0;
+ virtual char *devinfo(int, long *, long *, long *, long *) = 0;
+ virtual char *opAttr(long) = 0;
+ virtual long opMode(long) = 0;
+ virtual long fread(long, unsigned char *, long) = 0;
+ virtual long fwrite(long, unsigned char *, long) = 0;
+ virtual long copyFromPsion(const char *, const char *, cpCallback_t) = 0;
+ virtual long copyToPsion(const char *, const char *, cpCallback_t) = 0;
+ virtual long fsetsize(long, long) = 0;
+ virtual long fseek(long, long, long) = 0;
+ virtual long mkdir(const char *) = 0;
+ virtual long rmdir(const char *) = 0;
+ virtual long rename(const char *, const char *) = 0;
+ virtual long remove(const char *) = 0;
+
+ char *opErr(long);
+
+ enum seek_mode {
+ PSI_SEEK_SET = 1,
+ PSI_SEEK_CUR = 2,
+ PSI_SEEK_END = 3
+ };
+
+ enum open_flags {
+ PSI_O_RDONLY = 00,
+ PSI_O_WRONLY = 01,
+ PSI_O_RDWR = 02,
+ };
+
+ enum open_mode {
+ PSI_O_CREAT = 0100,
+ PSI_O_EXCL = 0200,
+ PSI_O_TRUNC = 01000,
+ PSI_O_APPEND = 02000,
+ };
+
+ enum errs {
+ E_PSI_GEN_NONE = 0,
+ E_PSI_GEN_FAIL = -1,
+ E_PSI_GEN_ARG = -2,
+ E_PSI_GEN_OS = -3,
+ E_PSI_GEN_NSUP = -4,
+ E_PSI_GEN_UNDER = -5,
+ E_PSI_GEN_OVER = -6,
+ E_PSI_GEN_RANGE = -7,
+ E_PSI_GEN_DIVIDE = -8,
+ E_PSI_GEN_INUSE = -9,
+ E_PSI_GEN_NOMEMORY = - 10,
+ E_PSI_GEN_NOSEGMENTS = -11,
+ E_PSI_GEN_NOSEM = -12,
+ E_PSI_GEN_NOPROC = -13,
+ E_PSI_GEN_OPEN = -14,
+ E_PSI_GEN_NOTOPEN = -15,
+ E_PSI_GEN_IMAGE = -16,
+ E_PSI_GEN_RECEIVER = -17,
+ E_PSI_GEN_DEVICE = -18,
+ E_PSI_GEN_FSYS = -19,
+ E_PSI_GEN_START = -20,
+ E_PSI_GEN_NOFONT = -21,
+ E_PSI_GEN_TOOWIDE = -22,
+ E_PSI_GEN_TOOMANY = -23,
+ E_PSI_FILE_EXIST = -32,
+ E_PSI_FILE_NXIST = -33,
+ E_PSI_FILE_WRITE = -34,
+ E_PSI_FILE_READ = -35,
+ E_PSI_FILE_EOF = -36,
+ E_PSI_FILE_FULL = -37,
+ E_PSI_FILE_NAME = -38,
+ E_PSI_FILE_ACCESS = -39,
+ E_PSI_FILE_LOCKED = -40,
+ E_PSI_FILE_DEVICE = -41,
+ E_PSI_FILE_DIR = -42,
+ E_PSI_FILE_RECORD = -43,
+ E_PSI_FILE_RDONLY = -44,
+ E_PSI_FILE_INV = -45,
+ E_PSI_FILE_PENDING = -46,
+ E_PSI_FILE_VOLUME = -47,
+ E_PSI_FILE_CANCEL = -48,
+ E_PSI_FILE_ALLOC = -49,
+ E_PSI_FILE_DISC = -50,
+ E_PSI_FILE_CONNECT = -51,
+ E_PSI_FILE_RETRAN = -52,
+ E_PSI_FILE_LINE = -53,
+ E_PSI_FILE_INACT = -54,
+ E_PSI_FILE_PARITY = -55,
+ E_PSI_FILE_FRAME = -56,
+ E_PSI_FILE_OVERRUN = -57,
+ E_PSI_MDM_CONFAIL = -58,
+ E_PSI_MDM_BUSY = -59,
+ E_PSI_MDM_NOANS = -60,
+ E_PSI_MDM_BLACKLIST = -61,
+ E_PSI_FILE_NOTREADY = -62,
+ E_PSI_FILE_UNKNOWN = -63,
+ E_PSI_FILE_DIRFULL = -64,
+ E_PSI_FILE_PROTECT = -65,
+ E_PSI_FILE_CORRUPT = -66,
+ E_PSI_FILE_ABORT = -67,
+ E_PSI_FILE_ERASE = -68,
+ E_PSI_FILE_INVALID = -69,
+ E_PSI_GEN_POWER = -100,
+ E_PSI_FILE_TOOBIG = -101,
+ E_PSI_GEN_DESCR = -102,
+ E_PSI_GEN_LIB = -103,
+ E_PSI_FILE_NDISC = -104,
+ E_PSI_FILE_DRIVER = -105,
+ E_PSI_FILE_COMPLETION = -106,
+ E_PSI_GEN_BUSY = -107,
+ E_PSI_GEN_TERMINATED = -108,
+ E_PSI_GEN_DIED = -109,
+ E_PSI_FILE_HANDLE = -110,
+
+ // Special error code for "Operation not permitted in RFSV16"
+ E_PSI_NOT_SIBO = -200
+ };
+};
+
+#endif
+
diff --git a/lib/rfsv16.cc b/lib/rfsv16.cc
new file mode 100644
index 0000000..9420b57
--- /dev/null
+++ b/lib/rfsv16.cc
@@ -0,0 +1,836 @@
+//
+// RFSV16 - An implementation of the PSION SIBO RFSV Client protocol
+//
+// Copyright (C) 1999 Philip Proudman
+// Modifications for plptools:
+// Copyright (C) 1999 Matt J. Gumbley <matt@gumbley.demon.co.uk>
+// Sources: rfsv32.cc by Fritz Elfert, and rfsv16.cc by Philip Proudman
+// Descriptions of the RFSV16 protocol by Michael Pieper, Olaf Flebbe & Me.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// e-mail philip.proudman@btinternet.com
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rfsv16.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+rfsv16::rfsv16(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+ reset();
+}
+
+// move to base class?
+rfsv16::~rfsv16()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+// move to base class?
+void rfsv16::
+reconnect()
+{
+cerr << "rfsv16::reconnect" << endl;
+ skt->closeSocket();
+ skt->reconnect();
+ serNum = 0;
+ reset();
+}
+
+// move to base class?
+void rfsv16::
+reset()
+{
+cerr << "rfsv16::reset" << endl;
+ bufferStore a;
+ status = E_PSI_FILE_DISC;
+ a.addStringT(getConnectName());
+ if (skt->sendBufferStore(a)) {
+ if (skt->getBufferStore(a) == 1) {
+ if (!strcmp(a.getString(0), "Ok"))
+ status = E_PSI_GEN_NONE;
+ }
+ }
+}
+
+// move to base class?
+long rfsv16::
+getStatus()
+{
+ return status;
+}
+
+// move to base class?
+const char *rfsv16::
+getConnectName()
+{
+ return "SYS$RFSV.*";
+}
+
+int rfsv16::
+convertName(const char* orig, char *retVal)
+{
+ int len = strlen(orig);
+ char *temp = new char [len+1];
+
+ // FIXME: need to return 1 if OOM?
+ for (int i=0; i <= len; i++) {
+ if (orig[i] == '/')
+ temp[i] = '\\';
+ else
+ temp[i] = orig[i];
+ }
+
+ if (len == 0 || temp[1] != ':') {
+ // We can automatically supply a drive letter
+ strcpy(retVal, DDRIVE);
+
+ if (len == 0 || temp[0] != '\\') {
+ strcat(retVal, DBASEDIR);
+ }
+ else {
+ retVal[strlen(retVal)-1] = 0;
+ }
+
+ strcat(retVal, temp);
+ }
+ else {
+ strcpy(retVal, temp);
+ }
+
+ delete [] temp;
+ cout << retVal << endl;
+ return 0;
+}
+
+long rfsv16::
+fopen(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return (long)rv;
+
+ // FIXME: anything that calls fopen should NOT do the name
+ // conversion - it's just done here.
+
+ a.addWord(attr & 0xFFFF);
+ a.addString(realName);
+ a.addByte(0x00); // Needs to be manually Null-Terminated.
+ if (!sendCommand(FOPEN, a))
+ 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);
+ return 0;
+ }
+ // cerr << "fopen: Unknown response (" << attr << "," << name << ") " << a <<endl;
+ return res;
+}
+
+// internal
+long rfsv16::
+mktemp(long *handle, char *tmpname)
+{
+cerr << "rfsv16::mktemp ***" << endl;
+ return 0;
+}
+
+// internal and external
+long rfsv16::
+fcreatefile(long attr, const char *name, long &handle)
+{
+cerr << "rfsv16::fcreatefile ***" << endl;
+ return 0;
+}
+
+// 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;
+}
+
+// internal
+long rfsv16::
+fopendir(long attr, const char *name, long &handle)
+{
+cerr << "rfsv16::fopendir ***" << endl;
+ return 0;
+}
+
+long rfsv16::
+fclose(long fileHandle)
+{
+ bufferStore a;
+ 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;
+}
+
+long rfsv16::
+dir(const char *dirName, bufferArray * files)
+{
+ long fileHandle;
+ long res;
+
+ long status = fopen(P_FDIR, dirName, fileHandle);
+ if (status != 0) {
+ return status;
+ }
+
+ while (1) {
+ bufferStore a;
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDIRREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(4); // Don't know what these mean!
+ while (a.getLen() > 16) {
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "dir: not version 2" << endl;
+ return 1;
+ }
+ int status = a.getWord(2);
+ long size = a.getDWord(4);
+ long date = a.getDWord(8);
+ const char *s = a.getString(16);
+ a.discardFirstBytes(17+strlen(s));
+
+ bufferStore temp;
+ temp.addDWord(date);
+ temp.addDWord(size);
+ temp.addDWord((long)status);
+ temp.addStringT(s);
+ files->pushBuffer(temp);
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+char * rfsv16::
+opAttr(long attr)
+{
+ static char buf[11];
+ buf[0] = ((attr & rfsv16::P_FAWRITE) ? 'w' : '-');
+ buf[1] = ((attr & rfsv16::P_FAHIDDEN) ? 'h' : '-');
+ buf[2] = ((attr & rfsv16::P_FASYSTEM) ? 's' : '-');
+ buf[3] = ((attr & rfsv16::P_FAVOLUME) ? 'v' : '-');
+ buf[4] = ((attr & rfsv16::P_FADIR) ? 'd' : '-');
+ buf[5] = ((attr & rfsv16::P_FAMOD) ? 'm' : '-');
+ buf[6] = ((attr & rfsv16::P_FAREAD) ? 'r' : '-');
+ buf[7] = ((attr & rfsv16::P_FAEXEC) ? 'x' : '-');
+ buf[8] = ((attr & rfsv16::P_FASTREAM) ? 'b' : '-');
+ buf[9] = ((attr & rfsv16::P_FATEXT) ? 't' : '-');
+ buf[10] = '\0';
+ return (char *) (&buf);
+}
+
+
+long rfsv16::
+opMode(long mode)
+{
+ long ret = 0;
+
+ ret |= ((mode & 03) == PSI_O_RDONLY) ? 0 : P_FUPDATE;
+ ret |= (mode & PSI_O_TRUNC) ? P_FREPLACE : 0;
+ ret |= (mode & PSI_O_CREAT) ? P_FCREATE : 0;
+ ret |= (mode & PSI_O_APPEND) ? P_FAPPEND : 0;
+ ret |= (mode & PSI_O_EXCL) ? 0 : P_FSHARE;
+ return ret;
+}
+
+long rfsv16::
+fgetmtime(const char *name, long *mtime)
+{
+cerr << "rfsv16::fgetmtime" << endl;
+ // NB: fgetattr, fgeteattr is almost identical...
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ 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);
+ }
+ cerr << "fgetmtime: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fsetmtime(const char *name, long mtime)
+{
+cerr << "rfsv16::fsetmtime ***" << endl;
+ // I don't think there's a protocol frame that allows us to set the
+ // modification time. SFDATE allows setting of creation time...
+ return E_PSI_NOT_SIBO;
+}
+
+long rfsv16::
+fgetattr(const char *name, long *attr)
+{
+ // NB: fgetmtime, fgeteattr are almost identical...
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ 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);
+ }
+ cerr << "fgetattr: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fgeteattr(const char *name, long *attr, long *size, long *time)
+{
+ bufferStore a;
+ char realName[200];
+ int rv = convertName(name, realName);
+ if (rv) return rv;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(FINFO, a))
+ return E_PSI_FILE_DISC;
+
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ if (a.getLen() == 2) {
+ cerr << "fgeteattr: Error " << a.getWord(0) << " on file " << name << endl;
+ return 1;
+ }
+ 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);
+ }
+ cerr << "fgeteattr: Unknown response (" << name << ") " << a <<endl;
+ return 1;
+}
+
+long rfsv16::
+fsetattr(const char *name, long seta, long unseta)
+{
+cerr << "rfsv16::fsetattr" << endl;
+ // seta are attributes to set; unseta are attributes to unset. Need to
+ // turn this into attributes to change state and a bit mask.
+ // 210000
+ // 008421
+ // a shr
+ long statusword = seta & (~ unseta);
+ statusword ^= 0x0000001; // r bit is inverted
+ long bitmask = seta | unseta;
+ // cerr << "seta is " << hex << setw(2) << setfill('0') << seta << endl;
+ // cerr << "unseta is " << hex << setw(2) << setfill('0') << unseta << endl;
+ // cerr << "statusword is " << hex << setw(2) << setfill('0') << statusword << endl;
+ // cerr << "bitmask is " << hex << setw(2) << setfill('0') << bitmask << endl;
+ bufferStore a;
+ a.addWord(statusword & 0xFFFF);
+ a.addWord(bitmask & 0xFFFF);
+ a.addString(name);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ if (!sendCommand(SFSTAT, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+long rfsv16::
+dircount(const char *name, long *count)
+{
+ long fileHandle;
+ long res;
+ *count = 0;
+
+ long status = fopen(P_FDIR, name, fileHandle);
+ if (status != 0) {
+ return status;
+ }
+
+ while (1) {
+ bufferStore a;
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDIRREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(4); // Don't know what these mean!
+ while (a.getLen() > 16) {
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "dir: not version 2" << endl;
+ return 1;
+ }
+ // int status = a.getWord(2);
+ // long size = a.getDWord(4);
+ // long date = a.getDWord(8);
+ const char *s = a.getString(16);
+ a.discardFirstBytes(17+strlen(s));
+ (*count)++;
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+long rfsv16::
+devlist(long *devbits)
+{
+ long res;
+ long fileHandle;
+ *devbits = 0;
+
+ // The following is taken from a trace between a Series 3c and PsiWin.
+ // Hope it works! We PARSE to find the correct node, then FOPEN
+ // (P_FDEVICE) this, FDEVICEREAD each entry, setting the appropriate
+ // drive-letter-bit in devbits, then FCLOSE.
+
+ bufferStore a;
+ a.init();
+ a.addByte(0x00); // no Name 1
+ a.addByte(0x00); // no Name 2
+ a.addByte(0x00); // no Name 3
+ if (!sendCommand(PARSE, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ return res;
+
+ // Find the drive to FOPEN
+ char name[4] = { 'x', ':', '\\', '\0' } ;
+ a.discardFirstBytes(8); // 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);
+ if (status != 0) {
+ return status;
+ }
+ while (1) {
+ bufferStore a;
+ a.init();
+ a.addWord(fileHandle & 0xFFFF);
+ if (!sendCommand(FDEVICEREAD, a))
+ return E_PSI_FILE_DISC;
+ res = getResponse(a);
+ if (res)
+ break;
+ a.discardFirstBytes(2); // Result
+ int version = a.getWord(0);
+ if (version != 2) {
+ cerr << "devlist: not version 2" << endl;
+ return 1; // FIXME
+ }
+ char drive = a.getByte(64);
+ if (drive >= 'A' && drive <= 'Z') {
+ int shift = (drive - 'A');
+ (*devbits) |= (long) ( 1 << shift );
+ }
+ else {
+ cerr << "devlist: non-alphabetic drive letter ("
+ << drive << ")" << endl;
+ }
+ }
+ if ((short int)res == E_PSI_FILE_EOF)
+ res = 0;
+ fclose(fileHandle);
+ return res;
+}
+
+char *rfsv16::
+devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
+ long *vuniqueid)
+{
+ bufferStore a;
+ long res;
+ long fileHandle;
+
+ // Again, this is taken from an excahnge between PsiWin and a 3c.
+ // For each drive, we PARSE with its drive letter to get a response
+ // (which we ignore), then do a STATUSDEVICE to get the info.
+
+ a.init();
+ a.addByte((char) (devnum + 'A')); // Name 1
+ a.addByte(':');
+ a.addByte(0x00);
+ a.addByte(0x00); // No name 2
+ a.addByte(0x00); // No name 3
+ if (!sendCommand(PARSE, a))
+ return NULL;
+ res = getResponse(a);
+ if (res) {
+ // cerr << "devinfo PARSE res is " << dec << (signed short int) res << endl;
+ return NULL;
+ }
+
+ a.init();
+ a.addByte((char) (devnum + 'A')); // Name 1
+ a.addByte(':');
+ a.addByte('\\');
+ a.addByte(0x00);
+ if (!sendCommand(STATUSDEVICE, a))
+ return NULL;
+ res = getResponse(a);
+ if (res) {
+ // 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);
+ long free = a.getDWord(10);
+ const char *volume = a.getString(14);
+ int battery = a.getWord(30);
+ const char *devicename = a.getString(62);
+ *vfree = free;
+ *vtotal = size;
+ *vattr = type;
+ *vuniqueid = 0;
+ static char name[2] = { 'x', '\0' };
+ name[0] = (char) (devnum + 'A');
+ return strdup(name);
+}
+
+bool rfsv16::
+sendCommand(enum commands cc, bufferStore & data)
+{
+ bool result;
+ bufferStore a;
+ a.addWord(cc);
+ a.addWord(data.getLen());
+ a.addBuff(data);
+ result = skt->sendBufferStore(a);
+ if (!result)
+ status = E_PSI_FILE_DISC;
+ return result;
+}
+
+
+long rfsv16::
+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 &&
+ data.getWord(2) == data.getLen()-4) {
+ data.discardFirstBytes(4);
+ long ret = data.getWord(0);
+ return ret;
+ } else
+ status = E_PSI_FILE_DISC;
+ cerr << "rfsv16::getResponse: duff response. Size field:" <<
+data.getWord(2) << " Frame size:" << data.getLen()-4 << " Result field:" <<
+data.getWord(4) << endl;
+ return status;
+}
+
+char * rfsv16::
+opErr(long status)
+{
+cerr << "rfsv16::opErr 0x" << hex << setfill('0') << setw(4)
+ << status << " (" << dec << (signed short int)status << ")" << endl;
+ return rfsv::opErr(status);
+}
+
+long rfsv16::
+fread(long handle, unsigned char *buf, long len)
+{
+cerr << "rfsv16::fread ***" << endl;
+ 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
+ // 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);
+ sendCommand(FREAD, a);
+ long res = getResponse(a);
+ remaining -= a.getLen();
+// copy the data to buf
+
+cerr << "fread getResponse returned " << dec<< (signed short int) res << " data: " << a << dec <<endl;
+ if (res) {
+ return res;
+ }
+ }
+ return len;
+}
+
+long rfsv16::
+fwrite(long handle, unsigned char *buf, long len)
+{
+cerr << "rfsv16::fwrite ***" << endl;
+ return 0;
+}
+
+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];
+ if ((len = fread(handle, buf, sizeof(buf))) > 0)
+ op.write(buf, len);
+ if (cb) {
+ if (!cb(len)) {
+ len = E_PSI_FILE_CANCEL;
+ break;
+ }
+ }
+ } while (len > 0);
+
+ fclose(handle);
+ op.close();
+ return len;
+}
+
+long rfsv16::
+copyToPsion(const char *from, const char *to, cpCallback_t cb)
+{
+cerr << "rfsv16::copyToPsion" << endl;
+ long handle;
+ long res;
+
+ ifstream ip(from);
+ if (!ip)
+ return E_PSI_FILE_NXIST;
+ res = fcreatefile(P_FSTREAM | P_FUPDATE, to, handle);
+ if (res != 0) {
+ res = freplacefile(P_FSTREAM | P_FUPDATE, to, handle);
+ if (res != 0)
+ return res;
+ }
+ unsigned char *buff = new unsigned char[RFSV_SENDLEN];
+ int total = 0;
+ while (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 = 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;
+}
+
+/*
+ * Unix-like implementation off fseek with one
+ * exception: If seeking beyond eof, the gap
+ * contains garbage instead of zeroes.
+ */
+long rfsv16::
+fseek(long handle, long pos, long mode)
+{
+cerr << "rfsv16::fseek ***" << endl;
+ return 0;
+}
+
+long rfsv16::
+mkdir(const char* dirName)
+{
+ char realName[200];
+ int rv = convertName(dirName, realName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(MKDIR, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from mkdir "<< a <<endl;
+ return 1;
+}
+
+long rfsv16::
+rmdir(const char *dirName)
+{
+ // There doesn't seem to be an RMDIR command, but DELETE works. We
+ // should probably check to see if the file is a directory first!
+ return remove(dirName);
+}
+
+long rfsv16::
+rename(const char *oldName, const char *newName)
+{
+cerr << "rfsv16::rename ***" << endl;
+ char realOldName[200];
+ int rv = convertName(oldName, realOldName);
+ if (rv) return rv;
+ char realNewName[200];
+ rv = convertName(newName, realNewName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realOldName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ a.addString(realNewName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(RENAME, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from rename "<< a <<endl;
+ return 1;
+}
+
+long rfsv16::
+remove(const char* psionName)
+{
+ char realName[200];
+ int rv = convertName(psionName, realName);
+ if (rv) return rv;
+ bufferStore a;
+ a.addString(realName);
+ a.addByte(0x00); // needs to be null-terminated,
+ // and this needs sending in the length word.
+ sendCommand(DELETE, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 2) {
+ // Correct response
+ return a.getWord(0);
+ }
+ cerr << "Unknown response from delete "<< a <<endl;
+ return 1;
+}
+
+
diff --git a/lib/rfsv16.h b/lib/rfsv16.h
new file mode 100644
index 0000000..175e540
--- /dev/null
+++ b/lib/rfsv16.h
@@ -0,0 +1,127 @@
+#ifndef _rfsv16_h_
+#define _rfsv16_h_
+
+#include "rfsv.h"
+
+class rfsv16 : public rfsv {
+ public:
+ rfsv16(ppsocket *);
+ ~rfsv16();
+ void reset(); // these 2 added
+ void reconnect();
+
+ // these are the original publics
+ long dir(const char *, bufferArray *);
+ /*long read(const char* psionName, const char* localName);
+ long write(const char* localName, const char* psionName);*/
+ long mkdir(const char *);
+
+ // these are FS' promotions
+ long dircount(const char *, long *);
+ long copyFromPsion(const char *, const char *, cpCallback_t);
+ long copyToPsion(const char *, const char *, cpCallback_t);
+ long rmdir(const char *);
+ long remove(const char *); // MJG: was this del? FE: yes
+ long rename(const char *, const char *);
+ long mktemp(long *, char *);
+ long fgeteattr(const char *, long *, long *, long *);
+ long fgetattr(const char *, long *);
+ long fsetattr(const char *, long seta, long unseta);
+ long fgetmtime(const char *, long *);
+ long fsetmtime(const char *, long);
+ long fopendir(long, const char *, long &);
+ long fopen(long, const char *, long &);
+ long fcreatefile(long, const char *, long &);
+ long freplacefile(long, const char *, long &);
+ long fseek(long, long, long);
+ long fread(long, unsigned char *, long);
+ long fwrite(long, unsigned char *, long);
+ long fsetsize(long, long);
+ long fclose(long);
+
+ long devlist(long *);
+ char *devinfo(int, long *, long *, long *, long *);
+ long getStatus();
+ char *opErr(long);
+ char *opAttr(long);
+ long opMode(long);
+
+private:
+ enum commands {
+ FOPEN = 0, // File Open
+ FCLOSE = 2, // File Close
+ FREAD = 4, // File Read
+ FDIRREAD = 6, // Read Directory entries
+ FDEVICEREAD = 8, // Device Information
+ FWRITE = 10, // File Write
+ FSEEK = 12, // File Seek
+ FFLUSH = 14, // Flush
+ FSETEOF = 16,
+ RENAME = 18,
+ DELETE = 20,
+ FINFO = 22,
+ SFSTAT = 24,
+ PARSE = 26,
+ MKDIR = 28,
+ OPENUNIQUE = 30,
+ STATUSDEVICE = 32,
+ PATHTEST = 34,
+ STATUSSYSTEM = 36,
+ CHANGEDIR = 38,
+ SFDATE = 40,
+ RESPONSE = 42
+ };
+
+ enum fopen_attrib {
+ P_FOPEN = 0x0000, /* Open file */
+ P_FCREATE = 0x0001, /* Create file */
+ P_FREPLACE = 0x0002, /* Replace file */
+ P_FAPPEND = 0x0003, /* Append records */
+ P_FUNIQUE = 0x0004, /* Unique file open */
+ P_FSTREAM = 0x0000, /* Stream access to a binary file */
+ P_FSTREAM_TEXT = 0x0010, /* Stream access to a text file */
+ P_FTEXT = 0x0020, /* Record access to a text file */
+ P_FDIR = 0x0030, /* Record access to a directory file */
+ P_FFORMAT = 0x0040, /* Format a device */
+ P_FDEVICE = 0x0050, /* Record access to device name list */
+ P_FNODE = 0x0060, /* Record access to node name list */
+ P_FUPDATE = 0x0100, /* Read and write access */
+ P_FRANDOM = 0x0200, /* Random access */
+ P_FSHARE = 0x0400 /* File can be shared */
+ };
+
+ enum status_enum {
+ P_FAWRITE = 0x0001, /* can the file be written to? */
+ P_FAHIDDEN = 0x0002, /* set if file is hidden */
+ P_FASYSTEM = 0x0004, /* set if file is a system file */
+ P_FAVOLUME = 0x0008, /* set if the name is a volume name */
+ P_FADIR = 0x0010, /* set if file is a directory file */
+ P_FAMOD = 0x0020, /* has the file been modified? */
+ P_FAREAD = 0x0100, /* can the file be read? */
+ P_FAEXEC = 0x0200, /* is the file executable? */
+ P_FASTREAM = 0x0400, /* is the file a byte stream file? */
+ P_FATEXT = 0x0800 /* is it a text file? */
+ };
+
+ const char *getConnectName();
+
+ // File handlers
+ //long fopen(fopen_attrib a, const char* file, int &handle); // returns status 0=OK
+ //long fclose(int fileHandle);
+
+ // Miscellaneous
+ int convertName(const char*, char *);
+
+ // Communication
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+
+ // Vars
+ ppsocket *skt;
+ // MJG: not sure what these are yet
+ int serNum;
+ long status; // current connection status
+ int tDiff; // don't think this is used anywhere
+};
+
+#endif
diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc
index 447a693..d4df37f 100644
--- a/lib/rfsv32.cc
+++ b/lib/rfsv32.cc
@@ -33,8 +33,6 @@
#include "ppsocket.h"
#include "bufferarray.h"
-#define RFSV_SENDLEN 230
-
rfsv32::rfsv32(ppsocket * _skt) : serNum(0)
{
skt = _skt;
@@ -45,7 +43,7 @@ rfsv32::~rfsv32()
{
bufferStore a;
a.addStringT("Close");
- if (status == PSI_ERR_NONE)
+ if (status == E_PSI_GEN_NONE)
skt->sendBufferStore(a);
skt->closeSocket();
}
@@ -63,12 +61,12 @@ void rfsv32::
reset()
{
bufferStore a;
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
a.addStringT(getConnectName());
if (skt->sendBufferStore(a)) {
if (skt->getBufferStore(a) == 1) {
if (!strcmp(a.getString(0), "Ok"))
- status = PSI_ERR_NONE;
+ status = E_PSI_GEN_NONE;
}
}
}
@@ -82,7 +80,7 @@ getStatus()
const char *rfsv32::
getConnectName()
{
- return "SYS$RFSV.*";
+ return "SYS$RFSV";
}
char *rfsv32::
@@ -105,7 +103,7 @@ fopen(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(OPEN_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4) {
handle = a.getDWord(0);
@@ -119,7 +117,7 @@ mktemp(long *handle, char *tmpname)
{
bufferStore a;
if (!sendCommand(TEMP_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res == 0) {
*handle = a.getDWord(0);
@@ -138,7 +136,7 @@ fcreatefile(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(CREATE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -155,7 +153,7 @@ freplacefile(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(REPLACE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -172,7 +170,7 @@ fopendir(long attr, const char *name, long &handle)
a.addString(n);
free(n);
if (!sendCommand(OPEN_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (!res && a.getLen() == 4)
handle = a.getDWord(0);
@@ -185,7 +183,7 @@ fclose(long handle)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(CLOSE_HANDLE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -206,6 +204,7 @@ micro2time(unsigned long microHi, unsigned long microLo)
micro -= pes;
micro += EPOCH_DIFF_SECS;
micro -= EPOCH_2H;
+ micro += 3600; /* 1 hour PJC */
return (long) micro;
}
@@ -218,6 +217,7 @@ time2micro(unsigned long time, unsigned long &microHi, unsigned long &microLo)
micro += pes;
micro -= EPOCH_DIFF_SECS;
micro += EPOCH_2H;
+ micro -= 3600; /* 1 hour PJC */
micro *= (unsigned long long)1000000;
microLo = (micro & (unsigned long long)0x0FFFFFFFF);
micro >>= 32;
@@ -228,7 +228,7 @@ long rfsv32::
dir(const char *name, bufferArray * files)
{
long handle;
- long res = fopendir(PSI_ATTR_HIDDEN | PSI_ATTR_SYSTEM | PSI_ATTR_DIRECTORY, name, handle);
+ long res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle);
if (res != 0)
return res;
@@ -236,7 +236,7 @@ dir(const char *name, bufferArray * files)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(READ_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
if (res)
break;
@@ -270,12 +270,40 @@ dir(const char *name, bufferArray * files)
a.discardFirstBytes(d);
}
}
- if (res == PSI_ERR_EoF)
+ if (res == E_PSI_FILE_EOF)
res = 0;
fclose(handle);
return res;
}
+// beware this returns static data
+char * rfsv32::
+opAttr(long attr)
+{
+ static char buf[10];
+ buf[0] = ((attr & rfsv32::EPOC_ATTR_DIRECTORY) ? 'd' : '-');
+ buf[1] = ((attr & rfsv32::EPOC_ATTR_RONLY) ? '-' : 'w');
+ buf[2] = ((attr & rfsv32::EPOC_ATTR_HIDDEN) ? 'h' : '-');
+ buf[3] = ((attr & rfsv32::EPOC_ATTR_SYSTEM) ? 's' : '-');
+ buf[4] = ((attr & rfsv32::EPOC_ATTR_ARCHIVE) ? 'a' : '-');
+ buf[5] = ((attr & rfsv32::EPOC_ATTR_VOLUME) ? 'v' : '-');
+ buf[6] = ((attr & rfsv32::EPOC_ATTR_NORMAL) ? 'n' : '-');
+ buf[7] = ((attr & rfsv32::EPOC_ATTR_TEMPORARY) ? 't' : '-');
+ buf[8] = ((attr & rfsv32::EPOC_ATTR_COMPRESSED) ? 'c' : '-');
+ buf[9] = '\0';
+ return (char *) (&buf);
+}
+
+long rfsv32::
+opMode(long mode)
+{
+ long ret = 0;
+
+ ret |= (((mode & 03) == PSI_O_RDONLY) ? 0 : EPOC_OMODE_READ_WRITE);
+ ret |= (mode & PSI_O_EXCL) ? 0 : EPOC_OMODE_SHARE_READERS;
+ return ret;
+}
+
long rfsv32::
fgetmtime(const char *name, long *mtime)
{
@@ -285,7 +313,7 @@ fgetmtime(const char *name, long *mtime)
a.addString(n);
free(n);
if (!sendCommand(MODIFIED, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -306,7 +334,7 @@ fsetmtime(const char *name, long mtime)
a.addString(n);
free(n);
if (!sendCommand(SET_MODIFIED, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -322,7 +350,7 @@ fgetattr(const char *name, long *attr)
a.addString(n);
free(n);
if (!sendCommand(ATT, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -339,7 +367,7 @@ fgeteattr(const char *name, long *attr, long *size, long *time)
a.addString(n);
free(n);
if (!sendCommand(REMOTE_ENTRY, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
long res = getResponse(a);
if (res != 0)
return res;
@@ -367,7 +395,7 @@ fsetattr(const char *name, long seta, long unseta)
a.addString(n);
free(n);
if (!sendCommand(SET_ATT, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -375,7 +403,7 @@ long rfsv32::
dircount(const char *name, long *count)
{
long handle;
- long res = fopendir(PSI_ATTR_HIDDEN | PSI_ATTR_SYSTEM | PSI_ATTR_DIRECTORY, name, handle);
+ long res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle);
*count = 0;
if (res != 0)
return res;
@@ -384,7 +412,7 @@ dircount(const char *name, long *count)
bufferStore a;
a.addDWord(handle);
if (!sendCommand(READ_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
if (res)
break;
@@ -400,7 +428,7 @@ dircount(const char *name, long *count)
}
}
fclose(handle);
- if (res == PSI_ERR_EoF)
+ if (res == E_PSI_FILE_EOF)
res = 0;
return res;
}
@@ -412,7 +440,7 @@ devlist(long *devbits)
long res;
if (!sendCommand(GET_DRIVE_LIST, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
res = getResponse(a);
*devbits = 0;
if ((res == 0) && (a.getLen() == 26)) {
@@ -451,9 +479,9 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
bool rfsv32::
sendCommand(enum commands cc, bufferStore & data)
{
- if (status == PSI_ERR_DISCONNECTED) {
+ if (status == E_PSI_FILE_DISC) {
reconnect();
- if (status == PSI_ERR_DISCONNECTED)
+ if (status == E_PSI_FILE_DISC)
return false;
}
bool result;
@@ -467,7 +495,7 @@ sendCommand(enum commands cc, bufferStore & data)
a.addBuff(data);
result = skt->sendBufferStore(a);
if (!result)
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
return result;
}
@@ -478,155 +506,14 @@ getResponse(bufferStore & data)
data.getWord(0) == 0x11) {
long ret = data.getDWord(4);
data.discardFirstBytes(8);
- return ret;
+ return err2psierr(ret);
} else
- status = PSI_ERR_DISCONNECTED;
+ status = E_PSI_FILE_DISC;
return status;
}
-char * rfsv32::
-opErr(long status)
-{
- enum errs e = (enum errs) status;
- switch (e) {
- case PSI_ERR_NONE:
- return "";
- case PSI_ERR_NOT_FOUND:
- return "not found";
- case PSI_ERR_GENERAL:
- return "general";
- break;
- case PSI_ERR_CANCEL:
- return "cancelled";
- break;
- case PSI_ERR_NO_MEMORY:
- return "out of memory";
- break;
- case PSI_ERR_NOT_SUPPORTED:
- return "unsupported";
- break;
- case PSI_ERR_ARGUMENT:
- return "bad argument";
- break;
- case PSI_ERR_TOTAL_LOSS_OF_PRECISION:
- return "total loss of precision";
- break;
- case PSI_ERR_BAD_HANDLE:
- return "bad handle";
- break;
- case PSI_ERR_OVERFLOW:
- return "overflow";
- break;
- case PSI_ERR_UNDERFLOW:
- return "underflow";
- break;
- case PSI_ERR_ALREADY_EXISTS:
- return "file already exists";
- break;
- case PSI_ERR_PATH_NOT_FOUND:
- return "path not found";
- break;
- case PSI_ERR_DIED:
- return "DIED";
- break;
- case PSI_ERR_IN_USE:
- return "resource in use";
- break;
- case PSI_ERR_SERVER_TERMINATED:
- return "server terminated";
- break;
- case PSI_ERR_SERVER_BUSY:
- return "server busy";
- break;
- case PSI_ERR_COMPLETION:
- return "completed";
- break;
- case PSI_ERR_NOT_READY:
- return "not ready";
- break;
- case PSI_ERR_UNKNOWN:
- return "unknown";
- break;
- case PSI_ERR_CORRUPT:
- return "corrupt";
- break;
- case PSI_ERR_ACCESS_DENIED:
- return "permission denied";
- break;
- case PSI_ERR_LOCKED:
- return "resource locked";
- break;
- case PSI_ERR_WRITE:
- return "write";
- break;
- case PSI_ERR_DISMOUNTED:
- return "dismounted";
- break;
- case PSI_ERR_EoF:
- return "end of file";
- break;
- case PSI_ERR_DISK_FULL:
- return "disk full";
- break;
- case PSI_ERR_BAD_DRIVER:
- return "bad driver";
- break;
- case PSI_ERR_BAD_NAME:
- return "bad name";
- break;
- case PSI_ERR_COMMS_LINE_FAIL:
- return "comms line failed";
- break;
- case PSI_ERR_COMMS_FRAME:
- return "comms framing error";
- break;
- case PSI_ERR_COMMS_OVERRUN:
- return "comms overrun";
- break;
- case PSI_ERR_COMMS_PARITY:
- return "comms parity error";
- break;
- case PSI_ERR_TIMEOUT:
- return "timed out";
- break;
- case PSI_ERR_COULD_NOT_CONNECT:
- return "could not connect";
- break;
- case PSI_ERR_COULD_NOT_DISCONNECT:
- return "could not disconnect";
- break;
- case PSI_ERR_DISCONNECTED:
- return "unit disconnected";
- break;
- case PSI_ERR_BAD_LIBRARY_ENTRY_POINT:
- return "bad library entry point";
- break;
- case PSI_ERR_BAD_DESCRIPTOR:
- return "bad descriptor";
- break;
- case PSI_ERR_ABORT:
- return "abort";
- break;
- case PSI_ERR_TOO_BIG:
- return "too big";
- break;
- case PSI_ERR_DIVIDE_BY_ZERO:
- return "division by zero";
- break;
- case PSI_ERR_BAD_POWER:
- return "bad power";
- break;
- case PSI_ERR_DIR_FULL:
- return "directory full";
- break;
- default:
- return "Unknown error";
- break;
- }
-}
-
long rfsv32::
-fread(long handle, char *buf, long len)
+fread(long handle, unsigned char *buf, long len)
{
long res;
long count = 0;
@@ -634,9 +521,9 @@ fread(long handle, char *buf, long len)
do {
bufferStore a;
a.addDWord(handle);
- a.addDWord(((len-count) > 2000)?2000:(len-count));
+ a.addDWord(((len-count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len-count));
if (!sendCommand(READ_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
res = a.getLen();
@@ -650,20 +537,20 @@ fread(long handle, char *buf, long len)
}
long rfsv32::
-fwrite(long handle, char *buf, long len)
+fwrite(long handle, unsigned char *buf, long len)
{
long res;
long total = 0;
long count;
do {
- count = ((len - total) > 2000)?2000:(len - total);
+ count = ((len - total) > RFSV_SENDLEN)?RFSV_SENDLEN:(len - total);
bufferStore a;
bufferStore tmp((unsigned char *)buf, count);
a.addDWord(handle);
a.addBuff(tmp);
if (!sendCommand(WRITE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
total += count;
@@ -673,42 +560,48 @@ fwrite(long handle, char *buf, long len)
}
long rfsv32::
-copyFromPsion(const char *from, const char *to)
+copyFromPsion(const char *from, const char *to, cpCallback_t cb)
{
long handle;
long res;
long len;
- if ((res = fopen(PSI_OMODE_SHARE_READERS | PSI_OMODE_BINARY, from, handle)) != 0)
+ if ((res = fopen(EPOC_OMODE_SHARE_READERS | EPOC_OMODE_BINARY, from, handle)) != 0)
return res;
ofstream op(to);
if (!op) {
fclose(handle);
return -1;
}
+ unsigned char *buff = new unsigned char[RFSV_SENDLEN];
do {
- char buf[2000];
- if ((len = fread(handle, buf, sizeof(buf))) > 0)
- op.write(buf, len);
+ if ((len = fread(handle, buff, RFSV_SENDLEN)) > 0)
+ op.write(buff, len);
+ if (cb) {
+ if (!cb(len)) {
+ len = E_PSI_FILE_CANCEL;
+ break;
+ }
+ }
} while (len > 0);
-
+ delete[]buff;
fclose(handle);
op.close();
return len;
}
long rfsv32::
-copyToPsion(const char *from, const char *to)
+copyToPsion(const char *from, const char *to, cpCallback_t cb)
{
long handle;
long res;
ifstream ip(from);
if (!ip)
- return PSI_ERR_NOT_FOUND;
- res = fcreatefile(PSI_OMODE_BINARY | PSI_OMODE_SHARE_EXCLUSIVE | PSI_OMODE_READ_WRITE, to, handle);
+ return E_PSI_FILE_NXIST;
+ res = fcreatefile(EPOC_OMODE_BINARY | EPOC_OMODE_SHARE_EXCLUSIVE | EPOC_OMODE_READ_WRITE, to, handle);
if (res != 0) {
- res = freplacefile(PSI_OMODE_BINARY | PSI_OMODE_SHARE_EXCLUSIVE | PSI_OMODE_READ_WRITE, to, handle);
+ res = freplacefile(EPOC_OMODE_BINARY | EPOC_OMODE_SHARE_EXCLUSIVE | EPOC_OMODE_READ_WRITE, to, handle);
if (res != 0)
return res;
}
@@ -717,19 +610,33 @@ copyToPsion(const char *from, const char *to)
while (ip && !ip.eof()) {
ip.read(buff, RFSV_SENDLEN);
bufferStore tmp(buff, ip.gcount());
- total += tmp.getLen();
- if (tmp.getLen() == 0)
+ int len = tmp.getLen();
+ total += len;
+ if (len == 0)
break;
bufferStore a;
a.addDWord(handle);
a.addBuff(tmp);
- if (!sendCommand(WRITE_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ if (!sendCommand(WRITE_FILE, a)) {
+ ip.close();
+ delete[]buff;
+ return E_PSI_FILE_DISC;
+ }
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();
@@ -744,7 +651,7 @@ fsetsize(long handle, long size)
a.addDWord(handle);
a.addDWord(size);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -776,7 +683,7 @@ fseek(long handle, long pos, long mode)
*/
if ((mode < PSI_SEEK_SET) || (mode > PSI_SEEK_END))
- return PSI_ERR_ARGUMENT;
+ return E_PSI_GEN_ARG;
if ((mode == PSI_SEEK_CUR) && (pos >= 0)) {
/* get and save current position */
@@ -784,7 +691,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(PSI_SEEK_CUR);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
savpos = a.getDWord(0);
@@ -798,7 +705,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(PSI_SEEK_END);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
savpos = a.getDWord(0);
@@ -809,7 +716,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(savpos + pos);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
pos = 0;
@@ -820,7 +727,7 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(mode);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
realpos = a.getDWord(0);
@@ -841,14 +748,14 @@ fseek(long handle, long pos, long mode)
a.addDWord(handle);
a.addDWord(calcpos);
if (!sendCommand(SET_SIZE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
a.addDWord(calcpos);
a.addDWord(handle);
a.addDWord(PSI_SEEK_SET);
if (!sendCommand(SEEK_FILE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
if ((res = getResponse(a)) != 0)
return res;
realpos = a.getDWord(0);
@@ -871,7 +778,7 @@ mkdir(const char *name)
}
free(n);
if (!sendCommand(MK_DIR_ALL, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -890,7 +797,7 @@ rmdir(const char *name)
}
free(n);
if (!sendCommand(RM_DIR, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -907,7 +814,7 @@ rename(const char *oldname, const char *newname)
free(on);
free(nn);
if (!sendCommand(RENAME, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
@@ -920,6 +827,63 @@ remove(const char *name)
a.addString(n);
free(n);
if (!sendCommand(DELETE, a))
- return PSI_ERR_DISCONNECTED;
+ return E_PSI_FILE_DISC;
return getResponse(a);
}
+
+static long e2psi[] = {
+ rfsv::E_PSI_FILE_DIRFULL, // -43
+ rfsv::E_PSI_GEN_POWER, // -42
+ rfsv::E_PSI_GEN_DIVIDE, // -41
+ rfsv::E_PSI_FILE_TOOBIG, // -40
+ rfsv::E_PSI_FILE_ABORT, // -39
+ rfsv::E_PSI_GEN_DESCR, // -38
+ rfsv::E_PSI_GEN_LIB, // -37
+ rfsv::E_PSI_FILE_NDISC, // -36
+ rfsv::E_PSI_FILE_DISC, // -35
+ rfsv::E_PSI_FILE_CONNECT, // -34
+ rfsv::E_PSI_FILE_RETRAN, // -33
+ rfsv::E_PSI_FILE_PARITY, // -32
+ rfsv::E_PSI_FILE_OVERRUN, // -31
+ rfsv::E_PSI_FILE_FRAME, // -30
+ rfsv::E_PSI_FILE_LINE, // -29
+ rfsv::E_PSI_FILE_NAME, // -28
+ rfsv::E_PSI_FILE_DRIVER, // -27
+ rfsv::E_PSI_FILE_FULL, // -26
+ rfsv::E_PSI_FILE_EOF, // -25
+ rfsv::E_PSI_GEN_FSYS, // -24
+ rfsv::E_PSI_FILE_WRITE, // -23
+ rfsv::E_PSI_FILE_LOCKED, // -22
+ rfsv::E_PSI_FILE_ACCESS, // -21
+ rfsv::E_PSI_FILE_CORRUPT, // -20
+ rfsv::E_PSI_FILE_UNKNOWN, // -19
+ rfsv::E_PSI_FILE_NOTREADY, // -18
+ rfsv::E_PSI_FILE_COMPLETION, // -17
+ rfsv::E_PSI_GEN_BUSY, // -16
+ rfsv::E_PSI_GEN_TERMINATED, // -15
+ rfsv::E_PSI_GEN_INUSE, // -14
+ rfsv::E_PSI_GEN_DIED, // -13
+ rfsv::E_PSI_FILE_DIR, // -12
+ rfsv::E_PSI_FILE_EXIST, // -11
+ rfsv::E_PSI_GEN_UNDER, // -10
+ rfsv::E_PSI_GEN_OVER, // -9
+ rfsv::E_PSI_FILE_HANDLE, // -8
+ rfsv::E_PSI_GEN_RANGE, // -7
+ rfsv::E_PSI_GEN_ARG, // -6
+ rfsv::E_PSI_GEN_NSUP, // -5
+ rfsv::E_PSI_GEN_NOMEMORY, // -4
+ rfsv::E_PSI_FILE_CANCEL, // -3
+ rfsv::E_PSI_GEN_FAIL, // -2
+ rfsv::E_PSI_FILE_NXIST, // -1
+ rfsv::E_PSI_GEN_NONE // 0
+};
+
+long rfsv32::
+err2psierr(long status)
+{
+ if ((status > E_EPOC_NONE) || (status < E_EPOC_DIR_FULL)) {
+ cerr << "FATAL: inavlid error-code" << endl;
+ return -999;
+ }
+ return e2psi[status - E_EPOC_DIR_FULL];
+}
diff --git a/lib/rfsv32.h b/lib/rfsv32.h
index 00cab2b..8383e72 100644
--- a/lib/rfsv32.h
+++ b/lib/rfsv32.h
@@ -1,121 +1,119 @@
#ifndef _rfsv32_h_
#define _rfsv32_h_
+#include "rfsv.h"
+
class ppsocket;
class bufferStore;
class bufferArray;
-class rfsv32 {
+class rfsv32 : public rfsv {
public:
- rfsv32(ppsocket * skt);
+ rfsv32(ppsocket *);
~rfsv32();
void reset();
void reconnect();
- long dir(const char *name, bufferArray * files);
- long dircount(const char *name, long *count);
- long copyFromPsion(const char *from, const char *to);
- long copyToPsion(const char *from, const char *to);
- long mkdir(const char *name);
- long rmdir(const char *name);
- long remove(const char *name);
- long rename(const char *oldname, const char *newname);
- long mktemp(long *handle, char *tmpname);
- long fgeteattr(const char *name, long *attr, long *size, long *time);
- long fgetattr(const char *name, long *attr);
- long fsetattr(const char *name, long seta, long unseta);
- long fgetmtime(const char *name, long *mtime);
- long fsetmtime(const char *name, long mtime);
- long fopendir(long attr, const char *name, long &handle);
- long fopen(long attr, const char *name, long &handle);
- long fcreatefile(long attr, const char *name, long &handle);
- long freplacefile(long attr, const char *name, long &handle);
- long fseek(long handle, long pos, long mode);
- long fread(long handle, char *buf, long len);
- long fwrite(long handle, char *buf, long len);
- long fsetsize(long handle, long size);
- long fclose(long handle);
+ long dir(const char *, bufferArray *);
+ long dircount(const char *, long *);
+ long copyFromPsion(const char *, const char *, cpCallback_t);
+ long copyToPsion(const char *, const char *, cpCallback_t);
+ long mkdir(const char *);
+ long rmdir(const char *);
+ long remove(const char *);
+ long rename(const char *, const char *);
+ long mktemp(long *, char *);
+ long fgeteattr(const char *, long *, long *, long *);
+ long fgetattr(const char *, long *);
+ long fsetattr(const char *, long, long);
+ long fgetmtime(const char *, long *);
+ long fsetmtime(const char *, long);
+ long fopendir(long, const char *, long &);
+ long fopen(long, const char *, long &);
+ long fcreatefile(long, const char *, long &);
+ long freplacefile(long, const char *, long &);
+ long fseek(long, long, long);
+ long fread(long, unsigned char *, long);
+ long fwrite(long, unsigned char *, long);
+ long fsetsize(long, long);
+ long fclose(long);
- long devlist(long *devbits);
- char *devinfo(int devnum, long *vfree, long *vtotal, long *vattr, long *vuiqueid);
+ long devlist(long *);
+ char *devinfo(int, long *, long *, long *, long *);
long getStatus();
- char *opErr(long status);
-
- enum seek_mode {
- PSI_SEEK_SET = 1,
- PSI_SEEK_CUR = 2,
- PSI_SEEK_END = 3
- };
+ char *opAttr(long);
+ long opMode(long);
+ private:
+
enum file_attrib {
- PSI_ATTR_RONLY = 0x0001,
- PSI_ATTR_HIDDEN = 0x0002,
- PSI_ATTR_SYSTEM = 0x0004,
- PSI_ATTR_DIRECTORY = 0x0010,
- PSI_ATTR_ARCHIVE = 0x0020,
- PSI_ATTR_VOLUME = 0x0040,
- PSI_ATTR_NORMAL = 0x0080,
- PSI_ATTR_TEMPORARY = 0x0100,
- PSI_ATTR_COMPRESSED = 0x0800
+ EPOC_ATTR_RONLY = 0x0001,
+ EPOC_ATTR_HIDDEN = 0x0002,
+ EPOC_ATTR_SYSTEM = 0x0004,
+ EPOC_ATTR_DIRECTORY = 0x0010,
+ EPOC_ATTR_ARCHIVE = 0x0020,
+ EPOC_ATTR_VOLUME = 0x0040,
+ EPOC_ATTR_NORMAL = 0x0080,
+ EPOC_ATTR_TEMPORARY = 0x0100,
+ EPOC_ATTR_COMPRESSED = 0x0800
};
enum open_mode {
- PSI_OMODE_SHARE_EXCLUSIVE = 0x0000,
- PSI_OMODE_SHARE_READERS = 0x0001,
- PSI_OMODE_SHARE_ANY = 0x0002,
- PSI_OMODE_BINARY = 0x0000,
- PSI_OMODE_TEXT = 0x0020,
- PSI_OMODE_READ_WRITE = 0x0200
+ EPOC_OMODE_SHARE_EXCLUSIVE = 0x0000,
+ EPOC_OMODE_SHARE_READERS = 0x0001,
+ EPOC_OMODE_SHARE_ANY = 0x0002,
+ EPOC_OMODE_BINARY = 0x0000,
+ EPOC_OMODE_TEXT = 0x0020,
+ EPOC_OMODE_READ_WRITE = 0x0200
};
- enum errs {
- PSI_ERR_NONE = 0,
- PSI_ERR_NOT_FOUND = -1,
- PSI_ERR_GENERAL = -2,
- PSI_ERR_CANCEL = -3,
- PSI_ERR_NO_MEMORY = -4,
- PSI_ERR_NOT_SUPPORTED = -5,
- PSI_ERR_ARGUMENT = -6,
- PSI_ERR_TOTAL_LOSS_OF_PRECISION = -7,
- PSI_ERR_BAD_HANDLE = -8,
- PSI_ERR_OVERFLOW = -9,
- PSI_ERR_UNDERFLOW = -10,
- PSI_ERR_ALREADY_EXISTS = -11,
- PSI_ERR_PATH_NOT_FOUND = -12,
- PSI_ERR_DIED = -13,
- PSI_ERR_IN_USE = -14,
- PSI_ERR_SERVER_TERMINATED = -15,
- PSI_ERR_SERVER_BUSY = -16,
- PSI_ERR_COMPLETION = -17,
- PSI_ERR_NOT_READY = -18,
- PSI_ERR_UNKNOWN = -19,
- PSI_ERR_CORRUPT = -20,
- PSI_ERR_ACCESS_DENIED = -21,
- PSI_ERR_LOCKED = -22,
- PSI_ERR_WRITE = -23,
- PSI_ERR_DISMOUNTED = -24,
- PSI_ERR_EoF = -25,
- PSI_ERR_DISK_FULL = -26,
- PSI_ERR_BAD_DRIVER = -27,
- PSI_ERR_BAD_NAME = -28,
- PSI_ERR_COMMS_LINE_FAIL = -29,
- PSI_ERR_COMMS_FRAME = -30,
- PSI_ERR_COMMS_OVERRUN = -31,
- PSI_ERR_COMMS_PARITY = -32,
- PSI_ERR_TIMEOUT = -33,
- PSI_ERR_COULD_NOT_CONNECT = -34,
- PSI_ERR_COULD_NOT_DISCONNECT = -35,
- PSI_ERR_DISCONNECTED = -36,
- PSI_ERR_BAD_LIBRARY_ENTRY_POINT = -37,
- PSI_ERR_BAD_DESCRIPTOR = -38,
- PSI_ERR_ABORT = -39,
- PSI_ERR_TOO_BIG = -40,
- PSI_ERR_DIVIDE_BY_ZERO = -41,
- PSI_ERR_BAD_POWER = -42,
- PSI_ERR_DIR_FULL = -43
+ enum epoc_errs {
+ E_EPOC_NONE = 0,
+ E_EPOC_NOT_FOUND = -1,
+ E_EPOC_GENERAL = -2,
+ E_EPOC_CANCEL = -3,
+ E_EPOC_NO_MEMORY = -4,
+ E_EPOC_NOT_SUPPORTED = -5,
+ E_EPOC_ARGUMENT = -6,
+ E_EPOC_TOTAL_LOSS_OF_PRECISION = -7,
+ E_EPOC_BAD_HANDLE = -8,
+ E_EPOC_OVERFLOW = -9,
+ E_EPOC_UNDERFLOW = -10,
+ E_EPOC_ALREADY_EXISTS = -11,
+ E_EPOC_PATH_NOT_FOUND = -12,
+ E_EPOC_DIED = -13,
+ E_EPOC_IN_USE = -14,
+ E_EPOC_SERVER_TERMINATED = -15,
+ E_EPOC_SERVER_BUSY = -16,
+ E_EPOC_COMPLETION = -17,
+ E_EPOC_NOT_READY = -18,
+ E_EPOC_UNKNOWN = -19,
+ E_EPOC_CORRUPT = -20,
+ E_EPOC_ACCESS_DENIED = -21,
+ E_EPOC_LOCKED = -22,
+ E_EPOC_WRITE = -23,
+ E_EPOC_DISMOUNTED = -24,
+ E_EPOC_EoF = -25,
+ E_EPOC_DISK_FULL = -26,
+ E_EPOC_BAD_DRIVER = -27,
+ E_EPOC_BAD_NAME = -28,
+ E_EPOC_COMMS_LINE_FAIL = -29,
+ E_EPOC_COMMS_FRAME = -30,
+ E_EPOC_COMMS_OVERRUN = -31,
+ E_EPOC_COMMS_PARITY = -32,
+ E_EPOC_TIMEOUT = -33,
+ E_EPOC_COULD_NOT_CONNECT = -34,
+ E_EPOC_COULD_NOT_DISCONNECT = -35,
+ E_EPOC_DISCONNECTED = -36,
+ E_EPOC_BAD_LIBRARY_ENTRY_POINT = -37,
+ E_EPOC_BAD_DESCRIPTOR = -38,
+ E_EPOC_ABORT = -39,
+ E_EPOC_TOO_BIG = -40,
+ E_EPOC_DIVIDE_BY_ZERO = -41,
+ E_EPOC_BAD_POWER = -42,
+ E_EPOC_DIR_FULL = -43
};
- private:
enum commands {
CLOSE_HANDLE = 0x01,
OPEN_DIR = 0x10,
@@ -154,15 +152,16 @@ class rfsv32 {
};
const char *getConnectName();
+ long err2psierr(long);
// Communication
- bool sendCommand(enum commands c, bufferStore & data);
- long getResponse(bufferStore & data);
- char *convertSlash(const char *name);
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+ char *convertSlash(const char *);
// time-conversion
- unsigned long micro2time(unsigned long microHi, unsigned long microLo);
- void time2micro(unsigned long mtime, unsigned long &microHi, unsigned long &microLo);
+ unsigned long micro2time(unsigned long, unsigned long);
+ void time2micro(unsigned long, unsigned long &, unsigned long &);
// Vars
ppsocket *skt;
diff --git a/lib/rfsvfactory.cc b/lib/rfsvfactory.cc
new file mode 100644
index 0000000..2e2067e
--- /dev/null
+++ b/lib/rfsvfactory.cc
@@ -0,0 +1,86 @@
+//
+// RFSVFACTORY - factory object that creates an appropriate RFSV object
+// based on whatever the NCP daemon discovered in the INFO exchange.
+//
+// Copyright (C) 1999 Matt J. Gumbley <matt@gumbley.demon.co.uk>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rfsv.h"
+#include "rfsv16.h"
+#include "rfsv32.h"
+#include "rfsvfactory.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+rfsvfactory::rfsvfactory(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+}
+
+rfsv * rfsvfactory::create(bool reconnect)
+{
+ // skt is connected to the ncp daemon, which will have (hopefully) seen
+ // an INFO exchange, where the protocol version of the remote Psion was
+ // sent, and noted. We have to ask the ncp daemon which protocol it saw,
+ // so we can instantiate the correct RFSV protocol handler for the
+ // caller. We announce ourselves to the NCP daemon, and the relevant
+ // RFSV module will also announce itself.
+ bufferStore a;
+ a.init();
+ a.addStringT("NCP$INFO");
+ if (!skt->sendBufferStore(a)) {
+ if (!reconnect)
+ cerr << "rfsvfactory::create couldn't send version request" << endl; else {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ }
+ return NULL;
+ }
+ if (skt->getBufferStore(a) == 1) {
+ if (a.getLen() > 8 && !strncmp(a.getString(), "Series 3", 8)) {
+ return new rfsv16(skt);
+ }
+ else if (a.getLen() > 8 && !strncmp(a.getString(), "Series 5", 8)) {
+ return new rfsv32(skt);
+ }
+ if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ return NULL;
+ }
+ // Invalid protocol version
+ cerr << "rfsvfactory::create received odd protocol version from
+ncpd! (" << a << ")" << endl;
+ } else {
+ cerr << "rfsvfactory::create sent, response not 1" << endl;
+ }
+
+ // No message returned.
+ return NULL;
+}
+
diff --git a/lib/rfsvfactory.h b/lib/rfsvfactory.h
new file mode 100644
index 0000000..17b7252
--- /dev/null
+++ b/lib/rfsvfactory.h
@@ -0,0 +1,20 @@
+#ifndef _rfsvfactory_h_
+#define _rfsvfactory_h_
+
+#include "rfsv.h"
+
+class ppsocket;
+
+class rfsvfactory {
+ public:
+ rfsvfactory(ppsocket * skt);
+ virtual rfsv * create(bool);
+
+ private:
+ // Vars
+ ppsocket *skt;
+ int serNum;
+};
+
+#endif
+
diff --git a/lib/rpcs.cc b/lib/rpcs.cc
new file mode 100644
index 0000000..5863c5b
--- /dev/null
+++ b/lib/rpcs.cc
@@ -0,0 +1,283 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "bufferarray.h"
+
+//
+// public common API
+//
+void rpcs::
+reconnect()
+{
+ skt->closeSocket();
+ skt->reconnect();
+ reset();
+}
+
+void rpcs::
+reset()
+{
+ bufferStore a;
+ status = E_PSI_FILE_DISC;
+ a.addStringT(getConnectName());
+ if (skt->sendBufferStore(a)) {
+ if (skt->getBufferStore(a) == 1) {
+ if (!strcmp(a.getString(0), "Ok"))
+ status = E_PSI_GEN_NONE;
+ }
+ }
+}
+
+long rpcs::
+getStatus()
+{
+ return status;
+}
+
+const char *rpcs::
+getConnectName()
+{
+ return "SYS$RPCS";
+}
+
+//
+// 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)
+{
+ if (status == E_PSI_FILE_DISC) {
+ reconnect();
+ if (status == E_PSI_FILE_DISC)
+ return false;
+ }
+ bool result;
+ bufferStore a;
+ a.addByte(cc);
+ a.addBuff(data);
+ result = skt->sendBufferStore(a);
+ if (!result)
+ status = E_PSI_FILE_DISC;
+ return result;
+}
+
+long rpcs::
+getResponse(bufferStore & data)
+{
+ if (skt->getBufferStore(data) == 1) {
+ long ret = data.getByte(0);
+ return ret;
+ } else
+ status = E_PSI_FILE_DISC;
+ return status;
+}
+
+//
+// APIs, identical on SIBO and EPOC
+//
+int rpcs::
+getNCPversion(int &major, int &minor)
+{
+ bufferStore a;
+ if (!sendCommand(QUERY_NCP, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 2)
+ return E_PSI_GEN_FAIL;
+ major = a.getByte(0);
+ minor = a.getByte(1);
+ return res;
+}
+
+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--)
+ a.addByte(0);
+ a.addByte(strlen(args));
+ a.addStringT(args);
+ if (!sendCommand(EXEC_PROG, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+cout << res << " " << a << endl;
+ return res;
+}
+
+int rpcs::
+stopProgram(const char *program)
+{
+ bufferStore a;
+ a.addStringT(program);
+ if (!sendCommand(STOP_PROG, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+queryProgram(const char *program)
+{
+ bufferStore a;
+ a.addStringT(program);
+ if (!sendCommand(QUERY_PROG, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+formatOpen(const char *drive, int &handle, int &count)
+{
+ bufferStore a;
+ a.addStringT(drive);
+ if (!sendCommand(FORMAT_OPEN, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 4)
+ return E_PSI_GEN_FAIL;
+ handle = a.getWord(0);
+ count = a.getWord(2);
+ return res;
+}
+
+int rpcs::
+formatRead(int handle)
+{
+ bufferStore a;
+ a.addWord(handle);
+ if (!sendCommand(FORMAT_READ, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
+int rpcs::
+getUniqueID(const char *device, long &id)
+{
+ bufferStore a;
+ a.addStringT(device);
+ if (!sendCommand(GET_UNIQUEID, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 4)
+ return E_PSI_GEN_FAIL;
+ id = a.getDWord(0);
+ return res;
+}
+
+int rpcs::
+getOwnerInfo(bufferArray &ret)
+{
+ bufferStore a;
+ if (!sendCommand(GET_OWNERINFO, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ a.addByte(0);
+ int l = a.getLen();
+ char *s = (char *)a.getString(0);
+ for (int i = 0; i < l; i++)
+ if (s[i] == 6)
+ s[i] = 0;
+ ret.clear();
+ while (l > 0) {
+ bufferStore b;
+ b.addStringT(s);
+ ret += b;
+ l -= (strlen(s) + 1);
+ s += (strlen(s) + 1);
+ }
+ return res;
+}
+
+int rpcs::
+getMachineType(int &type)
+{
+ bufferStore a;
+ if (!sendCommand(GET_MACHINETYPE, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ if (a.getLen() != 2)
+ return E_PSI_GEN_FAIL;
+ type = a.getWord(0);
+ return res;
+}
+
+int rpcs::
+fuser(const char *name, char *buf, int bufsize)
+{
+ bufferStore a;
+ a.addStringT(name);
+ if (!sendCommand(FUSER, a))
+ return E_PSI_FILE_DISC;
+ long res = getResponse(a);
+ a.discardFirstBytes(1);
+ if (res)
+ return res;
+ int len = ((int)a.getLen() > bufsize) ? bufsize - 1 : a.getLen();
+ strncpy(buf, a.getString(0), len);
+ buf[len] = '\0';
+ char *p;
+ while ((p = strchr(buf, 6)))
+ *p = '\n';
+ return res;
+}
+
+int rpcs::
+quitServer()
+{
+ bufferStore a;
+ if (!sendCommand(QUIT_SERVER, a))
+ return E_PSI_FILE_DISC;
+ return getResponse(a);
+}
+
diff --git a/lib/rpcs.h b/lib/rpcs.h
new file mode 100644
index 0000000..cb71c88
--- /dev/null
+++ b/lib/rpcs.h
@@ -0,0 +1,103 @@
+#ifndef _rpcs_h_
+#define _rpcs_h_
+
+class ppsocket;
+class bufferStore;
+class bufferArray;
+
+class rpcs {
+ public:
+ virtual ~rpcs() {};
+ void reset();
+ void reconnect();
+ long getStatus();
+
+ // API idendical on SIBO and EPOC
+ int getNCPversion(int &, int &);
+ int execProgram(const char *, const char *);
+ int stopProgram(const char *);
+ int queryProgram(const char *);
+ int formatOpen(const char *, int &, int &);
+ int formatRead(int);
+ int getUniqueID(const char *, long &);
+ int getOwnerInfo(bufferArray &);
+ int getMachineType(int &);
+ int fuser(const char *, char *, int);
+ int quitServer(void);
+
+ // API different on SIBO and EPOC
+ virtual int queryDrive(const char, bufferArray &) = 0;
+ virtual int getCmdLine(const char *, char *, int) = 0;
+
+ // API only existent on EPOC
+ // default-methods for SIBO here.
+ virtual int getMachineInfo(void) { 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;}
+ virtual int regWrite(void) { return E_PSI_NOT_SIBO;}
+ virtual int regRead(void) { return E_PSI_NOT_SIBO;}
+ virtual int regDelete(void) { return E_PSI_NOT_SIBO;}
+ virtual int setTime(void) { return E_PSI_NOT_SIBO;}
+ virtual int configOpen(void) { return E_PSI_NOT_SIBO;}
+ virtual int configRead(void) { return E_PSI_NOT_SIBO;}
+ virtual int configWrite(void) { return E_PSI_NOT_SIBO;}
+ virtual int queryOpen(void) { return E_PSI_NOT_SIBO;}
+ virtual int queryRead(void) { return E_PSI_NOT_SIBO;}
+
+ enum errs {
+ E_PSI_GEN_NONE = 0,
+ E_PSI_GEN_FAIL = -1,
+ E_PSI_FILE_DISC = -50,
+ // Special error code for "Operation not permitted in RPCS16"
+ E_PSI_NOT_SIBO = -200
+ };
+
+ enum machs {
+ PSI_MACH_UNKNOWN = 0,
+ PSI_MACH_PC = 1,
+ PSI_MACH_MC = 2,
+ PSI_MACH_HC = 3,
+ PSI_MACH_S3 = 4,
+ PSI_MACH_S3A = 5,
+ PSI_MACH_WORKABOUT = 6,
+ PSI_MACH_SIENNA = 7,
+ PSI_MACH_S3C = 8,
+ PSI_MACH_S5 = 32,
+ PSI_MACH_WINC = 33,
+//TODO: Code for 5mx
+ };
+
+ protected:
+
+ // Vars
+ ppsocket *skt;
+ long status;
+
+ enum commands {
+ QUERY_NCP = 0x00,
+ EXEC_PROG = 0x01,
+ QUERY_DRIVE = 0x02,
+ STOP_PROG = 0x03,
+ QUERY_PROG = 0x04,
+ FORMAT_OPEN = 0x05,
+ FORMAT_READ = 0x06,
+ GET_UNIQUEID = 0x07,
+ GET_OWNERINFO = 0x08,
+ GET_MACHINETYPE = 0x09,
+ GET_CMDLINE = 0x0a,
+ FUSER = 0x0b,
+ CONFIG_OPEN = 0x66,
+ CONFIG_READ = 0x6d,
+ QUIT_SERVER = 0xff
+ };
+
+ // Communication
+ bool sendCommand(enum commands, bufferStore &);
+ long getResponse(bufferStore &);
+ const char *getConnectName();
+
+ char *convertSlash(const char *);
+};
+
+#endif
diff --git a/lib/rpcs16.cc b/lib/rpcs16.cc
new file mode 100644
index 0000000..2786ee8
--- /dev/null
+++ b/lib/rpcs16.cc
@@ -0,0 +1,63 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs16.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+
+rpcs16::rpcs16(ppsocket * _skt)
+{
+ skt = _skt;
+ reset();
+}
+
+rpcs16::~rpcs16()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+int rpcs16::
+queryDrive(char drive, bufferArray &ret)
+{
+ bufferStore a;
+ a.addByte(drive);
+ if (!sendCommand(rpcs::QUERY_DRIVE, a))
+ return rpcs::E_PSI_FILE_DISC;
+ long res = getResponse(a);
+cout << dec << "qd: " << res << " " << a.getLen() << " a="<< a << endl;
+ if (res)
+ return res;
+ return res;
+}
+
+int rpcs16::
+getCmdLine(const char *process, char *buf, int bufsize)
+{
+ return 0;
+}
diff --git a/lib/rpcs16.h b/lib/rpcs16.h
new file mode 100644
index 0000000..14809ae
--- /dev/null
+++ b/lib/rpcs16.h
@@ -0,0 +1,18 @@
+#ifndef _rpcs16_h_
+#define _rpcs16_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+class bufferStore;
+
+class rpcs16 : public rpcs {
+ public:
+ rpcs16(ppsocket *);
+ ~rpcs16();
+
+ int queryDrive(const char, bufferArray &);
+ int getCmdLine(const char *, char *, int);
+};
+
+#endif
diff --git a/lib/rpcs32.cc b/lib/rpcs32.cc
new file mode 100644
index 0000000..d710b9c
--- /dev/null
+++ b/lib/rpcs32.cc
@@ -0,0 +1,114 @@
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+
+#include <stream.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs32.h"
+#include "bufferstore.h"
+#include "bufferarray.h"
+#include "ppsocket.h"
+
+rpcs32::rpcs32(ppsocket * _skt)
+{
+ skt = _skt;
+ reset();
+}
+
+rpcs32::~rpcs32()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == E_PSI_GEN_NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+int rpcs32::
+queryDrive(char drive, bufferArray &ret)
+{
+ bufferStore a;
+ a.addByte(drive);
+ if (!sendCommand(rpcs::QUERY_DRIVE, a))
+ return rpcs::E_PSI_FILE_DISC;
+ getResponse(a);
+ int l = a.getLen();
+ ret.clear();
+//cout << dec << "qd: " << a.getLen() << " a="<< a << endl;
+ while (l > 1) {
+ bufferStore b, c;
+ const char *s;
+ char *p;
+ int pid;
+ int sl;
+
+ s = a.getString(0);
+ sl = strlen(s) + 1;
+ l -= sl;
+ a.discardFirstBytes(sl);
+ p = strstr(s, ".$");
+ if (p) {
+ *p = '\0'; p += 2;
+ sscanf(p, "%d", &pid);
+ } else
+ pid = 0;
+ b.addWord(pid);
+ b.addStringT(s);
+ s = a.getString(0);
+ sl = strlen(s) + 1;
+ l -= sl;
+ a.discardFirstBytes(sl);
+ c.addStringT(s);
+ ret.push(c);
+ ret.push(b);
+ }
+ return 0;
+}
+
+int rpcs32::
+getCmdLine(const char *process, char *buf, int bufsize)
+{
+ return 0;
+}
+
+int rpcs32::
+configOpen(void)
+{
+ bufferStore a;
+cout << "configOpen:" << endl;
+ if (!sendCommand(rpcs::CONFIG_OPEN, a))
+ return rpcs::E_PSI_FILE_DISC;
+ getResponse(a);
+cout << a << endl;
+}
+
+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;
+}
diff --git a/lib/rpcs32.h b/lib/rpcs32.h
new file mode 100644
index 0000000..e33ef10
--- /dev/null
+++ b/lib/rpcs32.h
@@ -0,0 +1,36 @@
+#ifndef _rpcs32_h_
+#define _rpcs32_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+
+class rpcs32 : public rpcs {
+ public:
+ rpcs32(ppsocket *);
+ ~rpcs32();
+
+ int queryDrive(const char, bufferArray &);
+ int getCmdLine(const char *, char *, int);
+#if 0
+ int getMachineInfo(void);
+ int closeHandle(int);
+ int regOpenIter(void);
+ int regReadIter(void);
+ int regWrite(void);
+ 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);
+ int quitServer(void);
+#endif
+
+};
+
+#endif
diff --git a/lib/rpcsfactory.cc b/lib/rpcsfactory.cc
new file mode 100644
index 0000000..7358e56
--- /dev/null
+++ b/lib/rpcsfactory.cc
@@ -0,0 +1,85 @@
+//
+// RPCSFACTORY - factory object that creates an appropriate RPCS object
+// based on whatever the NCP daemon discovered in the INFO exchange.
+// Derived from rfsvfactory by Matt J. Gumbley <matt@gumbley.demon.co.uk>
+//
+// Copyright (C) 2000 Fritz Elfert <felfert@to.com>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include <stream.h>
+#include <stdlib.h>
+#include <fstream.h>
+#include <iomanip.h>
+#include <time.h>
+#include <string.h>
+
+#include "defs.h"
+#include "bool.h"
+#include "rpcs16.h"
+#include "rpcs32.h"
+#include "rpcsfactory.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+
+rpcsfactory::rpcsfactory(ppsocket *_skt) : serNum(0)
+{
+ skt = _skt;
+}
+
+rpcs * rpcsfactory::create(bool reconnect)
+{
+ // skt is connected to the ncp daemon, which will have (hopefully) seen
+ // an INFO exchange, where the protocol version of the remote Psion was
+ // sent, and noted. We have to ask the ncp daemon which protocol it saw,
+ // so we can instantiate the correct rpcs protocol handler for the
+ // caller. We announce ourselves to the NCP daemon, and the relevant
+ // rpcs module will also announce itself.
+ bufferStore a;
+ a.init();
+ a.addStringT("NCP$INFO");
+ if (!skt->sendBufferStore(a)) {
+ if (!reconnect)
+ cerr << "rpcsfactory::create couldn't send version request" << endl; else {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ }
+ return NULL;
+ }
+ if (skt->getBufferStore(a) == 1) {
+ if (a.getLen() > 8 && !strncmp(a.getString(), "Series 3", 8)) {
+ return new rpcs16(skt);
+ }
+ else if (a.getLen() > 8 && !strncmp(a.getString(), "Series 5", 8)) {
+ return new rpcs32(skt);
+ }
+ if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) {
+ skt->closeSocket();
+ serNum = 0;
+ skt->reconnect();
+ return NULL;
+ }
+ // Invalid protocol version
+ cerr << "rpcsfactory::create received odd protocol version from
+ncpd! (" << a << ")" << endl;
+ } else {
+ cerr << "rpcsfactory::create sent, response not 1" << endl;
+ }
+
+ // No message returned.
+ return NULL;
+}
+
diff --git a/lib/rpcsfactory.h b/lib/rpcsfactory.h
new file mode 100644
index 0000000..17a2719
--- /dev/null
+++ b/lib/rpcsfactory.h
@@ -0,0 +1,20 @@
+#ifndef _rpcsfactory_h_
+#define _rpcsfactory_h_
+
+#include "rpcs.h"
+
+class ppsocket;
+
+class rpcsfactory {
+ public:
+ rpcsfactory(ppsocket * skt);
+ virtual rpcs * create(bool);
+
+ private:
+ // Vars
+ ppsocket *skt;
+ int serNum;
+};
+
+#endif
+