summaryrefslogtreecommitdiff
path: root/noncore/settings/packagemanager/oipkg.cpp
Unidiff
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 @@
1/*
2                This file is part of the Opie Project
3
4              Copyright (c) 2003 Dan Williams <drw@handhelds.org>
5 =.
6 .=l.
7           .>+-=
8 _;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software
12 - .   .-<_>     .<> Foundation; either version 2 of the License,
13     ._= =}       : or (at your option) any later version.
14    .%`+i>       _;_.
15    .i_,=:_.      -<s. This program is distributed in the hope that
16     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17    : ..    .:,     . . . without even the implied warranty of
18    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22 :     =  ...= . :.=-
23 -.   .:....=;==+<; You should have received a copy of the GNU
24  -_. . .   )=.  = Library General Public License along with
25    --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
29
30*/
31
32#include "oipkg.h"
33
34#include <stdio.h>
35
36#include <qdir.h>
37#include <qfile.h>
38#include <qtextstream.h>
39
40#include <opie/oprocess.h>
41
42const QString IPKG_EXEC = "ipkg"; // Fully-qualified name of Ipkg executable
43const QString IPKG_CONF = "/etc/ipkg.conf"; // Fully-qualified name of Ipkg primary configuration file
44const QString IPKG_CONF_DIR = "/etc/ipkg"; // Directory of secondary Ipkg configuration files
45const QString IPKG_PKG_PATH = "/usr/lib/ipkg/lists"; // Directory containing server package lists
46const QString IPKG_STATUS_PATH = "usr/lib/ipkg/status"; // Destination status file location
47
48OIpkg::OIpkg( Config *config, QObject *parent, const char *name )
49 : QObject( parent, name )
50 , m_config( config )
51 , m_ipkgExec( IPKG_EXEC ) // TODO - find executable?
52 , m_confInfo( NULL )
53 , m_ipkgExecOptions( 0 )
54 , m_ipkgExecVerbosity( 1 )
55 , m_ipkgProcess( NULL )
56{
57}
58
59OIpkg::~OIpkg()
60{
61 // Upon destruction, ensure that items in config list are deleted with list
62 if ( m_confInfo )
63 m_confInfo->setAutoDelete( true );
64
65 // Terminate any running ipkg processes
66 if ( m_ipkgProcess )
67 delete m_ipkgProcess;
68}
69
70OConfItemList *OIpkg::configItems()
71{
72 // Retrieve all configuration items
73 return filterConfItems();
74}
75
76OConfItemList *OIpkg::servers()
77{
78 // Retrieve only servers
79 return filterConfItems( OConfItem::Source );
80}
81
82OConfItemList *OIpkg::destinations()
83{
84 // Retrieve only destinations
85 return filterConfItems( OConfItem::Destination );
86}
87
88OConfItemList *OIpkg::options()
89{
90 // Retrieve only destinations
91 return filterConfItems( OConfItem::Option );
92}
93
94void OIpkg::setConfigItems( OConfItemList *configList )
95{
96 if ( m_confInfo )
97 delete m_confInfo;
98
99 m_confInfo = configList;
100}
101
102void OIpkg::saveSettings()
103{
104 // Save Ipkg execution options to application configuration file
105 if ( m_config )
106 {
107 m_config->setGroup( "Ipkg" );
108 m_config->writeEntry( "ExecOptions", m_ipkgExecOptions );
109 m_config->writeEntry( "Verbosity", m_ipkgExecVerbosity );
110 }
111}
112
113OPackageList *OIpkg::availablePackages( const QString &server )
114{
115 // Load Ipkg configuration info if not already cached
116 if ( !m_confInfo )
117 loadConfiguration();
118
119 // Build new server list (caller is responsible for deleting)
120 OPackageList *pl = new OPackageList;
121
122 // Open package list file
123 QFile f( IPKG_PKG_PATH + "/" + server );
124 if ( !f.open( IO_ReadOnly ) )
125 return NULL;
126 QTextStream t( &f );
127
128 // Process all information in package list file
129 OPackage *package = NULL;
130 QString line = t.readLine();
131 while ( !t.eof() )
132 {
133 // Determine key/value pair
134 int pos = line.find( ':', 0 );
135 QString key;
136 if ( pos > -1 )
137 key = line.mid( 0, pos );
138 else
139 key = QString::null;
140 QString value = line.mid( pos+2, line.length()-pos );
141
142 // Allocate new package and insert into list
143 if ( package == NULL && !key.isEmpty() )
144 {
145 package = new OPackage( value );
146 package->setSource( server );
147 pl->append( package );
148 }
149
150 // Update package data
151 if ( key == "Package" )
152 package->setName( value );
153 else if ( key == "Version" )
154 package->setVersion( value );
155 else if ( key == "Section" )
156 package->setCategory( value );
157 //DataManager::setAvailableCategories( value );
158 else if ( key.isEmpty() && value.isEmpty() )
159 package = NULL;
160
161 // Skip past all description lines
162 if ( key == "Description" )
163 {
164 line = t.readLine();
165 while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
166 line = t.readLine();
167 }
168 else
169 line = t.readLine();
170 }
171
172 f.close();
173
174 return pl;
175}
176
177OPackageList *OIpkg::installedPackages( const QString &destName, const QString &destPath )
178{
179 // Load Ipkg configuration info if not already cached
180 if ( !m_confInfo )
181 loadConfiguration();
182
183 // Build new server list (caller is responsible for deleting)
184 OPackageList *pl = new OPackageList;
185
186 // Open status file
187 QString path = destPath;
188 if ( path.right( 1 ) != "/" )
189 path.append( "/" );
190 path.append( IPKG_STATUS_PATH );
191
192 QFile f( path );
193 if ( !f.open( IO_ReadOnly ) )
194 return NULL;
195 QTextStream t( &f );
196
197 // Process all information in status file
198 bool newPackage = false;
199 QString line = t.readLine();
200 QString name;
201 QString version;
202 QString status;
203
204 while ( !t.eof() )
205 {
206 // Determine key/value pair
207 int pos = line.find( ':', 0 );
208 QString key;
209 if ( pos > -1 )
210 key = line.mid( 0, pos );
211 else
212 key = QString::null;
213 QString value = line.mid( pos+2, line.length()-pos );
214
215 // Allocate new package and insert into list
216 if ( newPackage && !key.isEmpty() )
217 {
218 // Add to list only if it has a valid name and is installed
219 if ( !name.isNull() && status.contains( " installed" ) )
220 {
221 pl->append( new OPackage( name, QString::null, version, QString::null, destName ) );
222 name = QString::null;
223 version = QString::null;
224 status = QString::null;
225
226 newPackage = false;
227 }
228 }
229
230 // Update package data
231 if ( key == "Package" )
232 name = value;
233 else if ( key == "Version" )
234 version = value;
235 else if ( key == "Status" )
236 status = value;
237 else if ( key.isEmpty() && value.isEmpty() )
238 newPackage = true;
239
240 // Skip past all description lines
241 if ( key == "Description" )
242 {
243 line = t.readLine();
244 while ( !line.isEmpty() && line.find( ':', 0 ) == -1 && !t.eof() )
245 line = t.readLine();
246 }
247 else
248 line = t.readLine();
249 }
250
251 f.close();
252
253 return pl;
254}
255
256bool OIpkg::executeCommand( OPackage::Command command, QStringList *parameters, const QString &destination,
257 const QObject *receiver, const char *slotOutput, const char *slotErrors,
258 const char *slotFinished, bool rawOutput )
259{
260 if ( command == OPackage::NotDefined )
261 return false;
262
263 // Set up command line for execution
264 QStringList cmdLine;
265 cmdLine.append( IPKG_EXEC );
266
267 QString verbosity( "-V" );
268 verbosity.append( QString::number( m_ipkgExecVerbosity ) );
269 cmdLine.append( verbosity );
270
271 // Determine Ipkg execution options
272 if ( command == OPackage::Install && destination != QString::null )
273 {
274 // TODO - Set destination for installs
275 cmdLine.append( "-dest" );
276 cmdLine.append( destination );
277 }
278
279 if ( command != OPackage::Update && command != OPackage::Download )
280 {
281 if ( m_ipkgExecOptions & FORCE_DEPENDS )
282 cmdLine.append( "-force-depends" );
283 if ( m_ipkgExecOptions & FORCE_REINSTALL )
284 cmdLine.append( "-force-reinstall" );
285 if ( m_ipkgExecOptions & FORCE_REMOVE )
286 cmdLine.append( "-force-removal-of-essential-packages" );
287 if ( m_ipkgExecOptions & FORCE_OVERWRITE )
288 cmdLine.append( "-force-overwrite" );
289 if ( m_ipkgExecVerbosity == 3 )
290 cmdLine.append( "-verbose_wget" );
291
292 // TODO
293 // Handle make links
294 // Rules - If make links is switched on, create links to root
295 // if destDir is NOT /
296 /*
297 if ( m_ipkgExecOptions & MAKE_LINKS )
298 {
299 // If destDir == / turn off make links as package is being insalled
300 // to root already.
301 if ( destDir == "/" )
302 m_ipkgExecOptions ^= MAKE_LINKS;
303 }
304 */
305 }
306
307 QString cmd;
308 switch( command )
309 {
310 case OPackage::Install: cmd = "install";
311 break;
312 case OPackage::Remove: cmd = "remove";
313 break;
314 case OPackage::Update: cmd = "update";
315 break;
316 case OPackage::Upgrade: cmd = "upgrade";
317 break;
318 case OPackage::Download: cmd = "download";
319 break;
320 case OPackage::Info: cmd = "info";
321 break;
322 case OPackage::Files: cmd = "files";
323 break;
324 //case OPackage::Version: cmd = "" );
325 // break;
326 default:
327 break;
328 };
329 cmdLine.append( cmd );
330
331 // TODO
332 // If we are removing, reinstalling or upgrading packages and make links option is selected
333 // create the links
334/*
335 if ( command == Remove || command == Upgrade )
336 {
337 createLinks = false;
338 if ( flags & MAKE_LINKS )
339 {
340 emit outputText( tr( "Removing symbolic links...\n" ) );
341 linkPackage( Utils::getPackageNameFromIpkFilename( package ), destination, destDir );
342 emit outputText( QString( " " ) );
343 }
344 }
345*/
346 // Append package list (if any) to end of command line
347 if ( parameters && !parameters->isEmpty() )
348 {
349 for ( QStringList::Iterator it = parameters->begin(); it != parameters->end(); ++it )
350 {
351 cmdLine.append( *it );
352 }
353 }
354
355 // Create OProcess
356 if ( m_ipkgProcess )
357 delete m_ipkgProcess;
358 m_ipkgProcess = new OProcess( cmdLine, this );
359
360 // Connect signals (if any)
361 if ( receiver )
362 {
363 if ( rawOutput )
364 {
365 if ( slotOutput )
366 connect( m_ipkgProcess, SIGNAL(receivedStdout(OProcess*,char*,int)), receiver, slotOutput );
367 if ( slotErrors )
368 connect( m_ipkgProcess, SIGNAL(receivedStderr(OProcess*,char*,int)), receiver, slotErrors );
369 if ( slotFinished )
370 connect( m_ipkgProcess, SIGNAL(processExited(OProcess*)), receiver, slotFinished );
371 }
372 else // !rawOutput
373 {
374 // TODO - how should it handle partial lines? (i.e. "Installing opi", "e-aqpkg...")
375 }
376 }
377
378 // Run process
379printf( "Running: \'%s\'\n", cmdLine.join( " " ).latin1() );
380 return m_ipkgProcess->start( OProcess::NotifyOnExit, OProcess::All );
381}
382
383void OIpkg::abortCommand()
384{
385 if ( m_ipkgProcess )
386 delete m_ipkgProcess;
387}
388
389void OIpkg::loadConfiguration()
390{
391 if ( m_confInfo )
392 delete m_confInfo;
393
394 // Load configuration item list
395 m_confInfo = new OConfItemList();
396
397 QStringList confFiles;
398 QDir confDir( IPKG_CONF_DIR );
399 if ( confDir.exists() )
400 {
401 confDir.setNameFilter( "*.conf" );
402 confDir.setFilter( QDir::Files );
403 confFiles = confDir.entryList( "*.conf", QDir::Files );
404 confFiles << IPKG_CONF;
405
406 for ( QStringList::Iterator it = confFiles.begin(); it != confFiles.end(); ++it )
407 {
408 // Create absolute file path if necessary
409 QString absFile = (*it);
410 if ( !absFile.startsWith( "/" ) )
411 absFile.prepend( QString( IPKG_CONF_DIR ) + "/" );
412
413 // Read in file
414 QFile f( absFile );
415 if ( f.open( IO_ReadOnly ) )
416 {
417 QTextStream s( &f );
418 while ( !s.eof() )
419 {
420
421 QString line = s.readLine().simplifyWhiteSpace();
422
423 // Parse line and save info to the conf options list
424 if ( !line.isEmpty() )
425 {
426 if ( !line.startsWith( "#" ) ||
427 line.startsWith( "#src" ) ||
428 line.startsWith( "#dest" ) ||
429 line.startsWith( "#arch" ) ||
430 line.startsWith( "#option" ) )
431 {
432 int pos = line.find( ' ', 1 );
433
434 // Type
435 QString typeStr = line.left( pos );
436 OConfItem::Type type;
437 if ( typeStr == "src" || typeStr == "#src" )
438 type = OConfItem::Source;
439 else if ( typeStr == "dest" || typeStr == "#dest" )
440 type = OConfItem::Destination;
441 else if ( typeStr == "option" || typeStr == "#option" )
442 type = OConfItem::Option;
443 else if ( typeStr == "arch" || typeStr == "#arch" )
444 type = OConfItem::Arch;
445 else
446 type = OConfItem::NotDefined;
447 ++pos;
448 int endpos = line.find( ' ', pos );
449
450 // Name
451 QString name = line.mid( pos, endpos - pos );
452
453 // Value
454 QString value = "";
455 if ( endpos > -1 )
456 value = line.right( line.length() - endpos - 1 );
457
458 // Active
459 bool active = !line.startsWith( "#" );
460
461 // Add to list
462 m_confInfo->append( new OConfItem( absFile, type, name, value, active ) );
463 }
464 }
465 }
466
467 f.close();
468 }
469 }
470 }
471
472 // Load Ipkg execution options from application configuration file
473 if ( m_config )
474 {
475 m_config->setGroup( "Ipkg" );
476 m_ipkgExecOptions = m_config->readNumEntry( "ExecOptions", m_ipkgExecOptions );
477 m_ipkgExecVerbosity = m_config->readNumEntry( "Verbosity", m_ipkgExecVerbosity );
478 }
479}
480
481OConfItemList *OIpkg::filterConfItems( OConfItem::Type typefilter )
482{
483 // Load Ipkg configuration info if not already cached
484 if ( !m_confInfo )
485 loadConfiguration();
486
487 // Build new server list (caller is responsible for deleting)
488 OConfItemList *sl = new OConfItemList;
489
490 // If typefilter is empty, retrieve all items
491 bool retrieveAll = ( typefilter == OConfItem::NotDefined );
492
493 // Parse configuration info for servers
494 OConfItemListIterator it( *m_confInfo );
495 for ( ; it.current(); ++it )
496 {
497 OConfItem *item = it.current();
498 if ( retrieveAll || item->type() == typefilter )
499 {
500 sl->append( item );
501 }
502 }
503
504 return sl;
505}