1 /*
2 * Copyright (c) 2007, Novell Inc.
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
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
solv_oom(size_t num,size_t len)19 solv_oom(size_t num, size_t len)
20 {
21 if (num)
22 fprintf(stderr, "Out of memory allocating %zu*%zu bytes!\n", num, len);
23 else
24 fprintf(stderr, "Out of memory allocating %zu bytes!\n", len);
25 abort();
26 exit(1);
27 }
28
29 void *
solv_malloc(size_t len)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 *
solv_malloc2(size_t num,size_t len)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 *
solv_realloc(void * old,size_t len)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 *
solv_realloc2(void * old,size_t num,size_t len)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 *
solv_calloc(size_t num,size_t len)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 void *
solv_free(void * mem)80 solv_free(void *mem)
81 {
82 if (mem)
83 free(mem);
84 return 0;
85 }
86
87 char *
solv_strdup(const char * s)88 solv_strdup(const char *s)
89 {
90 char *r;
91 if (!s)
92 return 0;
93 r = strdup(s);
94 if (!r)
95 solv_oom(0, strlen(s));
96 return r;
97 }
98
99 unsigned int
solv_timems(unsigned int subtract)100 solv_timems(unsigned int subtract)
101 {
102 struct timeval tv;
103 unsigned int r;
104
105 if (gettimeofday(&tv, 0))
106 return 0;
107 r = (((unsigned int)tv.tv_sec >> 16) * 1000) << 16;
108 r += ((unsigned int)tv.tv_sec & 0xffff) * 1000;
109 r += (unsigned int)tv.tv_usec / 1000;
110 return r - subtract;
111 }
112
113 /* bsd's qsort_r has different arguments, so we define our
114 own version in case we need to do some clever mapping
115
116 see also: http://sources.redhat.com/ml/libc-alpha/2008-12/msg00003.html
117 */
118 #if defined(__GLIBC__) && (defined(HAVE_QSORT_R) || defined(HAVE___QSORT_R))
119
120 void
solv_sort(void * base,size_t nmemb,size_t size,int (* compar)(const void *,const void *,void *),void * compard)121 solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
122 {
123 # if defined(HAVE_QSORT_R)
124 qsort_r(base, nmemb, size, compar, compard);
125 # else
126 /* backported for SLE10-SP2 */
127 __qsort_r(base, nmemb, size, compar, compard);
128 # endif
129
130 }
131
132 #elif defined(HAVE_QSORT_R) /* not glibc, but has qsort_r() */
133
134 struct solv_sort_data {
135 int (*compar)(const void *, const void *, void *);
136 void *compard;
137 };
138
139 static int
solv_sort_helper(void * compard,const void * a,const void * b)140 solv_sort_helper(void *compard, const void *a, const void *b)
141 {
142 struct solv_sort_data *d = compard;
143 return (*d->compar)(a, b, d->compard);
144 }
145
146 void
solv_sort(void * base,size_t nmemb,size_t size,int (* compar)(const void *,const void *,void *),void * compard)147 solv_sort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *compard)
148 {
149 struct solv_sort_data d;
150 d.compar = compar;
151 d.compard = compard;
152 qsort_r(base, nmemb, size, &d, solv_sort_helper);
153 }
154
155 #else /* not glibc and no qsort_r() */
156 /* use own version of qsort if none available */
157 #include "qsort_r.c"
158 #endif
159
160 char *
solv_dupjoin(const char * str1,const char * str2,const char * str3)161 solv_dupjoin(const char *str1, const char *str2, const char *str3)
162 {
163 int l1, l2, l3;
164 char *s, *str;
165 l1 = str1 ? strlen(str1) : 0;
166 l2 = str2 ? strlen(str2) : 0;
167 l3 = str3 ? strlen(str3) : 0;
168 s = str = solv_malloc(l1 + l2 + l3 + 1);
169 if (l1)
170 {
171 strcpy(s, str1);
172 s += l1;
173 }
174 if (l2)
175 {
176 strcpy(s, str2);
177 s += l2;
178 }
179 if (l3)
180 {
181 strcpy(s, str3);
182 s += l3;
183 }
184 *s = 0;
185 return str;
186 }
187
188 char *
solv_dupappend(const char * str1,const char * str2,const char * str3)189 solv_dupappend(const char *str1, const char *str2, const char *str3)
190 {
191 char *str = solv_dupjoin(str1, str2, str3);
192 solv_free((void *)str1);
193 return str;
194 }
195
196 int
solv_hex2bin(const char ** strp,unsigned char * buf,int bufl)197 solv_hex2bin(const char **strp, unsigned char *buf, int bufl)
198 {
199 const char *str = *strp;
200 int i;
201
202 for (i = 0; i < bufl; i++)
203 {
204 int c = *str;
205 int d;
206 if (c >= '0' && c <= '9')
207 d = c - '0';
208 else if (c >= 'a' && c <= 'f')
209 d = c - ('a' - 10);
210 else if (c >= 'A' && c <= 'F')
211 d = c - ('A' - 10);
212 else
213 break;
214 c = *++str;
215 d <<= 4;
216 if (c >= '0' && c <= '9')
217 d |= c - '0';
218 else if (c >= 'a' && c <= 'f')
219 d |= c - ('a' - 10);
220 else if (c >= 'A' && c <= 'F')
221 d |= c - ('A' - 10);
222 else
223 break;
224 buf[i] = d;
225 ++str;
226 }
227 *strp = str;
228 return i;
229 }
230
231 char *
solv_bin2hex(const unsigned char * buf,int l,char * str)232 solv_bin2hex(const unsigned char *buf, int l, char *str)
233 {
234 int i;
235 for (i = 0; i < l; i++, buf++)
236 {
237 int c = *buf >> 4;
238 *str++ = c < 10 ? c + '0' : c + ('a' - 10);
239 c = *buf & 15;
240 *str++ = c < 10 ? c + '0' : c + ('a' - 10);
241 }
242 *str = 0;
243 return str;
244 }
245
246
247