1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | #define _GNU_SOURCE |
9 | |
10 | #include <stdio.h> |
11 | #include <stdlib.h> |
12 | #include <unistd.h> |
13 | #include <string.h> |
14 | #include <sys/time.h> |
15 | |
16 | #include "util.h" |
17 | |
18 | void |
19 | solv_oom(size_t num, size_t len) |
20 | { |
21 | if (num) |
22 | fprintf(stderrstderr, "Out of memory allocating %zu*%zu bytes!\n", num, len); |
23 | else |
24 | fprintf(stderrstderr, "Out of memory allocating %zu bytes!\n", len); |
25 | abort(); |
26 | exit(1); |
27 | } |
28 | |
29 | void * |
30 | solv_malloc(size_t len) |
31 | { |
32 | void *r = malloc(len ? len : 1); |
33 | if (!r) |
34 | solv_oom(0, len); |
35 | return r; |
36 | } |
37 | |
38 | void * |
39 | solv_malloc2(size_t num, size_t len) |
40 | { |
41 | if (len && (num * len) / len != num) |
42 | solv_oom(num, len); |
43 | return solv_malloc(num * len); |
44 | } |
45 | |
46 | void * |
47 | solv_realloc(void *old, size_t len) |
48 | { |
49 | if (old == 0) |
50 | old = malloc(len ? len : 1); |
51 | else |
52 | old = realloc(old, len ? len : 1); |
53 | if (!old) |
54 | solv_oom(0, len); |
55 | return old; |
56 | } |
57 | |
58 | void * |
59 | solv_realloc2(void *old, size_t num, size_t len) |
60 | { |
61 | if (len && (num * len) / len != num) |
62 | solv_oom(num, len); |
63 | return solv_realloc(old, num * len); |
64 | } |
65 | |
66 | void * |
67 | solv_calloc(size_t num, size_t len) |
68 | { |
69 | void *r; |
70 | if (num == 0 || len == 0) |
71 | r = malloc(1); |
72 | else |
73 | r = calloc(num, len); |
74 | if (!r) |
75 | solv_oom(num, len); |
76 | return r; |
77 | } |
78 | |
79 | |
80 | |
81 | void * |
82 | solv_extend_realloc(void *old, size_t len, size_t size, size_t block) |
83 | { |
84 | size_t xblock = (block + 1) << 5; |
85 | len = (len + block) & ~block; |
86 | if (len >= xblock && xblock) |
87 | { |
88 | xblock <<= 1; |
89 | while (len >= xblock && xblock) |
90 | xblock <<= 1; |
91 | if (xblock) |
92 | { |
93 | size_t nlen; |
94 | xblock = (xblock >> 5) - 1; |
95 | nlen = (len + xblock) & ~xblock; |
96 | if (nlen > len) |
97 | len = nlen; |
98 | } |
99 | } |
100 | return solv_realloc2(old, len, size); |
101 | } |
102 | |
103 | void * |
104 | solv_free(void *mem) |
105 | { |
106 | if (mem) |
107 | free(mem); |
108 | return 0; |
109 | } |
110 | |
111 | char * |
112 | solv_strdup(const char *s) |
113 | { |
114 | char *r; |
115 | if (!s) |
116 | return 0; |
117 | r = strdup(s); |
118 | if (!r) |
119 | solv_oom(0, strlen(s)); |
120 | return r; |
121 | } |
122 | |
123 | unsigned int |
124 | solv_timems(unsigned int subtract) |
125 | { |
126 | struct timeval tv; |
127 | unsigned int r; |
128 | |
129 | if (gettimeofday(&tv, 0)) |
130 | return 0; |
131 | r = (((unsigned int)tv.tv_sec >> 16) * 1000) << 16; |
132 | r += ((unsigned int)tv.tv_sec & 0xffff) * 1000; |
133 | r += (unsigned int)tv.tv_usec / 1000; |
134 | return r - subtract; |
135 | } |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | #if (defined(__GLIBC__2) || defined(__NEWLIB__)) && (defined(HAVE_QSORT_R1) || defined(HAVE___QSORT_R)) |
143 | |
144 | void |
145 | solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard) |
146 | { |
147 | # if defined(HAVE_QSORT_R1) |
148 | qsort_r(base, nmemb, size, compar, compard); |
149 | # else |
150 | |
151 | __qsort_r(base, nmemb, size, compar, compard); |
152 | # endif |
153 | |
154 | } |
155 | |
156 | #elif defined(HAVE_QSORT_R1) /* not glibc, but has qsort_r() */ |
157 | |
158 | struct solv_sort_data { |
159 | int (*compar)(const void *, const void *, void *); |
160 | void *compard; |
161 | }; |
162 | |
163 | static int |
164 | solv_sort_helper(void *compard, const void *a, const void *b) |
165 | { |
166 | struct solv_sort_data *d = compard; |
167 | return (*d->compar)(a, b, d->compard); |
168 | } |
169 | |
170 | void |
171 | solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard) |
172 | { |
173 | struct solv_sort_data d; |
174 | d.compar = compar; |
175 | d.compard = compard; |
176 | qsort_r(base, nmemb, size, &d, solv_sort_helper); |
177 | } |
178 | |
179 | #else /* not glibc and no qsort_r() */ |
180 | |
181 | #include "qsort_r.c" |
182 | #endif |
183 | |
184 | char * |
185 | solv_dupjoin(const char *str1, const char *str2, const char *str3) |
186 | { |
187 | int l1, l2, l3; |
188 | char *s, *str; |
189 | l1 = str1 ? strlen(str1) : 0; |
| 2 | | Assuming 'str1' is non-null | |
|
| |
190 | l2 = str2 ? strlen(str2) : 0; |
| |
| |
191 | l3 = str3 ? strlen(str3) : 0; |
| |
| |
192 | s = str = solv_malloc(l1 + l2 + l3 + 1); |
193 | if (l1) |
| 8 | | Assuming 'l1' is not equal to 0 | |
|
| |
194 | { |
195 | strcpy(s, str1); |
| 10 | | String copy function overflows destination buffer |
|
196 | s += l1; |
197 | } |
198 | if (l2) |
199 | { |
200 | strcpy(s, str2); |
201 | s += l2; |
202 | } |
203 | if (l3) |
204 | { |
205 | strcpy(s, str3); |
206 | s += l3; |
207 | } |
208 | *s = 0; |
209 | return str; |
210 | } |
211 | |
212 | char * |
213 | solv_dupappend(const char *str1, const char *str2, const char *str3) |
214 | { |
215 | char *str = solv_dupjoin(str1, str2, str3); |
| |
216 | solv_free((void *)str1); |
217 | return str; |
218 | } |
219 | |
220 | int |
221 | solv_hex2bin(const char **strp, unsigned char *buf, int bufl) |
222 | { |
223 | const char *str = *strp; |
224 | int i; |
225 | |
226 | for (i = 0; i < bufl; i++) |
227 | { |
228 | int c = *str; |
229 | int d; |
230 | if (c >= '0' && c <= '9') |
231 | d = c - '0'; |
232 | else if (c >= 'a' && c <= 'f') |
233 | d = c - ('a' - 10); |
234 | else if (c >= 'A' && c <= 'F') |
235 | d = c - ('A' - 10); |
236 | else |
237 | break; |
238 | c = str[1]; |
239 | d <<= 4; |
240 | if (c >= '0' && c <= '9') |
241 | d |= c - '0'; |
242 | else if (c >= 'a' && c <= 'f') |
243 | d |= c - ('a' - 10); |
244 | else if (c >= 'A' && c <= 'F') |
245 | d |= c - ('A' - 10); |
246 | else |
247 | break; |
248 | buf[i] = d; |
249 | str += 2; |
250 | } |
251 | *strp = str; |
252 | return i; |
253 | } |
254 | |
255 | char * |
256 | solv_bin2hex(const unsigned char *buf, int l, char *str) |
257 | { |
258 | int i; |
259 | for (i = 0; i < l; i++, buf++) |
260 | { |
261 | int c = *buf >> 4; |
262 | *str++ = c < 10 ? c + '0' : c + ('a' - 10); |
263 | c = *buf & 15; |
264 | *str++ = c < 10 ? c + '0' : c + ('a' - 10); |
265 | } |
266 | *str = 0; |
267 | return str; |
268 | } |
269 | |
270 | size_t |
271 | solv_validutf8(const char *buf) |
272 | { |
273 | const unsigned char *p; |
274 | int x; |
275 | |
276 | for (p = (const unsigned char *)buf; (x = *p) != 0; p++) |
277 | { |
278 | if (x < 0x80) |
279 | continue; |
280 | if (x < 0xc0) |
281 | break; |
282 | if (x < 0xe0) |
283 | { |
284 | |
285 | if ((p[1] & 0xc0) != 0x80) |
286 | break; |
287 | if ((x & 0x1e) == 0) |
288 | break; |
289 | p += 1; |
290 | continue; |
291 | } |
292 | if (x < 0xf0) |
293 | { |
294 | |
295 | if ((p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80) |
296 | break; |
297 | if ((x & 0x0f) == 0 && (p[1] & 0x20) == 0) |
298 | break; |
299 | if (x == 0xed && (p[1] & 0x20) != 0) |
300 | break; |
301 | if (x == 0xef && p[1] == 0xbf && (p[2] == 0xbe || p[2] == 0xbf)) |
302 | break; |
303 | p += 2; |
304 | continue; |
305 | } |
306 | if (x < 0xf8) |
307 | { |
308 | |
309 | if ((p[1] & 0xc0) != 0x80 || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80) |
310 | break; |
311 | if ((x & 0x07) == 0 && (p[1] & 0x30) == 0) |
312 | break; |
313 | if ((x & 0x07) > 4 || ((x & 0x07) == 4 && (p[1] & 0x30) != 0)) |
314 | break; |
315 | p += 3; |
316 | continue; |
317 | } |
318 | break; |
319 | } |
320 | return (const char *)p - buf; |
321 | } |
322 | |
323 | char * |
324 | solv_latin1toutf8(const char *buf) |
325 | { |
326 | int l = 1; |
327 | const char *p; |
328 | char *r, *rp; |
329 | |
330 | for (p = buf; *p; p++) |
331 | if ((*(const unsigned char *)p & 128) != 0) |
332 | l++; |
333 | r = rp = solv_malloc(p - buf + l); |
334 | for (p = buf; *p; p++) |
335 | { |
336 | if ((*(const unsigned char *)p & 128) != 0) |
337 | { |
338 | *rp++ = *(const unsigned char *)p & 64 ? 0xc3 : 0xc2; |
339 | *rp++ = *p & 0xbf; |
340 | } |
341 | else |
342 | *rp++ = *p; |
343 | } |
344 | *rp = 0; |
345 | return r; |
346 | } |
347 | |
348 | char * |
349 | solv_replacebadutf8(const char *buf, int replchar) |
350 | { |
351 | size_t l, nl; |
352 | const char *p; |
353 | char *r = 0, *rp = 0; |
354 | int repllen, replin; |
355 | |
356 | if (replchar < 0 || replchar > 0x10ffff) |
357 | replchar = 0xfffd; |
358 | if (!replchar) |
359 | repllen = replin = 0; |
360 | else if (replchar < 0x80) |
361 | { |
362 | repllen = 1; |
363 | replin = (replchar & 0x40) | 0x80; |
364 | } |
365 | else if (replchar < 0x800) |
366 | { |
367 | repllen = 2; |
368 | replin = 0x40; |
369 | } |
370 | else if (replchar < 0x10000) |
371 | { |
372 | repllen = 3; |
373 | replin = 0x60; |
374 | } |
375 | else |
376 | { |
377 | repllen = 4; |
378 | replin = 0x70; |
379 | } |
380 | for (;;) |
381 | { |
382 | for (p = buf, nl = 0; *p; ) |
383 | { |
384 | l = solv_validutf8(p); |
385 | if (rp && l) |
386 | { |
387 | memcpy(rp, p, l); |
388 | rp += l; |
389 | } |
390 | nl += l; |
391 | p += l; |
392 | if (!*p) |
393 | break; |
394 | |
395 | if (rp && replchar) |
396 | { |
397 | switch (repllen) |
398 | { |
399 | case 4: |
400 | *rp++ = (replchar >> 18 & 0x3f) | 0x80; |
401 | case 3: |
402 | *rp++ = (replchar >> 12 & 0x3f) | 0x80; |
403 | case 2: |
404 | *rp++ = (replchar >> 6 & 0x3f) | 0x80; |
405 | default: |
406 | *rp++ = (replchar & 0x3f) | 0x80; |
407 | } |
408 | rp[-repllen] ^= replin; |
409 | } |
410 | nl += repllen; |
411 | p++; |
412 | while ((*(const unsigned char *)p & 0xc0) == 0x80) |
413 | p++; |
414 | } |
415 | if (rp) |
416 | break; |
417 | r = rp = solv_malloc(nl + 1); |
418 | } |
419 | *rp = 0; |
420 | return r; |
421 | } |
422 | |