21 structPosition(structPosition), _name(name), _location(location), _size(size),
22 _newLocation(location), _newSize(size), _paddingAfter(0)
137 fs.append(static_cast<IsoFile *>(fOrD));
146 QList<IsoDirectory *> ds;
150 ds.append(static_cast<IsoDirectory *>(fOrD));
161 if((index = path.indexOf(
"/")) != -1) {
164 if(fOrD == NULL)
return NULL;
181 if(fOrD == NULL)
return NULL;
187 return static_cast<IsoFile *
>(fOrD);
194 if(fOrD == NULL)
return NULL;
210 _io(0), _newIO(0), dataChanged(false),
211 _newIOMustBeRemoved(false)
229 if(
_io->isOpen() ||
_io->open(QIODevice::ReadOnly)) {
231 return maxSize == 0 ?
_io->readAll() :
_io->read(maxSize);
240 return maxSize == 0 ?
_newIO->readAll() :
_newIO->read(maxSize);
242 return data(maxSize);
249 maxSize = maxSize == 0 ?
size() : qMin(maxSize,
size());
252 QFile ret(destination);
253 if(!ret.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
256 if(!
_io->isOpen() && !
_io->open(QIODevice::ReadOnly)) {
260 while(maxSize-totalR > 0 && (r =
_io->read(data, qMin((qint64)
MAX_ISO_READ, maxSize-totalR))) > 0) {
290 if(!io->isOpen() && !io->open(QIODevice::ReadOnly)) {
304 QBuffer *io =
new QBuffer();
347 bool open = QFile::open(mode);
348 if(!open)
return false;
350 if(mode.testFlag(QIODevice::Truncate)) {
393 qint64 read, readTotal = 0, seqLen;
399 if(seqLen < 0)
return 0;
401 while((read = this->read(data, seqLen)) > 0) {
415 return read < 0 ? read : readTotal;
420 char *data =
new char[maxSize];
422 QByteArray baData(data,
readIso(data, maxSize));
431 qint64 write, writeTotal = 0, seqLen;
438 while((write = this->write(data, seqLen)) > 0) {
443 seqLen = qMin((qint64)2048, maxSize);
452 return write < 0 ? write : writeTotal;
457 return writeIso(byteArray.constData(), byteArray.size());
500 qint64 dataSize = data.size();
502 QByteArray sectorData;
510 sectorData.append(data);
521 QIODevice(parent), _io(io), _infos(infos)
526 if(mode.testFlag(QIODevice::Append)
527 || mode.testFlag(QIODevice::Truncate)
528 || mode.testFlag(QIODevice::WriteOnly)) {
531 return QIODevice::open(mode);
546 return _io->
readIso(data, qMin(maxSize, size - pos()));
560 return pos() <
size();
564 _rootDirectory(NULL), _error(
Archive::NoError)
584 if (mode.testFlag(QIODevice::Truncate)) {
589 qWarning() <<
"IsoArchive::open" <<
"cannot open volume descriptor";
590 _io.setErrorString(
"Cannot open volume descriptor");
594 qint64 size =
_io.size();
597 _io.setErrorString(
"Archive size error");
602 qWarning() <<
"IsoArchive::_open cannot open root directory";
603 _io.setErrorString(
"Cannot open root directory");
657 Q_UNUSED(writeToTheMain)
658 Q_UNUSED(writeToTheEnd)
665 QMap<quint32, const IsoFile *> writeToTheMain;
666 QList<const IsoFile *> writeToTheEnd;
667 QList<IsoFileOrDirectory *> filesWithPadding =
getIntegrity();
668 IsoFileOrDirectory *lastFileWithPadding = filesWithPadding.isEmpty() ? NULL : filesWithPadding.last();
670 sectorCountAtTheEnd = lastFileWithPadding ? (endOfIso - lastFileWithPadding->
locationAfter()) : 0,
671 lastPadding = lastFileWithPadding ? lastFileWithPadding->
paddingAfter() : 0,
672 endOfFilledIso, endOfFilledIsoAfter;
674 if (lastFileWithPadding && sectorCountAtTheEnd == lastPadding) {
678 endOfFilledIso = endOfIso;
680 endOfFilledIsoAfter = endOfFilledIso;
682 if(directory == NULL) {
684 if(directory == NULL) {
704 filesWithPadding.replace(index, isoFile);
706 filesWithPadding.removeAt(index);
708 writeToTheMain.insert(isoFile->
newLocation(), isoFile);
710 qWarning() <<
"Found enough space at" << fileWithPaddingAfter->
name() << isoFile->
newLocation() <<
"for" << isoFile->
name();
713 writeToTheEnd.append(isoFile);
716 qWarning() <<
"Add file at the end" << isoFile->
name() << endOfFilledIsoAfter;
723 writeToTheMain.insert(isoFile->
newLocation(), isoFile);
735 destinationIO->reset();
738 foreach(
const IsoFile *isoFile, writeToTheMain) {
751 #ifdef ISOARCHIVE_DEBUG 752 if(destinationIO->pos() %
SECTOR_SIZE != 0) qWarning() <<
"destination error 1a" << (destinationIO->pos() %
SECTOR_SIZE) << isoFile->
name();
753 if(destinationIO->
currentSector() != fileLocation) qWarning() <<
"destination error 1b" << destinationIO->
currentSector() << fileLocation << isoFile->
name();
754 if(destinationIO->pos() !=
_io.pos()) qWarning() <<
"destination error 1c" << destinationIO->pos() <<
_io.pos() << isoFile->
name();
761 _io.seek(destinationIO->pos());
763 #ifdef ISOARCHIVE_DEBUG 764 if(destinationIO->pos() %
SECTOR_SIZE != 0) qWarning() <<
"destination error 2a" << (destinationIO->pos() %
SECTOR_SIZE) << isoFile->
name();
766 if(destinationIO->pos() !=
_io.pos()) qWarning() <<
"destination error 2c" << destinationIO->pos() <<
_io.pos() << isoFile->
name();
778 #ifdef ISOARCHIVE_DEBUG 779 if(destinationIO->pos() %
SECTOR_SIZE != 0) qWarning() <<
"destination error 3a" << (destinationIO->pos() %
SECTOR_SIZE);
781 if(destinationIO->pos() !=
_io.pos()) qWarning() <<
"destination error 3c" << destinationIO->pos() <<
_io.pos();
785 foreach(
const IsoFile *isoFile, writeToTheEnd) {
790 #ifdef ISOARCHIVE_DEBUG 791 qWarning() <<
"Write file at the end" << isoFile->
name() << destinationIO->
currentSector();
798 #ifdef ISOARCHIVE_DEBUG 799 if(destinationIO->pos() %
SECTOR_SIZE != 0) qWarning() <<
"destination error 3a" << (destinationIO->pos() %
SECTOR_SIZE) << isoFile->
name();
806 if(!
copySectors(destinationIO, endOfIso - endOfFilledIso, control,
true)) {
812 if(destinationIO->size() !=
_io.size()) {
813 #ifdef ISOARCHIVE_DEBUG 818 quint32 volume_space_size = destinationIO->size() /
SECTOR_SIZE, volume_space_size2 = qToBigEndian(volume_space_size);
819 destinationIO->write((
char *)&volume_space_size, 4);
820 destinationIO->write((
char *)&volume_space_size2, 4);
839 #ifdef ISOARCHIVE_DEBUG 840 if(destinationIO->size() %
SECTOR_SIZE != 0) qWarning() <<
"Invalid size" << destinationIO->size();
848 if (sectorCount < 0) {
849 qWarning() <<
"IsoArchive::copySectors sectorCount < 0" << sectorCount;
857 for(
int i = 0 ; i < sectorCount ; ++i) {
865 qWarning() <<
"IsoArchive::copySectors read error" << data.size() <<
SECTOR_SIZE;
872 qWarning() <<
"IsoArchive::copySectors write error" << data.size() <<
SECTOR_SIZE;
880 qWarning() <<
"IsoArchive::copySectors writeSector error";
895 if(!in->isOpen() || !in->reset()) {
900 qint64 remainingSize = in->size();
903 while(remainingSize > 0) {
909 QByteArray sectorData;
913 toRead = remainingSize;
920 sectorData = in->read(toRead);
921 if(sectorData.size() != toRead) {
931 remainingSize = in->size() - in->pos();
934 if(sectorCount != 0) {
954 quint32 pos, oldSectorStart, newSectorStart, newSectorStart2, oldSize, newSize, newSize2;
955 QList<IsoDirectory *> dirs;
960 oldSectorStart = fileOrDir->
location();
961 oldSize = fileOrDir->
size();
963 newSize = fileOrDir->
newSize();
966 if(newSectorStart != oldSectorStart) {
967 newSectorStart2 = qToBigEndian(newSectorStart);
975 if(newSize != oldSize) {
976 newSize2 = qToBigEndian(newSize);
985 dirs.append(static_cast<IsoDirectory *>(fileOrDir));
1029 qWarning() <<
"2" <<
_io.pos();
1045 if(!
_io.seek(
_io.pos() + 31)) {
1051 if(!
_io.seek(
_io.pos() + 1)) {
1068 QList<quint32> dirVisisted;
1075 const quint32 sector = directories->
location(), dataSize = directories->
size();
1077 if(dirVisisted.contains(sector))
return directories;
1079 dirVisisted.append(sector + i);
1082 goto _openDirectoryRecordError;
1086 const quint32 maxPos =
_io.
posIso() + dataSize;
1093 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot read length_dr at" << beginPos;
1094 goto _openDirectoryRecordError;
1104 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot read extended_attr_record_length at" << beginPos;
1105 goto _openDirectoryRecordError;
1108 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot read drh at" << beginPos;
1109 goto _openDirectoryRecordError;
1114 goto _openDirectoryRecordError;
1118 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot seek to" << beginPos + 33;
1119 goto _openDirectoryRecordError;
1127 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot seek to" << beginPos + + dr.
length_dr;
1128 goto _openDirectoryRecordError;
1144 qWarning() <<
"IsoArchive::_openDirectoryRecord cannot open directory" << dir->
name() << dir->
location();
1145 goto _openDirectoryRecordError;
1153 _openDirectoryRecordError:
1193 return QByteArray();
1197 return QByteArray();
1199 return file->
data(maxSize);
1211 return file->
file();
1217 return QByteArray();
1221 return QByteArray();
1247 return file->
extract(destination, maxSize);
1259 QDir destDir(destination);
1263 if (!file->
extract(destDir.filePath(file->
name()))) {
1283 QDir dir(destination);
1284 QString currentPath = dir.absolutePath().append(
'/');
1287 QCoreApplication::processEvents();
1292 dir.mkdir(fileOrDir->
name());
1293 _extractAll(currentPath + fileOrDir->
name(),
static_cast<IsoDirectory *
>(fileOrDir), currentInternalDir.isEmpty() ? fileOrDir->
name() : currentInternalDir +
'/' + fileOrDir->
name());
1299 extract(currentInternalDir.isEmpty() ? fileOrDir->
name() : currentInternalDir +
'/' + fileOrDir->
name(), currentPath + fileOrDir->
name());
1312 if(isoFile == NULL) {
1337 if(prevFile != NULL) {
1341 QByteArray sectorHeaderEmpty(
"\x00\x00\x20\x00\x00\x00\x20\x00", 8),
1342 sectorHeaderVoid(8,
'\0');
1345 for (sector = 0 ; sector < prevFile->
paddingAfter() ; ++sector) {
1347 if (sectorHeaderPart != sectorHeaderEmpty
1348 && sectorHeaderPart != sectorHeaderVoid) {
1353 #ifdef ISOARCHIVE_DEBUG 1355 qDebug() << QString(
"%1 -> %2 (%3 sectors, %4 empty) : padding after %5 (%6 sectors)")
1360 .arg(prevFile->
name())
1376 QMap<quint32, IsoFileOrDirectory *> files;
1377 QList<IsoFileOrDirectory *> filesWithPadding;
1383 QMapIterator<quint32, IsoFileOrDirectory *> i(files);
1384 while (i.hasNext()) {
1389 filesWithPadding.append(prevFile);
1396 filesWithPadding.append(prevFile);
1399 return filesWithPadding;
1406 files.insert(fileOrDir->
location(), fileOrDir);
1409 _getIntegrity(files, static_cast<IsoDirectory *>(fileOrDir));
1417 QMap<quint32, IsoFile *> ret;
1427 }
else if(static_cast<IsoFile *>(fileOrDir)->isModified()) {
1461 _io.setErrorString(errorString);
1464 #ifdef ISOARCHIVE_DEBUG 1466 QString IsoArchive::isoTimeToString(
const IsoTime &time)
1468 return QString(
"%1/%2/%3 %4:%5:%6 (%7ms) [GMT%8]").arg(
1469 QByteArray((
char *)time.
day, 2),
1470 QByteArray((
char *)time.
month, 2),
1471 QByteArray((
char *)time.
year, 4),
1472 QByteArray((
char *)time.
hour, 2),
1473 QByteArray((
char *)time.
minute, 2),
1474 QByteArray((
char *)time.
second, 2),
1475 QByteArray((
char *)time.
millis, 2),
1476 QString(
"%1%2").arg(time.
GMT >= 0 ?
"+" :
"").arg(time.
GMT));
1482 out.append(
"struct VolumeDescriptor {\n");
1483 out.append(QString(
"\t type = %1\n").arg(vd.
vd1.
type, 2, 16, QChar(
'0')));
1484 out.append(QString(
"\t id = %1\n").arg(QString(QByteArray((
char *)vd.
vd1.
id,
sizeof(vd.
vd1.
id)))));
1485 out.append(QString(
"\t version = %1\n").arg(vd.
vd1.
version));
1487 out.append(QString(
"\t system_id = %1\n").arg(QString(QByteArray((
char *)vd.
vd1.
system_id,
sizeof(vd.
vd1.
system_id)))));
1488 out.append(QString(
"\t volume_id = %1\n").arg(QString(QByteArray((
char *)vd.
vd1.
volume_id,
sizeof(vd.
vd1.
volume_id)))));
1492 out.append(QString(
"\t volume_set_size2 = %1\n").arg(qFromBigEndian(vd.
vd1.
volume_set_size2)));
1498 out.append(QString(
"\t path_table_size2 = %1\n").arg(qFromBigEndian(vd.
vd1.
path_table_size2)));
1501 out.append(QString(
"\t type_path_table2 = %1\n").arg(qFromBigEndian(vd.
vd1.
type_path_table2)));
1503 out.append(
"\t ====================\n");
1504 out.append(directoryRecordToString(vd.
dr));
1505 out.append(
"\t ====================\n");
1513 out.append(QString(
"\t creation_date = %1\n").arg(isoTimeToString(vd.
vd2.
creation_date)));
1522 QString IsoArchive::directoryRecordToString(
const DirectoryRecord &dr)
1525 out.append(
"struct DirectoryRecord {\n");
1526 out.append(QString(
"\t length_dr = %1\n").arg(dr.
length_dr));
1529 out.append(QString(
"\t location_extent2 = %1\n").arg(qFromBigEndian(dr.
drh.
location_extent2)));
1530 out.append(QString(
"\t data_length = %1\n").arg(dr.
drh.
data_length));
1531 out.append(QString(
"\t data_length2 = %1\n").arg(qFromBigEndian(dr.
drh.
data_length2)));
1532 out.append(QString(
"\t %3/%2/%1 %4:%5:%6 [GMT%7]\n").arg(dr.
drh.
year, 2, 10, QChar(
'0')).arg(dr.
drh.
month, 2, 10, QChar(
'0')).arg(dr.
drh.
day, 2, 10, QChar(
'0')).arg(dr.
drh.
hour, 2, 10, QChar(
'0')).arg(dr.
drh.
minute, 2, 10, QChar(
'0')).arg(dr.
drh.
second, 2, 10, QChar(
'0')).arg(QString(
"%1%2").arg(dr.
drh.
GMT >= 0 ?
"+" :
"").arg(dr.
drh.
GMT)));
1533 out.append(QString(
"\t file_flags = %1\n").arg(dr.
drh.
file_flags, 8, 2, QChar(
'0')));
1538 out.append(QString(
"\t length_fi = %1\n").arg(dr.
drh.
length_fi));
1539 out.append(QString(
"\t name = %1\n").arg(dr.
name));
1544 QString IsoArchive::pathTableToString(
const PathTable &pathTable,
bool bigEndian)
1547 out.append(
"struct PathTable {\n");
1548 out.append(QString(
"\t length_di = %1\n").arg(pathTable.
length_di));
1552 out.append(QString(
"\t name = %1\n").arg(pathTable.
name));
quint32 currentSector() const
QByteArray sectorFooter(quint32 num)
bool setModifiedFile(QIODevice *io)
quint32 newLocation() const
Archive::ArchiveError _error
quint16 volume_sequence_number2
IsoDirectory * rootDirectory() const
virtual bool isDirectory() const =0
qint64 readIso(char *data, qint64 maxSize)
virtual bool reorganizeModifiedFilesAfter(QMap< quint32, const IsoFile * > &writeToTheMain, QList< const IsoFile * > &writeToTheEnd)
Used to extend IsoArchive. Called in pack() afer file reorganization.
IsoFile(const QString &name, quint32 location, quint32 size, qint64 structPosition, IsoArchiveIO *io)
#define MAX_FILENAME_LENGTH
#define SECTOR_SIZE_FOOTER
IsoFile * file(const QString &path) const
void _getIntegrity(QMap< quint32, IsoFileOrDirectory * > &files, IsoDirectory *directory) const
quint8 file_structure_version
IsoDirectory * _openDirectoryRecord(IsoDirectory *directories, QList< quint32 > &dirVisisted)
IsoDirectory * directory(const QString &path) const
QList< IsoFileOrDirectory * > getIntegrity()
quint16 volume_sequence_number
quint8 extended_attr_record_length
static qint64 isoPos(qint64 pos)
static int findPadding(const QList< IsoFileOrDirectory * > &filesWithPadding, quint32 minSectorCount)
QIODevice * fileDevice(const QString &path) const
quint8 bibliographic_file_id[37]
QMap< QString, IsoFileOrDirectory * > _filesAndDirectories
QString errorString() const
void setName(const QString &name)
void _extractAll(const QString &destination, IsoDirectory *directories, QString currentInternalDir=QString()) const
void setFile(QIODevice *io)
quint8 abstract_file_id[37]
static QByteArray buildFooter(quint32 sector)
quint16 logical_block_size
bool openRootDirectory(quint32 sector, quint32 dataSize=SECTOR_SIZE_DATA)
quint16 volume_sequence_number2
bool openVolumeDescriptor(quint8 num=0)
bool extractDir(const QString &path, const QString &destination) const
quint16 volume_sequence_number
QByteArray modifiedData(quint32 maxSize=0) const
bool extract(const QString &destination, quint32 maxSize=0) const
qint32 diffCountSectors(const QString &path, quint32 newSize) const
quint8 paddingAfter() const
quint32 sectorCount() const
static qint64 filePos(qint64 pos)
quint8 application_data[512]
bool getIntegritySetPaddingAfter(IsoFileOrDirectory *prevFile, quint32 fileLocation)
virtual void applyModifications()
QByteArray data(quint32 maxSize=0) const
const QMap< QString, IsoFileOrDirectory * > & filesAndDirectories() const
virtual void setObserverMaximum(unsigned int max)=0
QIODevice * modifiedFile() const
quint8 application_id[128]
virtual bool open(QIODevice::OpenMode mode)
quint8 extended_attr_record_length
quint32 volume_space_size2
bool writeFile(QIODevice *in, quint32 sectorCount=0, ArchiveObserver *control=NULL)
qint64 readData(char *data, qint64 maxSize)
QByteArray modifiedFile(const QString &path, quint32 maxSize=0) const
void applyModifications()
void setError(Archive::ArchiveError error, const QString &errorString=QString())
Sets the file's error type and text.
IsoDirectory * _rootDirectory
quint16 parent_directory_number
quint32 opt_type_path_table
void extractAll(const QString &destination) const
virtual ~IsoFileOrDirectory()
quint16 logical_block_size2
quint32 locationAfter() const
qint64 writeData(const char *data, qint64 maxSize)
void setLocation(quint32 location)
virtual void setObserverValue(int value)=0
QByteArray sectorHeader(quint32 num)
const QString & name() const
virtual bool observerWasCanceled() const =0
void add(IsoFileOrDirectory *fileOrDirectory)
The Archive class is a device list in a file system or an archive file.
QByteArray file(const QString &path, quint32 maxSize=0) const
quint8 copyright_file_id[37]
Archive::ArchiveError error() const
Returns the last error status.
quint32 sectorCount() const
quint32 opt_type_path_table2
qint64 writeIso(const char *data, qint64 maxSize)
void setPaddingAfter(quint8 after)
quint8 interleave_grap_size
bool copySectors(IsoArchiveIO *out, qint64 size, ArchiveObserver *control=NULL, bool repair=false)
IsoDirectory(const QString &name, quint32 location, quint32 size, qint64 structPosition)
bool open(QIODevice::OpenMode mode)
bool writeSector(const QByteArray &data, quint8 type, quint8 mode=2)
quint8 volume_set_id[128]
#define SECTOR_SIZE_HEADER
QByteArray sector(quint32 num, quint16 maxSize=SECTOR_SIZE_DATA)
QList< IsoFile * > files() const
bool pack(IsoArchive *destination, ArchiveObserver *control=NULL, IsoDirectory *directory=NULL)
QList< IsoDirectory * > directories() const
bool extract(const QString &path, const QString &destination, quint32 maxSize=0) const
QIODevice * modifiedFileDevice(const QString &path) const
virtual bool isModified() const
IsoFileOrDirectory * fileOrDirectory(const QString &path) const
static void headerInfos(const QByteArray &header, quint8 *type, quint8 *mode=NULL)
static void repairLocationSectors(IsoDirectory *directory, IsoArchive *newIso)
bool seekToSector(quint32 num)
static quint32 sectorCountData(quint32 dataSize)
void applyModifications(IsoDirectory *directory)
quint32 volume_space_size
quint32 newSectorCount() const
IsoFileOrDirectory(const QString &name, quint32 location, quint32 size, qint64 structPosition)
static QByteArray buildHeader(quint32 sector, quint8 type, quint8 mode=2)
IsoFileIO(IsoArchiveIO *io, const IsoFile *infos, QObject *parent=0)
QMap< quint32, IsoFile * > getModifiedFiles(IsoDirectory *directory) const