From e8f669a346a359a038118a0ad588db7b32275069 Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Thu, 12 Nov 2015 12:55:12 +0100 Subject: Remove unused update tools Change-Id: I3bf3863e76d58ba6dc42947c337451e1d7fc4ee5 Reviewed-by: Gatis Paeglis --- src/b2qt-update-application/.gitignore | 4 - .../b2qt-update-application.pro | 35 --- src/b2qt-update-application/filewrapper.cpp | 53 ---- src/b2qt-update-application/filewrapper.h | 40 --- src/b2qt-update-application/main.cpp | 204 -------------- src/b2qt-update-application/tar.cpp | 309 --------------------- src/b2qt-update-application/tar.h | 99 ------- src/b2qt-update-application/update.cpp | 202 -------------- src/b2qt-update-application/update.h | 50 ---- src/b2qt-update-util/.gitignore | 4 - src/b2qt-update-util/b2qt-update-util.pro | 23 -- src/b2qt-update-util/main.cpp | 144 ---------- src/src.pro | 3 +- 13 files changed, 1 insertion(+), 1169 deletions(-) delete mode 100644 src/b2qt-update-application/.gitignore delete mode 100644 src/b2qt-update-application/b2qt-update-application.pro delete mode 100644 src/b2qt-update-application/filewrapper.cpp delete mode 100644 src/b2qt-update-application/filewrapper.h delete mode 100644 src/b2qt-update-application/main.cpp delete mode 100644 src/b2qt-update-application/tar.cpp delete mode 100644 src/b2qt-update-application/tar.h delete mode 100644 src/b2qt-update-application/update.cpp delete mode 100644 src/b2qt-update-application/update.h delete mode 100644 src/b2qt-update-util/.gitignore delete mode 100644 src/b2qt-update-util/b2qt-update-util.pro delete mode 100644 src/b2qt-update-util/main.cpp (limited to 'src') diff --git a/src/b2qt-update-application/.gitignore b/src/b2qt-update-application/.gitignore deleted file mode 100644 index d2a78c0..0000000 --- a/src/b2qt-update-application/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -Makefile -b2qt-update-application -moc_*.cpp -*.o diff --git a/src/b2qt-update-application/b2qt-update-application.pro b/src/b2qt-update-application/b2qt-update-application.pro deleted file mode 100644 index 51fc06f..0000000 --- a/src/b2qt-update-application/b2qt-update-application.pro +++ /dev/null @@ -1,35 +0,0 @@ -CONFIG += c++11 -QT = core network -SOURCES += \ - main.cpp \ - tar.cpp \ - filewrapper.cpp \ - update.cpp - -HEADERS += \ - tar.h \ - filewrapper.h \ - update.h - -LIBS += -lcrypto -INSTALLS += target -target.path = /usr/bin - -# Find out git hash -unix:system(which git):HAS_GIT=TRUE -win32:system(where git.exe):HAS_GIT=TRUE -contains(HAS_GIT, TRUE) { - GIT_HASH=$$system(git log -1 --format=%H) - !system(git diff-index --quiet HEAD): GIT_HASH="$$GIT_HASH-dirty" - GIT_VERSION=$$system(git describe --tags --exact-match) - isEmpty(GIT_VERSION) : GIT_VERSION="unknown" -} else { - GIT_HASH="unknown" - GIT_VERSION="unknown" -} - -isEmpty(GIT_VERSION) : error("No suitable tag found") -isEmpty(GIT_HASH) : error("No hash available") - -DEFINES+="GIT_HASH=\\\"$$GIT_HASH\\\"" -DEFINES+="GIT_VERSION=\\\"$$GIT_VERSION\\\"" diff --git a/src/b2qt-update-application/filewrapper.cpp b/src/b2qt-update-application/filewrapper.cpp deleted file mode 100644 index 6b4a759..0000000 --- a/src/b2qt-update-application/filewrapper.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include "filewrapper.h" -#include -#include - -FileWrapper::FileWrapper(const QString &fileName, QObject *parent) - : QFile(fileName, parent) - , mTimer(new QTimer(this)) -{ - mTimer->setInterval(50); - connect(mTimer, &QTimer::timeout, this, &FileWrapper::emitReadyRead); -} - -FileWrapper::~FileWrapper() -{ -} - -bool FileWrapper::open(OpenMode mode) -{ - bool rc = QFile::open(mode); - if (rc) { - mTimer->start(); - } - return rc; -} - -void FileWrapper::emitReadyRead() -{ - if (!atEnd()) { - emit readyRead(); - } else { - mTimer->stop(); - close(); - } -} diff --git a/src/b2qt-update-application/filewrapper.h b/src/b2qt-update-application/filewrapper.h deleted file mode 100644 index fc8a977..0000000 --- a/src/b2qt-update-application/filewrapper.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#ifndef FILEWRAPPER_H -#define FILEWRAPPER_H - -#include -class QTimer; - -class FileWrapper : public QFile -{ - Q_OBJECT - -public: - FileWrapper(const QString &fileName, QObject *parent = 0); - virtual ~FileWrapper(); - bool open(OpenMode mode); - -private: - void emitReadyRead(); - QTimer *mTimer; -}; - -#endif // FILEWRAPPER_H diff --git a/src/b2qt-update-application/main.cpp b/src/b2qt-update-application/main.cpp deleted file mode 100644 index 353edd9..0000000 --- a/src/b2qt-update-application/main.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "update.h" -#include "filewrapper.h" - -#define UPDATE_MOUNTPOINT "/mnt/update" - -QStringList mounts; - -void cleanup() -{ - foreach (const QString &m, mounts) { - QProcess::execute("umount", QStringList() << m); - } - mounts.clear(); -} - -void error(const QString &message) -{ - fprintf(stderr, "%s\n", message.toLocal8Bit().constData()); - cleanup(); - exit(1); -} - -bool execute(const QString &binary, const QStringList &arguments) -{ - int rc = QProcess::execute(binary, arguments); - if (rc != 0) - error("Failed to execute command '" + binary + " " + arguments.join(" ")); - return rc == 0; -} - -bool mount(const QString &device, const QString &mountpoint, const QString &arguments = QString()) -{ - QStringList tmp; - if (!arguments.isEmpty()) - tmp << "-o" << arguments; - - if (!execute("mount", QStringList() << tmp << device << mountpoint)) - return false; - - if (!arguments.contains("remount")) - mounts << mountpoint; - return true; -} - -QByteArray readAll(const QString &fileName) -{ - QFile f(fileName); - if (!f.open(QFile::ReadOnly)) { - qWarning() << "Could not read" << fileName; - return QByteArray(); - } - - return f.readAll(); -} - -bool writeAll(const QString &fileName, const QByteArray &content) -{ - QFile f(fileName); - if (!f.open(QFile::WriteOnly)) { - qWarning() << "Could not write" << fileName; - return false; - } - if (f.write(content) != content.size()) { - qWarning() << "write size mismatch"; - return false; - } - f.close(); - return true; -} - -QStringList find_usb_storage() -{ - QStringList rc; - QDir d("/sys/dev/block"); - - foreach (QString s, d.entryList()) { - QFileInfo fi(d.absoluteFilePath(s)); - QString path = fi.canonicalFilePath(); - if (path.contains("/usb")) - rc += path.mid(path.lastIndexOf('/')); - } - return rc; -} - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - printf("Version %s, SHA1 %s\n", GIT_VERSION, GIT_HASH); - - mount(QString(), "/", "remount,rw"); - execute("mkdir", QStringList() << "-p" << "/mnt/boot"); - execute("mkdir", QStringList() << "-p" << "/mnt/root"); - execute("mkdir", QStringList() << "-p" << UPDATE_MOUNTPOINT); - mount("/dev/mmcblk0p1", "/mnt/boot", "ro"); - - QByteArray update_state = readAll("/mnt/boot/update/state").trimmed(); - if (update_state.isEmpty()) - qFatal("Update state is empty"); - - if (update_state == "v") - qFatal("Update state is 'valid', this should not happen"); - else if (update_state == "t") - qDebug() << "Update state is 'testing', this should not happen"; - else if (update_state == "u") - qDebug() << "Update state is 'update'"; - else - qDebug() << "Unknown update state:" << update_state; - - QStringList usbsticks = find_usb_storage(); - - qDebug() << "Found USB storage devices:" << usbsticks; - - bool update_found = false; - foreach (QString s, usbsticks) { - if (QProcess::execute("mount", QStringList() << "-o" << "ro" << "/dev/" + s << UPDATE_MOUNTPOINT) == 0) { - mounts << UPDATE_MOUNTPOINT; - qDebug() << "mount successful"; - - if (QFile::exists(UPDATE_MOUNTPOINT "/b2qt-update")) { - qDebug() << "update found"; - update_found = true; - break; - } - execute("umount", QStringList() << UPDATE_MOUNTPOINT); - mounts.removeAt(mounts.lastIndexOf(UPDATE_MOUNTPOINT)); - qDebug() << "no update found"; - } else { - qDebug() << "mount of" << s << "failed"; - } - } - - Update update; - - if (update_found) { - FileWrapper *fw = new FileWrapper(UPDATE_MOUNTPOINT "/b2qt-update", &update); - if (!fw->open(QFile::ReadOnly)) - qFatal("Failed to open update"); - qDebug() << "Starting update from USB"; - update.setDevice(fw); - } else { - QByteArray update_source = readAll("/mnt/boot/update/source").trimmed(); - if (update_source.isEmpty()) { - execute("umount", QStringList() << "/mnt/boot"); // FIXME - mounts.removeAt(mounts.lastIndexOf("/mnt/boot")); - qFatal("Update source is empty"); - } - - execute("udhcpc", QStringList() << "-i" << "eth0"); - - QNetworkAccessManager *manager = new QNetworkAccessManager(0); - QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(update_source))); - reply->setReadBufferSize(2000000); // 2 MB - - QObject::connect(reply, (void (QNetworkReply::*)(QNetworkReply::NetworkError))&QNetworkReply::error, - [](QNetworkReply::NetworkError e){qDebug() << "network error" << e;}); - QObject::connect(reply, &QNetworkReply::sslErrors, - [](QList){ qDebug() << "ssl errors";}); - - qDebug() << "Starting update from Internet" << update_source; - update.setDevice(reply); - } - - app.exec(); - - qDebug() << "unmount"; - cleanup(); - - qDebug() << "sync"; - sync(); - qDebug() << "reboot; waiting 2 seconds"; - sleep(2); - reboot(RB_AUTOBOOT); - return 0; -} diff --git a/src/b2qt-update-application/tar.cpp b/src/b2qt-update-application/tar.cpp deleted file mode 100644 index c0369ff..0000000 --- a/src/b2qt-update-application/tar.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include "tar.h" -#include -#include -#include -#include - -static bool isZeroed(const char *ptr, unsigned int size) -{ - while (size) { - if (*ptr) { - return false; - } - ++ptr; - --size; - } - return true; -} - -Tar::Tar(QIODevice *source) - : QObject(source) - , mSource(source) - , mSize(0) - , mRemainingSize(0) - , mRemainingFileBytes(0) - , mProcess(0) - , mState(WaitForHeader) - , x509(0) - , mdctx(0) -{ - // Initialize table with all digests in order to look them up by string later - OpenSSL_add_all_digests(); - - connect(source, &QIODevice::readyRead, this, &Tar::dataIncoming); - connect(source, &QIODevice::aboutToClose, this, &Tar::aboutToClose); -} - -Tar::~Tar() -{ - if (x509) - X509_free(x509); - x509 = 0; - if (mdctx) - EVP_MD_CTX_destroy(mdctx); - mdctx = 0; -} - -const QByteArray &Tar::currentContent() const -{ - return mContent; -} - -unsigned long Tar::currentSize() const -{ - return mSize; -} - -QString Tar::currentFileName() const -{ - if (mHeader.name[sizeof(mHeader.name)-1]) - return QString::fromLatin1(mHeader.name, sizeof(mHeader.name)); - else - return QString::fromLatin1(mHeader.name); -} - -void Tar::dataIncoming() -{ - while (mSource->bytesAvailable() > 512) { - - if (mState == WaitForHeader) { - if (mSource->bytesAvailable() < 512) - return; - if (mSource->read((char*)&mHeader, sizeof(mHeader)) != sizeof(mHeader)) - qFatal("Tar read error"); - if (isZeroed((char*)&mHeader, sizeof(mHeader))) { - qDebug() << "Zero Tar block"; - qDebug() << "Bytes left" << mSource->bytesAvailable(); - mSource->close(); - return; - } - if (mHeader.name[0] == 0) - qFatal("Header starts with 0"); - - mSize = QString::fromLatin1(mHeader.size, sizeof(mHeader.size)-1).toULongLong(0, 8); - mRemainingFileBytes = mSize; - mRemainingSize = mSize; - if (mSize % 512) // padding to 512 byte block - mRemainingSize += 512 - (mSize % 512); - - if (mSize == 0) { - qFatal("Size of file is 0"); - } - - mState = WaitForDecision; - qDebug() << "Started file" << currentFileName() << mSize; - if (x509) - setupMDContext(); - emit startingFile(currentFileName()); - } else if (mState == WaitForDecision) { - return; - } else if (mState == Extract) { - QByteArray ba; - - quint64 bytesToHandle = mRemainingSize; - - if (mSource->bytesAvailable() < mRemainingSize) - bytesToHandle = mSource->bytesAvailable(); - if (bytesToHandle > 60000) - bytesToHandle = 60000; - ba = mSource->read(bytesToHandle); - - updateMDContext(ba); - mProcess->write(ba); - mProcess->waitForBytesWritten(); - mRemainingSize -= ba.size(); - // do not return - } else if (mState == Receive) { - QByteArray ba; - - if (mSource->bytesAvailable() > mRemainingSize) - ba = mSource->read(mRemainingSize); - else - ba = mSource->readAll(); - updateMDContext(ba); - mContent += ba; - mRemainingSize -= ba.size(); - if (mContent.size() > mSize) - mContent.resize(mSize); - // do not return - } else if (mState == Skip) { - QByteArray ba; - - if (mSource->bytesAvailable() > mRemainingSize) { - ba = mSource->read(mRemainingSize); - } else { - ba = mSource->readAll(); - } - updateMDContext(ba); - mRemainingSize -= ba.size(); - // drop data - // do not return - } else if (mState == WaitForContinue) { - return; - } else { - qFatal("Unknown tar state"); - } - - if (mState != WaitForContinue && mState != WaitForHeader && mRemainingSize == 0) { - if (mState == Extract) { - qDebug() << "End tar process"; - // please tar - // it needs 2 zeroed blocks - char buffer[sizeof(mHeader)]; - memset(buffer, 0, sizeof(buffer)); - mProcess->write(buffer, sizeof(buffer)); - mProcess->write(buffer, sizeof(buffer)); - mProcess->waitForBytesWritten(); - mProcess->closeWriteChannel(); - mProcess->waitForFinished(-1); - mProcess->deleteLater(); - mProcess = 0; - } - mState = WaitForContinue; - - emit(endingFile(currentFileName())); - } - - } -} - -void Tar::extractContent(const QString &targetDir) -{ - if (mState == WaitForDecision) { - qDebug() << Q_FUNC_INFO; - mState = Extract; - delete mProcess; - mProcess = new QProcess(this); - mProcess->setProcessChannelMode(QProcess::ForwardedChannels); - mProcess->start("tar", QStringList() << "xvf" << "-" << "-C" << targetDir); - - // if we want to extract a file directly, the header needs to be passed to tar - if (!currentFileName().endsWith(".tar")) - mProcess->write((const char*)&mHeader, sizeof(mHeader)); - } -} - -void Tar::receiveContent() -{ - if (mState == WaitForDecision) - mState = Receive; -} - -void Tar::skipContent() -{ - if (mState == WaitForDecision) - mState = Skip; -} - -void Tar::continueContent() -{ - if (mState == WaitForContinue) { - mState = WaitForHeader; - mSize = 0; - mContent.clear(); - delete mProcess; - mProcess = 0; - } else - qDebug() << "Called" << Q_FUNC_INFO << "in wrong state"; -} - -void Tar::aboutToClose() -{ - if (mState != WaitForHeader) { - qWarning() << "unexpected close"; - } - emit finished(); -} - -bool Tar::setVerificationData(const QString &certificateFileName, const QString &mdType) -{ - if (x509) - qFatal("Setting key twice"); - - // Load key from file - BIO *i = BIO_new(BIO_s_file()); - BIO *o = BIO_new_fp(stdout,BIO_NOCLOSE); - - if ((BIO_read_filename(i, certificateFileName.toLatin1().constData()) <= 0) || - ((x509 = PEM_read_bio_X509_AUX(i, NULL, NULL, NULL)) == NULL)) { - qWarning() << "Invalid certificate, failed to read file" << certificateFileName; - return false; - } - // Showing used certificate - X509_print_ex(o, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT); - BIO_free(i); - BIO_free(o); - qDebug() << "Using verification key:" << certificateFileName; - - md = EVP_get_digestbyname(mdType.toLatin1().constData()); - if (md == NULL) - qFatal("Digest not found"); - return true; -} - -void Tar::setupMDContext() -{ - if (mdctx) - EVP_MD_CTX_destroy(mdctx); - if (!(mdctx = EVP_MD_CTX_create())) - qFatal("EVP_MD_CTX_create failed"); - - EVP_PKEY *key = X509_get_pubkey(x509); - if (key == NULL) { - qFatal("X509_get_pubkey failed"); - } - - if (md == NULL) - qFatal("No digest set"); - - if (1 != EVP_DigestVerifyInit(mdctx, NULL, md, NULL, key)) - qFatal("EVP_DigestVerifyInit failed"); -} - -void Tar::updateMDContext(QByteArray data) -{ - if (mRemainingFileBytes == 0) - qFatal("Trying to update MD context when no more bytes are expected"); - - if (mRemainingFileBytes < data.size()) - data = data.left(mRemainingFileBytes); - mRemainingFileBytes -= data.size(); - - if (!mdctx) - return; - - if (1 != EVP_DigestVerifyUpdate(mdctx, data.constData(), data.size())) - qFatal("EVP_DigestVerifyUpdate failed"); -} - -bool Tar::checkSignature(const QByteArray &signature) -{ - return 1 == EVP_DigestVerifyFinal(mdctx, (unsigned char*)signature.constData(), signature.size()); -} - -bool Tar::verifyCurrentContent(const QByteArray &signature) -{ - setupMDContext(); - if (1 != EVP_DigestVerifyUpdate(mdctx, mContent.constData(), mContent.size())) - qFatal("EVP_DigestVerifyUpdate failed"); - return checkSignature(signature); -} diff --git a/src/b2qt-update-application/tar.h b/src/b2qt-update-application/tar.h deleted file mode 100644 index e3ca1d2..0000000 --- a/src/b2qt-update-application/tar.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#ifndef TAR_H -#define TAR_H - -#include -#include -class QIODevice; -class QProcess; -#define USTAR_HEADER_SIZE 512 - -struct ustar_header -{ -char name[100]; /* File name. Null-terminated if room. */ -char mode[8]; /* Permissions as octal string. */ -char uid[8]; /* User ID as octal string. */ -char gid[8]; /* Group ID as octal string. */ -char size[12]; /* File size in bytes as octal string. */ -char mtime[12]; /* Modification time in seconds from Jan 1, 1970, as octal string. */ -char chksum[8]; /* Sum of octets in header as octal string. */ -char typeflag; /* An enum ustar_type value. */ -char linkname[100]; /* Name of link target. Null-terminated if room. */ -char magic[6]; /* "ustar\0" */ -char version[2]; /* "00" */ -char uname[32]; /* User name, always null-terminated. */ -char gname[32]; /* Group name, always null-terminated. */ -char devmajor[8]; /* Device major number as octal string. */ -char devminor[8]; /* Device minor number as octal string. */ -char prefix[155]; /* Prefix to file name. Null-terminated if room. */ -char padding[12]; /* Pad to 512 bytes. */ -} __attribute__((packed)); - -class Tar : public QObject -{ - Q_OBJECT - -public: - Tar(QIODevice *source); - virtual ~Tar(); - - const QByteArray ¤tContent() const; - unsigned long currentSize() const; - QString currentFileName() const; - - enum State { WaitForHeader, WaitForDecision, Extract, Receive, Skip, WaitForContinue}; - bool setVerificationData(const QString &certificateFileName, const QString &md); - bool checkSignature(const QByteArray &signature); - bool verifyCurrentContent(const QByteArray &signature); - -signals: - void startingFile(const QString &name); - void endingFile(const QString &name); - void finished(); - -public slots: - void extractContent(const QString &targetDir); - void receiveContent(); - void skipContent(); - void dataIncoming(); - void continueContent(); - -private slots: - void aboutToClose(); - -private: - void setupMDContext(); - void updateMDContext(QByteArray); - - QIODevice *mSource; - qint64 mSize; - qint64 mRemainingSize; // File Size + Padding - qint64 mRemainingFileBytes; // File Size without Padding - ustar_header mHeader; - QByteArray mContent; - QProcess *mProcess; - State mState; - X509 *x509; - EVP_MD_CTX *mdctx; - const EVP_MD *md; -}; - -#endif // TAR_H diff --git a/src/b2qt-update-application/update.cpp b/src/b2qt-update-application/update.cpp deleted file mode 100644 index 79fea64..0000000 --- a/src/b2qt-update-application/update.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include "update.h" -#include "tar.h" -#include -#include -#include -#include - -extern QStringList mounts; -bool writeAll(const QString &fileName, const QByteArray &content); -static QStringList allowedFiles; -QByteArray readAll(const QString &fileName); -bool execute(const QString &binary, const QStringList &arguments); -bool mount(const QString &device, const QString &mountpoint, const QString &arguments = QString()); - -QMap parseMetaInfo(const QByteArray &data) -{ - QMap rc; - QList list = data.split('\n'); - foreach (const QByteArray &ba, list) { - if (ba.isEmpty()) - continue; - int i = ba.indexOf(':'); - if (i < 0 || i == ba.size()) - qFatal("Invalid meta.info content: No colon found or no data after colon"); - - QString key = ba.left(i); - QString value = ba.mid(i+1).trimmed(); - - if (rc.contains(key)) - qFatal("Invalid meta.info content: Same key given twice"); - rc.insert(key, value); - } - if (rc.isEmpty()) - qFatal("Invalid meta.info content: No keys given"); - return rc; -} - -Update::Update(QObject *parent) - : QObject(parent) - , mTar(0) - , mSource(0) -{ - allowedFiles << "key.info" << "meta.info" << "keys.tar" << "uImage" << "rootfs.tar"; -} - -Update::~Update() -{ -} - -//# openssl dgst -sha256 -sign priv.pem file.txt > file.txt.sig -//# openssl dgst -sha256 -verify public.pem -signature file.txt.sig file.txt - -void Update::setDevice(QIODevice *source) -{ - if (!source) { - qFatal("Source device is NULL"); - return; - } - - if (mSource) { - qFatal("Source already set"); - return; - } - - mSource = source; - mTar = new Tar(mSource); - - connect(mTar, &Tar::startingFile, this, &Update::tarStartingFile); - connect(mTar, &Tar::endingFile, this, &Update::tarEndingFile); - connect(mTar, &Tar::finished, this, &Update::tarFinished); -} - -void Update::tarStartingFile(const QString &name) -{ - if (name == "key.info") { - mTar->receiveContent(); - } else if (name.endsWith(".sig")) { - mTar->receiveContent(); - mCurrentFile = name; - mCurrentFile.chop(4); - - bool found = false; - while (!allowedFiles.isEmpty()) { - QString n = allowedFiles.takeFirst(); - if (n == mCurrentFile) { - found = true; - break; - } - } - - if (!found) - qFatal("File not allowed"); - - } else if (mCurrentFile != name) { - qFatal("Invalid file order"); - } else { - if (mCurrentFile == "meta.info") { - mTar->receiveContent(); - } else if (mCurrentFile == "uImage") { - mount(QString(), "/mnt/boot", "remount,rw"); - mTar->extractContent("/mnt/boot"); - } else if (mCurrentFile == "rootfs.tar") { - qDebug() << "Formatting rootfs"; - execute("mkfs." + mMetaInfo["filesystemType"], QStringList() << mMetaInfo["rootDevice"]); - mount(mMetaInfo["rootDevice"], "/mnt/root"); - mTar->extractContent("/mnt/root"); - } else if (mCurrentFile == "keys.tar") { - mount(QString(), "/mnt/boot", "remount,rw"); - execute("rm", QStringList() << "-r" << "/mnt/boot/update/keys/"); - execute("mkdir", QStringList() << "/mnt/boot/update/keys/"); - mTar->extractContent("/mnt/boot/update/keys"); - } else { - qFatal("Unexpected file in update data"); - } - } -} - -void Update::tarEndingFile(const QString &name) -{ - if (name == "meta.info") { - QMap map = parseMetaInfo(mTar->currentContent()); - - // Some rough sanity checks - if (!map.contains("version")) - qFatal("No version information found" ); - if (map["version"] != "1") - qFatal("Invalid update version"); - if (!map.contains("platform") || map["platform"].isEmpty()) - qFatal("Platform information missing"); - if (map["platform"] != readAll("/mnt/boot/update/platform").trimmed()) - qFatal("Invalid platform information"); - else - qDebug() << "Platform matches"; - if (!map.contains("rootDevice") || map["rootDevice"].isEmpty()) - qFatal("Root device information missing"); - if (!QFile::exists(map["rootDevice"])) - qFatal("Root device not found"); - if (!map.contains("key") || map["key"].isEmpty() || map["key"].contains('/')) - qFatal("Invalid or no key fingerprint"); - if (!map.contains("digest") || map["digest"].isEmpty()) - qFatal("Invalid digest type"); - if (!map.contains("filesystemType") || map["filesystemType"].isEmpty() || map["filesystemType"].contains(' ') || map["filesystemType"].contains('/')) - qFatal("Invalid filesystem type"); - - mMetaInfo = map; - - if (!mTar->setVerificationData("/mnt/boot/update/keys/" + mMetaInfo["key"], mMetaInfo["digest"])) - qFatal("Loading of certificate failed"); - - // Now verify the meta.info itself - if (mTar->verifyCurrentContent(mCurrentSignature)) { - qDebug() << "meta.info VERIFIED OK"; - } else { - qDebug() << "meta.info VERIFICATION FAILED"; - qFatal("VERIFICATION FAILED"); - return; - } - - } else if (name.endsWith(".sig")) { - mCurrentSignature = mTar->currentContent(); - qDebug() << "Received signature with" << mCurrentSignature.size() << "bytes."; - } else { - if (mTar->checkSignature(mCurrentSignature)) { - qDebug() << "VERIFIED OK"; - // FIXME: do something here - } else { - qDebug() << "VERIFICATION FAILED"; - qFatal("VERIFICATION FAILED"); - } - } - - mTar->continueContent(); -} - -void Update::tarFinished() -{ - qDebug() << "Update finished"; - mount(QString(), "/mnt/boot", "remount,rw"); - if (!writeAll("/mnt/boot/update/state", "t")) - qFatal("Could not set state to testing"); - mount(QString(), "/mnt/boot", "remount,ro"); - qApp->exit(); -} diff --git a/src/b2qt-update-application/update.h b/src/b2qt-update-application/update.h deleted file mode 100644 index 830be56..0000000 --- a/src/b2qt-update-application/update.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#ifndef UPDATE_H -#define UPDATE_H - -#include -#include -class Tar; -class QIODevice; - -class Update : public QObject -{ - Q_OBJECT - -public: - Update(QObject *parent = 0); - virtual ~Update(); - void setDevice(QIODevice *source); - -private slots: - void tarStartingFile(const QString &name); - void tarEndingFile(const QString &name); - void tarFinished(); - -private: - Tar *mTar; - QIODevice *mSource; - QString mCurrentFile; - QByteArray mCurrentSignature; - QMap mMetaInfo; -}; - -#endif // UPDATE_H diff --git a/src/b2qt-update-util/.gitignore b/src/b2qt-update-util/.gitignore deleted file mode 100644 index 67f0098..0000000 --- a/src/b2qt-update-util/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -Makefile -b2qt-update-util -*.o -moc_*.cpp diff --git a/src/b2qt-update-util/b2qt-update-util.pro b/src/b2qt-update-util/b2qt-update-util.pro deleted file mode 100644 index 0b5ab32..0000000 --- a/src/b2qt-update-util/b2qt-update-util.pro +++ /dev/null @@ -1,23 +0,0 @@ -QT = core -SOURCES = main.cpp -INSTALLS += target -target.path = /usr/bin - -# Find out git hash -unix:system(which git):HAS_GIT=TRUE -win32:system(where git.exe):HAS_GIT=TRUE -contains(HAS_GIT, TRUE) { - GIT_HASH=$$system(git log -1 --format=%H) - !system(git diff-index --quiet HEAD): GIT_HASH="$$GIT_HASH-dirty" - GIT_VERSION=$$system(git describe --tags --exact-match) - isEmpty(GIT_VERSION) : GIT_VERSION="unknown" -} else { - GIT_HASH="unknown" - GIT_VERSION="unknown" -} - -isEmpty(GIT_VERSION) : error("No suitable tag found") -isEmpty(GIT_HASH) : error("No hash available") - -DEFINES+="GIT_HASH=\\\"$$GIT_HASH\\\"" -DEFINES+="GIT_VERSION=\\\"$$GIT_VERSION\\\"" diff --git a/src/b2qt-update-util/main.cpp b/src/b2qt-update-util/main.cpp deleted file mode 100644 index 137cbd5..0000000 --- a/src/b2qt-update-util/main.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -bool mount_boot() -{ - // In some cases the boot partition is already mounted somewhere else. - // Mounting it again is no problem but data loss will happen. - QProcess::execute("umount", QStringList() << "/dev/mmcblk0p1"); // Ignore return value - return QProcess::execute("mount", QStringList() << "/dev/mmcblk0p1" << "/boot") == 0; -} - -bool umount_boot() -{ - return QProcess::execute("umount", QStringList() << "/boot") == 0; -} - -bool finish_update() -{ - if (!mount_boot()) { - qWarning() << "Could not mount /boot"; - return false; - } - QFile f("/boot/update/state"); - if (!f.open(QFile::WriteOnly)) { - qWarning() << "Could not open file for writing"; - return false; - } - if (f.write("v") != 1) { - qWarning() << "Write error"; - return false; - } - fsync(f.handle()); - f.close(); - if (!umount_boot()) { - qWarning() << "Could not unmount /boot"; - return false; - } - return true; -} - -int start_update(const QString &source) -{ - if (!mount_boot()) { - qWarning() << "Could not mount /boot"; - return false; - } - { - QFile f("/boot/update/source"); - if (!f.open(QFile::WriteOnly)) { - qWarning() << "Could not open file for writing"; - return false; - } - QByteArray ba = source.toUtf8(); - - if (f.write(ba) != ba.size()) { - qWarning() << "Write error"; - return false; - } - fsync(f.handle()); - f.close(); - } - - { - QFile f("/boot/update/state"); - if (!f.open(QFile::WriteOnly)) { - qWarning() << "Could not open file for writing"; - return false; - } - if (f.write("u") != 1) { - qWarning() << "Write error"; - return false; - } - fsync(f.handle()); - f.close(); - } - if (!umount_boot()) { - qWarning() << "Could not unmount /boot"; - return false; - } - reboot(RB_AUTOBOOT); - return true; -} - -void usage() -{ - fprintf(stderr, - "b2qt-update [start|finish] [...]\n" - " start: For internet update provide a http URL as parameter\n" - " finish: An update\n" - ); -} - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - QStringList args = app.arguments(); - - args.removeFirst(); - if (args.size() == 0) { - usage(); - return 1; - } - - QString arg = args.takeFirst(); - - if (arg == "finish") - return finish_update(); - else if (arg == "start") { - if (args.size() == 0) - return start_update(QString()); - else - return start_update(args.takeFirst()); - } else if (arg == "version") { - printf("Version %s, SHA1 %s\n", GIT_VERSION, GIT_HASH); - return 0; - } else { - usage(); - return 1; - } -} diff --git a/src/src.pro b/src/src.pro index 7ddc9ca..ebe58b5 100644 --- a/src/src.pro +++ b/src/src.pro @@ -4,5 +4,4 @@ SUBDIRS += \ utils \ wifi \ imports \ - doc \ - b2qt-update-util + doc -- cgit v1.2.3