Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/lib/striconv.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* Charset conversion. | - | ||||||||||||||||||||||||
2 | Copyright (C) 2001-2007, 2010-2018 Free Software Foundation, Inc. | - | ||||||||||||||||||||||||
3 | Written by Bruno Haible and Simon Josefsson. | - | ||||||||||||||||||||||||
4 | - | |||||||||||||||||||||||||
5 | This program is free software; you can redistribute it and/or modify | - | ||||||||||||||||||||||||
6 | it under the terms of the GNU General Public License as published by | - | ||||||||||||||||||||||||
7 | the Free Software Foundation; either version 3, or (at your option) | - | ||||||||||||||||||||||||
8 | any later version. | - | ||||||||||||||||||||||||
9 | - | |||||||||||||||||||||||||
10 | This program is distributed in the hope that it will be useful, | - | ||||||||||||||||||||||||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||||||||||||||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||||||||||||||
13 | GNU General Public License for more details. | - | ||||||||||||||||||||||||
14 | - | |||||||||||||||||||||||||
15 | You should have received a copy of the GNU General Public License | - | ||||||||||||||||||||||||
16 | along with this program; if not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||||||||||||||
17 | - | |||||||||||||||||||||||||
18 | #include <config.h> | - | ||||||||||||||||||||||||
19 | - | |||||||||||||||||||||||||
20 | /* Specification. */ | - | ||||||||||||||||||||||||
21 | #include "striconv.h" | - | ||||||||||||||||||||||||
22 | - | |||||||||||||||||||||||||
23 | #include <errno.h> | - | ||||||||||||||||||||||||
24 | #include <stdlib.h> | - | ||||||||||||||||||||||||
25 | #include <string.h> | - | ||||||||||||||||||||||||
26 | - | |||||||||||||||||||||||||
27 | #if HAVE_ICONV | - | ||||||||||||||||||||||||
28 | # include <iconv.h> | - | ||||||||||||||||||||||||
29 | /* Get MB_LEN_MAX, CHAR_BIT. */ | - | ||||||||||||||||||||||||
30 | # include <limits.h> | - | ||||||||||||||||||||||||
31 | #endif | - | ||||||||||||||||||||||||
32 | - | |||||||||||||||||||||||||
33 | #include "c-strcase.h" | - | ||||||||||||||||||||||||
34 | - | |||||||||||||||||||||||||
35 | #ifndef SIZE_MAX | - | ||||||||||||||||||||||||
36 | # define SIZE_MAX ((size_t) -1) | - | ||||||||||||||||||||||||
37 | #endif | - | ||||||||||||||||||||||||
38 | - | |||||||||||||||||||||||||
39 | - | |||||||||||||||||||||||||
40 | #if HAVE_ICONV | - | ||||||||||||||||||||||||
41 | - | |||||||||||||||||||||||||
42 | int | - | ||||||||||||||||||||||||
43 | mem_cd_iconv (const char *src, size_t srclen, iconv_t cd, | - | ||||||||||||||||||||||||
44 | char **resultp, size_t *lengthp) | - | ||||||||||||||||||||||||
45 | { | - | ||||||||||||||||||||||||
46 | # define tmpbufsize 4096 | - | ||||||||||||||||||||||||
47 | size_t length; | - | ||||||||||||||||||||||||
48 | char *result; | - | ||||||||||||||||||||||||
49 | - | |||||||||||||||||||||||||
50 | /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ | - | ||||||||||||||||||||||||
51 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
52 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
53 | || defined __sun) | - | ||||||||||||||||||||||||
54 | /* Set to the initial state. */ | - | ||||||||||||||||||||||||
55 | iconv (cd, NULL, NULL, NULL, NULL); | - | ||||||||||||||||||||||||
56 | # endif | - | ||||||||||||||||||||||||
57 | - | |||||||||||||||||||||||||
58 | /* Determine the length we need. */ | - | ||||||||||||||||||||||||
59 | { | - | ||||||||||||||||||||||||
60 | size_t count = 0; | - | ||||||||||||||||||||||||
61 | /* The alignment is needed when converting e.g. to glibc's WCHAR_T or | - | ||||||||||||||||||||||||
62 | libiconv's UCS-4-INTERNAL encoding. */ | - | ||||||||||||||||||||||||
63 | union { unsigned int align; char buf[tmpbufsize]; } tmp; | - | ||||||||||||||||||||||||
64 | # define tmpbuf tmp.buf | - | ||||||||||||||||||||||||
65 | const char *inptr = src; | - | ||||||||||||||||||||||||
66 | size_t insize = srclen; | - | ||||||||||||||||||||||||
67 | - | |||||||||||||||||||||||||
68 | while (insize > 0)
| 0 | ||||||||||||||||||||||||
69 | { | - | ||||||||||||||||||||||||
70 | char *outptr = tmpbuf; | - | ||||||||||||||||||||||||
71 | size_t outsize = tmpbufsize; | - | ||||||||||||||||||||||||
72 | size_t res = iconv (cd, | - | ||||||||||||||||||||||||
73 | (ICONV_CONST char **) &inptr, &insize, | - | ||||||||||||||||||||||||
74 | &outptr, &outsize); | - | ||||||||||||||||||||||||
75 | - | |||||||||||||||||||||||||
76 | if (res == (size_t)(-1))
| 0 | ||||||||||||||||||||||||
77 | { | - | ||||||||||||||||||||||||
78 | if (errno == E2BIG)
| 0 | ||||||||||||||||||||||||
79 | ; never executed: ; | 0 | ||||||||||||||||||||||||
80 | else if (errno == EINVAL)
| 0 | ||||||||||||||||||||||||
81 | break; never executed: break; | 0 | ||||||||||||||||||||||||
82 | else | - | ||||||||||||||||||||||||
83 | return -1; never executed: return -1; | 0 | ||||||||||||||||||||||||
84 | } | - | ||||||||||||||||||||||||
85 | # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) | - | ||||||||||||||||||||||||
86 | /* Irix iconv() inserts a NUL byte if it cannot convert. | - | ||||||||||||||||||||||||
87 | NetBSD iconv() inserts a question mark if it cannot convert. | - | ||||||||||||||||||||||||
88 | Only GNU libiconv and GNU libc are known to prefer to fail rather | - | ||||||||||||||||||||||||
89 | than doing a lossy conversion. */ | - | ||||||||||||||||||||||||
90 | else if (res > 0) | - | ||||||||||||||||||||||||
91 | { | - | ||||||||||||||||||||||||
92 | errno = EILSEQ; | - | ||||||||||||||||||||||||
93 | return -1; | - | ||||||||||||||||||||||||
94 | } | - | ||||||||||||||||||||||||
95 | # endif | - | ||||||||||||||||||||||||
96 | count += outptr - tmpbuf; | - | ||||||||||||||||||||||||
97 | } never executed: end of block | 0 | ||||||||||||||||||||||||
98 | /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ | - | ||||||||||||||||||||||||
99 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
100 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
101 | || defined __sun) | - | ||||||||||||||||||||||||
102 | { | - | ||||||||||||||||||||||||
103 | char *outptr = tmpbuf; | - | ||||||||||||||||||||||||
104 | size_t outsize = tmpbufsize; | - | ||||||||||||||||||||||||
105 | size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); | - | ||||||||||||||||||||||||
106 | - | |||||||||||||||||||||||||
107 | if (res == (size_t)(-1))
| 0 | ||||||||||||||||||||||||
108 | return -1; never executed: return -1; | 0 | ||||||||||||||||||||||||
109 | count += outptr - tmpbuf; | - | ||||||||||||||||||||||||
110 | } | - | ||||||||||||||||||||||||
111 | # endif | - | ||||||||||||||||||||||||
112 | length = count; | - | ||||||||||||||||||||||||
113 | # undef tmpbuf | - | ||||||||||||||||||||||||
114 | } | - | ||||||||||||||||||||||||
115 | - | |||||||||||||||||||||||||
116 | if (length == 0)
| 0 | ||||||||||||||||||||||||
117 | { | - | ||||||||||||||||||||||||
118 | *lengthp = 0; | - | ||||||||||||||||||||||||
119 | return 0; never executed: return 0; | 0 | ||||||||||||||||||||||||
120 | } | - | ||||||||||||||||||||||||
121 | if (*resultp != NULL && *lengthp >= length)
| 0 | ||||||||||||||||||||||||
122 | result = *resultp; never executed: result = *resultp; | 0 | ||||||||||||||||||||||||
123 | else | - | ||||||||||||||||||||||||
124 | { | - | ||||||||||||||||||||||||
125 | result = (char *) malloc (length); | - | ||||||||||||||||||||||||
126 | if (result == NULL)
| 0 | ||||||||||||||||||||||||
127 | { | - | ||||||||||||||||||||||||
128 | errno = ENOMEM; | - | ||||||||||||||||||||||||
129 | return -1; never executed: return -1; | 0 | ||||||||||||||||||||||||
130 | } | - | ||||||||||||||||||||||||
131 | } never executed: end of block | 0 | ||||||||||||||||||||||||
132 | - | |||||||||||||||||||||||||
133 | /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ | - | ||||||||||||||||||||||||
134 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
135 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
136 | || defined __sun) | - | ||||||||||||||||||||||||
137 | /* Return to the initial state. */ | - | ||||||||||||||||||||||||
138 | iconv (cd, NULL, NULL, NULL, NULL); | - | ||||||||||||||||||||||||
139 | # endif | - | ||||||||||||||||||||||||
140 | - | |||||||||||||||||||||||||
141 | /* Do the conversion for real. */ | - | ||||||||||||||||||||||||
142 | { | - | ||||||||||||||||||||||||
143 | const char *inptr = src; | - | ||||||||||||||||||||||||
144 | size_t insize = srclen; | - | ||||||||||||||||||||||||
145 | char *outptr = result; | - | ||||||||||||||||||||||||
146 | size_t outsize = length; | - | ||||||||||||||||||||||||
147 | - | |||||||||||||||||||||||||
148 | while (insize > 0)
| 0 | ||||||||||||||||||||||||
149 | { | - | ||||||||||||||||||||||||
150 | size_t res = iconv (cd, | - | ||||||||||||||||||||||||
151 | (ICONV_CONST char **) &inptr, &insize, | - | ||||||||||||||||||||||||
152 | &outptr, &outsize); | - | ||||||||||||||||||||||||
153 | - | |||||||||||||||||||||||||
154 | if (res == (size_t)(-1))
| 0 | ||||||||||||||||||||||||
155 | { | - | ||||||||||||||||||||||||
156 | if (errno == EINVAL)
| 0 | ||||||||||||||||||||||||
157 | break; never executed: break; | 0 | ||||||||||||||||||||||||
158 | else | - | ||||||||||||||||||||||||
159 | goto fail; never executed: goto fail; | 0 | ||||||||||||||||||||||||
160 | } | - | ||||||||||||||||||||||||
161 | # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) | - | ||||||||||||||||||||||||
162 | /* Irix iconv() inserts a NUL byte if it cannot convert. | - | ||||||||||||||||||||||||
163 | NetBSD iconv() inserts a question mark if it cannot convert. | - | ||||||||||||||||||||||||
164 | Only GNU libiconv and GNU libc are known to prefer to fail rather | - | ||||||||||||||||||||||||
165 | than doing a lossy conversion. */ | - | ||||||||||||||||||||||||
166 | else if (res > 0) | - | ||||||||||||||||||||||||
167 | { | - | ||||||||||||||||||||||||
168 | errno = EILSEQ; | - | ||||||||||||||||||||||||
169 | goto fail; | - | ||||||||||||||||||||||||
170 | } | - | ||||||||||||||||||||||||
171 | # endif | - | ||||||||||||||||||||||||
172 | } never executed: end of block | 0 | ||||||||||||||||||||||||
173 | /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ | - | ||||||||||||||||||||||||
174 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
175 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
176 | || defined __sun) | - | ||||||||||||||||||||||||
177 | { | - | ||||||||||||||||||||||||
178 | size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); | - | ||||||||||||||||||||||||
179 | - | |||||||||||||||||||||||||
180 | if (res == (size_t)(-1))
| 0 | ||||||||||||||||||||||||
181 | goto fail; never executed: goto fail; | 0 | ||||||||||||||||||||||||
182 | } | - | ||||||||||||||||||||||||
183 | # endif | - | ||||||||||||||||||||||||
184 | if (outsize != 0)
| 0 | ||||||||||||||||||||||||
185 | abort (); never executed: abort (); | 0 | ||||||||||||||||||||||||
186 | } | - | ||||||||||||||||||||||||
187 | - | |||||||||||||||||||||||||
188 | *resultp = result; | - | ||||||||||||||||||||||||
189 | *lengthp = length; | - | ||||||||||||||||||||||||
190 | - | |||||||||||||||||||||||||
191 | return 0; never executed: return 0; | 0 | ||||||||||||||||||||||||
192 | - | |||||||||||||||||||||||||
193 | fail: | - | ||||||||||||||||||||||||
194 | { | - | ||||||||||||||||||||||||
195 | if (result != *resultp)
| 0 | ||||||||||||||||||||||||
196 | { | - | ||||||||||||||||||||||||
197 | int saved_errno = errno; | - | ||||||||||||||||||||||||
198 | free (result); | - | ||||||||||||||||||||||||
199 | errno = saved_errno; | - | ||||||||||||||||||||||||
200 | } never executed: end of block | 0 | ||||||||||||||||||||||||
201 | return -1; never executed: return -1; | 0 | ||||||||||||||||||||||||
202 | } | - | ||||||||||||||||||||||||
203 | # undef tmpbufsize | - | ||||||||||||||||||||||||
204 | } | - | ||||||||||||||||||||||||
205 | - | |||||||||||||||||||||||||
206 | char * | - | ||||||||||||||||||||||||
207 | str_cd_iconv (const char *src, iconv_t cd) | - | ||||||||||||||||||||||||
208 | { | - | ||||||||||||||||||||||||
209 | /* For most encodings, a trailing NUL byte in the input will be converted | - | ||||||||||||||||||||||||
210 | to a trailing NUL byte in the output. But not for UTF-7. So that this | - | ||||||||||||||||||||||||
211 | function is usable for UTF-7, we have to exclude the NUL byte from the | - | ||||||||||||||||||||||||
212 | conversion and add it by hand afterwards. */ | - | ||||||||||||||||||||||||
213 | # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__) | - | ||||||||||||||||||||||||
214 | /* Irix iconv() inserts a NUL byte if it cannot convert. | - | ||||||||||||||||||||||||
215 | NetBSD iconv() inserts a question mark if it cannot convert. | - | ||||||||||||||||||||||||
216 | Only GNU libiconv and GNU libc are known to prefer to fail rather | - | ||||||||||||||||||||||||
217 | than doing a lossy conversion. For other iconv() implementations, | - | ||||||||||||||||||||||||
218 | we have to look at the number of irreversible conversions returned; | - | ||||||||||||||||||||||||
219 | but this information is lost when iconv() returns for an E2BIG reason. | - | ||||||||||||||||||||||||
220 | Therefore we cannot use the second, faster algorithm. */ | - | ||||||||||||||||||||||||
221 | - | |||||||||||||||||||||||||
222 | char *result = NULL; | - | ||||||||||||||||||||||||
223 | size_t length = 0; | - | ||||||||||||||||||||||||
224 | int retval = mem_cd_iconv (src, strlen (src), cd, &result, &length); | - | ||||||||||||||||||||||||
225 | char *final_result; | - | ||||||||||||||||||||||||
226 | - | |||||||||||||||||||||||||
227 | if (retval < 0) | - | ||||||||||||||||||||||||
228 | { | - | ||||||||||||||||||||||||
229 | if (result != NULL) | - | ||||||||||||||||||||||||
230 | abort (); | - | ||||||||||||||||||||||||
231 | return NULL; | - | ||||||||||||||||||||||||
232 | } | - | ||||||||||||||||||||||||
233 | - | |||||||||||||||||||||||||
234 | /* Add the terminating NUL byte. */ | - | ||||||||||||||||||||||||
235 | final_result = | - | ||||||||||||||||||||||||
236 | (result != NULL ? realloc (result, length + 1) : malloc (length + 1)); | - | ||||||||||||||||||||||||
237 | if (final_result == NULL) | - | ||||||||||||||||||||||||
238 | { | - | ||||||||||||||||||||||||
239 | free (result); | - | ||||||||||||||||||||||||
240 | errno = ENOMEM; | - | ||||||||||||||||||||||||
241 | return NULL; | - | ||||||||||||||||||||||||
242 | } | - | ||||||||||||||||||||||||
243 | final_result[length] = '\0'; | - | ||||||||||||||||||||||||
244 | - | |||||||||||||||||||||||||
245 | return final_result; | - | ||||||||||||||||||||||||
246 | - | |||||||||||||||||||||||||
247 | # else | - | ||||||||||||||||||||||||
248 | /* This algorithm is likely faster than the one above. But it may produce | - | ||||||||||||||||||||||||
249 | iconv() returns for an E2BIG reason, when the output size guess is too | - | ||||||||||||||||||||||||
250 | small. Therefore it can only be used when we don't need the number of | - | ||||||||||||||||||||||||
251 | irreversible conversions performed. */ | - | ||||||||||||||||||||||||
252 | char *result; | - | ||||||||||||||||||||||||
253 | size_t result_size; | - | ||||||||||||||||||||||||
254 | size_t length; | - | ||||||||||||||||||||||||
255 | const char *inptr = src; | - | ||||||||||||||||||||||||
256 | size_t inbytes_remaining = strlen (src); | - | ||||||||||||||||||||||||
257 | - | |||||||||||||||||||||||||
258 | /* Make a guess for the worst-case output size, in order to avoid a | - | ||||||||||||||||||||||||
259 | realloc. It's OK if the guess is wrong as long as it is not zero and | - | ||||||||||||||||||||||||
260 | doesn't lead to an integer overflow. */ | - | ||||||||||||||||||||||||
261 | result_size = inbytes_remaining; | - | ||||||||||||||||||||||||
262 | { | - | ||||||||||||||||||||||||
263 | size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2); | - | ||||||||||||||||||||||||
264 | if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
| 0-30 | ||||||||||||||||||||||||
265 | result_size *= MB_LEN_MAX; executed 30 times by 2 tests: result_size *= 16 ; Executed by:
| 30 | ||||||||||||||||||||||||
266 | } | - | ||||||||||||||||||||||||
267 | result_size += 1; /* for the terminating NUL */ | - | ||||||||||||||||||||||||
268 | - | |||||||||||||||||||||||||
269 | result = (char *) malloc (result_size); | - | ||||||||||||||||||||||||
270 | if (result == NULL)
| 0-30 | ||||||||||||||||||||||||
271 | { | - | ||||||||||||||||||||||||
272 | errno = ENOMEM; | - | ||||||||||||||||||||||||
273 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||||||||||||||
274 | } | - | ||||||||||||||||||||||||
275 | - | |||||||||||||||||||||||||
276 | /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ | - | ||||||||||||||||||||||||
277 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
278 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
279 | || defined __sun) | - | ||||||||||||||||||||||||
280 | /* Set to the initial state. */ | - | ||||||||||||||||||||||||
281 | iconv (cd, NULL, NULL, NULL, NULL); | - | ||||||||||||||||||||||||
282 | # endif | - | ||||||||||||||||||||||||
283 | - | |||||||||||||||||||||||||
284 | /* Do the conversion. */ | - | ||||||||||||||||||||||||
285 | { | - | ||||||||||||||||||||||||
286 | char *outptr = result; | - | ||||||||||||||||||||||||
287 | size_t outbytes_remaining = result_size - 1; | - | ||||||||||||||||||||||||
288 | - | |||||||||||||||||||||||||
289 | for (;;) | - | ||||||||||||||||||||||||
290 | { | - | ||||||||||||||||||||||||
291 | /* Here inptr + inbytes_remaining = src + strlen (src), | - | ||||||||||||||||||||||||
292 | outptr + outbytes_remaining = result + result_size - 1. */ | - | ||||||||||||||||||||||||
293 | size_t res = iconv (cd, | - | ||||||||||||||||||||||||
294 | (ICONV_CONST char **) &inptr, &inbytes_remaining, | - | ||||||||||||||||||||||||
295 | &outptr, &outbytes_remaining); | - | ||||||||||||||||||||||||
296 | - | |||||||||||||||||||||||||
297 | if (res == (size_t)(-1))
| 15 | ||||||||||||||||||||||||
298 | { | - | ||||||||||||||||||||||||
299 | if (errno == EINVAL)
| 0-15 | ||||||||||||||||||||||||
300 | break; never executed: break; | 0 | ||||||||||||||||||||||||
301 | else if (errno == E2BIG)
| 0-15 | ||||||||||||||||||||||||
302 | { | - | ||||||||||||||||||||||||
303 | size_t used = outptr - result; | - | ||||||||||||||||||||||||
304 | size_t newsize = result_size * 2; | - | ||||||||||||||||||||||||
305 | char *newresult; | - | ||||||||||||||||||||||||
306 | - | |||||||||||||||||||||||||
307 | if (!(newsize > result_size))
| 0 | ||||||||||||||||||||||||
308 | { | - | ||||||||||||||||||||||||
309 | errno = ENOMEM; | - | ||||||||||||||||||||||||
310 | goto failed; never executed: goto failed; | 0 | ||||||||||||||||||||||||
311 | } | - | ||||||||||||||||||||||||
312 | newresult = (char *) realloc (result, newsize); | - | ||||||||||||||||||||||||
313 | if (newresult == NULL)
| 0 | ||||||||||||||||||||||||
314 | { | - | ||||||||||||||||||||||||
315 | errno = ENOMEM; | - | ||||||||||||||||||||||||
316 | goto failed; never executed: goto failed; | 0 | ||||||||||||||||||||||||
317 | } | - | ||||||||||||||||||||||||
318 | result = newresult; | - | ||||||||||||||||||||||||
319 | result_size = newsize; | - | ||||||||||||||||||||||||
320 | outptr = result + used; | - | ||||||||||||||||||||||||
321 | outbytes_remaining = result_size - 1 - used; | - | ||||||||||||||||||||||||
322 | } never executed: end of block | 0 | ||||||||||||||||||||||||
323 | else | - | ||||||||||||||||||||||||
324 | goto failed; executed 15 times by 2 tests: goto failed; Executed by:
| 15 | ||||||||||||||||||||||||
325 | } | - | ||||||||||||||||||||||||
326 | else | - | ||||||||||||||||||||||||
327 | break; executed 15 times by 2 tests: break; Executed by:
| 15 | ||||||||||||||||||||||||
328 | } | - | ||||||||||||||||||||||||
329 | /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ | - | ||||||||||||||||||||||||
330 | # if defined _LIBICONV_VERSION \ | - | ||||||||||||||||||||||||
331 | || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
332 | || defined __sun) | - | ||||||||||||||||||||||||
333 | for (;;) | - | ||||||||||||||||||||||||
334 | { | - | ||||||||||||||||||||||||
335 | /* Here outptr + outbytes_remaining = result + result_size - 1. */ | - | ||||||||||||||||||||||||
336 | size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining); | - | ||||||||||||||||||||||||
337 | - | |||||||||||||||||||||||||
338 | if (res == (size_t)(-1))
| 0-15 | ||||||||||||||||||||||||
339 | { | - | ||||||||||||||||||||||||
340 | if (errno == E2BIG)
| 0 | ||||||||||||||||||||||||
341 | { | - | ||||||||||||||||||||||||
342 | size_t used = outptr - result; | - | ||||||||||||||||||||||||
343 | size_t newsize = result_size * 2; | - | ||||||||||||||||||||||||
344 | char *newresult; | - | ||||||||||||||||||||||||
345 | - | |||||||||||||||||||||||||
346 | if (!(newsize > result_size))
| 0 | ||||||||||||||||||||||||
347 | { | - | ||||||||||||||||||||||||
348 | errno = ENOMEM; | - | ||||||||||||||||||||||||
349 | goto failed; never executed: goto failed; | 0 | ||||||||||||||||||||||||
350 | } | - | ||||||||||||||||||||||||
351 | newresult = (char *) realloc (result, newsize); | - | ||||||||||||||||||||||||
352 | if (newresult == NULL)
| 0 | ||||||||||||||||||||||||
353 | { | - | ||||||||||||||||||||||||
354 | errno = ENOMEM; | - | ||||||||||||||||||||||||
355 | goto failed; never executed: goto failed; | 0 | ||||||||||||||||||||||||
356 | } | - | ||||||||||||||||||||||||
357 | result = newresult; | - | ||||||||||||||||||||||||
358 | result_size = newsize; | - | ||||||||||||||||||||||||
359 | outptr = result + used; | - | ||||||||||||||||||||||||
360 | outbytes_remaining = result_size - 1 - used; | - | ||||||||||||||||||||||||
361 | } never executed: end of block | 0 | ||||||||||||||||||||||||
362 | else | - | ||||||||||||||||||||||||
363 | goto failed; never executed: goto failed; | 0 | ||||||||||||||||||||||||
364 | } | - | ||||||||||||||||||||||||
365 | else | - | ||||||||||||||||||||||||
366 | break; executed 15 times by 2 tests: break; Executed by:
| 15 | ||||||||||||||||||||||||
367 | } | - | ||||||||||||||||||||||||
368 | # endif | - | ||||||||||||||||||||||||
369 | - | |||||||||||||||||||||||||
370 | /* Add the terminating NUL byte. */ | - | ||||||||||||||||||||||||
371 | *outptr++ = '\0'; | - | ||||||||||||||||||||||||
372 | - | |||||||||||||||||||||||||
373 | length = outptr - result; | - | ||||||||||||||||||||||||
374 | } | - | ||||||||||||||||||||||||
375 | - | |||||||||||||||||||||||||
376 | /* Give away unused memory. */ | - | ||||||||||||||||||||||||
377 | if (length < result_size)
| 0-15 | ||||||||||||||||||||||||
378 | { | - | ||||||||||||||||||||||||
379 | char *smaller_result = (char *) realloc (result, length); | - | ||||||||||||||||||||||||
380 | - | |||||||||||||||||||||||||
381 | if (smaller_result != NULL)
| 0-15 | ||||||||||||||||||||||||
382 | result = smaller_result; executed 15 times by 2 tests: result = smaller_result; Executed by:
| 15 | ||||||||||||||||||||||||
383 | } executed 15 times by 2 tests: end of block Executed by:
| 15 | ||||||||||||||||||||||||
384 | - | |||||||||||||||||||||||||
385 | return result; executed 15 times by 2 tests: return result; Executed by:
| 15 | ||||||||||||||||||||||||
386 | - | |||||||||||||||||||||||||
387 | failed: | - | ||||||||||||||||||||||||
388 | { | - | ||||||||||||||||||||||||
389 | int saved_errno = errno; | - | ||||||||||||||||||||||||
390 | free (result); | - | ||||||||||||||||||||||||
391 | errno = saved_errno; | - | ||||||||||||||||||||||||
392 | return NULL; executed 15 times by 2 tests: return ((void *)0) ; Executed by:
| 15 | ||||||||||||||||||||||||
393 | } | - | ||||||||||||||||||||||||
394 | - | |||||||||||||||||||||||||
395 | # endif | - | ||||||||||||||||||||||||
396 | } | - | ||||||||||||||||||||||||
397 | - | |||||||||||||||||||||||||
398 | #endif | - | ||||||||||||||||||||||||
399 | - | |||||||||||||||||||||||||
400 | char * | - | ||||||||||||||||||||||||
401 | str_iconv (const char *src, const char *from_codeset, const char *to_codeset) | - | ||||||||||||||||||||||||
402 | { | - | ||||||||||||||||||||||||
403 | if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
| 0-30 | ||||||||||||||||||||||||
404 | { | - | ||||||||||||||||||||||||
405 | char *result = strdup (src); never executed: __retval = (char *) memcpy (__retval, src , __len);
| 0 | ||||||||||||||||||||||||
406 | - | |||||||||||||||||||||||||
407 | if (result == NULL)
| 0 | ||||||||||||||||||||||||
408 | errno = ENOMEM; never executed: (*__errno_location ()) = 12 ; | 0 | ||||||||||||||||||||||||
409 | return result; never executed: return result; | 0 | ||||||||||||||||||||||||
410 | } | - | ||||||||||||||||||||||||
411 | else | - | ||||||||||||||||||||||||
412 | { | - | ||||||||||||||||||||||||
413 | #if HAVE_ICONV | - | ||||||||||||||||||||||||
414 | iconv_t cd; | - | ||||||||||||||||||||||||
415 | char *result; | - | ||||||||||||||||||||||||
416 | - | |||||||||||||||||||||||||
417 | /* Avoid glibc-2.1 bug with EUC-KR. */ | - | ||||||||||||||||||||||||
418 | # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \ | - | ||||||||||||||||||||||||
419 | && !defined _LIBICONV_VERSION | - | ||||||||||||||||||||||||
420 | if (c_strcasecmp (from_codeset, "EUC-KR") == 0 | - | ||||||||||||||||||||||||
421 | || c_strcasecmp (to_codeset, "EUC-KR") == 0) | - | ||||||||||||||||||||||||
422 | { | - | ||||||||||||||||||||||||
423 | errno = EINVAL; | - | ||||||||||||||||||||||||
424 | return NULL; | - | ||||||||||||||||||||||||
425 | } | - | ||||||||||||||||||||||||
426 | # endif | - | ||||||||||||||||||||||||
427 | cd = iconv_open (to_codeset, from_codeset); | - | ||||||||||||||||||||||||
428 | if (cd == (iconv_t) -1)
| 0-30 | ||||||||||||||||||||||||
429 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||||||||||||||
430 | - | |||||||||||||||||||||||||
431 | result = str_cd_iconv (src, cd); | - | ||||||||||||||||||||||||
432 | - | |||||||||||||||||||||||||
433 | if (result == NULL)
| 15 | ||||||||||||||||||||||||
434 | { | - | ||||||||||||||||||||||||
435 | /* Close cd, but preserve the errno from str_cd_iconv. */ | - | ||||||||||||||||||||||||
436 | int saved_errno = errno; | - | ||||||||||||||||||||||||
437 | iconv_close (cd); | - | ||||||||||||||||||||||||
438 | errno = saved_errno; | - | ||||||||||||||||||||||||
439 | } executed 15 times by 2 tests: end of block Executed by:
| 15 | ||||||||||||||||||||||||
440 | else | - | ||||||||||||||||||||||||
441 | { | - | ||||||||||||||||||||||||
442 | if (iconv_close (cd) < 0)
| 0-15 | ||||||||||||||||||||||||
443 | { | - | ||||||||||||||||||||||||
444 | /* Return NULL, but free the allocated memory, and while doing | - | ||||||||||||||||||||||||
445 | that, preserve the errno from iconv_close. */ | - | ||||||||||||||||||||||||
446 | int saved_errno = errno; | - | ||||||||||||||||||||||||
447 | free (result); | - | ||||||||||||||||||||||||
448 | errno = saved_errno; | - | ||||||||||||||||||||||||
449 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||||||||||||||
450 | } | - | ||||||||||||||||||||||||
451 | } executed 15 times by 2 tests: end of block Executed by:
| 15 | ||||||||||||||||||||||||
452 | return result; executed 30 times by 2 tests: return result; Executed by:
| 30 | ||||||||||||||||||||||||
453 | #else | - | ||||||||||||||||||||||||
454 | /* This is a different error code than if iconv_open existed but didn't | - | ||||||||||||||||||||||||
455 | support from_codeset and to_codeset, so that the caller can emit | - | ||||||||||||||||||||||||
456 | an error message such as | - | ||||||||||||||||||||||||
457 | "iconv() is not supported. Installing GNU libiconv and | - | ||||||||||||||||||||||||
458 | then reinstalling this package would fix this." */ | - | ||||||||||||||||||||||||
459 | errno = ENOSYS; | - | ||||||||||||||||||||||||
460 | return NULL; | - | ||||||||||||||||||||||||
461 | #endif | - | ||||||||||||||||||||||||
462 | } | - | ||||||||||||||||||||||||
463 | } | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |