1 /* pkg.c - the opkg package management system
2 
3    Carl D. Worth
4 
5    Copyright (C) 2001 University of Southern California
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2, or (at
10    your option) any later version.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 */
17 
18 #include <stdio.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <unistd.h>
22 #include <libgen.h>
23 
24 #include "pkg.h"
25 
26 #include "pkg_parse.h"
27 #include "pkg_extract.h"
28 #include "opkg_message.h"
29 #include "opkg_utils.h"
30 
31 #include "libbb/libbb.h"
32 #include "sprintf_alloc.h"
33 #include "file_util.h"
34 #include "xsystem.h"
35 #include "opkg_conf.h"
36 
37 typedef struct enum_map enum_map_t;
38 struct enum_map {
39 	unsigned int value;
40 	const char *str;
41 };
42 
43 static const enum_map_t pkg_state_want_map[] = {
44 	{SW_UNKNOWN, "unknown"},
45 	{SW_INSTALL, "install"},
46 	{SW_DEINSTALL, "deinstall"},
47 	{SW_PURGE, "purge"}
48 };
49 
50 static const enum_map_t pkg_state_flag_map[] = {
51 	{SF_OK, "ok"},
52 	{SF_REINSTREQ, "reinstreq"},
53 	{SF_HOLD, "hold"},
54 	{SF_REPLACE, "replace"},
55 	{SF_NOPRUNE, "noprune"},
56 	{SF_PREFER, "prefer"},
57 	{SF_OBSOLETE, "obsolete"},
58 	{SF_USER, "user"},
59 };
60 
61 static const enum_map_t pkg_state_status_map[] = {
62 	{SS_NOT_INSTALLED, "not-installed"},
63 	{SS_UNPACKED, "unpacked"},
64 	{SS_HALF_CONFIGURED, "half-configured"},
65 	{SS_INSTALLED, "installed"},
66 	{SS_HALF_INSTALLED, "half-installed"},
67 	{SS_CONFIG_FILES, "config-files"},
68 	{SS_POST_INST_FAILED, "post-inst-failed"},
69 	{SS_REMOVAL_FAILED, "removal-failed"}
70 };
71 
pkg_init(pkg_t * pkg)72 static void pkg_init(pkg_t * pkg)
73 {
74 	pkg->name = NULL;
75 	pkg->dest = NULL;
76 	pkg->src = NULL;
77 	pkg->state_want = SW_UNKNOWN;
78 	pkg->state_flag = SF_OK;
79 	pkg->state_status = SS_NOT_INSTALLED;
80 
81 	pkg->installed_files = NULL;
82 	pkg->installed_files_ref_cnt = 0;
83 	pkg->essential = 0;
84 	pkg->provided_by_hand = 0;
85 
86 	pkg->arch_index = 0;
87 
88 	blob_buf_init(&pkg->blob, 0);
89 }
90 
pkg_new(void)91 pkg_t *pkg_new(void)
92 {
93 	pkg_t *pkg;
94 
95 	pkg = xcalloc(1, sizeof(pkg_t));
96 	pkg_init(pkg);
97 
98 	return pkg;
99 }
100 
pkg_set_raw(pkg_t * pkg,int id,const void * val,size_t len)101 void *pkg_set_raw(pkg_t *pkg, int id, const void *val, size_t len)
102 {
103 	int rem;
104 	struct blob_attr *cur;
105 
106 	blob_for_each_attr(cur, pkg->blob.head, rem) {
107 		if (blob_id(cur) == id) {
108 			if (blob_len(cur) < len) {
109 				fprintf(stderr, "ERROR: truncating field %d <%p> to %d byte",
110 				        id, val, blob_len(cur));
111 			}
112 			memcpy(blob_data(cur), val, blob_len(cur));
113 			return blob_data(cur);
114 		}
115 	}
116 
117 	cur = blob_put(&pkg->blob, id, val, len);
118 	return cur ? blob_data(cur) : NULL;
119 }
120 
pkg_get_raw(const pkg_t * pkg,int id)121 void *pkg_get_raw(const pkg_t * pkg, int id)
122 {
123 	int rem;
124 	struct blob_attr *cur;
125 
126 	blob_for_each_attr(cur, pkg->blob.head, rem)
127 		if (blob_id(cur) == id)
128 			return blob_data(cur);
129 
130 	return NULL;
131 }
132 
pkg_set_string(pkg_t * pkg,int id,const char * s)133 char *pkg_set_string(pkg_t *pkg, int id, const char *s)
134 {
135 	size_t len;
136 	char *p;
137 
138 	if (!s)
139 		return NULL;
140 
141 	len = strlen(s);
142 
143 	while (isspace(*s)) {
144 		s++;
145 		len--;
146 	}
147 
148 	while (len > 0 && isspace(s[len - 1]))
149 		len--;
150 
151 	if (!len)
152 		return NULL;
153 
154 	p = pkg_set_raw(pkg, id, s, len + 1);
155 	p[len] = 0;
156 
157 	return p;
158 }
159 
pkg_get_architecture(const pkg_t * pkg)160 char *pkg_get_architecture(const pkg_t *pkg)
161 {
162 	nv_pair_list_elt_t *l;
163 	int n = 1;
164 
165 	list_for_each_entry(l, &conf->arch_list.head, node) {
166 		nv_pair_t *nv = (nv_pair_t *) l->data;
167 		if (n++ == pkg->arch_index)
168 			return nv->name;
169 	}
170 
171 	return NULL;
172 }
173 
pkg_set_architecture(pkg_t * pkg,const char * architecture,ssize_t len)174 char *pkg_set_architecture(pkg_t *pkg, const char *architecture, ssize_t len)
175 {
176 	nv_pair_list_elt_t *l;
177 	int n = 1;
178 
179 	list_for_each_entry(l, &conf->arch_list.head, node) {
180 		nv_pair_t *nv = (nv_pair_t *) l->data;
181 
182 		if (!strncmp(nv->name, architecture, len) && nv->name[len] == '\0') {
183 			if (n >= 8) {
184 				opkg_msg(ERROR, "Internal error: too many different architectures\n");
185 				break;
186 			}
187 
188 			pkg->arch_index = n;
189 			return nv->name;
190 		}
191 
192 		n++;
193 	}
194 
195 	pkg->arch_index = 0;
196 	return NULL;
197 }
198 
pkg_get_arch_priority(const pkg_t * pkg)199 int pkg_get_arch_priority(const pkg_t *pkg)
200 {
201 	nv_pair_list_elt_t *l;
202 	int n = 1;
203 
204 	list_for_each_entry(l, &conf->arch_list.head, node) {
205 		nv_pair_t *nv = (nv_pair_t *) l->data;
206 		if (n++ == pkg->arch_index)
207 			return strtol(nv->value, NULL, 0);
208 	}
209 
210 	return 0;
211 }
212 
pkg_get_md5(const pkg_t * pkg)213 char *pkg_get_md5(const pkg_t *pkg)
214 {
215 	char *p = pkg_get_raw(pkg, PKG_MD5SUM);
216 
217 	if (!p)
218 		return NULL;
219 
220 	return checksum_bin2hex(p, 16);
221 }
222 
pkg_set_md5(pkg_t * pkg,const char * cksum)223 char *pkg_set_md5(pkg_t *pkg, const char *cksum)
224 {
225 	size_t len;
226 	char *p = checksum_hex2bin(cksum, &len);
227 
228 	if (!p || len != 16)
229 		return NULL;
230 
231 	return pkg_set_raw(pkg, PKG_MD5SUM, p, len);
232 }
233 
pkg_get_sha256(const pkg_t * pkg)234 char *pkg_get_sha256(const pkg_t *pkg)
235 {
236 	char *p = pkg_get_raw(pkg, PKG_SHA256SUM);
237 
238 	if (!p)
239 		return NULL;
240 
241 	return checksum_bin2hex(p, 32);
242 }
243 
pkg_set_sha256(pkg_t * pkg,const char * cksum)244 char *pkg_set_sha256(pkg_t *pkg, const char *cksum)
245 {
246 	size_t len;
247 	char *p = checksum_hex2bin(cksum, &len);
248 
249 	if (!p || len != 32)
250 		return NULL;
251 
252 	return pkg_set_raw(pkg, PKG_SHA256SUM, p, len);
253 }
254 
255 
compound_depend_deinit(compound_depend_t * depends)256 static void compound_depend_deinit(compound_depend_t * depends)
257 {
258 	int i;
259 	for (i = 0; i < depends->possibility_count; i++) {
260 		depend_t *d;
261 		d = depends->possibilities[i];
262 		free(d->version);
263 		free(d);
264 	}
265 	free(depends->possibilities);
266 }
267 
pkg_deinit(pkg_t * pkg)268 void pkg_deinit(pkg_t * pkg)
269 {
270 	int rem;
271 	struct blob_attr *cur;
272 	compound_depend_t *deps, *dep;
273 	void *ptr;
274 
275 	if (pkg->name)
276 		free(pkg->name);
277 	pkg->name = NULL;
278 
279 	/* owned by opkg_conf_t */
280 	pkg->dest = NULL;
281 	/* owned by opkg_conf_t */
282 	pkg->src = NULL;
283 
284 	pkg->state_want = SW_UNKNOWN;
285 	pkg->state_flag = SF_OK;
286 	pkg->state_status = SS_NOT_INSTALLED;
287 
288 	blob_for_each_attr(cur, pkg->blob.head, rem) {
289 		switch (blob_id(cur)) {
290 		case PKG_DEPENDS:
291 		case PKG_CONFLICTS:
292 			deps = pkg_get_ptr(pkg, blob_id(cur));
293 
294 			if (deps) {
295 				for (dep = deps; dep->type; dep++)
296 					compound_depend_deinit(dep);
297 
298 				free(deps);
299 			}
300 
301 			pkg_set_ptr(pkg, blob_id(cur), NULL);
302 			break;
303 
304 		case PKG_REPLACES:
305 		case PKG_PROVIDES:
306 			ptr = pkg_get_ptr(pkg, blob_id(cur));
307 
308 			if (ptr)
309 				free(ptr);
310 
311 			pkg_set_ptr(pkg, blob_id(cur), NULL);
312 			break;
313 
314 		case PKG_CONFFILES:
315 			ptr = pkg_get_ptr(pkg, blob_id(cur));
316 
317 			if (ptr) {
318 				conffile_list_deinit(ptr);
319 				free(ptr);
320 			}
321 
322 			pkg_set_ptr(pkg, blob_id(cur), NULL);
323 			break;
324 		case PKG_ALTERNATIVES:
325 			ptr = pkg_get_ptr(pkg, blob_id(cur));
326 
327 			if (ptr) {
328 				struct pkg_alternatives *pkg_alts = ptr;
329 
330 				while (pkg_alts->nalts)
331 					free(pkg_alts->alts[--pkg_alts->nalts]);
332 				free(pkg_alts->alts);
333 				free(pkg_alts);
334 			}
335 
336 			pkg_set_ptr(pkg, blob_id(cur), NULL);
337 			break;
338 		}
339 	}
340 
341 	//conffile_list_deinit(&pkg->conffiles);
342 
343 	/* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
344 	   since if they are calling deinit, they should know. Maybe do an
345 	   assertion here instead? */
346 	pkg->installed_files_ref_cnt = 1;
347 	pkg_free_installed_files(pkg);
348 	pkg->essential = 0;
349 
350 	blob_buf_free(&pkg->blob);
351 }
352 
pkg_init_from_file(pkg_t * pkg,const char * filename)353 int pkg_init_from_file(pkg_t * pkg, const char *filename)
354 {
355 	int fd, err = 0;
356 	FILE *control_file;
357 	char *control_path, *tmp;
358 
359 	pkg_init(pkg);
360 
361 	if (!(pkg->state_flag & SF_NEED_DETAIL)) {
362 		opkg_msg(DEBUG, "applying abpkg flag to %s\n", filename);
363 		pkg->state_flag |= SF_NEED_DETAIL;
364 	}
365 
366 	pkg_set_string(pkg, PKG_LOCAL_FILENAME, filename);
367 
368 	tmp = xstrdup(filename);
369 	sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
370 		      conf->tmp_dir, basename(tmp));
371 	free(tmp);
372 	fd = mkstemp(control_path);
373 	if (fd == -1) {
374 		opkg_perror(ERROR, "Failed to make temp file %s", control_path);
375 		err = -1;
376 		goto err0;
377 	}
378 
379 	control_file = fdopen(fd, "r+");
380 	if (control_file == NULL) {
381 		opkg_perror(ERROR, "Failed to fdopen %s", control_path);
382 		close(fd);
383 		err = -1;
384 		goto err1;
385 	}
386 
387 	err = pkg_extract_control_file_to_stream(pkg, control_file);
388 	if (err) {
389 		opkg_msg(ERROR, "Failed to extract control file from %s.\n",
390 			 filename);
391 		goto err2;
392 	}
393 
394 	rewind(control_file);
395 
396 	if ((err = pkg_parse_from_stream(pkg, control_file, 0))) {
397 		if (err == 1) {
398 			opkg_msg(ERROR, "Malformed package file %s.\n",
399 				 filename);
400 		}
401 		err = -1;
402 	}
403 
404 err2:
405 	fclose(control_file);
406 err1:
407 	unlink(control_path);
408 err0:
409 	free(control_path);
410 
411 	return err;
412 }
413 
414 /* Merge any new information in newpkg into oldpkg */
pkg_merge(pkg_t * oldpkg,pkg_t * newpkg)415 int pkg_merge(pkg_t * oldpkg, pkg_t * newpkg)
416 {
417 	abstract_pkg_t **ab;
418 
419 	if (oldpkg == newpkg) {
420 		return 0;
421 	}
422 
423 	if (!oldpkg->auto_installed)
424 		oldpkg->auto_installed = newpkg->auto_installed;
425 
426 	if (!oldpkg->src)
427 		oldpkg->src = newpkg->src;
428 	if (!oldpkg->dest)
429 		oldpkg->dest = newpkg->dest;
430 	if (!oldpkg->arch_index)
431 		oldpkg->arch_index = newpkg->arch_index;
432 	if (!pkg_get_string(oldpkg, PKG_SECTION))
433 		pkg_set_string(oldpkg, PKG_SECTION, pkg_get_string(newpkg, PKG_SECTION));
434 	if (!pkg_get_string(oldpkg, PKG_MAINTAINER))
435 		pkg_set_string(oldpkg, PKG_MAINTAINER, pkg_get_string(newpkg, PKG_MAINTAINER));
436 	if (!pkg_get_string(oldpkg, PKG_DESCRIPTION))
437 		pkg_set_string(oldpkg, PKG_DESCRIPTION, pkg_get_string(newpkg, PKG_DESCRIPTION));
438 
439 	if (!pkg_get_ptr(oldpkg, PKG_DEPENDS)) {
440 		pkg_set_ptr(oldpkg, PKG_DEPENDS, pkg_get_ptr(newpkg, PKG_DEPENDS));
441 		pkg_set_ptr(newpkg, PKG_DEPENDS, NULL);
442 	}
443 
444 	ab = pkg_get_ptr(oldpkg, PKG_PROVIDES);
445 
446 	if (!ab || !ab[0] || !ab[1]) {
447 		pkg_set_ptr(oldpkg, PKG_PROVIDES, pkg_get_ptr(newpkg, PKG_PROVIDES));
448 		pkg_set_ptr(newpkg, PKG_PROVIDES, NULL);
449 
450 		if (ab)
451 			free(ab);
452 	}
453 
454 	if (!pkg_get_ptr(oldpkg, PKG_CONFLICTS)) {
455 		pkg_set_ptr(oldpkg, PKG_CONFLICTS, pkg_get_ptr(newpkg, PKG_CONFLICTS));
456 		pkg_set_ptr(newpkg, PKG_CONFLICTS, NULL);
457 	}
458 
459 	if (!pkg_get_ptr(oldpkg, PKG_REPLACES)) {
460 		pkg_set_ptr(oldpkg, PKG_REPLACES, pkg_get_ptr(newpkg, PKG_REPLACES));
461 		pkg_set_ptr(newpkg, PKG_REPLACES, NULL);
462 	}
463 
464 	if (!pkg_get_string(oldpkg, PKG_FILENAME))
465 		pkg_set_string(oldpkg, PKG_FILENAME, pkg_get_string(newpkg, PKG_FILENAME));
466 	if (!pkg_get_string(oldpkg, PKG_LOCAL_FILENAME))
467 		pkg_set_string(oldpkg, PKG_LOCAL_FILENAME, pkg_get_string(newpkg, PKG_LOCAL_FILENAME));
468 	if (!pkg_get_string(oldpkg, PKG_TMP_UNPACK_DIR))
469 		pkg_set_string(oldpkg, PKG_TMP_UNPACK_DIR, pkg_get_string(newpkg, PKG_TMP_UNPACK_DIR));
470 	if (!pkg_get_md5(oldpkg))
471 		pkg_set_md5(oldpkg, pkg_get_md5(newpkg));
472 	if (!pkg_get_sha256(oldpkg))
473 		pkg_set_sha256(oldpkg, pkg_get_sha256(newpkg));
474 	if (!pkg_get_int(oldpkg, PKG_SIZE))
475 		pkg_set_int(oldpkg, PKG_SIZE, pkg_get_int(newpkg, PKG_SIZE));
476 	if (!pkg_get_int(oldpkg, PKG_INSTALLED_SIZE))
477 		pkg_set_int(oldpkg, PKG_INSTALLED_SIZE, pkg_get_int(newpkg, PKG_INSTALLED_SIZE));
478 	if (!pkg_get_string(oldpkg, PKG_PRIORITY))
479 		pkg_set_string(oldpkg, PKG_PRIORITY, pkg_get_string(newpkg, PKG_PRIORITY));
480 	if (!pkg_get_string(oldpkg, PKG_SOURCE))
481 		pkg_set_string(oldpkg, PKG_SOURCE, pkg_get_string(newpkg, PKG_SOURCE));
482 
483 	if (!pkg_get_ptr(oldpkg, PKG_CONFFILES)) {
484 		pkg_set_ptr(oldpkg, PKG_CONFFILES, pkg_get_ptr(newpkg, PKG_CONFFILES));
485 		pkg_set_ptr(newpkg, PKG_CONFFILES, NULL);
486 	}
487 
488 	if (!oldpkg->installed_files) {
489 		oldpkg->installed_files = newpkg->installed_files;
490 		oldpkg->installed_files_ref_cnt =
491 		    newpkg->installed_files_ref_cnt;
492 		newpkg->installed_files = NULL;
493 	}
494 
495 	if (!oldpkg->essential)
496 		oldpkg->essential = newpkg->essential;
497 
498 	if (!oldpkg->provided_by_hand)
499 		oldpkg->provided_by_hand = newpkg->provided_by_hand;
500 
501 	return 0;
502 }
503 
abstract_pkg_init(abstract_pkg_t * ab_pkg)504 static void abstract_pkg_init(abstract_pkg_t * ab_pkg)
505 {
506 	ab_pkg->provided_by = abstract_pkg_vec_alloc();
507 	ab_pkg->dependencies_checked = 0;
508 	ab_pkg->state_status = SS_NOT_INSTALLED;
509 }
510 
abstract_pkg_new(void)511 abstract_pkg_t *abstract_pkg_new(void)
512 {
513 	abstract_pkg_t *ab_pkg;
514 
515 	ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
516 	abstract_pkg_init(ab_pkg);
517 
518 	return ab_pkg;
519 }
520 
pkg_state_want_to_str(pkg_state_want_t sw)521 static const char *pkg_state_want_to_str(pkg_state_want_t sw)
522 {
523 	int i;
524 
525 	for (i = 0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
526 		if (pkg_state_want_map[i].value == sw) {
527 			return pkg_state_want_map[i].str;
528 		}
529 	}
530 
531 	opkg_msg(ERROR, "Internal error: state_want=%d\n", sw);
532 	return "<STATE_WANT_UNKNOWN>";
533 }
534 
pkg_state_want_from_str(char * str)535 pkg_state_want_t pkg_state_want_from_str(char *str)
536 {
537 	int i;
538 
539 	for (i = 0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
540 		if (strcmp(str, pkg_state_want_map[i].str) == 0) {
541 			return pkg_state_want_map[i].value;
542 		}
543 	}
544 
545 	opkg_msg(ERROR, "Internal error: state_want=%s\n", str);
546 	return SW_UNKNOWN;
547 }
548 
pkg_state_flag_to_str(pkg_state_flag_t sf)549 static char *pkg_state_flag_to_str(pkg_state_flag_t sf)
550 {
551 	int i;
552 	unsigned int len;
553 	char *str;
554 
555 	/* clear the temporary flags before converting to string */
556 	sf &= SF_NONVOLATILE_FLAGS;
557 
558 	if (sf == 0)
559 		return xstrdup("ok");
560 
561 	len = 0;
562 	for (i = 0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
563 		if (sf & pkg_state_flag_map[i].value)
564 			len += strlen(pkg_state_flag_map[i].str) + 1;
565 	}
566 
567 	str = xmalloc(len + 1);
568 	str[0] = '\0';
569 
570 	for (i = 0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
571 		if (sf & pkg_state_flag_map[i].value) {
572 			strncat(str, pkg_state_flag_map[i].str, len);
573 			strncat(str, ",", len);
574 		}
575 	}
576 
577 	len = strlen(str);
578 	str[len - 1] = '\0';	/* squash last comma */
579 
580 	return str;
581 }
582 
pkg_state_flag_from_str(const char * str)583 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
584 {
585 	int i;
586 	int sf = SF_OK;
587 	const char *sfname;
588 	unsigned int sfname_len;
589 
590 	if (strcmp(str, "ok") == 0) {
591 		return SF_OK;
592 	}
593 	for (i = 0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
594 		sfname = pkg_state_flag_map[i].str;
595 		sfname_len = strlen(sfname);
596 		if (strncmp(str, sfname, sfname_len) == 0) {
597 			sf |= pkg_state_flag_map[i].value;
598 			str += sfname_len;
599 			if (str[0] == ',') {
600 				str++;
601 			} else {
602 				break;
603 			}
604 		}
605 	}
606 
607 	return sf;
608 }
609 
pkg_state_status_to_str(pkg_state_status_t ss)610 static const char *pkg_state_status_to_str(pkg_state_status_t ss)
611 {
612 	int i;
613 
614 	for (i = 0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
615 		if (pkg_state_status_map[i].value == ss) {
616 			return pkg_state_status_map[i].str;
617 		}
618 	}
619 
620 	opkg_msg(ERROR, "Internal error: state_status=%d\n", ss);
621 	return "<STATE_STATUS_UNKNOWN>";
622 }
623 
pkg_state_status_from_str(const char * str)624 pkg_state_status_t pkg_state_status_from_str(const char *str)
625 {
626 	int i;
627 
628 	for (i = 0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
629 		if (strcmp(str, pkg_state_status_map[i].str) == 0) {
630 			return pkg_state_status_map[i].value;
631 		}
632 	}
633 
634 	opkg_msg(ERROR, "Internal error: state_status=%s\n", str);
635 	return SS_NOT_INSTALLED;
636 }
637 
pkg_formatted_field(FILE * fp,pkg_t * pkg,const char * field)638 void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
639 {
640 	int i, j;
641 	char *str;
642 	const char *p;
643 	compound_depend_t *dep;
644 	abstract_pkg_t **ab_pkg;
645 
646 	if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
647 		goto UNKNOWN_FMT_FIELD;
648 	}
649 
650 	switch (field[0]) {
651 	case 'a':
652 	case 'A':
653 		if (strcasecmp(field, "Alternatives") == 0) {
654 			struct pkg_alternatives *pkg_alts = pkg_get_ptr(pkg, PKG_ALTERNATIVES);
655 
656 			if (pkg_alts && pkg_alts->nalts > 0) {
657 				int i;
658 				struct pkg_alternative *alt;
659 
660 				alt = pkg_alts->alts[0];
661 				fprintf(fp, "Alternatives: %d:%s:%s", alt->prio, alt->path, alt->altpath);
662 				for (i = 1; i < pkg_alts->nalts; i++) {
663 					alt = pkg_alts->alts[i];
664 					fprintf(fp, ", %d:%s:%s", alt->prio, alt->path, alt->altpath);
665 				}
666 				fputs("\n", fp);
667 			}
668 		} else if (strcasecmp(field, "Architecture") == 0) {
669 			p = pkg_get_architecture(pkg);
670 			if (p) {
671 				fprintf(fp, "Architecture: %s\n",
672 					p);
673 			}
674 		} else if (strcasecmp(field, "Auto-Installed") == 0) {
675 			if (pkg->auto_installed)
676 				fprintf(fp, "Auto-Installed: yes\n");
677 		} else {
678 			goto UNKNOWN_FMT_FIELD;
679 		}
680 		break;
681 	case 'c':
682 	case 'C':
683 		if (strcasecmp(field, "Conffiles") == 0) {
684 			conffile_list_t *cl;
685 			conffile_list_elt_t *iter;
686 
687 			cl = pkg_get_ptr(pkg, PKG_CONFFILES);
688 
689 			if (!cl || nv_pair_list_empty(cl))
690 				return;
691 
692 			fprintf(fp, "Conffiles:\n");
693 			for (iter = nv_pair_list_first(cl); iter;
694 			     iter = nv_pair_list_next(cl, iter)) {
695 				if (((conffile_t *) iter->data)->name
696 				    && ((conffile_t *) iter->data)->value) {
697 					fprintf(fp, " %s %s\n",
698 						((conffile_t *) iter->data)->
699 						name,
700 						((conffile_t *) iter->data)->
701 						value);
702 				}
703 			}
704 		} else if (strcasecmp(field, "Conflicts") == 0) {
705 			struct depend *cdep;
706 			compound_depend_t *deps, *dep;
707 			deps = pkg_get_ptr(pkg, PKG_CONFLICTS);
708 			if (deps) {
709 				fprintf(fp, "Conflicts:");
710 				for (i = 0, dep = deps; dep->type; dep++, i++) {
711 					cdep = dep->possibilities[0];
712 					fprintf(fp, "%s %s", i == 0 ? "" : ",",
713 						cdep->pkg->name);
714 					if (cdep->version) {
715 						fprintf(fp, " (%s%s)",
716 							constraint_to_str(cdep->
717 									  constraint),
718 							cdep->version);
719 					}
720 				}
721 				fprintf(fp, "\n");
722 			}
723 		} else {
724 			goto UNKNOWN_FMT_FIELD;
725 		}
726 		break;
727 	case 'd':
728 	case 'D':
729 		if (strcasecmp(field, "Depends") == 0) {
730 			dep = pkg_get_depends(pkg, DEPEND);
731 			if (dep) {
732 				fprintf(fp, "Depends:");
733 				for (i = 0, j = 0; dep && dep->type; i++, dep++) {
734 					if (dep->type != DEPEND)
735 						continue;
736 					str = pkg_depend_str(pkg, i);
737 					fprintf(fp, "%s %s", j == 0 ? "" : ",",
738 						str);
739 					free(str);
740 					j++;
741 				}
742 				fprintf(fp, "\n");
743 			}
744 		} else if (strcasecmp(field, "Description") == 0) {
745 			p = pkg_get_string(pkg, PKG_DESCRIPTION);
746 			if (p) {
747 				fprintf(fp, "Description: %s\n",
748 					p);
749 			}
750 		} else {
751 			goto UNKNOWN_FMT_FIELD;
752 		}
753 		break;
754 	case 'e':
755 	case 'E':
756 		if (pkg->essential) {
757 			fprintf(fp, "Essential: yes\n");
758 		}
759 		break;
760 	case 'f':
761 	case 'F':
762 		p = pkg_get_string(pkg, PKG_FILENAME);
763 		if (p) {
764 			fprintf(fp, "Filename: %s\n", p);
765 		}
766 		break;
767 	case 'i':
768 	case 'I':
769 		if (strcasecmp(field, "Installed-Size") == 0) {
770 			fprintf(fp, "Installed-Size: %lu\n",
771 				(unsigned long) pkg_get_int(pkg, PKG_INSTALLED_SIZE));
772 		} else if (strcasecmp(field, "Installed-Time") == 0) {
773 			i = pkg_get_int(pkg, PKG_INSTALLED_TIME);
774 			if (i) {
775 				fprintf(fp, "Installed-Time: %lu\n",
776 					(unsigned long) i);
777 			}
778 		}
779 		break;
780 	case 'm':
781 	case 'M':
782 		if (strcasecmp(field, "Maintainer") == 0) {
783 			p = pkg_get_string(pkg, PKG_MAINTAINER);
784 			if (p) {
785 				fprintf(fp, "Maintainer: %s\n", p);
786 			}
787 		} else if (strcasecmp(field, "MD5sum") == 0) {
788 			p = pkg_get_md5(pkg);
789 			if (p) {
790 				fprintf(fp, "MD5Sum: %s\n", p);
791 			}
792 		} else {
793 			goto UNKNOWN_FMT_FIELD;
794 		}
795 		break;
796 	case 'p':
797 	case 'P':
798 		if (strcasecmp(field, "Package") == 0) {
799 			fprintf(fp, "Package: %s\n", pkg->name);
800 		} else if (strcasecmp(field, "Priority") == 0) {
801 			fprintf(fp, "Priority: %s\n", pkg_get_string(pkg, PKG_PRIORITY));
802 		} else if (strcasecmp(field, "Provides") == 0) {
803 			ab_pkg = pkg_get_ptr(pkg, PKG_PROVIDES);
804 			if (ab_pkg && ab_pkg[0] && ab_pkg[1]) {
805 				fprintf(fp, "Provides:");
806 				for (i = 1; ab_pkg[i]; i++) {
807 					fprintf(fp, "%s %s", i == 1 ? "" : ",",
808 						ab_pkg[i]->name);
809 				}
810 				fprintf(fp, "\n");
811 			}
812 		} else {
813 			goto UNKNOWN_FMT_FIELD;
814 		}
815 		break;
816 	case 'r':
817 	case 'R':
818 		if (strcasecmp(field, "Replaces") == 0) {
819 			ab_pkg = pkg_get_ptr(pkg, PKG_REPLACES);
820 			if (ab_pkg && *ab_pkg) {
821 				fprintf(fp, "Replaces:");
822 				for (i = 0; *ab_pkg; i++, ab_pkg++) {
823 					fprintf(fp, "%s %s", i == 0 ? "" : ",",
824 						(*ab_pkg)->name);
825 				}
826 				fprintf(fp, "\n");
827 			}
828 		} else if (strcasecmp(field, "Recommends") == 0) {
829 			dep = pkg_get_depends(pkg, RECOMMEND);
830 			if (dep) {
831 				fprintf(fp, "Recommends:");
832 				for (j = 0, i = 0; dep && dep->type; i++, dep++) {
833 					if (dep->type != RECOMMEND)
834 						continue;
835 					str = pkg_depend_str(pkg, i);
836 					fprintf(fp, "%s %s", j == 0 ? "" : ",",
837 						str);
838 					free(str);
839 					j++;
840 				}
841 				fprintf(fp, "\n");
842 			}
843 		} else {
844 			goto UNKNOWN_FMT_FIELD;
845 		}
846 		break;
847 	case 's':
848 	case 'S':
849 		if (strcasecmp(field, "Section") == 0) {
850 			p = pkg_get_string(pkg, PKG_SECTION);
851 			if (p) {
852 				fprintf(fp, "Section: %s\n", p);
853 			}
854 		} else if (strcasecmp(field, "SHA256sum") == 0) {
855 			p = pkg_get_string(pkg, PKG_SHA256SUM);
856 			if (p) {
857 				fprintf(fp, "SHA256sum: %s\n", p);
858 			}
859 		} else if (strcasecmp(field, "Size") == 0) {
860 			i = pkg_get_int(pkg, PKG_SIZE);
861 			if (i) {
862 				fprintf(fp, "Size: %lu\n", (unsigned long) i);
863 			}
864 		} else if (strcasecmp(field, "Source") == 0) {
865 			p = pkg_get_string(pkg, PKG_SOURCE);
866 			if (p) {
867 				fprintf(fp, "Source: %s\n", p);
868 			}
869 		} else if (strcasecmp(field, "Status") == 0) {
870 			char *pflag = pkg_state_flag_to_str(pkg->state_flag);
871 			fprintf(fp, "Status: %s %s %s\n",
872 				pkg_state_want_to_str(pkg->state_want),
873 				pflag,
874 				pkg_state_status_to_str(pkg->state_status));
875 			free(pflag);
876 		} else if (strcasecmp(field, "Suggests") == 0) {
877 			dep = pkg_get_depends(pkg, SUGGEST);
878 			if (dep) {
879 				fprintf(fp, "Suggests:");
880 				for (j = 0, i = 0; dep && dep->type; i++, dep++) {
881 					if (dep->type != SUGGEST)
882 						continue;
883 					str = pkg_depend_str(pkg, i);
884 					fprintf(fp, "%s %s", j == 0 ? "" : ",",
885 						str);
886 					free(str);
887 					j++;
888 				}
889 				fprintf(fp, "\n");
890 			}
891 		} else {
892 			goto UNKNOWN_FMT_FIELD;
893 		}
894 		break;
895 	case 't':
896 	case 'T':
897 		if (strcasecmp(field, "Tags") == 0) {
898 			p = pkg_get_string(pkg, PKG_TAGS);
899 			if (p) {
900 				fprintf(fp, "Tags: %s\n", p);
901 			}
902 		}
903 		break;
904 	case 'v':
905 	case 'V':
906 		{
907 			char *version = pkg_version_str_alloc(pkg);
908 			if (version == NULL)
909 				return;
910 			fprintf(fp, "Version: %s\n", version);
911 			free(version);
912 		}
913 		break;
914 	default:
915 		goto UNKNOWN_FMT_FIELD;
916 	}
917 
918 	return;
919 
920 UNKNOWN_FMT_FIELD:
921 	opkg_msg(ERROR, "Internal error: field=%s\n", field);
922 }
923 
pkg_formatted_info(FILE * fp,pkg_t * pkg)924 void pkg_formatted_info(FILE * fp, pkg_t * pkg)
925 {
926 	pkg_formatted_field(fp, pkg, "Package");
927 	pkg_formatted_field(fp, pkg, "Version");
928 	pkg_formatted_field(fp, pkg, "Depends");
929 	pkg_formatted_field(fp, pkg, "Recommends");
930 	pkg_formatted_field(fp, pkg, "Suggests");
931 	pkg_formatted_field(fp, pkg, "Provides");
932 	pkg_formatted_field(fp, pkg, "Replaces");
933 	pkg_formatted_field(fp, pkg, "Conflicts");
934 	pkg_formatted_field(fp, pkg, "Status");
935 	pkg_formatted_field(fp, pkg, "Section");
936 	pkg_formatted_field(fp, pkg, "Essential");
937 	pkg_formatted_field(fp, pkg, "Architecture");
938 	pkg_formatted_field(fp, pkg, "Maintainer");
939 	pkg_formatted_field(fp, pkg, "MD5sum");
940 	pkg_formatted_field(fp, pkg, "Size");
941 	pkg_formatted_field(fp, pkg, "Filename");
942 	pkg_formatted_field(fp, pkg, "Conffiles");
943 	pkg_formatted_field(fp, pkg, "Source");
944 	pkg_formatted_field(fp, pkg, "Description");
945 	pkg_formatted_field(fp, pkg, "Installed-Time");
946 	pkg_formatted_field(fp, pkg, "Tags");
947 	fputs("\n", fp);
948 }
949 
pkg_print_status(pkg_t * pkg,FILE * file)950 void pkg_print_status(pkg_t * pkg, FILE * file)
951 {
952 	if (pkg == NULL) {
953 		return;
954 	}
955 
956 	pkg_formatted_field(file, pkg, "Package");
957 	pkg_formatted_field(file, pkg, "Version");
958 	pkg_formatted_field(file, pkg, "Depends");
959 	pkg_formatted_field(file, pkg, "Recommends");
960 	pkg_formatted_field(file, pkg, "Suggests");
961 	pkg_formatted_field(file, pkg, "Provides");
962 	pkg_formatted_field(file, pkg, "Replaces");
963 	pkg_formatted_field(file, pkg, "Conflicts");
964 	pkg_formatted_field(file, pkg, "Status");
965 	pkg_formatted_field(file, pkg, "Essential");
966 	pkg_formatted_field(file, pkg, "Architecture");
967 	pkg_formatted_field(file, pkg, "Conffiles");
968 	pkg_formatted_field(file, pkg, "Installed-Time");
969 	pkg_formatted_field(file, pkg, "Auto-Installed");
970 	pkg_formatted_field(file, pkg, "Alternatives");
971 	fputs("\n", file);
972 }
973 
974 /*
975  * libdpkg - Debian packaging suite library routines
976  * vercmp.c - comparison of version numbers
977  *
978  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
979  */
980 
981 /* assume ascii; warning: evaluates x multiple times! */
982 #define order(x) ((x) == '~' ? -1 \
983 		: isdigit((x)) ? 0 \
984 		: !(x) ? 0 \
985 		: isalpha((x)) ? (x) \
986 		: (x) + 256)
987 
verrevcmp(const char * val,const char * ref)988 static int verrevcmp(const char *val, const char *ref)
989 {
990 	if (!val)
991 		val = "";
992 	if (!ref)
993 		ref = "";
994 
995 	while (*val || *ref) {
996 		int first_diff = 0;
997 
998 		while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
999 			int vc = order(*val), rc = order(*ref);
1000 			if (vc != rc)
1001 				return vc - rc;
1002 			val++;
1003 			ref++;
1004 		}
1005 
1006 		while (*val == '0')
1007 			val++;
1008 		while (*ref == '0')
1009 			ref++;
1010 		while (isdigit(*val) && isdigit(*ref)) {
1011 			if (!first_diff)
1012 				first_diff = *val - *ref;
1013 			val++;
1014 			ref++;
1015 		}
1016 		if (isdigit(*val))
1017 			return 1;
1018 		if (isdigit(*ref))
1019 			return -1;
1020 		if (first_diff)
1021 			return first_diff;
1022 	}
1023 	return 0;
1024 }
1025 
pkg_compare_versions(const pkg_t * pkg,const pkg_t * ref_pkg)1026 int pkg_compare_versions(const pkg_t * pkg, const pkg_t * ref_pkg)
1027 {
1028 	unsigned int epoch1 = (unsigned int) pkg_get_int(pkg, PKG_EPOCH);
1029 	unsigned int epoch2 = (unsigned int) pkg_get_int(ref_pkg, PKG_EPOCH);
1030 	char *revision1 = pkg_get_string(pkg, PKG_REVISION);
1031 	char *revision2 = pkg_get_string(ref_pkg, PKG_REVISION);
1032 	const char *version1 = pkg_get_string(pkg, PKG_VERSION);
1033 	const char *version2 = pkg_get_string(ref_pkg, PKG_VERSION);
1034 	int r;
1035 
1036 	if (epoch1 > epoch2) {
1037 		return 1;
1038 	}
1039 
1040 	if (epoch1 < epoch2) {
1041 		return -1;
1042 	}
1043 
1044 	r = verrevcmp(version1, version2);
1045 	if (r) {
1046 		return r;
1047 	}
1048 
1049 	r = verrevcmp(revision1, revision2);
1050 	if (r) {
1051 		return r;
1052 	}
1053 
1054 	return r;
1055 }
1056 
pkg_version_satisfied(pkg_t * it,pkg_t * ref,const char * op)1057 int pkg_version_satisfied(pkg_t * it, pkg_t * ref, const char *op)
1058 {
1059 	int r;
1060 
1061 	r = pkg_compare_versions(it, ref);
1062 
1063 	if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1064 		return r <= 0;
1065 	}
1066 
1067 	if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1068 		return r >= 0;
1069 	}
1070 
1071 	if (strcmp(op, "<<") == 0) {
1072 		return r < 0;
1073 	}
1074 
1075 	if (strcmp(op, ">>") == 0) {
1076 		return r > 0;
1077 	}
1078 
1079 	if (strcmp(op, "=") == 0) {
1080 		return r == 0;
1081 	}
1082 
1083 	opkg_msg(ERROR, "Unknown operator: %s.\n", op);
1084 	return 0;
1085 }
1086 
pkg_name_version_and_architecture_compare(const void * p1,const void * p2)1087 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1088 {
1089 	const pkg_t * a = *(const pkg_t **)p1;
1090 	const pkg_t * b = *(const pkg_t **)p2;
1091 	int namecmp;
1092 	int vercmp;
1093 	int arch_prio1, arch_prio2;
1094 	if (!a->name || !b->name) {
1095 		opkg_msg(ERROR, "Internal error: a->name=%p, b->name=%p.\n",
1096 			 a->name, b->name);
1097 		return 0;
1098 	}
1099 
1100 	namecmp = strcmp(a->name, b->name);
1101 	if (namecmp)
1102 		return namecmp;
1103 	vercmp = pkg_compare_versions(a, b);
1104 	if (vercmp)
1105 		return vercmp;
1106 	arch_prio1 = pkg_get_arch_priority(a);
1107 	arch_prio2 = pkg_get_arch_priority(b);
1108 	if (!arch_prio1 || !arch_prio2) {
1109 		opkg_msg(ERROR,
1110 			 "Internal error: a->arch_priority=%i b->arch_priority=%i.\n",
1111 			 arch_prio1, arch_prio2);
1112 		return 0;
1113 	}
1114 	if (arch_prio1 > arch_prio2)
1115 		return 1;
1116 	if (arch_prio1 < arch_prio2)
1117 		return -1;
1118 	return 0;
1119 }
1120 
abstract_pkg_name_compare(const void * p1,const void * p2)1121 int abstract_pkg_name_compare(const void *p1, const void *p2)
1122 {
1123 	const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1124 	const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1125 	if (!a->name || !b->name) {
1126 		opkg_msg(ERROR, "Internal error: a->name=%p b->name=%p.\n",
1127 			 a->name, b->name);
1128 		return 0;
1129 	}
1130 	return strcmp(a->name, b->name);
1131 }
1132 
pkg_version_str_alloc(pkg_t * pkg)1133 char *pkg_version_str_alloc(pkg_t * pkg)
1134 {
1135 	const char *verstr;
1136 	char *version, *revptr;
1137 	unsigned int epoch = (unsigned int) pkg_get_int(pkg, PKG_EPOCH);
1138 
1139 	revptr = pkg_get_string(pkg, PKG_REVISION);
1140 	verstr = pkg_get_string(pkg, PKG_VERSION);
1141 
1142 	if (epoch) {
1143 		if (revptr)
1144 			sprintf_alloc(&version, "%d:%s-%s",
1145 				      epoch, verstr, revptr);
1146 		else
1147 			sprintf_alloc(&version, "%d:%s",
1148 				      epoch, verstr);
1149 	} else {
1150 		if (revptr)
1151 			sprintf_alloc(&version, "%s-%s",
1152 				      verstr, revptr);
1153 		else
1154 			version = xstrdup(verstr);
1155 	}
1156 
1157 	return version;
1158 }
1159 
1160 /*
1161  * XXX: this should be broken into two functions
1162  */
pkg_get_installed_files(pkg_t * pkg)1163 str_list_t *pkg_get_installed_files(pkg_t * pkg)
1164 {
1165 	int err, fd;
1166 	char *list_file_name = NULL;
1167 	FILE *list_file = NULL;
1168 	char *line;
1169 	char *installed_file_name;
1170 	unsigned int rootdirlen = 0;
1171 	int list_from_package;
1172 	const char *local_filename;
1173 
1174 	pkg->installed_files_ref_cnt++;
1175 
1176 	if (pkg->installed_files) {
1177 		return pkg->installed_files;
1178 	}
1179 
1180 	pkg->installed_files = str_list_alloc();
1181 
1182 	/*
1183 	 * For installed packages, look at the package.list file in the database.
1184 	 * For uninstalled packages, get the file list directly from the package.
1185 	 */
1186 	if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL)
1187 		list_from_package = 1;
1188 	else
1189 		list_from_package = 0;
1190 
1191 	if (list_from_package) {
1192 		local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
1193 
1194 		if (!local_filename) {
1195 			return pkg->installed_files;
1196 		}
1197 		/* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1198 		   file. In other words, change deb_extract so that it can
1199 		   simply return the file list as a char *[] rather than
1200 		   insisting on writing it to a FILE * as it does now. */
1201 		sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1202 			      conf->tmp_dir, pkg->name);
1203 		fd = mkstemp(list_file_name);
1204 		if (fd == -1) {
1205 			opkg_perror(ERROR, "Failed to make temp file %s.",
1206 				    list_file_name);
1207 			free(list_file_name);
1208 			return pkg->installed_files;
1209 		}
1210 		list_file = fdopen(fd, "r+");
1211 		if (list_file == NULL) {
1212 			opkg_perror(ERROR, "Failed to fdopen temp file %s.",
1213 				    list_file_name);
1214 			close(fd);
1215 			unlink(list_file_name);
1216 			free(list_file_name);
1217 			return pkg->installed_files;
1218 		}
1219 		err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1220 		if (err) {
1221 			opkg_msg(ERROR, "Error extracting file list from %s.\n",
1222 				 local_filename);
1223 			fclose(list_file);
1224 			unlink(list_file_name);
1225 			free(list_file_name);
1226 			str_list_deinit(pkg->installed_files);
1227 			pkg->installed_files = NULL;
1228 			return NULL;
1229 		}
1230 		rewind(list_file);
1231 	} else {
1232 		sprintf_alloc(&list_file_name, "%s/%s.list",
1233 			      pkg->dest->info_dir, pkg->name);
1234 		list_file = fopen(list_file_name, "r");
1235 		if (list_file == NULL) {
1236 			opkg_perror(ERROR, "Failed to open %s", list_file_name);
1237 			free(list_file_name);
1238 			return pkg->installed_files;
1239 		}
1240 		free(list_file_name);
1241 	}
1242 
1243 	if (conf->offline_root)
1244 		rootdirlen = strlen(conf->offline_root);
1245 
1246 	while (1) {
1247 		char *file_name;
1248 
1249 		line = file_read_line_alloc(list_file);
1250 		if (line == NULL) {
1251 			break;
1252 		}
1253 		file_name = line;
1254 
1255 		if (list_from_package) {
1256 			if (*file_name == '.') {
1257 				file_name++;
1258 			}
1259 			if (*file_name == '/') {
1260 				file_name++;
1261 			}
1262 			sprintf_alloc(&installed_file_name, "%s%s",
1263 				      pkg->dest->root_dir, file_name);
1264 		} else {
1265 			if (conf->offline_root &&
1266 			    strncmp(conf->offline_root, file_name,
1267 				    rootdirlen)) {
1268 				sprintf_alloc(&installed_file_name, "%s%s",
1269 					      conf->offline_root, file_name);
1270 			} else {
1271 				// already contains root_dir as header -> ABSOLUTE
1272 				sprintf_alloc(&installed_file_name, "%s",
1273 					      file_name);
1274 			}
1275 		}
1276 		str_list_append(pkg->installed_files, installed_file_name);
1277 		free(installed_file_name);
1278 		free(line);
1279 	}
1280 
1281 	fclose(list_file);
1282 
1283 	if (list_from_package) {
1284 		unlink(list_file_name);
1285 		free(list_file_name);
1286 	}
1287 
1288 	return pkg->installed_files;
1289 }
1290 
1291 /* XXX: CLEANUP: This function and it's counterpart,
1292    (pkg_get_installed_files), do not match our init/deinit naming
1293    convention. Nor the alloc/free convention. But, then again, neither
1294    of these conventions currrently fit the way these two functions
1295    work. */
pkg_free_installed_files(pkg_t * pkg)1296 void pkg_free_installed_files(pkg_t * pkg)
1297 {
1298 	pkg->installed_files_ref_cnt--;
1299 
1300 	if (pkg->installed_files_ref_cnt > 0)
1301 		return;
1302 
1303 	if (pkg->installed_files) {
1304 		str_list_purge(pkg->installed_files);
1305 	}
1306 
1307 	pkg->installed_files = NULL;
1308 }
1309 
pkg_remove_installed_files_list(pkg_t * pkg)1310 void pkg_remove_installed_files_list(pkg_t * pkg)
1311 {
1312 	char *list_file_name;
1313 
1314 	sprintf_alloc(&list_file_name, "%s/%s.list",
1315 		      pkg->dest->info_dir, pkg->name);
1316 
1317 	if (!conf->noaction)
1318 		(void)unlink(list_file_name);
1319 
1320 	free(list_file_name);
1321 }
1322 
pkg_get_conffile(pkg_t * pkg,const char * file_name)1323 conffile_t *pkg_get_conffile(pkg_t * pkg, const char *file_name)
1324 {
1325 	conffile_list_elt_t *iter;
1326 	conffile_list_t *cl;
1327 	conffile_t *conffile;
1328 
1329 	if (pkg == NULL) {
1330 		return NULL;
1331 	}
1332 
1333 	cl = pkg_get_ptr(pkg, PKG_CONFFILES);
1334 
1335 	for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
1336 	     iter = nv_pair_list_next(cl, iter)) {
1337 		conffile = (conffile_t *) iter->data;
1338 
1339 		if (strcmp(conffile->name, file_name) == 0) {
1340 			return conffile;
1341 		}
1342 	}
1343 
1344 	return NULL;
1345 }
1346 
pkg_run_script(pkg_t * pkg,const char * script,const char * args)1347 int pkg_run_script(pkg_t * pkg, const char *script, const char *args)
1348 {
1349 	int err;
1350 	char *path;
1351 	char *cmd;
1352 	char *tmp_unpack_dir;
1353 
1354 	if (conf->noaction)
1355 		return 0;
1356 
1357 	/* XXX: FEATURE: When conf->offline_root is set, we should run the
1358 	   maintainer script within a chroot environment. */
1359 	if (conf->offline_root && !conf->force_postinstall) {
1360 		opkg_msg(INFO, "Offline root mode: not running %s.%s.\n",
1361 			 pkg->name, script);
1362 		return 0;
1363 	}
1364 
1365 	/* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1366 	   have scripts in tmp_unpack_dir. */
1367 	if (pkg->state_status == SS_INSTALLED
1368 	    || pkg->state_status == SS_UNPACKED
1369 	    || pkg->state_status == SS_HALF_INSTALLED) {
1370 		if (pkg->dest == NULL) {
1371 			opkg_msg(ERROR, "Internal error: %s has a NULL dest.\n",
1372 				 pkg->name);
1373 			return -1;
1374 		}
1375 		sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name,
1376 			      script);
1377 	} else {
1378 		tmp_unpack_dir = pkg_get_string(pkg, PKG_TMP_UNPACK_DIR);
1379 		if (tmp_unpack_dir == NULL) {
1380 			opkg_msg(ERROR,
1381 				 "Internal error: %s has a NULL tmp_unpack_dir.\n",
1382 				 pkg->name);
1383 			return -1;
1384 		}
1385 		sprintf_alloc(&path, "%s/%s", tmp_unpack_dir, script);
1386 	}
1387 
1388 	opkg_msg(INFO, "Running script %s.\n", path);
1389 
1390 	setenv("PKG_ROOT",
1391 	       pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir,
1392 	       1);
1393 
1394 	if (pkg->is_upgrade)
1395 		setenv("PKG_UPGRADE", "1", 1);
1396 	else
1397 		setenv("PKG_UPGRADE", "0", 1);
1398 
1399 	if (!file_exists(path)) {
1400 		free(path);
1401 		return 0;
1402 	}
1403 
1404 	sprintf_alloc(&cmd, "%s %s", path, args);
1405 	free(path);
1406 	{
1407 		const char *argv[] = { "/bin/sh", "-c", cmd, NULL };
1408 		err = xsystem(argv);
1409 	}
1410 	free(cmd);
1411 
1412 	if (err) {
1413 		opkg_msg(ERROR,
1414 			 "package \"%s\" %s script returned status %d.\n",
1415 			 pkg->name, script, err);
1416 		return err;
1417 	}
1418 
1419 	return 0;
1420 }
1421 
pkg_arch_supported(pkg_t * pkg)1422 int pkg_arch_supported(pkg_t * pkg)
1423 {
1424 	nv_pair_list_elt_t *l;
1425 	char *architecture = pkg_get_architecture(pkg);
1426 
1427 	if (!architecture)
1428 		return 1;
1429 
1430 	list_for_each_entry(l, &conf->arch_list.head, node) {
1431 		nv_pair_t *nv = (nv_pair_t *) l->data;
1432 		if (strcmp(nv->name, architecture) == 0) {
1433 			opkg_msg(DEBUG,
1434 				 "Arch %s (priority %s) supported for pkg %s.\n",
1435 				 nv->name, nv->value, pkg->name);
1436 			return 1;
1437 		}
1438 	}
1439 
1440 	opkg_msg(DEBUG, "Arch %s unsupported for pkg %s.\n",
1441 		 architecture, pkg->name);
1442 	return 0;
1443 }
1444 
pkg_info_preinstall_check(void)1445 void pkg_info_preinstall_check(void)
1446 {
1447 	int i;
1448 	pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1449 
1450 	/* update the file owner data structure */
1451 	opkg_msg(INFO, "Updating file owner list.\n");
1452 	pkg_hash_fetch_all_installed(installed_pkgs);
1453 	for (i = 0; i < installed_pkgs->len; i++) {
1454 		pkg_t *pkg = installed_pkgs->pkgs[i];
1455 		str_list_t *installed_files = pkg_get_installed_files(pkg);	/* this causes installed_files to be cached */
1456 		str_list_elt_t *iter, *niter;
1457 		if (installed_files == NULL) {
1458 			opkg_msg(ERROR, "Failed to determine installed "
1459 				 "files for pkg %s.\n", pkg->name);
1460 			break;
1461 		}
1462 		for (iter = str_list_first(installed_files), niter =
1463 		     str_list_next(installed_files, iter); iter;
1464 		     iter = niter, niter =
1465 		     str_list_next(installed_files, iter)) {
1466 			char *installed_file = (char *)iter->data;
1467 			file_hash_set_file_owner(installed_file, pkg);
1468 		}
1469 		pkg_free_installed_files(pkg);
1470 	}
1471 	pkg_vec_free(installed_pkgs);
1472 }
1473 
1474 struct pkg_write_filelist_data {
1475 	pkg_t *pkg;
1476 	FILE *stream;
1477 };
1478 
1479 static void
pkg_write_filelist_helper(const char * key,void * entry_,void * data_)1480 pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1481 {
1482 	struct pkg_write_filelist_data *data = data_;
1483 	pkg_t *entry = entry_;
1484 	if (entry == data->pkg) {
1485 		fprintf(data->stream, "%s\n", key);
1486 	}
1487 }
1488 
pkg_write_filelist(pkg_t * pkg)1489 int pkg_write_filelist(pkg_t * pkg)
1490 {
1491 	struct pkg_write_filelist_data data;
1492 	char *list_file_name;
1493 
1494 	sprintf_alloc(&list_file_name, "%s/%s.list",
1495 		      pkg->dest->info_dir, pkg->name);
1496 
1497 	opkg_msg(INFO, "Creating %s file for pkg %s.\n",
1498 		 list_file_name, pkg->name);
1499 
1500 	data.stream = fopen(list_file_name, "w");
1501 	if (!data.stream) {
1502 		opkg_perror(ERROR, "Failed to open %s", list_file_name);
1503 		free(list_file_name);
1504 		return -1;
1505 	}
1506 
1507 	data.pkg = pkg;
1508 	hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1509 	fclose(data.stream);
1510 	free(list_file_name);
1511 
1512 	pkg->state_flag &= ~SF_FILELIST_CHANGED;
1513 
1514 	return 0;
1515 }
1516 
pkg_write_changed_filelists(void)1517 int pkg_write_changed_filelists(void)
1518 {
1519 	pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1520 	int i, err, ret = 0;
1521 
1522 	if (conf->noaction)
1523 		return 0;
1524 
1525 	opkg_msg(INFO, "Saving changed filelists.\n");
1526 
1527 	pkg_hash_fetch_all_installed(installed_pkgs);
1528 	for (i = 0; i < installed_pkgs->len; i++) {
1529 		pkg_t *pkg = installed_pkgs->pkgs[i];
1530 		if (pkg->state_flag & SF_FILELIST_CHANGED) {
1531 			err = pkg_write_filelist(pkg);
1532 			if (err)
1533 				ret = -1;
1534 		}
1535 	}
1536 
1537 	pkg_vec_free(installed_pkgs);
1538 
1539 	return ret;
1540 }
1541