2003-06-18 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / src / module.c
1 /* module.c - Module management for libgcrypt.
2  * Copyright (C) 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <assert.h>
22 #include <config.h>
23 #include <errno.h>
24 #include "g10lib.h"
25
26 /* Internal function.  Generate a new, unique module ID for a module
27    that should be inserted into the module chain starting at
28    MODULES.  */
29 static gpg_err_code_t
30 _gcry_module_id_new (gcry_module_t *modules, unsigned int *id_new)
31 {
32   /* FIXME, what should be the ID of the first module registered by
33      the user?  */
34   unsigned int id_min = 600, id_max = (unsigned int) -1, id;
35   gpg_err_code_t err = GPG_ERR_NO_ERROR;
36   gcry_module_t *module;
37
38   /* Search for unused ID.  */
39   for (id = id_min; id < id_max; id++)
40     {
41       /* Search for a module with the current ID.  */
42       for (module = modules; module; module = module->next)
43         if (id == module->id)
44           break;
45
46       if (! module)
47         /* None found -> the ID is available for use.  */
48         break;
49     }
50
51   if (id < id_max)
52     /* Done.  */
53     *id_new = id;
54   else
55     /* No free ID found.  */
56     err = GPG_ERR_INTERNAL;
57
58   return err;
59 }
60
61 /* Public function.  Add a module specification to the list ENTRIES.
62    The new module has it's use-counter set to one.  */
63 gpg_err_code_t
64 _gcry_module_add (gcry_module_t **entries, unsigned int id,
65                   void *spec, gcry_module_t **module)
66 {
67   gpg_err_code_t err = 0;
68   gcry_module_t *entry;
69
70   if (! id)
71     err = _gcry_module_id_new (*entries, &id);
72
73   if (! err)
74     {
75       entry = gcry_malloc (sizeof (gcry_module_t));
76       if (! entry)
77         err = gpg_err_code_from_errno (errno);
78     }
79
80   if (! err)
81     {
82       /* Fill new module entry.  */
83       entry->flags = 0;
84       entry->counter = 1;
85       entry->spec = spec;
86       entry->id = id;
87
88       /* Link it into the list.  */
89       entry->next = *entries;
90       entry->prevp = entries;
91       if (*entries)
92         (*entries)->prevp = &entry->next;
93       *entries = entry;
94
95       /* And give it to the caller.  */
96       if (module)
97         *module = entry;
98     }
99   return err;
100 }
101
102 /* Internal function.  Unlink CIPHER_ENTRY from the list of registered
103    ciphers and destroy it.  */
104 static void
105 _gcry_module_drop (gcry_module_t *entry)
106 {
107   *entry->prevp = entry->next;
108   if (entry->next)
109     entry->next->prevp = entry->prevp;
110
111   gcry_free (entry);
112 }
113
114 /* Public function.  Lookup a module specification by it's ID.  After a
115    successfull lookup, the module has it's resource counter
116    incremented.  */
117 gcry_module_t *
118 _gcry_module_lookup_id (gcry_module_t *entries, unsigned int id)
119 {
120   gcry_module_t *entry;
121
122   for (entry = entries; entry; entry = entry->next)
123     if (entry->id == id)
124       {
125         entry->counter++;
126         break;
127       }
128
129   return entry;
130 }
131
132 /* Public function.  Lookup a module specification.  After a
133    successfull lookup, the module has it's resource counter
134    incremented.  FUNC is a function provided by the caller, which is
135    responsible for identifying the wanted module.  */
136 gcry_module_t *
137 _gcry_module_lookup (gcry_module_t *entries, void *data,
138                      gcry_module_tLookup func)
139 {
140   gcry_module_t *entry;
141
142   for (entry = entries; entry; entry = entry->next)
143     if ((*func) (entry->spec, data))
144       {
145         entry->counter++;
146         break;
147       }
148
149   return entry;
150 }
151
152 /* Public function.  Release a module.  In case the use-counter
153    reaches zero, destroy the module.  */
154 void
155 _gcry_module_release (gcry_module_t *module)
156 {
157   if (! --module->counter)
158     _gcry_module_drop (module);
159 }
160
161 /* Public function.  Add a reference to a module.  */
162 void
163 _gcry_module_use (gcry_module_t *module)
164 {
165   ++module->counter;
166 }