diff options
author | Fritz Elfert <felfert@to.com> | 2000-01-17 11:49:41 +0000 |
---|---|---|
committer | Fritz Elfert <felfert@to.com> | 2000-01-17 11:49:41 +0000 |
commit | ab18114bfd38d4632c66401b5bc079241e27fab3 (patch) | |
tree | 14f9c1d5f020cf8ed2f205094ca9e2fc907bb969 /lib | |
parent | 6eceb82662300bf306e70bd943200665bc3c9bc3 (diff) | |
download | plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.gz plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.tar.bz2 plptools-ab18114bfd38d4632c66401b5bc079241e27fab3.zip |
Release of plptools-0.5
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 8 | ||||
-rw-r--r-- | lib/bufferarray.cc | 97 | ||||
-rw-r--r-- | lib/bufferarray.h | 21 | ||||
-rw-r--r-- | lib/bufferstore.cc | 13 | ||||
-rw-r--r-- | lib/bufferstore.h | 25 | ||||
-rw-r--r-- | lib/ppsocket.cc | 21 | ||||
-rw-r--r-- | lib/rfsv.cc | 158 | ||||
-rw-r--r-- | lib/rfsv.h | 151 | ||||
-rw-r--r-- | lib/rfsv16.cc | 836 | ||||
-rw-r--r-- | lib/rfsv16.h | 127 | ||||
-rw-r--r-- | lib/rfsv32.cc | 368 | ||||
-rw-r--r-- | lib/rfsv32.h | 199 | ||||
-rw-r--r-- | lib/rfsvfactory.cc | 86 | ||||
-rw-r--r-- | lib/rfsvfactory.h | 20 | ||||
-rw-r--r-- | lib/rpcs.cc | 283 | ||||
-rw-r--r-- | lib/rpcs.h | 103 | ||||
-rw-r--r-- | lib/rpcs16.cc | 63 | ||||
-rw-r--r-- | lib/rpcs16.h | 18 | ||||
-rw-r--r-- | lib/rpcs32.cc | 114 | ||||
-rw-r--r-- | lib/rpcs32.h | 36 | ||||
-rw-r--r-- | lib/rpcsfactory.cc | 85 | ||||
-rw-r--r-- | lib/rpcsfactory.h | 20 |
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 µHi, unsigned long µLo) 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 µHi, unsigned long µLo); + 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 + |