From 68d5fd192fee358ad195c32b47333f8f87ae13f2 Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Mon, 7 Aug 2000 23:42:40 +0000 Subject: General cleanup: - Corrected some operators of bufferArray - Added more constructors to PsiTime - Added one more fallback for Timezone calculation in PsiTime - Use PsiTime in rfsv - Moved some common methods from rfsv16/32 to rfsv - Added more kdoc comments. - Made interface more robust (added const whereever possible, changed pointer arguments to references) --- lib/bufferarray.cc | 23 ++-- lib/bufferarray.h | 31 ++++- lib/iowatch.cc | 68 +++++----- lib/iowatch.h | 58 +++++++-- lib/log.cc | 3 - lib/log.h | 4 +- lib/psitime.cc | 72 ++++++++++- lib/psitime.h | 68 ++++++++-- lib/rfsv.cc | 65 ++++++++++ lib/rfsv.h | 359 ++++++++++++++++++++++++++++++++++++++++++++--------- lib/rfsv16.cc | 298 +++++++++++++++++--------------------------- lib/rfsv16.h | 188 +++++++++++++--------------- lib/rfsv32.cc | 344 ++++++++++++++++++++------------------------------ lib/rfsv32.h | 66 +++++----- plpftp/ftp.cc | 134 ++++++++++---------- plpnfsd/main.cc | 67 +++++----- 16 files changed, 1090 insertions(+), 758 deletions(-) diff --git a/lib/bufferarray.cc b/lib/bufferarray.cc index 77a08c6..953ec8f 100644 --- a/lib/bufferarray.cc +++ b/lib/bufferarray.cc @@ -125,15 +125,24 @@ operator [](const unsigned long index) return buff[index]; } -bufferArray &bufferArray:: -operator +(const bufferStore &a) +bufferArray bufferArray:: +operator +(const bufferStore &s) { - append(a); - return *this; + bufferArray res = *this; + res += s; + return res; } -bufferArray &bufferArray:: +bufferArray bufferArray:: operator +(const bufferArray &a) +{ + bufferArray res = *this; + res += a; + return res; +} + +bufferArray &bufferArray:: +operator +=(const bufferArray &a) { lenAllocd += a.lenAllocd; bufferStore *nb = new bufferStore[lenAllocd]; @@ -148,8 +157,8 @@ operator +(const bufferArray &a) } bufferArray &bufferArray:: -operator +=(const bufferStore &a) +operator +=(const bufferStore &s) { - append(a); + append(s); return *this; } diff --git a/lib/bufferarray.h b/lib/bufferarray.h index 7389ab6..b43dcbd 100644 --- a/lib/bufferarray.h +++ b/lib/bufferarray.h @@ -48,19 +48,40 @@ public: bufferStore &operator [](const unsigned long index); /** - * Appends a bufferStore. + * Appends a bufferStore to a bufferArray. + * + * @param s The bufferStore to be appended. + * + * @returns A new bufferArray with bufferStore appended to. */ - bufferArray &operator +(const bufferStore &); + bufferArray operator +(const bufferStore &s); /** * Concatenates two bufferArrays. + * + * @param a The bufferArray to be appended. + * + * @returns A new bufferArray consisting with a appended. */ - bufferArray &operator +(const bufferArray &); + bufferArray operator +(const bufferArray &a); /** - * Appends a bufferStore. + * Appends a bufferStore to current instance. + * + * @param s The bufferStore to append. + * + * @returns A reference to the current instance with s appended. + */ + bufferArray &operator +=(const bufferStore &s); + + /** + * Appends a bufferArray to current instance. + * + * @param a The bufferArray to append. + * + * @returns A reference to the current instance with a appended. */ - bufferArray &operator +=(const bufferStore &b); + bufferArray &operator +=(const bufferArray &a); /** * Removes the first bufferStore. diff --git a/lib/iowatch.cc b/lib/iowatch.cc index 15e8ecf..df7be8e 100644 --- a/lib/iowatch.cc +++ b/lib/iowatch.cc @@ -30,48 +30,46 @@ #include "iowatch.h" IOWatch::IOWatch() { - num = 0; - io = new int [MAX_IO]; + num = 0; + io = new int [FD_SETSIZE]; } IOWatch::~IOWatch() { - delete [] io; + delete [] io; } -void IOWatch::addIO(int a) { - int pos; - for (pos = 0; pos < num && a < io[pos]; pos++); - for (int i = num; i > pos; i--) io[i] = io[i-1]; - io[pos] = a; - num++; +void IOWatch::addIO(const int fd) { + int pos; + for (pos = 0; pos < num && fd < io[pos]; pos++); + if (io[pos] == fd) + return; + for (int i = num; i > pos; i--) + io[i] = io[i-1]; + io[pos] = fd; + num++; } -void IOWatch::remIO(int a) { - int pos; - for (pos = 0; pos < num && a != io[pos]; pos++); - if (pos != num) { - num--; - for (int i = pos; i 0) { - fd_set iop; - FD_ZERO(&iop); - for (int i=0; i 0) { + fd_set iop; + FD_ZERO(&iop); + for (int i = 0; i < num; i++) + FD_SET(io[i], &iop); + struct timeval t; + t.tv_usec = usecs; + t.tv_sec = secs; + return (select(io[0]+1, &iop, NULL, NULL, &t) > 0); + } + sleep(secs); + usleep(usecs); + return false; } - - diff --git a/lib/iowatch.h b/lib/iowatch.h index 18c0d44..a578e05 100644 --- a/lib/iowatch.h +++ b/lib/iowatch.h @@ -3,19 +3,57 @@ #include "bool.h" +/** + * A simple wrapper for select() + * + * IOWatch is a simple wrapper for the select + * system call. In particular, it takes care + * of passing the maximum file descriptor + * argument (arg 1) of select() correctly. + * IOWatch handles select on read descriptors only. + */ class IOWatch { public: - IOWatch(); - ~IOWatch(); - - void addIO(int a); - void remIO(int a); - bool watch(long secs, long usecs); -private: + /** + * Creates a new instance. + */ + IOWatch(); + + /** + * Destroys an instance. + */ + ~IOWatch(); + + /** + * Adds a file descriptor to + * the set of descriptors. + * + * @param fd The file descriptor to add. + */ + void addIO(const int fd); + + /** + * Removes a file descriptor from the + * set of descriptors. + * + * @param fd The file descriptor to remove. + */ + void remIO(const int fd); - enum consts { MAX_IO = 20 }; - int *io; - int num; + /** + * Performs a select() call. + * + * @param secs Number of seconds to wait. + * @param usecs Number of microseconds to wait. + * + * @return true, if any of the descriptors is + * readable. + */ + bool watch(const long secs, const long usecs); + +private: + int num; + int *io; }; #endif diff --git a/lib/log.cc b/lib/log.cc index 79a6a35..2f7a795 100644 --- a/lib/log.cc +++ b/lib/log.cc @@ -1,6 +1,3 @@ -//#include -//#include - #include "log.h" logbuf::logbuf(int _level) { diff --git a/lib/log.h b/lib/log.h index 7a6528d..708631f 100644 --- a/lib/log.h +++ b/lib/log.h @@ -38,7 +38,7 @@ class logbuf : public streambuf { logbuf(int level); /** - * @internal Called by the associated + * Called by the associated * ostream to write a character. * Stores the character in a buffer * and calls syslog(level, buffer) @@ -56,7 +56,7 @@ class logbuf : public streambuf { /** * Current length of buffer. */ - int len; + unsigned int len; /** * The log level to use with syslog. diff --git a/lib/psitime.cc b/lib/psitime.cc index 95ba6da..11e16e0 100644 --- a/lib/psitime.cc +++ b/lib/psitime.cc @@ -2,6 +2,17 @@ #include "psitime.h" #include +PsiTime::PsiTime(void) { + ptzValid = false; + setUnixNow(); +} + +PsiTime::PsiTime(time_t time) { + ptzValid = false; + gettimeofday(NULL, &utz); + setUnixTime(time); +} + PsiTime::PsiTime(psi_timeval *_ptv, psi_timezone *_ptz) { if (_ptv != 0L) ptv = *_ptv; @@ -15,6 +26,23 @@ PsiTime::PsiTime(psi_timeval *_ptv, psi_timezone *_ptz) { psi2unix(); } +PsiTime::PsiTime(const unsigned long _ptvHi, const unsigned long _ptvLo) { + ptv.tv_high = _ptvHi; + ptv.tv_low = _ptvLo; + ptzValid = false; + /* get our own timezone */ + gettimeofday(NULL, &utz); + psi2unix(); +} + +PsiTime::PsiTime(struct timeval *_utv = 0L, struct timezone *_utz = 0L) { + if (_utv != 0L) + utv = *_utv; + if (_utz != 0L) + utz = *_utz; + unix2psi(); +} + PsiTime::~PsiTime() { } @@ -24,6 +52,12 @@ void PsiTime::setUnixTime(struct timeval *_utv) { unix2psi(); } +void PsiTime::setUnixTime(time_t time) { + utv.tv_sec = time; + utv.tv_usec = 0; + unix2psi(); +} + void PsiTime::setUnixNow(void) { gettimeofday(&utv, &utz); unix2psi(); @@ -36,6 +70,12 @@ void PsiTime::setPsiTime(psi_timeval *_ptv) { psi2unix(); } +void PsiTime::setPsiTime(const unsigned long _ptvHi, const unsigned long _ptvLo) { + ptv.tv_high = _ptvHi; + ptv.tv_low = _ptvLo; + psi2unix(); +} + void PsiTime::setPsiZone(psi_timezone *_ptz) { if (_ptz != 0L) { ptz = *_ptz; @@ -56,6 +96,14 @@ psi_timeval &PsiTime::getPsiTimeval(void) { return ptv; } +const unsigned long PsiTime::getPsiTimeLo(void) { + return ptv.tv_low; +} + +const unsigned long PsiTime::getPsiTimeHi(void) { + return ptv.tv_high; +} + ostream &operator<<(ostream &s, const PsiTime &t) { const char *fmt = "%c"; char buf[100]; @@ -73,7 +121,7 @@ ostream &operator<<(ostream &s, const PsiTime &t) { #define EPOCH_DIFF 0x00dcddb30f2f8000ULL static unsigned long long -evalOffset(psi_timezone ptz, bool valid) { +evalOffset(psi_timezone ptz, time_t time, bool valid) { unsigned long long offset = 0; if (valid) { @@ -81,12 +129,28 @@ evalOffset(psi_timezone ptz, bool valid) { if ((ptz.dst_zones & 0x40000000) || (ptz.dst_zones & ptz.home_zone)) offset += 3600; } else { + /** + * Fallback. If no Psion zone given, use + * environment variable PSI_TZ + */ const char *offstr = getenv("PSI_TZ"); if (offstr != 0L) { char *err = 0L; offset = strtoul(offstr, &err, 0); - if (err != 0L) + if (err != 0L && *err != '\0') offset = 0; + } else { + /** + * Fallback. If PSI_TZ is not set, + * use the local timezone. This assumes, + * that both Psion and local machine are + * configured for the same timezone and + * daylight saving. + */ + struct tm *tm = localtime(&time); + offset = timezone; + if (tm->tm_isdst) + offset += 3600; } } offset *= 1000000; @@ -98,8 +162,8 @@ void PsiTime::psi2unix(void) { micro = (micro << 32) | ptv.tv_low; /* Substract Psion's idea of UTC offset */ - micro -= evalOffset(ptz, ptzValid); micro -= EPOCH_DIFF; + micro -= evalOffset(ptz, micro / 1000000, ptzValid); utv.tv_sec = micro / 1000000; utv.tv_usec = micro % 1000000; @@ -109,8 +173,8 @@ void PsiTime::unix2psi(void) { unsigned long long micro = utv.tv_sec * 1000000 + utv.tv_usec; /* Add Psion's idea of UTC offset */ + micro += evalOffset(ptz, utv.tv_sec, ptzValid); micro += EPOCH_DIFF; - micro += evalOffset(ptz, ptzValid); ptv.tv_low = micro & 0x0ffffffff; ptv.tv_high = (micro >> 32) & 0x0ffffffff; diff --git a/lib/psitime.h b/lib/psitime.h index 6946fc1..9755473 100644 --- a/lib/psitime.h +++ b/lib/psitime.h @@ -89,25 +89,48 @@ typedef struct psi_timezone_t { * not set, a fallback using the environment * variable PSI_TZ is provided. Users should * set this variable to the offset of their time zone - * in seconds. + * in seconds. If PSI_TZ is net set, a second + * fallback uses the local machine's setup, which assumes + * that both Psion and local machine have the same + * time zone and daylight settings. */ class PsiTime { public: + /** + * Contructs a new instance. + * + * @param _utv A Unix time value for initialization. + * @param _utz A Unix timezone for initialization. + */ + PsiTime(struct timeval *_utv, struct timezone *_utz = 0L); + + /** + * Contructs a new instance. + * + * @param time A Unix time value for initialization. + */ + PsiTime(time_t time); + /** * Contructs a new instance. * * @param _ptv A Psion time value for initialization. * @param _ptz A Psion timezone for initialization. */ - PsiTime(psi_timeval *_ptv = 0L, psi_timezone *_ptz = 0L); + PsiTime(psi_timeval *_ptv, psi_timezone *_ptz = 0L); /** - * Constructs a new instance. - * - * @param _utv A Unix time value for initialization. - * @param _utz A Unix timezone for initialization. + * Contructs a new instance. + * + * @param _ptvHi The high 16 bits of a Psion time value for initialization. + * @param _ptvLo The low 16 bits of a Psion time value for initialization. */ - PsiTime(struct timeval *_utv = 0L, struct timezone *_utz = 0L); + PsiTime(const unsigned long _ptvHi, const unsigned long _ptvLo); + + /** + * Constructs a new instance, initializing to now. + */ + PsiTime(void); /** * Destroys the instance. @@ -121,6 +144,14 @@ public: */ void setPsiTime(psi_timeval *_ptv); + /** + * Modifies the value of this instance. + * + * @param _ptvHi The high 32 bits of a Psion time. + * @param _ptvLo The low 32 bits of a Psion time. + */ + void setPsiTime(const unsigned long _ptvHi, const unsigned long _ptvLo); + /** * Sets the Psion time zone of this instance. * @@ -135,6 +166,13 @@ public: */ void setUnixTime(struct timeval *_utv); + /** + * Sets the value of this instance. + * + * @param _utv The new Unix time representation. + */ + void setUnixTime(time_t time); + /** * Sets the value of this instance to the * current time of the Unix machine. @@ -165,6 +203,22 @@ public: */ psi_timeval &getPsiTimeval(void); + /** + * Retrieves the instance's current value + * in Psion time format, high 32 bits. + * + * @returns The instance's current time as lower 32 bits of a Psion struct psi_timeval_t. + */ + const unsigned long getPsiTimeLo(void); + + /** + * Retrieves the instance's current value + * in Psion time format, low 32 bits. + * + * @returns The instance's current time as upper 32 bits of a Psion struct psi_timeval_t. + */ + const unsigned long getPsiTimeHi(void); + /** * Prints the instance's value in human readable format. * This function uses the current locale setting for diff --git a/lib/rfsv.cc b/lib/rfsv.cc index 0b7fd42..cd13cb3 100644 --- a/lib/rfsv.cc +++ b/lib/rfsv.cc @@ -1,4 +1,6 @@ #include "rfsv.h" +#include "ppsocket.h" +#include "bufferstore.h" #include "Enum.h" ENUM_DEFINITION(rfsv::errs, rfsv::E_PSI_GEN_NONE) { @@ -78,3 +80,66 @@ ENUM_DEFINITION(rfsv::errs, rfsv::E_PSI_GEN_NONE) { stringRep.add(rfsv::E_PSI_INTERNAL, "libplp internal error"); } +const char *rfsv::getConnectName(void) { + return "SYS$RFSV"; +} + +rfsv::~rfsv() { + bufferStore a; + a.addStringT("Close"); + if (status == E_PSI_GEN_NONE) + skt->sendBufferStore(a); + skt->closeSocket(); +} + +void rfsv::reconnect(void) +{ + skt->closeSocket(); + skt->reconnect(); + serNum = 0; + reset(); +} + +void rfsv::reset(void) { + 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; + } + } +} + +Enum rfsv::getStatus(void) { + return status; +} + +// beware this returns static data +const char * const rfsv:: +attr2String(const long attr) +{ + static char buf[11]; + buf[0] = ((attr & PSI_A_DIR) ? 'd' : '-'); + buf[1] = ((attr & PSI_A_READ) ? 'r' : '-'); + buf[2] = ((attr & PSI_A_RDONLY) ? '-' : 'w'); + buf[3] = ((attr & PSI_A_HIDDEN) ? 'h' : '-'); + buf[4] = ((attr & PSI_A_SYSTEM) ? 's' : '-'); + buf[5] = ((attr & PSI_A_ARCHIVE) ? 'a' : '-'); + buf[6] = ((attr & PSI_A_VOLUME) ? 'v' : '-'); + + // EPOC + buf[7] = ((attr & PSI_A_NORMAL) ? 'n' : '-'); + buf[8] = ((attr & PSI_A_TEMP) ? 't' : '-'); + buf[9] = ((attr & PSI_A_COMPRESSED) ? 'c' : '-'); + + // SIBO + buf[7] = ((attr & PSI_A_EXEC) ? 'x' : buf[7]); + buf[8] = ((attr & PSI_A_STREAM) ? 'b' : buf[8]); + buf[9] = ((attr & PSI_A_TEXT) ? 't' : buf[9]); + + buf[10] = '\0'; + return (char *) (&buf); +} + diff --git a/lib/rfsv.h b/lib/rfsv.h index 6cfa254..a1241d6 100644 --- a/lib/rfsv.h +++ b/lib/rfsv.h @@ -2,6 +2,7 @@ #define _rfsv_h_ #include "Enum.h" +#include "psitime.h" class ppsocket; class bufferStore; @@ -15,8 +16,6 @@ const long RFSV_SENDLEN = 2000; */ typedef int (*cpCallback_t)(long); -// Abstract base class of RFSV ; 16-bit and 32-bit variants implement this -// interface /** * Access remote file services of a Psion. * @@ -148,66 +147,308 @@ class rfsv { * The known file attributes */ enum file_attribs { - /** - * Attributes, valid on both EPOC and SIBO. - */ - PSI_A_RDONLY = 0x0001, - PSI_A_HIDDEN = 0x0002, - PSI_A_SYSTEM = 0x0004, - PSI_A_DIR = 0x0008, - PSI_A_ARCHIVE = 0x0010, - PSI_A_VOLUME = 0x0020, - - /** - * Attributes, valid on EPOC only. - */ - PSI_A_NORMAL = 0x0040, - PSI_A_TEMP = 0x0080, + /** Attributes, valid on both EPOC and SIBO. */ + PSI_A_RDONLY = 0x0001, + PSI_A_HIDDEN = 0x0002, + PSI_A_SYSTEM = 0x0004, + PSI_A_DIR = 0x0008, + PSI_A_ARCHIVE = 0x0010, + PSI_A_VOLUME = 0x0020, + + /** Attributes, valid on EPOC only. */ + PSI_A_NORMAL = 0x0040, + PSI_A_TEMP = 0x0080, PSI_A_COMPRESSED = 0x0100, - /** - * Attributes, valid on SIBO only. - */ - PSI_A_READ = 0x0200, - PSI_A_EXEC = 0x0400, - PSI_A_STREAM = 0x0800, - PSI_A_TEXT = 0x1000 + /** Attributes, valid on SIBO only. */ + PSI_A_READ = 0x0200, + PSI_A_EXEC = 0x0400, + PSI_A_STREAM = 0x0800, + PSI_A_TEXT = 0x1000, }; - virtual ~rfsv() {} - virtual void reset() = 0; - virtual void reconnect() = 0; - virtual Enum getStatus() = 0; - virtual const char *getConnectName() = 0; - virtual Enum fopen(long, const char *, long &) = 0; - virtual Enum mktemp(long *, char *) = 0; - virtual Enum fcreatefile(long, const char *, long &) = 0; - virtual Enum freplacefile(long, const char *, long &) = 0; - virtual Enum fopendir(long, const char *, long &) = 0; - virtual Enum fclose(long) = 0; - virtual Enum dir(const char *, bufferArray *) = 0; - virtual Enum fgetmtime(const char *, long *) = 0; - virtual Enum fsetmtime(const char *, long) = 0; - virtual Enum fgetattr(const char *, long *) = 0; - virtual Enum fgeteattr(const char *, long *, long *, long *) =0; - virtual Enum fsetattr(const char *, long, long) = 0; - virtual Enum dircount(const char *, long *) = 0; - virtual Enum 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 Enum copyFromPsion(const char *, const char *, cpCallback_t) = 0; - virtual Enum copyToPsion(const char *, const char *, cpCallback_t) = 0; - virtual Enum fsetsize(long, long) = 0; - virtual long fseek(long, long, long) = 0; - virtual Enum mkdir(const char *) = 0; - virtual Enum rmdir(const char *) = 0; - virtual Enum rename(const char *, const char *) = 0; - virtual Enum remove(const char *) = 0; - - virtual long attr2std(long) = 0; - virtual long std2attr(long) = 0; + + virtual ~rfsv(); + void reset(); + void reconnect(); + + /** + * Retrieves the current connection status. + * + * @returns The status of the connection. + */ + Enum getStatus(); + + /** + * Opens a file. + * + */ + virtual Enum fopen(const long attr, const char * const name, long &handle) = 0; + + /** + * Creates a unique temporary file. + * The file is opened for reading and writing. + * + * @param handle The handle for usage with @ref fread, @ref frwrite, @ref fseek @ref fclose is returned here. + * @param name The name of the temporary file is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum mktemp(long &handle, char * const name) = 0; + + /** + * Creates a named file. + */ + virtual Enum fcreatefile(const long attr, const char * const name, long &handle) = 0; + + /** + * Creates an named file, overwriting an existing file. + */ + virtual Enum freplacefile(const long attr, const char * const name, long &handle) = 0; + + /** + * Close a file on the Psion whih was previously opened/created by using + * @ref fopen, @ref fcreatefile, @ref freplacefile or @ref mktemp. + * + * @param handle A valid file handle. + */ + virtual Enum fclose(const long handle) = 0; + + /** + * Reads a directory on the Psion. + * The returned array of @ref bufferArray contains one @ref bufferStore element + * for each directory entry. + * The layout of information data is as follows: + *
+		 * 	offset		size	value
+		 * 	0		4	Pointer to a PsiTime object, representing the file's modification.
+		 * 	4		4	Size in bytes.
+		 * 	8		4	Attributes.
+		 * 	12		?	Zero terminated file name.
+		 * 
+ * + * @param name The name of the directory + * @param ret Array of @ref bufferStore containing information for directory entries. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum dir(const char * const name, bufferArray &ret) = 0; + + /** + * Retrieves the modification time of a file on the Psion. + * + * @param name Name of the file. + * @param mtime Modification time is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fgetmtime(const char * const name, PsiTime &mtime) = 0; + + /** + * Sets the modification time of a file on the Psion. + * + * @param name Name of the file whose modification time should be set. + * @param mtime The desired modification time. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fsetmtime(const char * const name, const PsiTime mtime) = 0; + + /** + * Retrieves attributes of a file on the Psion. + * + * @param name Name of the file whose attributes ar to be retrieved. + * @param attr The file's attributes are returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fgetattr(const char * const name, long &attr) = 0; + + /** + * Retrieves attributes, size and modification time of a file on the Psion. + * + * @param name The name of the file. + * @param attr The file's attributes are returned here. + * @param size The file's size in bytes is returned here. + * @param time The file's modification time is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fgeteattr(const char * const name, long &attr, long &size, PsiTime &time) =0; + + /** + * @param name + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fsetattr(const char * const name, const long seta, const long unseta) = 0; + + /** + * Counts number of entries in a directory. + * + * @param name The directory whose entries are to be counted. + * @param count The number of entries is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum dircount(const char * const name, long &count) = 0; + virtual Enum devlist(long &devbits) = 0; + virtual Enum devinfo(const int dev, long &free, long &total, long &attr, long &uniqueid, char * const name) = 0; + + + /** + * Reads from a file on the Psion. + * + * @param handle Handle of the file to read from. + * @param buffer The area where to store the data read. + * @param len The number of bytes to read. + * @param count The number of bytes actually read is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fread(const long handle, unsigned char * const buffer, const long len, long &count) = 0; + + /** + * Write to a file on the Psion. + * + * @param handle Handle of the file to read from. + * @param buffer The area to be written. + * @param len The number of bytes to write. + * @param count The number of bytes actually written is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fwrite(const long handle, const unsigned char * const buffer, const long len, long &count) = 0; + + /** + * Copies a file from the Psion to the local machine. + * + * @param from Name of the file on the Psion to be copied. + * @param to Name of the destination file on the local machine. + * @param func Pointer to a function which gets called on every read. + * This function can be used to show some progress etc. May be set + * to NULL, where no callback is performed. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum copyFromPsion(const char *from, const char *to, cpCallback_t func) = 0; + + /** + * Copies a file from local machine to the Psion. + * + * @param from Name of the file on the local machine to be copied. + * @param to Name of the destination file on the Psion. + * @param func Pointer to a function which gets called on every read. + * This function can be used to show some progress etc. May be set + * to NULL, where no callback is performed. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum copyToPsion(const char * const from, const char * const to, cpCallback_t func) = 0; + + /** + * Resizes an open file on the Psion. + * If the new size is greater than the file's + * current size, the contents of the added + * data is undefined. If The new size is smaller, + * the file is truncated. + * + * @param handle Handle of the file to be resized. + * @param size New size for that file. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fsetsize(const long handle, const long size) = 0; + + /** + * Sets the current file position of a file on the Psion. + * + * @param handle The file handle. + * @param offset Position to be seeked to. + * @param mode The mode for seeking. + * @param resultpos The final file position after seeking is returned here. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum fseek(const long handle, const long offset, const long mode, long &resultpos) = 0; + + /** + * Creates a directory on the Psion. + * + * @param name Name of the directory to be created. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum mkdir(const char * const name) = 0; + + /** + * Removes a directory on the Psion. + * + * @param name Name of the directory to be removed. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum rmdir(const char * const name) = 0; + + /** + * Renames a file on the Psion. + * + * @param oldname Name of the file to be renamed. + * @param newname New Name for that file. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum rename(const char * const oldname, const char * const newname) = 0; + + /** + * Removes a file on the Psion. + * + * @param name Name of the file to be removed. + * + * @returns A Psion error code (One of enum @ref #errs ). + */ + virtual Enum remove(const char * const name) = 0; + + /** + * Converts a file attribute @ref rfsv::file_attribs to + * human readable format, usable for showing them in directory + * listings. The first 7 characters are common to all + * machine types: + *
+		 * 	Char Nr.	Value
+		 * 	0		'd' if a directory,			'-' otherwise.
+		 * 	1		'r' if file is readable,		'-' otherwise.
+		 * 	2		'w' if file is writeable,		'-' otherwise.
+		 * 	3		'h' if file is hidden,			'-' otherwise.
+		 * 	4		's' if file is a system file,		'-' otherwise.
+		 * 	5		'a' if file is modified (archive flag),	'-' otherwise.
+		 * 	6		'v' if file is a volume name,		'-' otherwise.
+		 * 
+ * The rest (3 characters) are machine specific: + *
+		 * 	Char Nr.	EPOC Value		SIBO Value
+		 * 	7		'n' if normal,		'x' if executable,	'-' otherwise.
+		 * 	8		't' if temporary,	'b' if a stream,	'-' otherwise.
+		 * 	8		'c' if compressed,	't' if a textfile,	'-' otherwise.
+		 * 
+ * + * @param attr the generic file attribute. + * + * @returns Pointer to static textual representation of file attributes. + * + */ + const char * const attr2String(const long attr); + virtual long opMode(const long mode) = 0; +protected: + /** + * Retrieves the PLP protocol name. Mainly internal use. + * + * @returns The connection name always "SYS$RFSV" + */ + const char *getConnectName(); + + ppsocket *skt; + Enum status; + int serNum; }; #endif diff --git a/lib/rfsv16.cc b/lib/rfsv16.cc index bd30039..9cc34da 100644 --- a/lib/rfsv16.cc +++ b/lib/rfsv16.cc @@ -42,61 +42,14 @@ #define RFSV16_MAXDATALEN 852 // 640 -rfsv16::rfsv16(ppsocket *_skt) : serNum(0) +rfsv16::rfsv16(ppsocket *_skt) { - 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() -{ - skt->closeSocket(); - skt->reconnect(); serNum = 0; + status = rfsv::E_PSI_FILE_DISC; + skt = _skt; reset(); } -// move to base class? -void rfsv16:: -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; - } - } -} - -// move to base class? -Enum rfsv16:: -getStatus() -{ - return status; -} - -// move to base class? -const char *rfsv16:: -getConnectName() -{ - return "SYS$RFSV"; -} - Enum rfsv16:: convertName(const char* orig, char *retVal) { @@ -160,7 +113,7 @@ fopen(long attr, const char *name, long &handle) // internal Enum rfsv16:: -mktemp(long *handle, char *tmpname) +mktemp(long &handle, char * const tmpname) { bufferStore a; @@ -175,8 +128,9 @@ mktemp(long *handle, char *tmpname) Enum res = getResponse(a); if (res == E_PSI_GEN_NONE) { - *handle = a.getWord(0); - strcpy(tmpname, a.getString(2)); + handle = a.getWord(0); + if (tmpname) + strcpy(tmpname, a.getString(2)); return res; } return res; @@ -196,12 +150,10 @@ freplacefile(long attr, const char *name, long &handle) return fopen(attr | P_FREPLACE, name, handle); } -// internal Enum rfsv16:: -fopendir(long attr, const char *name, long &handle) +fopendir(const char * const name, long &handle) { -cerr << "rfsv16::fopendir ***" << endl; - return E_PSI_GEN_NONE; + return fopen(P_FDIR, name, handle); } Enum rfsv16:: @@ -215,10 +167,10 @@ fclose(long fileHandle) } Enum rfsv16:: -dir(const char *dirName, bufferArray * files) +dir(const char * const dirName, bufferArray &files) { long fileHandle; - Enum res = fopen(P_FDIR, dirName, fileHandle); + Enum res = fopendir(dirName, fileHandle); if (res != E_PSI_GEN_NONE) return res; @@ -239,7 +191,7 @@ dir(const char *dirName, bufferArray * files) fclose(fileHandle); return E_PSI_GEN_FAIL; } - int status = a.getWord(2); + long attr = attr2std((long)a.getWord(2)); long size = a.getDWord(4); long date = a.getDWord(8); const char *s = a.getString(16); @@ -248,9 +200,9 @@ dir(const char *dirName, bufferArray * files) bufferStore temp; temp.addDWord(date); temp.addDWord(size); - temp.addDWord((long)status); + temp.addDWord(attr); temp.addStringT(s); - files->append(temp); + files += temp; } } if (res == E_PSI_FILE_EOF) @@ -259,25 +211,6 @@ dir(const char *dirName, bufferArray * files) 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) { @@ -293,7 +226,7 @@ opMode(long mode) } Enum rfsv16:: -fgetmtime(const char *name, long *mtime) +fgetmtime(const char * const name, PsiTime &mtime) { cerr << "rfsv16::fgetmtime" << endl; // NB: fgetattr, fgeteattr is almost identical... @@ -313,7 +246,11 @@ cerr << "rfsv16::fgetmtime" << endl; return res; } else if (a.getLen() == 16) { - *mtime = a.getDWord(8); + // struct timeval tv; + // tv.tv_sec = a.getDWord(8); + // tv.tv_usec = 0; + // mtime.setUnixTime(&tv); + mtime.setUnixTime(a.getDWord(8)); return res; } cerr << "fgetmtime: Unknown response (" << name << ") " << a < rfsv16:: -fsetmtime(const char *name, long mtime) +fsetmtime(const char *name, PsiTime mtime) { cerr << "rfsv16::fsetmtime ***" << endl; // I don't think there's a protocol frame that allows us to set the @@ -330,7 +267,7 @@ cerr << "rfsv16::fsetmtime ***" << endl; } Enum rfsv16:: -fgetattr(const char *name, long *attr) +fgetattr(const char * const name, long &attr) { // NB: fgetmtime, fgeteattr are almost identical... bufferStore a; @@ -349,7 +286,7 @@ fgetattr(const char *name, long *attr) return res; } else if (a.getLen() == 16) { - *attr = (long)(a.getWord(2)); + attr = attr2std((long)a.getWord(2)); return res; } cerr << "fgetattr: Unknown response (" << name << ") " << a < rfsv16:: -fgeteattr(const char *name, long *attr, long *size, long *time) +fgeteattr(const char * const name, long &attr, long &size, PsiTime &time) { bufferStore a; char realName[200]; @@ -375,9 +312,10 @@ fgeteattr(const char *name, long *attr, long *size, long *time) return res; } else if (a.getLen() == 16) { - *attr = (long)(a.getWord(2)); - *size = a.getDWord(4); - *time = a.getDWord(8); + attr = a.getWord(2); + size = a.getDWord(4); + time.setUnixTime(a.getDWord(8)); + //time = a.getDWord(8); return res; } cerr << "fgeteattr: Unknown response (" << name << ") " << a < rfsv16:: -dircount(const char *name, long *count) +dircount(const char * const name, long &count) { long fileHandle; Enum res; - *count = 0; + count = 0; res = fopen(P_FDIR, name, fileHandle); if (res != E_PSI_GEN_NONE) @@ -443,7 +381,7 @@ dircount(const char *name, long *count) // long date = a.getDWord(8); const char *s = a.getString(16); a.discardFirstBytes(17+strlen(s)); - (*count)++; + count++; } } if (res == E_PSI_FILE_EOF) @@ -453,11 +391,11 @@ dircount(const char *name, long *count) } Enum rfsv16:: -devlist(long *devbits) +devlist(long &devbits) { Enum res; long fileHandle; - *devbits = 0; + 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 @@ -502,7 +440,7 @@ devlist(long *devbits) char drive = a.getByte(64); if (drive >= 'A' && drive <= 'Z') { int shift = (drive - 'A'); - (*devbits) |= (long) ( 1 << shift ); + devbits |= (long) ( 1 << shift ); } else { cerr << "devlist: non-alphabetic drive letter (" @@ -515,12 +453,11 @@ devlist(long *devbits) return res; } -char *rfsv16:: -devinfo(int devnum, long *vfree, long *vtotal, long *vattr, - long *vuniqueid) +Enum rfsv16:: +devinfo(const int devnum, long &free, long &size, long &attr, long &uniqueid, char * const name) { bufferStore a; - long res; + Enum res; // long fileHandle; // Again, this is taken from an exchange between PsiWin and a 3c. @@ -534,11 +471,10 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr, a.addByte(0x00); // No name 2 a.addByte(0x00); // No name 3 if (!sendCommand(PARSE, a)) - return NULL; - res = getResponse(a); - if (res) { + return E_PSI_FILE_DISC; + if ((res = getResponse(a)) != E_PSI_GEN_NONE) { // cerr << "devinfo PARSE res is " << dec << (signed short int) res << endl; - return NULL; + return res; } a.init(); @@ -547,26 +483,24 @@ devinfo(int devnum, long *vfree, long *vtotal, long *vattr, a.addByte('\\'); a.addByte(0x00); if (!sendCommand(STATUSDEVICE, a)) - return NULL; - res = getResponse(a); - if (res) { + return E_PSI_FILE_DISC; + if ((res = getResponse(a)) != E_PSI_GEN_NONE) { // cerr << "devinfo STATUSDEVICE res is " << dec << (signed short int) res << endl; - return NULL; + return res; } - int type = a.getWord(2); + attr = a.getWord(2); // int changeable = a.getWord(4); - long size = a.getDWord(6); - long free = a.getDWord(10); + size = a.getDWord(6); + 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); + uniqueid = 0; + if (name) { + name[0] = (char) (devnum + 'A'); + name[1] = '\0'; + } + return res; } bool rfsv16:: @@ -618,49 +552,49 @@ getResponse(bufferStore & data) return status; } -long rfsv16:: -fread(long handle, unsigned char *buf, long len) +Enum rfsv16:: +fread(const long handle, unsigned char * const buf, const long len, long &count) { - long res; - long count = 0; + Enum res; + unsigned char *p = buf; + count = 0; while (count < len) { - bufferStore a; + bufferStore a; // 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. + // just has data, 297 bytes (or less) of it. + // a.addWord(handle); a.addWord((len - count) > RFSV16_MAXDATALEN ? RFSV16_MAXDATALEN : (len - count)); - sendCommand(FREAD, a); - res = getResponse(a); - - // The rest of the code treats a 0 return from here - // as meaning EOF, so we'll arrange for that to happen. - if (res == E_PSI_FILE_EOF) - return count; - else if (res < 0) + if (!sendCommand(FREAD, a)) + return E_PSI_FILE_DISC; + if ((res = getResponse(a)) != E_PSI_GEN_NONE) { + if (res == E_PSI_FILE_EOF) + return E_PSI_GEN_NONE; return res; - - res = a.getLen(); - memcpy(buf, a.getString(), res); - count += res; - buf += res; } - return count; + long l = a.getLen(); + memcpy(buf, a.getString(), l); + count += l; + p += l; + } + return res; } -long rfsv16:: -fwrite(long handle, unsigned char *buf, long len) +Enum rfsv16:: +fwrite(const long handle, const unsigned char * const buf, const long len, long &count) { - long res; - long count = 0; + Enum res; + const unsigned char *p = buf; + count = 0; while (count < len) { bufferStore a; int nbytes; @@ -675,16 +609,16 @@ fwrite(long handle, unsigned char *buf, long len) ? RFSV16_MAXDATALEN : (len - count); a.addWord(handle); - a.addBytes(buf, nbytes); - sendCommand(FWRITE, a); - res = getResponse(a); - if (res != 0) + a.addBytes(p, nbytes); + if (!sendCommand(FWRITE, a)) + return E_PSI_FILE_DISC; + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; count += nbytes; - buf += nbytes; + p += nbytes; } - return count; + return res; } Enum rfsv16:: @@ -693,6 +627,7 @@ copyFromPsion(const char *from, const char *to, cpCallback_t cb) long handle; Enum res; long len; + long total; if ((res = fopen(P_FSHARE | P_FSTREAM, from, handle)) != E_PSI_GEN_NONE) return res; @@ -703,17 +638,14 @@ copyFromPsion(const char *from, const char *to, cpCallback_t cb) } do { unsigned char buf[RFSV_SENDLEN]; - if ((len = fread(handle, buf, sizeof(buf))) > 0) - op.write(buf, len); - else - res = (enum rfsv::errs)len; - if (cb) { - if (!cb(len)) { + if ((res = fread(handle, buf, sizeof(buf), len)) == E_PSI_GEN_NONE) { + if (len > 0) + op.write(buf, len); + total += len; + if (cb && !cb(total)) res = E_PSI_FILE_CANCEL; - break; - } } - } while (res > 0); + } while (len > 0 && (res == E_PSI_GEN_NONE)); fclose(handle); op.close(); @@ -727,6 +659,7 @@ copyToPsion(const char *from, const char *to, cpCallback_t cb) { long handle; long len = 0; + long total = 0; Enum res; ifstream ip(from); @@ -739,21 +672,18 @@ copyToPsion(const char *from, const char *to, cpCallback_t cb) return res; } unsigned char *buff = new unsigned char[RFSV_SENDLEN]; - while (res >= 0 && ip && !ip.eof()) { + while (res == E_PSI_GEN_NONE && ip && !ip.eof()) { ip.read(buff, RFSV_SENDLEN); - len = fwrite(handle, buff, ip.gcount()); - if (len <= 0) - res = (enum rfsv::errs)len; - if (cb) - if (!cb(len)) { + if ((res = fwrite(handle, buff, ip.gcount(), len)) == E_PSI_GEN_NONE) { + total += len; + if (cb && !cb(total)) res = E_PSI_FILE_CANCEL; - } + } } - delete[]buff; fclose(handle); ip.close(); - return E_PSI_GEN_NONE; + return res; } Enum rfsv16:: @@ -772,11 +702,11 @@ fsetsize(long handle, long size) * exception: If seeking beyond eof, the gap * contains garbage instead of zeroes. */ -long rfsv16:: -fseek(long handle, long pos, long mode) +Enum rfsv16:: +fseek(const long handle, const long pos, const long mode, long &resultpos) { bufferStore a; - long res; + Enum res; long savpos = 0; long realpos; long calcpos = 0; @@ -805,11 +735,13 @@ fseek(long handle, long pos, long mode) a.addWord(PSI_SEEK_CUR); if (!sendCommand(FSEEK, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; savpos = a.getDWord(0); - if (pos == 0) - return savpos; + if (pos == 0) { + resultpos = savpos; + return res; + } } if ((mode == PSI_SEEK_END) && (pos >= 0)) { /* get and save end position */ @@ -819,11 +751,13 @@ fseek(long handle, long pos, long mode) a.addWord(PSI_SEEK_END); if (!sendCommand(FSEEK, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; savpos = a.getDWord(0); - if (pos == 0) - return savpos; + if (pos == 0) { + resultpos = savpos; + return res; + } } /* Now the real seek */ a.addWord(handle); @@ -842,13 +776,14 @@ fseek(long handle, long pos, long mode) calcpos = savpos + pos; break; case PSI_SEEK_END: - return realpos; + resultpos = realpos; + return res; break; } if (calcpos > realpos) { /* Beyond end of file */ res = fsetsize(handle, calcpos); - if (res != 0) + if (res != E_PSI_GEN_NONE) return res; a.init(); a.addWord(handle); @@ -860,7 +795,8 @@ fseek(long handle, long pos, long mode) return res; realpos = a.getDWord(0); } - return realpos; + resultpos = realpos; + return res; } Enum rfsv16:: @@ -980,7 +916,7 @@ attr2std(long attr) * Translate standard attributes to SIBO attributes. */ long rfsv16:: -std2attr(long attr) +std2attr(const long attr) { long res = 0; diff --git a/lib/rfsv16.h b/lib/rfsv16.h index 08c87f5..73c4983 100644 --- a/lib/rfsv16.h +++ b/lib/rfsv16.h @@ -4,126 +4,104 @@ #include "rfsv.h" class rfsv16 : public rfsv { - public: +public: rfsv16(ppsocket *); - ~rfsv16(); - void reset(); // these 2 added - void reconnect(); - // these are the original publics - Enum dir(const char *, bufferArray *); - /*long read(const char* psionName, const char* localName); - long write(const char* localName, const char* psionName);*/ - Enum mkdir(const char *); + Enum fopen(const long, const char * const, long &); + Enum mktemp(long &, char * const); + Enum fcreatefile(const long, const char * const, long &); + Enum freplacefile(const long, const char * const, long &); + Enum fclose(const long); + Enum dir(const char * const, bufferArray &); + Enum fgetmtime(const char * const, PsiTime &); + Enum fsetmtime(const char * const, const PsiTime); + Enum fgetattr(const char * const, long &); + Enum fgeteattr(const char * const, long &, long &, PsiTime &); + Enum fsetattr(const char * const, const long seta, const long unseta); + Enum dircount(const char * const, long &); + Enum devlist(long &); + Enum devinfo(const int, long &, long &, long &, long &, char * const); + Enum fread(const long, unsigned char * const, const long, long &); + Enum fwrite(const long, const unsigned char * const, const long, long &); + Enum copyFromPsion(const char * const, const char * const, cpCallback_t); + Enum copyToPsion(const char * const, const char * const, cpCallback_t); + Enum fsetsize(const long, const long); + Enum fseek(const long, const long, const long, long &); + Enum mkdir(const char * const); + Enum rmdir(const char * const); + Enum rename(const char * const, const char * const); + Enum remove(const char * const); - // these are FS' promotions - Enum dircount(const char *, long *); - Enum copyFromPsion(const char *, const char *, cpCallback_t); - Enum copyToPsion(const char *, const char *, cpCallback_t); - Enum rmdir(const char *); - Enum remove(const char *); // MJG: was this del? FE: yes - Enum rename(const char *, const char *); - Enum mktemp(long *, char *); - Enum fgeteattr(const char *, long *, long *, long *); - Enum fgetattr(const char *, long *); - Enum fsetattr(const char *, long seta, long unseta); - Enum fgetmtime(const char *, long *); - Enum fsetmtime(const char *, long); - Enum fopendir(long, const char *, long &); - Enum fopen(long, const char *, long &); - Enum fcreatefile(long, const char *, long &); - Enum freplacefile(long, const char *, long &); - long fseek(long, long, long); - long fread(long, unsigned char *, long); - long fwrite(long, unsigned char *, long); - Enum fsetsize(long, long); - Enum fclose(long); - - Enum devlist(long *); - char *devinfo(int, long *, long *, long *, long *); - Enum getStatus(); - char *opAttr(long); - long opMode(long); - - long attr2std(long); - long std2attr(long); + long opMode(const 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 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 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? */ - }; + 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? */ + P_FAMASK = 0x0f3f /* All of the above */ + }; - const char *getConnectName(); - - // File handlers - //long fopen(fopen_attrib a, const char* file, int &handle); // returns status 0=OK - //long fclose(int fileHandle); // Miscellaneous Enum convertName(const char*, char *); + Enum fopendir(const char * const, long &); + long attr2std(const long); + long std2attr(const long); // Communication bool sendCommand(enum commands, bufferStore &); Enum getResponse(bufferStore &); - - // Vars - ppsocket *skt; - // MJG: not sure what these are yet - int serNum; - Enum 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 99c7f06..c654228 100644 --- a/lib/rfsv32.cc +++ b/lib/rfsv32.cc @@ -36,56 +36,14 @@ #include "ppsocket.h" #include "bufferarray.h" -rfsv32::rfsv32(ppsocket * _skt) : serNum(0), status(rfsv::E_PSI_FILE_DISC) +rfsv32::rfsv32(ppsocket * _skt) { skt = _skt; - reset(); -} - -rfsv32::~rfsv32() -{ - bufferStore a; - a.addStringT("Close"); - if (status == E_PSI_GEN_NONE) - skt->sendBufferStore(a); - skt->closeSocket(); -} - -void rfsv32:: -reconnect() -{ - skt->closeSocket(); - skt->reconnect(); serNum = 0; + status = rfsv::E_PSI_FILE_DISC; reset(); } -void rfsv32:: -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; - } - } -} - -Enum rfsv32:: -getStatus() -{ - return status; -} - -const char *rfsv32:: -getConnectName() -{ - return "SYS$RFSV"; -} - char *rfsv32:: convertSlash(const char *name) { @@ -116,14 +74,14 @@ fopen(long attr, const char *name, long &handle) } Enum rfsv32:: -mktemp(long *handle, char *tmpname) +mktemp(long &handle, char * const tmpname) { bufferStore a; if (!sendCommand(TEMP_FILE, a)) return E_PSI_FILE_DISC; Enum res = getResponse(a); if (res == E_PSI_GEN_NONE) { - *handle = a.getDWord(0); + handle = a.getDWord(0); strcpy(tmpname, a.getString(6)); } return res; @@ -147,7 +105,7 @@ fcreatefile(long attr, const char *name, long &handle) } Enum rfsv32:: -freplacefile(long attr, const char *name, long &handle) +freplacefile(const long attr, const char * const name, long &handle) { bufferStore a; char *n = convertSlash(name); @@ -164,7 +122,7 @@ freplacefile(long attr, const char *name, long &handle) } Enum rfsv32:: -fopendir(long attr, const char *name, long &handle) +fopendir(const long attr, const char * const name, long &handle) { bufferStore a; char *n = convertSlash(name); @@ -190,6 +148,7 @@ fclose(long handle) return getResponse(a); } +#if 0 /* Microseconds since 1.1.1980 00:00:00 */ #define PSI_EPOCH_SECS8 0x0e8c52f4 #define EPOCH_2H 7200 @@ -244,9 +203,10 @@ time2micro(unsigned long time, unsigned long µHi, unsigned long µLo) micro >>= 32; microHi = (micro & (unsigned long long)0x0FFFFFFFF); } +#endif Enum rfsv32:: -dir(const char *name, bufferArray * files) +dir(const char *name, bufferArray &files) { long handle; Enum res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle); @@ -263,19 +223,20 @@ dir(const char *name, bufferArray * files) break; while (a.getLen() > 16) { long shortLen = a.getDWord(0); - long attributes = a.getDWord(4); + long attributes = attr2std(a.getDWord(4)); long size = a.getDWord(8); - unsigned long modLow = a.getDWord(12); - unsigned long modHi = a.getDWord(16); + //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); + //long date = micro2time(modHi, modLow); + PsiTime *date = new PsiTime(a.getDWord(16), a.getDWord(12)); bufferStore s; - s.addDWord(date); + s.addDWord((unsigned long)date); s.addDWord(size); s.addDWord(attributes); int d = 36; @@ -284,7 +245,7 @@ dir(const char *name, bufferArray * files) s.addByte(0); while (d % 4) d++; - files->append(s); + files += s; d += shortLen; while (d % 4) d++; @@ -297,26 +258,8 @@ dir(const char *name, bufferArray * files) 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) +opMode(const long mode) { long ret = 0; @@ -327,7 +270,7 @@ opMode(long mode) } Enum rfsv32:: -fgetmtime(const char *name, long *mtime) +fgetmtime(const char * const name, PsiTime &mtime) { bufferStore a; char *n = convertSlash(name); @@ -339,19 +282,20 @@ fgetmtime(const char *name, long *mtime) Enum res = getResponse(a); if (res != E_PSI_GEN_NONE) return res; - *mtime = micro2time(a.getDWord(4), a.getDWord(0)); + //mtime = micro2time(a.getDWord(4), a.getDWord(0)); + mtime.setPsiTime(a.getDWord(4), a.getDWord(0)); return res; } Enum rfsv32:: -fsetmtime(const char *name, long mtime) +fsetmtime(const char * const name, PsiTime mtime) { bufferStore a; - unsigned long microLo, microHi; + //unsigned long microLo, microHi; char *n = convertSlash(name); - time2micro(mtime, microHi, microLo); - a.addDWord(microLo); - a.addDWord(microHi); + // time2micro(mtime, microHi, microLo); + a.addDWord(mtime.getPsiTimeLo()); + a.addDWord(mtime.getPsiTimeHi()); a.addWord(strlen(n)); a.addString(n); free(n); @@ -361,7 +305,7 @@ fsetmtime(const char *name, long mtime) } Enum rfsv32:: -fgetattr(const char *name, long *attr) +fgetattr(const char * const name, long &attr) { bufferStore a; char *n = convertSlash(name); @@ -373,12 +317,12 @@ fgetattr(const char *name, long *attr) Enum res = getResponse(a); if (res != E_PSI_GEN_NONE) return res; - *attr = a.getDWord(0); + attr = attr2std(a.getDWord(0)); return res; } Enum rfsv32:: -fgeteattr(const char *name, long *attr, long *size, long *time) +fgeteattr(const char * const name, long &attr, long &size, PsiTime &time) { bufferStore a; char *n = convertSlash(name); @@ -391,25 +335,26 @@ fgeteattr(const char *name, long *attr, long *size, long *time) if (res != E_PSI_GEN_NONE) 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); + attr = attr2std(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); + //time = micro2time(modHi, modLow); + time.setPsiTime(a.getDWord(16), a.getDWord(12)); return res; } Enum rfsv32:: -fsetattr(const char *name, long seta, long unseta) +fsetattr(const char * const name, const long seta, const long unseta) { bufferStore a; char *n = convertSlash(name); - a.addDWord(seta); - a.addDWord(unseta); + a.addDWord(std2attr(seta)); + a.addDWord(std2attr(unseta)); a.addWord(strlen(n)); a.addString(n); free(n); @@ -419,11 +364,11 @@ fsetattr(const char *name, long seta, long unseta) } Enum rfsv32:: -dircount(const char *name, long *count) +dircount(const char * const name, long &count) { long handle; Enum res = fopendir(EPOC_ATTR_HIDDEN | EPOC_ATTR_SYSTEM | EPOC_ATTR_DIRECTORY, name, handle); - *count = 0; + count = 0; if (res != E_PSI_GEN_NONE) return res; @@ -443,7 +388,7 @@ dircount(const char *name, long *count) while (d % 4) d++; a.discardFirstBytes(d); - (*count)++; + count++; } } fclose(handle); @@ -453,7 +398,7 @@ dircount(const char *name, long *count) } Enum rfsv32:: -devlist(long *devbits) +devlist(long &devbits) { bufferStore a; Enum res; @@ -461,38 +406,38 @@ devlist(long *devbits) if (!sendCommand(GET_DRIVE_LIST, a)) return E_PSI_FILE_DISC; res = getResponse(a); - *devbits = 0; + devbits = 0; if ((res == E_PSI_GEN_NONE) && (a.getLen() == 26)) { for (int i = 25; i >= 0; i--) { - *devbits <<= 1; + devbits <<= 1; if (a.getByte(i) != 0) - *devbits |= 1; + devbits |= 1; } } return res; } -char *rfsv32:: -devinfo(int devnum, long *vfree, long *vtotal, long *vattr, - long *vuniqueid) +Enum rfsv32:: +devinfo(const int dev, long &free, long &total, long &attr, long &uniqueid, char * const name) { bufferStore a; - long res; + Enum res; - a.addDWord(devnum); + a.addDWord(dev); if (!sendCommand(DRIVE_INFO, a)) - return NULL; + return E_PSI_FILE_DISC; res = getResponse(a); - if (res == 0) { - *vattr = a.getDWord(0); - *vuniqueid = a.getDWord(16); - *vtotal = a.getDWord(20); - *vfree = a.getDWord(28); + if (res == E_PSI_GEN_NONE) { + attr = a.getDWord(0); + uniqueid = a.getDWord(16); + total = a.getDWord(20); + free = a.getDWord(28); // vnamelen = a.getDWord(36); a.addByte(0); - return (strdup(a.getString(40))); + if (name) + strcpy(name, a.getString(40)); } - return NULL; + return res; } bool rfsv32:: @@ -535,51 +480,55 @@ getResponse(bufferStore & data) return status; } -long rfsv32:: -fread(long handle, unsigned char *buf, long len) +Enum rfsv32:: +fread(const long handle, unsigned char * const buf, const long len, long &count) { - long res; - long count = 0; + Enum res; + count = 0; + long l; + unsigned char *p = buf; do { bufferStore a; a.addDWord(handle); - a.addDWord(((len-count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len-count)); + a.addDWord(((len - count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len - count)); if (!sendCommand(READ_FILE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; - res = a.getLen(); - if (res > 0) { - memcpy(buf, a.getString(), res); - count += res; - buf += res; + if ((l = a.getLen()) > 0) { + memcpy(p, a.getString(), l); + count += l; + p += res; } - } while ((count < len) && (res > 0)); - return (res < 0)?res:count; + } while ((count < len) && (l > 0)); + return res; } -long rfsv32:: -fwrite(long handle, unsigned char *buf, long len) +Enum rfsv32:: +fwrite(const long handle, const unsigned char * const buf, const long len, long &count) { - long res; - long total = 0; - long count; + Enum res; + const unsigned char *p = buf; + long l; + count = 0; do { - 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 E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) - return res; - total += count; - buf += count; - } while ((total < len) && (count > 0)); - return total; + l = ((len - count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len - count); + if (l > 0) { + bufferStore a; + bufferStore tmp(p, l); + a.addDWord(handle); + a.addBuff(tmp); + if (!sendCommand(WRITE_FILE, a)) + return E_PSI_FILE_DISC; + if ((res = getResponse(a)) != E_PSI_GEN_NONE) + return res; + count += l; + p += l; + } + } while ((count < len) && (l > 0)); + return res; } Enum rfsv32:: @@ -588,6 +537,7 @@ copyFromPsion(const char *from, const char *to, cpCallback_t cb) long handle; Enum res; long len; + long total = 0; if ((res = fopen(EPOC_OMODE_SHARE_READERS | EPOC_OMODE_BINARY, from, handle)) != E_PSI_GEN_NONE) return res; @@ -598,15 +548,11 @@ copyFromPsion(const char *from, const char *to, cpCallback_t cb) } unsigned char *buff = new unsigned char[RFSV_SENDLEN]; do { - if ((len = fread(handle, buff, RFSV_SENDLEN)) > 0) + if ((res = fread(handle, buff, RFSV_SENDLEN, len)) == E_PSI_GEN_NONE) { op.write(buff, len); - else - res = (enum rfsv::errs)len; - if (cb) { - if (!cb(len)) { + total += len; + if (cb && !cb(total)) res = E_PSI_FILE_CANCEL; - break; - } } } while ((len > 0) && (res == E_PSI_GEN_NONE)); delete[]buff; @@ -631,42 +577,20 @@ copyToPsion(const char *from, const char *to, cpCallback_t cb) return res; } unsigned char *buff = new unsigned char[RFSV_SENDLEN]; - int total = 0; - while (ip && !ip.eof()) { + long total = 0; + while (ip && !ip.eof() && (res == E_PSI_GEN_NONE)) { + long len; 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(WRITE_FILE, a)) { - ip.close(); - delete[]buff; - return E_PSI_FILE_DISC; - } - res = getResponse(a); - if (res != E_PSI_GEN_NONE) { - fclose(handle); - ip.close(); - delete[]buff; - return res; - } - if (cb) { - if (!cb(len)) { - fclose(handle); - ip.close(); - delete[]buff; - return E_PSI_FILE_CANCEL; - } + if ((res = fwrite(handle, buff, ip.gcount(), len)) == E_PSI_GEN_NONE) { + total += len; + if (cb && !cb(total)) + res = E_PSI_FILE_CANCEL; } } fclose(handle); ip.close(); delete[]buff; - return E_PSI_GEN_NONE; + return res; } Enum rfsv32:: @@ -685,14 +609,15 @@ fsetsize(long handle, long size) * exception: If seeking beyond eof, the gap * contains garbage instead of zeroes. */ -long rfsv32:: -fseek(long handle, long pos, long mode) +Enum rfsv32:: +fseek(const long handle, const long pos, const long mode, long &resultpos) { bufferStore a; - long res; + Enum res; long savpos = 0; - long realpos; long calcpos = 0; + long mypos = pos; + long realpos; /* seek-parameter for psion: @@ -710,61 +635,66 @@ fseek(long handle, long pos, long mode) if ((mode < PSI_SEEK_SET) || (mode > PSI_SEEK_END)) return E_PSI_GEN_ARG; - if ((mode == PSI_SEEK_CUR) && (pos >= 0)) { + if ((mode == PSI_SEEK_CUR) && (mypos >= 0)) { /* get and save current position */ a.addDWord(0); a.addDWord(handle); a.addDWord(PSI_SEEK_CUR); if (!sendCommand(SEEK_FILE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; savpos = a.getDWord(0); - if (pos == 0) - return savpos; + if (mypos == 0) { + resultpos = savpos; + return res; + } a.init(); } - if ((mode == PSI_SEEK_END) && (pos >= 0)) { + if ((mode == PSI_SEEK_END) && (mypos >= 0)) { /* get and save end position */ a.addDWord(0); a.addDWord(handle); a.addDWord(PSI_SEEK_END); if (!sendCommand(SEEK_FILE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; savpos = a.getDWord(0); - if (pos == 0) - return savpos; + if (mypos == 0) { + resultpos = savpos; + return res; + } /* Expand file */ a.init(); a.addDWord(handle); - a.addDWord(savpos + pos); + a.addDWord(savpos + mypos); if (!sendCommand(SET_SIZE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; - pos = 0; + mypos = 0; a.init(); } /* Now the real seek */ - a.addDWord(pos); + a.addDWord(mypos); a.addDWord(handle); a.addDWord(mode); if (!sendCommand(SEEK_FILE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; realpos = a.getDWord(0); switch (mode) { case PSI_SEEK_SET: - calcpos = pos; + calcpos = mypos; break; case PSI_SEEK_CUR: - calcpos = savpos + pos; + calcpos = savpos + mypos; break; case PSI_SEEK_END: - return realpos; + resultpos = realpos; + return res; break; } if (calcpos > realpos) { @@ -774,18 +704,19 @@ fseek(long handle, long pos, long mode) a.addDWord(calcpos); if (!sendCommand(SET_SIZE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; a.addDWord(calcpos); a.addDWord(handle); a.addDWord(PSI_SEEK_SET); if (!sendCommand(SEEK_FILE, a)) return E_PSI_FILE_DISC; - if ((res = getResponse(a)) != 0) + if ((res = getResponse(a)) != E_PSI_GEN_NONE) return res; realpos = a.getDWord(0); } - return realpos; + resultpos = realpos; + return res; } Enum rfsv32:: @@ -918,7 +849,7 @@ err2psierr(long status) * Translate EPOC attributes to standard attributes. */ long rfsv32:: -attr2std(long attr) +attr2std(const long attr) { long res = 0; @@ -954,12 +885,11 @@ attr2std(long attr) * Translate standard attributes to EPOC attributes. */ long rfsv32:: -std2attr(long attr) +std2attr(const long attr) { long res = 0; - // Common attributes - if (!(attr & PSI_A_RDONLY)) + if (attr & PSI_A_RDONLY) res |= EPOC_ATTR_RONLY; if (attr & PSI_A_HIDDEN) res |= EPOC_ATTR_HIDDEN; diff --git a/lib/rfsv32.h b/lib/rfsv32.h index af59af6..b45f132 100644 --- a/lib/rfsv32.h +++ b/lib/rfsv32.h @@ -8,46 +8,39 @@ class bufferStore; class bufferArray; class rfsv32 : public rfsv { - public: + +public: rfsv32(ppsocket *); - ~rfsv32(); - void reset(); - void reconnect(); - Enum dir(const char *, bufferArray *); - Enum dircount(const char *, long *); + Enum dir(const char * const, bufferArray &); + Enum dircount(const char * const, long &); Enum copyFromPsion(const char *, const char *, cpCallback_t); Enum copyToPsion(const char *, const char *, cpCallback_t); Enum mkdir(const char *); Enum rmdir(const char *); Enum remove(const char *); Enum rename(const char *, const char *); - Enum mktemp(long *, char *); - Enum fgeteattr(const char *, long *, long *, long *); - Enum fgetattr(const char *, long *); - Enum fsetattr(const char *, long, long); - Enum fgetmtime(const char *, long *); - Enum fsetmtime(const char *, long); - Enum fopendir(long, const char *, long &); - Enum fopen(long, const char *, long &); - Enum fcreatefile(long, const char *, long &); - Enum freplacefile(long, const char *, long &); - long fseek(long, long, long); - long fread(long, unsigned char *, long); - long fwrite(long, unsigned char *, long); + Enum mktemp(long &, char * const); + Enum fgeteattr(const char * const, long &, long &, PsiTime &); + Enum fgetattr(const char * const, long &); + Enum fsetattr(const char * const, const long, const long); + Enum fgetmtime(const char * const, PsiTime &); + Enum fsetmtime(const char * const, PsiTime const); + Enum fopen(const long, const char * const, long &); + Enum fcreatefile(const long, const char * const, long &); + Enum freplacefile(const long, const char * const, long &); + Enum fseek(const long, const long, const long, long &); + Enum fread(const long, unsigned char * const, const long, long &); + Enum fwrite(const long, const unsigned char * const, const long, long &); Enum fsetsize(long, long); - Enum fclose(long); + Enum fclose(const long); - Enum devlist(long *); - char *devinfo(int, long *, long *, long *, long *); - Enum getStatus(); - char *opAttr(long); - long opMode(long); + Enum devlist(long &); + Enum devinfo(const int, long &, long &, long &, long &, char * const); - long attr2std(long); - long std2attr(long); + long opMode(const long); - private: +private: enum file_attrib { EPOC_ATTR_RONLY = 0x0001, @@ -58,7 +51,8 @@ class rfsv32 : public rfsv { EPOC_ATTR_VOLUME = 0x0040, EPOC_ATTR_NORMAL = 0x0080, EPOC_ATTR_TEMPORARY = 0x0100, - EPOC_ATTR_COMPRESSED = 0x0800 + EPOC_ATTR_COMPRESSED = 0x0800, + EPOC_ATTR_MASK = 0x09f7 /* All of the above */ }; enum open_mode { @@ -154,8 +148,11 @@ class rfsv32 : public rfsv { REPLACE = 0x32 }; - const char *getConnectName(); Enum err2psierr(long); + Enum fopendir(const long, const char *, long &); + long attr2std(const long); + long std2attr(const long); + // Communication bool sendCommand(enum commands, bufferStore &); @@ -163,13 +160,8 @@ class rfsv32 : public rfsv { char *convertSlash(const char *); // time-conversion - unsigned long micro2time(unsigned long, unsigned long); - void time2micro(unsigned long, unsigned long &, unsigned long &); - - // Vars - ppsocket *skt; - int serNum; - Enum status; + // unsigned long micro2time(unsigned long, unsigned long); + // void time2micro(unsigned long, unsigned long &, unsigned long &); }; #endif diff --git a/plpftp/ftp.cc b/plpftp/ftp.cc index 60ebfb4..c0dceb9 100644 --- a/plpftp/ftp.cc +++ b/plpftp/ftp.cc @@ -85,7 +85,7 @@ void ftp::usage() { cout << " gtime " << endl; cout << " test " << endl; cout << " gattr " << endl; - cout << " sattr [[-|+]rhsa] " << endl; + cout << " sattr [[-|+]rwhsa] " << endl; cout << " devs" << endl; cout << " dir|ls" << endl; cout << " dircnt" << endl; @@ -105,6 +105,10 @@ void ftp::usage() { cout << endl << "Known RPC commands:" << endl << endl; cout << " ps" << endl; cout << " kill " << endl; + cout << " run [args]" << endl; + cout << " killsave " << endl; + cout << " runrestore " << endl; + cout << " machinfo" << endl; } static int Wildmat(const char *s, char *p); @@ -211,7 +215,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if (!once) { bufferArray b; - if (!(res = r.getOwnerInfo(b))) { + if ((res = r.getOwnerInfo(b)) == rfsv::E_PSI_GEN_NONE) { Enum machType; r.getMachineType(machType); cout << "Connected to a " << machType << ", OwnerInfo:" << endl; @@ -228,10 +232,10 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) int i; strcpy(defDrive, "::"); - if (a.devlist(&devbits) == 0) { + if (a.devlist(devbits) == 0) { for (i = 0; i < 26; i++) { - if ((devbits & 1) && a.devinfo(i, &vfree, &vtotal, &vattr, &vuniqueid)) { + if ((devbits & 1) && a.devinfo(i, vfree, vtotal, vattr, vuniqueid, NULL) == rfsv::E_PSI_GEN_NONE) { defDrive[0] = 'A' + i; break; } @@ -282,31 +286,29 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) strcat(f1, argv[1]); strcpy(f2, psionDir); strcat(f2, argv[2]); - if ((res = a.rename(f1, f2)) != 0) + if ((res = a.rename(f1, f2)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } if (!strcmp(argv[0], "touch") && (argc == 2)) { strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.fsetmtime(f1, time(0))) != 0) + PsiTime pt; + if ((res = a.fsetmtime(f1, pt)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } if (!strcmp(argv[0], "test") && (argc == 2)) { - long attr, size, time; + long attr, size; + PsiTime time; strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.fgeteattr(f1, &attr, &size, &time)) != 0) + if ((res = a.fgeteattr(f1, attr, size, time)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; else { - // never used to do this - char dateBuff[100]; - strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&time)); - cout << a.opAttr(attr); + cout << a.attr2String(attr); cout << " " << dec << setw(10) << setfill(' ') << size; - cout << " " << dateBuff; - cout << " " << argv[1] << endl; + cout << " " << time << " " << argv[1] << endl; } continue; } @@ -314,28 +316,25 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) long attr; strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.fgetattr(f1, &attr)) != 0) + if ((res = a.fgetattr(f1, attr)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; else { cout << hex << setw(4) << setfill('0') << attr; - cout << " (" << a.opAttr(attr) << ")" << endl; + cout << " (" << a.attr2String(attr) << ")" << endl; } continue; } if (!strcmp(argv[0], "gtime") && (argc == 2)) { - long mtime; + PsiTime mtime; strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.fgetmtime(f1, &mtime)) != 0) + if ((res = a.fgetmtime(f1, mtime)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; - else { - char dateBuff[100]; - strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&mtime)); - cout << dateBuff << endl; - } + else + cout << mtime << endl; continue; } - if (!strcmp(argv[0], "sattr") && (argc == 2)) { + if (!strcmp(argv[0], "sattr") && (argc == 3)) { long attr[2]; int aidx = 0; char *p = argv[1]; @@ -353,31 +352,35 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) aidx = 1; break; case 'r': - attr[aidx] |= 0x01; - attr[1 - aidx] &= ~0x01; + attr[aidx] |= rfsv::PSI_A_READ; + attr[aidx] &= ~rfsv::PSI_A_READ; + break; + case 'w': + attr[1 - aidx] |= rfsv::PSI_A_RDONLY; + attr[aidx] &= ~rfsv::PSI_A_RDONLY; break; case 'h': - attr[aidx] |= 0x02; - attr[1 - aidx] &= ~0x02; + attr[aidx] |= rfsv::PSI_A_HIDDEN; + attr[1 - aidx] &= ~rfsv::PSI_A_HIDDEN; break; case 's': - attr[aidx] |= 0x04; - attr[1 - aidx] &= ~0x04; + attr[aidx] |= rfsv::PSI_A_SYSTEM; + attr[1 - aidx] &= ~rfsv::PSI_A_SYSTEM; break; case 'a': - attr[aidx] |= 0x20; - attr[1 - aidx] &= ~0x20; + attr[aidx] |= rfsv::PSI_A_ARCHIVE; + attr[1 - aidx] &= ~rfsv::PSI_A_ARCHIVE; break; } p++; } - if ((res = a.fsetattr(f1, attr[0], attr[1])) != 0) + if ((res = a.fsetattr(f1, attr[0], attr[1])) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } if (!strcmp(argv[0], "dircnt")) { long cnt; - if ((res = a.dircount(psionDir, &cnt)) != 0) + if ((res = a.dircount(psionDir, cnt)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; else cout << cnt << " Entries" << endl; @@ -385,22 +388,20 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if (!strcmp(argv[0], "devs")) { long devbits; - if ((res = a.devlist(&devbits)) == 0) { + if ((res = a.devlist(devbits)) == rfsv::E_PSI_GEN_NONE) { cout << "Drive Type Volname Total Free UniqueID" << endl; for (int i = 0; i < 26; i++) { - char *vname; + char vname[256]; long vtotal, vfree, vattr, vuniqueid; if ((devbits & 1) != 0) { - vname = a.devinfo(i, &vfree, &vtotal, &vattr, &vuniqueid); - if (vname != NULL) { + if (a.devinfo(i, vfree, vtotal, vattr, vuniqueid, vname) == rfsv::E_PSI_GEN_NONE) cout << (char) ('A' + i) << " " << hex << setw(4) << setfill('0') << vattr << " " << setw(12) << setfill(' ') << setiosflags(ios::left) << vname << resetiosflags(ios::left) << dec << setw(9) << - vtotal << setw(9) << vfree << setw(10) << vuniqueid << endl; - free(vname); - } + vtotal << setw(9) << vfree << " " << setw(8) << setfill('0') << hex << + vuniqueid << endl; } devbits >>= 1; } @@ -410,21 +411,18 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if (!strcmp(argv[0], "ls") || !strcmp(argv[0], "dir")) { bufferArray files; - if ((res = a.dir(psionDir, &files)) != 0) + if ((res = a.dir(psionDir, files)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; else while (!files.empty()) { bufferStore s; s = files.pop(); - long date = s.getDWord(0); + PsiTime *date = (PsiTime *)s.getDWord(0); long size = s.getDWord(4); long attr = s.getDWord(8); - char dateBuff[100]; - strftime(dateBuff, sizeof(dateBuff), datefmt, localtime(&date)); - cout << a.opAttr(attr); + cout << a.attr2String(attr); cout << " " << dec << setw(10) << setfill(' ') << size; - cout << " " << dateBuff; - cout << " " << s.getString(12) << endl; + cout << " " << *date << " " << s.getString(12) << endl; } continue; } @@ -470,7 +468,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if ((f1[strlen(f1) -1] != '/') && (f1[strlen(f1) -1] != '\\')) strcat(f1,"\\"); - if ((res = a.dircount(f1, &tmp)) == 0) { + if ((res = a.dircount(f1, tmp)) == rfsv::E_PSI_GEN_NONE) { for (char *p = f1; *p; p++) if (*p == '/') *p = '\\'; @@ -496,7 +494,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) else strcat(f2, argv[2]); gettimeofday(&stime, 0L); - if ((res = a.copyFromPsion(f1, f2, cab)) != 0) { + if ((res = a.copyFromPsion(f1, f2, cab)) != rfsv::E_PSI_GEN_NONE) { if (hash) cout << endl; continueRunning = 1; @@ -525,7 +523,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } else if ((!strcmp(argv[0], "mget")) && (argc == 2)) { char *pattern = argv[1]; bufferArray files; - if ((res = a.dir(psionDir, &files)) != 0) { + if ((res = a.dir(psionDir, files)) != rfsv::E_PSI_GEN_NONE) { cerr << "Error: " << res << endl; continue; } @@ -560,7 +558,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) for (char *p = f2; *p; p++) *p = tolower(*p); } - if ((res = a.copyFromPsion(f1, f2, cab)) != 0) { + if ((res = a.copyFromPsion(f1, f2, cab)) != rfsv::E_PSI_GEN_NONE) { if (hash) cout << endl; continueRunning = 1; @@ -588,7 +586,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) else strcat(f2, argv[2]); gettimeofday(&stime, 0L); - if ((res = a.copyToPsion(f1, f2, cab)) != 0) { + if ((res = a.copyToPsion(f1, f2, cab)) != rfsv::E_PSI_GEN_NONE) { if (hash) cout << endl; continueRunning = 1; @@ -649,7 +647,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) if (temp[0] == 'y') { strcpy(f2, psionDir); strcat(f2, de->d_name); - if ((res = a.copyToPsion(f1, f2, cab)) != 0) { + if ((res = a.copyToPsion(f1, f2, cab)) != rfsv::E_PSI_GEN_NONE) { if (hash) cout << endl; continueRunning = 1; @@ -672,21 +670,21 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) !strcmp(argv[0], "rm")) && (argc == 2)) { strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.remove(f1)) != 0) + if ((res = a.remove(f1)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } if (!strcmp(argv[0], "mkdir") && (argc == 2)) { strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.mkdir(f1)) != 0) + if ((res = a.mkdir(f1)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } if (!strcmp(argv[0], "rmdir") && (argc == 2)) { strcpy(f1, psionDir); strcat(f1, argv[1]); - if ((res = a.rmdir(f1)) != 0) + if ((res = a.rmdir(f1)) != rfsv::E_PSI_GEN_NONE) cerr << "Error: " << res << endl; continue; } @@ -710,6 +708,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) continue; } // RPCS commands +#ifdef EXPERIMENTAL if (!strcmp(argv[0], "x")) { r.configOpen(); continue; @@ -718,6 +717,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) r.configRead(); continue; } +#endif if (!strcmp(argv[0], "run") && (argc >= 2)) { char argbuf[1024]; char cmdbuf[1024]; @@ -740,7 +740,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if (!strcmp(argv[0], "machinfo")) { rpcs::machineInfo mi; - if ((res = r.getMachineInfo(mi))) { + if ((res = r.getMachineInfo(mi)) != rfsv::E_PSI_GEN_NONE) { cerr << "Error: " << res << endl; continue; } @@ -790,15 +790,22 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) } if (!strcmp(argv[0], "runrestore") && (argc == 2)) { ifstream ip(argv[1]); + char cmd[512]; + char arg[512]; if (!ip) { cerr << "Could not read processlist " << argv[1] << endl; continue; } + ip >> cmd; + if (strcmp(cmd, "#plpftp processlist")) { + ip.close(); + cerr << "Error: " << argv[1] << + " is not a process list saved with killsave" << endl; + continue; + } while (!ip.eof()) { - char cmd[256]; - char arg[256]; ip >> cmd >> arg; - if ((res = r.execProgram(cmd, arg))) { + if ((res = r.execProgram(cmd, arg)) != rfsv::E_PSI_GEN_NONE) { cerr << "Could not start " << cmd << " " << arg << endl; cerr << "Error: " << res << endl; } @@ -814,6 +821,7 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) continue; } r.queryDrive('C', tmp); + op << "#plpftp processlist" << endl; while (!tmp.empty()) { char pbuf[128]; bufferStore cmdargs; @@ -908,12 +916,12 @@ filename_generator(char *text, int state) if (!state) { - long res; + Enum res; len = strlen(text); if (comp_files) delete comp_files; comp_files = new bufferArray(); - if ((res = comp_a->dir(psionDir, comp_files)) != 0) { + if ((res = comp_a->dir(psionDir, *comp_files)) != rfsv::E_PSI_GEN_NONE) { cerr << "Error: " << res << endl; return NULL; } diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc index ef9abdd..04e4936 100644 --- a/plpnfsd/main.cc +++ b/plpnfsd/main.cc @@ -46,7 +46,7 @@ long rfsv_dir(const char *file, dentry **e) { if (!a) return -1; - ret = a->dir(&(*file), &entries); + ret = a->dir(file, entries); while (!entries.empty()) { bufferStore s; s = entries.pop(); @@ -54,9 +54,9 @@ long rfsv_dir(const char *file, dentry **e) { *e = (dentry *)malloc(sizeof(dentry)); if (!*e) return -1; - (*e)->time = s.getDWord(0); + (*e)->time = ((PsiTime *)s.getDWord(0))->getTime(); (*e)->size = s.getDWord(4); - (*e)->attr = a->attr2std(s.getDWord(8)); + (*e)->attr = s.getDWord(8); (*e)->name = strdup(s.getString(12)); (*e)->next = tmp; } @@ -66,7 +66,7 @@ long rfsv_dir(const char *file, dentry **e) { long rfsv_dircount(const char *file, long *count) { if (!a) return -1; - return a->dircount(&(*file), &(*count)); + return a->dircount(file, *count); } long rfsv_rmdir(const char *name) { @@ -142,6 +142,7 @@ static long rfsv_opencached(const char *name, long mode) { long rfsv_read(char *buf, long offset, long len, char *name) { long ret = 0; + long r_offset; if (!a) return -1; @@ -150,20 +151,22 @@ long rfsv_read(char *buf, long offset, long len, char *name) { if((ret = rfsv_opencached(name, rfsv::PSI_O_RDONLY))) return ret; } - if (a_offset != offset) - ret = a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET); - if (ret >= 0) { - a_offset = offset; - ret = a->fread(a_handle, (unsigned char *)buf, len); - if (ret <= 0) - return ret; - a_offset += ret; + if (a_offset != offset) { + if (a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE) + return -1; + if (offset != r_offset) + return -1; } + a_offset = offset; + if (a->fread(a_handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE) + return -1; + a_offset += ret; return ret; } long rfsv_write(char *buf, long offset, long len, char *name) { long ret = 0; + long r_offset; if (!a) return -1; @@ -174,15 +177,16 @@ long rfsv_write(char *buf, long offset, long len, char *name) { if ((ret = rfsv_opencached(name, rfsv::PSI_O_RDWR))) return ret; } - if (a_offset != offset) - ret = a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET); - if (ret >= 0) { - a_offset = offset; - ret = a->fwrite(a_handle, (unsigned char *)buf, len); - if (ret <= 0) - return ret; - a_offset += ret; + if (a_offset != offset) { + if (a->fseek(a_handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE) + return -1; + if (offset != r_offset) + return -1; } + a_offset = offset; + if (a->fwrite(a_handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE) + return -1; + a_offset += ret; return ret; } @@ -191,7 +195,7 @@ long rfsv_setmtime(const char *name, long time) { return -1; if (a_filename && !strcmp(a_filename, name)) rfsv_closecached(); - return a->fsetmtime(name, time); + return a->fsetmtime(name, PsiTime(time)); } long rfsv_setsize(const char *name, long size) { @@ -215,30 +219,27 @@ long rfsv_setattr(const char *name, long sattr, long dattr) { return -1; if (a_filename && !strcmp(name, a_filename)) rfsv_closecached(); - dattr = a->std2attr(dattr); - sattr = a->std2attr(sattr); return a->fsetattr(name, dattr, sattr); } long rfsv_getattr(const char *name, long *attr, long *size, long *time) { - long res, psiattr; + long res; + PsiTime pt; if (!a) return -1; - res = a->fgeteattr(&(*name), &psiattr, &(*size), &(*time)); - *attr = a->attr2std(psiattr); + res = a->fgeteattr(name, *attr, *size, pt); + *time = pt.getTime(); return res; } long rfsv_statdev(char letter) { long vfree, vtotal, vattr, vuniqueid; int devnum = letter - 'A'; - char *name; if (!a) return -1; - name = a->devinfo(devnum, &vfree, &vtotal, &vattr, &vuniqueid); - return (name == NULL); + return (a->devinfo(devnum, vfree, vtotal, vattr, vuniqueid, NULL) != rfsv::E_PSI_GEN_NONE); } long rfsv_rename(const char *oldname, const char *newname) { @@ -255,18 +256,18 @@ long rfsv_drivelist(int *cnt, device **dlist) { if (!a) return -1; - ret = a->devlist(&devbits); + ret = a->devlist(devbits); if (ret == 0) for (i = 0; i<26; i++) { - char *name; + char name[256]; long vtotal, vfree, vattr, vuniqueid; if ((devbits & 1) && - ((name = a->devinfo(i, &vfree, &vtotal, &vattr, &vuniqueid)))) { + ((a->devinfo(i, vfree, vtotal, vattr, vuniqueid, name) == rfsv::E_PSI_GEN_NONE))) { device *next = *dlist; *dlist = (device *)malloc(sizeof(device)); (*dlist)->next = next; - (*dlist)->name = name; + (*dlist)->name = strdup(name); (*dlist)->total = vtotal; (*dlist)->free = vfree; (*dlist)->letter = 'A' + i; -- cgit v1.2.3