Support reading OF files from zip.

Several devices require the original firmware to be able installing the
bootloader. Most vendors distribute the firmware file in zip format. Extend
reading the original firmware file to support reading the file from the zip
directly instead of requiring the user to separately extract it.

Change-Id: Ic4e89053456d8f7d6adc294f6657aceddbc354ba
This commit is contained in:
Dominik Riebeling 2012-01-15 23:20:17 +01:00
parent 66c3086ae5
commit b45cc0a13a
5 changed files with 84 additions and 16 deletions

View file

@ -31,6 +31,7 @@
#include "bootloaderinstallmpio.h" #include "bootloaderinstallmpio.h"
#include "bootloaderinstallimx.h" #include "bootloaderinstallimx.h"
#include "utils.h" #include "utils.h"
#include "ziputil.h"
#if defined(Q_OS_MACX) #if defined(Q_OS_MACX)
#include <sys/param.h> #include <sys/param.h>
@ -320,3 +321,43 @@ void BootloaderInstallBase::setBlFile(QStringList sl)
} }
} }
bool BootloaderInstallBase::setOfFile(QString of, QStringList blfile)
{
bool found = false;
ZipUtil z(this);
// check if the file set is in zip format
if(z.open(of)) {
emit logItem(tr("Zip file format detected"), LOGINFO);
QStringList contents = z.files();
qDebug() << "[BootloaderInstallBase] archive contains:" << contents;
for(int i = 0; i < blfile.size(); ++i) {
// strip any path, we don't know the structure in the zip
QString f = QFileInfo(blfile.at(i)).fileName();
qDebug() << "[BootloaderInstallBase] searching archive for" << f;
int index = contents.indexOf(f); // FIXME: support files in folders
if(index >= 0) {
found = true;
emit logItem(tr("Extracting firmware %1 from archive")
.arg(f), LOGINFO);
// store in class temporary file
m_tempof.open();
m_offile = m_tempof.fileName();
m_tempof.close();
if(!z.extractArchive(m_offile, contents.at(index))) {
emit logItem(tr("Error extracting firmware from archive"), LOGERROR);
found = false;
break;
}
}
}
if(!found) {
emit logItem(tr("Could not find firmware in archive"), LOGERROR);
}
}
else {
m_offile = of;
found = true;
}
return found;
}

View file

@ -60,8 +60,7 @@ class BootloaderInstallBase : public QObject
{ m_blurl = u; } { m_blurl = u; }
void setLogfile(QString f) void setLogfile(QString f)
{ m_logfile = f; } { m_logfile = f; }
void setOfFile(QString f) bool setOfFile(QString of, QStringList blfile);
{m_offile = f;}
//! returns a port Install Hint or empty if there is none //! returns a port Install Hint or empty if there is none
//! static and in the base class, so the installer classes dont need to //! static and in the base class, so the installer classes dont need to
@ -90,6 +89,7 @@ class BootloaderInstallBase : public QObject
QString m_logfile; //! file for installation log QString m_logfile; //! file for installation log
QUrl m_blurl; //! bootloader download URL QUrl m_blurl; //! bootloader download URL
QTemporaryFile m_tempfile; //! temporary file for download QTemporaryFile m_tempfile; //! temporary file for download
QTemporaryFile m_tempof; //! temporary file for OF extracted from archive
QDateTime m_blversion; //! download timestamp used for version information QDateTime m_blversion; //! download timestamp used for version information
QString m_offile; //! path to the offile QString m_offile; //! path to the offile
#if defined(Q_OS_MACX) #if defined(Q_OS_MACX)

View file

@ -70,10 +70,13 @@ bool ZipUtil::close(void)
//! @brief extract currently opened archive //! @brief extract currently opened archive
//! @brief dest path to extract archive to //! @brief dest path to extract archive to, can be filename when extracting a
//! single file.
//! @brief file file to extract from archive, full archive if empty.
//! @return true on success, false otherwise //! @return true on success, false otherwise
bool ZipUtil::extractArchive(QString& dest) bool ZipUtil::extractArchive(QString& dest, QString file)
{ {
qDebug() << "[ZipUtil] extractArchive" << dest << file;
bool result = true; bool result = true;
if(!m_zip) { if(!m_zip) {
return false; return false;
@ -81,6 +84,16 @@ bool ZipUtil::extractArchive(QString& dest)
QuaZipFile *currentFile = new QuaZipFile(m_zip); QuaZipFile *currentFile = new QuaZipFile(m_zip);
int entries = m_zip->getEntriesCount(); int entries = m_zip->getEntriesCount();
int current = 0; int current = 0;
// construct the filename when extracting a single file from an archive.
// if the given destination is a full path use it as output name,
// otherwise use it as path to place the file as named in the archive.
QString singleoutfile;
if(!file.isEmpty() && QFileInfo(dest).isDir()) {
singleoutfile = dest + "/" + file;
}
else if(!file.isEmpty()){
singleoutfile = dest;
}
for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile()) for(bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile())
{ {
++current; ++current;
@ -88,7 +101,16 @@ bool ZipUtil::extractArchive(QString& dest)
if(m_zip->getCurrentFileName().split("/").last() == "") if(m_zip->getCurrentFileName().split("/").last() == "")
continue; continue;
QString outfilename = dest + "/" + m_zip->getCurrentFileName(); QString outfilename;
if(!singleoutfile.isEmpty()
&& QFileInfo(m_zip->getCurrentFileName()).fileName() == file) {
outfilename = singleoutfile;
}
else if(singleoutfile.isEmpty()) {
outfilename = dest + "/" + m_zip->getCurrentFileName();
}
if(outfilename.isEmpty())
continue;
QFile outputFile(outfilename); QFile outputFile(outfilename);
// make sure the output path exists // make sure the output path exists
if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) { if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) {

View file

@ -31,9 +31,9 @@ class ZipUtil : public QObject
public: public:
ZipUtil(QObject* parent); ZipUtil(QObject* parent);
~ZipUtil(); ~ZipUtil();
bool open(QString& zipfile, QuaZip::Mode mode); bool open(QString& zipfile, QuaZip::Mode mode = QuaZip::mdUnzip);
bool close(void); bool close(void);
bool extractArchive(QString& dest); bool extractArchive(QString& dest, QString file = "");
bool appendDirToArchive(QString& source, QString& basedir); bool appendDirToArchive(QString& source, QString& basedir);
bool appendFileToArchive(QString& file, QString& basedir); bool appendFileToArchive(QString& file, QString& basedir);
qint64 totalUncompressedSize(unsigned int clustersize = 0); qint64 totalUncompressedSize(unsigned int clustersize = 0);

View file

@ -708,7 +708,14 @@ void RbUtilQt::installBootloader()
logger->setFinished(); logger->setFinished();
return; return;
} }
// the bootloader install class does NOT use any GUI stuff.
// All messages are passed via signals.
connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished()));
connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
// set bootloader filename. Do this now as installed() needs it. // set bootloader filename. Do this now as installed() needs it.
QStringList blfile = SystemInfo::value(SystemInfo::CurBootloaderFile).toStringList(); QStringList blfile = SystemInfo::value(SystemInfo::CurBootloaderFile).toStringList();
QStringList blfilepath; QStringList blfilepath;
@ -788,16 +795,14 @@ void RbUtilQt::installBootloader()
m_error = true; m_error = true;
return; return;
} }
bl->setOfFile(offile); if(!bl->setOfFile(offile, blfile)) {
logger->addItem(tr("Error reading firmware file"), LOGERROR);
logger->setFinished();
m_error = true;
return;
}
} }
// the bootloader install class does NOT use any GUI stuff.
// All messages are passed via signals.
connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished()));
connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
// start install. // start install.
if(!backupDestination.isEmpty()) { if(!backupDestination.isEmpty()) {
if(!bl->backup(backupDestination)) { if(!bl->backup(backupDestination)) {