summaryrefslogtreecommitdiff
path: root/src/pkgdb.cpp
blob: c80c215fb508cb304f2160e5eec57306274afe86 (plain)
    1 ////////////////////////////////////////////////////////////////////////
    2 // FILE:        pkgdb.cpp
    3 // AUTHOR:      Johannes Winkelmann, jw@tks6.net
    4 // COPYRIGHT:   (c) 2002 by Johannes Winkelmann
    5 // ---------------------------------------------------------------------
    6 //  This program is free software; you can redistribute it and/or modify
    7 //  it under the terms of the GNU General Public License as published by
    8 //  the Free Software Foundation; either version 2 of the License, or
    9 //  (at your option) any later version.
   10 ////////////////////////////////////////////////////////////////////////
   11 
   12 #include <algorithm>
   13 #include <fstream>
   14 #include <map>
   15 #include <iostream>
   16 using namespace std;
   17 
   18 #include <cstring>
   19 #include <cstdio>
   20 
   21 #include <fnmatch.h>
   22 
   23 #include "pkgdb.h"
   24 #include "datafileparser.h"
   25 #include "stringhelper.h"
   26 #include "pg_regex.h"
   27 
   28 
   29 const string PkgDB::PKGDB = "/var/lib/pkg/db";
   30 const string PkgDB::ALIAS_STORE = SYSCONFDIR"/prt-get.aliases";
   31 
   32 /*!
   33   Create a PkgDB object
   34 */
   35 PkgDB::PkgDB( const string& installRoot )
   36     : m_isLoaded( false ),
   37       m_installRoot( installRoot )
   38 {
   39 }
   40 
   41 /*!
   42   Check whether a package is installed
   43 
   44   \param name the name of the package to check
   45   \param isAlias whether a package is installed as alias
   46   \param aliasOriginalName the original name of an aliased package
   47 
   48   \return whether package \a name is installed
   49 */
   50 bool PkgDB::isInstalled( const string& name,
   51                          bool useAlias,
   52                          bool* isAlias,
   53                          string* aliasOrignalName ) const
   54 {
   55     if ( !load() ) {
   56         return false;
   57     }
   58     
   59     bool installed = m_packages.find( name ) != m_packages.end();
   60     if (!installed && useAlias) {
   61         string provider;
   62         installed = aliasExistsFor(name, provider);
   63 
   64         if (isAlias) {
   65             *isAlias = installed;
   66 
   67             if (installed && aliasOrignalName) {
   68                 *aliasOrignalName = provider;
   69             }
   70         }
   71     } else {
   72         if (isAlias) {
   73             *isAlias = false;
   74         }
   75     }
   76 
   77     return installed;
   78 }
   79 
   80 
   81 bool PkgDB::aliasExistsFor(const string& name, string& providerName) const
   82 {
   83     // when used the first time, split alias names
   84     if (m_splitAliases.size() < m_aliases.size()) {
   85         map<string, string>::iterator it = m_aliases.begin();
   86         for (; it != m_aliases.end(); ++it) {
   87             StringHelper::split(it->second, ',',
   88                                 m_splitAliases[it->first]);
   89         }
   90     }
   91 
   92     map<string, vector<string> >::iterator it = m_splitAliases.begin();
   93     for (; it != m_splitAliases.end(); ++it) {
   94         if (find(it->second.begin(), it->second.end(), name) !=
   95             it->second.end()) {
   96             providerName = it->first;
   97             return true;
   98         }
   99     }
  100 
  101     return false;
  102 }
  103 
  104 /*!
  105   load the package db
  106 */
  107 bool PkgDB::load() const
  108 {
  109     if ( m_isLoaded ) {
  110         return true;
  111     }
  112 
  113 #if 0
  114     // check this one out to see a really slow IO library :-(
  115 
  116 
  117     ifstream db( PKGDB );
  118     string line;
  119     bool emptyLine = true;
  120     while ( db.good() ) {
  121         getline( db, line );
  122         if ( emptyLine ) {
  123             if ( !line.empty() ) {
  124                 m_packages.push_back( line );
  125             }
  126             emptyLine = false;
  127         }
  128         if ( line == "" ) {
  129             emptyLine = true;
  130         }
  131     }
  132     db.close();
  133 #endif
  134 
  135     std::map<std::string, std::string> aliases;
  136     DataFileParser::parse(ALIAS_STORE, aliases);
  137 
  138     const int length = 256;
  139     char line[length];
  140     bool emptyLine = true;
  141     bool nameRead = false;
  142     string name;
  143 
  144     string pkgdb = "";
  145     if (m_installRoot != "") {
  146         pkgdb = m_installRoot;
  147     }
  148     pkgdb += PKGDB;
  149 
  150     FILE* fp = fopen( pkgdb.c_str(), "r" );
  151     if ( fp ) {
  152         while ( fgets( line, length, fp ) ) {
  153             if ( emptyLine ) {
  154                 line[strlen(line)-1] = '\0';
  155                 name = line;
  156                 emptyLine = false;
  157                 nameRead = true;
  158             } else if ( nameRead ) {
  159                 line[strlen(line)-1] = '\0';
  160                 m_packages[ name ] = line;
  161                 nameRead = false;
  162                 if (aliases.find(name) != aliases.end()) {
  163                     m_aliases[name] = aliases[name];
  164                 }
  165             }
  166             if ( line[0] == '\n' ) {
  167                 emptyLine = true;
  168             }
  169 
  170         }
  171     } else {
  172         return false;
  173     }
  174 
  175     m_isLoaded = true;
  176 
  177     fclose( fp );
  178 
  179     return true;
  180 }
  181 
  182 /*!
  183   return a map of installed packages, where the key is the package name and
  184   the value is the version/release string
  185   \return a map of installed packages (key=name, value=version/release)
  186 */
  187 const map<string, string>& PkgDB::installedPackages()
  188 {
  189     load();
  190     return m_packages;
  191 }
  192 
  193 /*!
  194   \return a package's version and release or an empty string if not found
  195 */
  196 string PkgDB::getPackageVersion( const string& name ) const
  197 {
  198     if ( !load() ) {
  199         return "";
  200     }
  201 
  202     map<string, string>::const_iterator it = m_packages.find( name );
  203     if ( it == m_packages.end() ) {
  204         return "";
  205     }
  206 
  207     return it->second;
  208 }
  209 
  210 /*!
  211   Search packages for a match of \a pattern in name. The name can
  212   contain shell wildcards.
  213 
  214   \param pattern the pattern to be found
  215   \return a list of matching packages
  216 */
  217 void PkgDB::getMatchingPackages( const string& pattern,
  218                                  map<string,string>& target,
  219                                  bool useRegex ) const
  220 {
  221     if ( !load() ) {
  222         return;
  223     }
  224 
  225     RegEx re(pattern);
  226     map<string, string>::const_iterator it = m_packages.begin();
  227     if (useRegex) {
  228         for ( ; it != m_packages.end(); ++it ) {
  229             if (re.match(it->first)) {
  230                 target[it->first] = it->second;
  231             }
  232         }
  233     } else {
  234         for ( ; it != m_packages.end(); ++it ) {
  235             // I assume fnmatch will be quite fast for "match all" (*), so
  236             // I didn't add a boolean to check for this explicitely
  237             if ( fnmatch( pattern.c_str(), it->first.c_str(), 0  ) == 0 ) {
  238                 target[it->first] = it->second;
  239             }
  240         }
  241     }
  242 }

Generated by cgit