summaryrefslogtreecommitdiff
path: root/noncore/settings/packagemanager/oipkg.cpp
Side-by-side diff
Diffstat (limited to 'noncore/settings/packagemanager/oipkg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/settings/packagemanager/oipkg.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/noncore/settings/packagemanager/oipkg.cpp b/noncore/settings/packagemanager/oipkg.cpp
new file mode 100644
index 0000000..13f3d7d
--- a/dev/null
+++ b/noncore/settings/packagemanager/oipkg.cpp
@@ -0,0 +1,505 @@
+/*
+                This file is part of the Opie Project
+
+              Copyright (c) 2003 Dan Williams <drw@handhelds.org>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "oipkg.h"
+
+#include <stdio.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <opie/oprocess.h>
+
+const QString IPKG_EXEC = "ipkg"; // Fully-qualified name of Ipkg executable
+const QString IPKG_CONF = "/etc/ipkg.conf"; // Fully-qualified name of Ipkg primary configuration file
+const QString IPKG_CONF_DIR = "/etc/ipkg"; // Directory of secondary Ipkg configuration files
+const QString IPKG_PKG_PATH = "/usr/lib/ipkg/lists"; // Directory containing server package lists
+const QString IPKG_STATUS_PATH = "usr/lib/ipkg/status"; // Destination status file location
+
+OIpkg::OIpkg( Config *config, QObject *parent, const char *name )
+ : QObject( parent, name )
+ , m_config( config )
+ , m_ipkgExec( IPKG_EXEC ) // TODO - find executable?
+ , m_confInfo( NULL )
+ , m_ipkgExecOptions( 0 )
+ , m_ipkgExecVerbosity( 1 )
+ , m_ipkgProcess( NULL )
+{
+}
+
+OIpkg::~OIpkg()
+{
+ // Upon destruction, ensure that items in config list are deleted with list
+ if ( m_confInfo )
+ m_confInfo->setAutoDelete( true );
+
+ // Terminate any running ipkg processes
+ if ( m_ipkgProcess )
+ delete m_ipkgProcess;
+}
+
+OConfItemList *OIpkg::configItems()
+{
+ // Retrieve all configuration items
+ return filterConfItems();
+}
+
+OConfItemList *OIpkg::servers()
+{
+ // Retrieve only servers
+ return filterConfItems( OConfItem::Source );
+}
+
+OConfItemList *OIpkg::destinations()
+{
+ // Retrieve only destinations
+ return filterConfItems( OConfItem::Destination );
+}
+
+OConfItemList *OIpkg::options()
+{
+ // Retrieve only destinations
+ return filterConfItems( OConfItem::Option );
+}
+
+void OIpkg::setConfigItems( OConfItemList *configList )
+{
+ if ( m_confInfo )
+ delete m_confInfo;
+
+ m_confInfo = configList;
+}
+
+void OIpkg::saveSettings()
+{
+ // Save Ipkg execution options to application configuration file
+ if ( m_config )
+ {
+ m_config->setGroup( "Ipkg" );
+ m_config->writeEntry( "ExecOptions", m_ipkgExecOptions );
+ m_config->writeEntry( "Verbosity", m_ipkgExecVerbosity );
+ }
+}
+
+OPackageList *OIpkg::availablePackages( const QString &server )
+{
+ // Load Ipkg configuration info if not already cached
+ if ( !m_confInfo )
+ loadConfiguration();
+
+ // Build new server list (caller is responsible for deleting)
+ OPackageList *pl = new OPackageList;
+
+ // Open package list file
+ QFile f( IPKG_PKG_PATH + "/" + server );
+ if ( !f.open( IO_ReadOnly ) )
+ return NULL;
+ QTextStream t( &f );
+
+ // Process all information in package list file
+ OPackage *package = NULL;
+ QString line = t.readLine();
+ while ( !t.eof() )
+ {
+ // Determine key/value pair
+ int pos = line.find( ':', 0 );
+ QString key;
+ if ( pos > -1 )
+ key = line.mid( 0, pos );
+ else
+ key = QString::null;
+ QString value = line.mid( pos+2, line.length()-pos );
+
+ // Allocate new package and insert into list
+ if ( package == NULL && !key.isEmpty() )
+ {
+ package = new OPackage( value );
+ package->setSource( server );
+ pl->append( package );
+ }
+
+ // Update package data
+ if ( key == "Package" )
+ package->setName( value );
+ else if ( key == "Version" )
+ package->setVersion( value );
+ else if ( key == "Section" )
+ package->setCategory( value );
+ //DataManager::setAvailableCategories( value );
+ else if ( key.isEmpty() && value.isEmpty() )
+ package = NULL;
+
+ // Skip past all description lines
+ if ( key == "Description" )
+ {
+ line = t.readLine();
+ while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
+ line = t.readLine();
+ }
+ else
+ line = t.readLine();
+ }
+
+ f.close();
+
+ return pl;
+}
+
+OPackageList *OIpkg::installedPackages( const QString &destName, const QString &destPath )
+{
+ // Load Ipkg configuration info if not already cached
+ if ( !m_confInfo )
+ loadConfiguration();
+
+ // Build new server list (caller is responsible for deleting)
+ OPackageList *pl = new OPackageList;
+
+ // Open status file
+ QString path = destPath;
+ if ( path.right( 1 ) != "/" )
+ path.append( "/" );
+ path.append( IPKG_STATUS_PATH );
+
+ QFile f( path );
+ if ( !f.open( IO_ReadOnly ) )
+ return NULL;
+ QTextStream t( &f );
+
+ // Process all information in status file
+ bool newPackage = false;
+ QString line = t.readLine();
+ QString name;
+ QString version;
+ QString status;
+
+ while ( !t.eof() )
+ {
+ // Determine key/value pair
+ int pos = line.find( ':', 0 );
+ QString key;
+ if ( pos > -1 )
+ key = line.mid( 0, pos );
+ else
+ key = QString::null;
+ QString value = line.mid( pos+2, line.length()-pos );
+
+ // Allocate new package and insert into list
+ if ( newPackage && !key.isEmpty() )
+ {
+ // Add to list only if it has a valid name and is installed
+ if ( !name.isNull() && status.contains( " installed" ) )
+ {
+ pl->append( new OPackage( name, QString::null, version, QString::null, destName ) );
+ name = QString::null;
+ version = QString::null;
+ status = QString::null;
+
+ newPackage = false;
+ }
+ }
+
+ // Update package data
+ if ( key == "Package" )
+ name = value;
+ else if ( key == "Version" )
+ version = value;
+ else if ( key == "Status" )
+ status = value;
+ else if ( key.isEmpty() && value.isEmpty() )
+ newPackage = true;
+
+ // Skip past all description lines
+ if ( key == "Description" )
+ {
+ line = t.readLine();
+ while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
+ line = t.readLine();
+ }
+ else
+ line = t.readLine();
+ }
+
+ f.close();
+
+ return pl;
+}
+
+bool OIpkg::executeCommand( OPackage::Command command, QStringList *parameters, const QString &destination,
+ const QObject *receiver, const char *slotOutput, const char *slotErrors,
+ const char *slotFinished, bool rawOutput )
+{
+ if ( command == OPackage::NotDefined )
+ return false;
+
+ // Set up command line for execution
+ QStringList cmdLine;
+ cmdLine.append( IPKG_EXEC );
+
+ QString verbosity( "-V" );
+ verbosity.append( QString::number( m_ipkgExecVerbosity ) );
+ cmdLine.append( verbosity );
+
+ // Determine Ipkg execution options
+ if ( command == OPackage::Install && destination != QString::null )
+ {
+ // TODO - Set destination for installs
+ cmdLine.append( "-dest" );
+ cmdLine.append( destination );
+ }
+
+ if ( command != OPackage::Update && command != OPackage::Download )
+ {
+ if ( m_ipkgExecOptions & FORCE_DEPENDS )
+ cmdLine.append( "-force-depends" );
+ if ( m_ipkgExecOptions & FORCE_REINSTALL )
+ cmdLine.append( "-force-reinstall" );
+ if ( m_ipkgExecOptions & FORCE_REMOVE )
+ cmdLine.append( "-force-removal-of-essential-packages" );
+ if ( m_ipkgExecOptions & FORCE_OVERWRITE )
+ cmdLine.append( "-force-overwrite" );
+ if ( m_ipkgExecVerbosity == 3 )
+ cmdLine.append( "-verbose_wget" );
+
+ // TODO
+ // Handle make links
+ // Rules - If make links is switched on, create links to root
+ // if destDir is NOT /
+ /*
+ if ( m_ipkgExecOptions & MAKE_LINKS )
+ {
+ // If destDir == / turn off make links as package is being insalled
+ // to root already.
+ if ( destDir == "/" )
+ m_ipkgExecOptions ^= MAKE_LINKS;
+ }
+ */
+ }
+
+ QString cmd;
+ switch( command )
+ {
+ case OPackage::Install: cmd = "install";
+ break;
+ case OPackage::Remove: cmd = "remove";
+ break;
+ case OPackage::Update: cmd = "update";
+ break;
+ case OPackage::Upgrade: cmd = "upgrade";
+ break;
+ case OPackage::Download: cmd = "download";
+ break;
+ case OPackage::Info: cmd = "info";
+ break;
+ case OPackage::Files: cmd = "files";
+ break;
+ //case OPackage::Version: cmd = "" );
+ // break;
+ default:
+ break;
+ };
+ cmdLine.append( cmd );
+
+ // TODO
+ // If we are removing, reinstalling or upgrading packages and make links option is selected
+ // create the links
+/*
+ if ( command == Remove || command == Upgrade )
+ {
+ createLinks = false;
+ if ( flags & MAKE_LINKS )
+ {
+ emit outputText( tr( "Removing symbolic links...\n" ) );
+ linkPackage( Utils::getPackageNameFromIpkFilename( package ), destination, destDir );
+ emit outputText( QString( " " ) );
+ }
+ }
+*/
+ // Append package list (if any) to end of command line
+ if ( parameters && !parameters->isEmpty() )
+ {
+ for ( QStringList::Iterator it = parameters->begin(); it != parameters->end(); ++it )
+ {
+ cmdLine.append( *it );
+ }
+ }
+
+ // Create OProcess
+ if ( m_ipkgProcess )
+ delete m_ipkgProcess;
+ m_ipkgProcess = new OProcess( cmdLine, this );
+
+ // Connect signals (if any)
+ if ( receiver )
+ {
+ if ( rawOutput )
+ {
+ if ( slotOutput )
+ connect( m_ipkgProcess, SIGNAL(receivedStdout(OProcess*,char*,int)), receiver, slotOutput );
+ if ( slotErrors )
+ connect( m_ipkgProcess, SIGNAL(receivedStderr(OProcess*,char*,int)), receiver, slotErrors );
+ if ( slotFinished )
+ connect( m_ipkgProcess, SIGNAL(processExited(OProcess*)), receiver, slotFinished );
+ }
+ else // !rawOutput
+ {
+ // TODO - how should it handle partial lines? (i.e. "Installing opi", "e-aqpkg...")
+ }
+ }
+
+ // Run process
+printf( "Running: \'%s\'\n", cmdLine.join( " " ).latin1() );
+ return m_ipkgProcess->start( OProcess::NotifyOnExit, OProcess::All );
+}
+
+void OIpkg::abortCommand()
+{
+ if ( m_ipkgProcess )
+ delete m_ipkgProcess;
+}
+
+void OIpkg::loadConfiguration()
+{
+ if ( m_confInfo )
+ delete m_confInfo;
+
+ // Load configuration item list
+ m_confInfo = new OConfItemList();
+
+ QStringList confFiles;
+ QDir confDir( IPKG_CONF_DIR );
+ if ( confDir.exists() )
+ {
+ confDir.setNameFilter( "*.conf" );
+ confDir.setFilter( QDir::Files );
+ confFiles = confDir.entryList( "*.conf", QDir::Files );
+ confFiles << IPKG_CONF;
+
+ for ( QStringList::Iterator it = confFiles.begin(); it != confFiles.end(); ++it )
+ {
+ // Create absolute file path if necessary
+ QString absFile = (*it);
+ if ( !absFile.startsWith( "/" ) )
+ absFile.prepend( QString( IPKG_CONF_DIR ) + "/" );
+
+ // Read in file
+ QFile f( absFile );
+ if ( f.open( IO_ReadOnly ) )
+ {
+ QTextStream s( &f );
+ while ( !s.eof() )
+ {
+
+ QString line = s.readLine().simplifyWhiteSpace();
+
+ // Parse line and save info to the conf options list
+ if ( !line.isEmpty() )
+ {
+ if ( !line.startsWith( "#" ) ||
+ line.startsWith( "#src" ) ||
+ line.startsWith( "#dest" ) ||
+ line.startsWith( "#arch" ) ||
+ line.startsWith( "#option" ) )
+ {
+ int pos = line.find( ' ', 1 );
+
+ // Type
+ QString typeStr = line.left( pos );
+ OConfItem::Type type;
+ if ( typeStr == "src" || typeStr == "#src" )
+ type = OConfItem::Source;
+ else if ( typeStr == "dest" || typeStr == "#dest" )
+ type = OConfItem::Destination;
+ else if ( typeStr == "option" || typeStr == "#option" )
+ type = OConfItem::Option;
+ else if ( typeStr == "arch" || typeStr == "#arch" )
+ type = OConfItem::Arch;
+ else
+ type = OConfItem::NotDefined;
+ ++pos;
+ int endpos = line.find( ' ', pos );
+
+ // Name
+ QString name = line.mid( pos, endpos - pos );
+
+ // Value
+ QString value = "";
+ if ( endpos > -1 )
+ value = line.right( line.length() - endpos - 1 );
+
+ // Active
+ bool active = !line.startsWith( "#" );
+
+ // Add to list
+ m_confInfo->append( new OConfItem( absFile, type, name, value, active ) );
+ }
+ }
+ }
+
+ f.close();
+ }
+ }
+ }
+
+ // Load Ipkg execution options from application configuration file
+ if ( m_config )
+ {
+ m_config->setGroup( "Ipkg" );
+ m_ipkgExecOptions = m_config->readNumEntry( "ExecOptions", m_ipkgExecOptions );
+ m_ipkgExecVerbosity = m_config->readNumEntry( "Verbosity", m_ipkgExecVerbosity );
+ }
+}
+
+OConfItemList *OIpkg::filterConfItems( OConfItem::Type typefilter )
+{
+ // Load Ipkg configuration info if not already cached
+ if ( !m_confInfo )
+ loadConfiguration();
+
+ // Build new server list (caller is responsible for deleting)
+ OConfItemList *sl = new OConfItemList;
+
+ // If typefilter is empty, retrieve all items
+ bool retrieveAll = ( typefilter == OConfItem::NotDefined );
+
+ // Parse configuration info for servers
+ OConfItemListIterator it( *m_confInfo );
+ for ( ; it.current(); ++it )
+ {
+ OConfItem *item = it.current();
+ if ( retrieveAll || item->type() == typefilter )
+ {
+ sl->append( item );
+ }
+ }
+
+ return sl;
+}