1 /*
2
3 This file is part of the KFloppy program, part of the KDE project
4
5 Copyright (C) 2002 Adriaan de Groot <groot@kde.org>
6 Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org>
7 Copyright (C) 2015, 2016 Wolfgang Bauer <wbauer@tmo.at>
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, version 2.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
22 */
23
24 #include "format.h"
25
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include "qplatformdefs.h"
30 #include <QRegExp>
31 #include <QStandardPaths>
32 #include <QTimer>
33
34 #include <KLocalizedString>
35 #include <KProcess>
36
37 static QStringList extPath = QStringList();
38
findExecutable(const QString & e)39 /* static */ QString findExecutable(const QString &e)
40 {
41 if (extPath.isEmpty()) {
42 QStringList path = QString::fromLocal8Bit(qgetenv("PATH")).split(QStringLiteral(":"));
43 path.append(QStringLiteral("/usr/sbin"));
44 path.append(QStringLiteral("/sbin"));
45 extPath = path;
46 }
47
48 return QStandardPaths::findExecutable(e, extPath);
49 }
50
KFAction(QObject * parent)51 KFAction::KFAction(QObject *parent)
52 : QObject(parent)
53 {
54 DEBUGSETUP;
55 }
56
~KFAction()57 KFAction::~KFAction()
58 {
59 DEBUGSETUP;
60 quit();
61 }
62
quit()63 /* slot */ void KFAction::quit()
64 {
65 DEBUGSETUP;
66 }
67
exec()68 /* slot */ void KFAction::exec()
69 {
70 DEBUGSETUP;
71 }
72
73 class KFActionQueue_p
74 {
75 public:
76 QList<KFAction *> list;
77 };
78
KFActionQueue(QObject * parent)79 KFActionQueue::KFActionQueue(QObject *parent)
80 : KFAction(parent)
81 , d(new KFActionQueue_p)
82 {
83 DEBUGSETUP;
84 }
85
~KFActionQueue()86 KFActionQueue::~KFActionQueue()
87 {
88 DEBUGSETUP;
89 qDeleteAll(d->list);
90 d->list.clear();
91 delete d;
92 }
93
queue(KFAction * p)94 void KFActionQueue::queue(KFAction *p)
95 {
96 DEBUGSETUP;
97
98 d->list.append(p);
99 DEBUGS(p->objectName());
100 }
101
exec()102 /* virtual */ void KFActionQueue::exec()
103 {
104 DEBUGSETUP;
105
106 actionDone(nullptr, true);
107 }
108
actionDone(KFAction * p,bool success)109 /* slot */ void KFActionQueue::actionDone(KFAction *p, bool success)
110 {
111 DEBUGSETUP;
112
113 if (p) {
114 if (!d->list.isEmpty() && d->list.first() == p) {
115 d->list.removeFirst();
116 delete p;
117 } else {
118 DEBUGS("Strange pointer received.");
119 Q_EMIT done(this, false);
120 return;
121 }
122 } else {
123 DEBUGS("Starting action queue.");
124 }
125
126 if (!success) {
127 DEBUGS("Action failed.");
128 Q_EMIT done(this, false);
129 return;
130 }
131
132 KFAction *next = d->list.isEmpty() ? nullptr : d->list.first();
133 if (!next) {
134 Q_EMIT done(this, true);
135 } else {
136 qCDebug(KFLOPPY_LOG) << "Running action " << next->objectName();
137 QObject::connect(next, &KFAction::done, this, &KFActionQueue::actionDone);
138 // Propagate signals
139 QObject::connect(next, &KFAction::status, this, &KFAction::status);
140 QTimer::singleShot(0, next, &KFAction::exec);
141 }
142 }
143
144 // Here we have names of devices. The variable
145 // names are basically the linux device names,
146 // replace with whatever your OS needs instead.
147 //
148 //
149 #ifdef ANY_LINUX
150
151 const char *const fd0H1440[] = {"/dev/fd0u1440", "/dev/floppy/0u1440", "/dev/fd0h1440", "/dev/fd0H1440", "/dev/fd0", nullptr};
152 const char *const fd0D720[] = {"/dev/fd0u720", "/dev/floppy/0u720", "/dev/fd0D720", "/dev/fd0h720", "/dev/fd0", nullptr};
153 const char *const fd0h1200[] = {"/dev/fd0h1200", "/dev/floppy/0h1200", "/dev/fd0", nullptr};
154 const char *const fd0h360[] = {"/dev/fd0u360", "/dev/floppy/0u360", "/dev/fd0h360", "/dev/fd0d360", "/dev/fd0", nullptr};
155
156 const char *const fd1H1440[] = {"/dev/fd1u1440", "/dev/floppy/1u1440", "/dev/fd1h1440", "/dev/fd1H1440", "/dev/fd1", nullptr};
157 const char *const fd1D720[] = {"/dev/fd1u720", "/dev/floppy/1u720", "/dev/fd1D720", "/dev/fd1h720", "/dev/fd1", nullptr};
158 const char *const fd1h1200[] = {"/dev/fd1h1200", "/dev/floppy/1h1200", "/dev/fd1", nullptr};
159 const char *const fd1h360[] = {"/dev/fd1u360", "/dev/floppy/1u360", "/dev/fd1h360", "/dev/fd1d360", "/dev/fd1", nullptr};
160
161 const char *const fd0auto[] = {"/dev/fd0", nullptr};
162 const char *const fd1auto[] = {"/dev/fd1", nullptr};
163
164 #endif
165
166 #ifdef ANY_BSD
167 const char *const fd0[] = {"/dev/fd0", nullptr};
168 const char *const fd1[] = {"/dev/fd1", nullptr};
169 #endif
170
171 // Next we have a table of device names and characteristics.
172 // These are ordered according to 2*densityIndex+deviceIndex,
173 // ie. primary (0) 1440K (0) is first, then secondary (1) 1440K is
174 // second, down to secondary (1) 360k (4) in position 3*2+1=7.
175 //
176 //
177 // Note that the data originally contained in KFloppy was
178 // patently false, so most of this is fake. I guess no one ever
179 // formatted a 5.25" floppy.
180 //
181 // The flags field is unused in this implementation.
182 //
183 //
184 const fdinfo fdtable[] = {
185 #ifdef ANY_LINUX
186 // device drv blks trk flg
187 {fd0H1440, 0, 1440, 80, 0},
188 {fd1H1440, 1, 1440, 80, 0},
189 {fd0D720, 0, 720, 80, 0},
190 {fd1D720, 1, 720, 80, 0},
191 {fd0h1200, 0, 1200, 80, 0},
192 {fd1h1200, 1, 1200, 80, 0},
193 {fd0h360, 0, 360, 40, 0},
194 {fd1h360, 1, 360, 40, 0},
195 {fd0auto, 0, 0, 80, 0},
196 {fd1auto, 1, 0, 80, 0},
197 #endif
198
199 #ifdef ANY_BSD
200 // Instead of the number of tracks, which is
201 // unneeded, we record the
202 // number of F's printed during an fdformat
203 {fd0, 0, 1440, 40, 0},
204 {fd1, 1, 1440, 40, 0},
205 {fd0, 0, 720, 40, 0},
206 {fd1, 1, 720, 40, 0},
207 {fd0, 0, 1200, 40, 0},
208 {fd1, 1, 1200, 40, 0},
209 {fd0, 0, 360, 40, 0},
210 {fd1, 1, 360, 40, 0},
211 #endif
212 {nullptr, 0, 0, 0, 0}};
213
FloppyAction(QObject * p)214 FloppyAction::FloppyAction(QObject *p)
215 : KFAction(p)
216 , deviceInfo(nullptr)
217 , theProcess(nullptr)
218 {
219 DEBUGSETUP;
220 }
221
quit()222 void FloppyAction::quit()
223 {
224 DEBUGSETUP;
225 delete theProcess;
226 theProcess = nullptr;
227
228 KFAction::quit();
229 }
230
configureDevice(const QString & newDeviceName)231 bool FloppyAction::configureDevice(const QString &newDeviceName)
232 {
233 deviceInfo = nullptr; // We have not any idea what the device is
234 deviceName = newDeviceName;
235 return true; // No problem!
236 }
237
configureDevice(int drive,int density)238 bool FloppyAction::configureDevice(int drive, int density)
239 {
240 DEBUGSETUP;
241 const char *devicename = nullptr;
242
243 deviceInfo = nullptr;
244 deviceName.clear();
245
246 if ((drive < 0) || (drive > 1)) {
247 Q_EMIT status(i18n("Unexpected drive number %1.", drive), -1);
248 return false;
249 }
250
251 const fdinfo *deviceinfo = fdtable;
252 for (; deviceinfo && (deviceinfo->devices); deviceinfo++) {
253 if (deviceinfo->blocks != density)
254 continue;
255 }
256 if (!deviceinfo) {
257 Q_EMIT status(i18n("Unexpected density number %1.", density), -1);
258 return false;
259 }
260
261 deviceinfo = fdtable;
262 for (; deviceinfo && (deviceinfo->devices); deviceinfo++) {
263 if (deviceinfo->blocks != density)
264 continue;
265 if (deviceinfo->drive == drive)
266 break;
267 }
268
269 if (!deviceinfo || !deviceinfo->devices) {
270 Q_EMIT status(i18n("Cannot find a device for drive %1 and density %2.", drive, density), -1);
271 return false;
272 }
273
274 for (const char *const *devices = deviceinfo->devices; *devices; devices++) {
275 if (QT_ACCESS(*devices, W_OK) >= 0) {
276 qCDebug(KFLOPPY_LOG) << "Found device " << *devices;
277 devicename = *devices;
278 break;
279 }
280 }
281
282 if (!devicename) {
283 const QString str = i18n(
284 "Cannot access %1\nMake sure that the device exists and that "
285 "you have write permission to it.",
286 QLatin1String(deviceinfo->devices[0]));
287 Q_EMIT status(str, -1);
288 return false;
289 }
290
291 deviceName = QLatin1String(devicename);
292 deviceInfo = deviceinfo;
293
294 return true;
295 }
296
readStdOut()297 void FloppyAction::readStdOut()
298 {
299 processStdOut(QString::fromUtf8(theProcess->readAllStandardOutput()));
300 }
301
readStdErr()302 void FloppyAction::readStdErr()
303 {
304 processStdOut(QString::fromUtf8(theProcess->readAllStandardError()));
305 }
306
processDone(int exitCode,QProcess::ExitStatus exitStatus)307 void FloppyAction::processDone(int exitCode, QProcess::ExitStatus exitStatus)
308 {
309 DEBUGSETUP;
310
311 if (exitStatus == QProcess::NormalExit) {
312 if (exitCode == 0) {
313 Q_EMIT status(QString(), 100);
314 Q_EMIT done(this, true);
315 } else {
316 Q_EMIT status(i18n("The program %1 terminated with an error.", theProcessName), 100);
317 Q_EMIT done(this, false);
318 }
319 } else {
320 Q_EMIT status(i18n("The program %1 terminated abnormally.", theProcessName), 100);
321 Q_EMIT done(this, false);
322 }
323 }
324
processStdOut(const QString & s)325 void FloppyAction::processStdOut(const QString &s)
326 {
327 qCDebug(KFLOPPY_LOG) << "stdout:" << s;
328 }
329
processStdErr(const QString & s)330 void FloppyAction::processStdErr(const QString &s)
331 {
332 processStdOut(s);
333 }
334
startProcess()335 bool FloppyAction::startProcess()
336 {
337 DEBUGSETUP;
338
339 connect(theProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processDone(int, QProcess::ExitStatus)));
340 connect(theProcess, &QProcess::readyReadStandardOutput, this, &FloppyAction::readStdOut);
341 connect(theProcess, &QProcess::readyReadStandardError, this, &FloppyAction::readStdErr);
342
343 theProcess->setEnv(QStringLiteral("LC_ALL"), QStringLiteral("C")); // We need the untranslated output of the tool
344 theProcess->setOutputChannelMode(KProcess::SeparateChannels);
345 theProcess->start();
346 return (theProcess->exitStatus() == QProcess::NormalExit);
347 }
348
349 /* static */ QString FDFormat::fdformatName = QString();
350
FDFormat(QObject * p)351 FDFormat::FDFormat(QObject *p)
352 : FloppyAction(p)
353 , doVerify(true)
354 {
355 DEBUGSETUP;
356 theProcessName = QStringLiteral("fdformat");
357 setObjectName(QStringLiteral("FDFormat"));
358 }
359
runtimeCheck()360 /* static */ bool FDFormat::runtimeCheck()
361 {
362 fdformatName = findExecutable(QStringLiteral("fdformat"));
363 return (!fdformatName.isEmpty());
364 }
365
configure(bool v)366 bool FDFormat::configure(bool v)
367 {
368 doVerify = v;
369 return true;
370 }
371
exec()372 /* virtual */ void FDFormat::exec()
373 {
374 DEBUGSETUP;
375
376 if (!deviceInfo || deviceName.isEmpty()) {
377 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
378 Q_EMIT done(this, false);
379 return;
380 }
381
382 if (fdformatName.isEmpty()) {
383 Q_EMIT status(i18n("Cannot find fdformat."), -1);
384 Q_EMIT done(this, false);
385 return;
386 }
387
388 delete theProcess;
389 theProcess = new KProcess;
390
391 formatTrackCount = 0;
392
393 *theProcess << fdformatName;
394
395 // Common to Linux and BSD, others may differ
396 if (!doVerify) {
397 *theProcess << QStringLiteral("-n");
398 }
399
400 #ifdef ANY_BSD
401 *theProcess << QStringLiteral("-y") << QStringLiteral("-f") << QString::number(deviceInfo->blocks);
402 #elif defined(ANY_LINUX)
403 // No Linux-specific flags
404 #endif
405
406 // Common to Linux and BSD, others may differ
407 *theProcess << deviceName;
408
409 if (!startProcess()) {
410 Q_EMIT status(i18n("Could not start fdformat."), -1);
411 Q_EMIT done(this, false);
412 }
413
414 // Now depend on fdformat running and producing output.
415 }
416
417 // Parse some output from the fdformat process. Lots of
418 // #ifdefs here to account for variations in the basic
419 // fdformat. Uses gotos to branch to whatever error message we
420 // need, since the messages can be standardized across OSsen.
421 //
422 //
processStdOut(const QString & s)423 void FDFormat::processStdOut(const QString &s)
424 {
425 DEBUGSETUP;
426
427 #ifdef ANY_BSD
428 if (s[0] == QLatin1Char('F')) {
429 formatTrackCount++;
430 Q_EMIT status(QString(), formatTrackCount * 100 / deviceInfo->tracks);
431 } else if (s[0] == QLatin1Char('E')) {
432 Q_EMIT status(i18n("Error formatting track %1.", formatTrackCount), -1);
433 } else {
434 if (s.contains(QLatin1String("ioctl(FD_FORM)"))) {
435 Q_EMIT status(i18n("Cannot access floppy or floppy drive.\n"
436 "Please insert a floppy and make sure that you "
437 "have selected a valid floppy drive."),
438 -1);
439 return;
440 }
441 if (s.indexOf(QLatin1String("/dev/")) >= 0) {
442 Q_EMIT status(s, -1);
443 return;
444 }
445 DEBUGS(s);
446 }
447 #elif defined(ANY_LINUX)
448 DEBUGS(s);
449 QRegExp regexp(QStringLiteral("([0-9]+)"));
450 if (s.startsWith(QLatin1String("bad data at cyl")) || s.contains(QLatin1String("Problem reading cylinder"))) {
451 if (regexp.indexIn(s) > -1) {
452 const int track = regexp.cap(1).toInt();
453 Q_EMIT status(i18n("Low-level formatting error at track %1.", track), -1);
454 } else {
455 // This error should not happen
456 Q_EMIT status(i18n("Low-level formatting error: %1", s), -1);
457 }
458 return;
459 } else if (s.contains(QLatin1String("ioctl(FDFMTBEG)"))) {
460 Q_EMIT status(i18n("Cannot access floppy or floppy drive.\n"
461 "Please insert a floppy and make sure that you "
462 "have selected a valid floppy drive."),
463 -1);
464 return;
465 } else if (s.contains(QLatin1String("busy"))) // "Device or resource busy"
466 {
467 Q_EMIT status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."), -1);
468 return;
469 }
470 // Be careful to leave "iotcl" as last before checking numbers
471 else if (s.contains(QLatin1String("ioctl"))) {
472 Q_EMIT status(i18n("Low-level format error: %1", s), -1);
473 return;
474 }
475 // Check for numbers at last (as /dev/fd0u1440 has numbers too)
476 else if (regexp.indexIn(s) > -1) {
477 // Normal track number (formatting or verifying)
478 const int p = regexp.cap(1).toInt();
479 if ((p >= 0) && (p < deviceInfo->tracks)) {
480 Q_EMIT status(QString(), p * 100 / deviceInfo->tracks);
481 }
482 }
483 #endif
484 return;
485 }
486
487 /* static */ QString DDZeroOut::m_ddName = QString();
488
DDZeroOut(QObject * p)489 DDZeroOut::DDZeroOut(QObject *p)
490 : FloppyAction(p)
491 {
492 qCDebug(KFLOPPY_LOG) << k_funcinfo;
493 theProcessName = QStringLiteral("dd");
494 setObjectName(QStringLiteral("DD"));
495 }
496
runtimeCheck()497 /* static */ bool DDZeroOut::runtimeCheck()
498 {
499 m_ddName = findExecutable(QStringLiteral("dd"));
500 return (!m_ddName.isEmpty());
501 }
502
exec()503 /* virtual */ void DDZeroOut::exec()
504 {
505 qCDebug(KFLOPPY_LOG) << k_funcinfo;
506
507 if (deviceName.isEmpty()) {
508 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
509 Q_EMIT done(this, false);
510 return;
511 }
512
513 if (m_ddName.isEmpty()) {
514 Q_EMIT status(i18n("Cannot find dd."), -1);
515 Q_EMIT done(this, false);
516 return;
517 }
518
519 delete theProcess;
520 theProcess = new KProcess;
521
522 *theProcess << m_ddName;
523
524 *theProcess << QStringLiteral("if=/dev/zero");
525 *theProcess << QStringLiteral("of=") + deviceName;
526
527 if (!startProcess()) {
528 Q_EMIT status(i18n("Could not start dd."), -1);
529 Q_EMIT done(this, false);
530 }
531 }
532
processDone(int exitCode,QProcess::ExitStatus exitStatus)533 void DDZeroOut::processDone(int exitCode, QProcess::ExitStatus exitStatus)
534 {
535 Q_UNUSED(exitCode);
536 Q_UNUSED(exitStatus);
537
538 qCDebug(KFLOPPY_LOG) << k_funcinfo;
539
540 /**
541 * As we do not give a number of blocks to dd(1), it will stop
542 * with the error "No space left on device"
543 *
544 * ### TODO: really check if the exit is not on an other error and then abort the formatting
545 */
546 Q_EMIT status(QString(), 100);
547 Q_EMIT done(this, true);
548 }
549
550 /* static */ QString FATFilesystem::newfs_fat = QString();
551
FATFilesystem(QObject * parent)552 FATFilesystem::FATFilesystem(QObject *parent)
553 : FloppyAction(parent)
554 {
555 DEBUGSETUP;
556 runtimeCheck();
557 theProcessName = newfs_fat;
558 setObjectName(QStringLiteral("FATFilesystem"));
559 }
560
runtimeCheck()561 /* static */ bool FATFilesystem::runtimeCheck()
562 {
563 DEBUGSETUP;
564
565 #ifdef ANY_BSD
566 newfs_fat = findExecutable(QStringLiteral("newfs_msdos"));
567 #elif defined(ANY_LINUX)
568 newfs_fat = findExecutable(QStringLiteral("mkdosfs"));
569 #else
570 return false;
571 #endif
572
573 return !newfs_fat.isEmpty();
574 }
575
configure(bool v,bool l,const QString & lbl)576 bool FATFilesystem::configure(bool v, bool l, const QString &lbl)
577 {
578 doVerify = v;
579 doLabel = l;
580 if (l)
581 label = lbl.simplified();
582 else
583 label.clear();
584
585 return true;
586 }
587
exec()588 void FATFilesystem::exec()
589 {
590 DEBUGSETUP;
591
592 if (
593 #ifdef ANY_BSD // BSD needs the deviceInfo for the block count
594 !deviceInfo ||
595 #endif
596 deviceName.isEmpty()) {
597 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
598 Q_EMIT done(this, false);
599 return;
600 }
601
602 if (newfs_fat.isEmpty()) {
603 Q_EMIT status(i18n("Cannot find a program to create FAT filesystems."), -1);
604 Q_EMIT done(this, false);
605 return;
606 }
607
608 delete theProcess;
609 KProcess *p = theProcess = new KProcess;
610
611 *p << newfs_fat;
612 #ifdef ANY_BSD
613 *p << QStringLiteral("-f") << QString::number(deviceInfo->blocks);
614 if (doLabel) {
615 *p << QStringLiteral("-L") << label;
616 }
617 #else
618 #ifdef ANY_LINUX
619 if (doLabel) {
620 *p << QStringLiteral("-n") << label;
621 }
622 if (doVerify) {
623 *p << QStringLiteral("-c");
624 }
625 #endif
626 #endif
627 *p << deviceName;
628
629 if (!startProcess()) {
630 Q_EMIT status(i18n("Cannot start FAT format program."), -1);
631 Q_EMIT done(this, false);
632 }
633 }
634
processStdOut(const QString & s)635 void FATFilesystem::processStdOut(const QString &s)
636 {
637 #ifdef ANY_BSD
638 // ### TODO: do some checks
639 #elif defined(ANY_LINUX)
640 qCDebug(KFLOPPY_LOG) << s;
641 if (s.contains(QLatin1String("mounted"))) // "/dev/fd0 contains a mounted filesystem"
642 {
643 Q_EMIT status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."), -1);
644 return;
645 } else if (s.contains(QLatin1String("busy"))) // "Device or resource busy"
646 {
647 Q_EMIT status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."), -1);
648 return;
649 } else if (s.contains(QLatin1String("denied"))) // "Permission denied"
650 {
651 Q_EMIT status(s, -1);
652 return;
653 }
654 #if 0
655 else if ( s.find( "mkdosfs" ) != -1 ) // DEBUG: get the program header and show it!
656 {
657 Q_EMIT status( s, -1 );
658 return;
659 }
660 #endif
661 #endif
662 }
663
664 #ifdef ANY_BSD
665
666 /* static */ QString UFSFilesystem::newfs = QString();
667
UFSFilesystem(QObject * parent)668 UFSFilesystem::UFSFilesystem(QObject *parent)
669 : FloppyAction(parent)
670 {
671 DEBUGSETUP;
672 runtimeCheck();
673 theProcessName = newfs;
674 setObjectName(QStringLiteral("UFSFilesystem"));
675 }
676
runtimeCheck()677 /* static */ bool UFSFilesystem::runtimeCheck()
678 {
679 DEBUGSETUP;
680
681 newfs = findExecutable(QStringLiteral("newfs"));
682
683 return !newfs.isEmpty();
684 }
685
exec()686 void UFSFilesystem::exec()
687 {
688 DEBUGSETUP;
689
690 if (deviceName.isEmpty()) {
691 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
692 Q_EMIT done(this, false);
693 return;
694 }
695
696 if (newfs.isEmpty()) {
697 Q_EMIT status(i18nc("BSD", "Cannot find a program to create UFS filesystems."), -1);
698 Q_EMIT done(this, false);
699 return;
700 }
701
702 delete theProcess;
703 KProcess *p = theProcess = new KProcess;
704
705 *p << newfs;
706
707 // ### TODO: is it still needed? (FreeBSD 5.3's man page says: "For backward compatibility.")
708 if (deviceInfo)
709 *p << QStringLiteral("-T") << QStringLiteral("fd%1").arg(deviceInfo->blocks);
710
711 *p << deviceName;
712
713 if (!startProcess()) {
714 Q_EMIT status(i18nc("BSD", "Cannot start UFS format program."), -1);
715 Q_EMIT done(this, false);
716 }
717 }
718 #endif
719
720 /* static */ QString Ext2Filesystem::newfs = QString();
721
Ext2Filesystem(QObject * parent)722 Ext2Filesystem::Ext2Filesystem(QObject *parent)
723 : FloppyAction(parent)
724 {
725 DEBUGSETUP;
726 runtimeCheck();
727 theProcessName = QStringLiteral("mke2fs");
728 setObjectName(QStringLiteral("Ext2Filesystem"));
729 }
730
runtimeCheck()731 /* static */ bool Ext2Filesystem::runtimeCheck()
732 {
733 DEBUGSETUP;
734
735 newfs = findExecutable(QStringLiteral("mke2fs"));
736
737 return !newfs.isEmpty();
738 }
739
configure(bool v,bool l,const QString & lbl)740 bool Ext2Filesystem::configure(bool v, bool l, const QString &lbl)
741 {
742 doVerify = v;
743 doLabel = l;
744 if (l) {
745 label = lbl.trimmed();
746 } else {
747 label.clear();
748 }
749
750 return true;
751 }
752
exec()753 void Ext2Filesystem::exec()
754 {
755 DEBUGSETUP;
756
757 if (
758 #ifdef ANY_BSD // BSD needs the deviceInfo for the block count
759 !deviceInfo ||
760 #endif
761 deviceName.isEmpty()) {
762 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
763 Q_EMIT done(this, false);
764 return;
765 }
766
767 if (newfs.isEmpty()) {
768 Q_EMIT status(i18n("Cannot find a program to create ext2 filesystems."), -1);
769 Q_EMIT done(this, false);
770 return;
771 }
772
773 delete theProcess;
774 KProcess *p = theProcess = new KProcess;
775
776 *p << newfs;
777 *p << QStringLiteral("-q");
778 if (doVerify)
779 *p << QStringLiteral("-c");
780 if (doLabel)
781 *p << QStringLiteral("-L") << label;
782
783 *p << deviceName;
784
785 if (!startProcess()) {
786 Q_EMIT status(i18n("Cannot start ext2 format program."), -1);
787 Q_EMIT done(this, false);
788 }
789 }
790
processStdOut(const QString & s)791 void Ext2Filesystem::processStdOut(const QString &s)
792 {
793 #ifdef ANY_BSD
794 // ### TODO: do some checks
795 #elif defined(ANY_LINUX)
796 qCDebug(KFLOPPY_LOG) << s;
797 if (s.contains(QLatin1String("mounted"))) // "/dev/fd0 is mounted; will not make a filesystem here!"
798 {
799 Q_EMIT status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."), -1);
800 return;
801 } else if (s.contains(QLatin1String("busy"))) // "Device or resource busy"
802 {
803 Q_EMIT status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."), -1);
804 return;
805 } else if (s.contains(QLatin1String("denied"))) // "Permission denied"
806 {
807 Q_EMIT status(s, -1);
808 return;
809 }
810 #endif
811 }
812
813 #ifdef ANY_LINUX
814 /* static */ QString MinixFilesystem::newfs = QString();
815
MinixFilesystem(QObject * parent)816 MinixFilesystem::MinixFilesystem(QObject *parent)
817 : FloppyAction(parent)
818 {
819 DEBUGSETUP;
820 runtimeCheck();
821 theProcessName = QStringLiteral("mkfs.minix");
822 setObjectName(QStringLiteral("Minix2Filesystem"));
823 }
824
runtimeCheck()825 /* static */ bool MinixFilesystem::runtimeCheck()
826 {
827 DEBUGSETUP;
828
829 newfs = findExecutable(QStringLiteral("mkfs.minix"));
830
831 return !newfs.isEmpty();
832 }
833
configure(bool v,bool l,const QString & lbl)834 bool MinixFilesystem::configure(bool v, bool l, const QString &lbl)
835 {
836 doVerify = v;
837 doLabel = l;
838 if (l) {
839 label = lbl.trimmed();
840 } else {
841 label.clear();
842 }
843
844 return true;
845 }
846
exec()847 void MinixFilesystem::exec()
848 {
849 DEBUGSETUP;
850
851 if (deviceName.isEmpty()) {
852 Q_EMIT status(i18n("Internal error: device not correctly defined."), -1);
853 Q_EMIT done(this, false);
854 return;
855 }
856
857 if (newfs.isEmpty()) {
858 Q_EMIT status(i18n("Cannot find a program to create Minix filesystems."), -1);
859 Q_EMIT done(this, false);
860 return;
861 }
862
863 delete theProcess;
864 KProcess *p = theProcess = new KProcess;
865
866 *p << newfs;
867
868 // Labeling is not possible
869 if (doVerify)
870 *p << QStringLiteral("-c");
871
872 *p << deviceName;
873
874 if (!startProcess()) {
875 Q_EMIT status(i18n("Cannot start Minix format program."), -1);
876 Q_EMIT done(this, false);
877 }
878 }
879
processStdOut(const QString & s)880 void MinixFilesystem::processStdOut(const QString &s)
881 {
882 qCDebug(KFLOPPY_LOG) << s;
883 if (s.contains(QLatin1String("mounted"))) // "mkfs.minix: /dev/fd0 is mounted; will not make a filesystem here!"
884 {
885 Q_EMIT status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."), -1);
886 return;
887 } else if (s.contains(QLatin1String("busy"))) // "Device or resource busy"
888 {
889 Q_EMIT status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."), -1);
890 return;
891 } else if (s.contains(QLatin1String("denied"))) // "Permission denied"
892 {
893 Q_EMIT status(s, -1);
894 return;
895 }
896 }
897
898 #endif
899