xref: /illumos-gate/usr/src/test/libc-tests/tests/strerror.c (revision 9164a50bf932130cbb5097a16f6986873ce0e6e5)
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