aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>1999-06-28 23:51:15 +0000
committerFritz Elfert <felfert@to.com>1999-06-28 23:51:15 +0000
commitbd48f19dd8931c871c9b79371ff68cf87d2ccc11 (patch)
tree2b024f2b707fb97fc0796611fb4e7527afcad876
parent7c9e56cea427fb98d84056482f801c4d5264f40e (diff)
downloadplptools-bd48f19dd8931c871c9b79371ff68cf87d2ccc11.tar.gz
plptools-bd48f19dd8931c871c9b79371ff68cf87d2ccc11.tar.bz2
plptools-bd48f19dd8931c871c9b79371ff68cf87d2ccc11.zip
Optimization for speed.
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/bufferarray.cc72
-rw-r--r--lib/bufferarray.h22
-rw-r--r--lib/bufferstore.cc158
-rw-r--r--lib/ppsocket.cc112
-rw-r--r--lib/rfsv32.cc889
-rw-r--r--lib/rfsv32.h172
7 files changed, 1245 insertions, 182 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ec2faee..d374f53 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,3 +1,3 @@
noinst_LIBRARIES = libutils.a
-libutils_a_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc
+libutils_a_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc rfsv32.cc
diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc
index 4dc3971..99b1811 100644
--- a/lib/bufferarray.cc
+++ b/lib/bufferarray.cc
@@ -25,44 +25,52 @@
#include "bufferstore.h"
#include "bufferarray.h"
-bufferArray::bufferArray() {
- len = 0;
- lenAllocd = 5;
- buff = new bufferStore [lenAllocd];
+bufferArray::bufferArray()
+{
+ len = 0;
+ lenAllocd = 5;
+ buff = new bufferStore[lenAllocd];
}
-bufferArray::bufferArray(const bufferArray &a) {
- len = a.len;
- lenAllocd = a.lenAllocd;
- buff = new bufferStore [lenAllocd];
- for (int i=0; i < len; i++) buff[i] = a.buff[i];
+bufferArray::bufferArray(const bufferArray & a)
+{
+ len = a.len;
+ lenAllocd = a.lenAllocd;
+ buff = new bufferStore[lenAllocd];
+ for (int i = 0; i < len; i++)
+ buff[i] = a.buff[i];
}
-bufferArray::~bufferArray() {
- delete [] buff;
+bufferArray::~bufferArray()
+{
+ delete[]buff;
}
-bufferStore bufferArray::popBuffer() {
- bufferStore ret;
- if (len > 0) {
- ret = buff[0];
- len--;
- for (long i=0; i<len; i++) {
- buff[i] = buff[i+1];
- }
- }
- return ret;
+bufferStore bufferArray::
+popBuffer()
+{
+ bufferStore ret;
+ if (len > 0) {
+ ret = buff[0];
+ len--;
+ for (long i = 0; i < len; i++) {
+ buff[i] = buff[i + 1];
+ }
+ }
+ return ret;
}
-void bufferArray::pushBuffer(const bufferStore &b) {
- if (len == lenAllocd) {
- lenAllocd += 5;
- bufferStore* nb = new bufferStore [lenAllocd];
- for (long i=0; i<len; i++) {
- nb[i] = buff[i];
- }
- delete [] buff;
- buff = nb;
- }
- buff[len++] = b;
+void bufferArray::
+pushBuffer(const bufferStore & b)
+{
+ if (len == lenAllocd) {
+ lenAllocd += 5;
+ bufferStore *nb = new bufferStore[lenAllocd];
+ for (long i = 0; i < len; i++) {
+ nb[i] = buff[i];
+ }
+ delete[]buff;
+ buff = nb;
+ }
+ buff[len++] = b;
}
diff --git a/lib/bufferarray.h b/lib/bufferarray.h
index 089eb4e..4cb948e 100644
--- a/lib/bufferarray.h
+++ b/lib/bufferarray.h
@@ -5,19 +5,19 @@
class bufferStore;
class bufferArray {
-public:
- bufferArray();
- bufferArray(const bufferArray &a);
- ~bufferArray();
- void operator =(const bufferArray &a);
+ public:
+ bufferArray();
+ bufferArray(const bufferArray &a);
+ ~bufferArray();
+ void operator =(const bufferArray &a);
- bool empty() const;
- bufferStore popBuffer();
- void pushBuffer(const bufferStore& b);
+ bool empty() const;
+ bufferStore popBuffer();
+ void pushBuffer(const bufferStore& b);
private:
- long len;
- long lenAllocd;
- bufferStore* buff;
+ long len;
+ long lenAllocd;
+ bufferStore* buff;
};
inline bool bufferArray::empty() const { return len == 0; }
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
index 8138ad2..886b952 100644
--- a/lib/bufferstore.cc
+++ b/lib/bufferstore.cc
@@ -26,141 +26,145 @@
#include "bufferstore.h"
bufferStore::bufferStore() {
- lenAllocd = 0;
- buff = NULL;
- len = 0;
- start = 0;
+ lenAllocd = 0;
+ buff = NULL;
+ len = 0;
+ start = 0;
}
bufferStore::bufferStore(const bufferStore &a) {
- lenAllocd = (a.getLen() > MIN_LEN) ? a.getLen() : MIN_LEN;
- buff = new unsigned char [lenAllocd];
- len = a.getLen();
- for (long i=0; i<len; i++) buff[i] = a.getByte(i);
- start = 0;
+ lenAllocd = (a.getLen() > MIN_LEN) ? a.getLen() : MIN_LEN;
+ buff = new unsigned char [lenAllocd];
+ len = a.getLen();
+ memcpy(buff, a.getString(0), len);
+ start = 0;
}
bufferStore::bufferStore(const unsigned char*_buff, long _len) {
- lenAllocd = (_len > MIN_LEN) ? _len : MIN_LEN;
- buff = new unsigned char [lenAllocd];
- len = _len;
- for (long i=0; i<len; i++) buff[i] = _buff[i];
- start = 0;
+ lenAllocd = (_len > MIN_LEN) ? _len : MIN_LEN;
+ buff = new unsigned char [lenAllocd];
+ len = _len;
+ memcpy(buff, _buff, len);
+ start = 0;
}
void bufferStore::operator =(const bufferStore &a) {
- checkAllocd(a.getLen());
- len = a.getLen();
- for (long i=0; i<len; i++) buff[i] = a.getByte(i);
- start = 0;
+ checkAllocd(a.getLen());
+ len = a.getLen();
+ memcpy(buff, a.getString(0), len);
+ start = 0;
}
void bufferStore::init() {
- start = 0;
- len = 0;
+ start = 0;
+ len = 0;
}
void bufferStore::init(const unsigned char*_buff, long _len) {
- checkAllocd(_len);
- start = 0;
- len = _len;
- for (long i=0; i<len; i++) buff[i] = _buff[i];
+ checkAllocd(_len);
+ start = 0;
+ len = _len;
+ memcpy(buff, _buff, len);
}
bufferStore::~bufferStore() {
- delete [] buff;
+ delete [] buff;
}
unsigned long bufferStore::getLen() const {
- if (start > len) return 0;
- return len - start;
+ return (start > len) ? 0 : len - start;
}
unsigned char bufferStore::getByte(long pos) const {
- return buff[pos+start];
+ return buff[pos+start];
}
unsigned int bufferStore::getWord(long pos) const {
- return buff[pos+start] + (buff[pos+start+1] << 8);
+ return buff[pos+start] + (buff[pos+start+1] << 8);
}
unsigned int bufferStore::getDWord(long pos) const {
- return buff[pos+start] +
- (buff[pos+start+1] << 8) +
- (buff[pos+start+2] << 16) +
- (buff[pos+start+3] << 24);
+ return buff[pos+start] +
+ (buff[pos+start+1] << 8) +
+ (buff[pos+start+2] << 16) +
+ (buff[pos+start+3] << 24);
}
const char* bufferStore::getString(long pos) const {
- return (const char*)buff+pos+start;
+ return (const char*)buff+pos+start;
}
ostream &operator<<(ostream &s, const bufferStore &m) {
- {
- for (int i = m.start; i < m.len; i++)
- s << hex << setw(2) << setfill('0') << (int)m.buff[i] << " ";
- }
- s << "(";
- {
- for (int i = m.start; i < m.len; i++) {
- unsigned char c = m.buff[i];
- if (c>=' ' && c <= 'z') s << c;
- }
- }
- s<< ")";
- return s;
+ {
+ for (int i = m.start; i < m.len; i++)
+ s << hex << setw(2) << setfill('0') << (int)m.buff[i] << " ";
+ }
+ s << "(";
+ {
+ for (int i = m.start; i < m.len; i++) {
+ unsigned char c = m.buff[i];
+ if (c>=' ' && c <= 'z') s << c;
+ }
+ }
+ s<< ")";
+ return s;
}
void bufferStore::discardFirstBytes(int n) {
- start += n;
- if (start > len) start = len;
+ start += n;
+ if (start > len) start = len;
}
void bufferStore::checkAllocd(long newLen) {
- if (newLen >= lenAllocd) {
- do {
- if (lenAllocd < MIN_LEN)
- lenAllocd = MIN_LEN;
- else
- lenAllocd *= 2;
- } while (newLen >= lenAllocd);
- unsigned char* newBuff = new unsigned char [lenAllocd];
- for (int i=start; i<len; i++) newBuff[i] = buff[i];
- delete [] buff;
- buff = newBuff;
- }
+ if (newLen >= lenAllocd) {
+ do {
+ lenAllocd = (lenAllocd < MIN_LEN)?MIN_LEN:(lenAllocd*2);
+ } while (newLen >= lenAllocd);
+ unsigned char* newBuff = new unsigned char [lenAllocd];
+ memcpy(&newBuff[start], &buff[start], len - start);
+ delete [] buff;
+ buff = newBuff;
+ }
}
void bufferStore::addByte(unsigned char cc) {
- checkAllocd(len + 1);
- buff[len++] = cc;
+ checkAllocd(len + 1);
+ buff[len++] = cc;
}
void bufferStore::addString(const char* s) {
- checkAllocd(len + strlen(s));
- for (int i=0; s[i]; i++) buff[len++] = s[i];
+ int l = strlen(s);
+ checkAllocd(len + l);
+ memcpy(&buff[len], s, l);
+ len += l;
}
void bufferStore::addStringT(const char* s) {
- addString(s);
- addByte(0);
+ addString(s);
+ addByte(0);
}
void bufferStore::addBuff(const bufferStore &s, long maxLen) {
- checkAllocd(len + s.getLen());
- for (unsigned long i=0; i < s.getLen() && (maxLen < 0 || i < (unsigned long)maxLen); i++) buff[len++] = s.getByte(i);
+ long l = s.getLen();
+ checkAllocd(len + l);
+ if ((maxLen >= 0) && (maxLen < l))
+ l = maxLen;
+ if (l > 0) {
+ memcpy(&buff[len], s.getString(0), l);
+ len += l;
+ }
}
void bufferStore::addWord(int a) {
- checkAllocd(len + 2);
- buff[len++] = a & 0xff;
- buff[len++] = (a>>8) & 0xff;
+ checkAllocd(len + 2);
+ buff[len++] = a & 0xff;
+ buff[len++] = (a>>8) & 0xff;
}
void bufferStore::addDWord(long a) {
- checkAllocd(len + 4);
- buff[len++] = a & 0xff;
- buff[len++] = (a>>8) & 0xff;
- buff[len++] = (a>>16) & 0xff;
- buff[len++] = (a>>24) & 0xff;
+ checkAllocd(len + 4);
+ buff[len++] = a & 0xff;
+ buff[len++] = (a>>8) & 0xff;
+ buff[len++] = (a>>16) & 0xff;
+ buff[len++] = (a>>24) & 0xff;
}
diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc
index c9ef495..1caa027 100644
--- a/lib/ppsocket.cc
+++ b/lib/ppsocket.cc
@@ -283,74 +283,64 @@ bool ppsocket::dataToGet() const {
}
int ppsocket::getBufferStore(bufferStore &a, bool wait) {
- /* Returns a 0 for for no message, 1 for message OK, and -1 for socket problem */
- if (!wait && !dataToGet()) return 0;
- a.init();
- bool hadEscape = false;
- do {
- char data;
- int j = readTimeout(&data, 1, 0);
- if (j == SOCKET_ERROR || j == 0) {
- return -1;
- }
- if (hadEscape) {
- a.addByte(data);
- hadEscape = false;
- }
- else {
- if (data == '\\')
- hadEscape = true;
- else if (data == '\0')
- break;
- else
- a.addByte(data);
- }
- } while (true);
+ /* Returns a 0 for for no message,
+ * 1 for message OK, and -1 for socket problem
+ */
+
+ long l;
+ long count = 0;
+ unsigned char *buff;
+ unsigned char *bp;
+ if (!wait && !dataToGet()) return 0;
+ a.init();
+
+ if (readTimeout((char *)&l, sizeof(l), 0) != sizeof(l))
+ return -1;
+ l = ntohl(l);
+ bp = buff = new unsigned char[l];
+ while (l > 0) {
+ int j = readTimeout((char *)bp, l, 0);
+ if (j == SOCKET_ERROR || j == 0) {
+ delete [] buff;
+ return -1;
+ }
+ count += j;
+ l -= j;
+ bp += j;
+ };
+ a.init(buff, count);
+ delete [] buff;
#ifdef SOCKET_DIAGNOSTICS
- cout << "ppsocket got " << a << endl;
+ cout << "ppsocket got " << a << endl;
#endif
- return (a.getLen() == 0) ? 0 : 1;
+ return (a.getLen() == 0) ? 0 : 1;
}
bool ppsocket::sendBufferStore(const bufferStore &a) {
#ifdef SOCKET_DIAGNOSTICS
- cout << "ppsocket sending " << a << endl;
+ cout << "ppsocket sending " << a << endl;
#endif
- bufferStore s;
- long l = a.getLen();
- for (long i = 0; i<l; i++) {
- unsigned char cc = a.getByte(i);
- if (cc == '\0' || cc == '\\') {
- s.addByte('\\');
- }
- s.addByte(cc);
- }
- s.addByte('\0');
-
- {
- int tosend, sent, retries, i;
-
- tosend = s.getLen();
- sent = retries = 0;
-
- while (tosend > 0)
- {
- i = writeTimeout(s.getString(sent), tosend, 0);
-
- if (i == SOCKET_ERROR || i == 0)
- return( false);
-
- sent += i;
- tosend -= i;
-
- if (++retries > 5)
- {
- m_LastError = 0;
- return(false);
- }
- }
- }
- return true;
+ long l = a.getLen();
+ long hl = htonl(l);
+ long sent = 0;
+ int retries = 0;
+ int i;
+
+ i = writeTimeout((char *)&hl, sizeof(hl), 0);
+ if (i != sizeof(hl))
+ return false;
+ while (l > 0) {
+ i = writeTimeout(a.getString(sent), l, 0);
+ if (i == SOCKET_ERROR || i == 0)
+ return(false);
+ sent += i;
+ l -= i;
+ if (++retries > 5) {
+ m_LastError = 0;
+ return(false);
+ }
+ }
+ return true;
}
int ppsocket::readEx(char* Data, int cTerm, int MaxLen)
diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc
new file mode 100644
index 0000000..b6105c5
--- /dev/null
+++ b/lib/rfsv32.cc
@@ -0,0 +1,889 @@
+//
+// PLP - An implementation of the PSION link protocol
+//
+// Copyright (C) 1999 Philip Proudman
+//
+// 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 "bool.h"
+#include "bool.h"
+#include "rfsv32.h"
+#include "bufferstore.h"
+#include "ppsocket.h"
+#include "../defaults.h"
+#include "bufferarray.h"
+
+rfsv32::rfsv32(ppsocket * _skt) : serNum(0)
+{
+ skt = _skt;
+ bufferStore a;
+ status = DISCONNECTED;
+ a.addStringT(getConnectName());
+ if (skt->sendBufferStore(a)) {
+ if (skt->getBufferStore(a) == 1) {
+ if (strcmp(a.getString(0), "Ok"))
+ cerr << "Not got ok over socket\n";
+ else
+ status = NONE;
+ }
+ }
+}
+
+rfsv32::~rfsv32()
+{
+ bufferStore a;
+ a.addStringT("Close");
+ if (status == NONE)
+ skt->sendBufferStore(a);
+ skt->closeSocket();
+}
+
+long rfsv32::
+getStatus()
+{
+ return status;
+}
+
+const char *rfsv32::
+getConnectName()
+{
+ return "SYS$RFSV.*";
+}
+
+void rfsv32::
+convertSlash(const char *name)
+{
+ for (char *p = (char *)name; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+}
+
+long rfsv32::
+fopen(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ a.addDWord(attr);
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(OPEN_FILE, a);
+
+ long res = getResponse(a);
+ if (!res && a.getLen() == 4) {
+ handle = a.getDWord(0);
+ return 0;
+ }
+ return res;
+}
+
+long rfsv32::
+mktemp(long *handle, char *tmpname)
+{
+ bufferStore a;
+ sendCommand(TEMP_FILE, a);
+ long res = getResponse(a);
+ if (res == 0) {
+ *handle = a.getDWord(0);
+ strcpy(tmpname, a.getString(6));
+ }
+ return res;
+}
+
+long rfsv32::
+fcreatefile(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ a.addDWord(attr);
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(CREATE_FILE, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 4)
+ handle = a.getDWord(0);
+ return res;
+}
+
+long rfsv32::
+freplacefile(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addDWord(attr);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(REPLACE_FILE, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 4)
+ handle = a.getDWord(0);
+ return res;
+}
+
+long rfsv32::
+fopendir(long attr, const char *name, long &handle)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addDWord(attr);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(OPEN_DIR, a);
+ long res = getResponse(a);
+ if (!res && a.getLen() == 4)
+ handle = a.getDWord(0);
+ return res;
+}
+
+long rfsv32::
+fclose(long handle)
+{
+ bufferStore a;
+ a.addDWord(handle);
+ sendCommand(CLOSE_HANDLE, a);
+ return getResponse(a);
+}
+
+/* Microseconds since 1.1.1980 00:00:00 */
+#define PSI_EPOCH_SECS8 0x0e8c52f4
+#define EPOCH_2H 7200
+#define EPOCH_DIFF_SECS (3652 * 24 * 60 * 60)
+
+unsigned long rfsv32::
+micro2time(unsigned long microHi, unsigned long microLo)
+{
+ unsigned long long micro = microHi;
+ unsigned long long pes = PSI_EPOCH_SECS8;
+ pes <<= 8;
+ micro <<= 32;
+ micro += microLo;
+ micro /= 1000000;
+ micro -= pes;
+ micro += EPOCH_DIFF_SECS;
+ micro -= EPOCH_2H;
+ return (long) micro;
+}
+
+void rfsv32::
+time2micro(unsigned long time, unsigned long &microHi, unsigned long &microLo)
+{
+ unsigned long long micro = (unsigned long long)time;
+ unsigned long long pes = PSI_EPOCH_SECS8;
+ pes <<= 8;
+ micro += pes;
+ micro -= EPOCH_DIFF_SECS;
+ micro += EPOCH_2H;
+ micro *= (unsigned long long)1000000;
+ microLo = (micro & (unsigned long long)0x0FFFFFFFF);
+ micro >>= 32;
+ microHi = (micro & (unsigned long long)0x0FFFFFFFF);
+}
+
+long rfsv32::
+dir(const char *name, bufferArray * files)
+{
+ long handle;
+ long res = fopendir(HIDDEN | SYSTEM | DIRECTORY, name, handle);
+ if (res != 0)
+ return res;
+
+ while (1) {
+ bufferStore a;
+ a.addDWord(handle);
+ sendCommand(READ_DIR, a);
+ res = getResponse(a);
+ if (res)
+ break;
+ while (a.getLen() > 16) {
+ long shortLen = a.getDWord(0);
+ long attributes = a.getDWord(4);
+ long size = a.getDWord(8);
+ unsigned long modLow = a.getDWord(12);
+ unsigned long modHi = a.getDWord(16);
+ // long uid1 = a.getDWord(20);
+ // long uid2 = a.getDWord(24);
+ // long uid3 = a.getDWord(28);
+ long longLen = a.getDWord(32);
+
+ long date = micro2time(modHi, modLow);
+
+ bufferStore s;
+ if (!files) {
+ char dateBuff[100];
+ struct tm *t;
+ t = localtime(&date);
+ strftime(dateBuff, 100, "%c", t);
+ cout << ((attributes & DIRECTORY) ? "d" : "-");
+ cout << ((attributes & READ_ONLY) ? "-" : "w");
+ cout << ((attributes & HIDDEN) ? "h" : "-");
+ cout << ((attributes & SYSTEM) ? "s" : "-");
+ cout << ((attributes & ARCHIVE) ? "a" : "-");
+ cout << ((attributes & VOLUME) ? "v" : "-");
+ cout << ((attributes & NORMAL) ? "n" : "-");
+ cout << ((attributes & TEMPORARY) ? "t" : "-");
+ cout << ((attributes & COMPRESSED) ? "c" : "-");
+ cout << " " << dec << setw(10) << setfill(' ') << size;
+ cout << " " << dateBuff;
+ } else {
+ s.addDWord(date);
+ s.addDWord(size);
+ s.addDWord(attributes);
+ }
+ int d = 36;
+ for (int i = 0; i < longLen; i++, d++)
+ s.addByte(a.getByte(d));
+ s.addByte(0);
+ while (d % 4)
+ d++;
+ if (!files)
+ cout << " " << s.getString() << endl;
+ else /* if ((attributes & DIRECTORY) == 0) */
+ files->pushBuffer(s);
+ d += shortLen;
+ while (d % 4)
+ d++;
+ a.discardFirstBytes(d);
+ }
+ }
+ if (res == EoF)
+ res = 0;
+ fclose(handle);
+ return res;
+}
+
+long rfsv32::
+fgetmtime(const char *name, long *mtime)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(MODIFIED, a);
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ *mtime = micro2time(a.getDWord(4), a.getDWord(0));
+ return 0;
+}
+
+long rfsv32::
+fsetmtime(const char *name, long mtime)
+{
+ bufferStore a;
+ unsigned long microLo, microHi;
+ time2micro(mtime, microHi, microLo);
+ convertSlash(name);
+ a.addDWord(microLo);
+ a.addDWord(microHi);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(SET_MODIFIED, a);
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ return 0;
+}
+
+long rfsv32::
+fgetattr(const char *name, long *attr)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(ATT, a);
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ *attr = a.getDWord(0);
+ return 0;
+}
+
+long rfsv32::
+fgeteattr(const char *name, long *attr, long *size, long *time)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(REMOTE_ENTRY, a);
+ long res = getResponse(a);
+ if (res != 0)
+ return res;
+ // long shortLen = a.getDWord(0);
+ *attr = a.getDWord(4);
+ *size = a.getDWord(8);
+ unsigned long modLow = a.getDWord(12);
+ unsigned long modHi = a.getDWord(16);
+ // long uid1 = a.getDWord(20);
+ // long uid2 = a.getDWord(24);
+ // long uid3 = a.getDWord(28);
+ // long longLen = a.getDWord(32);
+ *time = micro2time(modHi, modLow);
+ return 0;
+}
+
+long rfsv32::
+fsetattr(const char *name, long seta, long unseta)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addDWord(seta);
+ a.addDWord(unseta);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(SET_ATT, a);
+ return getResponse(a);
+}
+
+long rfsv32::
+dircount(const char *name, long *count)
+{
+ long handle;
+ convertSlash(name);
+ long res = fopendir(HIDDEN | SYSTEM | DIRECTORY, name, handle);
+ *count = 0;
+ if (res != 0)
+ return res;
+
+ while (1) {
+ bufferStore a;
+ a.addDWord(handle);
+ sendCommand(READ_DIR, a);
+ res = getResponse(a);
+ if (res)
+ break;
+ while (a.getLen() > 16) {
+ int d = 36 + a.getDWord(32);
+ while (d % 4)
+ d++;
+ d += a.getDWord(0);
+ while (d % 4)
+ d++;
+ a.discardFirstBytes(d);
+ (*count)++;
+ }
+ }
+ fclose(handle);
+ if (res == EoF)
+ res = 0;
+ return res;
+}
+
+long rfsv32::
+devlist(long *devbits)
+{
+ bufferStore a;
+ long res;
+
+ sendCommand(GET_DRIVE_LIST, a);
+ res = getResponse(a);
+ *devbits = 0;
+ if ((res == 0) && (a.getLen() == 26)) {
+ for (int i = 25; i >= 0; i--) {
+ *devbits <<= 1;
+ if (a.getByte(i) != 0)
+ *devbits |= 1;
+ }
+ }
+ return res;
+}
+
+char *rfsv32::
+devinfo(int devnum, long *vfree, long *vtotal, long *vattr,
+ long *vuniqueid)
+{
+ bufferStore a;
+ long res;
+
+ a.addDWord(devnum);
+ sendCommand(DRIVE_INFO, a);
+ res = getResponse(a);
+ if (res == 0) {
+ *vattr = a.getDWord(0);
+ *vuniqueid = a.getDWord(16);
+ *vtotal = a.getDWord(20);
+ *vfree = a.getDWord(28);
+ // vnamelen = a.getDWord(36);
+ a.addByte(0);
+ return (strdup(a.getString(40)));
+ }
+ return NULL;
+}
+
+bool rfsv32::
+sendCommand(enum commands cc, bufferStore & data)
+{
+ bufferStore a;
+ a.addWord(cc);
+ a.addWord(serNum);
+ if (serNum < 0xffff)
+ serNum++;
+ else
+ serNum = 0;
+ a.addBuff(data);
+ return skt->sendBufferStore(a);
+}
+
+long rfsv32::
+getResponse(bufferStore & data)
+{
+ if (skt->getBufferStore(data) == 1 &&
+ data.getWord(0) == 0x11) {
+ long ret = data.getDWord(4);
+ data.discardFirstBytes(8);
+ return ret;
+ } else
+ status = DISCONNECTED;
+ return (enum errs) GENERAL;
+}
+
+char * rfsv32::
+opErr(long status)
+{
+ enum errs e = (enum errs) status;
+ switch (e) {
+ case NONE:
+ return "";
+ case NOT_FOUND:
+ return "NOT_FOUND";
+ case GENERAL:
+ return "GENERAL";
+ break;
+ case CANCEL:
+ return "CANCEL";
+ break;
+ case NO_MEMORY:
+ return "NO_MEMORY";
+ break;
+ case NOT_SUPPORTED:
+ return "NOT_SUPPORTED";
+ break;
+ case ARGUMENT:
+ return "ARGUMENT";
+ break;
+ case TOTAL_LOSS_OF_PRECISION:
+ return "TOTAL_LOSS_OF_PRECISION";
+ break;
+ case BAD_HANDLE:
+ return "BAD_HANDLE";
+ break;
+ case OVERFLOW:
+ return "OVERFLOW";
+ break;
+ case UNDERFLOW:
+ return "UNDERFLOW";
+ break;
+ case ALREADY_EXISTS:
+ return "ALREADY_EXISTS";
+ break;
+ case PATH_NOT_FOUND:
+ return "PATH_NOT_FOUND";
+ break;
+ case DIED:
+ return "DIED";
+ break;
+ case IN_USE:
+ return "IN_USE";
+ break;
+ case SERVER_TERMINATED:
+ return "SERVER_TERMINATED";
+ break;
+ case SERVER_BUSY:
+ return "SERVER_BUSY";
+ break;
+ case COMPLETION:
+ return "COMPLETION";
+ break;
+ case NOT_READY:
+ return "NOT_READY";
+ break;
+ case UNKNOWN:
+ return "UNKNOWN";
+ break;
+ case CORRUPT:
+ return "CORRUPT";
+ break;
+ case ACCESS_DENIED:
+ return "ACCESS_DENIED";
+ break;
+ case LOCKED:
+ return "LOCKED";
+ break;
+ case WRITE:
+ return "WRITE";
+ break;
+ case DISMOUNTED:
+ return "DISMOUNTED";
+ break;
+ case EoF:
+ return "EOF";
+ break;
+ case DISK_FULL:
+ return "DISK_FULL";
+ break;
+ case BAD_DRIVER:
+ return "BAD_DRIVER";
+ break;
+ case BAD_NAME:
+ return "BAD_NAME";
+ break;
+ case COMMS_LINE_FAIL:
+ return "COMMS_LINE_FAIL";
+ break;
+ case COMMS_FRAME:
+ return "COMMS_FRAME";
+ break;
+ case COMMS_OVERRUN:
+ return "COMMS_OVERRUN";
+ break;
+ case COMMS_PARITY:
+ return "COMMS_PARITY";
+ break;
+ case PSI_TIMEOUT:
+ return "TIMEOUT";
+ break;
+ case COULD_NOT_CONNECT:
+ return "COULD_NOT_CONNECT";
+ break;
+ case COULD_NOT_DISCONNECT:
+ return "COULD_NOT_DISCONNECT";
+ break;
+ case DISCONNECTED:
+ return "DISCONNECTED";
+ break;
+ case BAD_LIBRARY_ENTRY_POINT:
+ return "BAD_LIBRARY_ENTRY_POINT";
+ break;
+ case BAD_DESCRIPTOR:
+ return "BAD_DESCRIPTOR";
+ break;
+ case ABORT:
+ return "ABORT";
+ break;
+ case TOO_BIG:
+ return "TOO_BIG";
+ break;
+ case DIVIDE_BY_ZERO:
+ return "DIVIDE_BY_ZERO";
+ break;
+ case BAD_POWER:
+ return "BAD_POWER";
+ break;
+ case DIR_FULL:
+ return "DIR_FULL";
+ break;
+ default:
+ return "Unknown error";
+ break;
+ }
+}
+
+long rfsv32::
+fread(long handle, char *buf, long len)
+{
+ long res;
+ long count = 0;
+
+ do {
+ bufferStore a;
+ a.addDWord(handle);
+ a.addDWord(((len-count) > 2000)?2000:(len-count));
+ sendCommand(READ_FILE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ res = a.getLen();
+ if (res > 0) {
+ memcpy(buf, a.getString(), res);
+ count += res;
+ buf += res;
+ }
+ } while ((count < len) && (res > 0));
+ return (res < 0)?res:count;
+}
+
+long rfsv32::
+fwrite(long handle, char *buf, long len)
+{
+ long res;
+ long total = 0;
+ long count;
+
+ do {
+ count = ((len - total) > 2000)?2000:(len - total);
+ bufferStore a;
+ bufferStore tmp((unsigned char *)buf, count);
+ a.addDWord(handle);
+ a.addBuff(tmp);
+ sendCommand(WRITE_FILE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ total += count;
+ buf += count;
+ } while ((total < len) && (count > 0));
+ return total;
+}
+
+long rfsv32::
+copyFromPsion(const char *from, const char *to)
+{
+ long handle;
+ long res;
+ long len;
+
+ if ((res = fopen(SHARE_READERS | BINARY, from, handle)) != 0)
+ return res;
+ ofstream op(to);
+ if (!op) {
+ fclose(handle);
+ return -1;
+ }
+ do {
+ char buf[2000];
+ if ((len = fread(handle, buf, sizeof(buf))) > 0)
+ op.write(buf, len);
+ } while (len > 0);
+
+ fclose(handle);
+ op.close();
+ return len;
+}
+
+long rfsv32::
+copyToPsion(const char *from, const char *to)
+{
+ long handle;
+ long res;
+
+ ifstream ip(from);
+ if (!ip)
+ return NOT_FOUND;
+ res = fcreatefile(BINARY | SHARE_EXCLUSIVE | READ_WRITE, to, handle);
+ if (res != 0) {
+ res = freplacefile(BINARY | SHARE_EXCLUSIVE | READ_WRITE, to, handle);
+ if (res != 0) {
+ opErr(res);
+ cerr << endl;
+ 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());
+ total += tmp.getLen();
+ if (tmp.getLen() == 0)
+ break;
+ bufferStore a;
+ a.addDWord(handle);
+ a.addBuff(tmp);
+ sendCommand(WRITE_FILE, a);
+ res = getResponse(a);
+ if (res) {
+ cerr << "Unknown response to fwrite - ";
+ opErr(res);
+ cerr << " " << a << endl;
+ fclose(handle);
+ return res;
+ }
+ }
+ fclose(handle);
+ ip.close();
+ delete[]buff;
+ return 0;
+}
+
+long rfsv32::
+fsetsize(long handle, long size)
+{
+ bufferStore a;
+ a.addDWord(handle);
+ a.addDWord(size);
+ sendCommand(SET_SIZE, a);
+ return getResponse(a);
+}
+
+/*
+ * Unix-like implementation off fseek with one
+ * exception: If seeking beyond eof, the gap
+ * contains garbage instead of zeroes.
+ */
+long rfsv32::
+fseek(long handle, long pos, long mode)
+{
+ bufferStore a;
+ long res;
+ long savpos = 0;
+ long realpos;
+ long calcpos = 0;
+
+/*
+ seek-parameter for psion:
+ dword position
+ dword handle
+ dword mode
+ 1 = from start
+ 2 = from current pos
+ 3 = from end
+ ??no more?? 4 = sense recpos
+ ??no more?? 5 = set recpos
+ ??no more?? 6 = text-rewind
+ */
+
+ if ((mode < PSEEK_SET) || (mode > PSEEK_END))
+ return ARGUMENT;
+
+ if ((mode == PSEEK_CUR) && (pos >= 0)) {
+ /* get and save current position */
+ a.addDWord(0);
+ a.addDWord(handle);
+ a.addDWord(PSEEK_CUR);
+ sendCommand(SEEK_FILE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ savpos = a.getDWord(0);
+ if (pos == 0)
+ return savpos;
+ a.init();
+ }
+ if ((mode == PSEEK_END) && (pos >= 0)) {
+ /* get and save end position */
+ a.addDWord(0);
+ a.addDWord(handle);
+ a.addDWord(PSEEK_END);
+ sendCommand(SEEK_FILE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ savpos = a.getDWord(0);
+ if (pos == 0)
+ return savpos;
+ /* Expand file */
+ a.init();
+ a.addDWord(handle);
+ a.addDWord(savpos + pos);
+ sendCommand(SET_SIZE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ pos = 0;
+ a.init();
+ }
+ /* Now the real seek */
+ a.addDWord(pos);
+ a.addDWord(handle);
+ a.addDWord(mode);
+ sendCommand(SEEK_FILE, a);
+ if ((res = getResponse(a)) != 0) {
+cout << "seekRES(" << handle << ")=" << res << endl;
+ return res;
+}
+ realpos = a.getDWord(0);
+cout << "seekPOS=" << realpos << endl;
+ switch (mode) {
+ case PSEEK_SET:
+ calcpos = pos;
+ break;
+ case PSEEK_CUR:
+ calcpos = savpos + pos;
+ break;
+ case PSEEK_END:
+ return realpos;
+ break;
+ }
+ if (calcpos > realpos) {
+ /* Beyond end of file */
+ a.init();
+ a.addDWord(handle);
+ a.addDWord(calcpos);
+ sendCommand(SET_SIZE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ a.addDWord(calcpos);
+ a.addDWord(handle);
+ a.addDWord(PSEEK_SET);
+ sendCommand(SEEK_FILE, a);
+ if ((res = getResponse(a)) != 0)
+ return res;
+ realpos = a.getDWord(0);
+ }
+ return realpos;
+}
+
+long rfsv32::
+mkdir(const char *name)
+{
+ bufferStore a;
+ convertSlash(name);
+ if (strlen(name) && (name[strlen(name) - 1] != '\\')) {
+ a.addWord(strlen(name) + 1);
+ a.addString(name);
+ a.addByte('\\');
+ } else {
+ a.addWord(strlen(name));
+ a.addString(name);
+ }
+ sendCommand(MK_DIR_ALL, a);
+ return getResponse(a);
+}
+
+long rfsv32::
+rmdir(const char *name)
+{
+ bufferStore a;
+ convertSlash(name);
+ if (strlen(name) && (name[strlen(name) - 1] != '\\')) {
+ a.addWord(strlen(name) + 1);
+ a.addString(name);
+ a.addByte('\\');
+ } else {
+ a.addWord(strlen(name));
+ a.addString(name);
+ }
+ sendCommand(RM_DIR, a);
+ return getResponse(a);
+}
+
+long rfsv32::
+rename(const char *oldname, const char *newname)
+{
+ bufferStore a;
+ convertSlash(oldname);
+ convertSlash(newname);
+ a.addWord(strlen(oldname));
+ a.addString(oldname);
+ a.addWord(strlen(newname));
+ a.addString(newname);
+ sendCommand(RENAME, a);
+ return getResponse(a);
+}
+
+long rfsv32::
+remove(const char *name)
+{
+ bufferStore a;
+ convertSlash(name);
+ a.addWord(strlen(name));
+ a.addString(name);
+ sendCommand(DELETE, a);
+ return getResponse(a);
+}
diff --git a/lib/rfsv32.h b/lib/rfsv32.h
new file mode 100644
index 0000000..083bd3d
--- /dev/null
+++ b/lib/rfsv32.h
@@ -0,0 +1,172 @@
+#ifndef _rfsv32_h_
+#define _rfsv32_h_
+
+class ppsocket;
+class bufferStore;
+class bufferArray;
+
+class rfsv32 {
+ public:
+ rfsv32(ppsocket * skt);
+ ~rfsv32();
+
+ 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 devlist(long *devbits);
+ char *devinfo(int devnum, long *vfree, long *vtotal, long *vattr, long *vuiqueid);
+ long getStatus();
+ char *opErr(long status);
+
+ enum seek_mode {
+ PSEEK_SET = 1,
+ PSEEK_CUR = 2,
+ PSEEK_END = 3
+ };
+
+ private:
+ enum commands {
+ CLOSE_HANDLE = 0x01,
+ OPEN_DIR = 0x10,
+ READ_DIR = 0x12,
+ GET_DRIVE_LIST = 0x13,
+ DRIVE_INFO = 0x14,
+ SET_VOLUME_LABEL = 0x15,
+ OPEN_FILE = 0x16,
+ TEMP_FILE = 0x17,
+ READ_FILE = 0x18,
+ WRITE_FILE = 0x19,
+ SEEK_FILE = 0x1a,
+ DELETE = 0x1b,
+ REMOTE_ENTRY = 0x1c,
+ FLUSH = 0x1d,
+ SET_SIZE = 0x1e,
+ RENAME = 0x1f,
+ MK_DIR_ALL = 0x20,
+ RM_DIR = 0x21,
+ SET_ATT = 0x22,
+ ATT = 0x23,
+ SET_MODIFIED = 0x24,
+ MODIFIED = 0x25,
+ SET_SESSION_PATH = 0x26,
+ SESSION_PATH = 0x27,
+ READ_WRITE_FILE = 0x28,
+ CREATE_FILE = 0x29,
+ REPLACE_FILE = 0x2a,
+ PATH_TEST = 0x2b,
+ LOCK = 0x2d,
+ UNLOCK = 0x2e,
+ OPEN_DIR_UID = 0x2f,
+ DRIVE_NAME = 0x30,
+ SET_DRIVE_NAME = 0x31,
+ REPLACE = 0x32
+ };
+
+ enum file_attrib {
+ READ_ONLY = 0x0001,
+ HIDDEN = 0x0002,
+ SYSTEM = 0x0004,
+ DIRECTORY = 0x0010,
+ ARCHIVE = 0x0020,
+ VOLUME = 0x0040,
+ NORMAL = 0x0080,
+ TEMPORARY = 0x0100,
+ COMPRESSED = 0x0800
+ };
+
+ enum open_mode {
+ SHARE_EXCLUSIVE = 0x0000,
+ SHARE_READERS = 0x0001,
+ SHARE_ANY = 0x0002,
+ BINARY = 0x0000,
+ TEXT = 0x0020,
+ READ_WRITE = 0x0200
+ };
+
+ enum errs {
+ NONE = 0,
+ NOT_FOUND = -1,
+ GENERAL = -2,
+ CANCEL = -3,
+ NO_MEMORY = -4,
+ NOT_SUPPORTED = -5,
+ ARGUMENT = -6,
+ TOTAL_LOSS_OF_PRECISION = -7,
+ BAD_HANDLE = -8,
+ OVERFLOW = -9,
+ UNDERFLOW = -10,
+ ALREADY_EXISTS = -11,
+ PATH_NOT_FOUND = -12,
+ DIED = -13,
+ IN_USE = -14,
+ SERVER_TERMINATED = -15,
+ SERVER_BUSY = -16,
+ COMPLETION = -17,
+ NOT_READY = -18,
+ UNKNOWN = -19,
+ CORRUPT = -20,
+ ACCESS_DENIED = -21,
+ LOCKED = -22,
+ WRITE = -23,
+ DISMOUNTED = -24,
+ EoF = -25,
+ DISK_FULL = -26,
+ BAD_DRIVER = -27,
+ BAD_NAME = -28,
+ COMMS_LINE_FAIL = -29,
+ COMMS_FRAME = -30,
+ COMMS_OVERRUN = -31,
+ COMMS_PARITY = -32,
+ PSI_TIMEOUT = -33,
+ COULD_NOT_CONNECT = -34,
+ COULD_NOT_DISCONNECT = -35,
+ DISCONNECTED = -36,
+ BAD_LIBRARY_ENTRY_POINT = -37,
+ BAD_DESCRIPTOR = -38,
+ ABORT = -39,
+ TOO_BIG = -40,
+ DIVIDE_BY_ZERO = -41,
+ BAD_POWER = -42,
+ DIR_FULL = -43
+ };
+
+ const char *getConnectName();
+
+ // Communication
+ bool sendCommand(enum commands c, bufferStore & data);
+ long getResponse(bufferStore & data);
+ void convertSlash(const char *name);
+
+ // time-conversion
+ unsigned long micro2time(unsigned long microHi, unsigned long microLo);
+ void time2micro(unsigned long mtime, unsigned long &microHi, unsigned long &microLo);
+
+ // Vars
+ ppsocket *skt;
+ int serNum;
+ long status;
+ int tDiff;
+};
+
+#endif