Exemple #1
0
  bool countFiles( const QStringList& l, const QString& dir ) {
    for( QStringList::const_iterator it = l.begin();
	 it != l.end(); ++it ) {

      if( m_canceled )
	return false;

      k3b_struct_stat s;
      if( k3b_lstat( QFile::encodeName( dir + *it ), &s ) )
	return false;	

      if( S_ISLNK( s.st_mode ) ) {
	++totalSymlinks;
	if( followSymlinks ) {
	  if( k3b_stat( QFile::encodeName( dir + *it ), &s ) )
	    return false;	
	}
      }

      if( S_ISDIR( s.st_mode ) ) {
	++totalDirs;
	if( !countDir( dir + *it + '/' ) )
	  return false;
      }
      else if( !S_ISLNK( s.st_mode ) ) {
	++totalFiles;
	totalSize += (KIO::filesize_t)s.st_size;
      }
    }

    return true;
  }
Exemple #2
0
QString K3bIsoImager::dummyDir( K3bDirItem* dir )
{
  //
  // since we use virtual folders in order to have folders with different weight factors and different
  // permissions we create different dummy dirs to be passed to mkisofs
  //

  QDir _appDir( locateLocal( "appdata", "temp/" ) );

  //
  // create a unique isoimager session id
  // This might become important in case we will allow multiple instances of the isoimager
  // to run at the same time.
  //
  QString jobId = qApp->sessionId() + "_" + QString::number( m_sessionNumber );

  if( !_appDir.cd( jobId ) ) {
    _appDir.mkdir( jobId );
    _appDir.cd( jobId );
  }

  QString name( "dummydir_" );
  name += QString::number( dir->sortWeight() );

  bool perm = false;
  k3b_struct_stat statBuf;
  if( !dir->localPath().isEmpty() ) {
    // permissions
    if( k3b_stat( QFile::encodeName(dir->localPath()), &statBuf ) == 0 ) {
      name += "_";
      name += QString::number( statBuf.st_uid );
      name += "_";
      name += QString::number( statBuf.st_gid );
      name += "_";
      name += QString::number( statBuf.st_mode );
      name += "_";
      name += QString::number( statBuf.st_mtime );

      perm = true;
    }
  }


  if( !_appDir.cd( name ) ) {

    kdDebug() << "(K3bIsoImager) creating dummy dir: " << _appDir.absPath() << "/" << name << endl;

    _appDir.mkdir( name );
    _appDir.cd( name );

    if( perm ) {
      ::chmod( QFile::encodeName( _appDir.absPath() ), statBuf.st_mode );
      ::chown( QFile::encodeName( _appDir.absPath() ), statBuf.st_uid, statBuf.st_gid );
      struct utimbuf tb;
      tb.actime = tb.modtime = statBuf.st_mtime;
      ::utime( QFile::encodeName( _appDir.absPath() ), &tb );
    }
  }

  return _appDir.absPath() + "/";
}
Exemple #3
0
void K3bDataUrlAddingDialog::slotAddUrls()
{
  if( m_bCanceled )
    return;

  // add next url
  KURL url = m_urlQueue.first().first;
  K3bDirItem* dir = m_urlQueue.first().second;
  m_urlQueue.remove( m_urlQueue.begin() );
  //
  // HINT:
  // we only use QFileInfo::absFilePath() and QFileInfo::isHidden()
  // both do not cause QFileInfo to stat, thus no speed improvement
  // can come from removing QFileInfo usage here.
  //
  QFileInfo info(url.path());
  QString absFilePath( info.absFilePath() );
  QString resolved( absFilePath );

  bool valid = true;
  k3b_struct_stat statBuf, resolvedStatBuf;
  bool isSymLink = false;
  bool isDir = false;
  bool isFile = false;

  ++m_filesHandled;

#if 0
  m_infoLabel->setText( url.path() );
  if( m_totalFiles == 0 )
    m_counterLabel->setText( QString("(%1)").arg(m_filesHandled) );
  else
    m_counterLabel->setText( QString("(%1/%2)").arg(m_filesHandled).arg(m_totalFiles) );
#endif

  //
  // 1. Check if we want and can add the url
  //

  if( !url.isLocalFile() ) {
    valid = false;
    m_nonLocalFiles.append( url.path() );
  }

  else if( k3b_lstat( QFile::encodeName(absFilePath), &statBuf ) != 0 ) {
    valid = false;
    m_notFoundFiles.append( url.path() );
  }

  else if( !m_encodingConverter->encodedLocally( QFile::encodeName( url.path() ) ) ) {
    valid = false;
    m_invalidFilenameEncodingFiles.append( url.path() );
  }

  else {
    isSymLink = S_ISLNK(statBuf.st_mode);
    isFile = S_ISREG(statBuf.st_mode);
    isDir = S_ISDIR(statBuf.st_mode);

    // symlinks are always readable and can always be added to a project
    // but we need to know if the symlink points to a directory
    if( isSymLink ) {
      resolved = K3b::resolveLink( absFilePath );
      k3b_stat( QFile::encodeName(resolved), &resolvedStatBuf );
      isDir = S_ISDIR(resolvedStatBuf.st_mode);
    }

    else {
      if( ::access( QFile::encodeName( absFilePath ), R_OK ) != 0 ) {
	valid = false;
	m_unreadableFiles.append( url.path() );
      }
      else if( isFile && (unsigned long long)statBuf.st_size >= 0xFFFFFFFFULL ) {
          if ( !k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "no-4gb-limit" ) ) {
              valid = false;
              m_tooBigFiles.append( url.path() );
          }
      }
    }

    // FIXME: if we do not add hidden dirs the progress gets messed up!

    //
    // check for hidden and system files
    //
    if( valid ) {
      if( info.isHidden() && !addHiddenFiles() )
	valid = false;
      if( S_ISCHR(statBuf.st_mode) ||
	  S_ISBLK(statBuf.st_mode) ||
	  S_ISFIFO(statBuf.st_mode) ||
	  S_ISSOCK(statBuf.st_mode) )
	if( !addSystemFiles() )
	  valid = false;
      if( isSymLink )
	if( S_ISCHR(resolvedStatBuf.st_mode) ||
	    S_ISBLK(resolvedStatBuf.st_mode) ||
	    S_ISFIFO(resolvedStatBuf.st_mode) ||
	    S_ISSOCK(resolvedStatBuf.st_mode) )
	  if( !addSystemFiles() )
	    valid = false;
    }
  }


  //
  // 2. Handle the url
  //

  QString newName = url.fileName();

  // filenames cannot end in backslashes (mkisofs problem. See comments in k3bisoimager.cpp (escapeGraftPoint()))
  bool bsAtEnd = false;
  while( newName[newName.length()-1] == '\\' ) {
    newName.truncate( newName.length()-1 );
    bsAtEnd = true;
  }
  if( bsAtEnd )
    m_mkisofsLimitationRenamedFiles.append( url.path() + " -> " + newName );

  // backup dummy name
  if( newName.isEmpty() )
    newName = "1";

  K3bDirItem* newDirItem = 0;

  //
  // The source is valid. Now check if the project already contains a file with that name
  // and if so handle it properly
  //
  if( valid ) {
    if( K3bDataItem* oldItem = dir->find( newName ) ) {
      //
      // reuse an existing dir
      //
      if( oldItem->isDir() && isDir )
	newDirItem = dynamic_cast<K3bDirItem*>(oldItem);

      //
      // we cannot replace files in the old session with dirs and vice versa (I think)
      // files are handled in K3bFileItem constructor and dirs handled above
      //
      else if( oldItem->isFromOldSession() &&
	       isDir != oldItem->isDir() ) {
	if( !getNewName( newName, dir, newName ) )
	  valid = false;
      }

      else if( m_bExistingItemsIgnoreAll )
	valid = false;

      else if( oldItem->localPath() == resolved ) {
	//
	// Just ignore if the same file is added again
	//
	valid = false;
      }

      else if( m_bExistingItemsReplaceAll ) {
	// if we replace an item from an old session the K3bFileItem constructor takes care
	// of replacing the item
	if( !oldItem->isFromOldSession() )
	  delete oldItem;
      }

      //
      // Let the user choose
      //
      else {
	switch( K3bMultiChoiceDialog::choose( i18n("File already exists"),
					      i18n("<p>File <em>%1</em> already exists in "
						   "project folder <em>%2</em>.")
					      .arg(newName)
					      .arg('/' + dir->k3bPath()),
					      QMessageBox::Warning,
					      this,
					      0,
					      6,
					      KGuiItem( i18n("Replace"),
							QString::null,
							i18n("Replace the existing file") ),
					      KGuiItem( i18n("Replace All"),
							QString::null,
							i18n("Always replace existing files") ),
					      KGuiItem( i18n("Ignore"),
							QString::null,
							i18n("Keep the existing file") ),
					      KGuiItem( i18n("Ignore All"),
							QString::null,
							i18n("Always keep the existing file") ),
					      KGuiItem( i18n("Rename"),
							QString::null,
							i18n("Rename the new file") ),
					      KStdGuiItem::cancel() ) ) {
	case 2: // replace all
	  m_bExistingItemsReplaceAll = true;
	  // fallthrough
	case 1: // replace
	  // if we replace an item from an old session the K3bFileItem constructor takes care
	  // of replacing the item
	  if( !oldItem->isFromOldSession() )
	    delete oldItem;
	  break;
	case 4: // ignore all
	  m_bExistingItemsIgnoreAll = true;
	  // fallthrough
	case 3: // ignore
	  valid = false;
	  break;
	case 5: // rename
	  if( !getNewName( newName, dir, newName ) )
	    valid = false;
	  break;
	case 6: // cancel
	  slotCancel();
	  return;
	}
      }
    }
  }


  //
  // One more thing to warn the user about: We cannot follow links to folders since that
  // would change the doc. So we simply ask the user what to do with a link to a folder
  //
  if( valid ) {
    // let's see if this link starts a loop
    // that means if it points to some folder above this one
    // if so we cannot follow it anyway
    if( isDir && isSymLink && !absFilePath.startsWith( resolved ) ) {
      bool followLink = dir->doc()->isoOptions().followSymbolicLinks() || m_bFolderLinksFollowAll;
      if( !followLink && !m_bFolderLinksAddAll ) {
	switch( K3bMultiChoiceDialog::choose( i18n("Adding link to folder"),
					      i18n("<p>'%1' is a symbolic link to folder '%2'."
						   "<p>If you intend to make K3b follow symbolic links you should consider letting K3b do this now "
						   "since K3b will not be able to do so afterwards because symbolic links to folders inside a "
						   "K3b project cannot be resolved."
						   "<p><b>If you do not intend to enable the option <em>follow symbolic links</em> you may safely "
						   "ignore this warning and choose to add the link to the project.</b>")
					      .arg(absFilePath)
					      .arg(resolved ),
					      QMessageBox::Warning,
					      this,
					      0,
					      5,
					      i18n("Follow link now"),
					      i18n("Always follow links"),
					      i18n("Add link to project"),
					      i18n("Always add links"),
					      KStdGuiItem::cancel() ) ) {
	case 2:
	  m_bFolderLinksFollowAll = true;
	case 1:
	  followLink = true;
	  break;
	case 4:
	  m_bFolderLinksAddAll = true;
	case 3:
	  followLink = false;
	  break;
	case 5:
	  slotCancel();
	  return;
	}
      }

      if( followLink ) {
	absFilePath = resolved;
	isSymLink = false;

	// count the files in the followed dir
	if( m_dirSizeJob->active() )
	  m_dirSizeQueue.append( KURL::fromPathOrURL(absFilePath) );
	else {
	  m_progressWidget->setTotalSteps( 0 );
	  m_dirSizeJob->setUrls( KURL::fromPathOrURL(absFilePath) );
	  m_dirSizeJob->start();
	}
      }
    }
  }


  //
  // Project valid also (we overwrite or renamed)
  // now create the new item
  //
  if( valid ) {
    //
    // Set the volume id from the first added url
    // only if the doc was not changed yet
    //
    if( m_urls.count() == 1 &&
	!dir->doc()->isModified() &&
	!dir->doc()->isSaved() ) {
      dir->doc()->setVolumeID( K3b::removeFilenameExtension( newName ) );
    }

    if( isDir && !isSymLink ) {
      if( !newDirItem ) { // maybe we reuse an already existing dir
	newDirItem = new K3bDirItem( newName , dir->doc(), dir );
	newDirItem->setLocalPath( url.path() ); // HACK: see k3bdiritem.h
      }

      QDir newDir( absFilePath );
      int dirFilter = QDir::All|QDir::Hidden|QDir::System;

      QStringList dlist = newDir.entryList( dirFilter );
      const QString& dot = KGlobal::staticQString( "." );
      const QString& dotdot = KGlobal::staticQString( ".." );
      dlist.remove( dot );
      dlist.remove( dotdot );

      for( QStringList::Iterator it = dlist.begin(); it != dlist.end(); ++it ) {
	m_urlQueue.append( qMakePair( KURL::fromPathOrURL(absFilePath + '/' + *it), newDirItem ) );
      }
    }
    else {
      (void)new K3bFileItem( &statBuf, &resolvedStatBuf, url.path(), dir->doc(), dir, newName );
    }
  }

  if( m_urlQueue.isEmpty() ) {
    m_dirSizeJob->cancel();
    m_progressWidget->setProgress( 100 );
    accept();
  }
  else {
    updateProgress();
    QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
  }
}
Exemple #4
0
bool K3b::Iso9660::open()
{
    if( d->isOpen )
        return true;

    if( !d->backend ) {
        // create a backend

        if( !m_filename.isEmpty() )
            d->backend = new K3b::Iso9660FileBackend( m_filename );

        else if( d->fd > 0 )
            d->backend = new K3b::Iso9660FileBackend( d->fd );

        else if( d->cdDevice ) {
            // now check if we have a scrambled video dvd
            if( d->cdDevice->copyrightProtectionSystemType() == K3b::Device::COPYRIGHT_PROTECTION_CSS ) {

                qDebug() << "(K3b::Iso9660) found encrypted dvd. using libdvdcss.";

                // open the libdvdcss stuff
                d->backend = new K3b::Iso9660LibDvdCssBackend( d->cdDevice );
                if( !d->backend->open() ) {
                    // fallback to devicebackend
                    delete d->backend;
                    d->backend = new K3b::Iso9660DeviceBackend( d->cdDevice );
                }
            }
            else
                d->backend = new K3b::Iso9660DeviceBackend( d->cdDevice );
        }
        else
            return false;
    }

    d->isOpen = d->backend->open();
    if( !d->isOpen )
        return false;

    iso_vol_desc *desc;
    QString path,tmp,uid,gid;
    k3b_struct_stat buf;
    int access,c_i,c_j;
    struct el_torito_boot_descriptor* bootdesc;

    // TODO implement win32 support

    /* We'll use the permission and user/group of the 'host' file except
     * in Rock Ridge, where the permissions are stored on the file system
     */
    if ( k3b_stat( QFile::encodeName(m_filename), &buf ) < 0 ) {
        /* defaults, if stat fails */
        memset(&buf,0,sizeof(k3b_struct_stat));
        buf.st_mode=0777;
    }
    uid.setNum(buf.st_uid);
    gid.setNum(buf.st_gid);
    access = buf.st_mode & ~S_IFMT;


    int c_b=1;
    c_i=1;c_j=1;

    desc = ReadISO9660( &K3b::Iso9660::read_callback, d->startSector, this );

    if (!desc) {
        qDebug() << "K3b::Iso9660::openArchive no volume descriptors";
        close();
        return false;
    }

    while (desc) {

        m_rr = false;

        switch (isonum_711(desc->data.type)) {
        case ISO_VD_BOOT:

            bootdesc=(struct el_torito_boot_descriptor*) &(desc->data);
            if( !memcmp( EL_TORITO_ID, bootdesc->system_id, ISODCL(8,39) ) ) {
                path="El Torito Boot";
                if( c_b > 1 )
                    path += " (" + QString::number(c_b) + ')';

                dirent = new K3b::Iso9660Directory( this, path, path, access | S_IFDIR,
                                                  buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString() );
                d->elToritoDirs.append( dirent );

                addBoot(bootdesc);
                c_b++;
            }
            break;

        case ISO_VD_PRIMARY:
            createSimplePrimaryDesc( (struct iso_primary_descriptor*)&desc->data );
            // fall through
        case ISO_VD_SUPPLEMENTARY:
        {
            struct iso_primary_descriptor* primaryDesc = (struct iso_primary_descriptor*)&desc->data;
            struct iso_directory_record* idr = (struct iso_directory_record*)&primaryDesc->root_directory_record;

            m_joliet = JolietLevel(&desc->data);

            // skip joliet in plain iso mode
            if( m_joliet && plainIso9660() )
                break;

            if (m_joliet) {
                path = "Joliet level " + QString::number(m_joliet);
                if( c_j > 1 )
                    path += " (" + QString::number(c_j) + ')';
            }
            else {
                path = QString::fromLocal8Bit( primaryDesc->volume_id, 32 );
                if( c_i > 1 )
                    path += " (" + QString::number(c_i) + ')';
            }

            dirent = new K3b::Iso9660Directory( this, path, path, access | S_IFDIR,
                                              buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString() );

            // expand the root entry
            ProcessDir( &K3b::Iso9660::read_callback, isonum_733(idr->extent),isonum_733(idr->size),&K3b::Iso9660::isofs_callback,this);

            if (m_joliet)
                c_j++;
            else
                c_i++;

            if( m_joliet )
                d->jolietDirs.append( dirent );
            else {
                if( m_rr )
                    d->rrDirs.append( dirent );
                d->isoDirs.append( dirent );
            }

            break;
        }
        }
        desc = desc->next;
    }

    FreeISO9660(desc);

    return true;
}