Maemo: Implement tar package creation step.

Currently unused.
This commit is contained in:
Christian Kandeler
2011-04-05 17:25:10 +02:00
parent e1ba3d0b89
commit 1352ae3deb
3 changed files with 192 additions and 10 deletions

View File

@@ -121,7 +121,7 @@ void AbstractMaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
connect(buildProc, SIGNAL(readyReadStandardError()), this,
SLOT(handleBuildOutput()));
emit addOutput(tr("Creating package file ..."), MessageOutput);
const bool success = createPackage(buildProc);
const bool success = createPackage(buildProc, fi);
disconnect(buildProc, 0, this, 0);
buildProc->deleteLater();
if (success) {
@@ -332,8 +332,10 @@ void MaemoDebianPackageCreationStep::ctor()
setDefaultDisplayName(tr("Create Debian Package"));
}
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc)
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
const QFutureInterface<bool> &fi)
{
Q_UNUSED(fi);
checkProjectName();
const QString projectDir
= buildConfiguration()->target()->project()->projectDirectory();
@@ -601,8 +603,10 @@ void MaemoRpmPackageCreationStep::ctor()
setDefaultDisplayName(tr("Create RPM Package"));
}
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc)
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc,
const QFutureInterface<bool> &fi)
{
Q_UNUSED(fi);
const QStringList args = QStringList() << QLatin1String("rrpmbuild")
<< QLatin1String("-bb") << rpmBasedMaemoTarget()->specFilePath();
if (!callPackagingCommand(buildProc, args))
@@ -661,6 +665,29 @@ private:
const MaemoTarPackageCreationStep * const m_step;
};
namespace {
const int TarBlockSize = 512;
struct TarFileHeader {
char fileName[100];
char fileMode[8];
char uid[8];
char gid[8];
char length[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char fileNamePrefix[155];
char padding[12];
};
} // Anonymous namespace.
MaemoTarPackageCreationStep::MaemoTarPackageCreationStep(BuildStepList *bsl)
: AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
{
@@ -679,15 +706,165 @@ void MaemoTarPackageCreationStep::ctor()
setDefaultDisplayName(tr("Create tar ball"));
}
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc)
bool MaemoTarPackageCreationStep::createPackage(QProcess *buildProc,
const QFutureInterface<bool> &fi)
{
Q_UNUSED(buildProc);
// TODO: Copy files one by one into tar file.
// TODO: Optimization: Only package changed files (needs refactoring in upper level; worth the effort?)
QFile tarFile(packageFilePath());
if (!tarFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
raiseError(tr("Error: tar file %1 cannot be opened (%2).")
.arg(QDir::toNativeSeparators(packageFilePath()),
tarFile.errorString()));
return false;
}
const QSharedPointer<MaemoDeployables> deployables = deployConfig()->deployables();
for (int i = 0; i < deployables->deployableCount(); ++i) {
const MaemoDeployable &d = deployables->deployableAt(i);
QFileInfo fileInfo(d.localFilePath);
if (!appendFile(tarFile, fileInfo, d.remoteDir + QLatin1Char('/')
+ fileInfo.fileName(), fi)) {
return false;
}
}
return true;
}
bool MaemoTarPackageCreationStep::appendFile(QFile &tarFile,
const QFileInfo &fileInfo, const QString &remoteFilePath,
const QFutureInterface<bool> &fi)
{
if (!writeHeader(tarFile, fileInfo, remoteFilePath))
return false;
if (fileInfo.isDir()) {
QDir dir(fileInfo.absoluteFilePath());
foreach (const QString &fileName,
dir.entryList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
const QString thisLocalFilePath
= dir.path() + QLatin1Char('/') + fileName;
const QString thisRemoteFilePath = remoteFilePath
+ QLatin1Char('/') + fileName;
if (!appendFile(tarFile, QFileInfo(thisLocalFilePath),
thisRemoteFilePath, fi)) {
return false;
}
}
} else {
const QString nativePath
= QDir::toNativeSeparators(fileInfo.filePath());
QFile file(fileInfo.filePath());
if (!file.open(QIODevice::ReadOnly)) {
raiseError(tr("Error reading file '%1': %2.")
.arg(nativePath, file.errorString()));
return false;
}
const int chunkSize = 1024*1024;
// TODO: Wasteful. Work with fixed-size buffer.
while (!file.atEnd() && !file.error() != QFile::NoError
&& !tarFile.error() != QFile::NoError) {
const QByteArray data = file.read(chunkSize);
tarFile.write(data);
if (fi.isCanceled())
return false;
}
if (file.error() != QFile::NoError) {
raiseError(tr("Error reading file '%1': %2.")
.arg(nativePath, file.errorString()));
return false;
}
const int blockModulo = file.size() % TarBlockSize;
if (blockModulo != 0) {
tarFile.write(QByteArray(TarBlockSize - blockModulo, 0));
}
if (tarFile.error() != QFile::NoError) {
raiseError(tr("Error writing tar file '%1': %2.")
.arg(QDir::toNativeSeparators(tarFile.fileName()),
tarFile.errorString()));
return false;
}
}
return true;
}
bool MaemoTarPackageCreationStep::writeHeader(QFile &tarFile,
const QFileInfo &fileInfo, const QString &remoteFilePath)
{
TarFileHeader header;
qMemSet(&header, '\0', sizeof header);
const QByteArray &filePath = remoteFilePath.toUtf8();
const int maxFilePathLength = sizeof header.fileNamePrefix
+ sizeof header.fileName;
if (filePath.count() > maxFilePathLength) {
raiseError(tr("Cannot tar file '%1': path is too long.")
.arg(QDir::toNativeSeparators(filePath)));
return false;
}
const int fileNameBytesToWrite
= qMin<int>(filePath.length(), sizeof header.fileName);
const int fileNameOffset = filePath.length() - fileNameBytesToWrite;
qMemCopy(&header.fileName, filePath.data() + fileNameOffset,
fileNameBytesToWrite);
if (fileNameOffset > 0)
qMemCopy(&header.fileNamePrefix, filePath.data(), fileNameOffset);
int permissions = (0400 * fileInfo.permission(QFile::ReadOwner))
| (0200 * fileInfo.permission(QFile::WriteOwner))
| (0100 * fileInfo.permission(QFile::ExeOwner))
| (040 * fileInfo.permission(QFile::ReadGroup))
| (020 * fileInfo.permission(QFile::WriteGroup))
| (010 * fileInfo.permission(QFile::ExeGroup))
| (04 * fileInfo.permission(QFile::ReadOther))
| (02 * fileInfo.permission(QFile::WriteOther))
| (01 * fileInfo.permission(QFile::ExeOther));
const QByteArray permissionString = QString("%1").arg(permissions,
sizeof header.fileMode - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.fileMode, permissionString.data(),
permissionString.length());
const QByteArray uidString = QString("%1").arg(fileInfo.ownerId(),
sizeof header.uid - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.uid, uidString.data(), uidString.length());
const QByteArray gidString = QString("%1").arg(fileInfo.groupId(),
sizeof header.gid - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.gid, gidString.data(), gidString.length());
const QByteArray sizeString = QString("%1").arg(fileInfo.size(),
sizeof header.length - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.length, sizeString.data(), sizeString.length());
const QByteArray mtimeString = QString("%1").arg(fileInfo.lastModified().toTime_t(),
sizeof header.mtime - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.mtime, mtimeString.data(), mtimeString.length());
if (fileInfo.isDir())
header.typeflag = '5';
qMemCopy(&header.magic, "ustar", sizeof "ustar");
qMemCopy(&header.version, "00", 2);
const QByteArray &owner = fileInfo.owner().toUtf8();
qMemCopy(&header.uname, owner.data(),
qMin<int>(owner.length(), sizeof header.uname - 1));
const QByteArray &group = fileInfo.group().toUtf8();
qMemCopy(&header.gname, group.data(),
qMin<int>(group.length(), sizeof header.gname - 1));
qMemSet(&header.chksum, ' ', sizeof header.chksum);
quint64 checksum = 0;
for (size_t i = 0; i < sizeof header; ++i)
checksum += reinterpret_cast<char *>(&header)[i];
const QByteArray checksumString = QString("%1").arg(checksum,
sizeof header.chksum - 1, 8, QLatin1Char('0')).toAscii();
qMemCopy(&header.chksum, checksumString.data(), checksumString.length());
header.chksum[sizeof header.chksum-1] = 0;
if (!tarFile.write(reinterpret_cast<char *>(&header), sizeof header)) {
raiseError(tr("Error writing tar file '%1': %2")
.arg(QDir::toNativeSeparators(packageFilePath()),
tarFile.errorString()));
return false;
}
return true;
}
bool MaemoTarPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
{
Q_UNUSED(packageDate);

View File

@@ -47,6 +47,7 @@
QT_BEGIN_NAMESPACE
class QDateTime;
class QFile;
class QFileInfo;
class QProcess;
QT_END_NAMESPACE
@@ -109,7 +110,7 @@ private:
virtual void run(QFutureInterface<bool> &fi);
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
virtual bool createPackage(QProcess *buildProc)=0;
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi)=0;
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const=0;
static QString nativePath(const QFile &file);
@@ -132,7 +133,7 @@ private:
MaemoDebianPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
MaemoDebianPackageCreationStep *other);
virtual bool createPackage(QProcess *buildProc);
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
void ctor();
@@ -159,7 +160,7 @@ public:
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *bsl);
private:
virtual bool createPackage(QProcess *buildProc);
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
MaemoRpmPackageCreationStep(ProjectExplorer::BuildStepList *buildConfig,
@@ -180,7 +181,7 @@ public:
virtual QString packageFilePath() const;
private:
virtual bool createPackage(QProcess *buildProc);
virtual bool createPackage(QProcess *buildProc, const QFutureInterface<bool> &fi);
virtual bool isMetaDataNewerThan(const QDateTime &packageDate) const;
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
@@ -188,6 +189,10 @@ private:
MaemoTarPackageCreationStep *other);
void ctor();
bool appendFile(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath, const QFutureInterface<bool> &fi);
bool writeHeader(QFile &tarFile, const QFileInfo &fileInfo,
const QString &remoteFilePath);
static const QString CreatePackageId;
};

View File

@@ -205,7 +205,7 @@ QString MaemoTarPackageInstaller::installCommand() const
QStringList MaemoTarPackageInstaller::installCommandArguments() const
{
return QStringList() << QLatin1String("xvf");
return QStringList() << QLatin1String("--absolute-names -xvf");
}
} // namespace Internal