~ubuntu-branches/debian/wheezy/betaradio/wheezy

« back to all changes in this revision

Viewing changes to libltdl/lt_dlloader.c

  • Committer: Package Import Robot
  • Author(s): Shih-Yuan Lee (FourDollars)
  • Date: 2012-01-14 20:58:32 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20120114205832-j58rskmjowwgcv37
Tags: 1.4-1
* New upstream release.
* debian/patches/00_dont_install_header: Don't install header file into the
  system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* lt_dlloader.c -- dynamic library loader interface
 
2
 
 
3
   Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
 
4
   Written by Gary V. Vaughan, 2004
 
5
 
 
6
   NOTE: The canonical source of this file is maintained with the
 
7
   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
 
8
 
 
9
GNU Libltdl is free software; you can redistribute it and/or
 
10
modify it under the terms of the GNU Lesser General Public
 
11
License as published by the Free Software Foundation; either
 
12
version 2 of the License, or (at your option) any later version.
 
13
 
 
14
As a special exception to the GNU Lesser General Public License,
 
15
if you distribute this file as part of a program or library that
 
16
is built using GNU Libtool, you may include this file under the
 
17
same distribution terms that you use for the rest of that program.
 
18
 
 
19
GNU Libltdl is distributed in the hope that it will be useful,
 
20
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
GNU Lesser General Public License for more details.
 
23
 
 
24
You should have received a copy of the GNU Lesser General Public
 
25
License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
 
26
copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
 
27
or obtained by writing to the Free Software Foundation, Inc.,
 
28
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
29
*/
 
30
 
 
31
#include "lt__private.h"
 
32
#include "lt_dlloader.h"
 
33
 
 
34
#define RETURN_SUCCESS 0
 
35
#define RETURN_FAILURE 1
 
36
 
 
37
static void *   loader_callback (SList *item, void *userdata);
 
38
 
 
39
/* A list of all the dlloaders we know about, each stored as a boxed
 
40
   SList item:  */
 
41
static  SList    *loaders               = 0;
 
42
 
 
43
 
 
44
/* Return NULL, unless the loader in this ITEM has a matching name,
 
45
   in which case we return the matching item so that its address is
 
46
   passed back out (for possible freeing) by slist_remove.  */
 
47
static void *
 
48
loader_callback (SList *item, void *userdata)
 
49
{
 
50
  const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
 
51
  const char *      name    = (const char *) userdata;
 
52
 
 
53
  assert (vtable);
 
54
 
 
55
  return streq (vtable->name, name) ? (void *) item : NULL;
 
56
}
 
57
 
 
58
 
 
59
/* Hook VTABLE into our global LOADERS list according to its own
 
60
   PRIORITY field value.  */
 
61
int
 
62
lt_dlloader_add (const lt_dlvtable *vtable)
 
63
{
 
64
  SList *item;
 
65
 
 
66
  if ((vtable == 0)     /* diagnose invalid vtable fields */
 
67
      || (vtable->module_open == 0)
 
68
      || (vtable->module_close == 0)
 
69
      || (vtable->find_sym == 0)
 
70
      || ((vtable->priority != LT_DLLOADER_PREPEND) &&
 
71
          (vtable->priority != LT_DLLOADER_APPEND)))
 
72
    {
 
73
      LT__SETERROR (INVALID_LOADER);
 
74
      return RETURN_FAILURE;
 
75
    }
 
76
 
 
77
  item = slist_box (vtable);
 
78
  if (!item)
 
79
    {
 
80
      (*lt__alloc_die) ();
 
81
 
 
82
      /* Let the caller know something went wrong if lt__alloc_die
 
83
         doesn't abort.  */
 
84
      return RETURN_FAILURE;
 
85
    }
 
86
 
 
87
  if (vtable->priority == LT_DLLOADER_PREPEND)
 
88
    {
 
89
      loaders = slist_cons (item, loaders);
 
90
    }
 
91
  else
 
92
    {
 
93
      assert (vtable->priority == LT_DLLOADER_APPEND);
 
94
      loaders = slist_concat (loaders, item);
 
95
    }
 
96
 
 
97
  return RETURN_SUCCESS;
 
98
}
 
99
 
 
100
#ifdef LT_DEBUG_LOADERS
 
101
static void *
 
102
loader_dump_callback (SList *item, void *userdata)
 
103
{
 
104
  const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
 
105
  fprintf (stderr, ", %s", (vtable && vtable->name) ? vtable->name : "(null)");
 
106
  return 0;
 
107
}
 
108
 
 
109
void
 
110
lt_dlloader_dump (void)
 
111
{
 
112
  fprintf (stderr, "loaders: ");
 
113
  if (!loaders)
 
114
    {
 
115
      fprintf (stderr, "(empty)");
 
116
    }
 
117
  else
 
118
    {
 
119
      const lt_dlvtable *head = (const lt_dlvtable *) loaders->userdata;
 
120
      fprintf (stderr, "%s", (head && head->name) ? head->name : "(null)");
 
121
      if (slist_tail (loaders))
 
122
        slist_foreach (slist_tail (loaders), loader_dump_callback, NULL);
 
123
    }
 
124
  fprintf (stderr, "\n");
 
125
}
 
126
#endif
 
127
 
 
128
/* An iterator for the global loader list: if LOADER is NULL, then
 
129
   return the first element, otherwise the following element.  */
 
130
lt_dlloader
 
131
lt_dlloader_next (lt_dlloader loader)
 
132
{
 
133
  SList *item = (SList *) loader;
 
134
  return (lt_dlloader) (item ? item->next : loaders);
 
135
}
 
136
 
 
137
 
 
138
/* Non-destructive unboxing of a loader.  */
 
139
const lt_dlvtable *
 
140
lt_dlloader_get (lt_dlloader loader)
 
141
{
 
142
  return (const lt_dlvtable *) (loader ? ((SList *) loader)->userdata : NULL);
 
143
}
 
144
 
 
145
 
 
146
/* Return the contents of the first item in the global loader list
 
147
   with a matching NAME after removing it from that list.  If there
 
148
   was no match, return NULL; if there is an error, return NULL and
 
149
   set an error for lt_dlerror; do not set an error if only resident
 
150
   modules need this loader; in either case, the loader list is not
 
151
   changed if NULL is returned.  */
 
152
lt_dlvtable *
 
153
lt_dlloader_remove (const char *name)
 
154
{
 
155
  const lt_dlvtable *   vtable  = lt_dlloader_find (name);
 
156
  static const char     id_string[] = "lt_dlloader_remove";
 
157
  lt_dlinterface_id     iface;
 
158
  lt_dlhandle           handle = 0;
 
159
  int                   in_use = 0;
 
160
  int                   in_use_by_resident = 0;
 
161
 
 
162
  if (!vtable)
 
163
    {
 
164
      LT__SETERROR (INVALID_LOADER);
 
165
      return 0;
 
166
    }
 
167
 
 
168
  /* Fail if there are any open modules which use this loader.  */
 
169
  iface = lt_dlinterface_register (id_string, NULL);
 
170
  while ((handle = lt_dlhandle_iterate (iface, handle)))
 
171
    {
 
172
      lt_dlhandle cur = handle;
 
173
      if (cur->vtable == vtable)
 
174
        {
 
175
          in_use = 1;
 
176
          if (lt_dlisresident (handle))
 
177
            in_use_by_resident = 1;
 
178
        }
 
179
    }
 
180
  lt_dlinterface_free (iface);
 
181
  if (in_use)
 
182
    {
 
183
      if (!in_use_by_resident)
 
184
        LT__SETERROR (REMOVE_LOADER);
 
185
      return 0;
 
186
    }
 
187
 
 
188
  /* Call the loader finalisation function.  */
 
189
  if (vtable && vtable->dlloader_exit)
 
190
    {
 
191
      if ((*vtable->dlloader_exit) (vtable->dlloader_data) != 0)
 
192
        {
 
193
          /* If there is an exit function, and it returns non-zero
 
194
             then it must set an error, and we will not remove it
 
195
             from the list.  */
 
196
          return 0;
 
197
        }
 
198
    }
 
199
 
 
200
  /* If we got this far, remove the loader from our global list.  */
 
201
  return (lt_dlvtable *)
 
202
      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) name));
 
203
}
 
204
 
 
205
 
 
206
const lt_dlvtable *
 
207
lt_dlloader_find (const char *name)
 
208
{
 
209
  return lt_dlloader_get (slist_find (loaders, loader_callback, (void *) name));
 
210
}