I've just started working on the text version of MandrakeUpdate a few
hours ago, in C++, using libcurl + librpm... it's still very alpha
quality and still not very usable.

What it can do right now:
download the mirror list, visit the FTP sites and check the description
of updates, list which package available for updates..

Source code listing is attached in simple.cpp

TODO:
- Check the RPM if it's installed
- Compare the rpm version of installed and the updates
- Auto dependency
- Put the entry in /etc/cron.weekly after it's done 
- Much more

-- 
Prana <[EMAIL PROTECTED]>
http://www.cyest.org
My GnuPG Key ID: 0x33343FD3 (2000-07-21)
Key fingerprint = F1FB 1F76 8866 0F40 A801  D9DA 6BED 6641 3334 3FD3
http://blackhole.pca.dfn.de:11371/pks/lookup?op=get&search=0x33343FD3
#include <string>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <hash_map>
#include <fstream>
#include <iostream>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <rpm/rpmlib.h>
#include <stl.h>
using namespace std;

#define mirror_list "http://www.linux-mandrake.com/mirrorsfull.list"
#define mirror_list_saved "/etc/urpmi/mirrorsfull.list"
#define temp_updatelist_file "/etc/urpmi/tempdownload.update"
#define version_file "/etc/mandrake-release"
#define DEBUG

enum either_file_or_directory
{
   is_a_file,
   is_a_directory
};

void open_mirror_ftp_sites()
{
}

/****************************************************************************/

bool download_file(const char *url_file, const char *tofile, either_file_or_directory 
filetype)
{
  CURL *curl;
  CURLcode res;
  FILE *contentfile;
  bool return_value = false;
  
  contentfile = fopen(tofile, "w");

  curl = curl_easy_init();
  if (curl)
  {
    /* what call to write: */
    curl_easy_setopt(curl, CURLOPT_URL, url_file);
    curl_easy_setopt(curl, CURLOPT_FILE, contentfile);
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS);
    if (filetype == is_a_directory)
       curl_easy_setopt(curl, CURLOPT_FTPLISTONLY);
    res = curl_easy_perform(curl);
    /* always cleanup */
    curl_easy_cleanup(curl);
    return_value = true;
  }
  fclose (contentfile);
  return return_value;
}

/****************************************************************************/

bool download_mirror(vector<string *> *mirrors, string *version, string *machine)
// Download the mirror
{
   ifstream *saved_mirror;
   string *ftp_site = new string;
   int colon_location;
   
   // Download the lists first from Mandrake's website
   download_file(mirror_list, mirror_list_saved, is_a_file);
   
   // Then open it..
   saved_mirror = new ifstream(mirror_list_saved);   
   *saved_mirror >> *ftp_site;
   while (!saved_mirror->eof())
   {
      // Process
      colon_location = ftp_site->find(":");
      if (ftp_site->substr(0,colon_location) == *machine)
      // Is it the right update?      
      {
#ifdef HARD_DEBUG
         cerr << ftp_site->substr(0,colon_location)
              << ftp_site->substr(colon_location+1, ftp_site->length())
              << endl;
#endif
         mirrors->push_back(new string( ftp_site->substr(colon_location+1, 
ftp_site->length()) ));
      }
      // Read again
      *saved_mirror >> *ftp_site;
   }
   saved_mirror->close();
}

/****************************************************************************/

bool visit_ftp_site(int retry, string *ftp_site, string *version, string *machine)
{
   bool get_description_okay;

#ifdef DEBUG
   cerr << "visit_ftp_site(...)" << endl;
#endif
   string *temp = new string(*ftp_site);
   *temp += "/" + *version;
   *temp += "/descriptions";
/*   if (download_file(temp->c_str(),"description_file", is_a_file))
   {
      cout << "OKAY" << endl;
   }*/
   *temp = *ftp_site;
   *temp += "/" + *version;
   *temp += "/RPMS/";
#ifdef DEBUG
   cerr << "Listing directory " << *temp << endl;
#endif
   if (download_file(temp->c_str(),temp_updatelist_file, is_a_directory))
   {
      cout << "Downloaded list" << endl;
   }
   delete temp;
   return true;
}

/****************************************************************************/

bool process_mirrors_and_do_updates(vector <string *> *mirrors_vector, string 
*version, string *machine)
{
   bool return_value = false;
   int ftp_site;
   
   for (ftp_site = 0; return_value==false && ftp_site < mirrors_vector->size(); 
ftp_site++)
   {
      return_value = visit_ftp_site( ftp_site, (*mirrors_vector)[ftp_site] , version, 
machine);
   }
   return return_value;
}

/****************************************************************************/

bool getversion_and_machine(string *version, string *machine)
// Get version from /etc/mandrake-release
{
   ifstream *mandrake_release;
   bool machine_found = false;
   bool return_value = false;
   bool cooker = false;   
   int position = 0;
  
   // Read string s from file
   mandrake_release = new ifstream(version_file);
   if (mandrake_release)
   {
      for (position = 0; position < 4; position++)
      {
         *mandrake_release >> *version;
         if (version->find("Cooker") != -1)
         {
            cooker = true;
            // Handler Cooker-sparc Cooker-i586 not done yet!!!!!!!!!
         }
      } // end for
      if (!cooker)
      {
         for (position = 0; position < 3; position++)
            *mandrake_release >> *machine;
      } // end if !cooker
      
      mandrake_release->close();
      // why do you put sparc into cookerparc? That's weird.
      if (*machine == "sparc")
         *machine = "parc";
         
      // If it's cooker
      if (cooker)
         *machine = "cooker" + *machine;
      else
         *machine = "updates" + *machine;
      return_value = (machine->length() > 0) && (version->length() > 0);
   }
   delete mandrake_release; // no memory leak
   return return_value;
}

/****************************************************************************/

bool is_rpm_package_installed (string *rpm_package_name)
{
   bool return_value = false;
   int status;   
   rpmdb rpm_database;
   dbiIndexSet matches;
   Header rpm_header;
   struct headerTagTableEntry tags;

#ifdef DEBUG
   cerr << "is_rpm_package_installed(\"" << *rpm_package_name << "\")" << endl;
#endif
#ifdef HARD_DEBUG
   cerr << "Calling rpmdbOpen(...)" << endl;
#endif
   // Init RPM
   rpmReadConfigFiles(NULL, NULL);
   
   if( rpmdbOpen("", &rpm_database, O_RDONLY, 0644 ) != 0 )
   {
      cerr << "Cannot open the RPM database!" << endl;
      exit(1);
   }   
#ifdef HARD_DEBUG
   else cerr << "RPM database is successfully opened!" << endl;
#endif
   // Process it here
   status = rpmdbFindPackage(rpm_database,rpm_package_name->c_str(), &matches);
   if (status == 0)
   {
      if (matches.count > 0)
      {
        cerr << "Number of matches: " << matches.count << endl;
        rpm_header = rpmdbGetRecord(rpm_database, matches.recs[0].recOffset);
        if (rpm_header)
//           cout << "HAHA" << endl;
           headerDump(rpm_header, stdout, 1, &tags);
        headerFree(rpm_header);
        dbiFreeIndexRecord(matches);
      }
    }   
   // End RPM
   rpmdbClose(rpm_database);
   return return_value;
}

int main(int argc, char **argv)
//Main
{
   string *version = new string;
   string *machine = new string;
   vector <string *> *mirrors_vector = new vector<string *>;
   vector <string *> *installed_rpms;
   vector <string *> *downloaded_rpms; // in /var/cache/grpmi
   vector <string *> *notyet_downloaded_rpms; // from updates
   
   string *test = new string("kernel");
   if (is_rpm_package_installed(test))
   {
      cout << "Package " << *test << " is found" << endl;
   }
   exit(1);
   // This won't be called until stable
   getversion_and_machine(version,machine);
   download_mirror(mirrors_vector, version, machine);
   process_mirrors_and_do_updates(mirrors_vector, version, machine);
   //delete[] mirrors_vector;
   delete mirrors_vector;
   delete version;
   delete machine;
   
   return 0;
}

Reply via email to