1
0
Fork 0
forked from len0rd/rockbox

Add support for CAB archives to rbutil

Change-Id: Ia8b4953343caf8bc2b3c5a6cfd53c921c6d082b1
Reviewed-on: http://gerrit.rockbox.org/418
Reviewed-by: Dominik Riebeling <Dominik.Riebeling@gmail.com>
This commit is contained in:
Amaury Pouly 2013-03-11 18:57:11 +01:00 committed by Dominik Riebeling
parent 289acf3333
commit 6375c47f03
8 changed files with 350 additions and 14 deletions

View file

@ -0,0 +1,30 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2013 Amaury Pouly
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <QtCore>
#include <QDebug>
#include "archiveutil.h"
ArchiveUtil::ArchiveUtil(QObject* parent)
:QObject(parent)
{
}
ArchiveUtil::~ArchiveUtil()
{
}

View file

@ -0,0 +1,41 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2013 Amaury Pouly
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef ARCHIVEUTIL_H
#define ARCHIVEUTIL_H
#include <QtCore>
class ArchiveUtil : public QObject
{
Q_OBJECT
public:
ArchiveUtil(QObject* parent);
~ArchiveUtil();
virtual bool close(void) = 0;
virtual bool extractArchive(const QString& dest, QString file = "") = 0;
virtual QStringList files(void) = 0;
signals:
void logProgress(int, int);
void logItem(QString, int);
};
#endif

View file

@ -22,6 +22,7 @@
#include "bootloaderinstallbase.h"
#include "utils.h"
#include "ziputil.h"
#include "mspackutil.h"
#if defined(Q_OS_MACX)
#include <sys/param.h>
@ -215,11 +216,34 @@ 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)) {
ArchiveUtil *util = 0;
// try ZIP first
ZipUtil *zu = new ZipUtil(this);
if(zu->open(of))
{
emit logItem(tr("Zip file format detected"), LOGINFO);
QStringList contents = z.files();
util = zu;
}
else
delete zu;
// if ZIP failed, try CAB
if(util == 0)
{
MsPackUtil *msu = new MsPackUtil(this);
if(msu->open(of))
{
emit logItem(tr("CAB file format detected"), LOGINFO);
util = msu;
}
else
delete msu;
}
// check if the file set is in zip format
if(util) {
QStringList contents = util->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
@ -237,7 +261,7 @@ bool BootloaderInstallBase::setOfFile(QString of, QStringList blfile)
m_tempof.open();
m_offile = m_tempof.fileName();
m_tempof.close();
if(!z.extractArchive(m_offile, contents.at(j))) {
if(!util->extractArchive(m_offile, contents.at(j))) {
emit logItem(tr("Error extracting firmware from archive"), LOGERROR);
found = false;
break;
@ -249,12 +273,13 @@ bool BootloaderInstallBase::setOfFile(QString of, QStringList blfile)
if(!found) {
emit logItem(tr("Could not find firmware in archive"), LOGERROR);
}
delete util;
}
else {
m_offile = of;
found = true;
}
return found;
}

View file

@ -0,0 +1,163 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2013 Amaury Pouly
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <QtCore>
#include <QDebug>
#include "mspackutil.h"
#include "progressloggerinterface.h"
MsPackUtil::MsPackUtil(QObject* parent)
:ArchiveUtil(parent)
{
m_cabd = mspack_create_cab_decompressor(NULL);
m_cabinet = NULL;
if(!m_cabd)
qDebug() << "[MsPackUtil] CAB decompressor creation failed!";
}
MsPackUtil::~MsPackUtil()
{
close();
if(m_cabd)
mspack_destroy_cab_decompressor(m_cabd);
}
bool MsPackUtil::open(QString& mspackfile)
{
close();
if(m_cabd == NULL)
{
qDebug() << "[MsPackUtil] No CAB decompressor available: cannot open file!";
return false;
}
m_cabinet = m_cabd->search(m_cabd, QFile::encodeName(mspackfile).constData());
return m_cabinet != NULL;
}
bool MsPackUtil::close(void)
{
if(m_cabd && m_cabinet)
m_cabd->close(m_cabd, m_cabinet);
m_cabinet = NULL;
return true;
}
bool MsPackUtil::extractArchive(const QString& dest, QString file)
{
qDebug() << "[MsPackUtil] extractArchive" << dest << file;
if(!m_cabinet)
{
qDebug() << "[MsPackUtil] CAB file not open!";
return false;
}
// 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;
struct mscabd_file *f = m_cabinet->files;
if(f == NULL)
{
qDebug() << "[MsPackUtil] CAB doesn't contain file" << file;
return true;
}
bool found = false;
while(f)
{
QString name = QFile::decodeName(f->filename);
name.replace("\\", "/");
if(name.at(0) == '/')
name.remove(0, 1);
if(name == file || file.isEmpty())
{
QString path;
if(!singleoutfile.isEmpty())
path = singleoutfile;
else
path = dest + "/" + name;
// make sure the output path exists
if(!QDir().mkpath(QFileInfo(path).absolutePath()))
{
emit logItem(tr("Creating output path failed"), LOGERROR);
qDebug() << "[MsPackUtil] creating output path failed for:" << path;
emit logProgress(1, 1);
return false;
}
int ret = m_cabd->extract(m_cabd, f, QFile::encodeName(path).constData());
if(ret != MSPACK_ERR_OK)
{
emit logItem(tr("Error during CAB operation"), LOGERROR);
qDebug() << "[MsPackUtil] mspack error: " << ret << "(" << errorStringMsPack(ret) << ")";
emit logProgress(1, 1);
return false;
}
found = true;
}
f = f->next;
}
emit logProgress(1, 1);
return found;
}
QStringList MsPackUtil::files(void)
{
QStringList list;
if(!m_cabinet)
{
qDebug() << "[MsPackUtil] CAB file not open!";
return list;
}
struct mscabd_file *file = m_cabinet->files;
while(file)
{
QString name = QFile::decodeName(file->filename);
name.replace("\\", "/");
if(name.at(0) == '/')
name.remove(0, 1);
list.append(name);
file = file->next;
}
return list;
}
QString MsPackUtil::errorStringMsPack(int error) const
{
switch(error)
{
case MSPACK_ERR_OK: return "Ok";
case MSPACK_ERR_ARGS: return "Bad arguments";
case MSPACK_ERR_OPEN: return "Open error";
case MSPACK_ERR_READ: return "Read error";
case MSPACK_ERR_WRITE: return "Write error";
case MSPACK_ERR_SEEK: return "Seek error";
case MSPACK_ERR_NOMEMORY: return "Out of memory";
case MSPACK_ERR_SIGNATURE: return "Bad signature";
case MSPACK_ERR_DATAFORMAT: return "Bad data format";
case MSPACK_ERR_CHECKSUM: return "Checksum error";
case MSPACK_ERR_CRUNCH: return "Compression error";
case MSPACK_ERR_DECRUNCH: return "Decompression error";
default: return "Unknown";
}
}

View file

@ -0,0 +1,51 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2013 Amaury Pouly
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef MSPACKUTIL_H
#define MSPACKUTIL_H
#include <QtCore>
#include "archiveutil.h"
#include "mspack/mspack.h"
class MsPackUtil : public ArchiveUtil
{
Q_OBJECT
public:
// archive types can be ORed
MsPackUtil(QObject* parent);
~MsPackUtil();
bool open(QString& mspackfile);
virtual bool close(void);
virtual bool extractArchive(const QString& dest, QString file = "");
virtual QStringList files(void);
signals:
void logProgress(int, int);
void logItem(QString, int);
private:
QString errorStringMsPack(int error) const;
struct mscab_decompressor* m_cabd;
struct mscabd_cabinet *m_cabinet;
};
#endif

View file

@ -26,7 +26,7 @@
#include "quazip/quazipfileinfo.h"
ZipUtil::ZipUtil(QObject* parent) : QObject(parent)
ZipUtil::ZipUtil(QObject* parent) : ArchiveUtil(parent)
{
m_zip = NULL;
}
@ -74,7 +74,7 @@ bool ZipUtil::close(void)
//! single file.
//! @brief file file to extract from archive, full archive if empty.
//! @return true on success, false otherwise
bool ZipUtil::extractArchive(QString& dest, QString file)
bool ZipUtil::extractArchive(const QString& dest, QString file)
{
qDebug() << "[ZipUtil] extractArchive" << dest << file;
bool result = true;

View file

@ -20,11 +20,12 @@
#define ZIPUTIL_H
#include <QtCore>
#include "archiveutil.h"
#include "quazip/quazip.h"
#include "quazip/quazipfile.h"
#include "quazip/quazipfileinfo.h"
class ZipUtil : public QObject
class ZipUtil : public ArchiveUtil
{
Q_OBJECT
@ -32,12 +33,12 @@ class ZipUtil : public QObject
ZipUtil(QObject* parent);
~ZipUtil();
bool open(QString& zipfile, QuaZip::Mode mode = QuaZip::mdUnzip);
bool close(void);
bool extractArchive(QString& dest, QString file = "");
virtual bool close(void);
virtual bool extractArchive(const QString& dest, QString file = "");
bool appendDirToArchive(QString& source, QString& basedir);
bool appendFileToArchive(QString& file, QString& basedir);
qint64 totalUncompressedSize(unsigned int clustersize = 0);
QStringList files(void);
virtual QStringList files(void);
signals:
void logProgress(int, int);

View file

@ -79,7 +79,14 @@ SOURCES += \
gui/comboboxviewdelegate.cpp \
gui/selectiveinstallwidget.cpp \
gui/backupdialog.cpp \
gui/changelog.cpp
gui/changelog.cpp \
mspack/cabd.c \
mspack/lzxd.c \
mspack/mszipd.c \
mspack/qtmd.c \
mspack/system-mspack.c \
base/mspackutil.cpp \
base/archiveutil.cpp \
HEADERS += \
@ -157,7 +164,25 @@ HEADERS += \
gui/comboboxviewdelegate.h \
gui/selectiveinstallwidget.h \
gui/backupdialog.h \
gui/changelog.h
gui/changelog.h \
mspack/cab.h \
mspack/chm.h \
mspack/des.h \
mspack/hlp.h \
mspack/kwaj.h \
mspack/lit.h \
mspack/lzss.h \
mspack/lzx.h \
mspack/mspack.h \
mspack/mszip.h \
mspack/qtm.h \
mspack/readbits.h \
mspack/readhuff.h \
mspack/sha.h \
mspack/system-mspack.h \
mspack/szdd.h \
base/mspackutil.h \
base/archiveutil.h \
FORMS += \