1 /*
2 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
3 SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6 #include "k3bmkisofshandler.h"
7
8 #include "k3bexternalbinmanager.h"
9 #include "k3bcore.h"
10 #include "k3bjob.h"
11 #include "k3b_i18n.h"
12
13 #include <QDebug>
14
15 #include <cmath>
16
17
18
19 class K3b::MkisofsHandler::Private
20 {
21 public:
22 const K3b::ExternalBin* mkisofsBin;
23 double firstProgressValue;
24 bool readError;
25 };
26
27
MkisofsHandler()28 K3b::MkisofsHandler::MkisofsHandler()
29 {
30 d = new Private;
31 d->mkisofsBin = 0;
32 }
33
34
~MkisofsHandler()35 K3b::MkisofsHandler::~MkisofsHandler()
36 {
37 delete d;
38 }
39
40
mkisofsReadError() const41 bool K3b::MkisofsHandler::mkisofsReadError() const
42 {
43 return d->readError;
44 }
45
46
initMkisofs()47 const K3b::ExternalBin* K3b::MkisofsHandler::initMkisofs()
48 {
49 d->mkisofsBin = k3bcore->externalBinManager()->binObject( "mkisofs" );
50
51 if( d->mkisofsBin ) {
52 if( !d->mkisofsBin->copyright().isEmpty() )
53 handleMkisofsInfoMessage( i18n("Using %1 %2 – Copyright © %3",
54 QString("mkisofs"),
55 d->mkisofsBin->version(),
56 d->mkisofsBin->copyright()),
57 K3b::Job::MessageInfo );
58
59 d->firstProgressValue = -1;
60 d->readError = false;
61 }
62 else {
63 qDebug() << "(K3b::MkisofsHandler) could not find mkisofs executable";
64 handleMkisofsInfoMessage( i18n("Mkisofs executable not found."), K3b::Job::MessageError );
65 }
66
67 return d->mkisofsBin;
68 }
69
70
parseMkisofsOutput(const QString & line)71 void K3b::MkisofsHandler::parseMkisofsOutput( const QString& line )
72 {
73 if( !line.isEmpty() ) {
74 if( line.startsWith( d->mkisofsBin->path() ) ) {
75 // error or warning
76 QString errorLine = line.mid( d->mkisofsBin->path().length() + 2 );
77 if( errorLine.startsWith( "Input/output error. Cannot read from" ) ) {
78 handleMkisofsInfoMessage( i18n("Read error from file '%1'", errorLine.mid( 38, errorLine.length()-40 ) ),
79 K3b::Job::MessageError );
80 d->readError = true;
81 }
82 else if( errorLine.startsWith( "Value too large for defined data type" ) ) {
83 handleMkisofsInfoMessage( i18n("Used version of mkisofs does not have large file support."), K3b::Job::MessageError );
84 handleMkisofsInfoMessage( i18n("Files bigger than 2 GB cannot be handled."), K3b::Job::MessageError );
85 d->readError = true;
86 }
87 else if( errorLine.startsWith( "No such file or directory. cannot open" ) ) {
88 handleMkisofsInfoMessage( i18n("No such file or directory '%1'.", errorLine.mid( 40, errorLine.length()-41 ) ),
89 K3b::Job::MessageError );
90 d->readError = true;
91 }
92 }
93 else if( line.contains( "done, estimate" ) ) {
94 int p = parseMkisofsProgress( line );
95 if( p != -1 )
96 handleMkisofsProgress( p );
97 }
98 else if( line.contains( "extents written" ) ) {
99 handleMkisofsProgress( 100 );
100 }
101 else if( line.startsWith( "Incorrectly encoded string" ) ) {
102 handleMkisofsInfoMessage( i18n("Encountered an incorrectly encoded filename '%1'",
103 line.section( QRegExp("[\\(\\)]"), 1, 1 )), K3b::Job::MessageError );
104 handleMkisofsInfoMessage( i18n("This may be caused by a system update which changed the local character set."), K3b::Job::MessageError );
105 handleMkisofsInfoMessage( i18n("You may use convmv (https://j3e.de/linux/convmv/) to fix the filename encoding."), K3b::Job::MessageError );
106 d->readError = true;
107 }
108 else if( line.endsWith( "has not an allowable size." ) ) {
109 handleMkisofsInfoMessage( i18n("The boot image has an invalid size."), K3b::Job::MessageError );
110 d->readError = true;
111 }
112 else if( line.endsWith( "has multiple partitions." ) ) {
113 handleMkisofsInfoMessage( i18n("The boot image contains multiple partitions."), K3b::Job::MessageError );
114 handleMkisofsInfoMessage( i18n("A hard-disk boot image has to contain a single partition."), K3b::Job::MessageError );
115 d->readError = true;
116 }
117 else {
118 qDebug() << "(mkisofs) " << line;
119 }
120 }
121 }
122
123
parseMkisofsProgress(const QString & line)124 int K3b::MkisofsHandler::parseMkisofsProgress(const QString& line)
125 {
126 // in multisession mode mkisofs' progress does not start at 0 but at (X+Y)/X
127 // where X is the data already on the cd and Y the data to create
128 // This is not very dramatic but kind or ugly.
129 // We just save the first emitted progress value and to some math ;)
130
131 QString perStr = line;
132 perStr.truncate(perStr.indexOf('%'));
133 // FIXME: how to support Inuit or Samaritan Aramaic format or cover all
134 // formats? right now it only support, for example: 0.52 and 0,52
135 QRegExp rx("(\\d+.|,+\\d)");
136 QStringList list;
137 int pos = 0;
138 bool ok;
139 while ((pos = rx.indexIn(perStr, pos)) != -1) {
140 list << rx.cap(1);
141 pos += rx.matchedLength();
142 }
143 if (list.size() < 2)
144 return -1;
145 // FIXME: the same story
146 double p = (list[0].replace(',', '.') + list[1]).toDouble(&ok);
147 if (!ok) {
148 qDebug() << "(K3b::MkisofsHandler) Parsing did not work for " << perStr;
149 return -1;
150 } else {
151 if (d->firstProgressValue < 0)
152 d->firstProgressValue = p;
153
154 return((int)::ceil((p - d->firstProgressValue) * 100.0 /
155 (100.0 - d->firstProgressValue)));
156 }
157 }
158