2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
31 #include "pwmd-error.h"
37 #include "util-misc.h"
38 #include "util-string.h"
54 static pthread_mutex_t cache_mutex
;
55 static struct slist_s
*key_cache
;
56 static struct slist_s
*plaintext_list
;
57 static unsigned char *cache_iv
;
58 static unsigned char *cache_key
;
59 static size_t cache_blocksize
;
60 static size_t cache_keysize
;
61 static struct agent_s
*cache_agent
;
64 extern void log_write (const char *fmt
, ...);
66 static gpg_error_t
clear_once (file_cache_t
* p
, int agent
, int force
);
67 static int remove_entry (const char *);
68 static void free_entry (file_cache_t
* p
, int agent
);
71 get_entry (const char *filename
)
73 int t
= slist_length (key_cache
);
79 for (i
= 0; i
< t
; i
++)
81 file_cache_t
*p
= slist_nth_data (key_cache
, i
);
83 if (!strcmp (p
->filename
, filename
))
91 cache_lock_mutex (void *ctx
, const char *filename
, long lock_timeout
, int add
,
94 MUTEX_LOCK (&cache_mutex
);
96 file_cache_t
*p
= get_entry (filename
);
98 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
102 MUTEX_UNLOCK (&cache_mutex
);
103 MUTEX_TRYLOCK (ctx
, p
->mutex
, rc
, lock_timeout
);
107 rc
= cache_add_file (filename
, NULL
, timeout
);
110 p
= get_entry (filename
);
111 MUTEX_UNLOCK (&cache_mutex
);
113 MUTEX_TRYLOCK (ctx
, p
->mutex
, rc
, lock_timeout
);
117 MUTEX_UNLOCK (&cache_mutex
);
122 MUTEX_UNLOCK (&cache_mutex
);
125 pthread_cleanup_pop (0);
126 return !p
&& !rc
? GPG_ERR_NO_DATA
: rc
;
130 remove_entry (const char *filename
)
132 MUTEX_LOCK (&cache_mutex
);
133 file_cache_t
*p
= get_entry (filename
);
135 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
138 /* Keep a refcount because another client maybe editing this same new
139 * file. The entry needs to be kept in case the other client SAVE's.
146 pthread_cleanup_pop (1);
151 free_cache_data (file_cache_t
*cache
, int force
)
153 gpg_error_t rc
= GPG_ERR_NO_DATA
;
155 struct client_thread_s
*found
= NULL
;
161 MUTEX_LOCK (&cn_mutex
);
162 t
= slist_length (cn_thread_list
);
164 /* Prevent clearing the cache entry when there are any connected clients
165 * using this cache entry to prevent clearing the plaintext which would cause
166 * cache_plaintext_set() to return GPG_ERR_NO_DATA and prevent CoW commands
168 for (i
= 0; i
< t
; i
++)
170 struct client_thread_s
*thd
= slist_nth_data (cn_thread_list
, i
);
175 if (thd
->cl
->filename
&& !strcmp (thd
->cl
->filename
, cache
->filename
)
178 cache
->defer_clear
= 1;
179 MUTEX_UNLOCK (&cn_mutex
);
184 pthread_cleanup_push (release_mutex_cb
, &cn_mutex
);
185 MUTEX_LOCK (&cache_mutex
);
186 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
188 for (i
= 0; i
< t
; i
++)
190 struct client_thread_s
*thd
= slist_nth_data (cn_thread_list
, i
);
195 self
= pthread_equal (pthread_self (), thd
->tid
);
197 if (thd
->cl
->filename
&& !strcmp (thd
->cl
->filename
, cache
->filename
))
205 /* Continue trying to find a client who has the same file open and
206 * also has a lock. */
207 rc
= cache_lock_mutex (thd
->cl
->ctx
, thd
->cl
->filename
, -1, 0, -1);
216 if (self
&& (!rc
|| rc
== GPG_ERR_NO_DATA
) && found
)
217 rc
= cache_lock_mutex (found
->cl
->ctx
, found
->cl
->filename
, -1, 0, -1);
219 if (exiting
|| !rc
|| rc
== GPG_ERR_NO_DATA
)
221 cache_free_data_once (cache
->data
);
223 cache
->defer_clear
= 0;
224 cache
->timeout
= (long)-1;
227 cache_unlock_mutex (found
->cl
->filename
, 0);
233 cache
->defer_clear
= 1;
235 pthread_cleanup_pop (1);
236 pthread_cleanup_pop (1);
241 cache_unlock_mutex (const char *filename
, int remove
)
243 MUTEX_LOCK (&cache_mutex
);
244 file_cache_t
*p
= get_entry (filename
);
246 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
250 MUTEX_UNLOCK (p
->mutex
);
252 remove_entry (filename
);
255 pthread_cleanup_pop (1);
256 return p
? 0 : GPG_ERR_NO_DATA
;
260 test_agent_cache_once (file_cache_t
*p
, const char *grip
)
266 rc
= agent_command (cache_agent
, &line
, NULL
, "KEYINFO --data %s", grip
);
269 char **fields
= str_split (line
, " ", 0);
272 if (*fields
[1] == 'T')
273 rc
= GPG_ERR_NO_DATA
;
275 rc
= isdigit (*fields
[4]) || *fields
[5] == 'C' ? 0 : GPG_ERR_NO_DATA
;
284 /* Test each keygrip in data->(sig)grip for gpg-agent cache status. The file is
285 * considered cached if at least one grip is cached in the agent or one siggrip
286 * is cached in the case of 'sign'.
289 test_agent_cache (file_cache_t
*data
, int sign
)
294 if ((!data
->grip
&& !sign
) || (!data
->siggrip
&& sign
))
295 return GPG_ERR_NO_DATA
;
297 for (p
= data
->grip
; !sign
&& p
&& *p
; p
++)
299 rc
= test_agent_cache_once (data
, *p
);
300 if (!rc
|| rc
!= GPG_ERR_NO_DATA
)
305 rc
= test_agent_cache_once (data
, data
->siggrip
);
311 extract_keygrip_once (struct crypto_s
*crypto
, char **keyids
, int sign
,
319 rc
= crypto_list_keys (crypto
, keyids
, sign
, &result
);
323 for (i
= 0; result
[i
]; i
++)
327 for (s
= result
[i
]->subkeys
; s
; s
= s
->next
)
331 if (sign
&& !s
->can_sign
)
334 for (k
= keyids
; *k
; k
++)
336 if (!strcmp (*k
, s
->keyid
) && s
->keygrip
)
339 size_t len
= strv_length (grips
);
341 tmp
= xrealloc (grips
, len
+2 * sizeof (char *));
349 grips
[len
] = str_dup (s
->keygrip
);
373 crypto_free_key_list (result
);
374 return rc
? rc
: grips
? rc
: GPG_ERR_NO_DATA
;
378 extract_keygrips (file_cache_t
*data
)
381 struct crypto_s
*crypto
;
382 char **grips
= NULL
, **siggrips
= NULL
;
384 if (!data
|| !data
->data
)
387 rc
= crypto_init (&crypto
, NULL
, NULL
, 0, NULL
);
391 pthread_cleanup_push ((void *)crypto_free
, crypto
);
393 if (data
->data
->pubkey
)
394 rc
= extract_keygrip_once (crypto
, data
->data
->pubkey
, 0, &grips
);
396 if (!rc
&& data
->data
->sigkey
)
400 strv_printf (&tmp
, "%s", data
->data
->sigkey
);
401 rc
= extract_keygrip_once (crypto
, tmp
, 1, &siggrips
);
407 strv_free (data
->grip
);
409 xfree (data
->siggrip
);
410 data
->siggrip
= NULL
;
411 if (siggrips
&& *siggrips
)
412 data
->siggrip
= str_dup (*siggrips
);
413 strv_free (siggrips
);
418 strv_free (siggrips
);
421 pthread_cleanup_pop (1);
426 iscached (const char *filename
, int *defer
, int agent
, int sign
)
428 file_cache_t
*p
= get_entry (filename
);
434 return GPG_ERR_NO_DATA
;
437 *defer
= p
->defer_clear
;
443 return GPG_ERR_NO_DATA
;
446 *defer
= p
->defer_clear
;
448 if (!rc
&& (p
->grip
|| p
->siggrip
))
449 rc
= test_agent_cache (p
, sign
);
451 rc
= GPG_ERR_NO_DATA
;
459 MUTEX_LOCK (&cache_mutex
);
460 unsigned total
= 0, i
, n
;
462 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
463 n
= slist_length (key_cache
);
464 for (i
= 0; i
< n
; i
++)
466 file_cache_t
*p
= slist_nth_data (key_cache
, i
);
468 if (!iscached (p
->filename
, NULL
, 0, 0))
472 pthread_cleanup_pop (1);
477 cache_adjust_timeout ()
479 MUTEX_LOCK (&cache_mutex
);
480 int t
= slist_length (key_cache
);
483 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
485 for (i
= 0; i
< t
; i
++)
487 file_cache_t
*p
= slist_nth_data (key_cache
, i
);
492 if (!p
->timeout
|| (p
->defer_clear
&& p
->timeout
!= (long)-1))
494 /* The file associated with this cache entry may be locked by a
495 * client. Defer freeing this cache entry until the next timeout
497 gpg_error_t rc
= clear_once (p
, 1, 0);
499 if (!rc
&& !p
->defer_clear
)
500 send_status_all (STATUS_CACHE
, NULL
);
504 pthread_cleanup_pop (1);
508 set_timeout (const char *filename
, long timeout
, int defer
, int force
)
510 MUTEX_LOCK (&cache_mutex
);
511 file_cache_t
*p
= get_entry (filename
);
514 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
519 if (!p
->defer_clear
&& (p
->timeout
== -1 || force
))
520 p
->timeout
= timeout
;
522 if (!timeout
|| defer
)
524 rc
= clear_once (p
, 1, 0);
526 send_status_all (STATUS_CACHE
, NULL
);
530 rc
= GPG_ERR_NOT_FOUND
;
532 pthread_cleanup_pop (1);
537 cache_set_data (const char *filename
, struct cache_data_s
*data
)
539 MUTEX_LOCK (&cache_mutex
);
540 gpg_error_t rc
= GPG_ERR_NO_DATA
;
541 file_cache_t
*p
= get_entry (filename
);
543 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
547 xfree (data
->filename
);
548 data
->filename
= NULL
;
550 data
->filename
= str_dup (p
->filename
);
553 rc
= set_timeout (filename
, p
->reset
, p
->defer_clear
, 0);
554 if (!rc
&& !p
->reset
)
556 clear_once (p
, 0, 0);
557 send_status_all (STATUS_CACHE
, NULL
);
560 rc
= extract_keygrips (p
);
563 pthread_cleanup_pop (1);
564 return p
&& !rc
? 0 : rc
;
567 struct cache_data_s
*
568 cache_get_data (const char *filename
, int *defer
)
570 MUTEX_LOCK (&cache_mutex
);
571 file_cache_t
*p
= get_entry (filename
);
574 *defer
= p
->defer_clear
;
575 MUTEX_UNLOCK (&cache_mutex
);
576 return p
? p
->data
: NULL
;
580 cache_add_file (const char *filename
, struct cache_data_s
*data
, long timeout
)
582 MUTEX_LOCK (&cache_mutex
);
583 file_cache_t
*p
= get_entry (filename
);
587 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
593 char *str
= p
->filename
? str_dup (p
->filename
) : NULL
;
595 if (p
->filename
&& !str
)
599 xfree (data
->filename
);
600 data
->filename
= str
;
608 rc
= set_timeout (filename
, timeout
, p
->defer_clear
, 0);
613 p
= xcalloc (1, sizeof (file_cache_t
));
616 p
->mutex
= (pthread_mutex_t
*) xmalloc (sizeof (pthread_mutex_t
));
619 pthread_mutexattr_t attr
;
620 pthread_mutexattr_init (&attr
);
621 pthread_mutexattr_settype (&attr
, PTHREAD_MUTEX_RECURSIVE
);
622 pthread_mutex_init (p
->mutex
, &attr
);
623 pthread_mutexattr_destroy (&attr
);
624 p
->filename
= str_dup (filename
);
628 xfree (data
->filename
);
629 data
->filename
= NULL
;
630 data
->filename
= str_dup (p
->filename
);
635 new = slist_append (key_cache
, p
);
639 rc
= cache_set_timeout(filename
, timeout
);
643 pthread_mutex_destroy (p
->mutex
);
663 rc
= extract_keygrips (p
);
665 pthread_cleanup_pop (1);
668 send_status_all (STATUS_CACHE
, NULL
);
674 cache_clear_agent_keys (const char *filename
, int decrypt
, int sign
)
676 MUTEX_LOCK (&cache_mutex
);
679 file_cache_t
*p
= get_entry (filename
);
681 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
685 for (key
= p
->grip
; decrypt
&& key
&& *key
; key
++)
687 rc
= agent_command (cache_agent
, NULL
, NULL
,
688 "CLEAR_PASSPHRASE --mode=normal %s", *key
);
693 if (p
->siggrip
&& sign
)
695 rc
= agent_command (cache_agent
, NULL
, NULL
,
696 "CLEAR_PASSPHRASE --mode=normal %s", p
->siggrip
);
702 rc
= GPG_ERR_NOT_FOUND
;
704 pthread_cleanup_pop (1);
709 clear_once (file_cache_t
*p
, int agent
, int force
)
711 gpg_error_t rc
= 0, trc
;
714 rc
= cache_clear_agent_keys (p
->filename
, 1, 1);
716 trc
= free_cache_data (p
, force
);
717 return rc
? rc
: trc
;
721 free_entry (file_cache_t
*p
, int agent
)
728 rc
= clear_once (p
, agent
, 0);
730 log_write ("%s(): %s", __FUNCTION__
, pwmd_strerror (rc
));
734 pthread_mutex_destroy (p
->mutex
);
741 key_cache
= slist_remove (key_cache
, p
);
746 cache_clear (struct client_s
*client
, const char *filename
, int agent
,
750 gpg_error_t rc
= 0, all_rc
= 0;
753 MUTEX_LOCK (&cache_mutex
);
754 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
758 p
= get_entry (filename
);
761 rc
= clear_once (p
, agent
, force
);
763 log_write ("%s(): %s", __FUNCTION__
, pwmd_strerror (rc
));
768 t
= slist_length (key_cache
);
769 for (i
= 0; i
< t
; i
++)
771 p
= slist_nth_data (key_cache
, i
);
775 assuan_peercred_t peer
;
776 int n
= client
->no_access_param
;
778 client
->no_access_param
= 1;
779 rc
= do_validate_peer (client
->ctx
, p
->filename
, &peer
);
780 client
->no_access_param
= n
;
781 if (rc
== GPG_ERR_FORBIDDEN
)
782 rc
= peer_is_invoker (client
);
786 all_rc
= !all_rc
? rc
: all_rc
;
791 clear_once (p
, agent
, 0);
795 pthread_cleanup_pop (1);
796 return filename
? rc
: all_rc
;
800 cache_iscached (const char *filename
, int *defer
, int agent
, int sign
)
805 return GPG_ERR_INV_PARAMETER
;
807 MUTEX_LOCK (&cache_mutex
);
808 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
809 rc
= iscached (filename
, defer
, agent
, sign
);
811 /* Test if the data file disappeared from the filesystem. */
812 if ((!rc
|| gpg_err_code (rc
) == GPG_ERR_NO_DATA
)
813 && access (filename
, R_OK
) == -1)
815 rc
= gpg_error_from_errno (errno
);
816 if (gpg_err_code (rc
) == GPG_ERR_ENOENT
)
818 /* Fixes clearing the cache entry that was created during OPEN when
819 * SAVE'ing a new file. */
820 if ((defer
&& *defer
== 1) || !defer
)
822 rc
= cache_defer_clear (filename
);
831 pthread_cleanup_pop (1);
836 cache_defer_clear (const char *filename
)
838 MUTEX_LOCK (&cache_mutex
);
839 file_cache_t
*p
= get_entry (filename
);
843 rc
= GPG_ERR_NOT_FOUND
;
847 MUTEX_UNLOCK (&cache_mutex
);
852 cache_set_timeout (const char *filename
, long timeout
)
854 return set_timeout (filename
, timeout
, 0, 1);
861 MUTEX_LOCK (&cache_mutex
);
862 int i
, t
= slist_length (key_cache
);
864 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
865 for (i
= 0; i
< t
; i
++)
867 file_cache_t
*p
= slist_nth_data (key_cache
, i
);
870 t
= slist_length (key_cache
);
874 gcry_free (cache_key
);
878 agent_free (cache_agent
);
880 pthread_cleanup_pop (1);
881 pthread_mutex_destroy (&cache_mutex
);
887 pthread_mutexattr_t attr
;
889 pthread_mutexattr_init (&attr
);
890 pthread_mutexattr_settype (&attr
, PTHREAD_MUTEX_RECURSIVE
);
891 pthread_mutex_init (&cache_mutex
, &attr
);
892 pthread_mutexattr_destroy (&attr
);
900 rc
= agent_init (&cache_agent
);
909 rc
= gcry_cipher_algo_info (GCRY_CIPHER_AES
, GCRYCTL_GET_BLKLEN
, NULL
,
914 rc
= gcry_cipher_algo_info (GCRY_CIPHER_AES
, GCRYCTL_GET_KEYLEN
, NULL
,
919 cache_key
= gcry_malloc (cache_keysize
);
921 return GPG_ERR_ENOMEM
;
923 cache_iv
= xmalloc (cache_blocksize
);
926 gcry_free (cache_key
);
928 return GPG_ERR_ENOMEM
;
931 gcry_create_nonce (cache_key
, cache_keysize
);
932 gcry_create_nonce (cache_iv
, cache_blocksize
);
943 MUTEX_LOCK (&cache_mutex
);
949 MUTEX_UNLOCK (&cache_mutex
);
953 update_plaintext_pointer (xmlDocPtr plaintext
)
958 t
= slist_length (key_cache
);
959 for (i
= 0; i
< t
; i
++)
961 file_cache_t
*p
= slist_nth_data (key_cache
, i
);
963 if (p
->data
&& p
->data
->plaintext
== plaintext
)
964 p
->data
->plaintext
= NULL
;
969 cache_free_data_once (struct cache_data_s
*data
)
974 xfree (data
->filename
);
975 strv_free (data
->pubkey
);
976 xfree (data
->sigkey
);
983 release_cipher (void *arg
)
985 gcry_cipher_close ((gcry_cipher_hd_t
) arg
);
989 cache_encrypt (struct crypto_s
*crypto
)
993 size_t len
= crypto
->plaintext_size
;
995 rc
= gcry_cipher_open (&h
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
, 0);
999 if (len
% cache_blocksize
)
1003 len
+= cache_blocksize
- (len
% cache_blocksize
);
1004 p
= xrealloc (crypto
->plaintext
, len
* sizeof (unsigned char));
1007 gcry_cipher_close (h
);
1008 return GPG_ERR_ENOMEM
;
1011 crypto
->plaintext
= p
;
1012 memset (&crypto
->plaintext
[crypto
->plaintext_size
], 0,
1013 len
- crypto
->plaintext_size
);
1016 pthread_cleanup_push (release_cipher
, h
);
1017 rc
= gcry_cipher_setiv (h
, cache_iv
, cache_blocksize
);
1020 rc
= gcry_cipher_setkey (h
, cache_key
, cache_keysize
);
1023 unsigned char *buf
= xmalloc (len
);
1025 pthread_cleanup_push (xfree
, buf
);
1028 rc
= GPG_ERR_ENOMEM
;
1032 rc
= gcry_cipher_encrypt (h
, buf
, len
, crypto
->plaintext
, len
);
1035 xfree (crypto
->plaintext
);
1036 crypto
->plaintext
= buf
;
1037 crypto
->plaintext_size
= len
;
1041 pthread_cleanup_pop (rc
!= 0);
1045 pthread_cleanup_pop (1);
1050 cache_decrypt (struct crypto_s
*crypto
)
1052 gcry_cipher_hd_t h
= NULL
;
1055 rc
= gcry_cipher_open (&h
, GCRY_CIPHER_AES
, GCRY_CIPHER_MODE_CBC
, 0);
1060 rc
= gcry_cipher_setiv (h
, cache_iv
, cache_blocksize
);
1063 rc
= gcry_cipher_setkey (h
, cache_key
, cache_keysize
);
1065 pthread_cleanup_push (release_cipher
, h
);
1069 rc
= gcry_cipher_decrypt (h
, crypto
->plaintext
, crypto
->plaintext_size
,
1071 if (rc
|| strncmp ((char *)crypto
->plaintext
, "<?xml ", 6))
1074 rc
= GPG_ERR_BAD_DATA
;
1078 pthread_cleanup_pop (1);
1087 MUTEX_LOCK (&cache_mutex
);
1088 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
1089 rc
= agent_kill_scd (cache_agent
);
1090 pthread_cleanup_pop (1);
1095 cache_agent_command (const char *cmd
)
1099 MUTEX_LOCK (&cache_mutex
);
1100 rc
= agent_command (cache_agent
, NULL
, NULL
, "%s", cmd
);
1101 MUTEX_UNLOCK (&cache_mutex
);
1106 cache_release_mutex ()
1108 MUTEX_UNLOCK (&cache_mutex
);
1112 plaintext_get (struct cache_data_s
*data
, xmlDocPtr
*r_doc
)
1115 unsigned t
= slist_length (plaintext_list
);
1117 assert (r_doc
!= NULL
);
1119 for (i
= 0; i
< t
; i
++)
1121 struct plaintext_s
*p
= slist_nth_data (plaintext_list
, i
);
1123 if (!strcmp (p
->filename
, data
->filename
) && !p
->modified
)
1125 *r_doc
= p
->plaintext
;
1131 return GPG_ERR_NO_DATA
;
1135 cache_plaintext_get (const char *filename
, xmlDocPtr
*r_doc
)
1140 MUTEX_LOCK (&cache_mutex
);
1141 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
1143 p
= get_entry (filename
);
1145 rc
= plaintext_get (p
->data
, r_doc
);
1147 rc
= GPG_ERR_NO_DATA
;
1149 pthread_cleanup_pop (1);
1154 release_plaintext (xmlDocPtr
*plaintext
)
1160 return GPG_ERR_NO_DATA
;
1162 t
= slist_length (plaintext_list
);
1163 for (i
= 0; i
< t
; i
++)
1165 struct plaintext_s
*p
= slist_nth_data (plaintext_list
, i
);
1167 if (p
->plaintext
== *plaintext
)
1169 assert (p
->refcount
> 0);
1170 if (--p
->refcount
== 0)
1172 xmlFreeDoc (p
->plaintext
);
1173 xfree (p
->filename
);
1174 plaintext_list
= slist_remove (plaintext_list
, p
);
1176 update_plaintext_pointer (*plaintext
);
1184 return GPG_ERR_NO_DATA
;
1188 cache_plaintext_release (xmlDocPtr
*plaintext
)
1192 MUTEX_LOCK (&cache_mutex
);
1193 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
1194 rc
= release_plaintext (plaintext
);
1195 pthread_cleanup_pop (1);
1200 cache_plaintext_set (const char *filename
, xmlDocPtr doc
, int modified
)
1205 MUTEX_LOCK (&cache_mutex
);
1206 pthread_cleanup_push (release_mutex_cb
, &cache_mutex
);
1208 p
= get_entry (filename
);
1211 struct plaintext_s
*s
= xcalloc (1, sizeof (struct plaintext_s
));
1215 s
->filename
= str_dup (p
->data
->filename
);
1220 l
= slist_append (plaintext_list
, s
);
1224 s
->plaintext
= p
->data
->plaintext
= doc
;
1225 s
->modified
= modified
;
1230 xfree (s
->filename
);
1231 rc
= GPG_ERR_ENOMEM
;
1235 rc
= GPG_ERR_ENOMEM
;
1241 rc
= GPG_ERR_ENOMEM
;
1244 rc
= GPG_ERR_NO_DATA
;
1246 pthread_cleanup_pop (1);