]> sourceware.org Git - glibc.git/blame - dlfcn/dlerror.c
Update.
[glibc.git] / dlfcn / dlerror.c
CommitLineData
c84142e8 1/* Return error detail for failing <dlfcn.h> functions.
04470dc0 2 Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
d66e34cd 9
afd4eb37
UD
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 Library General Public License for more details.
d66e34cd 14
afd4eb37
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
d66e34cd 19
d66e34cd 20#include <dlfcn.h>
04470dc0 21#include <libintl.h>
d66e34cd 22#include <stdio.h>
d66e34cd 23#include <stdlib.h>
a853022c 24#include <string.h>
8d9618b7 25#include <bits/libc-lock.h>
8d9618b7
UD
26
27/* Type for storing results of dynamic loading actions. */
28struct dl_action_result
29 {
30 int errcode;
4f2793d4 31 int returned;
04470dc0
UD
32 const char *objname;
33 const char *errstring;
8d9618b7
UD
34 };
35static struct dl_action_result last_result;
36static struct dl_action_result *static_buf;
37
38
39/* This is the key for the thread specific memory. */
40static __libc_key_t key;
41
42/* Destructor for the thread-specific data. */
43static void init (void);
44static void free_key_mem (void *mem);
d66e34cd 45
d66e34cd
RM
46
47char *
48dlerror (void)
49{
4f2793d4 50 char *buf;
8d9618b7 51 struct dl_action_result *result;
d66e34cd 52
8d9618b7 53 /* Get error string. */
af3878df
UD
54 result = (struct dl_action_result *) __libc_getspecific (key);
55 if (result == NULL)
8d9618b7
UD
56 result = &last_result;
57
4f2793d4
UD
58 /* Test whether we already returned the string. */
59 if (result->returned != 0)
60 {
61 /* We can now free the string. */
62 if (result->errstring != NULL)
63 {
04470dc0 64 free ((char *) result->errstring);
4f2793d4
UD
65 result->errstring = NULL;
66 }
67 buf = NULL;
68 }
421f82e5 69 else
8d9618b7 70 {
04470dc0 71 buf = (char *) result->errstring;
4f2793d4 72 if (result->errcode != 0
04470dc0
UD
73 && __asprintf (&buf, "%s: %s: %s",
74 result->objname, _(result->errstring),
75 strerror (result->errcode)) != -1)
4f2793d4
UD
76 {
77 /* We don't need the error string anymore. */
04470dc0 78 free ((char *) result->errstring);
4f2793d4
UD
79 result->errstring = buf;
80 }
8d9618b7 81
4f2793d4
UD
82 /* Mark the error as returned. */
83 result->returned = 1;
8d9618b7 84 }
421f82e5 85
8d9618b7 86 return buf;
d66e34cd
RM
87}
88
89int
d0fc4041 90internal_function
993b3242 91_dlerror_run (void (*operate) (void *), void *args)
d66e34cd 92{
8d9618b7
UD
93 __libc_once_define (static, once);
94 struct dl_action_result *result;
95
96 /* If we have not yet initialized the buffer do it now. */
97 __libc_once (once, init);
98
99 /* Get error string and number. */
100 if (static_buf != NULL)
101 result = static_buf;
102 else
103 {
104 /* We don't use the static buffer and so we have a key. Use it
105 to get the thread-specific buffer. */
106 result = __libc_getspecific (key);
107 if (result == NULL)
108 {
109 result = (struct dl_action_result *) calloc (1, sizeof (*result));
110 if (result == NULL)
111 /* We are out of memory. Since this is no really critical
112 situation we carry on by using the global variable.
113 This might lead to conflicts between the threads but
114 they soon all will have memory problems. */
115 result = &last_result;
116 else
117 /* Set the tsd. */
118 __libc_setspecific (key, result);
119 }
120 }
121
122 if (result->errstring != NULL)
dcf0671d
UD
123 /* Free the error string from the last failed command. This can
124 happen if `dlerror' was not run after an error was found. */
04470dc0 125 free ((char *) result->errstring);
8d9618b7 126
04470dc0
UD
127 result->errcode = _dl_catch_error (&result->objname, &result->errstring,
128 operate, args);
8d9618b7 129
4f2793d4
UD
130 /* If no error we mark that no error string is available. */
131 result->returned = result->errstring == NULL;
132
8d9618b7
UD
133 return result->errstring != NULL;
134}
135
dcf0671d 136
8d9618b7
UD
137/* Initialize buffers for results. */
138static void
139init (void)
140{
141 if (__libc_key_create (&key, free_key_mem))
142 /* Creating the key failed. This means something really went
143 wrong. In any case use a static buffer which is better than
144 nothing. */
145 static_buf = &last_result;
146}
147
148
149/* Free the thread specific data, this is done if a thread terminates. */
150static void
151free_key_mem (void *mem)
152{
153 free (mem);
154 __libc_setspecific (key, NULL);
d66e34cd 155}
This page took 0.128339 seconds and 5 git commands to generate.