1 /*
2  * libdpkg - Debian packaging suite library routines
3  * pkg.c - primitives for pkg handling
4  *
5  * Copyright © 1995, 1996 Ian Jackson <ijackson@chiark.greenend.org.uk>
6  * Copyright © 2009-2014 Guillem Jover <guillem@debian.org>
7  *
8  * This is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <compat.h>
24 
25 #include <string.h>
26 
27 #include <dpkg/ehandle.h>
28 #include <dpkg/string.h>
29 #include <dpkg/dpkg-db.h>
30 #include <dpkg/pkg.h>
31 
32 /**
33  * Set the package installation status.
34  */
35 void
pkg_set_status(struct pkginfo * pkg,enum pkgstatus status)36 pkg_set_status(struct pkginfo *pkg, enum pkgstatus status)
37 {
38 	if (pkg->status == status)
39 		return;
40 	else if (pkg->status == PKG_STAT_NOTINSTALLED)
41 		pkg->set->installed_instances++;
42 	else if (status == PKG_STAT_NOTINSTALLED)
43 		pkg->set->installed_instances--;
44 
45 	if (pkg->set->installed_instances < 0)
46 		internerr("pkgset %s went into negative installed instances %d",
47 		          pkg->set->name, pkg->set->installed_instances);
48 
49 	pkg->status = status;
50 	pkg->status_dirty = true;
51 }
52 
53 /**
54  * Set the specified flags to 1 in the package error flags.
55  */
56 void
pkg_set_eflags(struct pkginfo * pkg,enum pkgeflag eflag)57 pkg_set_eflags(struct pkginfo *pkg, enum pkgeflag eflag)
58 {
59 	pkg->eflag |= eflag;
60 }
61 
62 /**
63  * Clear the specified flags to 0 in the package error flags.
64  */
65 void
pkg_clear_eflags(struct pkginfo * pkg,enum pkgeflag eflag)66 pkg_clear_eflags(struct pkginfo *pkg, enum pkgeflag eflag)
67 {
68 	pkg->eflag &= ~eflag;
69 }
70 
71 /**
72  * Reset the package error flags to 0.
73  */
74 void
pkg_reset_eflags(struct pkginfo * pkg)75 pkg_reset_eflags(struct pkginfo *pkg)
76 {
77 	pkg->eflag = PKG_EFLAG_OK;
78 }
79 
80 /**
81  * Copy the package error flags to another package.
82  */
83 void
pkg_copy_eflags(struct pkginfo * pkg_dst,struct pkginfo * pkg_src)84 pkg_copy_eflags(struct pkginfo *pkg_dst, struct pkginfo *pkg_src)
85 {
86 	pkg_dst->eflag = pkg_src->eflag;
87 }
88 
89 /**
90  * Set the package selection status.
91  */
92 void
pkg_set_want(struct pkginfo * pkg,enum pkgwant want)93 pkg_set_want(struct pkginfo *pkg, enum pkgwant want)
94 {
95 	pkg->want = want;
96 }
97 
98 void
pkgbin_blank(struct pkgbin * pkgbin)99 pkgbin_blank(struct pkgbin *pkgbin)
100 {
101 	pkgbin->essential = false;
102 	pkgbin->depends = NULL;
103 	pkgbin->pkgname_archqual = NULL;
104 	pkgbin->description = NULL;
105 	pkgbin->maintainer = NULL;
106 	pkgbin->source = NULL;
107 	pkgbin->installedsize = NULL;
108 	pkgbin->bugs = NULL;
109 	pkgbin->origin = NULL;
110 	dpkg_version_blank(&pkgbin->version);
111 	pkgbin->conffiles = NULL;
112 	pkgbin->arbs = NULL;
113 }
114 
115 void
pkg_blank(struct pkginfo * pkg)116 pkg_blank(struct pkginfo *pkg)
117 {
118 	pkg->status = PKG_STAT_NOTINSTALLED;
119 	pkg->status_dirty = false;
120 	pkg->eflag = PKG_EFLAG_OK;
121 	pkg->want = PKG_WANT_UNKNOWN;
122 	pkg->priority = PKG_PRIO_UNKNOWN;
123 	pkg->otherpriority = NULL;
124 	pkg->section = NULL;
125 	dpkg_version_blank(&pkg->configversion);
126 	pkg->files_list_valid = false;
127 	pkg->files_list_phys_offs = 0;
128 	pkg->files = NULL;
129 	pkg->archives = NULL;
130 	pkg->clientdata = NULL;
131 	pkg->trigaw.head = NULL;
132 	pkg->trigaw.tail = NULL;
133 	pkg->othertrigaw_head = NULL;
134 	pkg->trigpend_head = NULL;
135 	pkgbin_blank(&pkg->installed);
136 	pkgbin_blank(&pkg->available);
137 
138 	/* The architectures are reset here (instead of in pkgbin_blank),
139 	 * because they are part of the package specification, and needed
140 	 * for selections. */
141 	pkg->installed.arch = dpkg_arch_get(DPKG_ARCH_NONE);
142 	pkg->installed.multiarch = PKG_MULTIARCH_NO;
143 	pkg->available.arch = dpkg_arch_get(DPKG_ARCH_NONE);
144 	pkg->available.multiarch = PKG_MULTIARCH_NO;
145 }
146 
147 void
pkgset_blank(struct pkgset * set)148 pkgset_blank(struct pkgset *set)
149 {
150 	set->name = NULL;
151 	set->depended.available = NULL;
152 	set->depended.installed = NULL;
153 	pkg_blank(&set->pkg);
154 	set->installed_instances = 0;
155 	set->pkg.set = set;
156 	set->pkg.arch_next = NULL;
157 }
158 
159 /**
160  * Link a pkginfo instance into a package set.
161  *
162  * @param set The package set to use.
163  * @param pkg The package to link into the set.
164  */
165 void
pkgset_link_pkg(struct pkgset * set,struct pkginfo * pkg)166 pkgset_link_pkg(struct pkgset *set, struct pkginfo *pkg)
167 {
168 	pkg->set = set;
169 	pkg->arch_next = set->pkg.arch_next;
170 	set->pkg.arch_next = pkg;
171 }
172 
173 /**
174  * Get the number of installed package instances in a package set.
175  *
176  * @param set The package set to use.
177  *
178  * @return The count of installed packages.
179  */
180 int
pkgset_installed_instances(struct pkgset * set)181 pkgset_installed_instances(struct pkgset *set)
182 {
183 	return set->installed_instances;
184 }
185 
186 /**
187  * Check if a pkg is informative.
188  *
189  * Used by dselect and dpkg query options as an aid to decide whether to
190  * display things, and by dump to decide whether to write them out.
191  */
192 bool
pkg_is_informative(struct pkginfo * pkg,struct pkgbin * pkgbin)193 pkg_is_informative(struct pkginfo *pkg, struct pkgbin *pkgbin)
194 {
195 	/* We ignore Section and Priority, as these tend to hang around. */
196 	if (pkgbin == &pkg->installed &&
197 	    (pkg->want != PKG_WANT_UNKNOWN ||
198 	     pkg->eflag != PKG_EFLAG_OK ||
199 	     pkg->status != PKG_STAT_NOTINSTALLED ||
200 	     dpkg_version_is_informative(&pkg->configversion)))
201 		return true;
202 
203 	if (pkgbin->depends ||
204 	    str_is_set(pkgbin->description) ||
205 	    str_is_set(pkgbin->maintainer) ||
206 	    str_is_set(pkgbin->origin) ||
207 	    str_is_set(pkgbin->bugs) ||
208 	    str_is_set(pkgbin->installedsize) ||
209 	    str_is_set(pkgbin->source) ||
210 	    dpkg_version_is_informative(&pkgbin->version) ||
211 	    pkgbin->conffiles ||
212 	    pkgbin->arbs)
213 		return true;
214 
215 	return false;
216 }
217