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 }