Coverage Report

Created: 2026-03-31 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wget/lib/setlocale_null-unlocked.c
Line
Count
Source
1
/* Query the name of the current global locale, without locking.
2
   Copyright (C) 2019-2026 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
75.3k
{
37
75.3k
  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
75.3k
  return result;
63
75.3k
}
64
65
int
66
setlocale_null_r_unlocked (int category, char *buf, size_t bufsize)
67
75.3k
{
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
          /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
90
          for (size_t i = 0; i <= length; i++)
91
            buf[i] = result[i];
92
93
          return 0;
94
        }
95
      else
96
        {
97
          if (bufsize > 0)
98
            {
99
              /* Return a truncated result in BUF.
100
                 This is a convenience for callers that don't want to write
101
                 explicit code for handling ERANGE.  */
102
              /* Convert wchar_t[] -> char[], assuming plain ASCII.  */
103
              for (size_t i = 0; i < bufsize; i++)
104
                buf[i] = result[i];
105
              buf[bufsize - 1] = '\0';
106
            }
107
          return ERANGE;
108
        }
109
    }
110
#else
111
75.3k
  const char *result = setlocale_null_unlocked (category);
112
113
75.3k
  if (result == NULL)
114
0
    {
115
      /* CATEGORY is invalid.  */
116
0
      if (bufsize > 0)
117
        /* Return an empty string in BUF.
118
           This is a convenience for callers that don't want to write explicit
119
           code for handling EINVAL.  */
120
0
        buf[0] = '\0';
121
0
      return EINVAL;
122
0
    }
123
75.3k
  else
124
75.3k
    {
125
75.3k
      size_t length = strlen (result);
126
75.3k
      if (length < bufsize)
127
75.3k
        {
128
75.3k
          memcpy (buf, result, length + 1);
129
75.3k
          return 0;
130
75.3k
        }
131
0
      else
132
0
        {
133
0
          if (bufsize > 0)
134
0
            {
135
              /* Return a truncated result in BUF.
136
                 This is a convenience for callers that don't want to write
137
                 explicit code for handling ERANGE.  */
138
0
              memcpy (buf, result, bufsize - 1);
139
0
              buf[bufsize - 1] = '\0';
140
0
            }
141
          return ERANGE;
142
0
        }
143
75.3k
    }
144
75.3k
#endif
145
75.3k
}