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