bool K3bIsoImager::addMkisofsParameters( bool printSize ) { // add multisession info if( !m_multiSessionInfo.isEmpty() ) { *m_process << "-cdrecord-params" << m_multiSessionInfo; if( m_device ) *m_process << "-prev-session" << m_device->blockDeviceName(); } // add the arguments *m_process << "-gui"; *m_process << "-graft-points"; if( printSize ) *m_process << "-print-size" << "-quiet"; if( !m_doc->isoOptions().volumeID().isEmpty() ) { QString s = m_doc->isoOptions().volumeID(); truncateTheHardWay(s, 32); // ensure max length *m_process << "-volid" << s; } else { emit infoMessage( i18n("No volume id specified. Using default."), WARNING ); *m_process << "-volid" << "CDROM"; } QString s = m_doc->isoOptions().volumeSetId(); truncateTheHardWay(s, 128); // ensure max length *m_process << "-volset" << s; s = m_doc->isoOptions().applicationID(); truncateTheHardWay(s, 128); // ensure max length *m_process << "-appid" << s; s = m_doc->isoOptions().publisher(); truncateTheHardWay(s, 128); // ensure max length *m_process << "-publisher" << s; s = m_doc->isoOptions().preparer(); truncateTheHardWay(s, 128); // ensure max length *m_process << "-preparer" << s; s = m_doc->isoOptions().systemId(); truncateTheHardWay(s, 32); // ensure max length *m_process << "-sysid" << s; s = m_doc->isoOptions().abstractFile(); truncateTheHardWay(s, 37); // ensure max length if ( !s.isEmpty() ) *m_process << "-abstract" << s; s = m_doc->isoOptions().copyrightFile(); truncateTheHardWay(s, 37); // ensure max length if ( !s.isEmpty() ) *m_process << "-copyright" << s; s = m_doc->isoOptions().bibliographFile(); truncateTheHardWay(s, 37); // ensure max length if ( !s.isEmpty() ) *m_process << "-biblio" << s; int volsetSize = m_doc->isoOptions().volumeSetSize(); int volsetSeqNo = m_doc->isoOptions().volumeSetNumber(); if( volsetSeqNo > volsetSize ) { kdDebug() << "(K3bIsoImager) invalid volume set sequence number: " << volsetSeqNo << " with volume set size: " << volsetSize << endl; volsetSeqNo = volsetSize; } *m_process << "-volset-size" << QString::number(volsetSize); *m_process << "-volset-seqno" << QString::number(volsetSeqNo); if( m_sortWeightFile ) { *m_process << "-sort" << m_sortWeightFile->name(); } if( m_doc->isoOptions().createRockRidge() ) { if( m_doc->isoOptions().preserveFilePermissions() ) *m_process << "-rock"; else *m_process << "-rational-rock"; if( m_rrHideFile ) *m_process << "-hide-list" << m_rrHideFile->name(); } if( m_doc->isoOptions().createJoliet() ) { *m_process << "-joliet"; if( m_doc->isoOptions().jolietLong() ) *m_process << "-joliet-long"; if( m_jolietHideFile ) *m_process << "-hide-joliet-list" << m_jolietHideFile->name(); } if( m_doc->isoOptions().doNotCacheInodes() ) *m_process << "-no-cache-inodes"; // // Check if we have files > 2 GB and enable udf in that case. // bool filesGreaterThan2Gb = false; K3bDataItem* item = m_doc->root(); while( (item = item->nextSibling()) ) { if( item->isFile() && item->size() > 2LL*1024LL*1024LL*1024LL ) { filesGreaterThan2Gb = true; break; } } if( filesGreaterThan2Gb ) { emit infoMessage( i18n("Found files bigger than 2 GB. These files will only be fully accessible if mounted with UDF."), WARNING ); // in genisoimage 1.1.3 "they" silently introduced this aweful parameter if ( d->mkisofsBin->hasFeature( "genisoimage" ) && d->mkisofsBin->version >= K3bVersion( 1, 1, 3 ) ) { *m_process << "-allow-limited-size"; } } bool udf = m_doc->isoOptions().createUdf(); if( !udf && filesGreaterThan2Gb ) { emit infoMessage( i18n("Enabling UDF extension."), INFO ); udf = true; } if( udf ) *m_process << "-udf"; if( m_doc->isoOptions().ISOuntranslatedFilenames() ) { *m_process << "-untranslated-filenames"; } else { if( m_doc->isoOptions().ISOallowPeriodAtBegin() ) *m_process << "-allow-leading-dots"; if( m_doc->isoOptions().ISOallow31charFilenames() ) *m_process << "-full-iso9660-filenames"; if( m_doc->isoOptions().ISOomitVersionNumbers() && !m_doc->isoOptions().ISOmaxFilenameLength() ) *m_process << "-omit-version-number"; if( m_doc->isoOptions().ISOrelaxedFilenames() ) *m_process << "-relaxed-filenames"; if( m_doc->isoOptions().ISOallowLowercase() ) *m_process << "-allow-lowercase"; if( m_doc->isoOptions().ISOnoIsoTranslate() ) *m_process << "-no-iso-translate"; if( m_doc->isoOptions().ISOallowMultiDot() ) *m_process << "-allow-multidot"; if( m_doc->isoOptions().ISOomitTrailingPeriod() ) *m_process << "-omit-period"; } if( m_doc->isoOptions().ISOmaxFilenameLength() ) *m_process << "-max-iso9660-filenames"; if( m_noDeepDirectoryRelocation ) *m_process << "-disable-deep-relocation"; // We do our own following // if( m_doc->isoOptions().followSymbolicLinks() || !m_doc->isoOptions().createRockRidge() ) // *m_process << "-follow-links"; if( m_doc->isoOptions().createTRANS_TBL() ) *m_process << "-translation-table"; if( m_doc->isoOptions().hideTRANS_TBL() ) *m_process << "-hide-joliet-trans-tbl"; *m_process << "-iso-level" << QString::number(m_doc->isoOptions().ISOLevel()); if( m_doc->isoOptions().forceInputCharset() ) *m_process << "-input-charset" << m_doc->isoOptions().inputCharset(); *m_process << "-path-list" << QFile::encodeName(m_pathSpecFile->name()); // boot stuff if( !m_doc->bootImages().isEmpty() ) { bool first = true; for( QPtrListIterator<K3bBootItem> it( m_doc->bootImages() ); *it; ++it ) { if( !first ) *m_process << "-eltorito-alt-boot"; K3bBootItem* bootItem = *it; *m_process << "-eltorito-boot"; *m_process << bootItem->writtenPath(); if( bootItem->imageType() == K3bBootItem::HARDDISK ) { *m_process << "-hard-disk-boot"; } else if( bootItem->imageType() == K3bBootItem::NONE ) { *m_process << "-no-emul-boot"; if( bootItem->loadSegment() > 0 ) *m_process << "-boot-load-seg" << QString::number(bootItem->loadSegment()); if( bootItem->loadSize() > 0 ) *m_process << "-boot-load-size" << QString::number(bootItem->loadSize()); } if( bootItem->imageType() != K3bBootItem::NONE && bootItem->noBoot() ) *m_process << "-no-boot"; if( bootItem->bootInfoTable() ) *m_process << "-boot-info-table"; first = false; } *m_process << "-eltorito-catalog" << m_doc->bootCataloge()->writtenPath(); } // additional parameters from config const QStringList& params = k3bcore->externalBinManager()->binObject( "mkisofs" )->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *m_process << *it; return true; }
void K3bDvdFormattingJob::startFormatting( const K3bDevice::DiskInfo& diskInfo ) { // // Now check the media type: // if DVD-RW: use d->mode // emit warning if formatting is full and stuff // // in overwrite mode: emit info that progress might stop before 100% since formatting will continue // in the background once the media gets rewritten (only DVD+RW?) // // emit info about what kind of media has been found if( !(diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_RW| K3bDevice::MEDIA_DVD_RW_SEQ| K3bDevice::MEDIA_DVD_RW_OVWR| K3bDevice::MEDIA_DVD_PLUS_RW)) ) { emit infoMessage( i18n("No rewritable DVD media found. Unable to format."), ERROR ); d->running = false; jobFinished(false); return; } bool format = true; // do we need to format bool blank = false; // blank is for DVD-RW sequential incremental // DVD-RW restricted overwrite and DVD+RW uses the force option (or no option at all) // // DVD+RW is quite easy to handle. There is only one possible mode and it is always recommended to not // format it more than once but to overwrite it once it is formatted // Once the initial formatting has been done it's always "appendable" (or "complete"???) // if( diskInfo.mediaType() == K3bDevice::MEDIA_DVD_PLUS_RW ) { emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), INFO ); // mode is ignored if( diskInfo.empty() ) { // // The DVD+RW is blank and needs to be initially formatted // blank = false; } else { emit infoMessage( i18n("No need to format %1 media more than once.") .arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), INFO ); emit infoMessage( i18n("It may simply be overwritten."), INFO ); if( d->force ) { emit infoMessage( i18n("Forcing formatting anyway."), INFO ); emit infoMessage( i18n("It is not recommended to force formatting of DVD+RW media."), INFO ); emit infoMessage( i18n("Already after 10-20 reformats the media might be unusable."), INFO ); blank = false; } else { format = false; } } if( format ) emit newSubTask( i18n("Formatting DVD+RW") ); } // // DVD-RW has two modes: incremental sequential (the default which is also needed for DAO writing) // and restricted overwrite which compares to the DVD+RW mode. // else { // MEDIA_DVD_RW emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_RW)), INFO ); if( diskInfo.currentProfile() != K3bDevice::MEDIA_UNKNOWN ) { emit infoMessage( i18n("Formatted in %1 mode.").arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); // // Is it possible to have an empty DVD-RW in restricted overwrite mode???? I don't think so. // if( diskInfo.empty() && (d->mode == K3b::WRITING_MODE_AUTO || (d->mode == K3b::WRITING_MODE_INCR_SEQ && diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ) || (d->mode == K3b::WRITING_MODE_RES_OVWR && diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR) ) ) { emit infoMessage( i18n("Media is already empty."), INFO ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), INFO ); else format = false; } else if( diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR && d->mode != K3b::WRITING_MODE_INCR_SEQ ) { emit infoMessage( i18n("No need to format %1 media more than once.") .arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); emit infoMessage( i18n("It may simply be overwritten."), INFO ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), INFO ); else format = false; } if( format ) { if( d->mode == K3b::WRITING_MODE_AUTO ) { // just format in the same mode as the media is currently formatted blank = (diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ); } else { blank = (d->mode == K3b::WRITING_MODE_INCR_SEQ); } emit newSubTask( i18n("Formatting" " DVD-RW in %1 mode.").arg(K3bDevice::mediaTypeString( blank ? K3bDevice::MEDIA_DVD_RW_SEQ : K3bDevice::MEDIA_DVD_RW_OVWR )) ); } } else { emit infoMessage( i18n("Unable to determine the current formatting state of the DVD-RW media."), ERROR ); d->running = false; jobFinished(false); return; } } if( format ) { delete d->process; d->process = new K3bProcess(); d->process->setRunPrivileged(true); // d->process->setSuppressEmptyLines(false); connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStderrLine(const QString&)) ); connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessFinished(KProcess*)) ); d->dvdFormatBin = k3bcore->externalBinManager()->binObject( "dvd+rw-format" ); if( !d->dvdFormatBin ) { emit infoMessage( i18n("Could not find %1 executable.").arg("dvd+rw-format"), ERROR ); d->running = false; jobFinished(false); return; } if( !d->dvdFormatBin->copyright.isEmpty() ) emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg(d->dvdFormatBin->name()).arg(d->dvdFormatBin->version).arg(d->dvdFormatBin->copyright), INFO ); *d->process << d->dvdFormatBin; if( d->dvdFormatBin->version >= K3bVersion( 4, 6 ) ) *d->process << "-gui"; QString p; if( blank ) p = "-blank"; else p = "-force"; if( !d->quick ) p += "=full"; *d->process << p; *d->process << d->device->blockDeviceName(); // additional user parameters from config const QStringList& params = d->dvdFormatBin->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; kdDebug() << "***** dvd+rw-format parameters:\n"; const QValueList<QCString>& args = d->process->args(); QString s; for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << endl << flush; emit debuggingOutput( "dvd+rw-format command:", s ); if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { // something went wrong when starting the program // it "should" be the executable kdDebug() << "(K3bDvdFormattingJob) could not start " << d->dvdFormatBin->path << endl; emit infoMessage( i18n("Could not start %1.").arg(d->dvdFormatBin->name()), K3bJob::ERROR ); d->running = false; jobFinished(false); } else { emit newTask( i18n("Formatting") ); } } else {
bool K3bGrowisofsWriter::prepareProcess() { d->growisofsBin = k3bcore->externalBinManager()->binObject( "growisofs" ); if( !d->growisofsBin ) { emit infoMessage( i18n("Could not find %1 executable.").arg("growisofs"), ERROR ); return false; } if( d->growisofsBin->version < K3bVersion( 5, 10 ) ) { emit infoMessage( i18n("Growisofs version %1 is too old. " "K3b needs at least version 5.10.").arg(d->growisofsBin->version), ERROR ); return false; } emit debuggingOutput( "Used versions", "growisofs: " + d->growisofsBin->version ); if( !d->growisofsBin->copyright.isEmpty() ) emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg("growisofs") .arg(d->growisofsBin->version).arg(d->growisofsBin->copyright), INFO ); // // The growisofs bin is ready. Now we add the parameters // delete d->process; d->process = new K3bProcess(); d->process->setRunPrivileged(true); // d->process->setPriority( KProcess::PrioHighest ); d->process->setSplitStdout(true); d->process->setRawStdin(true); connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); // // growisofs < 5.20 wants the tracksize to be a multiple of 16 (1 ECC block: 16*2048 bytes) // we simply pad ourselves. // // But since the writer itself properly pads or writes a longer lead-out we don't really need // to write zeros. We just tell growisofs to reserve a multiple of 16 blocks. // This is only releveant in DAO mode anyway. // // FIXME: seems as we also need this for double layer writing. Better make it the default and // actually write the pad bytes. The only possibility I see right now is to add a padding option // to the pipebuffer. int trackSizePadding = 0; if( d->trackSize > 0 && d->growisofsBin->version < K3bVersion( 5, 20 ) ) { if( d->trackSize % 16 ) { trackSizePadding = (16 - d->trackSize%16); kdDebug() << "(K3bGrowisofsWriter) need to pad " << trackSizePadding << " blocks." << endl; } } *d->process << d->growisofsBin; // set this var to true to enable the ringbuffer d->usingRingBuffer = ( d->growisofsBin->version < K3bVersion( 6, 0 ) ); QString s = burnDevice()->blockDeviceName() + "="; if( d->usingRingBuffer || d->image.isEmpty() ) { // we always read from stdin since the ringbuffer does the actual reading from the source s += "/dev/fd/0"; } else s += d->image; if( d->multiSession && !d->multiSessionInfo.isEmpty() ) *d->process << "-C" << d->multiSessionInfo; if( d->multiSession ) *d->process << "-M"; else *d->process << "-Z"; *d->process << s; if( !d->image.isEmpty() && d->usingRingBuffer ) { d->inputFile.setName( d->image ); d->trackSize = (K3b::filesize( d->image ) + 1024) / 2048; if( !d->inputFile.open( IO_ReadOnly ) ) { emit infoMessage( i18n("Could not open file %1.").arg(d->image), ERROR ); return false; } } // now we use the force (luke ;) do not reload the dvd, K3b does that. *d->process << "-use-the-force-luke=notray"; // we check for existing filesystems ourselves, so we always force the overwrite... *d->process << "-use-the-force-luke=tty"; bool dvdCompat = d->closeDvd; // DL writing with forced layer break if( d->layerBreak > 0 ) { *d->process << "-use-the-force-luke=break:" + QString::number(d->layerBreak); dvdCompat = true; } // the tracksize parameter takes priority over the dao:tracksize parameter since growisofs 5.18 else if( d->growisofsBin->version > K3bVersion( 5, 17 ) && d->trackSize > 0 ) *d->process << "-use-the-force-luke=tracksize:" + QString::number(d->trackSize + trackSizePadding); if( simulate() ) *d->process << "-use-the-force-luke=dummy"; if( d->writingMode == K3b::DAO ) { dvdCompat = true; if( d->growisofsBin->version >= K3bVersion( 5, 15 ) && d->trackSize > 0 ) *d->process << "-use-the-force-luke=dao:" + QString::number(d->trackSize + trackSizePadding); else *d->process << "-use-the-force-luke=dao"; d->gh->reset( burnDevice(), true ); } else d->gh->reset( burnDevice(), false ); // // Never use the -dvd-compat parameter with DVD+RW media // because the only thing it does is creating problems. // Normally this should be done in growisofs // int mediaType = burnDevice()->mediaType(); if( dvdCompat && mediaType != K3bDevice::MEDIA_DVD_PLUS_RW && mediaType != K3bDevice::MEDIA_DVD_RW_OVWR ) *d->process << "-dvd-compat"; // // Some DVD writers do not allow changing the writing speed so we allow // the user to ignore the speed setting // int speed = burnSpeed(); if( speed >= 0 ) { if( speed == 0 ) { // try to determine the writeSpeed // if it fails determineOptimalWriteSpeed() will return 0 and // the choice is left to growisofs which means that the choice is // really left to the drive since growisofs does not change the speed // if no option is given speed = burnDevice()->determineMaximalWriteSpeed(); } // speed may be a float number. example: DVD+R(W): 2.4x if( speed != 0 ) *d->process << QString("-speed=%1").arg( speed%1385 > 0 ? QString::number( (float)speed/1385.0, 'f', 1 ) : QString::number( speed/1385 ) ); } if( k3bcore->globalSettings()->overburn() ) *d->process << "-overburn"; if( !d->usingRingBuffer && d->growisofsBin->version >= K3bVersion( 6, 0 ) ) { bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); int bufSize = ( manualBufferSize ? k3bcore->globalSettings()->bufferSize() : 32 ); *d->process << QString("-use-the-force-luke=bufsize:%1m").arg(bufSize); } // additional user parameters from config const QStringList& params = d->growisofsBin->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; emit debuggingOutput( "Burned media", K3bDevice::mediaTypeString(mediaType) ); return true; }