Coverage Report

Created: 2025-03-06 06:58

/src/wget/lib/setlocale_null-unlocked.c
Line
Count
Source (jump to first uncovered line)
1
/* Query the name of the current global locale, without locking.
2
   Copyright (C) 2019-2025 Free Software Foundation, Inc.
3
4
   This file is free software: you can redistribute it and/or modify
5
   it under the terms of the GNU Lesser General Public License as
6
   published by the Free Software Foundation; either version 2.1 of the
7
   License, or (at your option) any later version.
8
9
   This file is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
   GNU Lesser General Public License for more details.
13
14
   You should have received a copy of the GNU Lesser General Public License
15
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16
17
/* Written by Bruno Haible <bruno@clisp.org>, 2019.  */
18
19
#include <config.h>
20
21
/* Specification.  */
22
#include "setlocale_null.h"
23
24
#include <errno.h>
25
#include <locale.h>
26
#include <string.h>
27
#if defined _WIN32 && !defined __CYGWIN__
28
# include <wchar.h>
29
#endif
30
31
/* Use the system's setlocale() function, not the gnulib override, here.  */
32
#undef setlocale
33
34
const char *
35
setlocale_null_unlocked (int category)
36
0
{
37
0
  const char *result = setlocale (category, NULL);
38
39
#ifdef __ANDROID__
40
  if (result == NULL)
41
    switch (category)
42
      {
43
      case LC_CTYPE:
44
      case LC_NUMERIC:
45
      case LC_TIME:
46
      case LC_COLLATE:
47
      case LC_MONETARY:
48
      case LC_MESSAGES:
49
      case LC_ALL:
50
      case LC_PAPER:
51
      case LC_NAME:
52
      case LC_ADDRESS:
53
      case LC_TELEPHONE:
54
      case LC_MEASUREMENT:
55
        result = "C";
56
        break;
57
      default:
58
        break;
59
      }
60
#endif
61
62
0
  return result;
63
0
}
64
65
int
66
setlocale_null_r_unlocked (int category, char *buf, size_t bufsize)
67
0
{
68
#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
69
  /* On native Windows, nowadays, the setlocale() implementation is based
70
     on _wsetlocale() and uses malloc() for the result.  We are better off
71
     using _wsetlocale() directly.  */
72
  const wchar_t *result = _wsetlocale (category, NULL);
73
74
  if (result == NULL)
75
    {
76
      /* CATEGORY is invalid.  */
77
      if (bufsize > 0)
78
        /* Return an empty string in BUF.
79
           This is a convenience for callers that don't want to write explicit
80
           code for handling EINVAL.  */
81
        buf[0] = '\0';
82
      return EINVAL;
83
    }
84
  else
85
    {
86
      size_t length = wcslen (result);
87
      if (length < bufsize)
88
        {
89
          size_t i;
90
91
          /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
92
          for (i = 0; i <= length; i++)
93
            buf[i] = result[i];
94
95
          return 0;
96
        }
97
      else
98
        {
99
          if (bufsize > 0)
100
            {
101
              /* Return a truncated result in BUF.
102
                 This is a convenience for callers that don't want to write
103
                 explicit code for handling ERANGE.  */
104
              size_t i;
105
106
              /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
107
              for (i = 0; i < bufsize; i++)
108
                buf[i] = result[i];
109
              buf[bufsize - 1] = '\0';
110
            }
111
          return ERANGE;
112
        }
113
    }
114
#else
115
0
  const char *result = setlocale_null_unlocked (category);
116
117
0
  if (result == NULL)
118
0
    {
119
      /* CATEGORY is invalid.  */
120
0
      if (bufsize > 0)
121
        /* Return an empty string in BUF.
122
           This is a convenience for callers that don't want to write explicit
123
           code for handling EINVAL.  */
124
0
        buf[0] = '\0';
125
0
      return EINVAL;
126
0
    }
127
0
  else
128
0
    {
129
0
      size_t length = strlen (result);
130
0
      if (length < bufsize)
131
0
        {
132
0
          memcpy (buf, result, length + 1);
133
0
          return 0;
134
0
        }
135
0
      else
136
0
        {
137
0
          if (bufsize > 0)
138
0
            {
139
              /* Return a truncated result in BUF.
140
                 This is a convenience for callers that don't want to write
141
                 explicit code for handling ERANGE.  */
142
0
              memcpy (buf, result, bufsize - 1);
143
0
              buf[bufsize - 1] = '\0';
144
0
            }
145
0
          return ERANGE;
146
0
        }
147
0
    }
148
0
#endif
149
0
}