1 /* kbnode.c - keyblock node utility functions
2 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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;
120 * Append NODE to ROOT. ROOT must exist!
123 add_kbnode( KBNODE root
, KBNODE node
)
127 for(n1
=root
; n1
->next
; n1
= n1
->next
)
133 * Insert NODE into the list after root but before a packet which is not of
135 * (only if PKTTYPE != 0)
138 insert_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
141 node
->next
= root
->next
;
147 for(n1
=root
; n1
->next
; n1
= n1
->next
)
148 if( pkttype
!= n1
->next
->pkt
->pkttype
) {
149 node
->next
= n1
->next
;
153 /* no such packet, append */
161 * Find the previous node (if PKTTYPE = 0) or the previous node
162 * with pkttype PKTTYPE in the list starting with ROOT of NODE.
165 find_prev_kbnode( KBNODE root
, KBNODE node
, int pkttype
)
169 for (n1
=NULL
; root
&& root
!= node
; root
= root
->next
) {
170 if (!pkttype
||root
->pkt
->pkttype
== pkttype
)
177 * Ditto, but find the next packet. The behaviour is trivial if
178 * PKTTYPE is 0 but if it is specified, the next node with a packet
179 * of this type is returned. The function has some knowledge about
180 * the valid ordering of packets: e.g. if the next signature packet
181 * is requested, the function will not return one if it encounters
185 find_next_kbnode( KBNODE node
, int pkttype
)
187 for( node
=node
->next
; node
; node
= node
->next
) {
190 else if( pkttype
== PKT_USER_ID
191 && ( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
192 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
194 else if( pkttype
== PKT_SIGNATURE
195 && ( node
->pkt
->pkttype
== PKT_USER_ID
196 || node
->pkt
->pkttype
== PKT_PUBLIC_KEY
197 || node
->pkt
->pkttype
== PKT_SECRET_KEY
) )
199 else if( node
->pkt
->pkttype
== pkttype
)
207 find_kbnode( KBNODE node
, int pkttype
)
209 for( ; node
; node
= node
->next
) {
210 if( node
->pkt
->pkttype
== pkttype
)
219 * Walk through a list of kbnodes. This function returns
220 * the next kbnode for each call; before using the function the first
221 * time, the caller must set CONTEXT to NULL (This has simply the effect
222 * to start with ROOT).
225 walk_kbnode( KBNODE root
, KBNODE
*context
, int all
)
235 n
= (*context
)->next
;
238 } while( !all
&& n
&& is_deleted_kbnode(n
) );
244 clear_kbnode_flags( KBNODE n
)
246 for( ; n
; n
= n
->next
) {
253 * Commit changes made to the kblist at ROOT. Note that ROOT my change,
254 * and it is therefore passed by reference.
255 * The function has the effect of removing all nodes marked as deleted.
256 * returns true if any node has been changed
259 commit_kbnode( KBNODE
*root
)
264 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
265 if( is_deleted_kbnode(n
) ) {
267 *root
= nl
= n
->next
;
270 if( !is_cloned_kbnode(n
) ) {
271 free_packet( n
->pkt
);
284 remove_kbnode( KBNODE
*root
, KBNODE node
)
288 for( n
= *root
, nl
=NULL
; n
; n
= nl
->next
) {
291 *root
= nl
= n
->next
;
294 if( !is_cloned_kbnode(n
) ) {
295 free_packet( n
->pkt
);
307 * Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
310 move_kbnode( KBNODE
*root
, KBNODE node
, KBNODE where
)
314 if( !root
|| !*root
|| !node
)
315 return; /* sanity check */
316 for( prev
= *root
; prev
&& prev
->next
!= node
; prev
= prev
->next
)
319 return; /* node is not in the list */
321 if( !where
) { /* move node before root */
322 if( node
== *root
) /* move to itself */
324 prev
->next
= node
->next
;
329 /* move it after where */
333 node
->next
= where
->next
;
342 dump_kbnode( KBNODE node
)
344 for(; node
; node
= node
->next
) {
346 switch( node
->pkt
->pkttype
) {
347 case 0: s
="empty"; break;
348 case PKT_PUBLIC_KEY
: s
="public-key"; break;
349 case PKT_SECRET_KEY
: s
="secret-key"; break;
350 case PKT_SECRET_SUBKEY
: s
= "secret-subkey"; break;
351 case PKT_PUBKEY_ENC
: s
="public-enc"; break;
352 case PKT_SIGNATURE
: s
="signature"; break;
353 case PKT_ONEPASS_SIG
: s
="onepass-sig"; break;
354 case PKT_USER_ID
: s
="user-id"; break;
355 case PKT_PUBLIC_SUBKEY
: s
="public-subkey"; break;
356 case PKT_COMMENT
: s
="comment"; break;
357 case PKT_RING_TRUST
: s
="trust"; break;
358 case PKT_PLAINTEXT
: s
="plaintext"; break;
359 case PKT_COMPRESSED
: s
="compressed"; break;
360 case PKT_ENCRYPTED
: s
="encrypted"; break;
361 case PKT_GPG_CONTROL
: s
="gpg-control"; break;
362 default: s
="unknown"; break;
364 fprintf(stderr
, "node %p %02x/%02x type=%s",
365 node
, node
->flag
, node
->private_flag
, s
);
366 if( node
->pkt
->pkttype
== PKT_USER_ID
) {
367 PKT_user_id
*uid
= node
->pkt
->pkt
.user_id
;
368 fputs(" \"", stderr
);
369 print_string( stderr
, uid
->name
, uid
->len
, 0 );
370 fprintf (stderr
, "\" %c%c%c%c\n",
371 uid
->is_expired
? 'e':'.',
372 uid
->is_revoked
? 'r':'.',
373 uid
->created
? 'v':'.',
374 uid
->is_primary
? 'p':'.' );
376 else if( node
->pkt
->pkttype
== PKT_SIGNATURE
) {
377 fprintf(stderr
, " class=%02x keyid=%08lX ts=%lu\n",
378 node
->pkt
->pkt
.signature
->sig_class
,
379 (ulong
)node
->pkt
->pkt
.signature
->keyid
[1],
380 (ulong
)node
->pkt
->pkt
.signature
->timestamp
);
382 else if( node
->pkt
->pkttype
== PKT_GPG_CONTROL
) {
383 fprintf(stderr
, " ctrl=%d len=%u\n",
384 node
->pkt
->pkt
.gpg_control
->control
,
385 (unsigned int)node
->pkt
->pkt
.gpg_control
->datalen
);
387 else if( node
->pkt
->pkttype
== PKT_PUBLIC_KEY
388 || node
->pkt
->pkttype
== PKT_PUBLIC_SUBKEY
) {
389 PKT_public_key
*pk
= node
->pkt
->pkt
.public_key
;
390 fprintf(stderr
, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
391 (ulong
)keyid_from_pk( pk
, NULL
),
392 pk
->pubkey_algo
, pk
->pubkey_usage
,
393 pk
->has_expired
? 'e':'.',
394 pk
->is_revoked
? 'r':'.',
395 pk
->is_valid
? 'v':'.',
396 pk
->mdc_feature
? 'm':'.');