1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2015 Joyent, Inc. 14 * Copyright 2024 Oxide Computer Company 15 */ 16 17 #include <string.h> 18 #include <locale.h> 19 #include <errno.h> 20 #include <stdio.h> 21 #include <sys/debug.h> 22 23 /* 24 * This is designed to test strerorr and strerror_l's ability to react properly 25 * to being in various locales. This also serves as a regression test for 26 * illumos#6133. This also tests that strerrordesc_np() does not translate 27 * propoerly. 28 * 29 * For this test, we utilize the poorly named 'zz_AA.UTF_8' locale which 30 * was created because it actually has a translation! It 'translates' 31 * the string: 32 * 33 * "No such file or directory" -> "It's a trap!" 34 * 35 * It's otherwise a boring en_US.UTF-8 locale under the hood. 36 * 37 * We explicitly want to verify the following cases: 38 * 39 * + strerror() honors the global locale before uselocale 40 * + strerror() honors the per-thread locale 41 * + strerror_l() always reflects the chosen locale 42 */ 43 44 static int terr = ENOENT; 45 static const char *en = "No such file or directory"; 46 static const char *trans = "It's a trap!"; 47 48 static void 49 strerror_verify(const char *exp) 50 { 51 const char *r; 52 errno = 0; 53 r = strerror(terr); 54 VERIFY0(errno); 55 VERIFY0(strcmp(r, exp)); 56 } 57 58 static void 59 strerror_l_verify(locale_t loc, const char *exp) 60 { 61 const char *r; 62 errno = 0; 63 r = strerror_l(terr, loc); 64 VERIFY0(errno); 65 VERIFY0(strcmp(r, exp)); 66 } 67 68 static void 69 strerrordesc_verify(const char *exp) 70 { 71 const char *r; 72 errno = 0; 73 r = strerrordesc_np(terr); 74 VERIFY0(errno); 75 VERIFY0(strcmp(r, exp)); 76 } 77 78 static void 79 strerrorname_verify(int errnum, const char *exp) 80 { 81 const char *r; 82 errno = 0; 83 r = strerrorname_np(errnum); 84 VERIFY0(errno); 85 VERIFY0(strcmp(r, exp)); 86 } 87 88 int 89 main(void) 90 { 91 locale_t loc; 92 93 (void) setlocale(LC_ALL, "C"); 94 strerror_verify(en); 95 strerrordesc_verify(en); 96 strerrorname_verify(0, "0"); 97 strerrorname_verify(EIO, "EIO"); 98 99 (void) setlocale(LC_ALL, "zz_AA.UTF-8"); 100 strerror_verify(trans); 101 strerrordesc_verify(en); 102 strerrorname_verify(ENOENT, "ENOENT"); 103 strerrorname_verify(ENOTSUP, "ENOTSUP"); 104 105 (void) setlocale(LC_MESSAGES, "C"); 106 strerror_verify(en); 107 strerrordesc_verify(en); 108 strerrorname_verify(EMFILE, "EMFILE"); 109 110 (void) setlocale(LC_ALL, "C"); 111 loc = newlocale(LC_MESSAGES_MASK, "zz_AA.UTF-8", NULL); 112 VERIFY(loc != NULL); 113 114 strerror_verify(en); 115 strerror_l_verify(NULL, en); 116 strerror_l_verify(loc, trans); 117 strerrordesc_verify(en); 118 strerrorname_verify(ENFILE, "ENFILE"); 119 120 (void) uselocale(loc); 121 strerror_verify(trans); 122 strerror_l_verify(NULL, trans); 123 strerror_l_verify(loc, trans); 124 strerrordesc_verify(en); 125 strerrorname_verify(EL2HLT, "EL2HLT"); 126 127 (void) uselocale(LC_GLOBAL_LOCALE); 128 strerror_verify(en); 129 strerror_l_verify(NULL, en); 130 strerror_l_verify(loc, trans); 131 strerrordesc_verify(en); 132 strerrorname_verify(ENOTSUP, "ENOTSUP"); 133 134 /* 135 * Validate a few different error cases. 135 is a Xenix special and 102 136 * is reserved. They both have an error message, but no actual constant. 137 */ 138 VERIFY3P(strerrordesc_np(1234567), ==, NULL); 139 VERIFY3P(strerrordesc_np(102), !=, NULL); 140 VERIFY3P(strerrordesc_np(135), !=, NULL); 141 VERIFY3P(strerrorname_np(1234567), ==, NULL); 142 VERIFY3P(strerrorname_np(102), ==, NULL); 143 VERIFY3P(strerrorname_np(135), ==, NULL); 144 145 freelocale(loc); 146 return (0); 147 } 148