2 * This file is part of the hildon-application-manager.
4 * Parts of this file are derived from apt. Apt is copyright 1997,
5 * 1998, 1999 Jason Gunthorpe and others.
7 * Copyright (C) 2005, 2006, 2007, 2008 Nokia Corporation. All Rights reserved.
9 * Contact: Marius Vollmer <marius.vollmer@nokia.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License version
13 * 2 as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 /* This is the process that runs as root and does all the work.
29 It is started from a separate program (as opposed to being forked
30 directly from the GUI process) since that allows us to use sudo for
33 This process communicates with the GUI process via some named pipes
34 that are created by that process. You can't really use it from the
37 It will output stuff to stdin and stderr, which the GUI process is
38 supposed to catch and put into its log.
40 The program tries hard not to exit prematurely. Once the
41 connection between the GUI process and this process has been
42 established, the apt-worker is supposed to stick around until that
43 connection is broken, even if it has to fail every request send to
44 it. This allows the user to try and fix the system after something
45 went wrong, although the options are limited, of course. The best
46 example is a corrupted /etc/apt/sources.list: even tho you can't do
47 anything related to packages, you still need the apt-worker to
48 correct /etc/apt/sources.list itself in the UI.
56 #include <sys/ioctl.h>
58 #include <sys/statvfs.h>
59 #include <sys/types.h>
60 #include <sys/fcntl.h>
68 #include <apt-pkg/init.h>
69 #include <apt-pkg/error.h>
70 #include <apt-pkg/tagfile.h>
71 #include <apt-pkg/pkgcache.h>
72 #include <apt-pkg/pkgcachegen.h>
73 #include <apt-pkg/sourcelist.h>
74 #include <apt-pkg/acquire.h>
75 #include <apt-pkg/acquire-item.h>
76 #include <apt-pkg/cachefile.h>
77 #include <apt-pkg/strutl.h>
78 #include <apt-pkg/sptr.h>
79 #include <apt-pkg/packagemanager.h>
80 #include <apt-pkg/deblistparser.h>
81 #include <apt-pkg/debversion.h>
82 #include <apt-pkg/dpkgpm.h>
83 #include <apt-pkg/debsystem.h>
84 #include <apt-pkg/orderlist.h>
85 #include <apt-pkg/algorithms.h>
86 #include <apt-pkg/metaindex.h>
87 #include <apt-pkg/debmetaindex.h>
88 #include <apt-pkg/policy.h>
89 #include <apt-pkg/md5.h>
90 #include <apt-pkg/sha1.h>
91 #include <apt-pkg/sha256.h>
93 #include <glib/glist.h>
94 #include <glib/gstring.h>
95 #include <glib/gstrfuncs.h>
96 #include <glib/gmem.h>
97 #include <glib/gfileutils.h>
98 #include <glib/gslist.h>
99 #include <glib/gkeyfile.h>
101 #include "apt-worker-proto.h"
102 #include "confutils.h"
104 #include "update-notifier-conf.h"
108 static void save_operation_record (const char *package,
109 const char *download_root);
110 static void erase_operation_record ();
111 static xexp *read_operation_record ();
113 /* Table of contents.
115 COMPILE-TIME CONFIGURATION
117 RUN-TIME CONFIGURATION
121 COMMUNICATING WITH THE FRONTEND
123 STARTUP AND COMMAND DISPATCHER
129 /** COMPILE-TIME CONFIGURATION
132 /* Defining this to non-zero will also recognize packages in the
133 "maemo" section as user packages. There are still packages
134 floating around that follow this old rule.
136 #define ENABLE_OLD_MAEMO_SECTION_TEST 1
138 /* Requests up to this size are put into a stack allocated buffer.
140 #define FIXED_REQUEST_BUF_SIZE 4096
142 /* The location where we keep our lock.
144 #define APT_WORKER_LOCK "/var/lib/hildon-application-manager/apt-worker-lock"
146 /* Temporary catalogues and temporary sources.list */
147 #define TEMP_CATALOGUE_CONF "/var/lib/hildon-application-manager/catalogues.temp"
148 #define TEMP_APT_SOURCE_LIST "/etc/apt/sources.list.d/hildon-application-manager-temp.list"
150 /* APT CACHE ARCHIVES DIRECTORIES */
151 #define DEFAULT_DIR_CACHE_ARCHIVES "archives/"
152 #define ALT_DIR_CACHE_ARCHIVES ".apt-archive-cache/"
154 /* Files related to the 'check for updates' process */
155 #define FAILED_CATALOGUES_FILE "/var/lib/hildon-application-manager/failed-catalogues"
157 /* Domain names associated with "OS" and "Nokia" updates */
158 #define OS_UPDATES_DOMAIN_NAME "nokia-system"
159 #define NOKIA_UPDATES_DOMAIN_NAME "nokia-certified"
161 /* Where we keep a journal of the current operation
163 #define CURRENT_OPERATION_FILE "/var/lib/hildon-application-manager/current-operation"
165 /* You know what this means.
168 /*#define DEBUG_COMMANDS*/
171 #define DBG log_stderr
176 /** RUN-TIME CONFIGURATION
179 /* Setting this to true will break the lock of the dpkg status
180 database if necessary.
182 bool flag_break_locks = false;
184 /* Setting this to true will not ignore package versions from a wrong
187 bool flag_allow_wrong_domains = false;
189 /* Setting this to true will use the normal apt-get algorithms for
190 installing/removing packages instead of our home-grown ones.
192 bool flag_use_apt_algorithms = false;
194 /* Setting this to false will not use MMC to save the packages when
197 bool flag_download_packages_to_mmc = false;
199 /** GENERAL UTILITIES
203 log_stderr (const char *fmt, ...)
206 va_start (args, fmt);
207 fprintf (stderr, "apt-worker: ");
208 vfprintf (stderr, fmt, args);
210 fprintf (stderr, "\n");
213 /** APT WORKER MULTI STATE MANAGEMENT
216 /* Inside this process, domains are identified with small integers.
219 typedef signed char domain_t;
228 xexp *domain_conf = NULL;
229 domain_info *domains = NULL;
230 int domains_number = 0;
231 time_t domains_last_modified = -1;
233 #define DOMAIN_INVALID -1
234 #define DOMAIN_UNSIGNED 0
235 #define DOMAIN_SIGNED 1
237 #define DOMAIN_DEFAULT DOMAIN_UNSIGNED
240 file_last_modified (const char *file_name)
244 if (stat (file_name, &buf) == -1)
246 perror ("error retriving file info");
257 xexp_free (domain_conf);
259 domain_conf = read_domains ();
263 n_domains += xexp_length (domain_conf);
265 domains = new domain_info[n_domains];
267 /* Setup the two implicit domains.
269 domains[0].name = "unsigned";
270 domains[0].conf = NULL;
271 domains[0].trust_level = 0;
272 domains[0].is_certified = false;
274 domains[1].name = "signed";
275 domains[1].conf = NULL;
276 domains[1].trust_level = 1;
277 domains[1].is_certified = false;
282 for (xexp *d = xexp_first (domain_conf); d; d = xexp_rest (d))
284 if (!xexp_is (d, "domain"))
287 domains[i].name = xexp_aref_text (d, "name");
288 if (domains[i].name == NULL)
291 domains[i].trust_level = xexp_aref_int (d, "trust-level", 2);
292 domains[i].is_certified = xexp_aref_bool (d, "certified");
299 /* Update domains number and last modified timestamp */
301 domains_last_modified = file_last_modified (PACKAGE_DOMAINS);
305 find_domain_by_tag (const char *tag, const char *val)
307 for (int i = 0; i < domains_number; i++)
309 if (domains[i].conf == NULL)
312 for (xexp *x = xexp_aref (domains[i].conf, tag);
314 x = xexp_aref_rest (x, tag))
316 if (xexp_is_text (x) && g_str_has_suffix (xexp_text (x), val))
321 return DOMAIN_SIGNED;
325 find_domain_by_key (const char *key)
327 return find_domain_by_tag ("key", key);
331 find_domain_by_uri (const char *uri)
333 return find_domain_by_tag ("uri", uri);
338 /* This class implements a global static cache managing for
344 static void Initialize ();
345 static AptWorkerCache * GetCurrent ();
347 bool init_cache_after_request;
349 pkgDepCache::ActionGroup *action_group;
350 static AptWorkerCache *current;
351 static bool global_initialized;
354 AptWorkerCache *AptWorkerCache::current = 0;
356 bool AptWorkerCache::global_initialized = false;
358 AptWorkerCache::AptWorkerCache ()
359 : init_cache_after_request (false), cache (0)
364 AptWorkerCache::GetCurrent (void)
369 /* Initialization of apt worker cache. It initializes the
370 * APT subsystem, and then gets the current instance. */
372 AptWorkerCache::Initialize (void)
374 if (!global_initialized)
376 if (pkgInitConfig (*_config) == false ||
377 pkgInitSystem (*_config, _system) == false)
379 _error->DumpErrors ();
383 _config->Set ("DPkg::Options::", "--force-confold");
384 _config->Set ("Dir::Log", "var/log");
385 _config->Set ("Dir::Log::Terminal", "");
386 global_initialized = true;
389 current = new AptWorkerCache;
392 /* This struct describes some status flags for specific packages.
393 * myCacheFile includes an array of these, with an entry per
396 typedef struct extra_info_struct
401 domain_t cur_domain, new_domain;
404 class myPolicy : public pkgPolicy {
407 myCacheFile *my_cache_file;
411 myPolicy (pkgCache *Owner, myCacheFile *cache_file)
412 : pkgPolicy (Owner), my_cache_file (cache_file)
414 pf_domain = new int[Owner->Head().PackageFileCount];
419 virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator Pkg);
422 class myCacheFile : public pkgCacheFile {
425 bool Open (OpProgress &Progress, bool WithLock = true);
427 void load_extra_info ();
428 void save_extra_info ();
430 extra_info_struct *extra_info;
443 static void set_sources_for_get_domain (pkgSourceList *sources);
444 static int get_domain (pkgIndexFile*);
447 myPolicy::InitDomains ()
449 for (pkgCache::PkgFileIterator I = Cache->FileBegin();
450 I != Cache->FileEnd(); I++)
451 pf_domain[I->ID] = DOMAIN_UNSIGNED;
454 if (!List.ReadMainList ())
456 _error->DumpErrors();
460 set_sources_for_get_domain (&List);
462 for (pkgCache::PkgFileIterator I = Cache->FileBegin();
463 I != Cache->FileEnd(); I++)
465 // Locate the associated index files so we can find its domain
467 if (List.FindIndex(I,Indx) || _system->FindIndex(I,Indx))
469 pf_domain[I->ID] = get_domain (Indx);
470 DBG ("%s: %s", Indx->Describe(true).c_str(),
471 domains[pf_domain[I->ID]].name);
475 set_sources_for_get_domain (NULL);
478 static bool domain_dominates_or_is_equal (int a, int b);
480 pkgCache::VerIterator
481 myPolicy::GetCandidateVer (pkgCache::PkgIterator Pkg)
483 // Look for a package pin and evaluate it.
484 signed Max = GetPriority(Pkg);
485 pkgCache::VerIterator Pref = GetMatch(Pkg);
487 /* Falling through to the default version.. Setting Max to zero
488 effectively excludes everything <= 0 which are the non-automatic
489 priorities.. The status file is given a prio of 100 which will exclude
490 not-automatic sources, except in a single shot not-installed mode.
491 The second pseduo-status file is at prio 1000, above which will permit
492 the user to force-downgrade things.
494 The user pin is subject to the same priority rules as default
495 selections. Thus there are two ways to create a pin - a pin that
496 tracks the default when the default is taken away, and a permanent
497 pin that stays at that setting.
499 for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; Ver++)
501 for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
504 /* If this is the status file, and the current version is not the
505 version in the status file (ie it is not installed, or somesuch)
506 then it is not a candidate for installation, ever. This weeds
507 out bogus entries that may be due to config-file states, or
509 if ((VF.File()->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource &&
510 Pkg.CurrentVer() != Ver)
513 /* If requested, skip versions from the wrong domain, but
517 if (!flag_allow_wrong_domains
518 && ((VF.File()->Flags & pkgCache::Flag::NotSource)
519 != pkgCache::Flag::NotSource))
521 if (!domain_dominates_or_is_equal
522 (pf_domain[VF.File()->ID],
523 my_cache_file->extra_info[Pkg->ID].cur_domain))
525 log_stderr ("Ignoring version from wrong domain: %s %s",
526 Pkg.Name(), Ver.VerStr());
527 log_stderr (" %s", VF.File().FileName());
532 signed Prio = PFPriority[VF.File()->ID];
540 if (Pkg.CurrentVer() == Ver && Max < 1000)
542 /* Elevate our current selection (or the status file itself)
543 to the Pseudo-status priority. */
544 if (Pref.end() == true)
548 // Fast path optimize.
549 if (StatusOverride == false)
557 myCacheFile::Open (OpProgress &Progress, bool WithLock)
559 if (BuildCaches(Progress,WithLock) == false)
563 myPolicy *pol = new myPolicy (Cache, this);
565 if (_error->PendingError() == true)
567 if (ReadPinFile(*Policy) == false)
574 // Create the dependency cache
575 DCache = new pkgDepCache(Cache,Policy);
576 if (_error->PendingError() == true)
579 DCache->Init(&Progress);
581 if (_error->PendingError() == true)
587 /* Save the 'extra_info' of the cache. We first make a copy of the
588 Auto flags in our own extra_info storage so that CACHE_RESET
589 will reset the Auto flags to the state last saved with this
594 myCacheFile::save_extra_info ()
596 if (mkdir ("/var/lib/hildon-application-manager", 0777) < 0
599 log_stderr ("/var/lib/hildon-application-manager: %m");
603 FILE *f = fopen ("/var/lib/hildon-application-manager/autoinst", "w");
606 pkgDepCache &cache = *DCache;
608 for (pkgCache::PkgIterator pkg = cache.PkgBegin(); !pkg.end (); pkg++)
610 if (cache[pkg].Flags & pkgCache::Flag::Auto)
612 extra_info[pkg->ID].autoinst = true;
613 fprintf (f, "%s\n", pkg.Name ());
616 extra_info[pkg->ID].autoinst = false;
623 for (domain_t i = 0; i < domains_number; i++)
626 g_strdup_printf ("/var/lib/hildon-application-manager/domain.%s",
629 FILE *f = fopen (name, "w");
632 pkgDepCache &cache = *DCache;
634 for (pkgCache::PkgIterator pkg = cache.PkgBegin();
637 if (extra_info[pkg->ID].cur_domain == i)
638 fprintf (f, "%s\n", pkg.Name ());
647 /* Load the 'extra_info'. You need to call CACHE_RESET to
648 transfer the auto flag into the actual cache. */
651 myCacheFile::load_extra_info ()
653 pkgCache &cache = *Cache;
655 int package_count = cache.Head().PackageCount;
657 extra_info = new extra_info_struct[package_count];
659 for (int i = 0; i < package_count; i++)
661 extra_info[i].autoinst = false;
662 extra_info[i].cur_domain = DOMAIN_DEFAULT;
665 FILE *f = fopen ("/var/lib/hildon-application-manager/autoinst", "r");
672 while ((n = getline (&line, &len, f)) != -1)
674 if (n > 0 && line[n-1] == '\n')
677 pkgCache::PkgIterator pkg = cache.FindPkg (line);
680 DBG ("auto: %s", pkg.Name ());
681 extra_info[pkg->ID].autoinst = true;
689 for (domain_t i = 0; i < domains_number; i++)
692 g_strdup_printf ("/var/lib/hildon-application-manager/domain.%s",
695 FILE *f = fopen (name, "r");
702 while ((n = getline (&line, &len, f)) != -1)
704 if (n > 0 && line[n-1] == '\n')
707 pkgCache::PkgIterator pkg = cache.FindPkg (line);
710 // DBG ("%s: %s (%d)", domains[i].name, pkg.Name (), pkg->ID);
711 extra_info[pkg->ID].cur_domain = i;
723 /* ALLOC_BUF and FREE_BUF can be used to manage a temporary buffer of
724 arbitrary size without having to allocate memory from the heap when
727 The way to use them is to allocate a buffer of 'normal' but fixed
728 size statically or on the stack and the use ALLOC_BUF when the
729 actual size of the needed buffer is known. If the actual size is
730 small enough, ALLOC_BUF will use the fixed size buffer, otherwise
731 it will allocate a new one. FREE_BUF will free that buffer.
734 /* Return a pointer to LEN bytes of free storage. When LEN is less
735 than or equal to FIXED_BUF_LEN return FIXED_BUF, otherwise a newly
736 allocated block of memory is returned. ALLOC_BUF never return
740 alloc_buf (int len, char *fixed_buf, int fixed_buf_len)
742 if (len <= fixed_buf_len)
745 return new char[len];
748 /* Free the block of memory pointed to by BUF if it is different from
752 free_buf (char *buf, char *fixed_buf)
754 if (buf != fixed_buf)
758 /* Open FILENAME with FLAGS, or die.
761 must_open (char *filename, int flags)
763 int fd = open (filename, flags);
773 must_set_flags (int fd, int flags)
775 if (fcntl (fd, F_SETFL, flags) < 0)
777 perror ("apt-worker fcntl");
783 block_for_read (int fd)
789 if (select (fd+1, &set, NULL, NULL, NULL) < 0)
791 perror ("apt-worker select");
800 if (read (fd, &byte, 1) == 1)
805 /* DRAIN_FD reads all bytes from FD that are available.
810 while (read_byte (fd) >= 0)
814 /* Get a lock as with GetLock from libapt-pkg, breaking it if needed
815 and allowed by flag_break_locks.
817 We do this so that the users can not lock themselves out. We break
818 locks instead of not locking since noisily breaking a lock is
819 better than silently corrupting stuff.
822 ForceLock (string File, bool Errors = true)
824 int lock_fd = GetLock (File, false);
828 if (flag_break_locks)
830 int res = unlink (File.c_str ());
831 if (res < 0 && errno != ENOENT)
832 log_stderr ("Can't remove %s: %m", File.c_str ());
834 log_stderr ("Forcing %s", File.c_str ());
837 return GetLock (File, Errors);
841 /** COMMUNICATING WITH THE FRONTEND.
843 The communication with the frontend happens over four
844 unidirectional fifos: requests are read from INPUT_FD and responses
845 are sent back via OUTPUT_FD. No new request is read until the
846 response to the current one has been completely sent.
848 The data read from INPUT_FD must follow the request format
849 specified in <apt-worker-proto.h>. The data written to OUTPUT_FD
850 follows the response format specified there.
852 The CANCEL_FD is polled periodically and when something is
853 available to be read, the current operation is aborted. There is
854 currently no meaning defined for the actual bytes that are sent,
855 the mere arrival of a byte triggers the abort.
857 When using the libapt-pkg PackageManager, it is configured in such
858 a way that it sends it "pmstatus:" message lines to STATUS_FD.
859 Other asynchronous status reports are sent as spontaneous
860 APTCMD_STATUS responses via OUTPUT_FD. 'Spontaneous' should mean
861 that no request is required to receive APTCMD_STATUS responses. In
862 fact, APTCMD_STATUS requests are treated as an error by the
865 Logging and debug output, and output from dpkg and the maintainer
866 scripts appears normally on stdout and stderr of the apt-worker
870 int input_fd, output_fd, status_fd, cancel_fd;
872 /* MUST_READ and MUST_WRITE read and write blocks of raw bytes from
873 INPUT_FD and to OUTPUT_FD. If they return, they have succeeded and
874 read or written the whole block.
878 must_read (void *buf, size_t n)
884 r = read (input_fd, buf, n);
887 perror ("apt-worker read");
896 buf = ((char *)buf) + r;
901 must_write (void *buf, ssize_t n)
903 if (n > 0 && write (output_fd, buf, n) != n)
905 perror ("apt-worker write");
910 /* This function sends a response on OUTPUT_FD with the given CMD and
911 SEQ. It either succeeds or does not return.
914 send_response_raw (int cmd, int seq, void *response, size_t len)
916 apt_response_header res = { cmd, seq, len };
917 must_write (&res, sizeof (res));
918 must_write (response, len);
921 /* Fabricate and send a APTCMD_STATUS response. Parameters OP,
922 ALREADY, and TOTAL are as specified in apt-worker-proto.h.
924 A status response is only sent when there is enough change since
925 the last time. The following counts as 'enough': ALREADY has
926 decreased, it has increased by more than MIN_CHANGE, it is equal to
927 -1, LAST_TOTAL has changed, or OP has changed.
931 send_status (int op, int already, int total, int min_change)
934 static apt_proto_encoder status_response;
936 static int last_already;
937 static int last_total;
940 || already < last_already
941 || already >= last_already + min_change
942 || total != last_total
945 last_already = already;
949 status_response.reset ();
950 status_response.encode_int (op);
951 status_response.encode_int (already);
952 status_response.encode_int (total);
953 send_response_raw (APTCMD_STATUS, -1,
954 status_response.get_buf (),
955 status_response.get_len ());
960 /** STARTUP AND COMMAND DISPATCHER.
963 /* Since the apt-worker only works on a single command at a time, we
964 use two global encoder and decoder engines that manage the
965 parameters of the request and the result values of the response.
967 Handlers of specific commands will read the parameters from REQUEST
968 and put the results into RESPONSE. The command dispatcher will
969 prepare REQUEST before calling the command handler and ship out
970 RESPONSE after it returned.
972 apt_proto_decoder request;
973 apt_proto_encoder response;
975 void cmd_get_package_list ();
976 void cmd_get_package_info ();
977 void cmd_get_package_details ();
978 int cmd_check_updates (bool with_status = true);
979 void cmd_get_catalogues ();
980 void cmd_set_catalogues ();
981 void cmd_add_temp_catalogues ();
982 void cmd_rm_temp_catalogues ();
983 void cmd_install_check ();
984 void cmd_download_package ();
985 void cmd_install_package ();
986 void cmd_remove_check ();
987 void cmd_remove_package ();
989 void cmd_get_file_details ();
990 void cmd_install_file ();
991 void cmd_save_backup_data ();
992 void cmd_get_system_update_packages ();
994 void cmd_set_options ();
997 int cmdline_check_updates (char **argv);
998 int cmdline_rescue (char **argv);
1000 /** MANAGEMENT FOR FAILED CATALOGUES LOG FILE
1003 /* Since it's needed to save the full report (including errors) after
1004 any refresh of the catalogues list, four functions were implemented
1005 to take care of the writting/reading to/from disk process.
1008 static void save_failed_catalogues (xexp *catalogues);
1009 static xexp *load_failed_catalogues ();
1010 static void clean_failed_catalogues ();
1011 static void clean_temp_catalogues ();
1012 static xexp *merge_catalogues_with_errors (xexp *catalogues);
1014 /** MANAGEMENT OF FILE WITH INFO ABOUT AVAILABLE UPDATES */
1016 static void write_available_updates_file ();
1018 /** MAPPING FUNCTION TO FILTER ERROR DETAILS
1019 IN CATALOGUES CONFIGURATION FILE
1021 static xexp *map_catalogue_error_details (xexp *x);
1024 /* Commands can request the package cache to be refreshed by calling
1025 NEED_CACHE_INIT before they return. The cache will then be
1026 reconstructed after sending the response and before starting to
1027 handle the next command. In this way, the cache reconstruction
1028 happens in the background.
1030 XXX - However, APTCMD_STATUS messages are still being sent when the
1031 cache is reconstructed in the background and the UI has some
1032 ugly logic to deal with that.
1035 void cache_init (bool with_status = true);
1040 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1041 awc->init_cache_after_request = true;
1044 #ifdef DEBUG_COMMANDS
1045 static const char *cmd_names[] = {
1050 "GET_PACKAGE_DETAILS",
1054 "ADD_TEMP_CATALOGUES",
1055 "RM_TEMP_CATALOGUES",
1064 "GET_SYSTEM_UPDATE_PACKAGES",
1074 apt_request_header req;
1075 char stack_reqbuf[FIXED_REQUEST_BUF_SIZE];
1077 AptWorkerCache * awc = 0;
1078 time_t last_modified = -1;
1080 must_read (&req, sizeof (req));
1082 #ifdef DEBUG_COMMANDS
1083 DBG ("got req %s/%d/%d", cmd_names[req.cmd], req.seq, req.len);
1086 reqbuf = alloc_buf (req.len, stack_reqbuf, FIXED_REQUEST_BUF_SIZE);
1087 must_read (reqbuf, req.len);
1089 drain_fd (cancel_fd);
1091 request.reset (reqbuf, req.len);
1094 awc = AptWorkerCache::GetCurrent ();
1095 awc->init_cache_after_request = false; // let's reset it now
1097 /* Re-read domains conf file if modified */
1098 last_modified = file_last_modified (PACKAGE_DOMAINS);
1099 if (last_modified != domains_last_modified)
1100 read_domain_conf ();
1109 case APTCMD_GET_PACKAGE_LIST:
1110 cmd_get_package_list ();
1113 case APTCMD_GET_PACKAGE_INFO:
1114 cmd_get_package_info ();
1117 case APTCMD_GET_PACKAGE_DETAILS:
1118 cmd_get_package_details ();
1121 case APTCMD_CHECK_UPDATES:
1122 cmd_check_updates ();
1125 case APTCMD_GET_CATALOGUES:
1126 cmd_get_catalogues ();
1129 case APTCMD_SET_CATALOGUES:
1130 cmd_set_catalogues ();
1133 case APTCMD_ADD_TEMP_CATALOGUES:
1134 cmd_add_temp_catalogues ();
1137 case APTCMD_RM_TEMP_CATALOGUES:
1138 cmd_rm_temp_catalogues ();
1141 case APTCMD_INSTALL_CHECK:
1142 cmd_install_check ();
1145 case APTCMD_DOWNLOAD_PACKAGE:
1146 cmd_download_package ();
1149 case APTCMD_INSTALL_PACKAGE:
1150 cmd_install_package ();
1153 case APTCMD_REMOVE_CHECK:
1154 cmd_remove_check ();
1157 case APTCMD_REMOVE_PACKAGE:
1158 cmd_remove_package ();
1165 case APTCMD_GET_FILE_DETAILS:
1166 cmd_get_file_details ();
1169 case APTCMD_INSTALL_FILE:
1170 cmd_install_file ();
1173 case APTCMD_SAVE_BACKUP_DATA:
1174 cmd_save_backup_data ();
1177 case APTCMD_GET_SYSTEM_UPDATE_PACKAGES:
1178 cmd_get_system_update_packages ();
1185 case APTCMD_SET_OPTIONS:
1189 case APTCMD_SET_ENV:
1194 log_stderr ("unrecognized request: %d", req.cmd);
1198 _error->DumpErrors ();
1200 send_response_raw (req.cmd, req.seq,
1201 response.get_buf (), response.get_len ());
1203 #ifdef DEBUG_COMMANDS
1204 DBG ("sent resp %s/%d/%d",
1205 cmd_names[req.cmd], req.seq, response.get_len ());
1208 free_buf (reqbuf, stack_reqbuf);
1210 if (awc->init_cache_after_request)
1213 _error->DumpErrors ();
1217 static int index_trust_level_for_package (pkgIndexFile *index,
1218 const pkgCache::VerIterator &ver);
1220 static const char *lc_messages;
1225 fprintf (stderr, "Usage: apt-worker check-for-updates [http_proxy]\n");
1226 fprintf (stderr, " apt-worker rescue [package] [archives]\n");
1230 /* Try to get the lock specified by FILE. If this fails because
1231 someone else has the lock, a string is returned with the content of
1232 the file. Otherwise MY_CONTENT is written to the file and NULL is
1235 Other kinds of failures (out of space, insufficient permissions,
1236 etc) will terminate this process.
1238 The lock will be released when this process exits.
1242 try_lock (const char *file, const char *my_content)
1244 int lock_fd = open (file, O_RDWR | O_CREAT, 0640);
1247 log_stderr ("Can't open %s: %m", file);
1251 SetCloseExec (lock_fd, true);
1254 fl.l_type = F_WRLCK;
1255 fl.l_whence = SEEK_SET;
1259 if (fcntl (lock_fd, F_SETLK, &fl) == -1)
1264 if (errno == ENOLCK)
1266 log_stderr ("locking not supported on %s: %m", file);
1270 /* We didn't get the lock.
1273 n = read (lock_fd, buf, 255);
1276 log_stderr ("can't read lock %s: %m", file);
1281 return g_strdup (buf);
1284 /* We have the lock.
1287 if (ftruncate (lock_fd, 0) < 0)
1289 log_stderr ("can't truncate lock %s: %m", file);
1293 int n = strlen (my_content);
1294 if (write (lock_fd, my_content, n) != n)
1296 log_stderr ("can't write lock %s: %m", file);
1304 get_apt_worker_lock (bool weak)
1306 char *mine = g_strdup_printf ("%c %d\n", weak? 'w' : 's', getpid ());
1308 int termination_attempts = 0;
1309 int lock_attempts = 0;
1314 his = try_lock (APT_WORKER_LOCK, mine);
1321 if (sscanf (his, "%c %d", &his_type, &his_pid) != 2)
1323 log_stderr ("can't parse lock.");
1327 if (weak || his_type != 'w')
1329 if (lock_attempts < 5)
1337 log_stderr ("too weak to get lock from %d.", his_pid);
1341 else if (termination_attempts < 5)
1343 termination_attempts += 1;
1344 log_stderr ("terminating %d to get lock.", his_pid);
1345 kill (his_pid, SIGTERM);
1353 log_stderr ("killing %d to get lock.", his_pid);
1354 kill (his_pid, SIGKILL);
1355 unlink (APT_WORKER_LOCK);
1370 /* MMC default mountpoints */
1371 #define INTERNAL_MMC_MOUNTPOINT "/home/user/MyDocs"
1372 #define REMOVABLE_MMC_MOUNTPOINT "/media/mmc1"
1377 lc_messages = getenv ("LC_MESSAGES");
1378 DBG ("LC_MESSAGES %s", lc_messages);
1380 DBG ("OSSO_PRODUCT_HARDWARE %s", getenv ("OSSO_PRODUCT_HARDWARE"));
1382 load_system_settings ();
1383 read_domain_conf ();
1385 AptWorkerCache::Initialize ();
1389 #ifdef HAVE_APT_TRUST_HOOK
1390 apt_set_index_trust_level_for_package_hook (index_trust_level_for_package);
1393 clean_temp_catalogues ();
1395 // initialize the MMC mount points with defaults
1396 setenv ("INTERNAL_MMC_MOUNTPOINT", INTERNAL_MMC_MOUNTPOINT, 1);
1397 setenv ("REMOVABLE_MMC_MOUNTPOINT", REMOVABLE_MMC_MOUNTPOINT, 1);
1401 set_options (const char *options)
1403 if (strchr (options, 'B'))
1404 flag_break_locks = true;
1406 if (strchr (options, 'D'))
1407 flag_allow_wrong_domains = true;
1409 if (strchr (options, 'M'))
1410 flag_download_packages_to_mmc = true;
1412 if (strchr (options, 'A'))
1413 flag_use_apt_algorithms = true;
1419 const char *options = request.decode_string_in_place ();
1420 set_options (options);
1426 const char *http_proxy = request.decode_string_in_place ();
1427 const char *https_proxy = request.decode_string_in_place ();
1428 const char *internal_mmc = request.decode_string_in_place ();
1429 const char *removable_mmc = request.decode_string_in_place ();
1433 setenv ("http_proxy", http_proxy, 1);
1434 DBG ("http_proxy: %s", http_proxy);
1439 setenv ("https_proxy", https_proxy, 1);
1440 DBG ("https_proxy: %s", https_proxy);
1445 setenv ("INTERNAL_MMC_MOUNTPOINT", internal_mmc, 1);
1446 DBG ("INTERNAL_MMC_MOUNTPOINT: %s", internal_mmc);
1451 setenv ("REMOVABLE_MMC_MOUNTPOINT", removable_mmc, 1);
1452 DBG ("REMOVABLE_MMC_MOUNTPOINT: %s", removable_mmc);
1457 is_fifo (const char *filename)
1459 struct stat statstruct;
1461 if ((stat (filename, &statstruct) == 0)
1462 && (S_ISFIFO (statstruct.st_mode)))
1463 return g_strdup (filename);
1469 main (int argc, char **argv)
1477 if (!strcmp (argv[0], "backend"))
1479 const char *options;
1483 log_stderr ("wrong invocation");
1487 DBG ("starting up");
1489 char *input_pipe = is_fifo (argv[1]);
1490 char *output_pipe = is_fifo (argv[2]);
1491 char *status_pipe = is_fifo (argv[3]);
1492 char *cancel_pipe = is_fifo (argv[4]);
1494 if (!(input_pipe && output_pipe && status_pipe && cancel_pipe))
1496 g_free (input_pipe);
1497 g_free (output_pipe);
1498 g_free (status_pipe);
1499 g_free (cancel_pipe);
1501 log_stderr ("wrong fifo pipes specified");
1505 input_fd = must_open (input_pipe, O_RDONLY | O_NONBLOCK);
1506 cancel_fd = must_open (cancel_pipe, O_RDONLY | O_NONBLOCK);
1507 output_fd = must_open (output_pipe, O_WRONLY);
1508 status_fd = must_open (status_pipe, O_WRONLY);
1510 g_free (input_pipe);
1511 g_free (output_pipe);
1512 g_free (status_pipe);
1513 g_free (cancel_pipe);
1515 /* This tells the frontend that the fifos are open.
1517 send_status (op_general, 0, 0, -1);
1519 /* This blocks until the frontend has opened our input fifo for
1522 block_for_read (input_fd);
1524 /* Reset the O_NONBLOCK flag for the input_fd since we want to block
1525 until a new request arrives. The cancel_fd remains in
1526 non-blocking mode since we just poll it periodically.
1528 must_set_flags (input_fd, O_RDONLY);
1532 DBG ("starting with pid %d, in %d, out %d, stat %d, cancel %d, options %s",
1533 getpid (), input_fd, output_fd, status_fd, cancel_fd,
1536 set_options (options);
1538 /* Don't let our heavy lifting starve the UI.
1541 if (nice (20) == -1 && errno != 0)
1542 log_stderr ("nice: %m");
1544 get_apt_worker_lock (false);
1552 else if (!strcmp (argv[0], "check-for-updates"))
1554 get_apt_worker_lock (true);
1556 return cmdline_check_updates (argv);
1558 else if (!strcmp (argv[0], "rescue"))
1560 return cmdline_rescue (argv);
1562 else if (!strcmp (argv[0], "sleep"))
1564 get_apt_worker_lock (argv[1] == NULL);
1567 fprintf (stderr, "sleeping...\n");
1577 This section contains some general purpose functions to maintain
1578 the cache of the package database.
1580 The package cache can represent both the 'current' situation
1581 (i.e., the union of the information from /var/lib/dpkg/status and
1582 the various Packages files downloaded from repositories) and a
1583 'desired' situation.
1585 A operation such as installing a package is performed by modifying
1586 the 'desired' situation in the cache and if that leads to a
1587 consistent configuration, the 'current' situation is brought in
1588 line with the 'desired' one by downloading the needed archives and
1589 running dpkg in an approriate way.
1591 We have our own idea of what should happen when a new package (or
1592 a new version of a package) is installed, for example, and the
1593 functions in this section implement this idea. These principal
1594 functions are available:
1596 We remember which operation the cache currently represents. That
1597 way, we can avoid recomputing it when the frontend requests the
1598 same operation multiple times in a row (which it likes to do).
1602 This function creates or recreates the cache from
1603 /var/lib/dpkg/status and the various Packages file from the
1608 This function tries to make sure that there is a valid
1609 PACKAGE_CACHE to work with. It returns true when it succeeds and
1610 PACKAGE_CACHE is non-NULL then. The idea is that if the cache
1611 couldn't be created in the past because of some transient error,
1612 it might be able to create it now. Thus, every command handler
1613 that needs a cache should call ensure_cache. When ensure_cache
1614 actually does some work, it will send STATUS messages if it was
1615 specified with its only parameter.
1619 This function resets the 'desired' state of the cache to be
1620 identical to the 'current' one.
1622 - mark_for_install ()
1624 This function modifies the 'desired' state of the cache to reflect
1625 the installation of the given package. It will try to achieve a
1626 consistent 'desired' configuration by installing missing
1627 dependencies etc. In general, it implements our own installation
1630 - mark_for_remove ()
1632 This function modifies the 'desired' state of the cache to reflect
1633 the removal of the given package. As with mark_for_install,
1634 mark_for_removal implements our own removal smartness.
1637 /* We only report real progress information when reconstructing the
1638 cache and during downloads. Only downloads can be cancelled.
1640 The following two classes allow us to hook into libapt-pkgs
1641 progress reporting mechanism. Instances of UPDATE_PROGESS are used
1642 for cache related activities, and instances of DOWNLOAD_STATUS are
1643 used when 'acquiring' things.
1646 class UpdateProgress : public OpProgress
1654 send_status (op_general, (int)Percent, 100, 5);
1658 UpdateProgress (bool ws) : with_status (ws) { }
1661 class DownloadStatus : public pkgAcquireStatus
1664 MediaChange (string Media, string Drive)
1670 Pulse (pkgAcquire *Owner)
1672 pkgAcquireStatus::Pulse (Owner);
1674 send_status (op_downloading, (int)CurrentBytes, (int)TotalBytes, 1000);
1676 /* The cancel_fd is in non-blocking mode.
1678 if (read_byte (cancel_fd) >= 0)
1686 is_user_section (const char *section, const char *end)
1688 if (section == NULL)
1691 #if ENABLE_OLD_MAEMO_SECTION_TEST
1692 if (end-section > 6 && !strncmp (section, "maemo/", 6))
1696 return end-section > 5 && !strncmp (section, "user/", 5);
1700 is_user_package (const pkgCache::VerIterator &ver)
1702 const char *section = ver.Section ();
1704 if (section == NULL)
1707 return is_user_section (section, section + strlen (section));
1710 /* Our own version of debSystem. We override the Lock member function
1711 to be able to break locks and to avoid failing when dpkg has left a
1715 class mydebSystem : public debSystem
1717 // For locking support
1723 virtual signed Score (Configuration const &Cnf);
1724 virtual bool Lock ();
1725 virtual bool UnLock (bool NoErrors);
1730 mydebSystem::mydebSystem ()
1733 Label = "handsfree Debian dpkg interface";
1737 mydebSystem::Score (Configuration const &Cnf)
1739 return debSystem::Score (Cnf) + 10; // Pick me, pick me, pick me!
1743 mydebSystem::Lock ()
1745 /* This is a modified copy of debSystem::Lock, which in turn is a
1746 copy of the behavior of dpkg.
1749 // Disable file locking
1750 if (_config->FindB("Debug::NoLocking",false) == true || LockCount > 1)
1756 // Create the lockfile, breaking the lock if requested.
1757 string AdminDir = flNotFile(_config->Find("Dir::State::status"));
1758 LockFD = ForceLock(AdminDir + "lock");
1761 if (errno == EACCES || errno == EAGAIN)
1762 return _error->Error("Unable to lock the administration directory (%s), "
1763 "is another process using it?",AdminDir.c_str());
1765 return _error->Error("Unable to lock the administration directory (%s), "
1766 "are you root?",AdminDir.c_str());
1774 // System::UnLock - Drop a lock /*{{{*/
1775 // ---------------------------------------------------------------------
1777 bool mydebSystem::UnLock(bool NoErrors)
1779 if (LockCount == 0 && NoErrors == true)
1783 return _error->Error("Not locked");
1784 if (--LockCount == 0)
1793 mydebSystem mydebsystem;
1796 clear_dpkg_updates ()
1798 string File = flNotFile(_config->Find("Dir::State::status")) + "updates/";
1799 DIR *DirP = opendir(File.c_str());
1803 /* We ignore any files that are not all digits, this skips .,.. and
1804 some tmp files dpkg will leave behind.. */
1806 for (struct dirent *Ent = readdir(DirP); Ent != 0; Ent = readdir(DirP))
1808 bool ignore = false;
1810 for (unsigned int I = 0; Ent->d_name[I] != 0; I++)
1812 // Check if its not a digit..
1813 if (isdigit(Ent->d_name[I]) == 0)
1822 log_stderr ("Running 'dpkg --configure dpkg' "
1823 "to clean up the journal.");
1824 system ("dpkg --configure dpkg");
1832 void cache_reset ();
1834 /* The operation represented by the cache.
1836 static char *current_cache_package = NULL;
1837 static bool current_cache_is_install;
1840 check_cache_state (const char *package, bool is_install)
1842 if (current_cache_package
1843 && current_cache_is_install == is_install
1844 && strcmp (current_cache_package, package) == 0)
1847 if (current_cache_package)
1850 current_cache_package = g_strdup (package);
1851 current_cache_is_install = is_install;
1855 /* Initialize libapt-pkg if this has not been done already and
1856 (re-)create PACKAGE_CACHE. If the cache can not be created,
1857 PACKAGE_CACHE is set to NULL and an appropriate message is output.
1860 cache_init (bool with_status)
1862 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1864 /* Closes the cache, to prevent getting blocked by other locks in
1865 * dpkg structures. If we don't do it, changing the apt worker state
1866 * does not remove the dpkg state lock and then fails on trying to
1868 /* @todo do we really keep doing this? */
1872 delete awc->action_group;
1873 awc->cache->Close ();
1879 /* We need to dump the errors here since any pending errors will
1880 cause the following operations to fail.
1882 _error->DumpErrors ();
1884 /* Clear out the dpkg journal before construction the cache.
1886 clear_dpkg_updates ();
1888 UpdateProgress progress (with_status);
1889 awc->cache = new myCacheFile;
1892 if (!awc->cache->Open (progress))
1895 _error->DumpErrors ();
1902 /* We create a ActionGroup here that is active for the whole
1903 lifetime of the cache. This prevents libapt-pkg from
1904 performing certain expensive operations that we don't need to
1905 be done intermediately, such as garbage collection.
1907 pkgDepCache &cache = *awc->cache;
1908 awc->action_group = new pkgDepCache::ActionGroup (cache);
1914 write_available_updates_file ();
1918 ensure_cache (bool with_status)
1920 AptWorkerCache * awc = 0;
1922 awc = AptWorkerCache::GetCurrent ();
1923 if (awc->cache == NULL)
1924 cache_init (with_status);
1926 return awc->cache != NULL;
1929 /* Determine whether a package was installed automatically to satisfy
1933 is_auto_package (pkgCache::PkgIterator &pkg)
1935 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1936 pkgDepCache &cache = *(awc->cache);
1938 return (cache[pkg].Flags & pkgCache::Flag::Auto) != 0;
1941 /* Determine whether a package is related to the current operation.
1944 is_related (pkgCache::PkgIterator &pkg)
1946 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1947 return awc->cache->extra_info[pkg->ID].related;
1951 mark_related (const pkgCache::VerIterator &ver)
1953 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1954 const pkgCache::PkgIterator &pkg = ver.ParentPkg();
1956 if (awc->cache->extra_info[pkg->ID].related)
1959 awc->cache->extra_info[pkg->ID].related = true;
1961 pkgDepCache &cache = *awc->cache;
1963 if (pkg.State() == pkgCache::PkgIterator::NeedsUnpack)
1964 cache.SetReInstall (pkg, true);
1966 /* When there are some packages that might need configuring or
1967 unpacking, we also mark all dependencies of this package as
1968 related so that we try to unpack/configure them as well.
1970 if (cache.BadCount () > 0)
1972 for (pkgCache::DepIterator D = ver.DependsList(); D.end() == false;
1975 const pkgCache::PkgIterator &dep_pkg = D.TargetPkg ();
1976 const pkgCache::VerIterator &dep_ver = dep_pkg.CurrentVer ();
1978 mark_related (dep_ver);
1983 /* Revert the cache to its initial state. More concretely, all
1984 packages are marked as 'keep' and 'unrelated'.
1986 XXX - let libapt-pkg handle the auto flags.
1989 cache_reset_package (pkgCache::PkgIterator &pkg)
1991 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
1992 pkgDepCache &cache = *(awc->cache);
1994 cache.MarkKeep (pkg);
1996 if (awc->cache->extra_info[pkg->ID].autoinst)
1997 cache[pkg].Flags |= pkgCache::Flag::Auto;
1999 cache[pkg].Flags &= ~pkgCache::Flag::Auto;
2001 awc->cache->extra_info[pkg->ID].related = false;
2002 awc->cache->extra_info[pkg->ID].soft = false;
2006 any_newly_or_related_broken ()
2008 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2009 if (awc->cache == NULL)
2012 pkgDepCache &cache = *(awc->cache);
2013 for (pkgCache::PkgIterator pkg = cache.PkgBegin(); !pkg.end (); pkg++)
2015 if (cache[pkg].InstBroken() &&
2016 (!cache[pkg].NowBroken() || is_related (pkg)))
2025 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2026 if (awc->cache == NULL)
2029 pkgDepCache &cache = *(awc->cache);
2031 for (pkgCache::PkgIterator pkg = cache.PkgBegin(); !pkg.end (); pkg++)
2032 cache_reset_package (pkg);
2034 g_free (current_cache_package);
2035 current_cache_package = NULL;
2038 /* Try to fix packages that have been broken by undoing soft changes.
2040 This is not really complicated, the code only looks impenetrable
2041 because of libapt-pkg's data structures.
2043 For each package that is broken for the planned operation, we try
2044 to fix it by undoing the removal of softly removed packages that it
2045 depends on. We do this in a loop since a package that has been put
2046 back might be broken itself and be in need of fixing.
2049 fix_soft_packages ()
2051 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2052 if (awc->cache == NULL)
2055 pkgDepCache &cache = *(awc->cache);
2057 bool something_changed;
2063 something_changed = false;
2064 for (pkgCache::PkgIterator pkg = cache.PkgBegin(); !pkg.end (); pkg++)
2066 if (cache[pkg].InstBroken())
2068 pkgCache::DepIterator Dep =
2069 cache[pkg].InstVerIter(cache).DependsList();
2070 for (; Dep.end() != true;)
2073 pkgCache::DepIterator Start = Dep;
2075 for (bool LastOR = true;
2076 Dep.end() == false && LastOR == true;
2079 LastOR = ((Dep->CompareOp & pkgCache::Dep::Or)
2080 == pkgCache::Dep::Or);
2082 if ((cache[Dep] & pkgDepCache::DepInstall)
2083 == pkgDepCache::DepInstall)
2087 // Dep is satisfied okay.
2088 if (Result == false)
2091 // Try to fix it by putting back the first softly
2094 for (bool LastOR = true;
2095 Start.end() == false && LastOR == true;
2098 LastOR = ((Start->CompareOp & pkgCache::Dep::Or)
2099 == pkgCache::Dep::Or);
2101 pkgCache::PkgIterator Pkg = Start.TargetPkg ();
2103 if (((cache[Start] & pkgDepCache::DepInstall)
2104 != pkgDepCache::DepInstall)
2106 && cache[Pkg].Delete()
2107 && awc->cache->extra_info[Pkg->ID].soft)
2109 DBG ("= %s", Pkg.Name());
2110 cache_reset_package (Pkg);
2111 something_changed = true;
2118 } while (something_changed);
2121 /* Determine whether PKG replaces TARGET.
2124 package_replaces (pkgCache::PkgIterator &pkg,
2125 pkgCache::PkgIterator &target)
2127 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2128 pkgDepCache &cache = *(awc->cache);
2130 pkgCache::DepIterator Dep = cache[pkg].InstVerIter(cache).DependsList();
2131 for (; Dep.end() != true; Dep++)
2133 if (Dep->Type == pkgCache::Dep::Replaces)
2135 SPtrArray<pkgCache::Version *> List = Dep.AllTargets();
2136 for (pkgCache::Version **I = List; *I != 0; I++)
2138 pkgCache::VerIterator Ver(cache,*I);
2139 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
2150 /* Determine whether PKG is a critical dependency of other packages
2151 thata re going to be installed.
2154 package_is_needed (pkgCache::PkgIterator &pkg)
2156 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2157 pkgDepCache &cache = *(awc->cache);
2159 pkgCache::DepIterator Dep = pkg.RevDependsList();
2160 for (; Dep.end() != true; Dep++)
2162 if (Dep->Type == pkgCache::Dep::PreDepends
2163 || Dep->Type == pkgCache::Dep::Depends)
2165 pkgCache::PkgIterator other_pkg = Dep.ParentPkg();
2166 pkgCache::VerIterator other_ver = Dep.ParentVer();
2167 pkgCache::VerIterator inst_ver = cache[other_pkg].InstVerIter(cache);
2169 if (other_ver == inst_ver)
2177 /* Mark a package for installation, using a 'no-surprises' approach
2178 suitable for the Application Manager.
2180 Concretely, installing a package will never automatically remove
2181 other packages. Thus, we undo the removals scheduled by
2182 MarkInstall. Doing this will break the original package, but that
2186 static void mark_for_remove_1 (pkgCache::PkgIterator &pkg, bool soft);
2189 mark_for_install_1 (pkgCache::PkgIterator &pkg, int level)
2191 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2192 pkgDepCache &cache = *(awc->cache);
2194 /* This check is just to be extra robust against infinite
2195 recursions. They shouldn't happen, but you never know...
2200 mark_related (cache[pkg].CandidateVerIter(cache));
2202 /* Avoid recursion if package is already marked for installation but
2203 try to fix it when it is broken.
2205 if (cache[pkg].Mode == pkgDepCache::ModeInstall
2206 && !cache[pkg].InstBroken ())
2209 DBG ("+ %s", pkg.Name());
2211 /* Now mark it and return if that fails. Both ModeInstall and
2212 ModeKeep are fine. ModeKeep only happens for broken packages.
2214 cache.MarkInstall (pkg, false);
2215 if (cache[pkg].Mode != pkgDepCache::ModeInstall
2216 && cache[pkg].Mode != pkgDepCache::ModeKeep)
2219 /* Try to satisfy dependencies. We can't use MarkInstall with
2220 AutoInst == true since we don't like how it handles conflicts,
2221 and we have our own way of uninstalling packages.
2223 The code below is lifted from pkgDepCache::MarkInstall. Sorry
2224 for introducing this mess here.
2227 pkgCache::DepIterator Dep = cache[pkg].InstVerIter(cache).DependsList();
2228 for (; Dep.end() != true;)
2231 pkgCache::DepIterator Start = Dep;
2234 for (bool LastOR = true; Dep.end() == false && LastOR == true;
2237 LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
2239 if ((cache[Dep] & pkgDepCache::DepInstall) == pkgDepCache::DepInstall)
2243 // Dep is satisfied okay.
2244 if (Result == false)
2247 /* Check if this dep should be consider for install. If it is a user
2248 defined important dep and we are installed a new package then
2249 it will be installed. Otherwise we only worry about critical deps */
2250 if (cache.IsImportantDep(Start) == false)
2253 if (pkg->CurrentVer != 0 && Start.IsCritical() == false)
2256 /* If we are in an or group locate the first or that can
2257 succeed. We have already cached this.. */
2259 && (cache[Start] & pkgDepCache::DepCVer) != pkgDepCache::DepCVer;
2263 /* This bit is for processing the possibilty of an install/upgrade
2264 fixing the problem */
2265 SPtrArray<pkgCache::Version *> List = Start.AllTargets();
2266 if ((cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
2268 // Right, find the best version to install..
2269 pkgCache::Version **Cur = List;
2270 pkgCache::PkgIterator P = Start.TargetPkg();
2271 pkgCache::PkgIterator InstPkg(cache,0);
2273 // See if there are direct matches (at the start of the list)
2274 for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
2276 pkgCache &pkgcache = cache.GetCache ();
2277 pkgCache::PkgIterator Pkg(pkgcache,
2278 pkgcache.PkgP + (*Cur)->ParentPkg);
2279 if (cache[Pkg].CandidateVer != *Cur)
2285 // Select the highest priority providing package
2286 if (InstPkg.end() == true)
2288 pkgPrioSortList(cache,Cur);
2289 for (; *Cur != 0; Cur++)
2291 pkgCache &pkgcache = cache.GetCache ();
2292 pkgCache::PkgIterator
2293 Pkg(pkgcache,pkgcache.PkgP + (*Cur)->ParentPkg);
2294 if (cache[Pkg].CandidateVer != *Cur)
2301 if (InstPkg.end() == false)
2303 mark_for_install_1 (InstPkg, level + 1);
2305 // Set the autoflag, after MarkInstall because
2306 // MarkInstall unsets it
2307 if (P->CurrentVer == 0)
2308 cache[InstPkg].Flags |= pkgCache::Flag::Auto;
2314 /* For conflicts/replaces combinations we de-install the package
2315 with mark_for_remove, but only if it is a non-user package.
2316 (Conflicts and Replaces may not have or groups.)
2318 if (Start->Type == pkgCache::Dep::Conflicts
2319 || Start->Type == pkgCache::Dep::Obsoletes)
2321 for (pkgCache::Version **I = List; *I != 0; I++)
2323 pkgCache::VerIterator Ver(cache,*I);
2324 pkgCache::PkgIterator target = Ver.ParentPkg();
2326 if (!is_user_package (Ver)
2327 && package_replaces (pkg, target))
2328 mark_for_remove_1 (target, true);
2336 mark_for_install (pkgCache::PkgIterator &pkg)
2338 DBG ("INSTALL %s", pkg.Name());
2340 if (flag_use_apt_algorithms)
2342 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2343 pkgDepCache &Cache = *(awc->cache);
2344 pkgDepCache::StateCache &State = Cache[pkg];
2346 pkgProblemResolver Fix(&Cache);
2351 Cache.MarkInstall(pkg,false);
2352 if (State.Install() == false)
2354 if (pkg->CurrentVer && pkg.CurrentVer().Downloadable())
2355 Cache.SetReInstall(pkg,true);
2358 // Install it with autoinstalling enabled (if we not respect the minial
2359 // required deps or the policy)
2360 if (State.InstBroken() == true || State.InstPolicyBroken() == true)
2361 Cache.MarkInstall(pkg,true);
2363 Fix.InstallProtect();
2364 if (Fix.Resolve(true) == false)
2369 mark_for_install_1 (pkg, 0);
2370 fix_soft_packages ();
2374 /* Mark every upgradeable non-user package for installation.
2377 mark_sys_upgrades ()
2379 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2380 pkgDepCache &cache = *(awc->cache);
2384 for (pkgCache::PkgIterator p = cache.PkgBegin (); !p.end (); p++)
2386 if (!p.CurrentVer().end()
2387 && !is_user_package (p.CurrentVer())
2389 mark_for_install_1 (p, 0);
2391 fix_soft_packages ();
2394 /* Mark the named package for installation. This function also
2395 handles magic packages like "magic:sys".
2399 mark_named_package_for_install (const char *package)
2401 if (check_cache_state (package, true))
2404 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2405 if (!strcmp (package, "magic:sys"))
2407 mark_sys_upgrades ();
2412 pkgDepCache &cache = *(awc->cache);
2413 pkgCache::PkgIterator pkg = cache.FindPkg (package);
2416 mark_for_install (pkg);
2424 /* Mark a package for removal and also remove as many of the packages
2425 that it depends on as possible.
2428 mark_for_remove_1 (pkgCache::PkgIterator &pkg, bool soft)
2430 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2431 pkgDepCache &cache = *(awc->cache);
2433 if (cache[pkg].Delete ())
2436 DBG ("- %s%s", pkg.Name(), soft? " (soft)" : "");
2438 cache.MarkDelete (pkg);
2439 cache[pkg].Flags &= ~pkgCache::Flag::Auto;
2440 awc->cache->extra_info[pkg->ID].soft = soft;
2442 if (!cache[pkg].Delete ())
2445 // Now try to remove all non-user, auto-installed dependencies of
2448 pkgCache::VerIterator cur = pkg.CurrentVer ();
2452 for (pkgCache::DepIterator dep = cur.DependsList(); dep.end() == false;
2455 if (dep->Type == pkgCache::Dep::PreDepends ||
2456 dep->Type == pkgCache::Dep::Depends)
2458 pkgCache::PkgIterator p = dep.TargetPkg ();
2460 && is_auto_package (p)
2461 && !p.CurrentVer().end()
2462 && !is_user_package (p.CurrentVer()))
2463 mark_for_remove_1 (p, true);
2469 mark_for_remove (pkgCache::PkgIterator &pkg)
2471 DBG ("REMOVE %s", pkg.Name());
2473 if (check_cache_state (pkg.Name (), false))
2476 if (flag_use_apt_algorithms)
2478 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2479 pkgDepCache &Cache = *(awc->cache);
2481 pkgProblemResolver Fix(&Cache);
2487 Cache.MarkDelete (pkg,false);
2489 Fix.InstallProtect();
2490 if (Fix.Resolve(true) == false)
2495 mark_for_remove_1 (pkg, false);
2496 fix_soft_packages ();
2500 /* Getting the package record in a nicely parsable form.
2503 struct package_record {
2505 pkgRecords::Parser &P;
2506 pkgTagSection section;
2509 package_record (pkgCache::VerIterator &ver);
2511 bool has (const char *tag);
2512 string get_string (const char *tag);
2513 char *get (const char *tag);
2514 int get_int (const char *tag, int def);
2516 string get_localized_string (const char *tag);
2519 package_record::package_record (pkgCache::VerIterator &ver)
2520 : Recs (*(AptWorkerCache::GetCurrent ()->cache)),
2521 P (Recs.Lookup (ver.FileList ()))
2523 const char *start, *stop;
2524 P.GetRec (start, stop);
2526 /* NOTE: pkTagSection::Scan only succeeds when the record ends in
2527 two newlines, but pkgRecords::Parser::GetRec does not
2528 include the second newline in its returned region.
2529 However, that second newline is always there, so we just
2530 pass one more character to Scan.
2533 valid = section.Scan (start, stop-start+1);
2537 package_record::has (const char *tag)
2540 return valid && section.Find (tag, pos);
2544 package_record::get_string (const char *tag)
2547 return section.FindS (tag);
2553 all_white_space (const char *text)
2556 if (!isspace (*text++))
2562 package_record::get (const char *tag)
2567 string res = get_string (tag);
2568 if (all_white_space (res.c_str ()))
2571 return g_strdup (res.c_str());
2575 package_record::get_int (const char *tag, int def)
2580 return section.FindI (tag, def);
2584 package_record::get_localized_string (const char *tag)
2586 if (lc_messages && *lc_messages)
2588 char *locale_tag = g_strdup_printf ("%s-%s", tag, lc_messages);
2590 if (has (locale_tag))
2592 string res = get_string (locale_tag);
2593 g_free (locale_tag);
2596 g_free (locale_tag);
2599 return get_string (tag);
2602 /** COMMAND HANDLERS
2605 /* APTCMD_GET_PACKAGE_LIST
2607 The get_package_list command can do some filtering and we have a
2608 few utility functions for implementing the necessary checks. The
2609 check generally take cache iterators to identify a package or a
2614 name_matches_pattern (pkgCache::PkgIterator &pkg,
2615 const char *pattern)
2618 char **words = g_strsplit (pattern, " ", 0);
2624 for (i = 0; words[i] != NULL; i++)
2625 if (strcasestr (pkg.Name(), words[i]))
2638 description_matches_pattern (pkgCache::VerIterator &ver,
2639 const char *pattern)
2642 char **words = g_strsplit (pattern, " ", 0);
2643 package_record rec (ver);
2644 const char *desc = rec.P.LongDesc().c_str();
2650 for (i = 0; words[i] != NULL; i++)
2651 if (strcasestr (desc, words[i])) // XXX - UTF8?
2664 get_description (int summary_kind,
2665 pkgCache::PkgIterator &pkg,
2666 package_record &rec)
2670 if (summary_kind == 1 && !pkg.CurrentVer().end())
2671 res = rec.get_localized_string ("Maemo-Upgrade-Description");
2675 /* XXX - support apt's own method of localizing descriptions as
2678 res = rec.get_localized_string ("Description");
2685 get_short_description (int summary_kind,
2686 pkgCache::PkgIterator &pkg,
2687 package_record &rec)
2689 string res = get_description (summary_kind, pkg, rec);
2690 string::size_type pos = res.find('\n');
2691 if (pos != string::npos)
2692 return string (res,0,pos);
2697 get_long_description (int summary_kind,
2698 pkgCache::PkgIterator &pkg,
2699 package_record &rec)
2701 return get_description (summary_kind, pkg, rec);
2705 get_icon (package_record &rec)
2707 return rec.get ("Maemo-Icon-26");
2710 struct flag_struct {
2714 { "close-apps", pkgflag_close_apps },
2715 { "suggest-backup", pkgflag_suggest_backup },
2716 { "reboot", pkgflag_reboot },
2717 { "system-update", pkgflag_system_update },
2718 { "flash-and-reboot", pkgflag_flash_and_reboot },
2723 get_flags (package_record &rec)
2726 char *flag_string = rec.get ("Maemo-Flags");
2727 char *ptr = flag_string, *tok;
2728 while ((tok = strsep (&ptr, ",")))
2730 for (int i = 0; flag_names[i].name != NULL; i++)
2731 if (tokens_equal (flag_names[i].name, tok))
2733 flags |= flag_names[i].flag;
2737 g_free (flag_string);
2743 get_pretty_name (package_record &rec)
2745 return rec.get_localized_string ("Maemo-Display-Name");
2749 get_required_free_space (package_record &rec)
2751 return 1024 * (int64_t) rec.get_int ("Maemo-Required-Free-Space", 0);
2755 encode_version_info (int summary_kind,
2756 pkgCache::VerIterator &ver, bool include_size)
2758 package_record rec (ver);
2761 response.encode_string (ver.VerStr ());
2763 response.encode_int64 (ver->InstalledSize);
2764 response.encode_string (ver.Section ());
2765 string pretty = get_pretty_name (rec);
2766 response.encode_string (pretty.empty()? NULL : pretty.c_str());
2767 pkgCache::PkgIterator pkg = ver.ParentPkg();
2768 response.encode_string
2769 (get_short_description (summary_kind, pkg, rec).c_str());
2770 icon = get_icon (rec);
2771 response.encode_string (icon);
2776 encode_empty_version_info (bool include_size)
2778 response.encode_string (NULL);
2780 response.encode_int64 (0);
2781 response.encode_string (NULL);
2782 response.encode_string (NULL);
2783 response.encode_string (NULL);
2784 response.encode_string (NULL);
2788 cmd_get_package_list ()
2790 AptWorkerCache *awc = AptWorkerCache::GetCurrent ();
2791 bool only_user = request.decode_int ();
2792 bool only_installed = request.decode_int ();
2793 bool only_available = request.decode_int ();
2794 const char *pattern = request.decode_string_in_place ();
2795 bool show_magic_sys = request.decode_int ();
2797 if (!ensure_cache (true))
2799 response.encode_int (0);
2803 response.encode_int (1);
2804 pkgDepCache &cache = *(awc->cache);
2806 for (pkgCache::PkgIterator pkg = cache.PkgBegin(); !pkg.end (); pkg++)
2810 /* Get installed and candidate iterators for current package */
2811 pkgCache::VerIterator installed = pkg.CurrentVer ();
2812 pkgCache::VerIterator candidate = cache[pkg].CandidateVerIter(cache);