4 * Implementation of POSIX standard IEEE 1003.1-2001 strerror_r() function.
8 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
9 * Copyright (C) 2016, 2017, MinGW.org Project
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
31 #define _POSIX_C_SOURCE 200112L
38 int strerror_r( int errnum, char *buf, size_t len )
40 /* Copy the error message, as retrieved by strerror(), to the user
41 * supplied buffer, so protecting it from subsequent overwrite by a
42 * future call to strerror(); returns zero on success, otherwise sets
43 * errno to, and returns, EINVAL if the user specified errnum doesn't
44 * refer to a valid message, or ERANGE if the associated message, and
45 * its terminating NUL, will not fit within the specified buffer.
47 * Note that Microsoft's strerror() DOES appear to be thread-safe,
48 * but it uses a single static buffer per thread; thus, within any
49 * one thread, successive calls will overwrite the previous contents
50 * of this buffer; use of strerror_r() allows the user to save a copy
51 * of strerror()'s buffer contents, following each call, where they
52 * are not subject to overwriting by a subsequent strerror() call.
55 /* POSIX does not recommend any handling for the case of a NULL
56 * return buffer argument; rather than segfault, we will treat it
57 * as a zero-length buffer, into which we can fit no message text
58 * at all, and so we simply return, setting errno to ERANGE.
60 return errno = ERANGE;
62 /* The buffer pointer isn't NULL; assume it is valid, (we will fail
63 * on segfault if it isn't), and proceed to validate errnum.
65 if( ((unsigned)(errnum)) >= sys_nerr )
66 { /* Note that we check errnum as unsigned; this will also catch a
67 * negative value, since it will appear to be within the positive
68 * range INT_MAX < errnum <= UINT_MAX, while sys_nerr is expected
69 * to be less than INT_MAX.
71 snprintf( buf, len, "Unknown error: %d", errnum );
72 return errno = EINVAL;
74 /* errnum appears to be valid; copy the associated message, while
75 * checking that its entire text is copied...
77 if( snprintf( buf, len, "%s", strerror( errnum )) >= len )
79 * ...otherwise, set errno on truncation.
81 return errno = ERANGE;
83 /* If we get to here, return zero, indicating success; (DO NOT
84 * modify errno, in this case).
89 /* $RCSfile$: end of file */