1 /* kbnode.c - keyblock node utility functions
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3 * 2005 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG 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 General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
32 #define USE_UNUSED_NODES 1
34 static KBNODE unused_nodes
;
43 unused_nodes
= n
->next
;
45 n
= xmalloc( sizeof *n
);
59 n
->next
= unused_nodes
;
70 new_kbnode( PACKET
*pkt
)
72 KBNODE n
= alloc_node();
79 clone_kbnode( KBNODE node
)
81 KBNODE n
= alloc_node();
84 n
->private_flag
= node
->private_flag
| 2; /* mark cloned */
90 release_kbnode( KBNODE n
)
96 if( !is_cloned_kbnode(n
) ) {
97 free_packet( n
->pkt
);
108 * Note: This only works with walk_kbnode!!
111 delete_kbnode( KBNODE node
)
113 node
->private_flag
|= 1;
117 * Append NODE to ROOT. ROOT must exist!
120 add_kbnode( KBNODE root
, KBNODE node
)
124 for(n1
=root
; n1
->next
; n1
= n1
->next
)
130 * Insert NODE into the list after root but before a packet which is not of
132 * (only if PKTTYPE != 0)
135 insert_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
138 node
->next
= root
->next
;
144 for(n1
=root
; n1
->next
; n1
= n1
->next
)
145 if( pkttype
!= n1
->next
->pkt
->pkttype
) {
146 node
->next
= n1
->next
;
150 /* no such packet, append */
158 * Find the previous node (if PKTTYPE = 0) or the previous node
159 * with pkttype PKTTYPE in the list starting with ROOT of NODE.
162 find_prev_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
166 for (n1
=NULL
; root
&& root
!= node
; root
= root
->next
) {
167 if (!pkttype
||root
->pkt
->pkttype
== pkttype
)
174 * Ditto, but find the next packet. The behaviour is trivial if
175 * PKTTYPE is 0 but if it is specified, the next node with a packet
176 * of this type is returned. The function has some knowledge about
177 * the valid ordering of packets: e.g. if the next signature packet
178 * is requested, the function will not return one if it encounters
182 find_next_kbnode( KBNODE node
, int pkttype
)
184 for( node
=node
->next
; node
; node
= node
->next
) {
187 else if( pkttype
== PKT_USER_ID
188 && ( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
189 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
191 else if( pkttype
== PKT_SIGNATURE
192 && ( node
->pkt
->pkttype
== PKT_USER_ID
193 || node
->pkt
->pkttype
== PKT_PUBLIC_KEY
194 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
196 else if( node
->pkt
->pkttype
== pkttype
)
204 find_kbnode( KBNODE node
, int pkttype
)
206 for( ; node
; node
= node
->next
) {
207 if( node
->pkt
->pkttype
== pkttype
)
216 * Walk through a list of kbnodes. This function returns
217 * the next kbnode for each call; before using the function the first
218 * time, the caller must set CONTEXT to NULL (This has simply the effect
219 * to start with ROOT).
222 walk_kbnode( KBNODE root
, KBNODE
*context
, int all
)
232 n
= (*context
)->next
;
235 } while( !all
&& n
&& is_deleted_kbnode(n
) );
241 clear_kbnode_flags( KBNODE n
)
243 for( ; n
; n
= n
->next
) {
250 * Commit changes made to the kblist at ROOT. Note that ROOT my change,
251 * and it is therefore passed by reference.
252 * The function has the effect of removing all nodes marked as deleted.
253 * returns true if any node has been changed
256 commit_kbnode( KBNODE
*root
)
261 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
262 if( is_deleted_kbnode(n
) ) {
264 *root
= nl
= n
->next
;
267 if( !is_cloned_kbnode(n
) ) {
268 free_packet( n
->pkt
);
281 remove_kbnode( KBNODE
*root
, KBNODE node
)
285 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
288 *root
= nl
= n
->next
;
291 if( !is_cloned_kbnode(n
) ) {
292 free_packet( n
->pkt
);
304 * Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
307 move_kbnode( KBNODE
*root
, KBNODE node
, KBNODE where
)
311 if( !root
|| !*root
|| !node
)
312 return; /* sanity check */
313 for( prev
= *root
; prev
&& prev
->next
!= node
; prev
= prev
->next
)
316 return; /* node is not in the list */
318 if( !where
) { /* move node before root */
319 if( node
== *root
) /* move to itself */
321 prev
->next
= node
->next
;
326 /* move it after where */
330 node
->next
= where
->next
;
339 dump_kbnode( KBNODE node
)
341 for(; node
; node
= node
->next
) {
343 switch( node
->pkt
->pkttype
) {
344 case 0: s
="empty"; break;
345 case PKT_PUBLIC_KEY
: s
="public-key"; break;
346 case PKT_SECRET_KEY
: s
="secret-key"; break;
347 case PKT_SECRET_SUBKEY
: s
= "secret-subkey"; break;
348 case PKT_PUBKEY_ENC
: s
="public-enc"; break;
349 case PKT_SIGNATURE
: s
="signature"; break;
350 case PKT_ONEPASS_SIG
: s
="onepass-sig"; break;
351 case PKT_USER_ID
: s
="user-id"; break;
352 case PKT_PUBLIC_SUBKEY
: s
="public-subkey"; break;
353 case PKT_COMMENT
: s
="comment"; break;
354 case PKT_RING_TRUST
: s
="trust"; break;
355 case PKT_PLAINTEXT
: s
="plaintext"; break;
356 case PKT_COMPRESSED
: s
="compressed"; break;
357 case PKT_ENCRYPTED
: s
="encrypted"; break;
358 case PKT_GPG_CONTROL
: s
="gpg-control"; break;
359 default: s
="unknown"; break;
361 fprintf(stderr
, "node %p %02x/%02x type=%s",
362 node
, node
->flag
, node
->private_flag
, s
);
363 if( node
->pkt
->pkttype
== PKT_USER_ID
) {
364 PKT_user_id
*uid
= node
->pkt
->pkt
.user_id
;
365 fputs(" \"", stderr
);
366 print_string( stderr
, uid
->name
, uid
->len
, 0 );
367 fprintf (stderr
, "\" %c%c%c%c\n",
368 uid
->is_expired
? 'e':'.',
369 uid
->is_revoked
? 'r':'.',
370 uid
->created
? 'v':'.',
371 uid
->is_primary
? 'p':'.' );
373 else if( node
->pkt
->pkttype
== PKT_SIGNATURE
) {
374 fprintf(stderr
, " class=%02x keyid=%08lX ts=%lu\n",
375 node
->pkt
->pkt
.signature
->sig_class
,
376 (ulong
)node
->pkt
->pkt
.signature
->keyid
[1],
377 (ulong
)node
->pkt
->pkt
.signature
->timestamp
);
379 else if( node
->pkt
->pkttype
== PKT_GPG_CONTROL
) {
380 fprintf(stderr
, " ctrl=%d len=%u\n",
381 node
->pkt
->pkt
.gpg_control
->control
,
382 (unsigned int)node
->pkt
->pkt
.gpg_control
->datalen
);
384 else if( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
385 || node
->pkt
->pkttype
== PKT_PUBLIC_SUBKEY
) {
386 PKT_public_key
*pk
= node
->pkt
->pkt
.public_key
;
387 fprintf(stderr
, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
388 (ulong
)keyid_from_pk( pk
, NULL
),
389 pk
->pubkey_algo
, pk
->pubkey_usage
,
390 pk
->has_expired
? 'e':'.',
391 pk
->is_revoked
? 'r':'.',
392 pk
->is_valid
? 'v':'.',
393 pk
->mdc_feature
? 'm':'.');