/* * Copyright (C) 2007-2008 Richard Hughes * Copyright (C) 2009-2012 Daniel Nicoletti * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include "apt-intf.h" #include "AptCacheFile.h" #include "apt-messages.h" #include "acqpkitstatus.h" #include "pkg_acqfile.h" #include "apt-sourceslist.h" /* static bodges */ static bool _cancel = false; static PkBackendSpawn *spawn; /** * pk_backend_get_description: */ gchar* pk_backend_get_description(PkBackend *backend) { return g_strdup("APTcc"); } /** * pk_backend_get_author: */ gchar* pk_backend_get_author(PkBackend *backend) { return g_strdup("Daniel Nicoletti "); } /** * pk_backend_initialize: */ void pk_backend_initialize(PkBackend *backend) { g_debug("APTcc Initializing"); if (pkgInitConfig(*_config) == false || pkgInitSystem(*_config, _system) == false) { g_debug("ERROR initializing backend"); } // Disable apt-listbugs as it freezes PK setenv("APT_LISTBUGS_FRONTEND", "none", 1); spawn = pk_backend_spawn_new(); pk_backend_spawn_set_name(spawn, "aptcc"); } /** * pk_backend_destroy: */ void pk_backend_destroy(PkBackend *backend) { g_debug("APTcc being destroyed"); } /** * pk_backend_get_groups: */ PkBitfield pk_backend_get_groups(PkBackend *backend) { return pk_bitfield_from_enums( PK_GROUP_ENUM_ACCESSORIES, PK_GROUP_ENUM_ADMIN_TOOLS, PK_GROUP_ENUM_COMMUNICATION, PK_GROUP_ENUM_DOCUMENTATION, PK_GROUP_ENUM_DESKTOP_GNOME, PK_GROUP_ENUM_DESKTOP_KDE, PK_GROUP_ENUM_DESKTOP_OTHER, PK_GROUP_ENUM_ELECTRONICS, PK_GROUP_ENUM_FONTS, PK_GROUP_ENUM_GAMES, PK_GROUP_ENUM_GRAPHICS, PK_GROUP_ENUM_INTERNET, PK_GROUP_ENUM_LEGACY, PK_GROUP_ENUM_LOCALIZATION, PK_GROUP_ENUM_MULTIMEDIA, PK_GROUP_ENUM_NETWORK, PK_GROUP_ENUM_OTHER, PK_GROUP_ENUM_PROGRAMMING, PK_GROUP_ENUM_PUBLISHING, PK_GROUP_ENUM_SCIENCE, PK_GROUP_ENUM_SYSTEM, -1); } /** * pk_backend_get_filters: */ PkBitfield pk_backend_get_filters(PkBackend *backend) { PkBitfield filters; filters = pk_bitfield_from_enums( PK_FILTER_ENUM_GUI, PK_FILTER_ENUM_INSTALLED, PK_FILTER_ENUM_DEVELOPMENT, PK_FILTER_ENUM_SUPPORTED, PK_FILTER_ENUM_FREE, -1); // if we have multiArch support we add the native filter if (APT::Configuration::getArchitectures(false).size() > 1) { pk_bitfield_add(filters, PK_FILTER_ENUM_ARCH); } return filters; } /** * pk_backend_get_mime_types: */ gchar* pk_backend_get_mime_types(PkBackend *backend) { return g_strdup("application/x-deb"); } /** * pk_backend_cancel: */ void pk_backend_cancel(PkBackend *backend) { AptIntf *apt = (AptIntf*) pk_backend_get_pointer(backend, "aptcc_obj"); if (apt) { apt->cancel(); } } static gboolean backend_get_depends_or_requires_thread(PkBackend *backend) { gchar **package_ids; PkBitfield filters; gchar *pi; bool recursive; package_ids = pk_backend_get_strv(backend, "package_ids"); filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); recursive = pk_backend_get_bool(backend, "recursive"); pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } bool depends = pk_backend_get_bool(backend, "get_depends"); pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList output; for (uint i = 0; i < g_strv_length(package_ids); ++i) { if (_cancel) { break; } pi = package_ids[i]; if (pk_package_id_check(pi) == false) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, pi); delete apt; return false; } const pkgCache::VerIterator &ver = apt->findPackageId(pi); if (ver.end()) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Couldn't find package"); delete apt; return false; } if (depends) { apt->getDepends(output, ver, recursive); } else { apt->getRequires(output, ver, recursive); } } // It's faster to emmit the packages here than in the matching part apt->emitPackages(output, filters); delete apt; return true; } /** * pk_backend_get_depends: */ void pk_backend_get_depends(PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive) { pk_backend_set_bool(backend, "get_depends", true); pk_backend_set_bool(backend, "recursive", recursive); pk_backend_thread_create(backend, backend_get_depends_or_requires_thread); } /** * pk_backend_get_requires: */ void pk_backend_get_requires(PkBackend *backend, PkBitfield filters, gchar **package_ids, gboolean recursive) { pk_backend_set_bool(backend, "get_depends", false); pk_backend_set_bool(backend, "recursive", recursive); pk_backend_thread_create(backend, backend_get_depends_or_requires_thread); } /** * pk_backend_get_distro_upgrades: */ void pk_backend_get_distro_upgrades(PkBackend *backend) { pk_backend_spawn_helper(spawn, "get-distro-upgrade.py", "get-distro-upgrades", NULL); } static gboolean backend_get_files_thread(PkBackend *backend) { gchar **package_ids; gchar *pi; package_ids = pk_backend_get_strv(backend, "package_ids"); if (package_ids == NULL) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "Invalid package id"); pk_backend_finished(backend); return false; } AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); for (uint i = 0; i < g_strv_length(package_ids); ++i) { pi = package_ids[i]; if (pk_package_id_check(pi) == false) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, pi); delete apt; return false; } const pkgCache::VerIterator &ver = apt->findPackageId(pi); if (ver.end()) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Couldn't find package"); delete apt; return false; } apt->emitPackageFiles(pi); } delete apt; return true; } /** * pk_backend_get_files: */ void pk_backend_get_files(PkBackend *backend, gchar **package_ids) { pk_backend_thread_create(backend, backend_get_files_thread); } static gboolean backend_get_details_thread(PkBackend *backend) { gchar **package_ids; PkRoleEnum role = pk_backend_get_role(backend); bool updateDetail = role == PK_ROLE_ENUM_GET_UPDATE_DETAIL ? true : false; package_ids = pk_backend_get_strv(backend, "package_ids"); if (package_ids == NULL) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "Invalid package id"); pk_backend_finished(backend); return false; } AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug ("Failed to create apt cache"); delete apt; return false; } if (updateDetail) { // this is needed to compare the changelog verstion to // current package using DoCmpVersion() pkgInitSystem(*_config, _system); } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList pkgs = apt->resolvePackageIds(package_ids); if (updateDetail) { apt->emitUpdateDetails(pkgs); } else { apt->emitDetails(pkgs); } delete apt; return true; } /** * pk_backend_get_update_detail: */ void pk_backend_get_update_detail(PkBackend *backend, gchar **package_ids) { pk_backend_thread_create(backend, backend_get_details_thread); } /** * pk_backend_get_details: */ void pk_backend_get_details(PkBackend *backend, gchar **package_ids) { pk_backend_thread_create(backend, backend_get_details_thread); } static gboolean backend_get_or_update_system_thread(PkBackend *backend) { PkBitfield filters; bool getUpdates; filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); getUpdates = pk_backend_get_bool(backend, "getUpdates"); pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); AptCacheFile cache(backend); int timeout = 10; // TODO test this while (cache.Open(!getUpdates) == false || cache.CheckDeps() == false) { if (getUpdates == true || (timeout <= 0)) { pk_backend_error_code(backend, PK_ERROR_ENUM_NO_CACHE, "Could not open package cache."); delete apt; return false; } else { pk_backend_set_status(backend, PK_STATUS_ENUM_WAITING_FOR_LOCK); sleep(1); timeout--; } } pk_backend_set_status(backend, PK_STATUS_ENUM_RUNNING); if (cache.DistUpgrade() == false) { cache.ShowBroken(false); g_debug("Internal error, DistUpgrade broke stuff"); delete apt; return false; } bool res = true; if (getUpdates) { PkgList updates; PkgList kept; for (pkgCache::PkgIterator pkg = cache->PkgBegin(); !pkg.end(); ++pkg) { if (cache[pkg].Upgrade() == true && cache[pkg].NewInstall() == false) { const pkgCache::VerIterator &ver = cache.findCandidateVer(pkg); if (!ver.end()) { updates.push_back(ver); } } else if (cache[pkg].Upgradable() == true && pkg->CurrentVer != 0 && cache[pkg].Delete() == false) { const pkgCache::VerIterator &ver = cache.findCandidateVer(pkg); if (!ver.end()) { kept.push_back(ver); } } } apt->emitUpdates(updates, filters); apt->emitPackages(kept, filters, PK_INFO_ENUM_BLOCKED); } else { // TODO there should be a simulate upgrade system, // tho afaik Apper and GPK don't use this res = apt->installPackages(cache, false); } delete apt; return res; } /** * pk_backend_get_updates: */ void pk_backend_get_updates(PkBackend *backend, PkBitfield filters) { pk_backend_set_bool(backend, "getUpdates", true); pk_backend_thread_create(backend, backend_get_or_update_system_thread); } /** * pk_backend_update_system: */ void pk_backend_update_system(PkBackend *backend, gboolean only_trusted) { pk_backend_set_bool(backend, "getUpdates", false); pk_backend_thread_create(backend, backend_get_or_update_system_thread); } static gboolean backend_what_provides_thread(PkBackend *backend) { PkProvidesEnum provides; PkBitfield filters; const gchar *provides_text; gchar **values; bool error = false; filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); provides = (PkProvidesEnum) pk_backend_get_uint(backend, "provides"); values = pk_backend_get_strv(backend, "search"); pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); // We can handle libraries, mimetypes and codecs if (provides == PK_PROVIDES_ENUM_SHARED_LIB || provides == PK_PROVIDES_ENUM_MIMETYPE || provides == PK_PROVIDES_ENUM_CODEC || provides == PK_PROVIDES_ENUM_ANY) { AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); g_strfreev(values); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList output; if (provides == PK_PROVIDES_ENUM_SHARED_LIB) { apt->providesLibrary(output, values); } else if (provides == PK_PROVIDES_ENUM_MIMETYPE) { apt->providesMimeType(output, values); } else if (provides == PK_PROVIDES_ENUM_CODEC) { apt->providesCodec(output, values); } else { // PK_PROVIDES_ENUM_ANY, just search for everything a package can provide apt->providesLibrary(output, values); apt->providesCodec(output, values); apt->providesMimeType(output, values); } // It's faster to emit the packages here rather than in the matching part apt->emitPackages(output, filters); delete apt; } else { provides_text = pk_provides_enum_to_string(provides); pk_backend_error_code(backend, PK_ERROR_ENUM_NOT_SUPPORTED, "Provides %s not supported", provides_text); pk_backend_finished(backend); } return true; } /** * pk_backend_what_provides */ void pk_backend_what_provides(PkBackend *backend, PkBitfield filters, PkProvidesEnum provide, gchar **values) { pk_backend_thread_create(backend, backend_what_provides_thread); } /** * pk_backend_download_packages_thread: */ static gboolean pk_backend_download_packages_thread(PkBackend *backend) { gchar **package_ids; string directory; package_ids = pk_backend_get_strv(backend, "package_ids"); directory = _config->FindDir("Dir::Cache::archives") + "partial/"; pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); // Create the progress AcqPackageKitStatus Stat(apt, backend, _cancel); // get a fetcher pkgAcquire fetcher; fetcher.Setup(&Stat); string filelist; gchar *pi; // TODO this might be useful when the item is in the cache // for (pkgAcquire::ItemIterator I = fetcher.ItemsBegin(); I < fetcher.ItemsEnd();) // { // if ((*I)->Local == true) // { // I++; // continue; // } // // // Close the item and check if it was found in cache // (*I)->Finished(); // if ((*I)->Complete == false) { // Transient = true; // } // // // Clear it out of the fetch list // delete *I; // I = fetcher.ItemsBegin(); // } for (uint i = 0; i < g_strv_length(package_ids); ++i) { pi = package_ids[i]; if (pk_package_id_check(pi) == false) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, pi); delete apt; return false; } if (_cancel) { break; } const pkgCache::VerIterator &ver = apt->findPackageId(pi); // Ignore packages that could not be found or that exist only due to dependencies. if (ver.end()) { _error->Error("Can't find this package id \"%s\".", pi); continue; } else { if(!ver.Downloadable()) { _error->Error("No downloadable files for %s," "perhaps it is a local or obsolete" "package?", pi); continue; } string storeFileName; if (apt->getArchive(&fetcher, ver, directory, storeFileName)) { Stat.addPackage(ver); } string destFile = directory + "/" + flNotDir(storeFileName); if (filelist.empty()) { filelist = destFile; } else { filelist.append(";" + destFile); } } } if (fetcher.Run() != pkgAcquire::Continue && _cancel == false) { // We failed and we did not cancel show_errors(backend, PK_ERROR_ENUM_PACKAGE_DOWNLOAD_FAILED); delete apt; return _cancel; } // send the filelist pk_backend_files(backend, NULL, filelist.c_str()); delete apt; return true; } /** * pk_backend_download_packages: */ void pk_backend_download_packages(PkBackend *backend, gchar **package_ids, const gchar *directory) { pk_backend_thread_create(backend, pk_backend_download_packages_thread); } /** * pk_backend_refresh_cache_thread: */ static gboolean pk_backend_refresh_cache_thread(PkBackend *backend) { pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_REFRESH_CACHE); // Lock the list directory FileFd Lock; if (_config->FindB("Debug::NoLocking", false) == false) { Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); if (_error->PendingError() == true) { pk_backend_error_code(backend, PK_ERROR_ENUM_CANNOT_GET_LOCK, "Unable to lock the list directory"); delete apt; return false; // return _error->Error(_("Unable to lock the list directory")); } } apt->refreshCache(); // Rebuild the cache. AptCacheFile cache(backend); if (cache.BuildCaches(true) == false) { if (_error->PendingError() == true) { show_errors(backend, PK_ERROR_ENUM_CANNOT_FETCH_SOURCES, true); } delete apt; return false; } // missing repo gpg signature would appear here if (_error->PendingError() == false && _error->empty() == false) { // TODO we need a repo warning show_warnings(backend, PK_MESSAGE_ENUM_BROKEN_MIRROR); } delete apt; return true; } /** * pk_backend_refresh_cache: */ void pk_backend_refresh_cache(PkBackend *backend, gboolean force) { pk_backend_thread_create(backend, pk_backend_refresh_cache_thread); } static gboolean pk_backend_resolve_thread(PkBackend *backend) { gchar **package_ids; PkBitfield filters; filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); package_ids = pk_backend_get_strv(backend, "package_ids"); pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } PkgList pkgs = apt->resolvePackageIds(package_ids); // It's faster to emmit the packages here rather than in the matching part apt->emitPackages(pkgs, filters); delete apt; return true; } /** * pk_backend_resolve: */ void pk_backend_resolve(PkBackend *backend, PkBitfield filters, gchar **packages) { pk_backend_thread_create(backend, pk_backend_resolve_thread); } static gboolean pk_backend_search_files_thread(PkBackend *backend) { gchar **values; PkBitfield filters; values = pk_backend_get_strv(backend, "search"); filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); pk_backend_set_allow_cancel(backend, true); // as we can only search for installed files lets avoid the opposite if (!pk_bitfield_contain(filters, PK_FILTER_ENUM_NOT_INSTALLED)) { AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList output; output = apt->searchPackageFiles(values); // It's faster to emit the packages here rather than in the matching part apt->emitPackages(output, filters); delete apt; } else { pk_backend_finished(backend); } return true; } /** * pk_backend_search_files: */ void pk_backend_search_files(PkBackend *backend, PkBitfield filters, gchar **values) { pk_backend_thread_create(backend, pk_backend_search_files_thread); } static gboolean backend_search_groups_thread(PkBackend *backend) { gchar **values; PkBitfield filters; values = pk_backend_get_strv(backend, "search"); filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); // It's faster to emmit the packages here rather than in the matching part PkgList output; output = apt->getPackagesFromGroup(values); apt->emitPackages(output, filters); pk_backend_set_percentage(backend, 100); delete apt; return true; } /** * pk_backend_search_groups: */ void pk_backend_search_groups(PkBackend *backend, PkBitfield filters, gchar **values) { pk_backend_thread_create(backend, backend_search_groups_thread); } static gboolean backend_search_package_thread(PkBackend *backend) { gchar **values; gchar *search; PkBitfield filters; values = pk_backend_get_strv(backend, "search"); search = g_strjoinv("|", values); filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); g_free(search); delete apt; return false; } if (_error->PendingError() == true) { g_free(search); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); pk_backend_set_percentage(backend, PK_BACKEND_PERCENTAGE_INVALID); pk_backend_set_allow_cancel(backend, true); PkgList output; if (pk_backend_get_bool(backend, "search_details")) { output = apt->searchPackageDetails(search); } else { output = apt->searchPackageName(search); } g_free(search); // It's faster to emmit the packages here than in the matching part apt->emitPackages(output, filters); pk_backend_set_percentage(backend, 100); delete apt; return true; } /** * pk_backend_search_names: */ void pk_backend_search_names(PkBackend *backend, PkBitfield filters, gchar **values) { pk_backend_set_bool(backend, "search_details", false); pk_backend_thread_create(backend, backend_search_package_thread); } /** * pk_backend_search_details: */ void pk_backend_search_details(PkBackend *backend, PkBitfield filters, gchar **values) { pk_backend_set_bool(backend, "search_details", true); pk_backend_thread_create(backend, backend_search_package_thread); } static gboolean backend_manage_packages_thread(PkBackend *backend) { bool simulate = false; bool remove = false; bool fileInstall = false; bool markAuto = false; bool fixBroken = false; gchar **full_paths = NULL; PkRoleEnum role = pk_backend_get_role(backend); if (role == PK_ROLE_ENUM_SIMULATE_INSTALL_FILES || role == PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES || role == PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES || role == PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES || role == PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM) { simulate = true; } if (role == PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES || role == PK_ROLE_ENUM_REMOVE_PACKAGES) { remove = true; } if (role == PK_ROLE_ENUM_SIMULATE_INSTALL_FILES || role == PK_ROLE_ENUM_INSTALL_FILES) { full_paths = pk_backend_get_strv(backend, "full_paths"); fileInstall = true; // Mark newly installed packages as auto-installed // (they're dependencies of the new local package) markAuto = true; } if (role == PK_ROLE_ENUM_SIMULATE_REPAIR_SYSTEM || role == PK_ROLE_ENUM_REPAIR_SYSTEM) { // On fix broken mode no package to remove/install is allowed fixBroken = true; } g_debug("FILE INSTALL: %i", fileInstall); pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList installPkgs, removePkgs; if (fileInstall) { // File installation EXPERIMENTAL // GDebi can not install more than one package at time if (g_strv_length(full_paths) > 1) { pk_backend_error_code(backend, PK_ERROR_ENUM_NOT_SUPPORTED, "The backend can only proccess one file at time."); delete apt; return false; } // get the list of packages to install if (!apt->markFileForInstall(full_paths[0], installPkgs, removePkgs)) { delete apt; return false; } cout << "installPkgs.size: " << installPkgs.size() << endl; cout << "removePkgs.size: " << removePkgs.size() << endl; } else if (!fixBroken) { // Resolve the given packages gchar **package_ids = pk_backend_get_strv(backend, "package_ids"); if (remove) { removePkgs = apt->resolvePackageIds(package_ids); } else { installPkgs = apt->resolvePackageIds(package_ids); } if (removePkgs.size() == 0 && installPkgs.size() == 0) { pk_backend_error_code(backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "Could not find package(s)"); delete apt; return false; } } // Install/Update/Remove packages, or just simulate if (!apt->runTransaction(installPkgs, removePkgs, simulate, markAuto, fixBroken)) { // Print transaction errors g_debug("AptIntf::runTransaction() failed: ", _error->PendingError()); delete apt; return false; } if (fileInstall) { // Now perform the installation! gchar *path; for (uint i = 0; i < g_strv_length(full_paths); ++i) { if (_cancel) { break; } path = full_paths[i]; if (!apt->installFile(path, simulate)) { cout << "Installation of DEB file " << path << " failed." << endl; delete apt; return false; } } } delete apt; return true; } /** * pk_backend_simulate_install_packages: */ void pk_backend_simulate_install_packages(PkBackend *backend, gchar **packages) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_install_packages: */ void pk_backend_install_packages(PkBackend *backend, gboolean only_trusted, gchar **package_ids) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_simulate_update_packages: */ void pk_backend_simulate_update_packages(PkBackend *backend, gchar **packages) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_update_packages: */ void pk_backend_update_packages(PkBackend *backend, gboolean only_trusted, gchar **package_ids) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_simulate_install_files: */ void pk_backend_simulate_install_files(PkBackend *backend, gchar **full_paths) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_install_files: */ void pk_backend_install_files(PkBackend *backend, gboolean only_trusted, gchar **full_paths) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_simulate_remove_packages: */ void pk_backend_simulate_remove_packages(PkBackend *backend, gchar **packages, gboolean autoremove) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_remove_packages: */ void pk_backend_remove_packages(PkBackend *backend, gchar **package_ids, gboolean allow_deps, gboolean autoremove) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_repair_system: */ void pk_backend_repair_system(PkBackend *backend, gboolean only_trusted) { pk_backend_thread_create(backend, backend_manage_packages_thread); } /** * pk_backend_simulate_repair_system: */ void pk_backend_simulate_repair_system(PkBackend *backend) { pk_backend_thread_create(backend, backend_manage_packages_thread); } static gboolean backend_repo_manager_thread(PkBackend *backend) { // list PkBitfield filters; bool notDevelopment; // enable const gchar *repo_id; bool enabled; bool found = false; // generic const char *const salt = "$1$/iSaq7rB$EoUw5jJPPvAPECNaaWzMK/"; bool list = pk_backend_get_bool(backend, "list"); if (list) { pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); notDevelopment = pk_bitfield_contain(filters, PK_FILTER_ENUM_NOT_DEVELOPMENT); } else { pk_backend_set_status(backend, PK_STATUS_ENUM_REQUEST); repo_id = pk_backend_get_string(backend, "repo_id"); enabled = pk_backend_get_bool(backend, "enabled"); } SourcesList _lst; if (_lst.ReadSources() == false) { _error-> Warning("Ignoring invalid record(s) in sources.list file!"); //return false; } if (_lst.ReadVendors() == false) { _error->Error("Cannot read vendors.list file"); show_errors(backend, PK_ERROR_ENUM_FAILED_CONFIG_PARSING); pk_backend_finished(backend); return false; } for (SourcesListIter it = _lst.SourceRecords.begin(); it != _lst.SourceRecords.end(); ++it) { if ((*it)->Type & SourcesList::Comment) { continue; } string Sections; for (unsigned int j = 0; j < (*it)->NumSections; ++j) { Sections += (*it)->Sections[j]; Sections += " "; } if (notDevelopment && ((*it)->Type & SourcesList::DebSrc || (*it)->Type & SourcesList::RpmSrc || (*it)->Type & SourcesList::RpmSrcDir || (*it)->Type & SourcesList::RepomdSrc)) { continue; } string repo; repo = (*it)->GetType(); repo += " " + (*it)->VendorID; repo += " " + (*it)->URI; repo += " " + (*it)->Dist; repo += " " + Sections; gchar *hash; const gchar allowedChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; hash = crypt(repo.c_str(), salt); g_strcanon(hash, allowedChars, 'D'); string repoId(hash); if (list) { pk_backend_repo_detail(backend, repoId.c_str(), repo.c_str(), !((*it)->Type & SourcesList::Disabled)); } else { if (repoId.compare(repo_id) == 0) { if (enabled) { (*it)->Type = (*it)->Type & ~SourcesList::Disabled; } else { (*it)->Type |= SourcesList::Disabled; } found = true; break; } } } if (!list) { if (!found) { _error->Error("Could not found the repositorie"); show_errors(backend, PK_ERROR_ENUM_REPO_NOT_AVAILABLE); } else if (!_lst.UpdateSources()) { _error->Error("Could not update sources file"); show_errors(backend, PK_ERROR_ENUM_CANNOT_WRITE_REPO_CONFIG); } } pk_backend_finished(backend); return true; } /** * pk_backend_get_repo_list: */ void pk_backend_get_repo_list(PkBackend *backend, PkBitfield filters) { pk_backend_set_bool(backend, "list", true); pk_backend_thread_create(backend, backend_repo_manager_thread); } /** * pk_backend_repo_enable: */ void pk_backend_repo_enable(PkBackend *backend, const gchar *rid, gboolean enabled) { pk_backend_set_bool(backend, "list", false); pk_backend_thread_create(backend, backend_repo_manager_thread); } static gboolean backend_get_packages_thread(PkBackend *backend) { PkBitfield filters; filters = (PkBitfield) pk_backend_get_uint(backend, "filters"); pk_backend_set_allow_cancel(backend, true); AptIntf *apt = new AptIntf(backend, _cancel); pk_backend_set_pointer(backend, "aptcc_obj", apt); if (apt->init()) { g_debug("Failed to create apt cache"); delete apt; return false; } pk_backend_set_status(backend, PK_STATUS_ENUM_QUERY); PkgList output; output = apt->getPackages(); // It's faster to emmit the packages rather here than in the matching part apt->emitPackages(output, filters); delete apt; return true; } /** * pk_backend_get_packages: */ void pk_backend_get_packages(PkBackend *backend, PkBitfield filter) { pk_backend_thread_create(backend, backend_get_packages_thread); } /** * pk_backend_get_categories: */ /* TODO void pk_backend_get_categories (PkBackend *backend) { pk_backend_thread_create (backend, pk_backend_get_categories_thread); } */ /** * pk_backend_get_roles: */ PkBitfield pk_backend_get_roles(PkBackend *backend) { PkBitfield roles; roles = pk_bitfield_from_enums( PK_ROLE_ENUM_CANCEL, PK_ROLE_ENUM_GET_DEPENDS, PK_ROLE_ENUM_GET_DETAILS, PK_ROLE_ENUM_GET_FILES, PK_ROLE_ENUM_GET_REQUIRES, PK_ROLE_ENUM_GET_PACKAGES, PK_ROLE_ENUM_WHAT_PROVIDES, PK_ROLE_ENUM_GET_UPDATES, PK_ROLE_ENUM_GET_UPDATE_DETAIL, PK_ROLE_ENUM_INSTALL_PACKAGES, PK_ROLE_ENUM_INSTALL_SIGNATURE, PK_ROLE_ENUM_REFRESH_CACHE, PK_ROLE_ENUM_REMOVE_PACKAGES, PK_ROLE_ENUM_DOWNLOAD_PACKAGES, PK_ROLE_ENUM_RESOLVE, PK_ROLE_ENUM_SEARCH_DETAILS, PK_ROLE_ENUM_SEARCH_FILE, PK_ROLE_ENUM_SEARCH_GROUP, PK_ROLE_ENUM_SEARCH_NAME, PK_ROLE_ENUM_UPDATE_PACKAGES, PK_ROLE_ENUM_UPDATE_SYSTEM, PK_ROLE_ENUM_GET_REPO_LIST, PK_ROLE_ENUM_REPO_ENABLE, PK_ROLE_ENUM_SIMULATE_INSTALL_PACKAGES, PK_ROLE_ENUM_SIMULATE_UPDATE_PACKAGES, PK_ROLE_ENUM_SIMULATE_REMOVE_PACKAGES, -1); // only add GetDistroUpgrades if the binary is present if (g_file_test(PREUPGRADE_BINARY, G_FILE_TEST_EXISTS)) { pk_bitfield_add(roles, PK_ROLE_ENUM_GET_DISTRO_UPGRADES); } // only add GetDistroUpgrades if the binary is present if (g_file_test(GDEBI_BINARY, G_FILE_TEST_EXISTS)) { pk_bitfield_add(roles, PK_ROLE_ENUM_SIMULATE_INSTALL_FILES); pk_bitfield_add(roles, PK_ROLE_ENUM_INSTALL_FILES); } return roles; }