1 /* pkg_vec.c - the opkg package management system
2 
3    Steven M. Ayer
4 
5    Copyright (C) 2002 Compaq Computer Corporation
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 <fnmatch.h>
20 
21 #include "pkg.h"
22 #include "opkg_message.h"
23 #include "libbb/libbb.h"
24 
pkg_vec_alloc(void)25 pkg_vec_t *pkg_vec_alloc(void)
26 {
27 	pkg_vec_t *vec = xcalloc(1, sizeof(pkg_vec_t));
28 	vec->pkgs = NULL;
29 	vec->len = 0;
30 
31 	return vec;
32 }
33 
pkg_vec_free(pkg_vec_t * vec)34 void pkg_vec_free(pkg_vec_t * vec)
35 {
36 	if (!vec)
37 		return;
38 
39 	if (vec->pkgs)
40 		free(vec->pkgs);
41 
42 	free(vec);
43 }
44 
45 /*
46  * assumption: all names in a vector are identical
47  * assumption: all version strings are trimmed,
48  *             so identical versions have identical version strings,
49  *             implying identical packages; let's marry these
50  */
pkg_vec_insert_merge(pkg_vec_t * vec,pkg_t * pkg,int set_status)51 void pkg_vec_insert_merge(pkg_vec_t * vec, pkg_t * pkg, int set_status)
52 {
53 	int i;
54 	int found = 0;
55 	char *pkg_version = pkg_get_string(pkg, PKG_VERSION);
56 	char *pkg_architecture = pkg_get_architecture(pkg);
57 	char *vec_architecture;
58 
59 	/* look for a duplicate pkg by name, version, and architecture */
60 	for (i = 0; i < vec->len; i++) {
61 		vec_architecture = pkg_get_architecture(vec->pkgs[i]);
62 
63 		opkg_msg(DEBUG2, "%s %s arch=%s vs. %s %s arch=%s.\n",
64 			 pkg->name, pkg_version, pkg_architecture,
65 			 vec->pkgs[i]->name, pkg_get_string(vec->pkgs[i], PKG_VERSION),
66 			 vec_architecture);
67 		/* if the name,ver,arch matches, or the name matches and the
68 		 * package is marked deinstall/hold  */
69 		if ((!strcmp(pkg->name, vec->pkgs[i]->name))
70 		    && ((pkg->state_want == SW_DEINSTALL
71 			 && (pkg->state_flag & SF_HOLD))
72 			|| ((pkg_compare_versions(pkg, vec->pkgs[i]) == 0)
73 			    && (!strcmp(pkg_architecture, vec_architecture))))) {
74 			found = 1;
75 			opkg_msg(DEBUG2,
76 				 "Duplicate for pkg=%s version=%s arch=%s.\n",
77 				 pkg->name, pkg_version, pkg_architecture);
78 			break;
79 		}
80 	}
81 
82 	/* we didn't find one, add it */
83 	if (!found) {
84 		opkg_msg(DEBUG2, "Adding new pkg=%s version=%s arch=%s.\n",
85 			 pkg->name, pkg_version, pkg_architecture);
86 		pkg_vec_insert(vec, pkg);
87 		return;
88 	}
89 
90 	/* update the one that we have */
91 	opkg_msg(DEBUG2, "Merging %s %s arch=%s, set_status=%d.\n",
92 		 pkg->name, pkg_version, pkg_architecture, set_status);
93 	if (set_status) {
94 		/* This is from the status file,
95 		 * so need to merge with existing database */
96 		pkg_merge(pkg, vec->pkgs[i]);
97 	}
98 
99 	/* overwrite the old one */
100 	pkg_deinit(vec->pkgs[i]);
101 	free(vec->pkgs[i]);
102 	vec->pkgs[i] = pkg;
103 }
104 
pkg_vec_insert(pkg_vec_t * vec,const pkg_t * pkg)105 void pkg_vec_insert(pkg_vec_t * vec, const pkg_t * pkg)
106 {
107 	vec->pkgs = xrealloc(vec->pkgs, (vec->len + 1) * sizeof(pkg_t *));
108 	vec->pkgs[vec->len] = (pkg_t *) pkg;
109 	vec->len++;
110 }
111 
pkg_vec_contains(pkg_vec_t * vec,pkg_t * apkg)112 int pkg_vec_contains(pkg_vec_t * vec, pkg_t * apkg)
113 {
114 	int i;
115 	for (i = 0; i < vec->len; i++)
116 		if (vec->pkgs[i] == apkg)
117 			return 1;
118 	return 0;
119 }
120 
pkg_vec_sort(pkg_vec_t * vec,compare_fcn_t compar)121 void pkg_vec_sort(pkg_vec_t * vec, compare_fcn_t compar)
122 {
123 	qsort(vec->pkgs, vec->len, sizeof(pkg_t *), compar);
124 }
125 
pkg_vec_clear_marks(pkg_vec_t * vec)126 int pkg_vec_clear_marks(pkg_vec_t * vec)
127 {
128 	int npkgs = vec->len;
129 	int i;
130 	for (i = 0; i < npkgs; i++) {
131 		pkg_t *pkg = vec->pkgs[i];
132 		pkg->state_flag &= ~SF_MARKED;
133 	}
134 	return 0;
135 }
136 
pkg_vec_mark_if_matches(pkg_vec_t * vec,const char * pattern)137 int pkg_vec_mark_if_matches(pkg_vec_t * vec, const char *pattern)
138 {
139 	int matching_count = 0;
140 	pkg_t **pkgs = vec->pkgs;
141 	int npkgs = vec->len;
142 	int i;
143 	for (i = 0; i < npkgs; i++) {
144 		pkg_t *pkg = pkgs[i];
145 		if (fnmatch(pattern, pkg->name, 0) == 0) {
146 			pkg->state_flag |= SF_MARKED;
147 			matching_count++;
148 		}
149 	}
150 	return matching_count;
151 }
152 
abstract_pkg_vec_alloc(void)153 abstract_pkg_vec_t *abstract_pkg_vec_alloc(void)
154 {
155 	abstract_pkg_vec_t *vec;
156 	vec = xcalloc(1, sizeof(abstract_pkg_vec_t));
157 	vec->pkgs = NULL;
158 	vec->len = 0;
159 
160 	return vec;
161 }
162 
abstract_pkg_vec_free(abstract_pkg_vec_t * vec)163 void abstract_pkg_vec_free(abstract_pkg_vec_t * vec)
164 {
165 	if (!vec)
166 		return;
167 	free(vec->pkgs);
168 	free(vec);
169 }
170 
171 /*
172  * assumption: all names in a vector are unique
173  */
abstract_pkg_vec_insert(abstract_pkg_vec_t * vec,abstract_pkg_t * pkg)174 void abstract_pkg_vec_insert(abstract_pkg_vec_t * vec, abstract_pkg_t * pkg)
175 {
176 	vec->pkgs =
177 	    xrealloc(vec->pkgs, (vec->len + 1) * sizeof(abstract_pkg_t *));
178 	vec->pkgs[vec->len] = pkg;
179 	vec->len++;
180 }
181 
abstract_pkg_vec_get(abstract_pkg_vec_t * vec,int i)182 abstract_pkg_t *abstract_pkg_vec_get(abstract_pkg_vec_t * vec, int i)
183 {
184 	if (vec->len > i)
185 		return vec->pkgs[i];
186 	else
187 		return NULL;
188 }
189 
abstract_pkg_vec_contains(abstract_pkg_vec_t * vec,abstract_pkg_t * apkg)190 int abstract_pkg_vec_contains(abstract_pkg_vec_t * vec, abstract_pkg_t * apkg)
191 {
192 	int i;
193 	for (i = 0; i < vec->len; i++)
194 		if (vec->pkgs[i] == apkg)
195 			return 1;
196 	return 0;
197 }
198 
abstract_pkg_vec_sort(abstract_pkg_vec_t * vec,compare_fcn_t compar)199 void abstract_pkg_vec_sort(abstract_pkg_vec_t * vec, compare_fcn_t compar)
200 {
201 	qsort(vec->pkgs, vec->len, sizeof(pkg_t *), compar);
202 }
203 
pkg_compare_names(const void * p1,const void * p2)204 int pkg_compare_names(const void *p1, const void *p2)
205 {
206 	const pkg_t *pkg1 = *(const pkg_t **)p1;
207 	const pkg_t *pkg2 = *(const pkg_t **)p2;
208 	if (pkg1->name == NULL)
209 		return 1;
210 	if (pkg2->name == NULL)
211 		return -1;
212 	return (strcmp(pkg1->name, pkg2->name));
213 }
214