File indexing completed on 2024-05-12 04:51:06

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3bmkisofshandler.h"
0007 
0008 #include "k3bexternalbinmanager.h"
0009 #include "k3bcore.h"
0010 #include "k3bjob.h"
0011 #include "k3b_i18n.h"
0012 
0013 #include <QDebug>
0014 #include <QRegExp>
0015 #include <QRegularExpression>
0016 
0017 #include <cmath>
0018 
0019 
0020 
0021 class K3b::MkisofsHandler::Private
0022 {
0023 public:
0024     const K3b::ExternalBin* mkisofsBin;
0025     double firstProgressValue;
0026     bool readError;
0027 };
0028 
0029 
0030 K3b::MkisofsHandler::MkisofsHandler()
0031 {
0032     d = new Private;
0033     d->mkisofsBin = 0;
0034 }
0035 
0036 
0037 K3b::MkisofsHandler::~MkisofsHandler()
0038 {
0039     delete d;
0040 }
0041 
0042 
0043 bool K3b::MkisofsHandler::mkisofsReadError() const
0044 {
0045     return d->readError;
0046 }
0047 
0048 
0049 const K3b::ExternalBin* K3b::MkisofsHandler::initMkisofs()
0050 {
0051     d->mkisofsBin = k3bcore->externalBinManager()->binObject( "mkisofs" );
0052 
0053     if( d->mkisofsBin ) {
0054         if( !d->mkisofsBin->copyright().isEmpty() )
0055             handleMkisofsInfoMessage( i18n("Using %1 %2 – Copyright © %3",
0056                                            QString("mkisofs"),
0057                                            d->mkisofsBin->version(),
0058                                            d->mkisofsBin->copyright()),
0059                                       K3b::Job::MessageInfo );
0060 
0061         d->firstProgressValue = -1;
0062         d->readError = false;
0063     }
0064     else {
0065         qDebug() << "(K3b::MkisofsHandler) could not find mkisofs executable";
0066         handleMkisofsInfoMessage( i18n("Mkisofs executable not found."), K3b::Job::MessageError );
0067     }
0068 
0069     return d->mkisofsBin;
0070 }
0071 
0072 
0073 void K3b::MkisofsHandler::parseMkisofsOutput( const QString& line )
0074 {
0075     if( !line.isEmpty() ) {
0076         if( line.startsWith( d->mkisofsBin->path() ) ) {
0077             // error or warning
0078             QString errorLine = line.mid( d->mkisofsBin->path().length() + 2 );
0079             if( errorLine.startsWith( "Input/output error. Cannot read from" ) ) {
0080                 handleMkisofsInfoMessage( i18n("Read error from file '%1'", errorLine.mid( 38, errorLine.length()-40 ) ),
0081                                           K3b::Job::MessageError );
0082                 d->readError = true;
0083             }
0084             else if( errorLine.startsWith( "Value too large for defined data type" ) ) {
0085                 handleMkisofsInfoMessage( i18n("Used version of mkisofs does not have large file support."), K3b::Job::MessageError );
0086                 handleMkisofsInfoMessage( i18n("Files bigger than 2 GB cannot be handled."), K3b::Job::MessageError );
0087                 d->readError = true;
0088             }
0089             else if( errorLine.startsWith( "No such file or directory. cannot open" ) ) {
0090                 handleMkisofsInfoMessage( i18n("No such file or directory '%1'.", errorLine.mid( 40, errorLine.length()-41 ) ),
0091                                           K3b::Job::MessageError );
0092                 d->readError = true;
0093             }
0094         }
0095         else if( line.contains( "done, estimate" ) ) {
0096             int p = parseMkisofsProgress( line );
0097             if( p != -1 )
0098                 handleMkisofsProgress( p );
0099         }
0100         else if( line.contains( "extents written" ) ) {
0101             handleMkisofsProgress( 100 );
0102         }
0103         else if( line.startsWith( "Incorrectly encoded string" ) ) {
0104             static const QRegularExpression rx("[\\(\\)]");
0105             handleMkisofsInfoMessage( i18n("Encountered an incorrectly encoded filename '%1'",
0106                                            line.section( rx, 1, 1 )), K3b::Job::MessageError );
0107             handleMkisofsInfoMessage( i18n("This may be caused by a system update which changed the local character set."), K3b::Job::MessageError );
0108             handleMkisofsInfoMessage( i18n("You may use convmv (https://j3e.de/linux/convmv/) to fix the filename encoding."), K3b::Job::MessageError );
0109             d->readError = true;
0110         }
0111         else if( line.endsWith( "has not an allowable size." ) ) {
0112             handleMkisofsInfoMessage( i18n("The boot image has an invalid size."), K3b::Job::MessageError );
0113             d->readError = true;
0114         }
0115         else if( line.endsWith( "has multiple partitions." ) ) {
0116             handleMkisofsInfoMessage( i18n("The boot image contains multiple partitions."), K3b::Job::MessageError );
0117             handleMkisofsInfoMessage( i18n("A hard-disk boot image has to contain a single partition."), K3b::Job::MessageError );
0118             d->readError = true;
0119         }
0120         else {
0121             qDebug() << "(mkisofs) " << line;
0122         }
0123     }
0124 }
0125 
0126 
0127 int K3b::MkisofsHandler::parseMkisofsProgress(const QString& line)
0128 {
0129     // in multisession mode mkisofs' progress does not start at 0 but at (X+Y)/X
0130     // where X is the data already on the cd and Y the data to create
0131     // This is not very dramatic but kind or ugly.
0132     // We just save the first emitted progress value and to some math ;)
0133 
0134     QString perStr = line;
0135     perStr.truncate(perStr.indexOf('%'));
0136     // FIXME: how to support Inuit or Samaritan Aramaic format or cover all
0137     // formats? right now it only support, for example: 0.52 and 0,52
0138     QRegExp rx("(\\d+.|,+\\d)");
0139     QStringList list;
0140     int pos = 0;
0141     bool ok;
0142     while ((pos = rx.indexIn(perStr, pos)) != -1) {
0143         list << rx.cap(1);
0144         pos += rx.matchedLength();
0145     }
0146     if (list.size() < 2)
0147         return -1;
0148     // FIXME: the same story
0149     double p = (list[0].replace(',', '.') + list[1]).toDouble(&ok);
0150     if (!ok) {
0151         qDebug() << "(K3b::MkisofsHandler) Parsing did not work for " << perStr;
0152         return -1;
0153     } else {
0154         if (d->firstProgressValue < 0)
0155             d->firstProgressValue = p;
0156 
0157         return((int)::ceil((p - d->firstProgressValue) * 100.0 /
0158                     (100.0 - d->firstProgressValue)));
0159     }
0160 }