From 6f49fd782b8935b8caf7cea7bcb6e10644851b13 Mon Sep 17 00:00:00 2001 From: Daniel Brahneborg Date: Sat, 2 Mar 2002 23:27:47 +0000 Subject: Actually copy stuff to the psion, and lots of other updates. --- sisinstall/Makefile.am | 4 +- sisinstall/fakepsion.cpp | 53 ++++++ sisinstall/fakepsion.h | 34 ++++ sisinstall/psion.cpp | 47 ++++- sisinstall/psion.h | 20 ++- sisinstall/sisinstaller.cpp | 406 ++++++++++++++++++++++++++++++++------------ sisinstall/sisinstaller.h | 37 ++++ sisinstall/sismain.cpp | 51 ++++-- 8 files changed, 510 insertions(+), 142 deletions(-) create mode 100644 sisinstall/fakepsion.cpp create mode 100644 sisinstall/fakepsion.h (limited to 'sisinstall') diff --git a/sisinstall/Makefile.am b/sisinstall/Makefile.am index 243f877..67c990d 100644 --- a/sisinstall/Makefile.am +++ b/sisinstall/Makefile.am @@ -4,7 +4,9 @@ INCLUDES=-I$(top_srcdir)/lib bin_PROGRAMS = sisinstall sisinstall_LDADD = $(top_srcdir)/lib/libplp.la -sisinstall_SOURCES = psion.cpp sisinstaller.cpp sismain.cpp +sisinstall_SOURCES = psion.cpp sisinstaller.cpp sismain.cpp \ + fakepsion.cpp +sisinstall_HEADERS = fakepsion.h EXTRA_DIST = psion.h sisinstaller.h maintainer-clean-local: diff --git a/sisinstall/fakepsion.cpp b/sisinstall/fakepsion.cpp new file mode 100644 index 0000000..49defca --- /dev/null +++ b/sisinstall/fakepsion.cpp @@ -0,0 +1,53 @@ + +#include "fakepsion.h" + +#include + +FakePsion::~FakePsion() +{ +} + +bool +FakePsion::connect() +{ + return true; +} + +Enum +FakePsion::copyToPsion(const char * const from, const char * const to, + void *, cpCallback_t func) +{ + printf(" -- Not really copying %s to %s\n", from, to); + return rfsv::E_PSI_GEN_NONE; +} + +Enum +FakePsion::devinfo(const char drive, PlpDrive& plpDrive) +{ + return rfsv::E_PSI_GEN_NONE; +} + +Enum +FakePsion::devlist(u_int32_t& devbits) +{ + return rfsv::E_PSI_GEN_FAIL; +} + +bool +FakePsion::dirExists(const char* name) +{ + return true; +} + +void +FakePsion::disconnect() +{ +} + +Enum +FakePsion::mkdir(const char* dir) +{ + printf(" -- Not really creating dir %s\n", dir); + return rfsv::E_PSI_GEN_NONE; +} + diff --git a/sisinstall/fakepsion.h b/sisinstall/fakepsion.h new file mode 100644 index 0000000..d53dafd --- /dev/null +++ b/sisinstall/fakepsion.h @@ -0,0 +1,34 @@ +#ifndef _FAKEPSION_H +#define _FAKEPSION_H + +#include "psion.h" + +/** + * A dummy version of the Psion proxy, mainly for testing the installer. + */ +class FakePsion : public Psion +{ +public: + + virtual ~FakePsion(); + + virtual bool connect(); + + virtual Enum copyToPsion(const char * const from, + const char * const to, + void *, cpCallback_t func); + + virtual Enum devinfo(const char drive, PlpDrive& plpDrive); + + virtual Enum devlist(u_int32_t& devbits); + + virtual bool dirExists(const char* name); + + virtual void disconnect(); + + virtual Enum mkdir(const char* dir); + +}; + +#endif + diff --git a/sisinstall/psion.cpp b/sisinstall/psion.cpp index 6aeadf1..287ea76 100644 --- a/sisinstall/psion.cpp +++ b/sisinstall/psion.cpp @@ -1,3 +1,4 @@ + #include "psion.h" #include @@ -14,6 +15,11 @@ #include +Psion::~Psion() +{ + disconnect(); +} + bool Psion::connect() { @@ -41,11 +47,11 @@ Psion::connect() m_skt = new ppsocket(); if (!m_skt->connect(NULL, sockNum)) { - return 1; + return false; } m_skt2 = new ppsocket(); if (!m_skt2->connect(NULL, sockNum)) { - return 1; + return false; } m_rfsvFactory = new rfsvfactory(m_skt); m_rpcsFactory = new rpcsfactory(m_skt2); @@ -53,24 +59,43 @@ Psion::connect() m_rpcs = m_rpcsFactory->create(true); if ((m_rfsv != NULL) && (m_rpcs != NULL)) return true; + return false; } -Psion::~Psion() +Enum +Psion::copyToPsion(const char * const from, const char * const to, + void *, cpCallback_t func) { - disconnect(); + return m_rfsv->copyToPsion(from, to, NULL, func); +} + +Enum +Psion::devinfo(const char drive, PlpDrive& plpDrive) +{ + return m_rfsv->devinfo(drive, plpDrive); } Enum Psion::devlist(u_int32_t& devbits) { - printf("Running devlist\n"); - u_int32_t devb; Enum res; - res = m_rfsv->devlist(devb); - devbits = devb; + res = m_rfsv->devlist(devbits); return res; } +bool +Psion::dirExists(const char* name) +{ + rfsvDirhandle handle; + Enum res; + bool exists = false; + res = m_rfsv->opendir(rfsv::PSI_A_ARCHIVE, name, handle); + if (res == rfsv::E_PSI_GEN_NONE) + exists = true; + res = m_rfsv->closedir(handle); + return exists; +} + void Psion::disconnect() { @@ -82,3 +107,9 @@ Psion::disconnect() delete m_rpcsFactory; } +Enum +Psion::mkdir(const char* dir) +{ + return m_rfsv->mkdir(dir); +} + diff --git a/sisinstall/psion.h b/sisinstall/psion.h index 0043140..4336bb0 100644 --- a/sisinstall/psion.h +++ b/sisinstall/psion.h @@ -9,19 +9,30 @@ class rfsvfactory; class rpcsfactory; class rpcs; +/** + * Semi smart proxy for communicating with a Psion. + */ class Psion { public: virtual ~Psion(); - bool connect(); + virtual bool connect(); - Enum devlist(u_int32_t& devbits); + virtual Enum copyToPsion(const char * const from, + const char * const to, + void *, cpCallback_t func); - void disconnect(); + virtual Enum devinfo(const char drive, PlpDrive& plpDrive); - rfsv* m_rfsv; + virtual Enum devlist(u_int32_t& devbits); + + virtual bool dirExists(const char* name); + + virtual void disconnect(); + + virtual Enum mkdir(const char* dir); private: @@ -30,6 +41,7 @@ private: rfsvfactory* m_rfsvFactory; rpcsfactory* m_rpcsFactory; rpcs* m_rpcs; + rfsv* m_rfsv; }; diff --git a/sisinstall/sisinstaller.cpp b/sisinstall/sisinstaller.cpp index efd0bfe..db58720 100644 --- a/sisinstall/sisinstaller.cpp +++ b/sisinstall/sisinstaller.cpp @@ -6,9 +6,180 @@ #include "sisreqrecord.h" #include "psion.h" +#include #include #include +static int continueRunning; + +static int +checkAbortHash(void *, u_int32_t) +{ + if (continueRunning) + { + printf("#"); + fflush(stdout); + } + return continueRunning; +} + +void +SISInstaller::createDirs(char* filename) +{ + char* end = filename + strlen(filename); + while (--end > filename) + { + char ch = *end; + if ((ch == '/') || (ch == '\\')) + { + *end = 0; + if (logLevel >= 1) + printf("Checking for existance of %s\n", filename); +// if (!m_psion->dirExists(filename)) + { + printf("Creating dir %s\n", filename); + Enum res; + res = m_psion->mkdir(filename); + if ((res != rfsv::E_PSI_GEN_NONE) && + (res != rfsv::E_PSI_FILE_EXIST)) + printf(" -> Failed: %s\n", (const char*)res); + } + *end = ch; + return; + } + } +} + +void +SISInstaller::copyFile(SISFileRecord* fileRecord) +{ + if (m_buf[fileRecord->m_destPtr] == '!') + { + if (m_drive == 0) + selectDrive(); + m_file->setDrive(m_drive); + } + int len = fileRecord->m_destLength; + char* dest = new char[len + 1]; + memcpy(dest, m_buf + fileRecord->m_destPtr, len); + dest[len] = 0; + if (dest[0] == '!') + { + dest[0] = m_drive; + m_buf[fileRecord->m_destPtr] = m_drive; + } + printf("Copying %d bytes to %s\n", + fileRecord->m_fileLengths[m_fileNo], dest); + copyBuf(m_buf + fileRecord->m_filePtrs[m_fileNo], + fileRecord->m_fileLengths[m_fileNo], + dest); + delete[] dest; +} + +void +SISInstaller::copyBuf(const uchar* buf, int len, char* name) +{ + createDirs(name); + char srcName[32]; + strcpy(srcName, "/tmp/plptools-sis-XXXXXX"); + int fd = mkstemp(srcName); + if (-1 == fd) + { + printf("Couldn't create temp file: %s\n", strerror(errno)); + return; + } + Enum res; + if (logLevel >= 2) + printf("Storing in %s\n", srcName); + write(fd, buf, len); + close(fd); + continueRunning = 1; + res = m_psion->copyToPsion(srcName, name, NULL, checkAbortHash); + if (res == rfsv::E_PSI_GEN_NONE) + { + printf(" -> Success.\n"); + } + else + { + printf(" -> Fail: %s\n", (const char*)res); + } + unlink(srcName); +} + +int +SISInstaller::installFile(SISFileRecord* fileRecord) +{ + char readbuf[2]; + switch (fileRecord->m_fileType) + { + case 0: + copyFile(fileRecord); + break; + case 1: + printf("Info:\n%.*s\n", + fileRecord->m_fileLengths[m_fileNo], + m_buf + fileRecord->m_filePtrs[m_fileNo]); + switch (fileRecord->m_fileDetails) + { + case 0: + printf("Continue\n"); + fgets(readbuf, 2, stdin); + break; + case 1: + printf("(Install next file?) [Y]es/No\n"); + fgets(readbuf, 2, stdin); + if (strchr("Nn", readbuf[0])) + { + return FILE_SKIP; + } + break; + case 2: + printf("(Continue installation?) [Y]es/No\n"); + fgets(readbuf, 2, stdin); + if (!strchr("Nn", readbuf[0])) + { + // Watch out if we have copied any files + // already. + // + return FILE_ABORT; + } + break; + } + break; + case 2: + { + if (logLevel >= 1) + printf("Recursive sis file...\n"); + SISFile sisFile; + uchar* buf2 = m_buf + fileRecord->m_filePtrs[m_fileNo]; + sisFile.fillFrom(buf2); + SISInstaller installer; + installer.setPsion(m_psion); + installer.run(&sisFile, buf2, m_file); + if (0 == m_drive) + { + m_drive = sisFile.m_header.m_installationDrive; + m_file->setDrive(m_drive); + if (logLevel >= 1) + printf("Updated drive to %c from recursive sis file\n", + m_drive); + } + break; + } + case 3: + printf("Run %.*s during installation/remove\n", + fileRecord->m_destLength, m_buf + fileRecord->m_destPtr); + break; + case 4: + if (logLevel >= 2) + printf("Running the app will create %.*s\n", + fileRecord->m_destLength, + m_buf + fileRecord->m_destPtr); + break; + } + return FILE_OK; +} + void SISInstaller::setPsion(Psion* psion) { @@ -26,13 +197,15 @@ SISInstaller::run(SISFile* file, uchar* buf, SISFile* parent) { int n; int lang; + m_file = file; + m_buf = buf; if (parent == 0) { - n = file->m_header.m_nlangs; + n = m_file->m_header.m_nlangs; if (n == 1) { printf("You have only one language: %s\n", - file->getLanguage(0)->m_name); + m_file->getLanguage(0)->m_name); lang = 0; } else @@ -40,7 +213,7 @@ SISInstaller::run(SISFile* file, uchar* buf, SISFile* parent) 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); + printf(" %d. %s\n", i, m_file->getLanguage(i)->m_name); } lang = 0; } @@ -48,18 +221,21 @@ SISInstaller::run(SISFile* file, uchar* buf, SISFile* parent) else { lang = parent->getLanguage(); - printf("Forcing language to %d\n", lang); + if (logLevel >= 1) + printf("Forcing language to %d\n", lang); } - file->setLanguage(lang); - printf("Installing component: `%s'\n", file->getName()); + m_file->setLanguage(lang); + uchar* compName = m_file->getName(); + printf("Installing component: `%s'\n", compName); // Check Requisites. // - n = file->m_header.m_nreqs; - printf("Found %d requisites, of some sort.\n", n); + n = m_file->m_header.m_nreqs; + if (logLevel >= 1) + printf("Found %d requisites, of some sort.\n", n); for (int i = 0; i < n; ++i) { - SISReqRecord* reqRecord = &file->m_reqRecords[i]; + SISReqRecord* reqRecord = &m_file->m_reqRecords[i]; printf(" Check if app with uid %08x exists with version >= %d.%d\n", reqRecord->m_uid, reqRecord->m_major, @@ -70,134 +246,138 @@ SISInstaller::run(SISFile* file, uchar* buf, SISFile* parent) // 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); + m_file->m_header.m_uid1, + m_file->m_header.m_major, + m_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; + n = m_file->m_header.m_nfiles; + if (logLevel >= 1) + printf("Found %d files.\n", n); + m_drive = (parent == 0) ? 0 : parent->m_header.m_installationDrive; + int nCopiedFiles = 0; int firstFile = -1; + bool skipnext = false; while (n-- > 0) { - SISFileRecord* fileRecord = &file->m_fileRecords[n]; - int ix = 0; - if (fileRecord->m_flags & 1) - ix = lang; + SISFileRecord* fileRecord = &m_file->m_fileRecords[n]; + m_fileNo = (fileRecord->m_flags & 1) ? lang : 0; char ch; #if 0 printf("FirstFile = %d, ptr = %d, length = %d\n", firstFile, - fileRecord->m_filePtrs[ix], - fileRecord->m_fileLengths[ix]); + fileRecord->m_filePtrs[m_fileNo], + fileRecord->m_fileLengths[m_fileNo]); #endif if ((firstFile == -1) || - (firstFile >= fileRecord->m_filePtrs[ix])) - firstFile = fileRecord->m_filePtrs[ix]; + (firstFile >= fileRecord->m_filePtrs[m_fileNo])) + firstFile = fileRecord->m_filePtrs[m_fileNo]; // We can only do this if we search all files... -// fileRecord->m_filePtrs[ix] + fileRecord->m_fileLengths[ix] +// fileRecord->m_filePtrs[m_fileNo] + fileRecord->m_fileLengths[m_fileNo] - switch (fileRecord->m_fileType) + if (skipnext) { - 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: + skipnext = false; + } + else + { + switch (installFile(fileRecord)) { - 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 FILE_OK: + break; + case FILE_SKIP: + skipnext = true; + break; + case FILE_ABORT: + 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++; + nCopiedFiles++; } - 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. - // + m_file->setFiles(nCopiedFiles); + if (logLevel >= 1) + printf("Installed %d files of %d, cutting at offset %d\n", + m_file->m_header.m_installationFiles, + m_file->m_header.m_nfiles, + firstFile); // Copy the updated sis file to the epoc machine. // + char* resname = new char[256]; + int namelen = 0; + while (compName[namelen] != 0) + { + if (compName[namelen] == ' ') + break; + namelen++; + } + sprintf(resname, "C:\\System\\Install\\%.*s.sis", namelen, compName); + printf("Creating residual sis file %s\n", resname); + copyBuf(buf, firstFile, resname); + delete[] resname; +} +void +SISInstaller::selectDrive() +{ + u_int32_t devbits = 0; + Enum res; + char drivelist[26]; + int ndrives = 0; + if ((res = m_psion->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) + { + for (int i = 0; i < 26; i++) + { + PlpDrive plpdrive; + if (((devbits & 1) != 0) && + (m_psion->devinfo(i + 'A', plpdrive) == rfsv::E_PSI_GEN_NONE)) + { + u_int32_t mediaType = plpdrive.getMediaType(); + if ((mediaType == 3) || (mediaType == 5)) + { + drivelist[ndrives++] = 'A' + i; + printf("%c: %d bytes free, %d bytes total\n", + 'A' + i, + plpdrive.getSpace(), + plpdrive.getSize()); + } + } + devbits >>= 1; + } + } + drivelist[ndrives] = 0; + if (ndrives == 0) + { + m_drive = 'C'; + printf("Selecting the only drive %c\n", m_drive); + } + else if (ndrives == 1) + { + m_drive = drivelist[0]; + printf("Selecting the only drive %c\n", m_drive); + } + else + { + printf("Please select a drive\n"); + char ch; + char readbuf[2]; + while (m_drive == 0) + { + fgets(readbuf, 2, stdin); + ch = readbuf[0]; + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) + { + m_drive = toupper(ch); + if (!strchr(drivelist, m_drive)) + { + m_drive = 0; + printf("Please select a valid drive: %s\n", drivelist); + } + } + } + } } diff --git a/sisinstall/sisinstaller.h b/sisinstall/sisinstaller.h index 653ede9..6bc6c18 100644 --- a/sisinstall/sisinstaller.h +++ b/sisinstall/sisinstaller.h @@ -5,6 +5,7 @@ class Psion; class SISFile; +class SISFileRecord; /** * A minimal SIS installer. @@ -18,12 +19,48 @@ public: void run(SISFile* file, uchar* buf, SISFile* parent); + /** + * Ask the user which drive to install to. + */ + void selectDrive(); + + /** + * Set the Psion manager. + */ void setPsion(Psion* psion); private: + char m_drive; + + int m_fileNo; + Psion* m_psion; + uchar* m_buf; + + SISFile* m_file; + + enum { + FILE_OK, + FILE_SKIP, + FILE_ABORT, + }; + + /** + * Store the contents of a buffer in a file on the Psion. + */ + void copyBuf(const uchar* buf, int len, char* name); + + /** + * Copy a file to the Psion. + */ + void copyFile(SISFileRecord* fileRecord); + + void createDirs(char* filename); + + int installFile(SISFileRecord* fileRecord); + }; #endif diff --git a/sisinstall/sismain.cpp b/sisinstall/sismain.cpp index 1b9f714..8516b0f 100644 --- a/sisinstall/sismain.cpp +++ b/sisinstall/sismain.cpp @@ -2,6 +2,7 @@ #include "sisfile.h" #include "sisinstaller.h" #include "psion.h" +#include "fakepsion.h" #include #include @@ -14,18 +15,33 @@ static void error(int line) { - fprintf(stderr, "Got errno = %d (%s) on line %d\n", - errno, strerror(errno), line); + fprintf(stderr, "Got errno = %d on line %d\n", errno, line); exit(1); } void main(int argc, char* argv[]) { char* filename = 0; - if (argc > 1) - filename = argv[1]; - else - return 0; + char option; + bool dryrun = false; + while ((option = getopt(argc, argv, "nl:")) != -1) + { + switch (option) + { + case 'l': + logLevel = atoi(optarg); + break; + case 'n': + dryrun = true; + break; + } + } + if (optind < argc) + { + filename = argv[optind]; + printf("Installing sis file %s%s\n", filename, + dryrun ? ", not really" : ""); + } struct stat st; if (-1 == stat(filename, &st)) error(__LINE__); @@ -39,23 +55,26 @@ void main(int argc, char* argv[]) if (-1 == read(fd, buf, len)) error(__LINE__); close(fd); - Psion psion; -#if 0 - if (!psion.connect()) + Psion* psion; + if (dryrun) + psion = new FakePsion(); + else + psion = new Psion(); + 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 + if (!dryrun) + { + SISInstaller installer; + installer.setPsion(psion); + installer.run(&sisFile, buf); + } + psion->disconnect(); exit(0); } -- cgit v1.2.3