aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2002-02-28 20:56:59 +0000
committerFritz Elfert <felfert@to.com>2002-02-28 20:56:59 +0000
commiteecba3b5fcb47a01e6e13ee1940def989f6dd22d (patch)
tree970f3113de0d2b9b0544c1420117e0cf9633abcd
parent12241e0ff5ea242891fc3a8c177e8f55e897f2a3 (diff)
downloadplptools-eecba3b5fcb47a01e6e13ee1940def989f6dd22d.tar.gz
plptools-eecba3b5fcb47a01e6e13ee1940def989f6dd22d.tar.bz2
plptools-eecba3b5fcb47a01e6e13ee1940def989f6dd22d.zip
- Added SIS stuff by Daniel Brahneborg
-rw-r--r--lib/Enum.h6
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/bufferstore.cc10
-rw-r--r--lib/rfsv32.cc5
-rw-r--r--lib/siscomponentrecord.cpp55
-rw-r--r--lib/siscomponentrecord.h38
-rw-r--r--lib/sisfile.cpp72
-rw-r--r--lib/sisfile.h53
-rw-r--r--lib/sisfileheader.cpp92
-rw-r--r--lib/sisfileheader.h63
-rw-r--r--lib/sisfilerecord.cpp89
-rw-r--r--lib/sisfilerecord.h64
-rw-r--r--lib/sislangrecord.cpp18
-rw-r--r--lib/sislangrecord.h23
-rw-r--r--lib/sisreqrecord.cpp43
-rw-r--r--lib/sisreqrecord.h30
-rw-r--r--lib/sistypes.cpp89
-rw-r--r--lib/sistypes.h32
-rw-r--r--sisinstall/.cvsignore5
-rw-r--r--sisinstall/Makefile.am11
-rw-r--r--sisinstall/psion.cpp84
-rw-r--r--sisinstall/psion.h37
-rw-r--r--sisinstall/sisinstaller.cpp203
-rw-r--r--sisinstall/sisinstaller.h30
-rw-r--r--sisinstall/sismain.cpp62
25 files changed, 1214 insertions, 8 deletions
diff --git a/lib/Enum.h b/lib/Enum.h
index e29b8c0..79c2f80 100644
--- a/lib/Enum.h
+++ b/lib/Enum.h
@@ -199,6 +199,12 @@ public:
return *this;
}
+ inline Enum& operator = (const Enum& rhs) {
+ if (&rhs != this)
+ value = rhs.value;
+ return *this;
+ }
+
/**
* returns the enumeration value hold with this
* enum.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 49c9e46..0451077 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -8,10 +8,14 @@ libplp_la_LDFLAGS = $(LIBDEBUG) -version-info $(LIBVERSION)
libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc \
rfsv16.cc rfsv32.cc rfsvfactory.cc log.cc rfsv.cc rpcs32.cc rpcs16.cc \
- rpcs.cc rpcsfactory.cc psitime.cc Enum.cc plpdirent.cc wprt.cc rclip.cc
+ rpcs.cc rpcsfactory.cc psitime.cc Enum.cc plpdirent.cc wprt.cc \
+ rclip.cc siscomponentrecord.cpp sisfile.cpp sisfileheader.cpp \
+ sisfilerecord.cpp sislangrecord.cpp sisreqrecord.cpp sistypes.cpp
pkginclude_HEADERS = bufferarray.h bufferstore.h iowatch.h ppsocket.h \
rfsv.h rfsv16.h rfsv32.h rfsvfactory.h log.h rpcs32.h rpcs16.h rpcs.h \
- rpcsfactory.h psitime.h Enum.h plpdirent.h wprt.h plpintl.h rclip.h
+ rpcsfactory.h psitime.h Enum.h plpdirent.h wprt.h plpintl.h rclip.h \
+ siscomponentrecord.h sisfile.h sisfileheader.h sisfilerecord.h \
+ sislangrecord.h sisreqrecord.h sistypes.h
maintainer-clean-local:
rm -f Makefile.in
diff --git a/lib/bufferstore.cc b/lib/bufferstore.cc
index 8d7ed45..183ae6c 100644
--- a/lib/bufferstore.cc
+++ b/lib/bufferstore.cc
@@ -55,10 +55,12 @@ bufferStore::bufferStore(const unsigned char *_buff, long _len) {
}
bufferStore &bufferStore::operator =(const bufferStore &a) {
- checkAllocd(a.getLen());
- len = a.getLen();
- memcpy(buff, a.getString(0), len);
- start = 0;
+ if (this != &a) {
+ checkAllocd(a.getLen());
+ len = a.getLen();
+ memcpy(buff, a.getString(0), len);
+ start = 0;
+ }
return *this;
}
diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc
index f1718d2..739844e 100644
--- a/lib/rfsv32.cc
+++ b/lib/rfsv32.cc
@@ -428,12 +428,12 @@ Enum<rfsv::errs> rfsv32::
fread(const u_int32_t handle, unsigned char * const buf, const u_int32_t len, u_int32_t &count)
{
Enum<rfsv::errs> res;
+ bufferStore a;
count = 0;
long l;
unsigned char *p = buf;
do {
- bufferStore a;
a.addDWord(handle);
a.addDWord(((len - count) > RFSV_SENDLEN)?RFSV_SENDLEN:(len - count));
if (!sendCommand(READ_FILE, a))
@@ -445,6 +445,7 @@ fread(const u_int32_t handle, unsigned char * const buf, const u_int32_t len, u_
count += l;
p += l;
}
+ a.init();
} while ((count < len) && (l > 0));
return res;
}
@@ -499,7 +500,7 @@ copyFromPsion(const char *from, const char *to, void *ptr, cpCallback_t cb)
res = E_PSI_FILE_CANCEL;
}
} while ((len > 0) && (res == E_PSI_GEN_NONE));
- delete[]buff;
+ delete [] buff;
fclose(handle);
op.close();
return res;
diff --git a/lib/siscomponentrecord.cpp b/lib/siscomponentrecord.cpp
new file mode 100644
index 0000000..b4b313a
--- /dev/null
+++ b/lib/siscomponentrecord.cpp
@@ -0,0 +1,55 @@
+
+#include "siscomponentrecord.h"
+#include "sisfile.h"
+
+#include <stdio.h>
+#include <string.h>
+
+SISComponentNameRecord::~SISComponentNameRecord()
+{
+ delete[] m_names;
+}
+
+void
+SISComponentNameRecord::fillFrom(uchar* buf, int base, SISFile* sisFile)
+{
+ int ix = base;
+
+ int n = sisFile->m_header.m_nlangs;
+ m_nameLengths = new uint32[n];
+ m_namePtrs = new uint32[n];
+ m_names = new uchar*[n];
+
+ // First read lengths.
+ //
+ for (int i = 0; i < n; ++i)
+ {
+ m_nameLengths[i] = read32(buf, &ix);
+ }
+
+ // Then read ptrs.
+ //
+ for (int i = 0; i < n; ++i)
+ {
+ m_namePtrs[i] = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Name %d (for %s) is %.*s\n",
+ i,
+ sisFile->getLanguage(i)->m_name,
+ m_nameLengths[i],
+ buf + m_namePtrs[i]);
+ int len = m_nameLengths[i];
+ m_names[i] = new uchar[len + 1];
+ memcpy(m_names[i], buf + m_namePtrs[i], len);
+ m_names[i][len] = 0;
+ }
+ if (logLevel >= 1)
+ printf("%d .. %d (%d bytes): Name records\n", base, ix, ix - base);
+}
+
+uchar*
+SISComponentNameRecord::getName(int no)
+{
+ return m_names[no];
+}
+
diff --git a/lib/siscomponentrecord.h b/lib/siscomponentrecord.h
new file mode 100644
index 0000000..995750d
--- /dev/null
+++ b/lib/siscomponentrecord.h
@@ -0,0 +1,38 @@
+#ifndef _SISCOMPONENTRECORD_H
+#define _SISCOMPONENTRECORD_H
+
+#include "sistypes.h"
+
+class SISFile;
+
+/**
+ * The name of the component in this SIS file.
+ * A single instance holds the names for all languages.
+ */
+class SISComponentNameRecord
+{
+public:
+
+ virtual ~SISComponentNameRecord();
+
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf, int base, SISFile* sisFile);
+
+ uchar* getName(int no);
+
+private:
+
+ uint32* m_nameLengths;
+ uint32* m_namePtrs;
+
+ /**
+ * The extracted names.
+ */
+ uchar** m_names;
+
+};
+
+#endif
+
diff --git a/lib/sisfile.cpp b/lib/sisfile.cpp
new file mode 100644
index 0000000..53b9c24
--- /dev/null
+++ b/lib/sisfile.cpp
@@ -0,0 +1,72 @@
+
+#include "sisfile.h"
+#include "sislangrecord.h"
+#include "sisfilerecord.h"
+#include "sisreqrecord.h"
+
+#include <stdio.h>
+
+void
+SISFile::fillFrom(uchar* buf)
+{
+ int ix = 0;
+ m_header.fillFrom(buf, &ix);
+ if (logLevel >= 2)
+ printf("Ate header, got ix = %d\n", ix);
+ int n;
+
+ // Read languages.
+ //
+ n = m_header.m_nlangs;
+ m_langRecords = new SISLangRecord[n];
+ ix = m_header.m_languagePtr;
+ for (int i = 0; i < n; ++i)
+ m_langRecords[i].fillFrom(buf, &ix);
+
+ // Read requisites.
+ //
+ n = m_header.m_nreqs;
+ m_reqRecords = new SISReqRecord[n];
+ ix = m_header.m_reqPtr;
+ for (int i = 0; i < n; ++i)
+ m_reqRecords[i].fillFrom(buf, &ix, this);
+
+ // Read component names, by language.
+ //
+ ix = m_header.m_componentPtr;
+ m_componentRecord.fillFrom(buf, ix, this);
+
+ // Read files.
+ //
+ n = m_header.m_nfiles;
+ m_fileRecords = new SISFileRecord[n];
+ ix = m_header.m_filesPtr;
+ for (int i = 0; i < n; ++i)
+ m_fileRecords[i].fillFrom(buf, &ix, this);
+
+}
+
+int
+SISFile::getLanguage()
+{
+ return m_header.m_installationLanguage;
+}
+
+LangTableEntry*
+SISFile::getLanguage(int i)
+{
+ return &langTable[m_langRecords[i].m_lang];
+}
+
+uchar*
+SISFile::getName()
+{
+ return m_componentRecord.getName(m_header.m_installationLanguage);
+}
+
+void
+SISFile::setLanguage(int lang)
+{
+ m_header.m_installationLanguage = lang;
+}
+
diff --git a/lib/sisfile.h b/lib/sisfile.h
new file mode 100644
index 0000000..5f0bcd5
--- /dev/null
+++ b/lib/sisfile.h
@@ -0,0 +1,53 @@
+#ifndef _SISFILE_H
+#define _SISFILE_H
+
+#include "sistypes.h"
+#include "sisfileheader.h"
+#include "siscomponentrecord.h"
+
+class SISLangRecord;
+class SISFileRecord;
+class SISReqRecord;
+
+/**
+ * The top level container of a SIS file.
+ * Based on documentation by Alexander Thoukydides <alex@thouky.co.uk>.
+ *
+ * @author Daniel Brahneborg, 2002
+ */
+class SISFile
+{
+public:
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf);
+
+ int getLanguage();
+
+ /**
+ * Find a language entry, based on the sequence number in the SISLangRecord
+ * part of the file.
+ */
+ LangTableEntry* getLanguage(int i);
+
+ /**
+ * Get the name of this component, in the selected language.
+ */
+ uchar* getName();
+
+ void setLanguage(int lang);
+
+ SISFileHeader m_header;
+ SISLangRecord* m_langRecords;
+ SISFileRecord* m_fileRecords;
+ SISReqRecord* m_reqRecords;
+
+private:
+
+ SISComponentNameRecord m_componentRecord;
+
+};
+
+#endif
+
diff --git a/lib/sisfileheader.cpp b/lib/sisfileheader.cpp
new file mode 100644
index 0000000..b9800b2
--- /dev/null
+++ b/lib/sisfileheader.cpp
@@ -0,0 +1,92 @@
+
+#include "sisfileheader.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+SISFileHeader::fillFrom(uchar* buf, int* base)
+{
+ int ix = *base;
+ m_uid1 = read32(buf, &ix);
+ if (logLevel >= 1)
+ printf("Got uid1 = %08x\n", m_uid1);
+ m_uid2 = read32(buf, &ix);
+ if (m_uid2 != 0x1000006d)
+ {
+ printf("Got bad uid2.\n");
+ exit(1);
+ }
+ if (logLevel >= 2)
+ printf("Got uid2 = %08x\n", m_uid2);
+ m_uid3 = read32(buf, &ix);
+ if (m_uid3 != 0x10000419)
+ {
+ printf("Got bad uid3.\n");
+ exit(1);
+ }
+ if (logLevel >= 2)
+ printf("Got uid3 = %08x\n", m_uid3);
+ m_uid4 = read32(buf, &ix);
+// printf("Got uid4 = %08x\n", m_uid4);
+ uint16 crc1 = 0;
+ for (int i = 0; i < 12; i += 2)
+ crc1 = updateCrc(crc1, buf[*base + i]);
+ uint16 crc2 = 0;
+ for (int i = 0; i < 12; i += 2)
+ crc2 = updateCrc(crc2, buf[*base + i + 1]);
+ if (logLevel >= 2)
+ printf("Got first crc = %08x, wanted %08x\n",
+ crc2 << 16 | crc1, m_uid4);
+ if ((crc2 << 16 | crc1) != m_uid4)
+ {
+ printf("Got bad crc.\n");
+ exit(1);
+ }
+ m_crc = read16(buf, &ix);
+ m_nlangs = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got %d languages\n", m_nlangs);
+ m_nfiles = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got %d files\n", m_nfiles);
+ m_nreqs = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got %d reqs\n", m_nreqs);
+ m_installationLanguage = read16(buf, &ix);
+ m_installationFiles = read16(buf, &ix);
+ m_installationDrive = read32(buf, &ix);
+ m_installerVersion = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got installer version: %08x\n", m_installerVersion);
+ m_options = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got options: %04x\n", m_options);
+ m_type = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got type: %0x\n", m_type);
+ m_major = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got major: %d\n", m_major);
+ m_minor = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got minor: %d\n", m_minor);
+ m_minor = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got variant: %d\n", m_variant);
+ m_languagePtr = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Languages begin at %d\n", m_languagePtr);
+ m_filesPtr = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Files begin at %d\n", m_filesPtr);
+ m_reqPtr = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Requisites begin at %d\n", m_reqPtr);
+ m_unknown = read32(buf, &ix);
+ m_componentPtr = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Components begin at %d\n", m_componentPtr);
+ *base = ix;
+}
+
diff --git a/lib/sisfileheader.h b/lib/sisfileheader.h
new file mode 100644
index 0000000..1583365
--- /dev/null
+++ b/lib/sisfileheader.h
@@ -0,0 +1,63 @@
+#ifndef _SISFILEHEADER_H
+#define _SISFILEHEADER_H
+
+#include "sistypes.h"
+
+/**
+ * The first part of a SIS file.
+ */
+class SISFileHeader
+{
+public:
+
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf, int* base);
+
+ enum FileOptions {
+ op_isUnicode = 1,
+ op_isDistributable = 2,
+#ifdef EPOC6
+ op_noCompress = 8,
+ op_shutdownApps = 16,
+#endif
+ };
+
+ enum FileType {
+ FT_App = 0,
+#ifdef EPOC6
+ FT_System = 1,
+ FT_Option = 2,
+ FT_Config = 3,
+ FT_Patch = 4,
+ FT_Upgrade = 5,
+#endif
+ };
+
+ uint32 m_uid1;
+ uint32 m_uid2;
+ uint32 m_uid3;
+ uint32 m_uid4;
+ uint16 m_crc;
+ uint16 m_nlangs;
+ uint16 m_nfiles;
+ uint16 m_nreqs;
+ uint16 m_installationLanguage;
+ uint16 m_installationFiles;
+ uint32 m_installationDrive;
+ uint32 m_installerVersion;
+ uint16 m_options;
+ uint16 m_type;
+ uint16 m_major;
+ uint16 m_minor;
+ uint32 m_variant;
+ uint32 m_languagePtr;
+ uint32 m_filesPtr;
+ uint32 m_reqPtr;
+ uint32 m_unknown;
+ uint32 m_componentPtr;
+};
+
+#endif
+
diff --git a/lib/sisfilerecord.cpp b/lib/sisfilerecord.cpp
new file mode 100644
index 0000000..74b78c5
--- /dev/null
+++ b/lib/sisfilerecord.cpp
@@ -0,0 +1,89 @@
+
+#include "sisfilerecord.h"
+#include "sisfile.h"
+
+#include <stdio.h>
+
+void
+SISFileRecord::fillFrom(uchar* buf, int* base, SISFile* sisFile)
+{
+ int ix = *base;
+ m_flags = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got flags %d\n", m_flags);
+ m_fileType = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got file type %d\n", m_fileType);
+ m_fileDetails = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got file details %d\n", m_fileDetails);
+ m_sourceLength = read32(buf, &ix);
+ m_sourcePtr = read32(buf, &ix);
+// printf("Got source length = %d, source name ptr = %d\n",
+// m_sourceLength, m_sourcePtr);
+ if (logLevel >= 2)
+ if (m_sourceLength > 0)
+ printf("Got source name %.*s\n", m_sourceLength, buf + m_sourcePtr);
+ m_destLength = read32(buf, &ix);
+ m_destPtr = read32(buf, &ix);
+// printf("Got dest length = %d, dest name ptr = %d\n",
+// m_destLength, m_destPtr);
+ if (logLevel >= 2)
+ printf("Got destination name %.*s\n", m_destLength, buf + m_destPtr);
+ switch (m_flags)
+ {
+ case 0: // Only one file.
+ m_fileLengths = new uint32[1];
+ m_filePtrs = new uint32[1];
+ m_fileLengths[0] = read32(buf, &ix);
+ m_filePtrs[0] = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("File is %d bytes long (at %d) (to %d)\n",
+ m_fileLengths[0], m_filePtrs[0],
+ m_fileLengths[0] + m_filePtrs[0]);
+ if (logLevel >= 1)
+ printf("%d .. %d (%d bytes): Single file record type %d, %.*s\n",
+ m_filePtrs[0],
+ m_filePtrs[0] + m_fileLengths[0],
+ m_fileLengths[0],
+ m_fileType,
+ m_destLength, buf + m_destPtr);
+ break;
+
+ case 1: // One file per language.
+ {
+ int n = sisFile->m_header.m_nlangs;
+ m_fileLengths = new uint32[n];
+ m_filePtrs = new uint32[n];
+ for (int i = 0; i < n; ++i)
+ {
+ m_fileLengths[i] = read32(buf, &ix);
+ }
+ for (int i = 0; i < n; ++i)
+ {
+ m_filePtrs[i] = read32(buf, &ix);
+ int len = m_fileLengths[i];
+ if (logLevel >= 2)
+ printf("File %d (for %s) is %d bytes long (at %d)\n",
+ i,
+ sisFile->getLanguage(i)->m_name,
+ len,
+ m_filePtrs[i]);
+ if (logLevel >= 1)
+ printf("%d .. %d (%d bytes): File record (%s) for %.*s\n",
+ m_filePtrs[i],
+ m_filePtrs[i] + len,
+ len,
+ sisFile->getLanguage(i)->m_name,
+ m_destLength, buf + m_destPtr);
+ }
+ break;
+ }
+
+ default:
+ if (logLevel >= 2)
+ printf("Unknown file flags %d\n", m_flags);
+ }
+ *base = ix;
+}
+
diff --git a/lib/sisfilerecord.h b/lib/sisfilerecord.h
new file mode 100644
index 0000000..1187ccf
--- /dev/null
+++ b/lib/sisfilerecord.h
@@ -0,0 +1,64 @@
+#ifndef _SISFILERECORD_H
+#define _SISFILERECORD_H
+
+#include "sistypes.h"
+
+class SISFile;
+
+/**
+ * Information about a file component in a SIS file.
+ *
+ * The file can be for multiple languages, in which case a single
+ * instance holds pointers to contents for all languages.
+ */
+class SISFileRecord
+{
+public:
+
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf, int* base, SISFile* sisFile);
+
+ /**
+ * 1 if multiple lang versions, otherwise 0.
+ */
+ uint32 m_flags;
+
+ /**
+ * Type of file.
+ *
+ * - 0: Standard file.
+ * - 1: Text file to display during installation.
+ * - 2: SIS component.
+ * - 3: File to run during installation/removal.
+ * - 4: Does not exist yet, but will be created when app is run, so
+ * it should not be removed during an upgrade.
+ */
+ uint32 m_fileType;
+
+ /**
+ * If file type is 1:
+ *
+ * - 0: Continue.
+ * - 1: Yes, No (skip next file).
+ * - 2: Yes, No (abort installation).
+ *
+ * If file type is 3:
+ *
+ * - 0: Run during installation.
+ * - 1: Run during removal.
+ * - 2: Run during both installation and removal.
+ */
+ uint32 m_fileDetails;
+
+ uint32 m_sourceLength;
+ uint32 m_sourcePtr;
+ uint32 m_destLength;
+ uint32 m_destPtr;
+ uint32* m_fileLengths;
+ uint32* m_filePtrs;
+};
+
+#endif
+
diff --git a/lib/sislangrecord.cpp b/lib/sislangrecord.cpp
new file mode 100644
index 0000000..c79c45b
--- /dev/null
+++ b/lib/sislangrecord.cpp
@@ -0,0 +1,18 @@
+
+#include "sislangrecord.h"
+
+#include <stdio.h>
+
+void
+SISLangRecord::fillFrom(uchar* buf, int* base)
+{
+ int ix = *base;
+ m_lang = read16(buf, &ix);
+ if (logLevel >= 2)
+ printf("Got language %d (%s)\n", m_lang, langTable[m_lang].m_name);
+ if (logLevel >= 1)
+ printf("%d .. %d (%d bytes): Language record for %s\n",
+ *base, ix, ix - *base, langTable[m_lang].m_name);
+ *base = ix;
+}
+
diff --git a/lib/sislangrecord.h b/lib/sislangrecord.h
new file mode 100644
index 0000000..e532c4e
--- /dev/null
+++ b/lib/sislangrecord.h
@@ -0,0 +1,23 @@
+#ifndef _SISLANGRECORD_H
+#define _SISLANGRECORD_H
+
+#include "sistypes.h"
+
+/**
+ * A simple language record, only containing the epoc specific 16 bit
+ * language number.
+ */
+class SISLangRecord
+{
+public:
+
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf, int* base);
+
+ uint16 m_lang;
+};
+
+#endif
+
diff --git a/lib/sisreqrecord.cpp b/lib/sisreqrecord.cpp
new file mode 100644
index 0000000..978ce48
--- /dev/null
+++ b/lib/sisreqrecord.cpp
@@ -0,0 +1,43 @@
+
+#include "sisreqrecord.h"
+#include "sisfile.h"
+
+#include <stdio.h>
+
+void
+SISReqRecord::fillFrom(uchar* buf, int* base, SISFile* sisFile)
+{
+ int ix = *base;
+
+ m_uid = read32(buf, &ix);
+ m_major = read16(buf, &ix);
+ m_minor = read16(buf, &ix);
+ m_variant = read32(buf, &ix);
+ int n = sisFile->m_header.m_nreqs;
+ m_nameLengths = new uint32[n];
+ m_namePtrs = new uint32[n];
+
+ // First read lengths.
+ //
+ for (int i = 0; i < n; ++i)
+ {
+ m_nameLengths[i] = read32(buf, &ix);
+ }
+
+ // Then read ptrs.
+ //
+ for (int i = 0; i < n; ++i)
+ {
+ m_namePtrs[i] = read32(buf, &ix);
+ if (logLevel >= 2)
+ printf("Name %d (for %s) is %.*s\n",
+ i,
+ sisFile->getLanguage(i)->m_name,
+ m_nameLengths[i],
+ buf + m_namePtrs[i]);
+ }
+ if (logLevel >= 1)
+ printf("%d .. %d (%d bytes): Req record\n", *base, ix, ix - *base);
+ *base = ix;
+}
+
diff --git a/lib/sisreqrecord.h b/lib/sisreqrecord.h
new file mode 100644
index 0000000..bd9aff2
--- /dev/null
+++ b/lib/sisreqrecord.h
@@ -0,0 +1,30 @@
+#ifndef _SISREQRECORD_H
+#define _SISREQRECORD_H
+
+#include "sistypes.h"
+
+class SISFile;
+
+/**
+ * Information about an application that must be installed prior to the
+ * current one.
+ */
+class SISReqRecord
+{
+public:
+
+ /**
+ * Populate the fields.
+ */
+ void fillFrom(uchar* buf, int* base, SISFile* file);
+
+ uint32 m_uid;
+ uint16 m_major;
+ uint16 m_minor;
+ uint32 m_variant;
+ uint32* m_nameLengths;
+ uint32* m_namePtrs;
+};
+
+#endif
+
diff --git a/lib/sistypes.cpp b/lib/sistypes.cpp
new file mode 100644
index 0000000..74ae5ea
--- /dev/null
+++ b/lib/sistypes.cpp
@@ -0,0 +1,89 @@
+
+#include "sistypes.h"
+
+static unsigned int s_crcTable[256];
+
+int logLevel = 0;
+
+void createCRCTable()
+{
+ const unsigned int polynomial = 0x1021;
+ unsigned int index;
+ s_crcTable[0] = 0;
+ for (index = 0; index < 128; index++)
+ {
+ unsigned int carry = s_crcTable[index] & 0x8000;
+ unsigned int temp = (s_crcTable[index] << 1) & 0xffff;
+ s_crcTable[index * 2 + (carry ? 0 : 1)] = temp ^ polynomial;
+ s_crcTable[index * 2 + (carry ? 1 : 0)] = temp;
+ }
+}
+
+uint16 updateCrc(uint16 crc, uchar value)
+{
+ return (crc << 8) ^ s_crcTable[((crc >> 8) ^ value) & 0xff];
+}
+
+uint16 calcCRC(uchar* data, int len)
+{
+ uint16 crc = 0;
+ for (int i = 0; i < len; ++i)
+ {
+ uchar value = data[i];
+ crc = (crc << 8) ^ s_crcTable[((crc >> 8) ^ value) & 0xff];
+ }
+ return crc;
+}
+
+uint16 read16(uchar* buf, int* ix)
+{
+ uchar* p = buf + *ix;
+ *ix += 2;
+ return p[0] | (p[1] << 8);
+}
+
+uint32 read32(uchar* buf, int* ix)
+{
+ uchar* p = buf + *ix;
+ *ix += 4;
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+LangTableEntry langTable[] =
+{
+ { 0, "", "Test" },
+ { 1, "EN", "UK English" },
+ { 2, "FR", "French" },
+ { 3, "GE", "German" },
+ { 4, "SP", "Spanish" },
+ { 5, "IT", "Italian" },
+ { 6, "SW", "Swedish" },
+ { 7, "DA", "Danish" },
+ { 8, "NO", "Norwegian" },
+ { 9, "FI", "Finnish" },
+ { 10, "AM", "American English" },
+ { 11, "SF", "Swiss French" },
+ { 12, "SG", "Swiss German" },
+ { 13, "PO", "Portuguese" },
+ { 14, "TU", "Turkish" },
+ { 15, "IC", "Icelandic" },
+ { 16, "RU", "Russian" },
+ { 17, "HU", "Hungarian" },
+ { 18, "DU", "Dutch" },
+ { 19, "BL", "Belgian Flemish" },
+ { 20, "AU", "Australian English" },
+ { 21, "BG", "Belgian French" },
+ { 22, "AS", "Austrian German" },
+ { 23, "NZ", "New Zealand" },
+ { 24, "IF", "International French" },
+ { 25, "CS", "Czech" },
+ { 26, "SK", "Slovak" },
+ { 27, "PL", "Polish" },
+ { 28, "SL", "Slovenian" },
+ { 29, "TC", "Taiwan Chinese" },
+ { 30, "HK", "Hong Kong" },
+ { 31, "ZH", "PRC Chinese" },
+ { 32, "JA", "Japanese" },
+ { 33, "TH", "Thai" },
+};
+
diff --git a/lib/sistypes.h b/lib/sistypes.h
new file mode 100644
index 0000000..834cf43
--- /dev/null
+++ b/lib/sistypes.h
@@ -0,0 +1,32 @@
+#ifndef _SISTYPES_H
+#define _SISTYPES_H
+
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned char uchar;
+
+extern uint16 read16(uchar* buf, int* ix);
+
+extern uint32 read32(uchar* buf, int* ix);
+
+extern void createCRCTable();
+
+extern uint16 updateCrc(uint16 crc, uchar value);
+
+extern int logLevel;
+
+/**
+ * Holder of a language entry, translating from language numbers to
+ * names.
+ */
+struct LangTableEntry
+{
+ uint16 m_no;
+ char m_code[3];
+ char* m_name;
+};
+
+extern LangTableEntry langTable[];
+
+#endif
+
diff --git a/sisinstall/.cvsignore b/sisinstall/.cvsignore
new file mode 100644
index 0000000..cef7c58
--- /dev/null
+++ b/sisinstall/.cvsignore
@@ -0,0 +1,5 @@
+Makefile.in
+Makefile
+sisinstall
+.libs
+.deps
diff --git a/sisinstall/Makefile.am b/sisinstall/Makefile.am
new file mode 100644
index 0000000..243f877
--- /dev/null
+++ b/sisinstall/Makefile.am
@@ -0,0 +1,11 @@
+# $Id$
+#
+INCLUDES=-I$(top_srcdir)/lib
+
+bin_PROGRAMS = sisinstall
+sisinstall_LDADD = $(top_srcdir)/lib/libplp.la
+sisinstall_SOURCES = psion.cpp sisinstaller.cpp sismain.cpp
+EXTRA_DIST = psion.h sisinstaller.h
+
+maintainer-clean-local:
+ rm -f Makefile.in
diff --git a/sisinstall/psion.cpp b/sisinstall/psion.cpp
new file mode 100644
index 0000000..6aeadf1
--- /dev/null
+++ b/sisinstall/psion.cpp
@@ -0,0 +1,84 @@
+#include "psion.h"
+
+#include <plpintl.h>
+#include <rfsv.h>
+#include <rpcs.h>
+#include <rfsvfactory.h>
+#include <rpcsfactory.h>
+#include <bufferarray.h>
+#include <bufferstore.h>
+#include <ppsocket.h>
+
+#include <dirent.h>
+#include <netdb.h>
+
+#include <stdio.h>
+
+bool
+Psion::connect()
+{
+ int sockNum = DPORT;
+
+#if 0
+ setlocale (LC_ALL, "");
+ textdomain(PACKAGE);
+#endif
+
+ struct servent *se = getservbyname("psion", "tcp");
+ endservent();
+ if (se != 0L)
+ sockNum = ntohs(se->s_port);
+
+#if 0
+ // Command line parameter processing
+ if ((argc > 2) && !strcmp(argv[1], "-p")) {
+ sockNum = atoi(argv[2]);
+ argc -= 2;
+ for (int i = 1; i < argc; i++)
+ argv[i] = argv[i + 2];
+ }
+#endif
+
+ m_skt = new ppsocket();
+ if (!m_skt->connect(NULL, sockNum)) {
+ return 1;
+ }
+ m_skt2 = new ppsocket();
+ if (!m_skt2->connect(NULL, sockNum)) {
+ return 1;
+ }
+ m_rfsvFactory = new rfsvfactory(m_skt);
+ m_rpcsFactory = new rpcsfactory(m_skt2);
+ m_rfsv = m_rfsvFactory->create(true);
+ m_rpcs = m_rpcsFactory->create(true);
+ if ((m_rfsv != NULL) && (m_rpcs != NULL))
+ return true;
+}
+
+Psion::~Psion()
+{
+ disconnect();
+}
+
+Enum<rfsv::errs>
+Psion::devlist(u_int32_t& devbits)
+{
+ printf("Running devlist\n");
+ u_int32_t devb;
+ Enum<rfsv::errs> res;
+ res = m_rfsv->devlist(devb);
+ devbits = devb;
+ return res;
+}
+
+void
+Psion::disconnect()
+{
+ delete m_rfsv;
+ delete m_rpcs;
+ delete m_skt;
+ delete m_skt2;
+ delete m_rfsvFactory;
+ delete m_rpcsFactory;
+}
+
diff --git a/sisinstall/psion.h b/sisinstall/psion.h
new file mode 100644
index 0000000..0043140
--- /dev/null
+++ b/sisinstall/psion.h
@@ -0,0 +1,37 @@
+#ifndef _PSION_H
+#define _PSION_H
+
+#include <Enum.h>
+#include "rfsv.h"
+
+class ppsocket;
+class rfsvfactory;
+class rpcsfactory;
+class rpcs;
+
+class Psion
+{
+public:
+
+ virtual ~Psion();
+
+ bool connect();
+
+ Enum<rfsv::errs> devlist(u_int32_t& devbits);
+
+ void disconnect();
+
+ rfsv* m_rfsv;
+
+private:
+
+ ppsocket* m_skt;
+ ppsocket* m_skt2;
+ rfsvfactory* m_rfsvFactory;
+ rpcsfactory* m_rpcsFactory;
+ rpcs* m_rpcs;
+
+};
+
+#endif
+
diff --git a/sisinstall/sisinstaller.cpp b/sisinstall/sisinstaller.cpp
new file mode 100644
index 0000000..efd0bfe
--- /dev/null
+++ b/sisinstall/sisinstaller.cpp
@@ -0,0 +1,203 @@
+
+#include "sisinstaller.h"
+
+#include "sisfile.h"
+#include "sisfilerecord.h"
+#include "sisreqrecord.h"
+#include "psion.h"
+
+#include <unistd.h>
+#include <stdio.h>
+
+void
+SISInstaller::setPsion(Psion* psion)
+{
+ m_psion = psion;
+}
+
+void
+SISInstaller::run(SISFile* file, uchar* buf)
+{
+ run(file, buf, 0);
+}
+
+void
+SISInstaller::run(SISFile* file, uchar* buf, SISFile* parent)
+{
+ int n;
+ int lang;
+ if (parent == 0)
+ {
+ n = file->m_header.m_nlangs;
+ if (n == 1)
+ {
+ printf("You have only one language: %s\n",
+ file->getLanguage(0)->m_name);
+ lang = 0;
+ }
+ else
+ {
+ printf("Select a language (%d alternatives):\n", n);
+ for (int i = 0; i < n; ++i)
+ {
+ printf(" %d. %s\n", i, file->getLanguage(i)->m_name);
+ }
+ lang = 0;
+ }
+ }
+ else
+ {
+ lang = parent->getLanguage();
+ printf("Forcing language to %d\n", lang);
+ }
+ file->setLanguage(lang);
+ printf("Installing component: `%s'\n", file->getName());
+
+ // Check Requisites.
+ //
+ n = file->m_header.m_nreqs;
+ printf("Found %d requisites, of some sort.\n", n);
+ for (int i = 0; i < n; ++i)
+ {
+ SISReqRecord* reqRecord = &file->m_reqRecords[i];
+ printf(" Check if app with uid %08x exists with version >= %d.%d\n",
+ reqRecord->m_uid,
+ reqRecord->m_major,
+ reqRecord->m_minor);
+ }
+
+ // Check previous version.
+ //
+ printf(
+ "Checking if this app (uid %08x) exists with a version less than %d.%d.\n",
+ file->m_header.m_uid1,
+ file->m_header.m_major,
+ file->m_header.m_minor);
+
+ // Install file components.
+ //
+ n = file->m_header.m_nfiles;
+ printf("Found %d files.\n", n);
+ char drive = (parent == 0) ? 0 : parent->m_header.m_installationDrive;
+ file->m_header.m_installationFiles = 0;
+ int firstFile = -1;
+ while (n-- > 0)
+ {
+ SISFileRecord* fileRecord = &file->m_fileRecords[n];
+ int ix = 0;
+ if (fileRecord->m_flags & 1)
+ ix = lang;
+ char ch;
+#if 0
+ printf("FirstFile = %d, ptr = %d, length = %d\n",
+ firstFile,
+ fileRecord->m_filePtrs[ix],
+ fileRecord->m_fileLengths[ix]);
+#endif
+ if ((firstFile == -1) ||
+ (firstFile >= fileRecord->m_filePtrs[ix]))
+ firstFile = fileRecord->m_filePtrs[ix];
+
+// We can only do this if we search all files...
+// fileRecord->m_filePtrs[ix] + fileRecord->m_fileLengths[ix]
+
+ switch (fileRecord->m_fileType)
+ {
+ case 0:
+ if (buf[fileRecord->m_destPtr] == '!')
+ {
+ if (drive == 0)
+ {
+#if 0
+ u_int32_t devbits = 0;
+ Enum<rfsv::errs> res;
+ if ((res = m_psion->m_rfsv->devlist(devbits)) == rfsv::E_PSI_GEN_NONE)
+ {
+ for (int i = 0; i < 26; i++)
+ {
+ PlpDrive plpdrive;
+ if ((devbits & 1) != 0)
+ {
+ u_int32_t mediaType = plpdrive.getMediaType();
+ if ((mediaType == 3) || (mediaType == 5))
+ {
+ printf("%c: %d bytes free\n", 'A' + i, plpdrive.getSpace());
+ }
+ }
+ devbits >>= 1;
+ }
+ }
+#endif
+ printf("Please select a drive\n");
+ read(0, &ch, 1);
+ if (ch >= 'a' && ch <= 'z')
+ drive = ch;
+ else
+ drive = 'c';
+ }
+ file->m_header.m_installationDrive = drive;
+ }
+ printf("Copying %d bytes to %.*s\n",
+ fileRecord->m_fileLengths[ix],
+ fileRecord->m_destLength,
+ buf + fileRecord->m_destPtr);
+ break;
+ case 1:
+ printf("Info:\n%.*s\n",
+ fileRecord->m_fileLengths[ix],
+ buf + fileRecord->m_filePtrs[ix]);
+ switch (fileRecord->m_fileDetails)
+ {
+ case 0:
+ printf("Continue\n");
+// read(0, &ch, 1);
+ break;
+ case 1:
+ printf("Skip next file? Yes/No\n");
+// read(0, &ch, 1);
+ break;
+ case 2:
+ printf("[Continue installation?] Yes/No\n");
+// read(0, &ch, 1);
+ break;
+ }
+ break;
+ case 2:
+ {
+ printf("Recursive sis file...\n");
+ SISFile sisFile;
+ uchar* buf2 = buf + fileRecord->m_filePtrs[ix];
+ sisFile.fillFrom(buf2);
+ SISInstaller installer;
+ installer.run(&sisFile, buf2, file);
+ if (0 == file->m_header.m_installationDrive)
+ drive =
+ file->m_header.m_installationDrive =
+ sisFile.m_header.m_installationDrive;
+ break;
+ }
+ case 3:
+ printf("Run %.*s during installation/remove\n",
+ fileRecord->m_destLength, buf + fileRecord->m_destPtr);
+ break;
+ case 4:
+ printf("Running the app will create %.*s\n",
+ fileRecord->m_destLength, buf + fileRecord->m_destPtr);
+ break;
+ }
+
+ file->m_header.m_installationFiles++;
+ }
+ printf("Installed %d files of %d, cutting at offset %d\n",
+ file->m_header.m_installationFiles,
+ file->m_header.m_nfiles,
+ firstFile);
+
+ // Set the new shortened size somewhere.
+ //
+
+ // Copy the updated sis file to the epoc machine.
+ //
+
+}
+
diff --git a/sisinstall/sisinstaller.h b/sisinstall/sisinstaller.h
new file mode 100644
index 0000000..653ede9
--- /dev/null
+++ b/sisinstall/sisinstaller.h
@@ -0,0 +1,30 @@
+#ifndef _SISINSTALLER_H
+#define _SISINSTALLER_H
+
+#include "sistypes.h"
+
+class Psion;
+class SISFile;
+
+/**
+ * A minimal SIS installer.
+ * Handles recursive sis files.
+ */
+class SISInstaller
+{
+public:
+
+ void run(SISFile* file, uchar* buf);
+
+ void run(SISFile* file, uchar* buf, SISFile* parent);
+
+ void setPsion(Psion* psion);
+
+private:
+
+ Psion* m_psion;
+
+};
+
+#endif
+
diff --git a/sisinstall/sismain.cpp b/sisinstall/sismain.cpp
new file mode 100644
index 0000000..1b9f714
--- /dev/null
+++ b/sisinstall/sismain.cpp
@@ -0,0 +1,62 @@
+
+#include "sisfile.h"
+#include "sisinstaller.h"
+#include "psion.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static void error(int line)
+{
+ fprintf(stderr, "Got errno = %d (%s) on line %d\n",
+ errno, strerror(errno), line);
+ exit(1);
+}
+
+void main(int argc, char* argv[])
+{
+ char* filename = 0;
+ if (argc > 1)
+ filename = argv[1];
+ else
+ return 0;
+ struct stat st;
+ if (-1 == stat(filename, &st))
+ error(__LINE__);
+ off_t len = st.st_size;
+ if (logLevel >= 2)
+ printf("File is %d bytes long\n", len);
+ uchar* buf = new uchar[len];
+ int fd = open(filename, O_RDONLY);
+ if (-1 == fd)
+ error(__LINE__);
+ if (-1 == read(fd, buf, len))
+ error(__LINE__);
+ close(fd);
+ Psion psion;
+#if 0
+ if (!psion.connect())
+ {
+ printf("Couldn't connect with the Psion\n");
+ exit(1);
+ }
+#endif
+ createCRCTable();
+ SISFile sisFile;
+ sisFile.fillFrom(buf);
+ SISInstaller installer;
+ installer.setPsion(&psion);
+ installer.run(&sisFile, buf);
+#if 0
+ psion.disconnect();
+#endif
+
+ exit(0);
+}
+