Diffstat (limited to 'noncore/settings/packagemanager/oipkg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/settings/packagemanager/oipkg.cpp | 208 |
1 files changed, 191 insertions, 17 deletions
diff --git a/noncore/settings/packagemanager/oipkg.cpp b/noncore/settings/packagemanager/oipkg.cpp index a66bd51..f2d7e39 100644 --- a/noncore/settings/packagemanager/oipkg.cpp +++ b/noncore/settings/packagemanager/oipkg.cpp | |||
@@ -31,39 +31,42 @@ _;:, .> :=|. This program is free software; you can | |||
31 | 31 | ||
32 | #include "oipkg.h" | 32 | #include "oipkg.h" |
33 | 33 | ||
34 | #include <qdir.h> | 34 | #include <qdir.h> |
35 | #include <qfile.h> | 35 | #include <qfile.h> |
36 | #include <qtextstream.h> | 36 | #include <qtextstream.h> |
37 | 37 | ||
38 | #include <stdlib.h> | 38 | #include <stdlib.h> |
39 | #include <unistd.h> | ||
39 | 40 | ||
40 | const QString IPKG_CONF = "/etc/ipkg.conf"; // Fully-qualified name of Ipkg primary configuration file | 41 | const QString IPKG_CONF = "/etc/ipkg.conf"; // Fully-qualified name of Ipkg primary configuration file |
41 | const QString IPKG_CONF_DIR = "/etc/ipkg"; // Directory of secondary Ipkg configuration files | 42 | const QString IPKG_CONF_DIR = "/etc/ipkg"; // Directory of secondary Ipkg configuration files |
42 | const QString IPKG_PKG_PATH = "/usr/lib/ipkg/lists"; // Directory containing server package lists | 43 | const QString IPKG_PKG_PATH = "/usr/lib/ipkg/lists"; // Directory containing server package lists |
43 | const QString IPKG_STATUS_PATH = "usr/lib/ipkg/status"; // Destination status file location | 44 | const QString IPKG_STATUS_PATH = "usr/lib/ipkg/status"; // Destination status file location |
45 | const QString IPKG_INFO_PATH = "usr/lib/ipkg/info"; // Package file lists location | ||
44 | 46 | ||
45 | OIpkg *oipkg; | 47 | OIpkg *oipkg; |
46 | 48 | ||
47 | // Ipkg callback functions | 49 | // Ipkg callback functions |
48 | 50 | ||
49 | int fsignalIpkgMessage( ipkg_conf_t *conf, message_level_t level, char *msg ) | 51 | int fsignalIpkgMessage( ipkg_conf_t *conf, message_level_t level, char *msg ) |
50 | { | 52 | { |
53 | // Display message only if it is below the message level threshold | ||
51 | if ( conf && ( conf->verbosity < level ) ) | 54 | if ( conf && ( conf->verbosity < level ) ) |
52 | return 0; | 55 | return 0; |
53 | else | 56 | else |
54 | oipkg->ipkgMessage( msg ); | 57 | oipkg->ipkgMessage( msg ); |
55 | 58 | ||
56 | return 0; | 59 | return 0; |
57 | } | 60 | } |
58 | 61 | ||
59 | char *fIpkgResponse( char */*question*/ ) | 62 | char *fIpkgResponse( char */*question*/ ) |
60 | { | 63 | { |
61 | return 0x0; | 64 | return 0l; |
62 | } | 65 | } |
63 | 66 | ||
64 | int fIpkgStatus( char */*name*/, int /*status*/, char *desc, void */*userdata*/ ) | 67 | int fIpkgStatus( char */*name*/, int /*status*/, char *desc, void */*userdata*/ ) |
65 | { | 68 | { |
66 | oipkg->ipkgStatus( desc ); | 69 | oipkg->ipkgStatus( desc ); |
67 | return 0; | 70 | return 0; |
68 | } | 71 | } |
69 | 72 | ||
@@ -76,16 +79,17 @@ int fIpkgFiles( char */*name*/, char *desc, char */*version*/, pkg_state_status_ | |||
76 | 79 | ||
77 | OIpkg::OIpkg( Config *config, QObject *parent, const char *name ) | 80 | OIpkg::OIpkg( Config *config, QObject *parent, const char *name ) |
78 | : QObject( parent, name ) | 81 | : QObject( parent, name ) |
79 | , m_config( config ) | 82 | , m_config( config ) |
80 | , m_confInfo( NULL ) | 83 | , m_confInfo( NULL ) |
81 | , m_ipkgExecOptions( 0 ) | 84 | , m_ipkgExecOptions( 0 ) |
82 | , m_ipkgExecVerbosity( 1 ) | 85 | , m_ipkgExecVerbosity( 1 ) |
83 | { | 86 | { |
87 | // Keep pointer to self for the Ipkg callback functions | ||
84 | oipkg = this; | 88 | oipkg = this; |
85 | 89 | ||
86 | // Initialize libipkg | 90 | // Initialize libipkg |
87 | ipkg_init( &fsignalIpkgMessage, &fIpkgResponse, &m_ipkgArgs ); | 91 | ipkg_init( &fsignalIpkgMessage, &fIpkgResponse, &m_ipkgArgs ); |
88 | 92 | ||
89 | // Default ipkg run-time arguments | 93 | // Default ipkg run-time arguments |
90 | m_ipkgArgs.noaction = false; | 94 | m_ipkgArgs.noaction = false; |
91 | m_ipkgArgs.force_defaults = true; | 95 | m_ipkgArgs.force_defaults = true; |
@@ -357,16 +361,34 @@ OPackageList *OIpkg::installedPackages( const QString &destName, const QString & | |||
357 | line = t.readLine(); | 361 | line = t.readLine(); |
358 | } | 362 | } |
359 | 363 | ||
360 | f.close(); | 364 | f.close(); |
361 | 365 | ||
362 | return pl; | 366 | return pl; |
363 | } | 367 | } |
364 | 368 | ||
369 | OConfItem *OIpkg::findConfItem( OConfItem::Type type, const QString &name ) | ||
370 | { | ||
371 | // Find configuration item in list | ||
372 | OConfItemListIterator configIt( *m_confInfo ); | ||
373 | OConfItem *config = 0l; | ||
374 | for ( ; configIt.current(); ++configIt ) | ||
375 | { | ||
376 | config = configIt.current(); | ||
377 | if ( config->type() == type && config->name() == name ) | ||
378 | break; | ||
379 | } | ||
380 | |||
381 | if ( config && config->type() == type && config->name() == name ) | ||
382 | return config; | ||
383 | |||
384 | return 0l; | ||
385 | } | ||
386 | |||
365 | bool OIpkg::executeCommand( OPackage::Command command, const QStringList ¶meters, const QString &destination, | 387 | bool OIpkg::executeCommand( OPackage::Command command, const QStringList ¶meters, const QString &destination, |
366 | const QObject *receiver, const char *slotOutput, bool rawOutput ) | 388 | const QObject *receiver, const char *slotOutput, bool rawOutput ) |
367 | { | 389 | { |
368 | if ( command == OPackage::NotDefined ) | 390 | if ( command == OPackage::NotDefined ) |
369 | return false; | 391 | return false; |
370 | 392 | ||
371 | // Set ipkg run-time options/arguments | 393 | // Set ipkg run-time options/arguments |
372 | m_ipkgArgs.force_depends = ( m_ipkgExecOptions & FORCE_DEPENDS ); | 394 | m_ipkgArgs.force_depends = ( m_ipkgExecOptions & FORCE_DEPENDS ); |
@@ -379,74 +401,89 @@ bool OIpkg::executeCommand( OPackage::Command command, const QStringList ¶me | |||
379 | if ( !destination.isNull() ) | 401 | if ( !destination.isNull() ) |
380 | { | 402 | { |
381 | int len = destination.length() + 1; | 403 | int len = destination.length() + 1; |
382 | m_ipkgArgs.dest = (char *)malloc( len ); | 404 | m_ipkgArgs.dest = (char *)malloc( len ); |
383 | strncpy( m_ipkgArgs.dest, destination, destination.length() ); | 405 | strncpy( m_ipkgArgs.dest, destination, destination.length() ); |
384 | m_ipkgArgs.dest[ len - 1 ] = '\0'; | 406 | m_ipkgArgs.dest[ len - 1 ] = '\0'; |
385 | } | 407 | } |
386 | else | 408 | else |
387 | m_ipkgArgs.dest = 0x0; | 409 | m_ipkgArgs.dest = 0l; |
388 | 410 | ||
389 | // Connect output signal to widget | 411 | // Connect output signal to widget |
390 | 412 | ||
391 | if ( rawOutput ) | 413 | if ( !rawOutput ) |
392 | { | ||
393 | // if ( slotOutput ) | ||
394 | // connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | ||
395 | } | ||
396 | else | ||
397 | { | 414 | { |
398 | // TODO - connect to local slot and parse output before emitting signalIpkgMessage | 415 | // TODO - connect to local slot and parse output before emitting signalIpkgMessage |
399 | } | 416 | } |
400 | 417 | ||
401 | switch( command ) | 418 | switch( command ) |
402 | { | 419 | { |
403 | case OPackage::Update : { | 420 | case OPackage::Update : { |
404 | connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | 421 | connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput ); |
405 | ipkg_lists_update( &m_ipkgArgs ); | 422 | ipkg_lists_update( &m_ipkgArgs ); |
406 | }; | 423 | }; |
407 | break; | 424 | break; |
408 | case OPackage::Upgrade : { | 425 | case OPackage::Upgrade : { |
409 | connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | 426 | connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput ); |
410 | ipkg_packages_upgrade( &m_ipkgArgs ); | 427 | ipkg_packages_upgrade( &m_ipkgArgs ); |
428 | |||
429 | // Re-link non-root destinations to make sure everything is in sync | ||
430 | OConfItemList *destList = destinations(); | ||
431 | OConfItemListIterator it( *destList ); | ||
432 | for ( ; it.current(); ++it ) | ||
433 | { | ||
434 | OConfItem *dest = it.current(); | ||
435 | if ( dest->name() != "root" ) | ||
436 | linkPackageDir( dest->name() ); | ||
437 | } | ||
438 | delete destList; | ||
411 | }; | 439 | }; |
412 | break; | 440 | break; |
413 | case OPackage::Install : { | 441 | case OPackage::Install : { |
414 | connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | 442 | connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput ); |
415 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) | 443 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) |
416 | { | 444 | { |
417 | ipkg_packages_install( &m_ipkgArgs, (*it) ); | 445 | ipkg_packages_install( &m_ipkgArgs, (*it) ); |
418 | } | 446 | } |
447 | if ( destination != "root" ) | ||
448 | linkPackageDir( destination ); | ||
419 | }; | 449 | }; |
420 | break; | 450 | break; |
421 | case OPackage::Remove : { | 451 | case OPackage::Remove : { |
422 | connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | 452 | connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput ); |
453 | |||
454 | // Get list of destinations for unlinking of packages not installed to root | ||
455 | OConfItemList *destList = destinations(); | ||
456 | |||
423 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) | 457 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) |
424 | { | 458 | { |
459 | unlinkPackage( (*it), destList ); | ||
425 | ipkg_packages_remove( &m_ipkgArgs, (*it), true ); | 460 | ipkg_packages_remove( &m_ipkgArgs, (*it), true ); |
426 | } | 461 | } |
462 | |||
463 | delete destList; | ||
427 | }; | 464 | }; |
428 | break; | 465 | break; |
429 | case OPackage::Download : { | 466 | case OPackage::Download : { |
430 | connect( this, SIGNAL(signalIpkgMessage(char*)), receiver, slotOutput ); | 467 | connect( this, SIGNAL(signalIpkgMessage(const QString &)), receiver, slotOutput ); |
431 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) | 468 | for ( QStringList::ConstIterator it = parameters.begin(); it != parameters.end(); ++it ) |
432 | { | 469 | { |
433 | ipkg_packages_download( &m_ipkgArgs, (*it) ); | 470 | ipkg_packages_download( &m_ipkgArgs, (*it) ); |
434 | } | 471 | } |
435 | }; | 472 | }; |
436 | break; | 473 | break; |
437 | case OPackage::Info : { | 474 | case OPackage::Info : { |
438 | connect( this, SIGNAL(signalIpkgStatus(char*)), receiver, slotOutput ); | 475 | connect( this, SIGNAL(signalIpkgStatus(const QString &)), receiver, slotOutput ); |
439 | ipkg_packages_info( &m_ipkgArgs, (*parameters.begin()), &fIpkgStatus, 0x0 ); | 476 | ipkg_packages_info( &m_ipkgArgs, (*parameters.begin()), &fIpkgStatus, 0l ); |
440 | }; | 477 | }; |
441 | break; | 478 | break; |
442 | case OPackage::Files : { | 479 | case OPackage::Files : { |
443 | connect( this, SIGNAL(signalIpkgList(char*)), receiver, slotOutput ); | 480 | connect( this, SIGNAL(signalIpkgList(const QString &)), receiver, slotOutput ); |
444 | ipkg_package_files( &m_ipkgArgs, (*parameters.begin()), &fIpkgFiles, 0x0 ); | 481 | ipkg_package_files( &m_ipkgArgs, (*parameters.begin()), &fIpkgFiles, 0l ); |
445 | }; | 482 | }; |
446 | break; | 483 | break; |
447 | default : break; | 484 | default : break; |
448 | }; | 485 | }; |
449 | 486 | ||
450 | return true; | 487 | return true; |
451 | } | 488 | } |
452 | 489 | ||
@@ -584,8 +621,145 @@ OConfItemList *OIpkg::filterConfItems( OConfItem::Type typefilter ) | |||
584 | if ( retrieveAll || item->type() == typefilter ) | 621 | if ( retrieveAll || item->type() == typefilter ) |
585 | { | 622 | { |
586 | sl->append( item ); | 623 | sl->append( item ); |
587 | } | 624 | } |
588 | } | 625 | } |
589 | 626 | ||
590 | return sl; | 627 | return sl; |
591 | } | 628 | } |
629 | |||
630 | const QString &OIpkg::rootPath() | ||
631 | { | ||
632 | if ( m_rootPath.isEmpty() ) | ||
633 | { | ||
634 | OConfItem *rootDest = findConfItem( OConfItem::Destination, "root" ); | ||
635 | rootDest ? m_rootPath = rootDest->value() | ||
636 | : m_rootPath = '/'; | ||
637 | if ( m_rootPath.right( 1 ) == '/' ) | ||
638 | m_rootPath.truncate( m_rootPath.length() - 1 ); | ||
639 | } | ||
640 | return m_rootPath; | ||
641 | } | ||
642 | |||
643 | void OIpkg::linkPackageDir( const QString &dest ) | ||
644 | { | ||
645 | if ( !dest.isNull() ) | ||
646 | { | ||
647 | OConfItem *destConfItem = findConfItem( OConfItem::Destination, dest ); | ||
648 | |||
649 | emit signalIpkgMessage( tr( "Linking packages installed in: %1" ).arg( dest ) ); | ||
650 | |||
651 | // Set package destination directory | ||
652 | QString destDir = destConfItem->value(); | ||
653 | QString destInfoDir = destDir; | ||
654 | if ( destInfoDir.right( 1 ) != '/' ) | ||
655 | destInfoDir.append( '/' ); | ||
656 | destInfoDir.append( IPKG_INFO_PATH ); | ||
657 | |||
658 | // Get list of installed packages in destination | ||
659 | QDir packageDir( destInfoDir ); | ||
660 | QStringList packageFiles; | ||
661 | if ( packageDir.exists() ) | ||
662 | { | ||
663 | packageDir.setNameFilter( "*.list" ); | ||
664 | packageDir.setFilter( QDir::Files ); | ||
665 | packageFiles = packageDir.entryList( "*.list", QDir::Files ); | ||
666 | } | ||
667 | |||
668 | // Link all files for every package installed in desination | ||
669 | QStringList::Iterator lastFile = packageFiles.end(); | ||
670 | for ( QStringList::Iterator it = packageFiles.begin(); it != lastFile; ++it ) | ||
671 | { | ||
672 | //emit signalIpkgMessage( QString( "Processing: %1/%2" ).arg( destInfoDir ).arg (*it) ); | ||
673 | QString packageFileName = destInfoDir; | ||
674 | packageFileName.append( '/' ); | ||
675 | packageFileName.append( (*it) ); | ||
676 | QFile packageFile( packageFileName ); | ||
677 | if ( packageFile.open( IO_ReadOnly ) ) | ||
678 | { | ||
679 | QTextStream t( &packageFile ); | ||
680 | QString linkFile; | ||
681 | while ( !t.eof() ) | ||
682 | { | ||
683 | // Get the name of the file to link and build the sym link filename | ||
684 | linkFile = t.readLine(); | ||
685 | QString linkDest( linkFile.right( linkFile.length() - destDir.length() ) ); | ||
686 | linkDest.prepend( rootPath() ); | ||
687 | |||
688 | // If file installed file is actually symbolic link, use actual file for linking | ||
689 | QFileInfo fileInfo( linkFile ); | ||
690 | if ( fileInfo.isSymLink() && !fileInfo.readLink().isEmpty() ) | ||
691 | linkFile = fileInfo.readLink(); | ||
692 | |||
693 | // See if directory exists in 'root', if not, create | ||
694 | fileInfo.setFile( linkDest ); | ||
695 | QString linkDestDirName = fileInfo.dirPath( true ); | ||
696 | QDir linkDestDir( linkDestDirName ); | ||
697 | if ( !linkDestDir.exists() ) | ||
698 | { | ||
699 | linkDestDir.mkdir( linkDestDirName ); | ||
700 | } | ||
701 | else | ||
702 | { | ||
703 | // Remove any previous link to make sure we will be pointing to the current version | ||
704 | if ( QFile::exists( linkDest ) ) | ||
705 | QFile::remove( linkDest ); | ||
706 | } | ||
707 | |||
708 | // Link the file | ||
709 | //emit signalIpkgMessage( QString( "Linking '%1' to '%2'" ).arg( linkFile ).arg( linkDest ) ); | ||
710 | if ( symlink( linkFile, linkDest ) == -1 ) | ||
711 | emit signalIpkgMessage( tr( "Error linkling '%1' to '%2'" ) | ||
712 | .arg( linkFile ) | ||
713 | .arg( linkDest ) ); | ||
714 | } | ||
715 | packageFile.close(); | ||
716 | } | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | |||
721 | void OIpkg::unlinkPackage( const QString &package, OConfItemList *destList ) | ||
722 | { | ||
723 | if ( !package.isNull() ) | ||
724 | { | ||
725 | // Find destination package is installed in | ||
726 | if ( destList ) | ||
727 | { | ||
728 | OConfItemListIterator it( *destList ); | ||
729 | for ( ; it.current(); ++it ) | ||
730 | { | ||
731 | OConfItem *dest = it.current(); | ||
732 | QString destInfoFileName = QString( "%1/%2/%3.list" ).arg( dest->value() ) | ||
733 | .arg( IPKG_INFO_PATH ) | ||
734 | .arg( package ); | ||
735 | //emit signalIpkgMessage( QString( "Looking for '%1'" ).arg ( destInfoFileName ) ); | ||
736 | |||
737 | // If found and destination is not 'root', remove symbolic links | ||
738 | if ( QFile::exists( destInfoFileName ) && dest->name() != "root" ) | ||
739 | { | ||
740 | QFile destInfoFile( destInfoFileName ); | ||
741 | if ( destInfoFile.open( IO_ReadOnly ) ) | ||
742 | { | ||
743 | QTextStream t( &destInfoFile ); | ||
744 | QString linkFile; | ||
745 | while ( !t.eof() ) | ||
746 | { | ||
747 | // Get the name of the file to link and build the sym link filename | ||
748 | linkFile = t.readLine(); | ||
749 | QString linkDest( linkFile.right( linkFile.length() - | ||
750 | dest->value().length() ) ); | ||
751 | linkDest.prepend( rootPath() ); | ||
752 | |||
753 | //emit signalIpkgMessage( QString( "Deleting: '%1'" ).arg( linkDest ) ); | ||
754 | QFile::remove( linkDest ); | ||
755 | } | ||
756 | destInfoFile.close(); | ||
757 | } | ||
758 | |||
759 | emit signalIpkgMessage( tr( "Links removed for: %1" ).arg( package ) ); | ||
760 | return; | ||
761 | } | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | } | ||