From b45cc0a13a20e88546cd7a536f09979edf8353a1 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Sun, 15 Jan 2012 23:20:17 +0100 Subject: 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 --- rbutil/rbutilqt/base/bootloaderinstallbase.cpp | 41 ++++++++++++++++++++++++++ rbutil/rbutilqt/base/bootloaderinstallbase.h | 4 +-- rbutil/rbutilqt/base/ziputil.cpp | 28 ++++++++++++++++-- rbutil/rbutilqt/base/ziputil.h | 4 +-- rbutil/rbutilqt/rbutilqt.cpp | 23 +++++++++------ 5 files changed, 84 insertions(+), 16 deletions(-) diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.cpp b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp index 750e33bef8..7941f24309 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallbase.cpp +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.cpp @@ -31,6 +31,7 @@ #include "bootloaderinstallmpio.h" #include "bootloaderinstallimx.h" #include "utils.h" +#include "ziputil.h" #if defined(Q_OS_MACX) #include @@ -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; +} diff --git a/rbutil/rbutilqt/base/bootloaderinstallbase.h b/rbutil/rbutilqt/base/bootloaderinstallbase.h index 8198d54e76..0e970c4af6 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallbase.h +++ b/rbutil/rbutilqt/base/bootloaderinstallbase.h @@ -60,8 +60,7 @@ class BootloaderInstallBase : public QObject { m_blurl = u; } void setLogfile(QString f) { m_logfile = f; } - void setOfFile(QString f) - {m_offile = f;} + bool setOfFile(QString of, QStringList blfile); //! returns a port Install Hint or empty if there is none //! 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 QUrl m_blurl; //! bootloader download URL 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 QString m_offile; //! path to the offile #if defined(Q_OS_MACX) diff --git a/rbutil/rbutilqt/base/ziputil.cpp b/rbutil/rbutilqt/base/ziputil.cpp index 481ad4c2ae..b9218a70bc 100644 --- a/rbutil/rbutilqt/base/ziputil.cpp +++ b/rbutil/rbutilqt/base/ziputil.cpp @@ -70,10 +70,13 @@ bool ZipUtil::close(void) //! @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 -bool ZipUtil::extractArchive(QString& dest) +bool ZipUtil::extractArchive(QString& dest, QString file) { + qDebug() << "[ZipUtil] extractArchive" << dest << file; bool result = true; if(!m_zip) { return false; @@ -81,6 +84,16 @@ bool ZipUtil::extractArchive(QString& dest) QuaZipFile *currentFile = new QuaZipFile(m_zip); int entries = m_zip->getEntriesCount(); 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()) { ++current; @@ -88,7 +101,16 @@ bool ZipUtil::extractArchive(QString& dest) if(m_zip->getCurrentFileName().split("/").last() == "") 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); // make sure the output path exists if(!QDir().mkpath(QFileInfo(outfilename).absolutePath())) { diff --git a/rbutil/rbutilqt/base/ziputil.h b/rbutil/rbutilqt/base/ziputil.h index 9cbb67488a..a6b0a8ca9c 100644 --- a/rbutil/rbutilqt/base/ziputil.h +++ b/rbutil/rbutilqt/base/ziputil.h @@ -31,9 +31,9 @@ class ZipUtil : public QObject public: ZipUtil(QObject* parent); ~ZipUtil(); - bool open(QString& zipfile, QuaZip::Mode mode); + bool open(QString& zipfile, QuaZip::Mode mode = QuaZip::mdUnzip); bool close(void); - bool extractArchive(QString& dest); + bool extractArchive(QString& dest, QString file = ""); bool appendDirToArchive(QString& source, QString& basedir); bool appendFileToArchive(QString& file, QString& basedir); qint64 totalUncompressedSize(unsigned int clustersize = 0); diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp index 403d13a760..958550e880 100644 --- a/rbutil/rbutilqt/rbutilqt.cpp +++ b/rbutil/rbutilqt/rbutilqt.cpp @@ -708,7 +708,14 @@ void RbUtilQt::installBootloader() logger->setFinished(); 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. QStringList blfile = SystemInfo::value(SystemInfo::CurBootloaderFile).toStringList(); QStringList blfilepath; @@ -788,16 +795,14 @@ void RbUtilQt::installBootloader() m_error = true; 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. if(!backupDestination.isEmpty()) { if(!bl->backup(backupDestination)) { -- cgit v1.2.3