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,
33 #define USE_UNUSED_NODES 1
35 static KBNODE unused_nodes
;
44 unused_nodes
= n
->next
;
46 n
= xmalloc( sizeof *n
);
60 n
->next
= unused_nodes
;
71 new_kbnode( PACKET
*pkt
)
73 KBNODE n
= alloc_node();
80 clone_kbnode( KBNODE node
)
82 KBNODE n
= alloc_node();
85 n
->private_flag
= node
->private_flag
| 2; /* mark cloned */
91 release_kbnode( KBNODE n
)
97 if( !is_cloned_kbnode(n
) ) {
98 free_packet( n
->pkt
);
109 * Note: This only works with walk_kbnode!!
112 delete_kbnode( KBNODE node
)
114 node
->private_flag
|= 1;
118 * Append NODE to ROOT. ROOT must exist!
121 add_kbnode( KBNODE root
, KBNODE node
)
125 for(n1
=root
; n1
->next
; n1
= n1
->next
)
131 * Insert NODE into the list after root but before a packet which is not of
133 * (only if PKTTYPE != 0)
136 insert_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
139 node
->next
= root
->next
;
145 for(n1
=root
; n1
->next
; n1
= n1
->next
)
146 if( pkttype
!= n1
->next
->pkt
->pkttype
) {
147 node
->next
= n1
->next
;
151 /* no such packet, append */
159 * Find the previous node (if PKTTYPE = 0) or the previous node
160 * with pkttype PKTTYPE in the list starting with ROOT of NODE.
163 find_prev_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
167 for (n1
=NULL
; root
&& root
!= node
; root
= root
->next
) {
168 if (!pkttype
||root
->pkt
->pkttype
== pkttype
)
175 * Ditto, but find the next packet. The behaviour is trivial if
176 * PKTTYPE is 0 but if it is specified, the next node with a packet
177 * of this type is returned. The function has some knowledge about
178 * the valid ordering of packets: e.g. if the next signature packet
179 * is requested, the function will not return one if it encounters
183 find_next_kbnode( KBNODE node
, int pkttype
)
185 for( node
=node
->next
; node
; node
= node
->next
) {
188 else if( pkttype
== PKT_USER_ID
189 && ( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
190 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
192 else if( pkttype
== PKT_SIGNATURE
193 && ( node
->pkt
->pkttype
== PKT_USER_ID
194 || node
->pkt
->pkttype
== PKT_PUBLIC_KEY
195 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
197 else if( node
->pkt
->pkttype
== pkttype
)
205 find_kbnode( KBNODE node
, int pkttype
)
207 for( ; node
; node
= node
->next
) {
208 if( node
->pkt
->pkttype
== pkttype
)
217 * Walk through a list of kbnodes. This function returns
218 * the next kbnode for each call; before using the function the first
219 * time, the caller must set CONTEXT to NULL (This has simply the effect
220 * to start with ROOT).
223 walk_kbnode( KBNODE root
, KBNODE
*context
, int all
)
233 n
= (*context
)->next
;
236 } while( !all
&& n
&& is_deleted_kbnode(n
) );
242 clear_kbnode_flags( KBNODE n
)
244 for( ; n
; n
= n
->next
) {
251 * Commit changes made to the kblist at ROOT. Note that ROOT my change,
252 * and it is therefore passed by reference.
253 * The function has the effect of removing all nodes marked as deleted.
254 * returns true if any node has been changed
257 commit_kbnode( KBNODE
*root
)
262 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
263 if( is_deleted_kbnode(n
) ) {
265 *root
= nl
= n
->next
;
268 if( !is_cloned_kbnode(n
) ) {
269 free_packet( n
->pkt
);
282 remove_kbnode( KBNODE
*root
, KBNODE node
)
286 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
289 *root
= nl
= n
->next
;
292 if( !is_cloned_kbnode(n
) ) {
293 free_packet( n
->pkt
);
305 * Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
308 move_kbnode( KBNODE
*root
, KBNODE node
, KBNODE where
)
312 if( !root
|| !*root
|| !node
)
313 return; /* sanity check */
314 for( prev
= *root
; prev
&& prev
->next
!= node
; prev
= prev
->next
)
317 return; /* node is not in the list */
319 if( !where
) { /* move node before root */
320 if( node
== *root
) /* move to itself */
322 prev
->next
= node
->next
;
327 /* move it after where */
331 node
->next
= where
->next
;
340 dump_kbnode( KBNODE node
)
342 for(; node
; node
= node
->next
) {
344 switch( node
->pkt
->pkttype
) {
345 case 0: s
="empty"; break;
346 case PKT_PUBLIC_KEY
: s
="public-key"; break;
347 case PKT_SECRET_KEY
: s
="secret-key"; break;
348 case PKT_SECRET_SUBKEY
: s
= "secret-subkey"; break;
349 case PKT_PUBKEY_ENC
: s
="public-enc"; break;
350 case PKT_SIGNATURE
: s
="signature"; break;
351 case PKT_ONEPASS_SIG
: s
="onepass-sig"; break;
352 case PKT_USER_ID
: s
="user-id"; break;
353 case PKT_PUBLIC_SUBKEY
: s
="public-subkey"; break;
354 case PKT_COMMENT
: s
="comment"; break;
355 case PKT_RING_TRUST
: s
="trust"; break;
356 case PKT_PLAINTEXT
: s
="plaintext"; break;
357 case PKT_COMPRESSED
: s
="compressed"; break;
358 case PKT_ENCRYPTED
: s
="encrypted"; break;
359 case PKT_GPG_CONTROL
: s
="gpg-control"; break;
360 default: s
="unknown"; break;
362 fprintf(stderr
, "node %p %02x/%02x type=%s",
363 node
, node
->flag
, node
->private_flag
, s
);
364 if( node
->pkt
->pkttype
== PKT_USER_ID
) {
365 PKT_user_id
*uid
= node
->pkt
->pkt
.user_id
;
366 fputs(" \"", stderr
);
367 print_string( stderr
, uid
->name
, uid
->len
, 0 );
368 fprintf (stderr
, "\" %c%c%c%c\n",
369 uid
->is_expired
? 'e':'.',
370 uid
->is_revoked
? 'r':'.',
371 uid
->created
? 'v':'.',
372 uid
->is_primary
? 'p':'.' );
374 else if( node
->pkt
->pkttype
== PKT_SIGNATURE
) {
375 fprintf(stderr
, " class=%02x keyid=%08lX ts=%lu\n",
376 node
->pkt
->pkt
.signature
->sig_class
,
377 (ulong
)node
->pkt
->pkt
.signature
->keyid
[1],
378 (ulong
)node
->pkt
->pkt
.signature
->timestamp
);
380 else if( node
->pkt
->pkttype
== PKT_GPG_CONTROL
) {
381 fprintf(stderr
, " ctrl=%d len=%u\n",
382 node
->pkt
->pkt
.gpg_control
->control
,
383 (unsigned int)node
->pkt
->pkt
.gpg_control
->datalen
);
385 else if( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
386 || node
->pkt
->pkttype
== PKT_PUBLIC_SUBKEY
) {
387 PKT_public_key
*pk
= node
->pkt
->pkt
.public_key
;
388 fprintf(stderr
, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
389 (ulong
)keyid_from_pk( pk
, NULL
),
390 pk
->pubkey_algo
, pk
->pubkey_usage
,
391 pk
->has_expired
? 'e':'.',
392 pk
->is_revoked
? 'r':'.',
393 pk
->is_valid
? 'v':'.',
394 pk
->mdc_feature
? 'm':'.');