Пример #1
0
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;
}
Пример #2
0
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 {
Пример #3
0
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;
}