From eecba3b5fcb47a01e6e13ee1940def989f6dd22d Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Thu, 28 Feb 2002 20:56:59 +0000 Subject: - Added SIS stuff by Daniel Brahneborg --- lib/Enum.h | 6 ++ lib/Makefile.am | 8 +- lib/bufferstore.cc | 10 ++- lib/rfsv32.cc | 5 +- lib/siscomponentrecord.cpp | 55 ++++++++++++ lib/siscomponentrecord.h | 38 +++++++++ lib/sisfile.cpp | 72 ++++++++++++++++ lib/sisfile.h | 53 ++++++++++++ lib/sisfileheader.cpp | 92 ++++++++++++++++++++ lib/sisfileheader.h | 63 ++++++++++++++ lib/sisfilerecord.cpp | 89 +++++++++++++++++++ lib/sisfilerecord.h | 64 ++++++++++++++ lib/sislangrecord.cpp | 18 ++++ lib/sislangrecord.h | 23 +++++ lib/sisreqrecord.cpp | 43 ++++++++++ lib/sisreqrecord.h | 30 +++++++ lib/sistypes.cpp | 89 +++++++++++++++++++ lib/sistypes.h | 32 +++++++ sisinstall/.cvsignore | 5 ++ sisinstall/Makefile.am | 11 +++ sisinstall/psion.cpp | 84 ++++++++++++++++++ sisinstall/psion.h | 37 ++++++++ sisinstall/sisinstaller.cpp | 203 ++++++++++++++++++++++++++++++++++++++++++++ sisinstall/sisinstaller.h | 30 +++++++ sisinstall/sismain.cpp | 62 ++++++++++++++ 25 files changed, 1214 insertions(+), 8 deletions(-) create mode 100644 lib/siscomponentrecord.cpp create mode 100644 lib/siscomponentrecord.h create mode 100644 lib/sisfile.cpp create mode 100644 lib/sisfile.h create mode 100644 lib/sisfileheader.cpp create mode 100644 lib/sisfileheader.h create mode 100644 lib/sisfilerecord.cpp create mode 100644 lib/sisfilerecord.h create mode 100644 lib/sislangrecord.cpp create mode 100644 lib/sislangrecord.h create mode 100644 lib/sisreqrecord.cpp create mode 100644 lib/sisreqrecord.h create mode 100644 lib/sistypes.cpp create mode 100644 lib/sistypes.h create mode 100644 sisinstall/.cvsignore create mode 100644 sisinstall/Makefile.am create mode 100644 sisinstall/psion.cpp create mode 100644 sisinstall/psion.h create mode 100644 sisinstall/sisinstaller.cpp create mode 100644 sisinstall/sisinstaller.h create mode 100644 sisinstall/sismain.cpp 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 rfsv32:: fread(const u_int32_t handle, unsigned char * const buf, const u_int32_t len, u_int32_t &count) { Enum 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 +#include + +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 + +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 . + * + * @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 +#include + +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 + +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 + +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 + +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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +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 +Psion::devlist(u_int32_t& devbits) +{ + printf("Running devlist\n"); + u_int32_t devb; + Enum 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 +#include "rfsv.h" + +class ppsocket; +class rfsvfactory; +class rpcsfactory; +class rpcs; + +class Psion +{ +public: + + virtual ~Psion(); + + bool connect(); + + Enum 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 +#include + +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 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 +#include +#include +#include +#include +#include +#include +#include + +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); +} + -- cgit v1.2.3