File indexing completed on 2024-10-06 04:26:02
0001 /* 0002 SPDX-FileCopyrightText: 2003-2008 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 2011 Michal Malek <michalm@jabster.pl> 0004 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 0009 #include <config-k3b.h> 0010 0011 0012 #include "k3bsystemproblemdialog.h" 0013 #include "k3b.h" 0014 #include "k3bapplication.h" 0015 #include "k3bthemedheader.h" 0016 #include "k3btitlelabel.h" 0017 #include "k3bexternalbinmanager.h" 0018 #include "k3bstdguiitems.h" 0019 #include "k3bdevicemanager.h" 0020 #include "k3bdevice.h" 0021 #include "k3bversion.h" 0022 #include "k3bglobals.h" 0023 #include "k3bpluginmanager.h" 0024 #include "k3bplugin.h" 0025 #include "k3bthememanager.h" 0026 #include "k3bcore.h" 0027 0028 #include <KColorScheme> 0029 #include <KConfigGroup> 0030 #include <KSharedConfig> 0031 #include <KProcess> 0032 #include <KNotification> 0033 #include <KLocalizedString> 0034 #include <KMessageBox> 0035 #include <KStandardGuiItem> 0036 0037 #include <QFileInfo> 0038 #include <QList> 0039 #include <QCloseEvent> 0040 #include <QIcon> 0041 #include <QCheckBox> 0042 #include <QDialogButtonBox> 0043 #include <QGridLayout> 0044 #include <QHBoxLayout> 0045 #include <QPushButton> 0046 #include <QTextEdit> 0047 0048 #ifdef HAVE_ICONV 0049 #include <langinfo.h> 0050 #endif 0051 0052 #ifdef HAVE_FSTAB_H 0053 #include <fstab.h> 0054 #endif 0055 #include <unistd.h> 0056 0057 0058 static QString markupString( const QString& s_ ) 0059 { 0060 QString s(s_); 0061 s.replace( '<', "<" ); 0062 s.replace( '>', ">" ); 0063 return s; 0064 } 0065 0066 0067 K3b::SystemProblem::SystemProblem( Type t, 0068 const QString& p, 0069 const QString& d, 0070 const QString& s ) 0071 : type(t), 0072 problem(p), 0073 details(d), 0074 solution(s) 0075 { 0076 } 0077 0078 0079 K3b::SystemProblemDialog::SystemProblemDialog( const QList<K3b::SystemProblem>& problems, 0080 bool showDeviceSettingsButton, 0081 bool showBinSettingsButton, 0082 bool forceCheck, 0083 QWidget* parent) 0084 : QDialog( parent ) 0085 { 0086 setWindowTitle( i18n("System Configuration Problems") ); 0087 // setup the title 0088 // --------------------------------------------------------------------------------------------------- 0089 K3b::ThemedHeader* titleFrame = new K3b::ThemedHeader( this ); 0090 titleFrame->setTitle( i18n("System Configuration Problems"), 0091 i18np("1 problem", "%1 problems", problems.count() ) ); 0092 0093 QDialogButtonBox* buttonBox = new QDialogButtonBox( this ); 0094 connect( buttonBox, SIGNAL(accepted()), SLOT(accept()) ); 0095 connect( buttonBox, SIGNAL(rejected()), SLOT(reject()) ); 0096 0097 if( showDeviceSettingsButton || showBinSettingsButton ) { 0098 QPushButton* configureButton = buttonBox->addButton( i18n("Configure K3b..."), QDialogButtonBox::NoRole ); 0099 if( showDeviceSettingsButton ) { 0100 connect( configureButton, SIGNAL(clicked()), SLOT(slotShowDeviceSettings()) ); 0101 } else if( showBinSettingsButton ) { 0102 connect( configureButton, SIGNAL(clicked()), SLOT(slotShowBinSettings()) ); 0103 } 0104 } 0105 0106 buttonBox->addButton( QDialogButtonBox::Close ); 0107 0108 m_checkDontShowAgain = new QCheckBox( i18n("Do not show again"), this ); 0109 m_checkDontShowAgain->setVisible(!forceCheck); 0110 0111 // setup the problem view 0112 // --------------------------------------------------------------------------------------------------- 0113 QTextEdit* view = new QTextEdit( this ); 0114 view->setReadOnly(true); 0115 0116 // layout everything 0117 QGridLayout* grid = new QGridLayout( this ); 0118 grid->addWidget( titleFrame, 0, 0, 1, 2 ); 0119 grid->addWidget( view, 1, 0, 1, 2 ); 0120 grid->addWidget( m_checkDontShowAgain, 2, 0 ); 0121 grid->addWidget( buttonBox, 2, 1 ); 0122 grid->setColumnStretch( 0, 1 ); 0123 grid->setRowStretch( 1, 1 ); 0124 0125 const KColorScheme colorScheme( QPalette::Normal, KColorScheme::Button ); 0126 const QColor negativeTextColor = colorScheme.foreground( KColorScheme::NegativeText ).color(); 0127 0128 QString text = "<html>"; 0129 0130 for( QList<K3b::SystemProblem>::const_iterator it = problems.constBegin(); 0131 it != problems.constEnd(); ++it ) { 0132 const K3b::SystemProblem& p = *it; 0133 0134 text.append( "<p><b>" ); 0135 if( p.type == K3b::SystemProblem::CRITICAL ) { 0136 text.append( QString("<span style=\"color:%1\">").arg( negativeTextColor.name() ) ); 0137 } 0138 text.append( markupString( p.problem ) ); 0139 if( p.type == K3b::SystemProblem::CRITICAL ) 0140 text.append( "</span>" ); 0141 text.append( "</b><br>" ); 0142 text.append( markupString( p.details ) + "<br>" ); 0143 if( !p.solution.isEmpty() ) 0144 text.append( "<i>" + i18n("Solution") + "</i>: " + p.solution ); 0145 text.append( "</p>" ); 0146 } 0147 0148 text.append( "</html>" ); 0149 0150 view->setText(text); 0151 view->moveCursor( QTextCursor::Start ); 0152 view->ensureCursorVisible(); 0153 } 0154 0155 0156 void K3b::SystemProblemDialog::done(int r) 0157 { 0158 if (m_checkDontShowAgain->isChecked()) { 0159 KConfigGroup grp(KSharedConfig::openConfig(), QStringLiteral("General Options")); 0160 grp.writeEntry("check system config", false); 0161 } 0162 QDialog::done(r); 0163 } 0164 0165 0166 void K3b::SystemProblemDialog::checkSystem(QWidget* parent, NotificationLevel level, bool forceCheck) 0167 { 0168 QList<K3b::SystemProblem> problems; 0169 bool showDeviceSettingsButton = false; 0170 bool showBinSettingsButton = false; 0171 0172 if (!forceCheck && !readCheckSystemConfig()) 0173 return; 0174 0175 const K3b::ExternalBin* cdrecordBin = k3bcore->externalBinManager()->binObject("cdrecord"); 0176 0177 if( k3bcore->deviceManager()->allDevices().isEmpty() ) { 0178 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0179 i18n("No optical drive found."), 0180 i18n("K3b did not find any optical device in your system."), 0181 #ifdef ENABLE_HAL_SUPPORT 0182 i18n("Make sure HAL daemon is running, it is used by K3b for finding devices.") 0183 #else 0184 QString() 0185 #endif 0186 ) ); 0187 } 0188 else if( k3bcore->deviceManager()->cdWriter().isEmpty() ) { 0189 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0190 i18n("No CD/DVD/BD writer found."), 0191 i18n("K3b did not find an optical writing device in your system. Thus, " 0192 "you will not be able to burn CDs or DVDs. However, you can still " 0193 "use other K3b features such as audio track extraction, audio " 0194 "transcoding or ISO 9660 image creation."), 0195 QString() ) ); 0196 } 0197 else { 0198 // 1. cdrecord, cdrdao 0199 if( !k3bcore->externalBinManager()->binNeedGroup( "cdrecord" ).isEmpty() ) { 0200 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0201 i18n("Insufficient permissions for %1 executable: %2",QString("cdrecord"),k3bcore->externalBinManager()->binPath("cdrecord")), 0202 i18n("K3b uses cdrecord to actually write CDs."), 0203 i18n("Check permissions via Settings -> Configure K3b... -> Programs -> Permissions. " 0204 "If K3b's default value is set make sure you are member of \"%1\" group.", k3bcore->externalBinManager()->binNeedGroup( "cdrecord" )) ) ); 0205 } 0206 else if( !k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) { 0207 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0208 i18n("Unable to find %1 executable",QString("cdrecord")), 0209 i18n("K3b uses cdrecord to actually write CDs."), 0210 i18n("Install the cdrtools package which contains " 0211 "cdrecord.") ) ); 0212 } 0213 else { 0214 if( cdrecordBin && cdrecordBin->hasFeature( "outdated" ) ) { 0215 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0216 i18n("Used %1 version %2 is outdated",QString("cdrecord"),QString(cdrecordBin->version())), 0217 i18n("Although K3b supports all cdrtools versions since " 0218 "1.10 it is highly recommended to at least use " 0219 "version 2.0."), 0220 i18n("Install a more recent version of the cdrtools.") ) ); 0221 } 0222 0223 #ifdef Q_OS_LINUX 0224 0225 // 0226 // Since kernel 2.6.8 older cdrecord versions are not able to use the SCSI subsystem when running suid root anymore 0227 // So far we ignore the suid root issue with kernel >= 2.6.8 and cdrecord < 2.01.01a02 0228 // 0229 // Kernel 2.6.16.something seems to introduce another problem which was apparently worked around in cdrecord 2.01.01a05 0230 // 0231 if( K3b::simpleKernelVersion() >= K3b::Version( 2, 6, 8 ) && cdrecordBin && 0232 cdrecordBin->version() < K3b::Version( 2, 1, 1, "a05" ) && !cdrecordBin->hasFeature( "wodim" ) ) { 0233 if( cdrecordBin->hasFeature( "suidroot" ) ) { 0234 showBinSettingsButton = true; 0235 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0236 i18n("%1 will be run with root privileges on kernel >= 2.6.8",QString("cdrecord <= 2.01.01a05")), 0237 i18n("Since Linux kernel 2.6.8 %1 will not work when run suid " 0238 "root for security reasons anymore.", 0239 QLatin1String( "cdrecord <= 2.01.01a05") ), 0240 i18n("Click \"Configure K3b...\" to solve this problem.") ) ); 0241 } 0242 } 0243 #ifdef CDRECORD_SUID_ROOT_CHECK 0244 else if( !k3bcore->externalBinManager()->binObject( "cdrecord" )->hasFeature( "suidroot" ) && getuid() != 0 ) { // not root 0245 showBinSettingsButton = true; 0246 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0247 i18n("%1 will be run without root privileges",QString("cdrecord")), 0248 i18n("It is highly recommended to configure cdrecord " 0249 "to run with root privileges, as then cdrecord " 0250 "runs with high priority that increases the overall " 0251 "stability of the burning process. As well as this, " 0252 "it allows the size of the burning buffer to be changed, " 0253 "and a lot of user problems can be solved this way."), 0254 i18n("Click \"Configure K3b...\" to solve this problem.") ) ); 0255 } 0256 #endif // CDRECORD_SUID_ROOT_CHECK 0257 #endif 0258 } 0259 0260 if( !k3bcore->externalBinManager()->binNeedGroup( "cdrdao" ).isEmpty() ) { 0261 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0262 i18n("Insufficient permissions for %1 executable: %2",QString("cdrdao"),k3bcore->externalBinManager()->binPath("cdrdao")), 0263 i18n("K3b uses cdrdao to actually write CDs."), 0264 i18n("Check permissions via Settings -> Configure K3b... -> Programs -> Permissions. " 0265 "If K3b's default value is set make sure you are member of \"%1\" group.", k3bcore->externalBinManager()->binNeedGroup( "cdrdao" )) ) ) ; 0266 } 0267 0268 else if( !k3bcore->externalBinManager()->foundBin( "cdrdao" ) ) { 0269 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0270 i18n("Unable to find %1 executable",QString("cdrdao")), 0271 i18n("K3b uses cdrdao to actually write CDs."), 0272 i18n("Install the cdrdao package.") ) ); 0273 } 0274 else { 0275 #ifdef Q_OS_LINUX 0276 #ifdef CDRECORD_SUID_ROOT_CHECK 0277 if( !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "suidroot" ) && getuid() != 0 ) { 0278 showBinSettingsButton = true; 0279 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0280 i18n("%1 will be run without root privileges",QString("cdrdao")), 0281 i18n("It is highly recommended to configure cdrdao " 0282 "to run with root privileges to increase the " 0283 "overall stability of the burning process."), 0284 i18n("Click \"Configure K3b...\" to solve this problem.") ) ); 0285 } 0286 #endif // CDRECORD_SUID_ROOT_CHECK 0287 #endif 0288 } 0289 0290 if (!k3bcore->externalBinManager()->foundBin("cdrskin")) { 0291 problems.append(K3b::SystemProblem(K3b::SystemProblem::NON_CRITICAL, 0292 i18n("Unable to find %1 executable", QString("cdrskin")), 0293 i18n("Cdrskin can substitute for cdrecord with data and audio" 0294 " CD, and for growisofs with DVD and BD."), 0295 i18n("Consider to install the libburn and cdrskin packages."))); 0296 } 0297 } 0298 0299 0300 if( !k3bcore->deviceManager()->dvdWriter().isEmpty() ) { 0301 0302 if( !k3bcore->externalBinManager()->binNeedGroup( "growisofs" ).isEmpty() ) { 0303 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0304 i18n("Insufficient permissions for %1 executable: %2",QString("growisofs"),k3bcore->externalBinManager()->binPath("growisofs")), 0305 i18n("K3b uses growisofs to actually write DVDs. " 0306 "Without growisofs you will not be able to write DVDs. " 0307 "Make sure to install at least version 5.10."), 0308 i18n("Check permissions via Settings -> Configure K3b... -> Programs -> Permissions. " 0309 "If K3b's default value is set make sure you are member of \"%1\" group.", k3bcore->externalBinManager()->binNeedGroup( "growisofs" )) ) ); 0310 } 0311 0312 else if( !k3bcore->externalBinManager()->foundBin( "growisofs" ) ) { 0313 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0314 i18n("Unable to find %1 executable",QString("growisofs")), 0315 i18n("K3b uses growisofs to actually write DVDs. " 0316 "Without growisofs you will not be able to write DVDs. " 0317 "Make sure to install at least version 5.10."), 0318 i18n("Install the dvd+rw-tools package.") ) ); 0319 } 0320 else { 0321 if( k3bcore->externalBinManager()->binObject( "growisofs" )->version() < K3b::Version( 5, 10 ) ) { 0322 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0323 i18n("Used %1 version %2 is outdated",QString("growisofs"),k3bcore->externalBinManager()->binObject( "growisofs" )->version()), 0324 i18n("K3b needs at least growisofs version 5.10 to write DVDs. " 0325 "All older versions will not work and K3b will refuse to use them."), 0326 i18n("Install a more recent version of %1.",QString("growisofs")) ) ); 0327 } 0328 else if( k3bcore->externalBinManager()->binObject( "growisofs" )->version() < K3b::Version( 5, 12 ) ) { 0329 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0330 i18n("Used %1 version %2 is outdated",QString("growisofs"),k3bcore->externalBinManager()->binObject( "growisofs" )->version()), 0331 i18n("K3b will not be able to copy DVDs on-the-fly or write a DVD+RW in multiple " 0332 "sessions using a growisofs " 0333 "version older than 5.12."), 0334 i18n("Install a more recent version of %1.",QString("growisofs")) ) ); 0335 } 0336 else if( k3bcore->externalBinManager()->binObject( "growisofs" )->version() < K3b::Version( 7, 0 ) ) { 0337 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0338 i18n("Used %1 version %2 is outdated",QString("growisofs"),k3bcore->externalBinManager()->binObject( "growisofs" )->version()), 0339 i18n("It is highly recommended to use growisofs 7.0 or higher. " 0340 "K3b will not be able to write a DVD+RW in multiple " 0341 "sessions using a growisofs version older than 7.0." ), 0342 i18n("Install a more recent version of %1.",QString("growisofs")) ) ); 0343 } 0344 // // for now we ignore the suid root bit because of the memorylocked issue 0345 // else if( !k3bcore->externalBinManager()->binObject( "growisofs" )->hasFeature( "suidroot" ) ) { 0346 // showBinSettingsButton = true; 0347 // problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0348 // i18n("%1 will be run without root privileges","growisofs"), 0349 // i18n("It is highly recommended to configure growisofs " 0350 // "to run with root privileges. Only then growisofs " 0351 // "runs with high priority which increases the overall " 0352 // "stability of the burning process."), 0353 // i18n("Click \"Configure K3b...\" to solve this problem.") ) ); 0354 // } 0355 } 0356 0357 if( !k3bcore->externalBinManager()->foundBin( "dvd+rw-format" ) ) { 0358 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0359 i18n("Unable to find %1 executable",QString("dvd+rw-format")), 0360 i18n("K3b uses dvd+rw-format to format DVD-RWs and DVD+RWs."), 0361 i18n("Install the dvd+rw-tools package.") ) ); 0362 } 0363 } 0364 0365 if( !k3bcore->externalBinManager()->foundBin( "mkisofs" ) ) { 0366 0367 } 0368 else if( k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "outdated" ) ) { 0369 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0370 i18n("Used %1 version %2 is outdated", 0371 QString("mkisofs"), 0372 k3bcore->externalBinManager()->binObject( "mkisofs" )->version()), 0373 i18n("K3b needs at least mkisofs version 1.14. Older versions may introduce problems " 0374 "when creating data projects."), 0375 i18n("Install a more recent version of %1.",QString("mkisofs")) ) ); 0376 } 0377 0378 // 2. device check 0379 #ifdef __GNUC__ 0380 #warning Make sure we have a proper new kernel and cdrecord for simple dev= stuff 0381 #endif 0382 bool atapiWriter = false; 0383 bool dvd_r_dl = false; 0384 QList<K3b::Device::Device *> items(k3bcore->deviceManager()->readingDevices()); 0385 for( QList<K3b::Device::Device *>::const_iterator it = items.constBegin(); 0386 it != items.constEnd(); ++it ) { 0387 if( (*it)->type() & K3b::Device::DEVICE_DVD_R_DL ) 0388 dvd_r_dl = true; 0389 } 0390 0391 #ifdef HAVE_FSTAB_H 0392 // check automounted devices 0393 QList<K3b::Device::Device*> automountedDevices = checkForAutomounting(); 0394 for( QList<K3b::Device::Device *>::const_iterator it = automountedDevices.constBegin(); 0395 it != automountedDevices.constEnd(); ++it ) { 0396 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0397 i18n("Device %1 - %2 is automounted.", 0398 (*it)->vendor(),(*it)->description()), 0399 i18n("K3b is not able to unmount automounted devices. Thus, especially " 0400 "DVD+RW rewriting might fail. There is no need to report this as " 0401 "a bug or feature wish; it is not possible to solve this problem " 0402 "from within K3b."), 0403 i18n("Replace the automounting entries in /etc/fstab with old-fashioned " 0404 "ones or use a user-space mounting solution like pmount or ivman.") ) ); 0405 } 0406 0407 #endif 0408 if( atapiWriter ) { 0409 if( !K3b::plainAtapiSupport() && 0410 !K3b::hackedAtapiSupport() ) { 0411 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0412 i18n("No ATAPI writing support in kernel"), 0413 i18n("Your kernel does not support writing without " 0414 "SCSI emulation but there is at least one " 0415 "writer in your system not configured to use " 0416 "SCSI emulation."), 0417 i18n("The best and recommended solution is to enable " 0418 "ide-scsi (SCSI emulation) for all devices. " 0419 "This way you will not have any problems. " 0420 "Be aware that you may still enable DMA on ide-scsi " 0421 "emulated drives.") ) ); 0422 } 0423 else { 0424 // we have atapi support in some way in the kernel 0425 0426 if( k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) { 0427 0428 if( !( cdrecordBin->hasFeature( "hacked-atapi" ) && 0429 K3b::hackedAtapiSupport() ) && 0430 !( cdrecordBin->hasFeature( "plain-atapi" ) && 0431 K3b::plainAtapiSupport() ) ) { 0432 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0433 i18n("%1 %2 does not support ATAPI",QString("cdrecord"),cdrecordBin->version()), 0434 i18n("The configured version of %1 does not " 0435 "support writing to ATAPI devices without " 0436 "SCSI emulation and there is at least one writer " 0437 "in your system not configured to use " 0438 "SCSI emulation.",QString("cdrecord")), 0439 i18n("The best, and recommended, solution is to use " 0440 "ide-scsi (SCSI emulation) for all writer devices: " 0441 "this way you will not have any problems; or, you can install " 0442 "(or select as the default) a more recent version of %1.",QString("cdrtools")) ) ); 0443 } 0444 } 0445 0446 if( k3bcore->externalBinManager()->foundBin( "cdrdao" ) ) { 0447 0448 if( !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "hacked-atapi" ) && 0449 !k3bcore->externalBinManager()->binObject( "cdrdao" )->hasFeature( "plain-atapi") ) { 0450 // FIXME: replace ">" with ">" 0451 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0452 i18n("%1 %2 does not support ATAPI", 0453 QLatin1String( "cdrdao"), 0454 k3bcore->externalBinManager()->binObject("cdrdao")->version().toString() ), 0455 i18n("The configured version of %1 does not " 0456 "support writing to ATAPI devices without " 0457 "SCSI emulation and there is at least one writer " 0458 "in your system not configured to use " 0459 "SCSI emulation.", QLatin1String( "cdrdao" ) ), 0460 K3b::simpleKernelVersion() > K3b::Version( 2, 5, 0 ) 0461 ? i18n("Install cdrdao >= 1.1.8 which supports writing to " 0462 "ATAPI devices directly.") 0463 : i18n("The best, and recommended, solution is to use " 0464 "ide-scsi (SCSI emulation) for all writer devices: " 0465 "this way you will not have any problems; or, you can install " 0466 "(or select as the default) a more recent version of %1.", 0467 QString("cdrdao")) ) ); 0468 } 0469 } 0470 } 0471 } 0472 0473 if( dvd_r_dl && k3bcore->externalBinManager()->foundBin( "growisofs" ) && k3bcore->externalBinManager()->binNeedGroup( "growisofs" ).isEmpty() ) { 0474 if( k3bcore->externalBinManager()->binObject( "growisofs" )->version() < K3b::Version( 6, 0 ) ) { 0475 problems.append( K3b::SystemProblem( K3b::SystemProblem::NON_CRITICAL, 0476 i18n("Used %1 version %2 is outdated",QString("growisofs"),k3bcore->externalBinManager()->binObject( "growisofs" )->version()), 0477 i18n("K3b will not be able to write DVD-R Dual Layer media using a growisofs " 0478 "version older than 6.0."), 0479 i18n("Install a more recent version of growisofs.") ) ); 0480 } 0481 } 0482 0483 QList<K3b::Device::Device *> items2(k3bcore->deviceManager()->allDevices()); 0484 for( QList<K3b::Device::Device *>::const_iterator it = items2.constBegin(); 0485 it != items2.constEnd(); ++it ) { 0486 K3b::Device::Device* dev = (*it); 0487 #ifndef Q_OS_WIN32 0488 if( !QFileInfo( dev->blockDeviceName() ).isWritable() ) { 0489 showDeviceSettingsButton = true; 0490 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0491 i18n("No write access to device %1",dev->blockDeviceName()), 0492 i18n("K3b needs write access to all the devices to perform certain tasks. " 0493 "Without it you might encounter problems with %1 - %2",dev->vendor(),dev->description()), 0494 i18n("Make sure you have write access to %1. In case you are not using " 0495 "devfs or udev click \"Modify Permissions...\" and setup permissions by hand.",dev->blockDeviceName()) ) ); 0496 } 0497 0498 if( !dmaActivated( dev ) ) { 0499 problems.append( K3b::SystemProblem( K3b::SystemProblem::CRITICAL, 0500 i18n("DMA disabled on device %1 - %2",dev->vendor(),dev->description()), 0501 i18n("With most modern CD/DVD/BD devices enabling DMA highly increases " 0502 "read/write performance. If you experience very low writing speeds " 0503 "this is probably the cause."), 0504 i18n("Enable DMA temporarily as root with 'hdparm -d 1 %1'.",dev->blockDeviceName()) ) ); 0505 } 0506 #endif 0507 } 0508 0509 0510 // 0511 // Check if the user specified some user parameters and warn about it 0512 // 0513 const QMap<QString, K3b::ExternalProgram*>& programMap = k3bcore->externalBinManager()->programs(); 0514 for( QMap<QString, K3b::ExternalProgram*>::const_iterator it = programMap.constBegin(); 0515 it != programMap.constEnd(); ++it ) { 0516 const K3b::ExternalProgram* p = *it; 0517 if( !p->userParameters().isEmpty() ) { 0518 problems.append( K3b::SystemProblem( K3b::SystemProblem::WARNING, 0519 i18n("User parameters specified for external program %1",p->name()), 0520 i18n("Sometimes it may be necessary to specify user parameters in addition to " 0521 "the parameters generated by K3b. This is simply a warning to make sure that " 0522 "these parameters are really wanted and will not be part of some bug report."), 0523 i18n("To remove the user parameters for the external program %1 open the " 0524 "K3b settings page 'Programs' and choose the tab 'User Parameters'." 0525 ,p->name()) ) ); 0526 } 0527 } 0528 0529 // 0530 // Way too many users are complaining about K3b not being able to decode mp3 files. So just warn them about 0531 // the legal restrictions with many distros 0532 // 0533 QList<K3b::Plugin*> plugins = k3bcore->pluginManager()->plugins( "AudioDecoder" ); 0534 bool haveMp3Decoder = false; 0535 for( QList<K3b::Plugin*>::const_iterator it = plugins.constBegin(); 0536 it != plugins.constEnd(); ++it ) { 0537 const KPluginMetaData &metaData = (*it)->pluginMetaData(); 0538 if (metaData.isValid() && metaData.pluginId() == "k3bmaddecoder" ) { 0539 haveMp3Decoder = true; 0540 break; 0541 } 0542 } 0543 if( !haveMp3Decoder ) { 0544 problems.append( K3b::SystemProblem( K3b::SystemProblem::WARNING, 0545 i18n("MP3 Audio Decoder plugin not found."), 0546 i18n("K3b could not load or find the MP3 decoder plugin. This means that you will not " 0547 "be able to create Audio CDs from MP3 files. Many Linux distributions do not " 0548 "include MP3 support for legal reasons."), 0549 i18n("To enable MP3 support, please install the MAD MP3 decoding library as well as the " 0550 "K3b MAD MP3 decoder plugin (the latter may already be installed but not functional " 0551 "due to the missing libmad). Some distributions allow installation of MP3 support " 0552 "via an online update tool.") ) ); 0553 } 0554 0555 #ifdef HAVE_ICONV 0556 char* codec = nl_langinfo( CODESET ); 0557 if( strcmp( codec, "ANSI_X3.4-1968" ) == 0 ) { 0558 // 0559 // On a glibc system the system locale defaults to ANSI_X3.4-1968 0560 // It is very unlikely that one would set the locale to ANSI_X3.4-1968 0561 // intentionally 0562 // 0563 problems.append( K3b::SystemProblem( K3b::SystemProblem::WARNING, 0564 i18n("System locale charset is ANSI_X3.4-1968"), 0565 i18n("Your system's locale charset (i.e. the charset used to encode filenames) " 0566 "is set to ANSI_X3.4-1968. It is highly unlikely that this has been done " 0567 "intentionally. Most likely the locale is not set at all. An invalid setting " 0568 "will result in problems when creating data projects."), 0569 i18n("To properly set the locale charset make sure the LC_* environment variables " 0570 "are set. Normally the distribution setup tools take care of this.") ) ); 0571 } 0572 #endif 0573 0574 0575 // 0576 // Never run K3b as root and especially not suid root! The latter is not possible anyway since 0577 // the kdelibs refuse it. 0578 // 0579 if( ::getuid() == 0 ) { 0580 showDeviceSettingsButton = true; 0581 problems.append( K3b::SystemProblem( K3b::SystemProblem::WARNING, 0582 i18n("Running K3b as root user"), 0583 i18n("It is not recommended to run K3b under the root user account. " 0584 "This introduces unnecessary security risks."), 0585 i18n("Run K3b from a proper user account and setup the device and " 0586 "external tool permissions appropriately.") 0587 + ' ' + i18n("The latter can be done via \"Configure K3b...\".") 0588 ) ); 0589 } 0590 0591 0592 qDebug() << "(K3b::Core) System problems:"; 0593 for( QList<K3b::SystemProblem>::const_iterator it = problems.constBegin(); 0594 it != problems.constEnd(); ++it ) { 0595 const K3b::SystemProblem& p = *it; 0596 0597 switch( p.type ) { 0598 case K3b::SystemProblem::CRITICAL: 0599 qDebug() << " CRITICAL"; 0600 break; 0601 case K3b::SystemProblem::NON_CRITICAL: 0602 qDebug() << " NON_CRITICAL"; 0603 break; 0604 case K3b::SystemProblem::WARNING: 0605 qDebug() << " WARNING"; 0606 break; 0607 } 0608 qDebug() << " PROBLEM: " << p.problem << Qt::endl 0609 << " DETAILS: " << p.details << Qt::endl 0610 << " SOLUTION: " << p.solution << Qt::endl << Qt::endl; 0611 0612 } 0613 if( problems.isEmpty() ) { 0614 qDebug() << " - none - "; 0615 if( level == AlwaysNotify ) { 0616 KNotification::event( "NoProblemsFound", 0617 i18n("System configured properly"), 0618 i18n("No problems found in system configuration.") ); 0619 } 0620 } 0621 else { 0622 static K3b::SystemProblemDialog* s_openDlg = 0; 0623 if( s_openDlg ) 0624 s_openDlg->close(); 0625 K3b::SystemProblemDialog dlg( problems, showDeviceSettingsButton, showBinSettingsButton, forceCheck, parent ); 0626 s_openDlg = &dlg; 0627 dlg.exec(); 0628 s_openDlg = 0; 0629 } 0630 0631 // remember which version of K3b checked the system the last time 0632 KConfigGroup cfg( KSharedConfig::openConfig(), QStringLiteral("General Options") ); 0633 cfg.writeEntry( "Last system check version", QString(k3bcore->version()) ); 0634 } 0635 0636 void K3b::SystemProblemDialog::slotShowDeviceSettings() 0637 { 0638 k3bappcore->k3bMainWindow()->showOptionDialog( OptionDialog::Devices ); 0639 } 0640 0641 0642 void K3b::SystemProblemDialog::slotShowBinSettings() 0643 { 0644 k3bappcore->k3bMainWindow()->showOptionDialog( OptionDialog::Programs ); 0645 } 0646 0647 0648 int K3b::SystemProblemDialog::dmaActivated( K3b::Device::Device* dev ) 0649 { 0650 QString hdparm = K3b::findExe( "hdparm" ); 0651 if( hdparm.isEmpty() ) 0652 return -1; 0653 0654 KProcess p; 0655 p.setOutputChannelMode( KProcess::MergedChannels ); 0656 0657 p << hdparm << "-d" << dev->blockDeviceName(); 0658 p.start(); 0659 if( !p.waitForFinished( -1 ) ) 0660 return -1; 0661 0662 // output is something like: 0663 // 0664 // /dev/hda: 0665 // using_dma = 1 (on) 0666 // 0667 // But we ignore the on/off since it might be translated 0668 // 0669 QByteArray out = p.readAll(); 0670 if( out.contains( "1 (" ) ) 0671 return 1; 0672 else if( out.contains( "0 (" ) ) 0673 return 0; 0674 else 0675 return -1; 0676 } 0677 0678 0679 #ifdef HAVE_FSTAB_H 0680 QList<K3b::Device::Device*> K3b::SystemProblemDialog::checkForAutomounting() 0681 { 0682 QList<K3b::Device::Device *> l; 0683 ::setfsent(); 0684 0685 struct fstab * mountInfo = 0; 0686 while( (mountInfo = ::getfsent()) ) 0687 { 0688 // check if the entry corresponds to a device 0689 QString md = K3b::resolveLink( QFile::decodeName( mountInfo->fs_spec ) ); 0690 QString type = QFile::decodeName( mountInfo->fs_vfstype ); 0691 0692 if( type == "supermount" || type == "subfs" ) { 0693 // parse the device 0694 QStringList opts = QString::fromLocal8Bit(mountInfo->fs_mntops).split( ',' ); 0695 for( QStringList::const_iterator it = opts.constBegin(); it != opts.constEnd(); ++it ) { 0696 if( (*it).startsWith("dev=") ) { 0697 md = (*it).mid( 4 ); 0698 break; 0699 } 0700 } 0701 0702 if( K3b::Device::Device* dev = k3bcore->deviceManager()->findDevice( md ) ) 0703 l.append( dev ); 0704 } 0705 } // while mountInfo 0706 0707 ::endfsent(); 0708 return l; 0709 } 0710 #endif 0711 0712 0713 bool K3b::SystemProblemDialog::readCheckSystemConfig() 0714 { 0715 KConfigGroup cfgGrp(KSharedConfig::openConfig(), QStringLiteral("General Options")); 0716 0717 K3b::Version configVersion(cfgGrp.readEntry( "Last system check version", "0.1" )); 0718 if (configVersion < k3bcore->version()) 0719 cfgGrp.writeEntry("check system config", true); 0720 0721 return cfgGrp.readEntry("check system config", false); 0722 } 0723 0724 #include "moc_k3bsystemproblemdialog.cpp"