1 /* Duplicate handle for selection of locales. 2 Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library 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 GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #include <locale.h> 20 #include <libc-lock.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <localeinfo.h> 25 26 27 /* Lock for protecting global data. */ __libc_rwlock_define(extern,__libc_setlocale_lock attribute_hidden)28__libc_rwlock_define (extern , __libc_setlocale_lock attribute_hidden) 29 30 31 locale_t 32 __duplocale (locale_t dataset) 33 { 34 /* This static object is returned for newlocale (LC_ALL_MASK, "C"). */ 35 if (dataset == _nl_C_locobj_ptr) 36 return dataset; 37 38 /* Handle a special value. */ 39 if (dataset == LC_GLOBAL_LOCALE) 40 dataset = &_nl_global_locale; 41 42 locale_t result; 43 int cnt; 44 size_t names_len = 0; 45 46 /* Calculate the total space we need to store all the names. */ 47 for (cnt = 0; cnt < __LC_LAST; ++cnt) 48 if (cnt != LC_ALL && dataset->__names[cnt] != _nl_C_name) 49 names_len += strlen (dataset->__names[cnt]) + 1; 50 51 /* Get memory. */ 52 result = malloc (sizeof (struct __locale_struct) + names_len); 53 54 if (result != NULL) 55 { 56 char *namep = (char *) (result + 1); 57 58 /* We modify global data (the usage counts). */ 59 __libc_rwlock_wrlock (__libc_setlocale_lock); 60 61 for (cnt = 0; cnt < __LC_LAST; ++cnt) 62 if (cnt != LC_ALL) 63 { 64 result->__locales[cnt] = dataset->__locales[cnt]; 65 if (result->__locales[cnt]->usage_count < MAX_USAGE_COUNT) 66 ++result->__locales[cnt]->usage_count; 67 68 if (dataset->__names[cnt] == _nl_C_name) 69 result->__names[cnt] = _nl_C_name; 70 else 71 { 72 result->__names[cnt] = namep; 73 namep = __stpcpy (namep, dataset->__names[cnt]) + 1; 74 } 75 } 76 77 /* Update the special members. */ 78 result->__ctype_b = dataset->__ctype_b; 79 result->__ctype_tolower = dataset->__ctype_tolower; 80 result->__ctype_toupper = dataset->__ctype_toupper; 81 82 /* It's done. */ 83 __libc_rwlock_unlock (__libc_setlocale_lock); 84 } 85 86 return result; 87 } 88 weak_alias (__duplocale, duplocale) 89