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; }
