rpm  5.2.1
strtolocale.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 #ifdef HAVE_LANGINFO_H
7 #include <langinfo.h>
8 #endif
9 #ifdef HAVE_ICONV
10 #include <iconv.h>
11 #endif
12 #include <rpmiotypes.h>
13 #include "debug.h"
14 
15 const char * xstrtolocale(const char *str)
16 {
17 #ifdef HAVE_ICONV
18  /*@only@*/
19  static char *locale_encoding = NULL;
20  static int locale_encoding_is_utf8 = 0;
21  iconv_t cd;
22  size_t src_size, dest_size;
23  char *result, *dest;
24  const char *src;
25 
26  if (locale_encoding == NULL) {
27 #ifdef HAVE_LANGINFO_H
28  const char *encoding = nl_langinfo(CODESET);
29 #else
30  const char *encoding = "char";
31 #endif
32  locale_encoding = xmalloc(strlen(encoding) + 11);
33  sprintf(locale_encoding, "%s//TRANSLIT", encoding);
34  locale_encoding_is_utf8 = strcasecmp(encoding, "UTF-8") == 0;
35  }
36 
37  if (!str || !*str || locale_encoding_is_utf8)
38  return str;
39 
40  cd = iconv_open(locale_encoding, "UTF-8");
41  if (cd == (iconv_t)-1)
42  return str;
43 
44  src_size = strlen(str);
45  dest_size = src_size + 1;
46  result = xmalloc(dest_size);
47  src = str;
48  dest = result;
49  for(;;) {
50  size_t status = iconv(cd, (char **)&src, &src_size, &dest, &dest_size);
51  if (status == (size_t)-1) {
52  size_t dest_offset;
53  if (errno != E2BIG) {
54  free(result);
55  (void) iconv_close(cd);
56  return str;
57  }
58  dest_offset = dest - result;
59  dest_size += 16;
60  result = xrealloc(result, dest_offset + dest_size);
61  dest = result + dest_offset;
62  } else if (src_size == 0) {
63  if (src == NULL) break;
64  src = NULL;
65  }
66  }
67  (void) iconv_close(cd);
68  free((void *)str);
69  if (dest_size == 0) {
70  size_t dest_offset = dest - result;
71  result = xrealloc(result, dest_offset + 1);
72  dest = result + dest_offset;
73  }
74  *dest = '\0';
75  return result;
76 #else
77  return str;
78 #endif
79 }