From bd48f19dd8931c871c9b79371ff68cf87d2ccc11 Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Mon, 28 Jun 1999 23:51:15 +0000 Subject: Optimization for speed. --- lib/Makefile.am | 2 +- lib/bufferarray.cc | 72 +++-- lib/bufferarray.h | 22 +- lib/bufferstore.cc | 158 +++++----- lib/ppsocket.cc | 112 +++---- lib/rfsv32.cc | 889 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rfsv32.h | 172 +++++++++++ 7 files changed, 1245 insertions(+), 182 deletions(-) create mode 100644 lib/rfsv32.cc create mode 100644 lib/rfsv32.h (limited to 'lib') 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 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 MIN_LEN) ? a.getLen() : MIN_LEN; - buff = new unsigned char [lenAllocd]; - len = a.getLen(); - for (long i=0; i 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 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) 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= 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 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 +#include +#include +#include +#include +#include + +#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 µHi, unsigned long µLo) +{ + 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 µHi, unsigned long µLo); + + // Vars + ppsocket *skt; + int serNum; + long status; + int tDiff; +}; + +#endif -- cgit v1.2.3