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 2 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
34 #define USE_UNUSED_NODES 1
36 static KBNODE unused_nodes
;
45 unused_nodes
= n
->next
;
47 n
= xmalloc( sizeof *n
);
61 n
->next
= unused_nodes
;
72 new_kbnode( PACKET
*pkt
)
74 KBNODE n
= alloc_node();
81 clone_kbnode( KBNODE node
)
83 KBNODE n
= alloc_node();
86 n
->private_flag
= node
->private_flag
| 2; /* mark cloned */
92 release_kbnode( KBNODE n
)
98 if( !is_cloned_kbnode(n
) ) {
99 free_packet( n
->pkt
);
110 * Note: This only works with walk_kbnode!!
113 delete_kbnode( KBNODE node
)
115 node
->private_flag
|= 1;
119 * Append NODE to ROOT. ROOT must exist!
122 add_kbnode( KBNODE root
, KBNODE node
)
126 for(n1
=root
; n1
->next
; n1
= n1
->next
)
132 * Insert NODE into the list after root but before a packet which is not of
134 * (only if PKTTYPE != 0)
137 insert_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
140 node
->next
= root
->next
;
146 for(n1
=root
; n1
->next
; n1
= n1
->next
)
147 if( pkttype
!= n1
->next
->pkt
->pkttype
) {
148 node
->next
= n1
->next
;
152 /* no such packet, append */
160 * Find the previous node (if PKTTYPE = 0) or the previous node
161 * with pkttype PKTTYPE in the list starting with ROOT of NODE.
164 find_prev_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
168 for (n1
=NULL
; root
&& root
!= node
; root
= root
->next
) {
169 if (!pkttype
||root
->pkt
->pkttype
== pkttype
)
176 * Ditto, but find the next packet. The behaviour is trivial if
177 * PKTTYPE is 0 but if it is specified, the next node with a packet
178 * of this type is returned. The function has some knowledge about
179 * the valid ordering of packets: e.g. if the next signature packet
180 * is requested, the function will not return one if it encounters
184 find_next_kbnode( KBNODE node
, int pkttype
)
186 for( node
=node
->next
; node
; node
= node
->next
) {
189 else if( pkttype
== PKT_USER_ID
190 && ( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
191 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
193 else if( pkttype
== PKT_SIGNATURE
194 && ( node
->pkt
->pkttype
== PKT_USER_ID
195 || node
->pkt
->pkttype
== PKT_PUBLIC_KEY
196 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
198 else if( node
->pkt
->pkttype
== pkttype
)
206 find_kbnode( KBNODE node
, int pkttype
)
208 for( ; node
; node
= node
->next
) {
209 if( node
->pkt
->pkttype
== pkttype
)
218 * Walk through a list of kbnodes. This function returns
219 * the next kbnode for each call; before using the function the first
220 * time, the caller must set CONTEXT to NULL (This has simply the effect
221 * to start with ROOT).
224 walk_kbnode( KBNODE root
, KBNODE
*context
, int all
)
234 n
= (*context
)->next
;
237 } while( !all
&& n
&& is_deleted_kbnode(n
) );
243 clear_kbnode_flags( KBNODE n
)
245 for( ; n
; n
= n
->next
) {
252 * Commit changes made to the kblist at ROOT. Note that ROOT my change,
253 * and it is therefore passed by reference.
254 * The function has the effect of removing all nodes marked as deleted.
255 * returns true if any node has been changed
258 commit_kbnode( KBNODE
*root
)
263 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
264 if( is_deleted_kbnode(n
) ) {
266 *root
= nl
= n
->next
;
269 if( !is_cloned_kbnode(n
) ) {
270 free_packet( n
->pkt
);
283 remove_kbnode( KBNODE
*root
, KBNODE node
)
287 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
290 *root
= nl
= n
->next
;
293 if( !is_cloned_kbnode(n
) ) {
294 free_packet( n
->pkt
);
306 * Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
309 move_kbnode( KBNODE
*root
, KBNODE node
, KBNODE where
)
313 if( !root
|| !*root
|| !node
)
314 return; /* sanity check */
315 for( prev
= *root
; prev
&& prev
->next
!= node
; prev
= prev
->next
)
318 return; /* node is not in the list */
320 if( !where
) { /* move node before root */
321 if( node
== *root
) /* move to itself */
323 prev
->next
= node
->next
;
328 /* move it after where */
332 node
->next
= where
->next
;
341 dump_kbnode( KBNODE node
)
343 for(; node
; node
= node
->next
) {
345 switch( node
->pkt
->pkttype
) {
346 case 0: s
="empty"; break;
347 case PKT_PUBLIC_KEY
: s
="public-key"; break;
348 case PKT_SECRET_KEY
: s
="secret-key"; break;
349 case PKT_SECRET_SUBKEY
: s
= "secret-subkey"; break;
350 case PKT_PUBKEY_ENC
: s
="public-enc"; break;
351 case PKT_SIGNATURE
: s
="signature"; break;
352 case PKT_ONEPASS_SIG
: s
="onepass-sig"; break;
353 case PKT_USER_ID
: s
="user-id"; break;
354 case PKT_PUBLIC_SUBKEY
: s
="public-subkey"; break;
355 case PKT_COMMENT
: s
="comment"; break;
356 case PKT_RING_TRUST
: s
="trust"; break;
357 case PKT_PLAINTEXT
: s
="plaintext"; break;
358 case PKT_COMPRESSED
: s
="compressed"; break;
359 case PKT_ENCRYPTED
: s
="encrypted"; break;
360 case PKT_GPG_CONTROL
: s
="gpg-control"; break;
361 default: s
="unknown"; break;
363 fprintf(stderr
, "node %p %02x/%02x type=%s",
364 node
, node
->flag
, node
->private_flag
, s
);
365 if( node
->pkt
->pkttype
== PKT_USER_ID
) {
366 PKT_user_id
*uid
= node
->pkt
->pkt
.user_id
;
367 fputs(" \"", stderr
);
368 print_string( stderr
, uid
->name
, uid
->len
, 0 );
369 fprintf (stderr
, "\" %c%c%c%c\n",
370 uid
->is_expired
? 'e':'.',
371 uid
->is_revoked
? 'r':'.',
372 uid
->created
? 'v':'.',
373 uid
->is_primary
? 'p':'.' );
375 else if( node
->pkt
->pkttype
== PKT_SIGNATURE
) {
376 fprintf(stderr
, " class=%02x keyid=%08lX ts=%lu\n",
377 node
->pkt
->pkt
.signature
->sig_class
,
378 (ulong
)node
->pkt
->pkt
.signature
->keyid
[1],
379 (ulong
)node
->pkt
->pkt
.signature
->timestamp
);
381 else if( node
->pkt
->pkttype
== PKT_GPG_CONTROL
) {
382 fprintf(stderr
, " ctrl=%d len=%u\n",
383 node
->pkt
->pkt
.gpg_control
->control
,
384 (unsigned int)node
->pkt
->pkt
.gpg_control
->datalen
);
386 else if( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
387 || node
->pkt
->pkttype
== PKT_PUBLIC_SUBKEY
) {
388 PKT_public_key
*pk
= node
->pkt
->pkt
.public_key
;
389 fprintf(stderr
, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
390 (ulong
)keyid_from_pk( pk
, NULL
),
391 pk
->pubkey_algo
, pk
->pubkey_usage
,
392 pk
->has_expired
? 'e':'.',
393 pk
->is_revoked
? 'r':'.',
394 pk
->is_valid
? 'v':'.',
395 pk
->mdc_feature
? 'm':'.');