From f1f20db42313032578ba256903d0004dd126a60a Mon Sep 17 00:00:00 2001
From: Daniel Brahneborg <basic@chello.se>
Date: Sun, 14 Apr 2002 12:03:02 +0000
Subject: More correct residual sis file truncation

---
 lib/siscomponentrecord.cpp  | 20 ++++++++++++++++++--
 lib/siscomponentrecord.h    |  7 ++++++-
 lib/sisfile.cpp             | 15 ++++++++++++++-
 lib/sisfile.h               | 13 +++++++++++++
 sisinstall/sisinstaller.cpp | 23 +++--------------------
 5 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/lib/siscomponentrecord.cpp b/lib/siscomponentrecord.cpp
index 3507bce..ac5ba6d 100644
--- a/lib/siscomponentrecord.cpp
+++ b/lib/siscomponentrecord.cpp
@@ -35,12 +35,15 @@ SISComponentNameRecord::~SISComponentNameRecord()
 }
 
 SisRC
-SISComponentNameRecord::fillFrom(uint8_t* buf, int base, off_t len,
+SISComponentNameRecord::fillFrom(uint8_t* buf, int* basePos, off_t len,
 								 SISFile* sisFile)
 {
 	int n = sisFile->m_header.m_nlangs;
-	if (base + 8 + n * 4 * 2 > len)
+	int base = *basePos;
+	int entrySize = 8 + n * 4 * 2;
+	if (base + entrySize > len)
 		return SIS_TRUNCATED;
+	*basePos += entrySize;
 
 	uint8_t* p = buf + base;
 	int size = 0;
@@ -90,6 +93,19 @@ SISComponentNameRecord::fillFrom(uint8_t* buf, int base, off_t len,
 	return SIS_OK;
 }
 
+uint32_t
+SISComponentNameRecord::getLastEnd()
+{
+	uint32_t last = 0;
+	for (int i = 0; i < m_nameCount; ++i)
+		{
+		uint32_t pos = m_namePtrs[i] + m_nameLengths[i];
+		if (last < pos)
+			last = pos;
+		}
+	return last;
+}
+
 uint8_t*
 SISComponentNameRecord::getName(int no)
 {
diff --git a/lib/siscomponentrecord.h b/lib/siscomponentrecord.h
index f2bc734..1fc4ff3 100644
--- a/lib/siscomponentrecord.h
+++ b/lib/siscomponentrecord.h
@@ -50,7 +50,12 @@ public:
 	 * @param len The length of the buffer, for range checking.
 	 * @param sisFile The container sis file.
 	 */
-	SisRC fillFrom(uint8_t* buf, int base, off_t len, SISFile* sisFile);
+	SisRC fillFrom(uint8_t* buf, int* base, off_t len, SISFile* sisFile);
+
+	/**
+	 * Find out the end position for the last name in the file.
+	 */
+	uint32_t getLastEnd();
 
 	/**
 	 * Return the name for the given language.
diff --git a/lib/sisfile.cpp b/lib/sisfile.cpp
index df60695..97fde1d 100644
--- a/lib/sisfile.cpp
+++ b/lib/sisfile.cpp
@@ -49,6 +49,7 @@ SISFile::compareApp(SISFile* other)
 SisRC
 SISFile::fillFrom(uint8_t* buf, off_t len)
 {
+	m_end = 0;
 	int ix = 0;
 	m_buf = buf;
 	SisRC rc = m_header.fillFrom(buf, &ix, len);
@@ -77,6 +78,7 @@ SISFile::fillFrom(uint8_t* buf, off_t len)
 			return rc;
 			}
 		}
+	updateEnd(ix);
 
 	// Read requisites.
 	//
@@ -94,11 +96,14 @@ SISFile::fillFrom(uint8_t* buf, off_t len)
 			return rc;
 			}
 		}
+	updateEnd(ix);
 
 	// Read component names, by language.
 	//
 	ix = m_header.m_componentPtr;
-	rc = m_componentRecord.fillFrom(buf, ix, len, this);
+	rc = m_componentRecord.fillFrom(buf, &ix, len, this);
+	updateEnd(ix);
+	updateEnd(m_componentRecord.getLastEnd());
 	if (rc != SIS_OK)
 		{
 		printf(_("Problem reading the name record, rc = %d.\n"), rc);
@@ -125,6 +130,7 @@ SISFile::fillFrom(uint8_t* buf, off_t len)
 				return rc;
 			}
 		}
+	updateEnd(ix);
 
 	return SIS_OK;
 }
@@ -165,3 +171,10 @@ SISFile::setLanguage(int lang)
 	m_header.m_installationLanguage = lang;
 }
 
+void
+SISFile::updateEnd(uint32_t pos)
+{
+	if (m_end < pos)
+		m_end = pos;
+}
+
diff --git a/lib/sisfile.h b/lib/sisfile.h
index d74cc1c..bb33570 100644
--- a/lib/sisfile.h
+++ b/lib/sisfile.h
@@ -74,6 +74,15 @@ public:
 	 */
 	uint8_t* getName();
 
+	/**
+	 * Get the number of bytes that should be copied to the residual sis
+	 * file on the psion.
+	 */
+	uint32_t getResidualEnd()
+		{
+		return m_end;
+		}
+
 	void ownBuffer()
 		{
 		m_ownBuffer = true;
@@ -112,6 +121,10 @@ private:
 
 	uint8_t* m_buf;
 
+	uint32_t m_end;
+
+	void updateEnd(uint32_t pos);
+
 };
 
 #endif
diff --git a/sisinstall/sisinstaller.cpp b/sisinstall/sisinstaller.cpp
index e23baed..aed67f0 100644
--- a/sisinstall/sisinstaller.cpp
+++ b/sisinstall/sisinstaller.cpp
@@ -654,7 +654,6 @@ SISInstaller::run(SISFile* file, uint8_t* buf, off_t len, SISFile* parent)
 		fprintf(stderr, "Found %d files.\n", n);
 	m_drive = (parent == 0) ? 0 : parent->m_header.m_installationDrive;
 	int nCopiedFiles = 0;
-	int firstFile = -1;
 	m_lastSisFile = 0;
 	bool skipnext = false;
 	bool aborted = false;
@@ -662,19 +661,6 @@ SISInstaller::run(SISFile* file, uint8_t* buf, off_t len, SISFile* parent)
 		{
 		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[m_fileNo],
-			   fileRecord->m_fileLengths[m_fileNo]);
-#endif
-		int fileIx = fileRecord->getFilePtr(m_fileNo) - m_buf;
-		if ((firstFile == -1) || (firstFile >= fileIx))
-			firstFile = fileIx;
-
-//		 We can only do this if we search all files...
-//		 fileRecord->m_filePtrs[m_fileNo] + fileRecord->m_fileLengths[m_fileNo]
 
 		if (skipnext)
 			{
@@ -700,13 +686,10 @@ SISInstaller::run(SISFile* file, uint8_t* buf, off_t len, SISFile* parent)
 	m_file->setFiles(nCopiedFiles);
 	if (logLevel >= 1)
 		fprintf(stderr,
-				"Installed %d files of %d, cutting at offset max(%d,%d)\n",
+				"Installed %d files of %d, cutting at offset %d.\n",
 				m_file->m_header.m_installationFiles,
 				m_file->m_header.m_nfiles,
-				firstFile,
-				m_lastSisFile);
-	if (firstFile < m_lastSisFile)
-		firstFile = m_lastSisFile;
+				m_file->getResidualEnd());
 	if (nCopiedFiles == 0)
 		{
 		// There is no need to copy any uninstall information to the
@@ -728,7 +711,7 @@ SISInstaller::run(SISFile* file, uint8_t* buf, off_t len, SISFile* parent)
 	sprintf(resname, "C:\\System\\Install\\%.*s.sis", namelen, compName);
 	if (logLevel >= 1)
 		fprintf(stderr, "Creating residual sis file %s\n", resname);
-	copyBuf(buf, firstFile, resname);
+	copyBuf(buf, m_file->getResidualEnd(), resname);
 #if HAVE_LIBNEWT
 	if (m_useNewt)
 		{
-- 
cgit v1.2.3