diff options
Diffstat (limited to 'kfloppy')
-rw-r--r-- | kfloppy/KFloppy.desktop | 96 | ||||
-rw-r--r-- | kfloppy/Makefile.am | 23 | ||||
-rw-r--r-- | kfloppy/README | 23 | ||||
-rw-r--r-- | kfloppy/TODO | 47 | ||||
-rw-r--r-- | kfloppy/debug.h | 65 | ||||
-rw-r--r-- | kfloppy/floppy.cpp | 741 | ||||
-rw-r--r-- | kfloppy/floppy.h | 128 | ||||
-rw-r--r-- | kfloppy/floppy_format.desktop | 54 | ||||
-rw-r--r-- | kfloppy/format.cpp | 996 | ||||
-rw-r--r-- | kfloppy/format.h | 426 | ||||
-rw-r--r-- | kfloppy/hi128-app-kfloppy.png | bin | 0 -> 12698 bytes | |||
-rw-r--r-- | kfloppy/hi16-app-kfloppy.png | bin | 0 -> 1008 bytes | |||
-rw-r--r-- | kfloppy/hi22-app-kfloppy.png | bin | 0 -> 1397 bytes | |||
-rw-r--r-- | kfloppy/hi32-app-kfloppy.png | bin | 0 -> 2374 bytes | |||
-rw-r--r-- | kfloppy/hi48-app-kfloppy.png | bin | 0 -> 3812 bytes | |||
-rw-r--r-- | kfloppy/hi64-app-kfloppy.png | bin | 0 -> 5298 bytes | |||
-rw-r--r-- | kfloppy/main.cpp | 79 | ||||
-rw-r--r-- | kfloppy/zip.cpp | 305 | ||||
-rw-r--r-- | kfloppy/zip.h | 106 |
19 files changed, 3089 insertions, 0 deletions
diff --git a/kfloppy/KFloppy.desktop b/kfloppy/KFloppy.desktop new file mode 100644 index 0000000..113a24d --- /dev/null +++ b/kfloppy/KFloppy.desktop @@ -0,0 +1,96 @@ +[Desktop Entry] +GenericName=Floppy Formatter +GenericName[af]=Sagteskyf Formateerder +GenericName[ar]=مهئ الأقراص المرنة +GenericName[az]=Disket Şəkilləndirici +GenericName[bg]=Форматиране на дискети +GenericName[br]=Furmader pladennig +GenericName[bs]=Formatiranje disketa +GenericName[ca]=Formatador de disquet +GenericName[cs]=Formátovač disket +GenericName[cy]=Fformatio Disg Meddal +GenericName[da]=Disketteformatering +GenericName[de]=Diskettenformatierer +GenericName[el]=Εργαλείο διαμόρφωσης δισκέτας +GenericName[eo]=Formatilo por disketoj +GenericName[es]=Formateador de disquetes +GenericName[et]=Diskettide vormindamise utiliit +GenericName[eu]=Diskete Eratzailea +GenericName[fa]=قالببندیکنندۀ فلاپی +GenericName[fi]=Levykkeiden alustusohjelma +GenericName[fr]=Outil de formatage de disquette +GenericName[ga]=Uirlis Fhormáidithe Dioscaí Boga +GenericName[gl]=Formatador de Disquetes +GenericName[he]=מאתחל תקליטונים +GenericName[hi]=फ़्लॉपी फार्मेटर +GenericName[hr]=Formatiranje disketa +GenericName[hu]=Floppy-formázó +GenericName[id]=Pemformat disket +GenericName[is]=Tól til að forsníða disklinga +GenericName[it]=Formattatore di dischetti +GenericName[ja]=フロッピーをフォーマット +GenericName[ka]=დისკეტის დამფორმატებელი +GenericName[kk]=Иілгіш дискін пішімдеу +GenericName[km]=កម្មវិធីធ្វើទ្រង់ទ្រាយថាស់ទន់ +GenericName[ko]=플로피 디스크를 포맷해주는 도구 +GenericName[lt]=Diskelio formatavimas +GenericName[lv]=Diskešu Formatētājs +GenericName[mk]=Форматирање на дискети +GenericName[ms]=Pengformat Cakera Liut +GenericName[mt]=Għodda biex tifformattja floppies +GenericName[nb]=Diskettformaterer +GenericName[nds]=Diskettformaterer +GenericName[ne]=फ्लपी ढाँचाकर्ता +GenericName[nl]=Diskettes formatteren +GenericName[nn]=Formaterer diskettar +GenericName[pa]=ਫਲਾਪੀ ਫਾਰਮਿਟਰ +GenericName[pl]=Program formatujący dyskietki +GenericName[pt]=Formatação de Disquetes +GenericName[pt_BR]=Formatador de disquetes +GenericName[ro]=Formator floppy-disc-uri +GenericName[ru]=Форматирование дискет +GenericName[sk]=Formátovanie diskiet +GenericName[sl]=Formatiranje disket +GenericName[sr]=Форматирање дискета +GenericName[sr@Latn]=Formatiranje disketa +GenericName[sv]=Formatera disketter +GenericName[ta]=நெகிழ்வட்டு வடிவமைப்பான் +GenericName[tg]=Шаклбанднамоии Диски Нарм +GenericName[th]=เครื่องมือฟอร์แมตแผ่นฟลอปปี้้ +GenericName[tr]=Disket Biçimlendirici +GenericName[uk]=Відформатувати дискету +GenericName[uz]=Disketni formatlagich +GenericName[uz@cyrillic]=Дискетни форматлагич +GenericName[ven]=Muvhekanyi wa Floppy +GenericName[vi]=Trình định dạng đĩa +GenericName[wa]=Usteye po-z abwesner des plaketes +GenericName[xh]=Floppy formata +GenericName[zh_CN]=软盘格式化程序 +GenericName[zh_TW]=軟碟格式化程式 +GenericName[zu]=Umakhi we-floppy +Name=KFloppy +Name[af]=Kfloppie +Name[eo]=Disketingo +Name[hi]=के-फ़्लॉपी +Name[lv]=KMīkstnis +Name[ne]=केडीई फ्लपी +Name[pa]=ਕਫਲਾਪੀ +Name[pl]=Dyskietka +Name[pt_BR]=Disquete +Name[sv]=Kfloppy +Name[ta]=கேநெகிழ்வட்டு +Name[tg]=KДиски Нарм +Name[th]=ฟอร์แมตฟลอปปี้ +Name[tr]=Disket Biçimlendirici +Name[wa]=KPlakete +Name[zh_TW]=KDE 軟碟 +MimeType= +DocPath=kfloppy/index.html +Exec=kfloppy -caption "%c" %i %m +Icon=kfloppy +Path= +Type=Application +Terminal=false +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility;X-KDE-Utilities-Peripherals; diff --git a/kfloppy/Makefile.am b/kfloppy/Makefile.am new file mode 100644 index 0000000..83b0411 --- /dev/null +++ b/kfloppy/Makefile.am @@ -0,0 +1,23 @@ +kfloppy_LDFLAGS = $(all_libraries) $(KDE_RPATH) +kfloppy_LDADD = $(LIB_KDEUI) -lm +INCLUDES = $(all_includes) + +####### Files + +bin_PROGRAMS = kfloppy + +noinst_HEADERS = floppy.h +kfloppy_SOURCES = main.cpp format.cpp floppy.cpp + +METASOURCES = format.moc floppy.moc + +KDE_ICON = kfloppy + +xdg_apps_DATA = KFloppy.desktop + +servicedata_DATA = floppy_format.desktop +servicedatadir = $(kde_datadir)/konqueror/servicemenus + +messages: + $(XGETTEXT) $(kfloppy_SOURCES) -o $(podir)/kfloppy.pot + diff --git a/kfloppy/README b/kfloppy/README new file mode 100644 index 0000000..79c40ce --- /dev/null +++ b/kfloppy/README @@ -0,0 +1,23 @@ +KFloppy 2.1 +=========== + +KFloppy was "done and feature complete and bug free", for systems +running Linux. Other KDE platforms had an app that put up a warning +box and was then totally inert. I've restructured the whole thing, +cleaned up the code somewhat, and modularized it. + +Currently KFloppy is tested on a FBSD machine with a floppy drive +and a zip drive. It should still behave on Linux, but I haven't tried. + +KFloppy 0.2 +=========== + + KFloppy formats disks and puts a DOS or ext2fs filesystem on +them. + +Best Regards, +Bernd Wuebben +wuebben@kde.org + + + diff --git a/kfloppy/TODO b/kfloppy/TODO new file mode 100644 index 0000000..6df5f2b --- /dev/null +++ b/kfloppy/TODO @@ -0,0 +1,47 @@ +2005-06-07 + +As I am wirting an answer to an email about the to-do in KFloppy, +better have it in the source too. + + + +The biggest challenge was to support non-legacy (USB, IDE...) floppy drives. +I have opened a way to it with what has the working title "user-given devices". +(A better title for the feature would be a good thing too. +It just mean that instead of selecting "Primary" or "Secondary" as floppy drive, +you can give a device, like /dev/sda4 ) + +The "user-given device" is pretty raw currently, allowing nearly no comfort for +the user. So if you have an external drive (may a ZIP drive), you could try to +make this mode better. + +A little variant would be to support the device like /dev/fd0u2880 for +formatting. Currently it does not work with Full Format, +as a "user-given device" is supposed not to be low-level formatable. +(I do not know any Linux or BSD tool that can low-level format +non-legacy drives.) + +Another thing that I have very recently discovered is that +extended floppy drives will not work in "superfloppy" format +(disks without partition table), as neither mkdosfs nor BSD's newfs allow this +without a special parameter. (I have not checked the other tools used.) + +Before I forget it: in the "user-given device" mode, it would be nice if there +was support from KDE (for example devices:/ ) to know what devices are really +flopy drives (not that a user roasts an umounted partition of his harddisk. + +A much easier task would be perhaps to catch more errors from +the external programs so that it is displayed to the user. +(Also to catch anything error message having the string "error" in it, +which is currently not done.) + +That is I think the list of what users could benefit. + +Internally, when the Qt4 switch is done, it would need a review to see how +to improve the way how the classes calling the external applications are +handled. + +Of course, when modifying, care must taken not to break the BSD part of the +code. (Perhaps we need a way on Linux to be able to compile the BSD part, +as there is nothing BSD specific in the code, only the external BSD programs +are specific.) diff --git a/kfloppy/debug.h b/kfloppy/debug.h new file mode 100644 index 0000000..e0080da --- /dev/null +++ b/kfloppy/debug.h @@ -0,0 +1,65 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2003 Adriaan de Groot <groot@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program in a file called COPYING; if not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + +*/ + +#ifndef DEBUG_H +#define DEBUG_H + +/** + * \file debug.h + * + * \brief Debugging definitions for KFloppy. + * + * It also tries to map operating systems + * into families, so you can use ANY_LINUX or ANY_BSD + * in the code to differentiate those families. + * What happens on other systems is anyone's guess. + */ + + +#define KFAREA (2002) + +#ifndef NDEBUG +#define DEBUGSETUP kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl +#define DEBUGS(a) kdDebug(KFAREA) << " " << a << endl +#else +#define DEBUGSETUP +#define DEBUGS(a) +#endif + + +// Detect vaguely what OS we're working with. Map variants +// to one known kind. +// +// +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#define ANY_BSD (1) +#else +#if defined(linux) || defined(LINUX) || defined (__linux) || defined(__linux__) +#define ANY_LINUX (1) +#endif +#endif + + + +#endif + diff --git a/kfloppy/floppy.cpp b/kfloppy/floppy.cpp new file mode 100644 index 0000000..043f2f0 --- /dev/null +++ b/kfloppy/floppy.cpp @@ -0,0 +1,741 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include <qlayout.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qcursor.h> +#include <qradiobutton.h> +#include <qbuttongroup.h> +#include <qwhatsthis.h> + +#include <kconfig.h> + +#include <kmessagebox.h> +#include <kdebug.h> +#include <khelpmenu.h> +#include <kpushbutton.h> +#include <kpopupmenu.h> +#include <kapplication.h> +#include <kprogress.h> +#include <klocale.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <dcopref.h> +#include <kurl.h> + +#include "floppy.h" +#include "format.h" + +FloppyData::FloppyData(QWidget * parent, const char * name) + : KDialog( parent, name ), + formatActions(0L), m_canLowLevel(false), m_canZeroOut( false ) +{ + + formating = false; + //abort = false; + blocks = 0; + + QVBoxLayout* ml = new QVBoxLayout( this, 10 ); + + QHBoxLayout* h1 = new QHBoxLayout( ml ); + + QVBoxLayout* v1 = new QVBoxLayout( h1 ); + h1->addSpacing( 5 ); + + QGridLayout* g1 = new QGridLayout( v1, 3, 2 ); + + deviceComboBox = new KComboBox( false, this, "ComboBox_1" ); + label1 = new QLabel( deviceComboBox, i18n("Floppy &drive:"), this ); + g1->addWidget( label1, 0, 0, AlignLeft ); + g1->addWidget( deviceComboBox, 0, 1 ); + + // Make the combo box editable, so that the user can enter a device name + deviceComboBox->setEditable( true ); + + deviceComboBox->insertItem(i18n("Primary")); + deviceComboBox->insertItem(i18n("Secondary")); + + const QString deviceWhatsThis = i18n("<qt>Select the floppy drive.</qt>"); + + QWhatsThis::add(label1, deviceWhatsThis); + QWhatsThis::add(deviceComboBox, deviceWhatsThis); + + + densityComboBox = new KComboBox( false, this, "ComboBox_1" ); + label2 = new QLabel( densityComboBox, i18n("&Size:"), this); + g1->addWidget( label2, 1, 0, AlignLeft ); + g1->addWidget( densityComboBox, 1, 1 ); + +#if defined(ANY_LINUX) + densityComboBox->insertItem( i18n( "Auto-Detect" ) ); +#endif + densityComboBox->insertItem(i18n("3.5\" 1.44MB")); + densityComboBox->insertItem(i18n("3.5\" 720KB")); + densityComboBox->insertItem(i18n("5.25\" 1.2MB")); + densityComboBox->insertItem(i18n("5.25\" 360KB")); + + const QString densityWhatsThis = + i18n("<qt>This allows you to select the " + "floppy disk's size and density.</qt>"); + + QWhatsThis::add(label2, densityWhatsThis); + QWhatsThis::add(densityComboBox, densityWhatsThis); + + + filesystemComboBox = new KComboBox( false, this, "ComboBox_2" ); + label3 = new QLabel( filesystemComboBox, i18n("F&ile system:"), this); + g1->addWidget( label3, 2, 0, AlignLeft ); + g1->addWidget( filesystemComboBox, 2, 1 ); + g1->setColStretch(1, 1); + +#if defined(ANY_LINUX) + QWhatsThis::add( label3, + i18n( "Linux", "KFloppy supports three file formats under Linux: MS-DOS, Ext2, and Minix" ) ); +#elif defined(ANY_BSD) + QWhatsThis::add( label3, + i18n( "BSD", "KFloppy supports three file formats under BSD: MS-DOS, UFS, and Ext2" ) ); +#endif + // If you modify the user visible string, change them also (far) below + + QString userFeedBack; + uint numFileSystems = 0; + +#if defined(ANY_LINUX) + QWhatsThis::add( filesystemComboBox, + i18n( "Linux", "KFloppy supports three file formats under Linux: MS-DOS, Ext2, and Minix" ) ); + if (FATFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("DOS")); + ++numFileSystems; + userFeedBack += i18n( "Linux", "Program mkdosfs found." ); + } + else { + userFeedBack += i18n( "Linux", "Program mkdosfs <b>not found</b>. MSDOS formatting <b>not available</b>." ); + } + userFeedBack += "<br>"; + if (Ext2Filesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("ext2")); + ++numFileSystems; + userFeedBack += i18n( "Program mke2fs found." ); + } + else { + userFeedBack += i18n( "Program mke2fs <b>not found</b>. Ext2 formatting <b>not available</b>" ); + } + userFeedBack += "<br>"; + if (MinixFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("Minix")); + ++numFileSystems; + userFeedBack += i18n( "Linux", "Program mkfs.minix found." ); + } + else { + userFeedBack += i18n( "Linux", "Program mkfs.minix <b>not found</b>. Minix formatting <b>not available</b>" ); + } +#elif defined(ANY_BSD) + QWhatsThis::add( filesystemComboBox, + i18n( "BSD", "KFloppy supports two file formats under BSD: MS-DOS and UFS" ) ); + if (FATFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("DOS")); + ++numFileSystems; + userFeedBack += i18n( "BSD", "Program newfs_msdos found." ); + } + else { + userFeedBack += i18n( "BSD", "Program newfs_msdos <b>not found</b>. MSDOS formatting <b>not available</b>." ); + } + userFeedBack += "<br>"; + if (UFSFilesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("UFS")); + ++numFileSystems; + userFeedBack += i18n( "BSD", "Program newfs found." ); + } + else { + userFeedBack += i18n( "BSD", "Program newfs <b>not found</b>. UFS formatting <b>not available</b>." ); + } + userFeedBack += "<br>"; + if (Ext2Filesystem::runtimeCheck()) { + filesystemComboBox->insertItem(i18n("ext2")); + ++numFileSystems; + userFeedBack += i18n( "Program mke2fs found." ); + } + else { + userFeedBack += i18n( "Program mke2fs <b>not found</b>. Ext2 formatting <b>not available</b>" ); + } +#endif + + v1->addSpacing( 10 ); + + buttongroup = new QButtonGroup( 3, Qt::Vertical, i18n("&Formatting"), this, "ButtonGroup_1" ); + + + quick = new QRadioButton( i18n( "Q&uick format" ), buttongroup, "RadioButton_2" ); + QWhatsThis::add( quick, + i18n("<qt>Quick format is only a high-level format:" + " it creates only a file system.</qt>") ); + + zerooutformat = new QRadioButton( i18n( "&Zero out and quick format"), buttongroup, "RadioButton_ZeroOutFormat" ); + QWhatsThis::add( zerooutformat, + i18n("<qt>This first erases the floppy by writing zeros and then it creates the file system.</qt>") ); + + fullformat = new QRadioButton( i18n( "Fu&ll format"), buttongroup, "RadioButton_3" ); + QWhatsThis::add( fullformat, + i18n("Full format is a low-level and high-level format. It erases everything on the disk.") ); + + v1->addWidget( buttongroup ); + + // ### TODO: we need some user feedback telling why full formatting is disabled. + userFeedBack += "<br>"; + m_canLowLevel = FDFormat::runtimeCheck(); + if (m_canLowLevel){ + fullformat->setChecked(true); + userFeedBack += i18n( "Program fdformat found." ); + } + else { + fullformat->setDisabled(true); + quick->setChecked(true); + userFeedBack += i18n( "Program fdformat <b>not found</b>. Full formatting <b>disabled</b>." ); + } + userFeedBack += "<br>"; + m_canZeroOut = DDZeroOut::runtimeCheck(); + if ( m_canZeroOut ) + { + zerooutformat->setChecked( true ); + userFeedBack += i18n( "Program dd found." ); + } + else { + zerooutformat->setDisabled(true); + userFeedBack += i18n( "Program dd <b>not found</b>. Zeroing-out <b>disabled</b>." ); + } + + verifylabel = new QCheckBox( this, "CheckBox_Integrity" ); + verifylabel->setText(i18n( "&Verify integrity" )); + verifylabel->setChecked(true); + v1->addWidget( verifylabel, AlignLeft ); + QWhatsThis::add( verifylabel, + i18n("<qt>Check this if you want the floppy disk to be checked after formatting." + " Please note that the floppy will be checked twice if you have selected full formatting.</qt>") ); + + labellabel = new QCheckBox( this, "Checkbox_Label" ); + labellabel->setText(i18n( "Volume la&bel:") ); + labellabel->setChecked(true); + v1->addWidget( labellabel, AlignLeft ); + QWhatsThis::add( labellabel, + i18n("<qt>Check this if you want a volume label for your floppy." + " Please note that Minix does not support labels at all.</qt>") ); + + QHBoxLayout* h2 = new QHBoxLayout( v1 ); + h2->addSpacing( 20 ); + + lineedit = new KLineEdit( this, "Lineedit" ); + // ### TODO ext2 supports 16 characters. Minix has not any label. UFS? + lineedit->setText(i18n( "Volume label, maximal 11 characters", "KDE Floppy" ) ); + lineedit->setMaxLength(11); + h2->addWidget( lineedit, AlignRight ); + QWhatsThis::add( lineedit, + i18n("<qt>This is for the volume label." + " Due to a limitation of MS-DOS the label can only be 11 characters long." + " Please note that Minix does not support labels, whatever you enter here.</qt>") ); + + connect(labellabel,SIGNAL(toggled(bool)),lineedit,SLOT(setEnabled(bool))); + + QVBoxLayout* v3 = new QVBoxLayout( h1 ); + + formatbutton = new KPushButton( this, "PushButton_3" ); + formatbutton->setText(i18n( "&Format") ); + formatbutton->setAutoRepeat( false ); + if (!numFileSystems) + formatbutton->setDisabled(false); // We have not any helper program for creating any file system + connect(formatbutton,SIGNAL(clicked()),this,SLOT(format())); + v3->addWidget( formatbutton ); + QWhatsThis::add( formatbutton, + i18n("<qt>Click here to start formatting.</qt>") ); + + v3->addStretch( 1 ); + + //Setup the Help Menu + helpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData(), false); + + helpbutton = new KPushButton( KStdGuiItem::help(), this ); + helpbutton->setAutoRepeat( false ); + helpbutton->setPopup(helpMenu->menu()); + v3->addWidget( helpbutton ); + + quitbutton = new KPushButton( KStdGuiItem::quit(), this ); + quitbutton->setAutoRepeat( false ); + connect(quitbutton,SIGNAL(clicked()),this,SLOT(quit())); + v3->addWidget( quitbutton ); + + ml->addSpacing( 10 ); + + frame = new QLabel( this, "NewsWindow" ); + frame->setFrameStyle(QFrame::Panel | QFrame::Sunken); + frame->setAlignment(WordBreak|ExpandTabs); + QWhatsThis::add( frame, + i18n("<qt>This is the status window, where error messages are displayed.</qt>") ); + + QString frameText( userFeedBack ); + frameText.prepend( "<qt>" ); + frameText.append( "</qt>" ); + frame->setText( frameText ); + + ml->addWidget( frame ); + + progress = new KProgress( this, "Progress" ); + progress->setDisabled( true ); + ml->addWidget( progress ); + + QWhatsThis::add(progress, + i18n("<qt>Shows progress of the format.</qt>")); + + readSettings(); + setWidgets(); + + if (!numFileSystems) { + QString errorMessage; + errorMessage += "<qt>"; + errorMessage += i18n("KFloppy cannot find any of the needed programs for creating file systems; please check your installation.<br><br>Log:"); + errorMessage += "<br>"; + errorMessage += userFeedBack; + errorMessage += "</qt>"; + KMessageBox::error( this, errorMessage ); + } +} + + +FloppyData::~FloppyData() +{ + delete formatActions; +} + +void FloppyData::closeEvent(QCloseEvent*) +{ + quit(); +} + +void FloppyData::keyPressEvent(QKeyEvent *e) +{ + switch(e->key()) { + case Qt::Key_F1: + kapp->invokeHelp(); + break; + default: + KDialog::keyPressEvent(e); + return; + } +} + +void FloppyData::show() { + setCaption(i18n("KDE Floppy Formatter")); + KDialog::show(); +} + +bool FloppyData::findDevice() +{ + // Note: this function does not handle user-given devices + + drive=-1; + if( deviceComboBox->currentText() == i18n("Primary") ) + { + drive=0; + } + else if( deviceComboBox->currentText() == i18n("Secondary") ) + { + drive=1; + } + + blocks=-1; + + if( densityComboBox->currentText() == i18n("3.5\" 1.44MB")){ + blocks = 1440; + } + else + if( densityComboBox->currentText() == i18n("3.5\" 720KB")){ + blocks = 720; + } + else + if( densityComboBox->currentText() == i18n("5.25\" 1.2MB")){ + blocks = 1200; + } + else + if( densityComboBox->currentText() == i18n("5.25\" 360KB")){ + blocks = 360; + } +#if defined(ANY_LINUX) + else { // For Linux, anything else is Auto + blocks = 0; + } +#endif + + return true; +} + +bool FloppyData::setInitialDevice(const QString& dev) +{ + + QString newDevice = dev; + + KURL url( newDevice ); + if( url.isValid() && ( url.protocol() == "media" || url.protocol() == "system" ) ) { + QString name = url.fileName(); + + DCOPRef mediamanager( "kded", "mediamanager" ); + DCOPReply reply = mediamanager.call("properties(QString)", name); + if (!reply.isValid()) { + kdError() << "Invalid reply from mediamanager" << endl; + } else { + QStringList properties = reply; + newDevice = properties[5]; + } + } + + int drive = -1; + if ( newDevice.startsWith("/dev/fd0") ) + drive = 0; + if ( newDevice.startsWith("/dev/fd1")) + drive = 1; + + // ### TODO user given devices + + bool ok = (drive>=0); + if (ok) + deviceComboBox->setCurrentItem(drive); + return ok; +} + +void FloppyData::quit(){ + if (formatActions) formatActions->quit(); + writeSettings(); + kapp->quit(); + delete this; +} + +void FloppyData::setEnabled(bool b) +{ + if (b) + unsetCursor(); + else + setCursor(QCursor(WaitCursor)); + label1->setEnabled(b); + deviceComboBox->setEnabled(b); + label2->setEnabled(b); + densityComboBox->setEnabled(b); + label3->setEnabled(b); + filesystemComboBox->setEnabled(b); + buttongroup->setEnabled(b); + quick->setEnabled(b); + fullformat->setEnabled(b && m_canLowLevel); + zerooutformat->setEnabled(b && m_canZeroOut); + verifylabel->setEnabled(b); + labellabel->setEnabled(b); + lineedit->setEnabled(b && labellabel->isChecked() ); + helpbutton->setEnabled(b); + quitbutton->setEnabled(b); + formatbutton->setEnabled(b); + progress->setDisabled( b ); // The other way round! +} + +void FloppyData::reset() +{ + DEBUGSETUP; + + formating = false; + + if (formatActions) + { + formatActions->quit(); + delete formatActions; + formatActions = 0L; + } + + progress->setValue(0); + formatbutton->setText(i18n("&Format")); + setEnabled(true); +} + +void FloppyData::format(){ + + if(formating){ + //abort = true; + reset(); + return; + } + + frame->clear(); + + const QString currentComboBoxDevice ( deviceComboBox->currentText() ); + const bool userDevice = ( currentComboBoxDevice.startsWith ("/dev/") ); + +#ifdef ANY_BSD + if ( userDevice && filesystemComboBox->currentText() != i18n("UFS")) + { + KMessageBox::error( this, i18n("BSD", "Formatting with BSD on a user-given device is only possible with UFS") ); + return; + } + // no "else" ! +#endif + if ( userDevice && ( quick->isChecked() || zerooutformat->isChecked() ) ) + { + if (KMessageBox::warningContinueCancel( this, + i18n("<qt>Formatting will erase all data on the device:<br/><b>%1</b><br/>" + "(Please check the correctness of the device name.)<br/>" + "Are you sure you wish to proceed?</qt>").arg( currentComboBoxDevice ) + , i18n("Proceed?") ) != KMessageBox::Continue) + { + return; + } + } + else if ( userDevice ) + { + // The user has selected full formatting on a user-given device. That is not supported yet! + KMessageBox::error( this, "Full formatting of a user-given device is not possible!" ); + return; + } + else + { + if (KMessageBox::warningContinueCancel( this, + i18n("Formatting will erase all data on the disk.\n" + "Are you sure you wish to proceed?"), i18n("Proceed?") ) != + KMessageBox::Continue) + { + return; + } + } + + // formatbutton->setText(i18n("A&bort")); + setEnabled(false); + + // Erase text box + frame->setText( QString::null ); + + if ( !userDevice ) + { + if ( !findDevice() ) + { + reset(); + return; + } + } + + if (formatActions) delete formatActions; + formatActions = new KFActionQueue(this); + + connect(formatActions,SIGNAL(status(const QString &,int)), + this,SLOT(formatStatus(const QString &,int))); + connect(formatActions,SIGNAL(done(KFAction *,bool)), + this,SLOT(reset())); + + if ( quick->isChecked()) + { + formating=false; + // No fdformat to push + } + else if ( zerooutformat->isChecked() ) + { + DDZeroOut* f = new DDZeroOut( this ); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice( drive, blocks ); + } + formatActions->queue(f); + } + else if ( userDevice ) + { + // We should not have got here, assume quick format + formating=false; + // No fdformat to push + } + else + { + FDFormat *f = new FDFormat(this); + f->configureDevice(drive,blocks); + f->configure(verifylabel->isChecked()); + formatActions->queue(f); + } + + if ( filesystemComboBox->currentText() == i18n("DOS") ) + { + FATFilesystem *f = new FATFilesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } + + else if ( filesystemComboBox->currentText() == i18n("ext2") ) + { + Ext2Filesystem *f = new Ext2Filesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } + +#ifdef ANY_BSD + else if ( filesystemComboBox->currentText() == i18n("UFS") ) + { + FloppyAction *f = new UFSFilesystem(this); + f->configureDevice(drive,blocks); + formatActions->queue(f); + } +#endif + +#ifdef ANY_LINUX + else if ( filesystemComboBox->currentText() == i18n("Minix") ) + { + MinixFilesystem *f = new MinixFilesystem(this); + f->configure(verifylabel->isChecked(), + labellabel->isChecked(), + lineedit->text()); + if ( userDevice ) + { + f->configureDevice( currentComboBoxDevice ); + } + else + { + f->configureDevice(drive,blocks); + } + formatActions->queue(f); + } +#endif + + + + formatActions->exec(); +} + +void FloppyData::formatStatus(const QString &s,int p) +{ + kdDebug(2002) << "FloppyData::formatStatus: " << s << " : " << p << endl; + if (!s.isEmpty()) + { + const QString oldText ( frame->text() ); + if ( oldText.isEmpty() ) + { + frame->setText( s ); + } + else + { + frame->setText( oldText + '\n' + s ); + } + } + + if ((0<=p) && (p<=100)) + progress->setValue(p); +} + +void FloppyData::writeSettings(){ + + config = kapp->config(); + config->setGroup("GeneralData"); + + densityconfig = densityComboBox->currentText().stripWhiteSpace(); + filesystemconfig = filesystemComboBox->currentText().stripWhiteSpace(); + driveconfig = deviceComboBox->currentText().stripWhiteSpace(); + + quickformatconfig = quick->isChecked(); + + labelnameconfig = lineedit->text().stripWhiteSpace(); + + labelconfig = labellabel->isChecked(); + + verifyconfig = verifylabel->isChecked(); + + config->writeEntry("CreateLabel",labelconfig); + config->writeEntry("Label",labelnameconfig); + + + config->writeEntry("QuickFormat",quickformatconfig); + config->writeEntry("FloppyDrive",driveconfig); + config->writeEntry("Density",densityconfig); + config->writeEntry("Filesystem",filesystemconfig); + config->writeEntry("Verify",verifyconfig); + config->sync(); + +} + +void FloppyData::readSettings(){ + + config = kapp->config(); + config->setGroup("GeneralData"); + + verifyconfig = config->readNumEntry("Verify", 1); + labelconfig = config->readNumEntry("CreateLabel",1); + labelnameconfig = config->readEntry( "Label", i18n("Volume label, maximal 11 characters", "KDE Floppy") ); + quickformatconfig = config->readNumEntry("QuickFormat",0); + driveconfig = config->readEntry( "FloppyDrive", i18n("Primary") ); +#if defined(ANY_LINUX) + densityconfig = config->readEntry( "Density", i18n( "Auto-Detect" ) ); +#else + densityconfig = config->readEntry( "Density", i18n("3.5\" 1.44MB") ); +#endif + filesystemconfig = config->readEntry( "Filesystem", i18n("DOS") ); + +} + +void FloppyData::setWidgets(){ + + labellabel->setChecked(labelconfig); + verifylabel->setChecked(verifyconfig); + quick->setChecked(quickformatconfig || !m_canLowLevel); + fullformat->setChecked(!quickformatconfig && m_canLowLevel); + lineedit->setText(labelnameconfig); + + for(int i = 0 ; i < deviceComboBox->count(); i++){ + if ( deviceComboBox->text(i) == driveconfig){ + deviceComboBox->setCurrentItem(i); + } + } + + for(int i = 0 ; i < filesystemComboBox->count(); i++){ + if ( filesystemComboBox->text(i) == filesystemconfig){ + filesystemComboBox->setCurrentItem(i); + } + } + + for(int i = 0 ; i < densityComboBox->count(); i++){ + if ( densityComboBox->text(i) == densityconfig){ + densityComboBox->setCurrentItem(i); + } + } +} + +#include "floppy.moc" diff --git a/kfloppy/floppy.h b/kfloppy/floppy.h new file mode 100644 index 0000000..2d4d519 --- /dev/null +++ b/kfloppy/floppy.h @@ -0,0 +1,128 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef FloppyData_included +#define FloppyData_included + +#include <kdialog.h> + +class QCheckBox; +class QLineEdit; +class QLabel; +class QRadioButton; +class QComboBox; +class QButtonGroup; +class QGroupBox; + +class KProgress; +class KConfig; +class KPushButton; +class KHelpMenu; +class KFAction; +class KFActionQueue; + +class FloppyData : public KDialog +{ + Q_OBJECT + +public: + FloppyData(QWidget* parent = 0, const char * name = 0); + virtual ~FloppyData(); + + /// Need to overload normal show() in order to mangle caption + void show(); + /// Maps combobox selection to drive and density + bool findDevice(); + /// set default device + bool setInitialDevice(const QString& dev); + /** Override closeEvent() in order to properly close + the entire application.*/ + void closeEvent(QCloseEvent*); + /// Writing the user-visible settings. + void writeSettings(); + /// Reading the user-visible settings. + void readSettings(); + /// Map stored settings to widget status + void setWidgets(); + /// A kind of QString::find() + int findKeyWord(QString &, const QString &); + /// Enable/disable all UI elements + void setEnabled(bool); + +public slots: + void quit(); + void format(); + void reset(); + + void formatStatus(const QString &,int); + +protected slots: + +private: + int verifyconfig; + int labelconfig; + QString labelnameconfig; + int quickformatconfig; + QString driveconfig; + QString densityconfig; + QString filesystemconfig; + KConfig *config; + + int drive; + /// Number of blocks of the floppy (typically 1440) + int blocks; + + bool formating; + //bool abort; + + QGroupBox* outerframe; + QLabel* label1; + QLabel* label2; + QLabel* label3; + QButtonGroup* buttongroup; + QCheckBox* verifylabel; + QCheckBox* labellabel; + QLineEdit* lineedit; + QRadioButton* quick; + QRadioButton* zerooutformat; + KPushButton* quitbutton; + KPushButton* helpbutton; + QRadioButton* fullformat; + KPushButton* formatbutton; + QLabel* frame; + QComboBox* deviceComboBox; + QComboBox* filesystemComboBox; + QComboBox* densityComboBox; + KProgress* progress; + KHelpMenu* helpMenu; + + KFActionQueue *formatActions; + + bool m_canLowLevel; ///< Low level formatting is possible (i.e. was fdformat found?) + bool m_canZeroOut; ///< Is zero-out possible (i.e. was dd found?) +protected: + void keyPressEvent(QKeyEvent *e); + +}; + +#endif // FloppyData_included diff --git a/kfloppy/floppy_format.desktop b/kfloppy/floppy_format.desktop new file mode 100644 index 0000000..b780ac9 --- /dev/null +++ b/kfloppy/floppy_format.desktop @@ -0,0 +1,54 @@ +[Desktop Action Format] +Exec=kfloppy %u +Icon=kfloppy +Name=Format +Name[ar]=تهيئة +Name[bg]=Форматиране +Name[br]=Furmadiñ +Name[ca]=Dona format +Name[cs]=Formátovat +Name[cy]=Fformat +Name[de]=Formatieren +Name[el]=Διαμόρφωση +Name[eo]=Formato +Name[es]=Formatear +Name[et]=Vorminda +Name[fa]=قالببندی +Name[fr]=Formater +Name[ga]=Formáid +Name[he]=פורמט +Name[hu]=Formázás +Name[is]=Forsníða +Name[it]=Formatta +Name[ja]=フォーマット +Name[ka]=ფორმატი +Name[kk]=Дискетаны пішімдеу +Name[km]=ធ្វើទ្រង់ទ្រាយ +Name[lt]=Formatas +Name[nds]=Formateren +Name[ne]=ढाँचा +Name[nl]=Formatteren +Name[nn]=Formater +Name[pa]=ਫਾਰਮਿਟ +Name[pl]=Formatuj +Name[pt]=Formatar +Name[pt_BR]=Formatar +Name[ru]=Форматирование дискет +Name[rw]=Imiterere +Name[sk]=Formátovanie +Name[sl]=Formatiraj +Name[sr]=Форматирај +Name[sr@Latn]=Formatiraj +Name[tr]=Biçimlendir +Name[uk]=Форматування +Name[uz]=Formatlash +Name[uz@cyrillic]=Форматлаш +Name[wa]=Abwesner +Name[zh_CN]=格式化 +Name[zh_TW]=格式化 + +[Desktop Entry] +Actions=Format; +ServiceTypes=media/floppy_unmounted,media/floppy5_unmounted +X-KDE-Priority=TopLevel +X-KDE-MediaNotifierHide=true diff --git a/kfloppy/format.cpp b/kfloppy/format.cpp new file mode 100644 index 0000000..6d76de3 --- /dev/null +++ b/kfloppy/format.cpp @@ -0,0 +1,996 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 Adriaan de Groot <groot@kde.org> + Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#include <unistd.h> +#include <stdlib.h> + +#include <qtimer.h> +#include <qregexp.h> + +#include <klocale.h> +#include <kprocess.h> +#include <kdebug.h> +#include <kstandarddirs.h> + +#include "format.h" + +static QString extPath = QString::null; + +/* static */ QString findExecutable(const QString &e) +{ + if (extPath.isEmpty()) + { + QString path = getenv("PATH"); + if (!path.isEmpty()) path.append(":"); + path.append("/usr/sbin:/sbin"); + extPath = path; + } + + return KGlobal::dirs()->findExe(e, extPath); +} + + + +KFAction::KFAction(QObject *parent) : + QObject(parent) +{ + DEBUGSETUP; +} + +KFAction::~KFAction() +{ + DEBUGSETUP; + quit(); +} + +/* slot */ void KFAction::quit() +{ + DEBUGSETUP; +} + +/* slot */ void KFAction::exec() +{ + DEBUGSETUP; +} + +class KFActionQueue_p +{ +public: + QPtrList<KFAction> list; +} ; + +KFActionQueue::KFActionQueue(QObject *parent) : + KFAction(parent), + d(new KFActionQueue_p) +{ + DEBUGSETUP; + d->list.setAutoDelete(true); +} + +KFActionQueue::~KFActionQueue() +{ + DEBUGSETUP; + delete d; +} + +void KFActionQueue::queue(KFAction *p) +{ + DEBUGSETUP; + + d->list.append(p); + DEBUGS(p->name()); +} + +/* virtual */ void KFActionQueue::exec() +{ + DEBUGSETUP; + + actionDone(0L,true); +} + +/* slot */ void KFActionQueue::actionDone(KFAction *p,bool success) +{ + DEBUGSETUP; + + if (p) + { + if (d->list.first()==p) + { + d->list.removeFirst(); + // delete p; /* auto-delete */ + } + else + { + DEBUGS( "Strange pointer received."); + emit done(this,false); + return; + } + } + else + { + DEBUGS("Starting action queue."); + } + + if (!success) + { + DEBUGS("Action failed."); + emit done(this,false); + return; + } + + KFAction *next = d->list.first(); + if (!next) + { + emit done(this,true); + } + else + { + kdDebug(KFAREA) << "Running action " << next->name() << endl; + QObject::connect(next,SIGNAL(done(KFAction *,bool)), + this,SLOT(actionDone(KFAction *,bool))); + // Propagate signals + QObject::connect(next,SIGNAL(status(const QString &,int)), + this,SIGNAL(status(const QString &,int))); + QTimer::singleShot(0,next,SLOT(exec())); + } +} + + + + +// Here we have names of devices. The variable +// names are basically the linux device names, +// replace with whatever your OS needs instead. +// +// +#ifdef ANY_LINUX + +const char *fd0H1440[] = { "/dev/fd0u1440", "/dev/floppy/0u1440", "/dev/fd0h1440", "/dev/fd0H1440", "/dev/fd0", 0L } ; +const char *fd0D720[] = { "/dev/fd0u720", "/dev/floppy/0u720", "/dev/fd0D720", "/dev/fd0h720", "/dev/fd0", 0L }; +const char *fd0h1200[] = { "/dev/fd0h1200", "/dev/floppy/0h1200", "/dev/fd0", 0L }; +const char *fd0h360[] = { "/dev/fd0u360", "/dev/floppy/0u360", "/dev/fd0h360", "/dev/fd0d360", "/dev/fd0", 0L }; + +const char *fd1H1440[] = { "/dev/fd1u1440", "/dev/floppy/1u1440","/dev/fd1h1440", "/dev/fd1H1440", "/dev/fd1", 0L } ; +const char *fd1D720[] = { "/dev/fd1u720", "/dev/floppy/1u720", "/dev/fd1D720", "/dev/fd1h720", "/dev/fd1", 0L }; +const char *fd1h1200[] = { "/dev/fd1h1200", "/dev/floppy/1h1200", "/dev/fd1", 0L }; +const char *fd1h360[] = { "/dev/fd1u360", "/dev/floppy/1u360","/dev/fd1h360", "/dev/fd1d360", "/dev/fd1", 0L }; + +const char *fd0auto[] = { "/dev/fd0", 0L }; +const char *fd1auto[] = { "/dev/fd1", 0L }; + +#endif + + +#ifdef ANY_BSD +const char *fd0[] = { "/dev/fd0", 0L } ; +const char *fd1[] = { "/dev/fd1", 0L } ; +#endif + +// Next we have a table of device names and characteristics. +// These are ordered according to 2*densityIndex+deviceIndex, +// ie. primary (0) 1440K (0) is first, then secondary (1) 1440K is +// second, down to secondary (1) 360k (4) in position 3*2+1=7. +// +// +// Note that the data originally contained in KFloppy was +// patently false, so most of this is fake. I guess noone ever +// formatted a 5.25" floppy. +// +// The flags field is unused in this implementation. +// +// +fdinfo fdtable[] = +{ +#ifdef ANY_LINUX + // device drv blks trk flg + { fd0H1440, 0, 1440, 80, 0 }, + { fd1H1440, 1, 1440, 80, 0 }, + { fd0D720, 0, 720, 80, 0 }, + { fd1D720, 1, 720, 80, 0 }, + { fd0h1200, 0, 1200, 80, 0 }, + { fd1h1200, 1, 1200, 80, 0 }, + { fd0h360, 0, 360, 40, 0 }, + { fd1h360, 1, 360, 40, 0 }, + { fd0auto, 0, 0, 80, 0 }, + { fd1auto, 1, 0, 80, 0 }, +#endif + +#ifdef ANY_BSD + // Instead of the number of tracks, which is + // unneeded, we record the + // number of F's printed during an fdformat + { fd0, 0, 1440, 40, 0 }, + { fd1, 1, 1440, 40, 0 }, + { fd0, 0, 720, 40, 0 }, + { fd1, 1, 720, 40, 0 }, + { fd0, 0, 1200, 40, 0}, + { fd1, 1, 1200, 40, 0}, + { fd0, 0, 360, 40, 0}, + { fd1, 1, 360, 40, 0}, +#endif + { 0L, 0, 0, 0, 0 } +} ; + + +FloppyAction::FloppyAction(QObject *p) : + KFAction(p), + deviceInfo(0L), + theProcess(0L) +{ + DEBUGSETUP; +} + +void FloppyAction::quit() +{ + DEBUGSETUP; + delete theProcess; + theProcess=0L; + + KFAction::quit(); +} + +bool FloppyAction::configureDevice( const QString& newDeviceName ) +{ + deviceInfo = 0; // We have not any idea what the device is + deviceName = newDeviceName; + return true; // No problem! +} + +bool FloppyAction::configureDevice(int drive,int density) +{ + DEBUGSETUP; + const char *devicename = 0L; + + deviceInfo=0L; + deviceName = QString::null; + + if ((drive<0) || (drive>1)) + { + emit status(i18n("Unexpected drive number %1.").arg(drive),-1); + return false; + } + + fdinfo *deviceinfo = fdtable; + for ( ; deviceinfo && (deviceinfo->devices) ; deviceinfo++) + { + if (deviceinfo->blocks != density) + continue; + } + if (!deviceinfo) + { + emit status(i18n("Unexpected density number %1.").arg(density),-1); + return false; + } + + deviceinfo = fdtable; + for ( ; deviceinfo && (deviceinfo->devices) ; deviceinfo++) + { + if (deviceinfo->blocks != density) + continue; + if (deviceinfo->drive == drive) + break; + } + + if (!deviceinfo || !deviceinfo->devices) + { + emit status(i18n("Cannot find a device for drive %1 and density %2.") + .arg(drive).arg(density),-1); + return false; + } + + for (const char **devices=deviceinfo->devices ; + *devices ; devices++) + { + if (access(*devices,W_OK)>=0) + { + kdDebug(KFAREA) << "Found device " << *devices << endl; + devicename=*devices; + break; + } + } + + if (!devicename) + { + const QString str = i18n( + "Cannot access %1\nMake sure that the device exists and that " + "you have write permission to it.").arg(deviceinfo->devices[0]); + emit status(str,-1); + return false; + } + + deviceName = devicename; + deviceInfo = deviceinfo; + + return true; +} + +void FloppyAction::processDone(KProcess *p) +{ + DEBUGSETUP; + + if (p!=theProcess) + { + DEBUGS(" Strange process exited."); + return; + } + + if (p->normalExit()) + { + if (p->exitStatus() == 0) + { + emit status(QString::null,100); + emit done(this,true); + } + else + { + emit status(i18n("The program %1 terminated with an error.").arg(theProcessName),100); + emit done(this,false); + } + } + else + { + emit status(i18n("The program %1 terminated abnormally.").arg(theProcessName),100); + emit done(this,false); + } +} + +void FloppyAction::processStdOut(KProcess *, char *b, int l) +{ + Q_UNUSED(b); + Q_UNUSED(l); + kdDebug(KFAREA) << "stdout:" << QString::fromLatin1(b,l) << endl; +} + +void FloppyAction::processStdErr(KProcess *p, char *b, int l) +{ + processStdOut(p,b,l); +} + +bool FloppyAction::startProcess() +{ + DEBUGSETUP; + + connect(theProcess,SIGNAL(processExited(KProcess *)), + this,SLOT(processDone(KProcess *))); + connect(theProcess,SIGNAL(receivedStdout(KProcess *,char *,int)), + this,SLOT(processStdOut(KProcess *,char *,int))); + connect(theProcess,SIGNAL(receivedStderr(KProcess *,char *,int)), + this,SLOT(processStdErr(KProcess *,char *,int))); + + theProcess->setEnvironment( "LC_ALL", "C" ); // We need the untranslated output of the tool + return theProcess->start(KProcess::NotifyOnExit, + KProcess::AllOutput); +} + + +/* static */ QString FDFormat::fdformatName = QString::null; + +FDFormat::FDFormat(QObject *p) : + FloppyAction(p), + doVerify(true) +{ + DEBUGSETUP; + theProcessName = QString::fromLatin1("fdformat"); + setName("FDFormat"); +} + +/* static */ bool FDFormat::runtimeCheck() +{ + fdformatName = findExecutable("fdformat"); + return (!fdformatName.isEmpty()); +} + +bool FDFormat::configure(bool v) +{ + doVerify=v; + return true; +} + +/* virtual */ void FDFormat::exec() +{ + DEBUGSETUP; + + if ( !deviceInfo || deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (fdformatName.isEmpty()) + { + emit status(i18n("Cannot find fdformat."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + theProcess = new KProcess; + + formatTrackCount=0; + + *theProcess << fdformatName ; + + // Common to Linux and BSD, others may differ + if (!doVerify) + { + *theProcess << "-n"; + } + +#ifdef ANY_BSD + *theProcess + << "-y" + << "-f" + << QString::number(deviceInfo->blocks) ; +#elif defined(ANY_LINUX) + // No Linux-specific flags +#endif + + // Common to Linux and BSD, others may differ + *theProcess << deviceName; + + if (!startProcess()) + { + emit status(i18n("Could not start fdformat."),-1); + emit done(this,false); + } + + // Now depend on fdformat running and producing output. +} + +// Parse some output from the fdformat process. Lots of +// #ifdefs here to account for variations in the basic +// fdformat. Uses gotos to branch to whatever error message we +// need, since the messages can be standardized across OSsen. +// +// +void FDFormat::processStdOut(KProcess *, char *b, int l) +{ + DEBUGSETUP; + QString s; + +#ifdef ANY_BSD + if (b[0]=='F') + { + formatTrackCount++; + emit status(QString::null, + formatTrackCount * 100 / deviceInfo->tracks); + } + else if (b[0]=='E') + { + emit status(i18n("Error formatting track %1.").arg(formatTrackCount),-1); + } + else + { + s = QString::fromLatin1(b,l); + if (s.contains("ioctl(FD_FORM)")) + { + emit status (i18n( + "Cannot access floppy or floppy drive.\n" + "Please insert a floppy and make sure that you " + "have selected a valid floppy drive."),-1); + return; + } + if (s.find("/dev/")>=0) + { + emit status(s,-1); + return; + } + DEBUGS(s); + } +#elif defined(ANY_LINUX) + s = QString::fromLatin1(b,l); + DEBUGS(s); + QRegExp regexp( "([0-9]+)" ); + if ( s.startsWith( "bad data at cyl" ) || ( s.find( "Problem reading cylinder" ) != -1 ) ) + { + if ( regexp.search( s ) > -1 ) + { + const int track = regexp.cap(1).toInt(); + emit status(i18n("Low-level formatting error at track %1.").arg(track), -1); + } + else + { + // This error should not happen + emit status(i18n("Low-level formatting error: %1").arg(s), -1); + } + return; + } + else if (s.find("ioctl(FDFMTBEG)")!=-1) + { + emit status (i18n( + "Cannot access floppy or floppy drive.\n" + "Please insert a floppy and make sure that you " + "have selected a valid floppy drive."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } + // Be careful to leave "iotcl" as last before checking numbers + else if (s.find("ioctl")!=-1) + { + emit status(i18n("Low-level format error: %1").arg(s),-1); + return; + } + // Check for numbers at last (as /dev/fd0u1440 has numbers too) + else if ( regexp.search(s) > -1 ) + { + // Normal track number (formatting or verifying) + const int p = regexp.cap(1).toInt(); + if ((p>=0) && (p<deviceInfo->tracks)) + { + emit status(QString::null, + p * 100 / deviceInfo->tracks); + } + } +#endif + return; +} + + +/* static */ QString DDZeroOut::m_ddName = QString::null; + +DDZeroOut::DDZeroOut(QObject *p) : + FloppyAction(p) +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + theProcessName = QString::fromLatin1("dd"); + setName("DD"); +} + +/* static */ bool DDZeroOut::runtimeCheck() +{ + m_ddName = findExecutable("dd"); + return (!m_ddName.isEmpty()); +} + +/* virtual */ void DDZeroOut::exec() +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done( this, false ); + return; + } + + if ( m_ddName.isEmpty() ) + { + emit status( i18n("Cannot find dd."), -1 ); + emit done( this, false ); + return; + } + + delete theProcess; + theProcess = new KProcess; + + *theProcess << m_ddName ; + + *theProcess << "if=/dev/zero" ; + *theProcess << "of="+deviceName; + + if ( !startProcess() ) + { + emit status( i18n("Could not start dd."), -1 ); + emit done( this, false ); + } + +} + +void DDZeroOut::processDone(KProcess *p) +{ + kdDebug(KFAREA) << (__PRETTY_FUNCTION__) << endl; + + if (p!=theProcess) + { + kdDebug(KFAREA) << "Strange process exited." << endl; + return; + } + + /** + * As we do not give a number of blocks to dd(1), it will stop + * with the error "No space left on device" + * + * ### TODO: really check if the exit is not on an other error and then abort the formatting + */ + emit status(QString::null,100); + emit done(this,true); +} + + + +/* static */ QString FATFilesystem::newfs_fat = QString::null ; + +FATFilesystem::FATFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName=newfs_fat; + setName("FATFilesystem"); +} + +/* static */ bool FATFilesystem::runtimeCheck() +{ + DEBUGSETUP; + +#ifdef ANY_BSD + newfs_fat = findExecutable("newfs_msdos"); +#elif defined(ANY_LINUX) + newfs_fat = findExecutable("mkdosfs"); +#else + return false; +#endif + + return !newfs_fat.isEmpty(); +} + +bool FATFilesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + label=lbl.simplifyWhiteSpace(); + else + label=QString::null; + + return true; +} + +void FATFilesystem::exec() +{ + DEBUGSETUP; + + + if ( +#ifdef ANY_BSD // BSD needs the deviceInfo for the block count + !deviceInfo || +#endif + deviceName.isEmpty()) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs_fat.isEmpty()) + { + emit status(i18n("Cannot find a program to create FAT filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs_fat; +#ifdef ANY_BSD + *p << "-f" << QString::number(deviceInfo->blocks); + if (doLabel) + { + *p << "-L" << label ; + } +#else +#ifdef ANY_LINUX + if (doLabel) + { + *p << "-n" << label ; + } + if (doVerify) + { + *p << "-c"; + } +#endif +#endif + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start FAT format program."),-1); + emit done(this,false); + } +} + +void FATFilesystem::processStdOut(KProcess *, char *b, int l) +{ +#ifdef ANY_BSD + // ### TODO: do some checks +#elif defined(ANY_LINUX) + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted file system")!=-1) // "/dev/fd0 contains a mounted file system + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +# if 0 + else if ( s.find( "mkdosfs" ) != -1 ) // DEBUG: get the program header and show it! + { + emit status( s, -1 ); + return; + } +# endif +#endif +} + + + + +#ifdef ANY_BSD + +/* static */ QString UFSFilesystem::newfs = QString::null ; + +UFSFilesystem::UFSFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName=newfs; + setName("UFSFilesystem"); +} + +/* static */ bool UFSFilesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("newfs"); + + return !newfs.isEmpty(); +} + +void UFSFilesystem::exec() +{ + DEBUGSETUP; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("BSD", "Cannot find a program to create UFS filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + + // ### TODO: is it still needed? (FreeBSD 5.3's man page says: "For backward compatibility.") + if ( deviceInfo ) + *p << "-T" << QString("fd%1").arg(deviceInfo->blocks); + + *p << deviceName; + + if (!startProcess()) + { + emit status(i18n("BSD", "Cannot start UFS format program."),-1); + emit done(this,false); + } +} +#endif + + + +/* static */ QString Ext2Filesystem::newfs = QString::null ; + +Ext2Filesystem::Ext2Filesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName="mke2fs"; + setName("Ext2Filesystem"); +} + +/* static */ bool Ext2Filesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("mke2fs"); + + return !newfs.isEmpty(); +} + +bool Ext2Filesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + { + label=lbl.stripWhiteSpace(); + } + else + { + label=QString::null; + } + + return true; +} + +void Ext2Filesystem::exec() +{ + DEBUGSETUP; + + if ( +#ifdef ANY_BSD // BSD needs the deviceInfo for the block count + !deviceInfo || +#endif + deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("Cannot find a program to create ext2 filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + *p << "-q"; + if (doVerify) *p << "-c" ; + if (doLabel) *p << "-L" << label ; + + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start ext2 format program."),-1); + emit done(this,false); + } +} + +void Ext2Filesystem::processStdOut(KProcess *, char *b, int l) +{ +#ifdef ANY_BSD + // ### TODO: do some checks +#elif defined(ANY_LINUX) + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted")!=-1) // "/dev/fd0 is mounted; will not make a filesystem here!" + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +#endif +} + + + +#ifdef ANY_LINUX +/* static */ QString MinixFilesystem::newfs = QString::null ; + +MinixFilesystem::MinixFilesystem(QObject *parent) : + FloppyAction(parent) +{ + DEBUGSETUP; + runtimeCheck(); + theProcessName="mkfs.minix"; + setName("Minix2Filesystem"); +} + +/* static */ bool MinixFilesystem::runtimeCheck() +{ + DEBUGSETUP; + + newfs = findExecutable("mkfs.minix"); + + return !newfs.isEmpty(); +} + +bool MinixFilesystem::configure(bool v,bool l,const QString &lbl) +{ + doVerify=v; + doLabel=l; + if (l) + { + label=lbl.stripWhiteSpace(); + } + else + { + label=QString::null; + } + + return true; +} + +void MinixFilesystem::exec() +{ + DEBUGSETUP; + + if ( deviceName.isEmpty() ) + { + emit status( i18n("Internal error: device not correctly defined."), -1 ); + emit done(this,false); + return; + } + + if (newfs.isEmpty()) + { + emit status(i18n("Cannot find a program to create Minix filesystems."),-1); + emit done(this,false); + return; + } + + if (theProcess) delete theProcess; + KProcess *p = theProcess = new KProcess; + + *p << newfs; + + // Labeling is not possible + if (doVerify) *p << "-c" ; + + *p << deviceName ; + + if (!startProcess()) + { + emit status(i18n("Cannot start Minix format program."),-1); + emit done(this,false); + } +} + +void MinixFilesystem::processStdOut(KProcess *, char *b, int l) +{ + QString s ( QString::fromLatin1( b, l ) ); + kdDebug(KFAREA) << s << endl; + if (s.find("mounted")!=-1) // "mkfs.minix: /dev/fd0 is mounted; will not make a filesystem here!" + { + emit status(i18n("Floppy is mounted.\nYou need to unmount the floppy first."),-1); + return; + } + else if (s.find("busy")!=-1) // "Device or resource busy" + { + emit status(i18n("Device busy.\nPerhaps you need to unmount the floppy first."),-1); + return; + } +} + +#endif + +#include "format.moc" diff --git a/kfloppy/format.h b/kfloppy/format.h new file mode 100644 index 0000000..0200d22 --- /dev/null +++ b/kfloppy/format.h @@ -0,0 +1,426 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 Adriaan de Groot <groot@kde.org> + Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org> + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef FORMAT_H +#define FORMAT_H + +/** \file format.h + * This file defines a hierarchy of classes that + * can run a sequence of external programs (like + * fdformat, mkisofs, etc.) in sequence. Stdout + * and stderr of those programs can be captured + * and analyzed in order to provide feedback to + * the user. + * + * <ul> + * <li>KFAction: Base class, just for performing some action. + * <li>KFActionQueue: Provides sequencing of KFActions + * <li>FloppyAction: Weird name; handles running a program, + * understands FD device names. This can be + * considered the "useful" base class of + * programming actions. + * <li>FDFormat: Runs fdformat(1) under BSD or Linux. + * <li>FATFilesystem: Creates an msdos (FAT) filesystem. + * <li>Ext2Filesystem: Creates ext2 filesystems. + * <li>MinixFilesystem: Creates Minix filesystems, under Linux. + * <li>UFSFilesystem: Creates UFS filesystem, under BSD. + * </ul> + * + * \note Maybe this is overkill, since for floppies all you need is + * fdformat(1) and some create-filesystem program like newfs(1) + * or mke2fs(1). However, for Zip disks, should they ever be supported, + * this is quite useful since you need to dd, fdisk, disklabel, and + * newfs them. +*/ + +#include "debug.h" +#include <qobject.h> + +/** + * \brief Abstract base class of actions to be undertaken. + * + * Basically you can create a KFActionStack (See below) + * and push a bunch of actions on it, then run exec() + * on the stack and wait for the done() signal. +*/ +class KFAction : public QObject +{ +Q_OBJECT + +public: + KFAction(QObject *parent = 0L); + virtual ~KFAction(); + +public slots: + /** + * Exec() should return quickly to ensire that the GUI + * thread stays alive. quit() should abort the action. + */ + virtual void exec(); + /** + * Quit aborts the action. No done() signal should + * be emitted. + */ + virtual void quit(); + +signals: + /** + * done() should always be emitted with this as first + * parameter, to avoid sender() magic and the like. + * @p success indicates whether the action was + * successful. + */ + void done(KFAction *me,bool success); + + /** + * Emit this signal to inform the user of interesting + * changes; setting msg to an empty string doesn't + * change any visible user message. @p progress + * indicates the action's progress (if that can be determined) + * and sending -1 leaves the visible indicator unchanged. + */ + void status(const QString &msg, int progress); + + /** error() displays a box. It interrupts + * the user's work and should be used with care. + */ + void error(const QString &msg, const QString &details); +} ; + + +/** + * Acts as a queue and executes the actions in the + * queue in FIFO order. + */ +class KFActionQueue : public KFAction +{ +Q_OBJECT + +public: + KFActionQueue(QObject *parent = 0L); + virtual ~KFActionQueue(); + + /** + * Add a KFAction to the queue. When exec() is called, + * the actions are called one after the other (if each + * action is successful; if any action fails, the whole + * queue fails and the unsuccessful action is the last + * one run.) Actions become the property of the queue + * action. Note that queues can be nested. + */ + void queue(KFAction *); + + virtual void exec(); + +protected slots: + void actionDone(KFAction *,bool); + +private: + class KFActionQueue_p *d; +} ; + + +/* +** The remainder of the Actions are concrete ones and +** might better go off to live in another header file, +** but this is only needed if the number of supported +** formats grows enormously. +*/ + +/** + * Description structure for floppy devices. + * devices is a list of possible device names (yay + * /dev/ consistency) while drive,blocks denotes + * fd0 or fd1, and the size of the disk (ought to + * be 1440, 1200, 720 or 360. I've never seen a 2880 + * floppy drive). + * + * Tracks is pretty bogus; see the internal code for its use. + * Similarly, flags are internal too. + */ + +typedef struct { const char **devices; + int drive; + int blocks; + int tracks; + int flags; } fdinfo; + +class KProcess; + +/** + * Concrete action for running a single external program. + */ + +class FloppyAction : public KFAction +{ +Q_OBJECT + +public: + FloppyAction(QObject *parent = 0L); + + /** + * Kills the running process, if one exists. + */ + virtual void quit(); + + /** + * ConfigureDevice() needs to be called prior to exec() + * or exec() will fail; this indicates which drive and + * density to use. + * + * \param driveno Number of drive (0 or 1) + * \param density Floppy density (in Kilobytes) + * \note This same function needs to be + * called on all subclasses in order to configure them + * for which drive to use, _along_ with their local + * configuration functions. + */ + + bool configureDevice(int driveno, int density ); + + /** + * \brief Configure the device with a device name + * + * This is an alternate to FloppyAction::configureDevice + * for user-given devices. + * + * \note It does not work for each type of FloppyAction yet + */ + bool configureDevice( const QString& newDeviceName ); + +protected: + fdinfo *deviceInfo; ///< Configuration info (Pointer into list of "/dev/..." entries) + QString deviceName; ///< Name of the device + +protected slots: + /** + * \brief Provide handling of the exit of the external program + */ + virtual void processDone(KProcess *); + /** + * \brief Provide handling of stdout + */ + virtual void processStdOut(KProcess *, char *, int); + /** + * \brief Provide handling stderr. + * + * The default implementation just sends stderr on + * to processStdOut(), so you need reimplement only + * FloppyAction::processStdOut if you choose. + */ + virtual void processStdErr(KProcess *, char *, int); + +protected: + KProcess *theProcess; + QString theProcessName; ///< human-readable + + /** + * Sets up connections, calls KProcess::run(). + * You need to *theProcess << program << args ; first. + */ + + bool startProcess(); +} ; + +/** + * Concrete class that runs fdformat(1) + */ + +class FDFormat : public FloppyAction +{ +public: + FDFormat(QObject *parent = 0L); + + virtual void exec(); + + + /** + * Concrete classes can provide a runtimeCheck + * function (heck, this is static, so the name + * is up to you) that checks if the required + * applications are available. This way, the + * calling application can decide not to use + * actions whose prerequisites are absent anyway. + */ + static bool runtimeCheck(); + + /** @p verify instructs fdformat(1) to verify the + * medium as well. + */ + + bool configure(bool verify); + + virtual void processStdOut(KProcess *, char *,int); + +protected: + static QString fdformatName; ///< path to executable. + int formatTrackCount; ///< How many tracks formatted. + bool doVerify; +} ; + +/** + * Zero out disk by runnind dd(1) + * \bug As dd terminates with the error "No space left on device", KFloppy aborts + */ +class DDZeroOut : public FloppyAction +{ +public: + DDZeroOut(QObject *parent = 0L); + + virtual void exec(); + + /** + * Concrete classes can provide a runtimeCheck + * function (heck, this is static, so the name + * is up to you) that checks if the required + * applications are available. This way, the + * calling application can decide not to use + * actions whose prerequisites are absent anyway. + */ + static bool runtimeCheck(); + +protected: + /** + * \brief Provide handling of the exit of the external program + */ + virtual void processDone(KProcess *); +protected: + static QString m_ddName; ///< path to executable. +} ; + + +/** + * Create an msdos (FAT) filesystem on the floppy. + */ +class FATFilesystem : public FloppyAction +{ +public: + FATFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /** + * newfs_msdos(1) doesn't support an additional verify, + * but Linux mkdosfs(1) does. Enable additional medium + * verify with @p verify. Disks can be labeled (@p label) with the + * remaining parameters (@p l). + */ + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); + +protected: + static QString newfs_fat; + + bool doVerify,doLabel; + QString label; + +} ; + +/** + * Format with Ext2 + */ +class Ext2Filesystem : public FloppyAction +{ +public: + Ext2Filesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /// Same args as FATFilesystem::configure + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); + +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; + +#ifdef ANY_BSD + +/** + * \brief Format with UFS + * \note BSD only + */ +class UFSFilesystem : public FloppyAction +{ +public: + UFSFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; +#endif + +#ifdef ANY_LINUX +/** + * \brief Format with Minix + * \note Linux only + */ +class MinixFilesystem : public FloppyAction +{ +public: + MinixFilesystem(QObject *parent = 0L); + + virtual void exec(); + + static bool runtimeCheck(); + + /// Same args as FATFilesystem::configure + bool configure(bool verify, bool label, const QString &l); + + /// Parse output + virtual void processStdOut(KProcess*, char* b, int l); +protected: + static QString newfs; + + bool doVerify,doLabel; + QString label; +} ; +#endif + +/** + * Utility function that looks for executables in $PATH + * and in /sbin and /usr/sbin. + */ + +QString findExecutable(const QString &); + +#endif + diff --git a/kfloppy/hi128-app-kfloppy.png b/kfloppy/hi128-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..ded3594 --- /dev/null +++ b/kfloppy/hi128-app-kfloppy.png diff --git a/kfloppy/hi16-app-kfloppy.png b/kfloppy/hi16-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..3b272fb --- /dev/null +++ b/kfloppy/hi16-app-kfloppy.png diff --git a/kfloppy/hi22-app-kfloppy.png b/kfloppy/hi22-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..c0b2fe3 --- /dev/null +++ b/kfloppy/hi22-app-kfloppy.png diff --git a/kfloppy/hi32-app-kfloppy.png b/kfloppy/hi32-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..a1bfb30 --- /dev/null +++ b/kfloppy/hi32-app-kfloppy.png diff --git a/kfloppy/hi48-app-kfloppy.png b/kfloppy/hi48-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..b53fc09 --- /dev/null +++ b/kfloppy/hi48-app-kfloppy.png diff --git a/kfloppy/hi64-app-kfloppy.png b/kfloppy/hi64-app-kfloppy.png Binary files differnew file mode 100644 index 0000000..c03b4b3 --- /dev/null +++ b/kfloppy/hi64-app-kfloppy.png diff --git a/kfloppy/main.cpp b/kfloppy/main.cpp new file mode 100644 index 0000000..f6aa98f --- /dev/null +++ b/kfloppy/main.cpp @@ -0,0 +1,79 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu> + Copyright (C) 2004, 2005 Nicolas GOUTTE <goutte@kde.org> + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include <kdeversion.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> + +#include "floppy.h" + + +static const char description[] = + I18N_NOOP("KDE Floppy Disk Utility"); + +static const KCmdLineOptions options[] = +{ + { "+[device]", I18N_NOOP("Default device"), 0 }, + KCmdLineLastOption +}; + +int main( int argc, char *argv[] ) +{ + KAboutData aboutData("kfloppy", + I18N_NOOP("KFloppy"), + KDE_VERSION_STRING, description, KAboutData::License_GPL, + "(c) 1997, Bernd Johannes Wuebben\n" + "(c) 2001, Chris Howells\n" + "(c) 2002, Adriaan de Groot\n" + "(c) 2004, 2005, Nicolas Goutte", + I18N_NOOP("KFloppy helps you format floppies with the filesystem of your choice.") + ); + + aboutData.addAuthor("Bernd Johannes Wuebben", I18N_NOOP("Author and former maintainer"), "wuebben@kde.org"); + aboutData.addCredit("Chris Howells", I18N_NOOP("User interface re-design"), "howells@kde.org"); + aboutData.addCredit("Adriaan de Groot", I18N_NOOP("Add BSD support"), "groot@kde.org"); + aboutData.addCredit("Nicolas Goutte", I18N_NOOP("Make KFloppy work again for KDE 3.4"), "goutte@kde.org"); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + QString device; + if (args->count()) { + device = args->arg(0); + } + args->clear(); + + KApplication a; + + FloppyData* floppy = new FloppyData(); + a.setMainWidget(floppy); + bool autoformat = floppy->setInitialDevice(device); + floppy->show(); + if (autoformat) + floppy->format(); + return a.exec(); +} + diff --git a/kfloppy/zip.cpp b/kfloppy/zip.cpp new file mode 100644 index 0000000..8a0ff29 --- /dev/null +++ b/kfloppy/zip.cpp @@ -0,0 +1,305 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 by Adriaan de Groot + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <sys/types.h> +#include <signal.h> + +#include <stdlib.h> +#include <ctype.h> + +#include "debug.h" +#include "zip.moc" + +#include <qcheckbox.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qwhatsthis.h> + +#include <klocale.h> +#include <kprocess.h> +#include <kconfig.h> + +ZipFormat::ZipFormat(QWidget *w,const char *n) : + DiskFormat(w,n), + zeroWholeDisk(0L), + p(0L), + formatStep(0), + statusTimer(0L) +{ + DEBUGSETUP; + + QGridLayout *grid = new QGridLayout(this,1,1,10); + + zeroWholeDisk = new QCheckBox(i18n("Zero entire disk"),this); + QWhatsThis::add(zeroWholeDisk, + i18n("Try to write zeroes to the entire disk " + "before adding a filesystem, in order " + "to check the disk's integrity.")); + grid->addWidget(zeroWholeDisk,0,0); + enableSoftUpdates = new QCheckBox(i18n("Enable softupdates"),this); + grid->addWidget(enableSoftUpdates,1,0); + + // Remember the stretch at the bottom to clear + // up layour problems when this widget is smaller + // than others in the stack. + // + grid->addRowSpacing(2,10); + grid->setRowStretch(2,100); + + endInit(); +} + +const char fslabel[] = I18N_NOOP("UFS Zip100"); + +FilesystemList ZipFormat::FSLabels() const +{ + FilesystemList l; + // THis isn't a basic format anywhere, I don't think. + l.append(new FilesystemData(i18n(fslabel),0xefc87329,(DiskFormat *)this)); + return l; +} + +/* static */ bool ZipFormat::runtimeCheck() +{ + DEBUGSETUP; + dd = findExecutable("dd"); + newfs = findExecutable("newfs"); + return !newfs.isEmpty() && !dd.isEmpty(); +} + +/* static */ QString ZipFormat::dd; +/* static */ QString ZipFormat::newfs; + +/* virtual slot */ void ZipFormat::setEnabled(bool b) +{ + zeroWholeDisk->setEnabled(b); + enableSoftUpdates->setEnabled(b); +} + +/* virtual */ void ZipFormat::readSettings(KConfig *c) +{ + c->setGroup(fslabel); + zeroWholeDisk->setChecked( + c->readBoolEntry("ZeroDisk",false)); + enableSoftUpdates->setChecked( + c->readBoolEntry("SoftUpdates",false)); +} + +/* virtual */ void ZipFormat::writeSettings(KConfig *c) +{ + c->setGroup(fslabel); + c->writeEntry("ZeroDisk",zeroWholeDisk->isChecked()); + c->writeEntry("SoftUpdates",enableSoftUpdates->isChecked()); +} + +void ZipFormat::quit() +{ + DEBUGSETUP; + if (p) delete p; + if (statusTimer) delete statusTimer; + + p=0L; + statusTimer=0L; +} + +/* virtual slot */ void ZipFormat::format(FilesystemData *f) +{ + DEBUGSETUP; + + if (f->magic()!=0xefc87329) + { + complainAboutFormat(f); + return; + } + + formatStep=0; + + if (p) delete p; + p = new KProcess(); + + if (statusTimer) delete statusTimer; + statusTimer = new QTimer(this); + + connect(p,SIGNAL(processExited(KProcess *)), + this,SLOT(transition())); + connect(p,SIGNAL(receivedStdout(KProcess *,char *,int)), + this,SLOT(processResult(KProcess *,char *,int))); + connect(p,SIGNAL(receivedStderr(KProcess *,char *,int)), + this,SLOT(processResult(KProcess *,char *,int))); + connect(statusTimer,SIGNAL(timeout()), + this,SLOT(statusRequest())); + + transition(); +} + +void ZipFormat::transition() +{ + DEBUGSETUP; + + switch(formatStep) + { + case 0 : + // We're using a larger block size to speed up writing. + // So instead of 196608 blocks of 512b, use 12288 blocks + // of 8k instead. + // + // For newfs we need to set the real number of blocks. + // + if (zeroWholeDisk->isChecked()) + { + // Zeroing whole disk takes about 2 min. + // No point in making a dizzy display of it. + statusTimer->start(10000); + QTimer::singleShot(1000,this, + SLOT(statusRequest())); + totalBlocks=12288; // 196608 * 512b = 12288 * 8192b ; + } + else + { + // Takes about 5 seconds. + statusTimer->start(1000); + totalBlocks=100; + } + + *p << dd + << "if=/dev/zero" + << "of=/dev/afd0c" + << "bs=8192" ; + *p << QString("count=%1").arg(totalBlocks); + if (!p->start(KProcess::NotifyOnExit,KProcess::AllOutput)) + { + emit statusMessage(i18n("Cannot start dd to zero disk.")); + emit formatDone(-1); + delete statusTimer; + delete p; + statusTimer=0L; + p=0L; + return; + } + + formatStep=1; + emit statusMessage(i18n("Zeroing disk...")); + break; + case 1 : + statusTimer->stop(); + // The dd for zeroing the disk has finished. + if (p->exitStatus()) + { + emit statusMessage(i18n("Zeroing disk failed.")); + emit formatDone(-1); + return; + } + + totalBlocks=196608; // Now use the real number of 512b blocks + + p->clearArguments(); + *p << newfs << "-T" << "zip100" ; + if (enableSoftUpdates->isChecked()) + { + *p << "-U" ; + } + *p << "/dev/afd0c" ; + if (!p->start(KProcess::NotifyOnExit,KProcess::AllOutput)) + { + emit statusMessage(i18n("Cannot start newfs.")); + emit formatDone(-1); + }; + formatStep=2; + emit statusMessage(i18n("Making filesystem...")); + break; + case 2 : + if (p->exitStatus()) + { + emit statusMessage(i18n("newfs failed.")); + emit formatDone(-1); + } + else + { + emit statusMessage(i18n("Disk formatted successfully.")); + emit formatDone(0); + } + break; + } +} + +void ZipFormat::processResult(KProcess *, char *b, int l) +{ + DEBUGSETUP; + +#ifdef DEBUG + QString o = QString::fromLatin1(b,l); + DEBUGS(QString(" %1").arg(o).latin1()); +#endif + + switch(formatStep) + { + case 1 : // These are messages from dd + if (strchr(b,'+')) + { + int currentblock=atoi(b); + emit setProgress(currentblock*100/totalBlocks); + if (totalBlocks>10000) + { + emit statusMessage(i18n("Zeroing block %1 of %2...") + .arg(currentblock) + .arg(totalBlocks)); + } + } + break; + case 2 : // These are messages from newfs + if ((b[0]==' ') && isdigit(b[1])) + { + int currentblock=atoi(b+1); + emit setProgress(currentblock*100/totalBlocks); + } + else + { + // This is the initial display message from + // newfs. It writes a first block to sector 32. + // + // + emit setProgress(1); + + // QString myBuf = QString::fromLatin1(b, l); + // DEBUGS(myBuf.latin1()); + } + break; + } +} + +void ZipFormat::statusRequest() +{ + if (formatStep!=1) // Not in dd mode? + return; + if (!p) // How can that happen? + return; + +#ifdef ANY_BSD + p->kill(SIGINFO); +#endif +} + + diff --git a/kfloppy/zip.h b/kfloppy/zip.h new file mode 100644 index 0000000..0054c50 --- /dev/null +++ b/kfloppy/zip.h @@ -0,0 +1,106 @@ +/* + + This file is part of the KFloppy program, part of the KDE project + + Copyright (C) 2002 by Adriaan de Groot + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + + +#ifndef _ZIP_FORMAT_H +#define _ZIP_FORMAT_H + +/** + * \file zip.h + * + * This file defines the ZipFormat class, a DiskFormat + * for KFloppy that deals with Zip disks and UFS under + * FreeBSD (and probably other BSD's, as well). + * + * \todo Add device selector to zip class + * \note This class is not used by KFloppy + * \bug This class assumes thatthe Zip disk has 100MB. It does not support 250MB and 750MB + */ + +#include "format.h" + +class QCheckBox; +class QTimer; +class KProcess; +class KConfig; + +class ZipFormat : public DiskFormat +{ +Q_OBJECT + +public: + ZipFormat(QWidget *w, const char *n); + + // All the virtuals we need to make + // a concrete DiskFormat class. See + // format.h for details. + // + virtual FilesystemList FSLabels() const; + virtual void setEnabled(bool); + virtual void format(FilesystemData *); + virtual void quit(); + virtual void readSettings(KConfig *); + virtual void writeSettings(KConfig *); + + /** Check for dd and newfs, which we + * need to do the formatting. + */ + static bool runtimeCheck(); + +protected: + QCheckBox *zeroWholeDisk; + QCheckBox *enableSoftUpdates; + + static QString newfs,dd; + + KProcess *p; ///< dd or newfs, doing the real work + int formatStep; ///< keeps track of what phase we are in + + // Variables for the zeroing phase + int totalBlocks; + QTimer *statusTimer; + +protected slots: + /** + * transition() realises the state machine we use + * to handle the different phases of the format: + * startup, dd and newfs. + */ + void transition(); + + /** + * processResult() reads output + * from either dd or newfs and interprets it. + */ + void processResult(KProcess *,char *,int); + + /** + *statusRequest() + * sends dd a SIGINFO to get it to print out block counts, + * which then triggers processResult() so that we can keep + * the progress bar moving. + */ + void statusRequest(); +}; + +#endif |