Whitespace cleanups.
[platform/upstream/evolution-data-server.git] / camel / camel-certdb.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  *  Authors: Jeffrey Stedfast <fejj@ximian.com>
4  *
5  *  Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34
35 #include <glib/gstdio.h>
36
37 #include "camel-certdb.h"
38 #include "camel-file-utils.h"
39 #include "camel-win32.h"
40
41 #define CAMEL_CERTDB_VERSION  0x100
42
43 #define CAMEL_CERTDB_GET_PRIVATE(obj) \
44         (G_TYPE_INSTANCE_GET_PRIVATE \
45         ((obj), CAMEL_TYPE_CERTDB, CamelCertDBPrivate))
46
47 struct _CamelCertDBPrivate {
48         GMutex *db_lock;        /* for the db hashtable/array */
49         GMutex *io_lock;        /* load/save lock, for access to saved_count, etc */
50         GMutex *alloc_lock;     /* for setting up and using allocators */
51         GMutex *ref_lock;       /* for reffing/unreffing certs */
52 };
53
54 static gint certdb_header_load (CamelCertDB *certdb, FILE *istream);
55 static gint certdb_header_save (CamelCertDB *certdb, FILE *ostream);
56 static CamelCert *certdb_cert_load (CamelCertDB *certdb, FILE *istream);
57 static gint certdb_cert_save (CamelCertDB *certdb, CamelCert *cert, FILE *ostream);
58 static CamelCert *certdb_cert_new (CamelCertDB *certdb);
59 static void certdb_cert_free (CamelCertDB *certdb, CamelCert *cert);
60
61 static const gchar *cert_get_string (CamelCertDB *certdb, CamelCert *cert, gint string);
62 static void cert_set_string (CamelCertDB *certdb, CamelCert *cert, gint string, const gchar *value);
63
64 G_DEFINE_TYPE (CamelCertDB, camel_certdb, CAMEL_TYPE_OBJECT)
65
66 static gboolean
67 certdb_str_equal_casecmp (gconstpointer str1,
68                           gconstpointer str2)
69 {
70         if (!str1 || !str2)
71                 return str1 == str2;
72
73         return g_ascii_strcasecmp (str1, str2) == 0;
74 }
75
76 static void
77 certdb_finalize (GObject *object)
78 {
79         CamelCertDB *certdb = CAMEL_CERTDB (object);
80         CamelCertDBPrivate *priv;
81
82         priv = CAMEL_CERTDB_GET_PRIVATE (object);
83
84         if (certdb->flags & CAMEL_CERTDB_DIRTY)
85                 camel_certdb_save (certdb);
86
87         camel_certdb_clear (certdb);
88         g_ptr_array_free (certdb->certs, TRUE);
89         g_hash_table_destroy (certdb->cert_hash);
90
91         g_free (certdb->filename);
92
93         if (certdb->cert_chunks)
94                 camel_memchunk_destroy (certdb->cert_chunks);
95
96         g_mutex_free (priv->db_lock);
97         g_mutex_free (priv->io_lock);
98         g_mutex_free (priv->alloc_lock);
99         g_mutex_free (priv->ref_lock);
100
101         /* Chain up to parent's finalize() method. */
102         G_OBJECT_CLASS (camel_certdb_parent_class)->finalize (object);
103 }
104
105 static void
106 camel_certdb_class_init (CamelCertDBClass *class)
107 {
108         GObjectClass *object_class;
109
110         g_type_class_add_private (class, sizeof (CamelCertDBPrivate));
111
112         object_class = G_OBJECT_CLASS (class);
113         object_class->finalize = certdb_finalize;
114
115         class->header_load = certdb_header_load;
116         class->header_save = certdb_header_save;
117
118         class->cert_new  = certdb_cert_new;
119         class->cert_load = certdb_cert_load;
120         class->cert_save = certdb_cert_save;
121         class->cert_free = certdb_cert_free;
122         class->cert_get_string = cert_get_string;
123         class->cert_set_string = cert_set_string;
124 }
125
126 static void
127 camel_certdb_init (CamelCertDB *certdb)
128 {
129         certdb->priv = CAMEL_CERTDB_GET_PRIVATE (certdb);
130
131         certdb->filename = NULL;
132         certdb->version = CAMEL_CERTDB_VERSION;
133         certdb->saved_certs = 0;
134
135         certdb->cert_size = sizeof (CamelCert);
136
137         certdb->cert_chunks = NULL;
138
139         certdb->certs = g_ptr_array_new ();
140         certdb->cert_hash = g_hash_table_new (g_str_hash, certdb_str_equal_casecmp);
141
142         certdb->priv->db_lock = g_mutex_new ();
143         certdb->priv->io_lock = g_mutex_new ();
144         certdb->priv->alloc_lock = g_mutex_new ();
145         certdb->priv->ref_lock = g_mutex_new ();
146 }
147
148 CamelCertDB *
149 camel_certdb_new (void)
150 {
151         return g_object_new (CAMEL_TYPE_CERTDB, NULL);
152 }
153
154 static CamelCertDB *default_certdb = NULL;
155 static GStaticMutex default_certdb_lock = G_STATIC_MUTEX_INIT;
156
157 void
158 camel_certdb_set_default (CamelCertDB *certdb)
159 {
160         g_static_mutex_lock (&default_certdb_lock);
161
162         if (default_certdb)
163                 g_object_unref (default_certdb);
164
165         if (certdb)
166                 g_object_ref (certdb);
167
168         default_certdb = certdb;
169
170         g_static_mutex_unlock (&default_certdb_lock);
171 }
172
173 CamelCertDB *
174 camel_certdb_get_default (void)
175 {
176         CamelCertDB *certdb;
177
178         g_static_mutex_lock (&default_certdb_lock);
179
180         if (default_certdb)
181                 g_object_ref (default_certdb);
182
183         certdb = default_certdb;
184
185         g_static_mutex_unlock (&default_certdb_lock);
186
187         return certdb;
188 }
189
190 void
191 camel_certdb_set_filename (CamelCertDB *certdb,
192                            const gchar *filename)
193 {
194         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
195         g_return_if_fail (filename != NULL);
196
197         camel_certdb_lock (certdb, CAMEL_CERTDB_DB_LOCK);
198
199         g_free (certdb->filename);
200         certdb->filename = g_strdup (filename);
201
202         camel_certdb_unlock (certdb, CAMEL_CERTDB_DB_LOCK);
203 }
204
205 static gint
206 certdb_header_load (CamelCertDB *certdb,
207                     FILE *istream)
208 {
209         if (camel_file_util_decode_uint32 (istream, &certdb->version) == -1)
210                 return -1;
211         if (camel_file_util_decode_uint32 (istream, &certdb->saved_certs) == -1)
212                 return -1;
213
214         return 0;
215 }
216
217 static CamelCert *
218 certdb_cert_load (CamelCertDB *certdb,
219                   FILE *istream)
220 {
221         CamelCert *cert;
222
223         cert = camel_certdb_cert_new (certdb);
224
225         if (camel_file_util_decode_string (istream, &cert->issuer) == -1)
226                 goto error;
227         if (camel_file_util_decode_string (istream, &cert->subject) == -1)
228                 goto error;
229         if (camel_file_util_decode_string (istream, &cert->hostname) == -1)
230                 goto error;
231         if (camel_file_util_decode_string (istream, &cert->fingerprint) == -1)
232                 goto error;
233         if (camel_file_util_decode_uint32 (istream, &cert->trust) == -1)
234                 goto error;
235
236         /* unset temporary trusts on load */
237         if (cert->trust == CAMEL_CERT_TRUST_TEMPORARY)
238                 cert->trust = CAMEL_CERT_TRUST_UNKNOWN;
239
240         return cert;
241
242  error:
243
244         camel_certdb_cert_unref (certdb, cert);
245
246         return NULL;
247 }
248
249 gint
250 camel_certdb_load (CamelCertDB *certdb)
251 {
252         CamelCertDBClass *class;
253         CamelCert *cert;
254         FILE *in;
255         gint i;
256
257         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
258         g_return_val_if_fail (certdb->filename, -1);
259
260         in = g_fopen (certdb->filename, "rb");
261         if (in == NULL)
262                 return -1;
263
264         class = CAMEL_CERTDB_GET_CLASS (certdb);
265         if (!class->header_load || !class->cert_load) {
266                 fclose (in);
267                 in = NULL;
268         }
269         g_return_val_if_fail (class->header_load != NULL, -1);
270         g_return_val_if_fail (class->cert_load != NULL, -1);
271
272         camel_certdb_lock (certdb, CAMEL_CERTDB_IO_LOCK);
273         if (class->header_load (certdb, in) == -1)
274                 goto error;
275
276         for (i = 0; i < certdb->saved_certs; i++) {
277                 cert = class->cert_load (certdb, in);
278
279                 if (cert == NULL)
280                         goto error;
281
282                 /* NOTE: If we are upgrading from an evolution-data-server version
283                  * prior to the change to look up certs by hostname (bug 606181),
284                  * this "put" will result in duplicate entries for the same
285                  * hostname being dropped.  The change will become permanent on
286                  * disk the next time the certdb is dirtied for some reason and
287                  * has to be saved. */
288                 camel_certdb_put (certdb, cert);
289         }
290
291         camel_certdb_unlock (certdb, CAMEL_CERTDB_IO_LOCK);
292
293         if (fclose (in) != 0)
294                 return -1;
295
296         certdb->flags &= ~CAMEL_CERTDB_DIRTY;
297
298         return 0;
299
300  error:
301
302         g_warning ("Cannot load certificate database: %s", g_strerror (ferror (in)));
303
304         camel_certdb_unlock (certdb, CAMEL_CERTDB_IO_LOCK);
305
306         fclose (in);
307
308         return -1;
309 }
310
311 static gint
312 certdb_header_save (CamelCertDB *certdb,
313                     FILE *ostream)
314 {
315         if (camel_file_util_encode_uint32 (ostream, certdb->version) == -1)
316                 return -1;
317         if (camel_file_util_encode_uint32 (ostream, certdb->saved_certs) == -1)
318                 return -1;
319
320         return 0;
321 }
322
323 static gint
324 certdb_cert_save (CamelCertDB *certdb,
325                   CamelCert *cert,
326                   FILE *ostream)
327 {
328         if (camel_file_util_encode_string (ostream, cert->issuer) == -1)
329                 return -1;
330         if (camel_file_util_encode_string (ostream, cert->subject) == -1)
331                 return -1;
332         if (camel_file_util_encode_string (ostream, cert->hostname) == -1)
333                 return -1;
334         if (camel_file_util_encode_string (ostream, cert->fingerprint) == -1)
335                 return -1;
336         if (camel_file_util_encode_uint32 (ostream, cert->trust) == -1)
337                 return -1;
338
339         return 0;
340 }
341
342 gint
343 camel_certdb_save (CamelCertDB *certdb)
344 {
345         CamelCertDBClass *class;
346         CamelCert *cert;
347         gchar *filename;
348         gint fd, i;
349         FILE *out;
350
351         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), -1);
352         g_return_val_if_fail (certdb->filename, -1);
353
354         /* no change, nothing new to save, simply return success */
355         if ((certdb->flags & CAMEL_CERTDB_DIRTY) == 0)
356                 return 0;
357
358         filename = alloca (strlen (certdb->filename) + 4);
359         sprintf (filename, "%s~", certdb->filename);
360
361         fd = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
362         if (fd == -1)
363                 return -1;
364
365         out = fdopen (fd, "wb");
366         if (out == NULL) {
367                 i = errno;
368                 close (fd);
369                 g_unlink (filename);
370                 errno = i;
371                 return -1;
372         }
373
374         class = CAMEL_CERTDB_GET_CLASS (certdb);
375         if (!class->header_save || !class->cert_save) {
376                 fclose (out);
377                 out = NULL;
378         }
379         g_return_val_if_fail (class->header_save != NULL, -1);
380         g_return_val_if_fail (class->cert_save != NULL, -1);
381
382         camel_certdb_lock (certdb, CAMEL_CERTDB_IO_LOCK);
383
384         certdb->saved_certs = certdb->certs->len;
385         if (class->header_save (certdb, out) == -1)
386                 goto error;
387
388         for (i = 0; i < certdb->saved_certs; i++) {
389                 cert = (CamelCert *) certdb->certs->pdata[i];
390
391                 if (class->cert_save (certdb, cert, out) == -1)
392                         goto error;
393         }
394
395         camel_certdb_unlock (certdb, CAMEL_CERTDB_IO_LOCK);
396
397         if (fflush (out) != 0 || fsync (fileno (out)) == -1) {
398                 i = errno;
399                 fclose (out);
400                 g_unlink (filename);
401                 errno = i;
402                 return -1;
403         }
404
405         if (fclose (out) != 0) {
406                 i = errno;
407                 g_unlink (filename);
408                 errno = i;
409                 return -1;
410         }
411
412         if (g_rename (filename, certdb->filename) == -1) {
413                 i = errno;
414                 g_unlink (filename);
415                 errno = i;
416                 return -1;
417         }
418
419         certdb->flags &= ~CAMEL_CERTDB_DIRTY;
420
421         return 0;
422
423  error:
424
425         g_warning ("Cannot save certificate database: %s", g_strerror (ferror (out)));
426
427         camel_certdb_unlock (certdb, CAMEL_CERTDB_IO_LOCK);
428
429         i = errno;
430         fclose (out);
431         g_unlink (filename);
432         errno = i;
433
434         return -1;
435 }
436
437 void
438 camel_certdb_touch (CamelCertDB *certdb)
439 {
440         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
441
442         certdb->flags |= CAMEL_CERTDB_DIRTY;
443 }
444
445 CamelCert *
446 camel_certdb_get_host (CamelCertDB *certdb,
447                        const gchar *hostname)
448 {
449         CamelCert *cert;
450
451         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
452
453         camel_certdb_lock (certdb, CAMEL_CERTDB_DB_LOCK);
454
455         cert = g_hash_table_lookup (certdb->cert_hash, hostname);
456         if (cert)
457                 camel_certdb_cert_ref (certdb, cert);
458
459         camel_certdb_unlock (certdb, CAMEL_CERTDB_DB_LOCK);
460
461         return cert;
462 }
463
464 void
465 camel_certdb_put (CamelCertDB *certdb,
466                   CamelCert *cert)
467 {
468         CamelCert *old_cert;
469
470         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
471
472         camel_certdb_lock (certdb, CAMEL_CERTDB_DB_LOCK);
473
474         /* Replace an existing entry with the same hostname. */
475         old_cert = g_hash_table_lookup (certdb->cert_hash, cert->hostname);
476         if (old_cert) {
477                 g_hash_table_remove (certdb->cert_hash, cert->hostname);
478                 g_ptr_array_remove (certdb->certs, old_cert);
479                 camel_certdb_cert_unref (certdb, old_cert);
480         }
481
482         camel_certdb_cert_ref (certdb, cert);
483         g_ptr_array_add (certdb->certs, cert);
484         g_hash_table_insert (certdb->cert_hash, cert->hostname, cert);
485
486         certdb->flags |= CAMEL_CERTDB_DIRTY;
487
488         camel_certdb_unlock (certdb, CAMEL_CERTDB_DB_LOCK);
489 }
490
491 void
492 camel_certdb_remove_host (CamelCertDB *certdb,
493                           const gchar *hostname)
494 {
495         CamelCert *cert;
496
497         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
498
499         camel_certdb_lock (certdb, CAMEL_CERTDB_DB_LOCK);
500
501         cert = g_hash_table_lookup (certdb->cert_hash, hostname);
502         if (cert) {
503                 g_hash_table_remove (certdb->cert_hash, hostname);
504                 g_ptr_array_remove (certdb->certs, cert);
505                 camel_certdb_cert_unref (certdb, cert);
506
507                 certdb->flags |= CAMEL_CERTDB_DIRTY;
508         }
509
510         camel_certdb_unlock (certdb, CAMEL_CERTDB_DB_LOCK);
511 }
512
513 static CamelCert *
514 certdb_cert_new (CamelCertDB *certdb)
515 {
516         CamelCert *cert;
517
518         if (certdb->cert_chunks)
519                 cert = camel_memchunk_alloc0 (certdb->cert_chunks);
520         else
521                 cert = g_malloc0 (certdb->cert_size);
522
523         cert->refcount = 1;
524
525         return cert;
526 }
527
528 CamelCert *
529 camel_certdb_cert_new (CamelCertDB *certdb)
530 {
531         CamelCertDBClass *class;
532         CamelCert *cert;
533
534         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
535
536         class = CAMEL_CERTDB_GET_CLASS (certdb);
537         g_return_val_if_fail (class->cert_new != NULL, NULL);
538
539         camel_certdb_lock (certdb, CAMEL_CERTDB_ALLOC_LOCK);
540
541         cert = class->cert_new (certdb);
542
543         camel_certdb_unlock (certdb, CAMEL_CERTDB_ALLOC_LOCK);
544
545         return cert;
546 }
547
548 void
549 camel_certdb_cert_ref (CamelCertDB *certdb,
550                        CamelCert *cert)
551 {
552         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
553         g_return_if_fail (cert != NULL);
554
555         camel_certdb_lock (certdb, CAMEL_CERTDB_REF_LOCK);
556         cert->refcount++;
557         camel_certdb_unlock (certdb, CAMEL_CERTDB_REF_LOCK);
558 }
559
560 static void
561 certdb_cert_free (CamelCertDB *certdb,
562                   CamelCert *cert)
563 {
564         g_free (cert->issuer);
565         g_free (cert->subject);
566         g_free (cert->hostname);
567         g_free (cert->fingerprint);
568         if (cert->rawcert)
569                 g_byte_array_free (cert->rawcert, TRUE);
570 }
571
572 void
573 camel_certdb_cert_unref (CamelCertDB *certdb,
574                          CamelCert *cert)
575 {
576         CamelCertDBClass *class;
577
578         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
579         g_return_if_fail (cert != NULL);
580
581         class = CAMEL_CERTDB_GET_CLASS (certdb);
582         g_return_if_fail (class->cert_free != NULL);
583
584         camel_certdb_lock (certdb, CAMEL_CERTDB_REF_LOCK);
585
586         if (cert->refcount <= 1) {
587                 class->cert_free (certdb, cert);
588                 if (certdb->cert_chunks)
589                         camel_memchunk_free (certdb->cert_chunks, cert);
590                 else
591                         g_free (cert);
592         } else {
593                 cert->refcount--;
594         }
595
596         camel_certdb_unlock (certdb, CAMEL_CERTDB_REF_LOCK);
597 }
598
599 static gboolean
600 cert_remove (gpointer key,
601              gpointer value,
602              gpointer user_data)
603 {
604         return TRUE;
605 }
606
607 void
608 camel_certdb_clear (CamelCertDB *certdb)
609 {
610         CamelCert *cert;
611         gint i;
612
613         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
614
615         camel_certdb_lock (certdb, CAMEL_CERTDB_DB_LOCK);
616
617         g_hash_table_foreach_remove (certdb->cert_hash, cert_remove, NULL);
618         for (i = 0; i < certdb->certs->len; i++) {
619                 cert = (CamelCert *) certdb->certs->pdata[i];
620                 camel_certdb_cert_unref (certdb, cert);
621         }
622
623         certdb->saved_certs = 0;
624         g_ptr_array_set_size (certdb->certs, 0);
625         certdb->flags |= CAMEL_CERTDB_DIRTY;
626
627         camel_certdb_unlock (certdb, CAMEL_CERTDB_DB_LOCK);
628 }
629
630 static const gchar *
631 cert_get_string (CamelCertDB *certdb,
632                  CamelCert *cert,
633                  gint string)
634 {
635         switch (string) {
636         case CAMEL_CERT_STRING_ISSUER:
637                 return cert->issuer;
638         case CAMEL_CERT_STRING_SUBJECT:
639                 return cert->subject;
640         case CAMEL_CERT_STRING_HOSTNAME:
641                 return cert->hostname;
642         case CAMEL_CERT_STRING_FINGERPRINT:
643                 return cert->fingerprint;
644         default:
645                 return NULL;
646         }
647 }
648
649 const gchar *
650 camel_cert_get_string (CamelCertDB *certdb,
651                        CamelCert *cert,
652                        gint string)
653 {
654         CamelCertDBClass *class;
655
656         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), NULL);
657         g_return_val_if_fail (cert != NULL, NULL);
658
659         class = CAMEL_CERTDB_GET_CLASS (certdb);
660         g_return_val_if_fail (class->cert_get_string != NULL, NULL);
661
662         /* FIXME: do locking? */
663
664         return class->cert_get_string (certdb, cert, string);
665 }
666
667 static void
668 cert_set_string (CamelCertDB *certdb,
669                  CamelCert *cert,
670                  gint string,
671                  const gchar *value)
672 {
673         switch (string) {
674         case CAMEL_CERT_STRING_ISSUER:
675                 g_free (cert->issuer);
676                 cert->issuer = g_strdup (value);
677                 break;
678         case CAMEL_CERT_STRING_SUBJECT:
679                 g_free (cert->subject);
680                 cert->subject = g_strdup (value);
681                 break;
682         case CAMEL_CERT_STRING_HOSTNAME:
683                 g_free (cert->hostname);
684                 cert->hostname = g_strdup (value);
685                 break;
686         case CAMEL_CERT_STRING_FINGERPRINT:
687                 g_free (cert->fingerprint);
688                 cert->fingerprint = g_strdup (value);
689                 break;
690         default:
691                 break;
692         }
693 }
694
695 void
696 camel_cert_set_string (CamelCertDB *certdb,
697                        CamelCert *cert,
698                        gint string,
699                        const gchar *value)
700 {
701         CamelCertDBClass *class;
702
703         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
704         g_return_if_fail (cert != NULL);
705
706         class = CAMEL_CERTDB_GET_CLASS (certdb);
707         g_return_if_fail (class->cert_set_string != NULL);
708
709         /* FIXME: do locking? */
710
711         class->cert_set_string (certdb, cert, string, value);
712 }
713
714 CamelCertTrust
715 camel_cert_get_trust (CamelCertDB *certdb,
716                       CamelCert *cert)
717 {
718         g_return_val_if_fail (CAMEL_IS_CERTDB (certdb), CAMEL_CERT_TRUST_UNKNOWN);
719         g_return_val_if_fail (cert != NULL, CAMEL_CERT_TRUST_UNKNOWN);
720
721         return cert->trust;
722 }
723
724 void
725 camel_cert_set_trust (CamelCertDB *certdb,
726                       CamelCert *cert,
727                       CamelCertTrust trust)
728 {
729         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
730         g_return_if_fail (cert != NULL);
731
732         cert->trust = trust;
733 }
734
735 /**
736  * camel_certdb_lock:
737  * @certdb: a #CamelCertDB
738  * @lock: lock type to lock
739  *
740  * Locks @certdb's @lock. Unlock it with camel_certdb_unlock().
741  *
742  * Since: 2.32
743  **/
744 void
745 camel_certdb_lock (CamelCertDB *certdb,
746                    CamelCertDBLock lock)
747 {
748         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
749
750         switch (lock) {
751         case CAMEL_CERTDB_DB_LOCK:
752                 g_mutex_lock (certdb->priv->db_lock);
753                 break;
754         case CAMEL_CERTDB_IO_LOCK:
755                 g_mutex_lock (certdb->priv->io_lock);
756                 break;
757         case CAMEL_CERTDB_ALLOC_LOCK:
758                 g_mutex_lock (certdb->priv->alloc_lock);
759                 break;
760         case CAMEL_CERTDB_REF_LOCK:
761                 g_mutex_lock (certdb->priv->ref_lock);
762                 break;
763         default:
764                 g_return_if_reached ();
765         }
766 }
767
768 /**
769  * camel_certdb_unlock:
770  * @certdb: a #CamelCertDB
771  * @lock: lock type to unlock
772  *
773  * Unlocks @certdb's @lock, previously locked with camel_certdb_lock().
774  *
775  * Since: 2.32
776  **/
777 void
778 camel_certdb_unlock (CamelCertDB *certdb,
779                      CamelCertDBLock lock)
780 {
781         g_return_if_fail (CAMEL_IS_CERTDB (certdb));
782
783         switch (lock) {
784         case CAMEL_CERTDB_DB_LOCK:
785                 g_mutex_unlock (certdb->priv->db_lock);
786                 break;
787         case CAMEL_CERTDB_IO_LOCK:
788                 g_mutex_unlock (certdb->priv->io_lock);
789                 break;
790         case CAMEL_CERTDB_ALLOC_LOCK:
791                 g_mutex_unlock (certdb->priv->alloc_lock);
792                 break;
793         case CAMEL_CERTDB_REF_LOCK:
794                 g_mutex_unlock (certdb->priv->ref_lock);
795                 break;
796         default:
797                 g_return_if_reached ();
798         }
799 }