OSDN Git Service

Implement strerror_r()/strerror_s() API.
[mingw/mingw-org-wsl.git] / mingwrt / mingwex / strerror_r.c
1 /*
2  * strerror_r.c
3  *
4  * Implementation of POSIX standard IEEE 1003.1-2001 strerror_r() function.
5  *
6  * $Id$
7  *
8  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
9  * Copyright (C) 2016, 2017, MinGW.org Project
10  *
11  *
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:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
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.
29  *
30  */
31 #define _POSIX_C_SOURCE 200112L
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37
38 int strerror_r( int errnum, char *buf, size_t len )
39 {
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.
46    *
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.
53    */
54   if( buf == NULL )
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.
59      */
60     return errno = ERANGE;
61
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.
64    */
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.
70      */
71     snprintf( buf, len, "Unknown error: %d", errnum );
72     return errno = EINVAL;
73   }
74   /* errnum appears to be valid; copy the associated message, while
75    * checking that its entire text is copied...
76    */
77   if( snprintf( buf, len, "%s", strerror( errnum )) >= len )
78     /*
79      * ...otherwise, set errno on truncation.
80      */
81     return errno = ERANGE;
82
83   /* If we get to here, return zero, indicating success; (DO NOT
84    * modify errno, in this case).
85    */
86   return 0;
87 }
88
89 /* $RCSfile$: end of file */