Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2008 Stefan Walter
5 : *
6 : * This program 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 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * 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, see
18 : * <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "config.h"
22 :
23 : #include "gkm-attributes.h"
24 : #define DEBUG_FLAG GKM_DEBUG_OBJECT
25 : #include "gkm-debug.h"
26 : #include "gkm-object.h"
27 : #include "gkm-memory-store.h"
28 : #include "gkm-transaction.h"
29 : #include "gkm-util.h"
30 :
31 : struct _GkmMemoryStore {
32 : GkmStore parent;
33 : GHashTable *entries;
34 : };
35 :
36 : typedef struct _Revert {
37 : GHashTable *attributes;
38 : CK_ATTRIBUTE_TYPE type;
39 : CK_ATTRIBUTE_PTR attr;
40 : } Revert;
41 :
42 2192 : G_DEFINE_TYPE (GkmMemoryStore, gkm_memory_store, GKM_TYPE_STORE);
43 :
44 : /* -----------------------------------------------------------------------------
45 : * INTERNAL
46 : */
47 :
48 : static void
49 16 : attribute_free (gpointer data)
50 : {
51 16 : CK_ATTRIBUTE_PTR attr = data;
52 16 : if (attr) {
53 8 : g_free (attr->pValue);
54 8 : g_slice_free (CK_ATTRIBUTE, attr);
55 : }
56 16 : }
57 :
58 : static CK_ATTRIBUTE_PTR
59 8 : attribute_dup (CK_ATTRIBUTE_PTR attr)
60 : {
61 : CK_ATTRIBUTE_PTR copy;
62 8 : g_assert (attr);
63 8 : copy = g_slice_new (CK_ATTRIBUTE);
64 8 : copy->ulValueLen = attr->ulValueLen;
65 8 : copy->pValue = g_memdup (attr->pValue, copy->ulValueLen);
66 8 : copy->type = attr->type;
67 8 : return copy;
68 : }
69 :
70 : static void
71 1 : object_gone (gpointer data, GObject *was_object)
72 : {
73 : GkmMemoryStore *self;
74 :
75 1 : g_assert (GKM_IS_MEMORY_STORE (data));
76 1 : self = GKM_MEMORY_STORE (data);
77 :
78 1 : if (!g_hash_table_remove (self->entries, was_object))
79 0 : g_return_if_reached ();
80 : }
81 :
82 : static gboolean
83 5 : remove_each_object (gpointer key, gpointer value, gpointer user_data)
84 : {
85 5 : g_assert (GKM_IS_OBJECT (key));
86 5 : g_assert (GKM_IS_MEMORY_STORE (user_data));
87 :
88 5 : g_object_weak_unref (key, object_gone, user_data);
89 5 : return TRUE;
90 : }
91 :
92 : static gboolean
93 8 : complete_set (GkmTransaction *transaction, GkmObject *object, Revert *revert)
94 : {
95 8 : g_assert (GKM_IS_OBJECT (object));
96 :
97 8 : if (gkm_transaction_get_failed (transaction)) {
98 4 : if (revert->attr)
99 2 : g_hash_table_replace (revert->attributes, &(revert->attr->type), revert->attr);
100 : else
101 2 : g_hash_table_remove (revert->attributes, &(revert->type));
102 :
103 4 : gkm_object_notify_attribute (object, revert->type);
104 :
105 4 : revert->attr = NULL;
106 4 : revert->type = 0;
107 : }
108 :
109 8 : g_hash_table_unref (revert->attributes);
110 8 : attribute_free (revert->attr);
111 8 : g_slice_free (Revert, revert);
112 8 : return TRUE;
113 : }
114 :
115 : /* -----------------------------------------------------------------------------
116 : * OBJECT
117 : */
118 :
119 : static CK_RV
120 15 : gkm_memory_store_real_read_value (GkmStore *base, GkmObject *object, CK_ATTRIBUTE_PTR attr)
121 : {
122 15 : GkmMemoryStore *self = GKM_MEMORY_STORE (base);
123 : GHashTable *attributes;
124 : CK_ATTRIBUTE_PTR at;
125 :
126 15 : attributes = g_hash_table_lookup (self->entries, object);
127 15 : if (attributes == NULL) {
128 5 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no object");
129 5 : return CKR_ATTRIBUTE_TYPE_INVALID;
130 : }
131 :
132 10 : at = g_hash_table_lookup (attributes, &(attr->type));
133 10 : if (at == NULL) {
134 1 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no attribute: %s",
135 : gkm_log_attr_type (attr->type));
136 1 : return CKR_ATTRIBUTE_TYPE_INVALID;
137 : }
138 :
139 9 : g_assert (at->type == attr->type);
140 :
141 : /* Yes, we don't fill a buffer, just return pointer */
142 9 : attr->pValue = at->pValue;
143 9 : attr->ulValueLen = at->ulValueLen;
144 :
145 9 : return CKR_OK;
146 : }
147 :
148 : static void
149 8 : gkm_memory_store_real_write_value (GkmStore *base, GkmTransaction *transaction,
150 : GkmObject *object, CK_ATTRIBUTE_PTR attr)
151 : {
152 8 : GkmMemoryStore *self = GKM_MEMORY_STORE (base);
153 : GHashTable *attributes;
154 : CK_ATTRIBUTE_PTR at;
155 : Revert *revert;
156 :
157 8 : g_return_if_fail (!gkm_transaction_get_failed (transaction));
158 :
159 8 : attributes = g_hash_table_lookup (self->entries, object);
160 8 : if (attributes == NULL) {
161 6 : g_object_weak_ref (G_OBJECT (object), object_gone, self);
162 6 : attributes = g_hash_table_new_full (gkm_util_ulong_hash, gkm_util_ulong_equal,
163 : NULL, attribute_free);
164 6 : g_hash_table_replace (self->entries, object, attributes);
165 : }
166 :
167 : /* No need to go any further if no change */
168 8 : at = g_hash_table_lookup (attributes, &(attr->type));
169 8 : if (at != NULL && gkm_attribute_equal (at, attr))
170 0 : return;
171 :
172 8 : revert = g_slice_new0 (Revert);
173 8 : revert->attributes = g_hash_table_ref (attributes);
174 8 : revert->type = attr->type;
175 8 : revert->attr = at;
176 8 : g_hash_table_steal (attributes, &(attr->type));
177 8 : gkm_transaction_add (transaction, object, (GkmTransactionFunc)complete_set, revert);
178 :
179 8 : attr = attribute_dup (attr);
180 8 : g_hash_table_replace (attributes, &(attr->type), attr);
181 8 : gkm_object_notify_attribute (object, attr->type);
182 : }
183 :
184 : static GObject*
185 517 : gkm_memory_store_constructor (GType type, guint n_props, GObjectConstructParam *props)
186 : {
187 517 : GkmMemoryStore *self = GKM_MEMORY_STORE (G_OBJECT_CLASS (gkm_memory_store_parent_class)->constructor(type, n_props, props));
188 517 : g_return_val_if_fail (self, NULL);
189 :
190 517 : return G_OBJECT (self);
191 : }
192 :
193 : static void
194 517 : gkm_memory_store_init (GkmMemoryStore *self)
195 : {
196 517 : self->entries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_hash_table_unref);
197 517 : }
198 :
199 : static void
200 517 : gkm_memory_store_dispose (GObject *obj)
201 : {
202 517 : GkmMemoryStore *self = GKM_MEMORY_STORE (obj);
203 :
204 517 : g_hash_table_foreach_remove (self->entries, remove_each_object, self);
205 :
206 517 : G_OBJECT_CLASS (gkm_memory_store_parent_class)->dispose (obj);
207 517 : }
208 :
209 : static void
210 517 : gkm_memory_store_finalize (GObject *obj)
211 : {
212 517 : GkmMemoryStore *self = GKM_MEMORY_STORE (obj);
213 :
214 517 : g_assert (g_hash_table_size (self->entries) == 0);
215 517 : g_hash_table_destroy (self->entries);
216 517 : self->entries = NULL;
217 :
218 517 : G_OBJECT_CLASS (gkm_memory_store_parent_class)->finalize (obj);
219 517 : }
220 :
221 : static void
222 0 : gkm_memory_store_set_property (GObject *obj, guint prop_id, const GValue *value,
223 : GParamSpec *pspec)
224 : {
225 : switch (prop_id) {
226 : default:
227 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
228 0 : break;
229 : }
230 0 : }
231 :
232 : static void
233 0 : gkm_memory_store_get_property (GObject *obj, guint prop_id, GValue *value,
234 : GParamSpec *pspec)
235 : {
236 : switch (prop_id) {
237 : default:
238 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
239 0 : break;
240 : }
241 0 : }
242 :
243 : static void
244 47 : gkm_memory_store_class_init (GkmMemoryStoreClass *klass)
245 : {
246 47 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
247 47 : GkmStoreClass *store_class = GKM_STORE_CLASS (klass);
248 :
249 47 : gobject_class->constructor = gkm_memory_store_constructor;
250 47 : gobject_class->dispose = gkm_memory_store_dispose;
251 47 : gobject_class->finalize = gkm_memory_store_finalize;
252 47 : gobject_class->set_property = gkm_memory_store_set_property;
253 47 : gobject_class->get_property = gkm_memory_store_get_property;
254 :
255 47 : store_class->read_value = gkm_memory_store_real_read_value;
256 47 : store_class->write_value = gkm_memory_store_real_write_value;
257 47 : }
258 :
259 : /* -----------------------------------------------------------------------------
260 : * PUBLIC
261 : */
262 :
263 : GkmMemoryStore*
264 517 : gkm_memory_store_new (void)
265 : {
266 517 : return g_object_new (GKM_TYPE_MEMORY_STORE, NULL);
267 : }
|