1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-23 10:29:58 +01:00
gnupg/g10/kbnode.c

384 lines
8.0 KiB
C
Raw Normal View History

1997-12-12 12:03:58 +00:00
/* kbnode.c - keyblock node utility functions
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
1997-12-12 12:03:58 +00:00
*
* This file is part of GnuPG.
1997-12-12 12:03:58 +00:00
*
* GnuPG is free software; you can redistribute it and/or modify
1997-12-12 12:03:58 +00:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
1997-12-12 12:03:58 +00:00
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include "util.h"
1997-12-12 12:03:58 +00:00
#include "packet.h"
#include "keydb.h"
1998-10-12 20:16:38 +00:00
#define USE_UNUSED_NODES 1
1997-12-12 12:03:58 +00:00
1998-10-12 20:16:38 +00:00
static KBNODE unused_nodes;
1997-12-12 12:03:58 +00:00
static KBNODE
alloc_node(void)
1997-12-12 12:03:58 +00:00
{
1998-10-12 20:16:38 +00:00
KBNODE n;
n = unused_nodes;
if( n )
unused_nodes = n->next;
else
n = gcry_xmalloc( sizeof *n );
1997-12-12 12:03:58 +00:00
n->next = NULL;
n->pkt = NULL;
n->flag = 0;
1998-02-17 20:48:52 +00:00
n->private_flag=0;
1998-10-21 17:34:36 +00:00
n->recno = 0;
1998-02-17 20:48:52 +00:00
return n;
}
static void
free_node( KBNODE n )
{
if( n ) {
#if USE_UNUSED_NODES
n->next = unused_nodes;
unused_nodes = n;
#else
gcry_free( n );
#endif
}
}
KBNODE
new_kbnode( PACKET *pkt )
{
KBNODE n = alloc_node();
n->pkt = pkt;
return n;
}
1998-02-17 20:48:52 +00:00
KBNODE
clone_kbnode( KBNODE node )
{
KBNODE n = alloc_node();
1998-10-12 20:16:38 +00:00
1998-02-17 20:48:52 +00:00
n->pkt = node->pkt;
1998-03-09 21:44:06 +00:00
n->private_flag = node->private_flag | 2; /* mark cloned */
1997-12-12 12:03:58 +00:00
return n;
}
void
release_kbnode( KBNODE n )
{
KBNODE n2;
while( n ) {
n2 = n->next;
if( !is_cloned_kbnode(n) ) {
1998-02-17 20:48:52 +00:00
free_packet( n->pkt );
gcry_free( n->pkt );
1998-10-12 20:16:38 +00:00
}
free_node( n );
1997-12-12 12:03:58 +00:00
n = n2;
}
}
1998-01-02 20:40:10 +00:00
/****************
* Delete NODE.
1998-04-14 17:51:16 +00:00
* Note: This only works with walk_kbnode!!
1998-01-02 20:40:10 +00:00
*/
void
1998-02-16 20:05:02 +00:00
delete_kbnode( KBNODE node )
1998-01-02 20:40:10 +00:00
{
node->private_flag |= 1;
}
1998-02-17 20:48:52 +00:00
1997-12-16 19:15:09 +00:00
/****************
1998-04-14 17:51:16 +00:00
* Append NODE to ROOT. ROOT must exist!
1997-12-16 19:15:09 +00:00
*/
void
add_kbnode( KBNODE root, KBNODE node )
{
KBNODE n1;
for(n1=root; n1->next; n1 = n1->next)
;
n1->next = node;
}
/****************
1998-07-29 19:35:05 +00:00
* Insert NODE into the list after root but before a packet which is not of
* type PKTTYPE
* (only if PKTTYPE != 0)
1997-12-16 19:15:09 +00:00
*/
void
insert_kbnode( KBNODE root, KBNODE node, int pkttype )
1997-12-16 19:15:09 +00:00
{
if( !pkttype ) {
node->next = root->next;
root->next = node;
}
1997-12-16 19:15:09 +00:00
else {
KBNODE n1;
for(n1=root; n1->next; n1 = n1->next)
1998-07-29 19:35:05 +00:00
if( pkttype != n1->next->pkt->pkttype ) {
node->next = n1->next;
n1->next = node;
return;
}
/* no such packet, append */
node->next = NULL;
1997-12-16 19:15:09 +00:00
n1->next = node;
}
}
1997-12-12 12:03:58 +00:00
/****************
* Find the previous node (if PKTTYPE = 0) or the previous node
* with pkttype PKTTYPE in the list starting with ROOT of NODE.
1997-12-12 12:03:58 +00:00
*/
KBNODE
find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
1997-12-12 12:03:58 +00:00
{
KBNODE n1;
1997-12-12 12:03:58 +00:00
for(n1=NULL ; root && root != node; root = root->next )
if( !pkttype || root->pkt->pkttype == pkttype )
n1 = root;
return n1;
}
/****************
1998-04-25 08:08:35 +00:00
* Ditto, but find the next packet. The behaviour is trivial if
* PKTTYPE is 0 but if it is specified, the next node with a packet
* of this type is returned. The function has some knowledge about
* the valid ordering of packets: e.g. if the next signature packet
* is requested, the function will not return one if it encounters
* a user-id.
*/
KBNODE
find_next_kbnode( KBNODE node, int pkttype )
{
for( node=node->next ; node; node = node->next ) {
if( !pkttype )
return node;
else if( pkttype == PKT_USER_ID
1998-06-29 12:30:57 +00:00
&& ( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
return NULL;
else if( pkttype == PKT_SIGNATURE
&& ( node->pkt->pkttype == PKT_USER_ID
1998-06-29 12:30:57 +00:00
|| node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
return NULL;
else if( node->pkt->pkttype == pkttype )
return node;
}
return NULL;
}
KBNODE
find_kbnode( KBNODE node, int pkttype )
{
for( ; node; node = node->next ) {
if( node->pkt->pkttype == pkttype )
return node;
1997-12-12 12:03:58 +00:00
}
1997-12-16 19:15:09 +00:00
return NULL;
1997-12-12 12:03:58 +00:00
}
1997-12-16 19:15:09 +00:00
/****************
1998-04-14 17:51:16 +00:00
* Walk through a list of kbnodes. This function returns
1997-12-16 19:15:09 +00:00
* the next kbnode for each call; before using the function the first
* time, the caller must set CONTEXT to NULL (This has simply the effect
* to start with ROOT).
*/
KBNODE
walk_kbnode( KBNODE root, KBNODE *context, int all )
1997-12-16 19:15:09 +00:00
{
KBNODE n;
1998-01-02 20:40:10 +00:00
do {
if( !*context ) {
*context = root;
1998-02-13 20:58:50 +00:00
n = root;
}
else {
n = (*context)->next;
*context = n;
1998-01-02 20:40:10 +00:00
}
} while( !all && n && is_deleted_kbnode(n) );
1997-12-16 19:15:09 +00:00
return n;
}
1997-12-12 12:03:58 +00:00
void
clear_kbnode_flags( KBNODE n )
{
for( ; n; n = n->next ) {
n->flag = 0;
}
}
1998-01-02 20:40:10 +00:00
1998-02-16 20:05:02 +00:00
/****************
* Commit changes made to the kblist at ROOT. Note that ROOT my change,
1998-04-14 17:51:16 +00:00
* and it is therefore passed by reference.
1998-02-16 20:05:02 +00:00
* The function has the effect of removing all nodes marked as deleted.
1998-04-14 17:51:16 +00:00
* returns true if any node has been changed
1998-02-16 20:05:02 +00:00
*/
int
commit_kbnode( KBNODE *root )
{
1998-02-17 20:48:52 +00:00
KBNODE n, nl;
1998-02-16 20:05:02 +00:00
int changed = 0;
1998-02-17 20:48:52 +00:00
for( n = *root, nl=NULL; n; n = nl->next ) {
if( is_deleted_kbnode(n) ) {
1998-02-16 20:05:02 +00:00
if( n == *root )
1998-02-17 20:48:52 +00:00
*root = nl = n->next;
else
nl->next = n->next;
if( !is_cloned_kbnode(n) ) {
1998-02-17 20:48:52 +00:00
free_packet( n->pkt );
gcry_free( n->pkt );
1998-10-12 20:16:38 +00:00
}
free_node( n );
1998-02-16 20:05:02 +00:00
changed = 1;
}
1998-02-17 20:48:52 +00:00
else
nl = n;
1998-02-16 20:05:02 +00:00
}
return changed;
}
void
remove_kbnode( KBNODE *root, KBNODE node )
{
KBNODE n, nl;
for( n = *root, nl=NULL; n; n = nl->next ) {
if( n == node ) {
if( n == *root )
*root = nl = n->next;
else
nl->next = n->next;
if( !is_cloned_kbnode(n) ) {
free_packet( n->pkt );
gcry_free( n->pkt );
}
free_node( n );
}
else
nl = n;
}
}
/****************
* Move NODE behind right after WHERE or to the beginning if WHERE is NULL.
*/
void
move_kbnode( KBNODE *root, KBNODE node, KBNODE where )
{
KBNODE tmp, prev;
if( !root || !*root || !node )
return; /* sanity check */
for( prev = *root; prev && prev->next != node; prev = prev->next )
;
if( !prev )
return; /* node is not in the list */
if( !where ) { /* move node before root */
if( node == *root ) /* move to itself */
return;
prev->next = node->next;
node->next = *root;
*root = node;
return;
}
/* move it after where */
if( node == where )
return;
tmp = node->next;
node->next = where->next;
where->next = node;
prev->next = tmp;
}
1998-02-17 20:48:52 +00:00
void
dump_kbnode( KBNODE node )
{
for(; node; node = node->next ) {
const char *s;
switch( node->pkt->pkttype ) {
case 0: s="empty"; break;
1998-06-29 12:30:57 +00:00
case PKT_PUBLIC_KEY: s="public-key"; break;
case PKT_SECRET_KEY: s="secret-key"; break;
case PKT_SECRET_SUBKEY: s= "secret-subkey"; break;
1998-02-17 20:48:52 +00:00
case PKT_PUBKEY_ENC: s="public-enc"; break;
case PKT_SIGNATURE: s="signature"; break;
case PKT_ONEPASS_SIG: s="onepass-sig"; break;
case PKT_USER_ID: s="user-id"; break;
1998-06-29 12:30:57 +00:00
case PKT_PUBLIC_SUBKEY: s="public-subkey"; break;
1998-02-17 20:48:52 +00:00
case PKT_COMMENT: s="comment"; break;
case PKT_RING_TRUST: s="trust"; break;
case PKT_PLAINTEXT: s="plaintext"; break;
case PKT_COMPRESSED: s="compressed"; break;
case PKT_ENCRYPTED: s="encrypted"; break;
default: s="unknown"; break;
}
fprintf(stderr, "node %p %02x/%02x type=%s",
node, node->flag, node->private_flag, s);
if( node->pkt->pkttype == PKT_USER_ID ) {
fputs(" \"", stderr);
print_string( stderr, node->pkt->pkt.user_id->name,
1998-03-09 21:44:06 +00:00
node->pkt->pkt.user_id->len, 0 );
1998-02-17 20:48:52 +00:00
fputs("\"\n", stderr);
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
fprintf(stderr, " class=%02x keyid=%08lX\n",
node->pkt->pkt.signature->sig_class,
1998-02-17 20:48:52 +00:00
(ulong)node->pkt->pkt.signature->keyid[1] );
}
1998-06-29 12:30:57 +00:00
else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
1998-02-17 20:48:52 +00:00
fprintf(stderr, " keyid=%08lX\n", (ulong)
1998-06-29 12:30:57 +00:00
keyid_from_pk( node->pkt->pkt.public_key, NULL ));
1998-02-17 20:48:52 +00:00
}
else
fputs("\n", stderr);
}
}