dd4f0ce246603687a3eca7fa262a3dcf2c643e0f
[gnupg.git] / g10 / kbnode.c
1 /* kbnode.c -  keyblock node utility functions
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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.
10  *
11  * G10 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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include "util.h"
27 #include "memory.h"
28 #include "packet.h"
29 #include "keydb.h"
30
31
32
33 KBNODE
34 new_kbnode( PACKET *pkt )
35 {
36     KBNODE n = m_alloc( sizeof *n );
37     n->next = NULL;
38     n->pkt = pkt;
39     n->flag = 0;
40     n->private_flag=0; /* kludge to delete a node */
41     return n;
42 }
43
44
45 void
46 release_kbnode( KBNODE n )
47 {
48     KBNODE n2;
49
50     while( n ) {
51         n2 = n->next;
52         free_packet( n->pkt );
53         m_free( n );
54         n = n2;
55     }
56 }
57
58
59 /****************
60  * Delete NODE from ROOT, ROOT must exist!
61  * Note: This does only work with walk_kbnode!!
62  */
63 void
64 delete_kbnode( KBNODE root, KBNODE node )
65 {
66     node->private_flag |= 1;
67 }
68
69 /****************
70  * Append NODE to ROOT, ROOT must exist!
71  */
72 void
73 add_kbnode( KBNODE root, KBNODE node )
74 {
75     KBNODE n1;
76
77     for(n1=root; n1->next; n1 = n1->next)
78         ;
79     n1->next = node;
80 }
81
82 /****************
83  * Insert NODE into the list after root but before a packet with type PKTTYPE
84  * (only if PKTTYPE != 0)
85  */
86 void
87 insert_kbnode( KBNODE root, KBNODE node, int pkttype )
88 {
89     if( !pkttype ) {
90         node->next = root->next;
91         root->next = node;
92     }
93     else {
94         KBNODE n1;
95
96         for(n1=root; n1->next;  n1 = n1->next)
97             if( pkttype == n1->next->pkt->pkttype ) {
98                 node->next = n1->next;
99                 n1->next = node;
100                 return;
101             }
102         /* no such packet, append */
103         node->next = NULL;
104         n1->next = node;
105     }
106 }
107
108
109 /****************
110  * Find the previous node (if PKTTYPE = 0) or the previous node
111  * with pkttype PKTTYPE in the list starting with ROOT of NODE.
112  */
113 KBNODE
114 find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
115 {
116     KBNODE n1;
117
118     for(n1=NULL ; root && root != node; root = root->next )
119         if( !pkttype || root->pkt->pkttype == pkttype )
120             n1 = root;
121     return n1;
122 }
123
124 /****************
125  * Ditto, but find the next package.  The behaviour is trivial if
126  * PKTTYPE is 0 but if it is specified, the next node with a packet
127  * of this type is returned.  The function has some knowledge about
128  * the valid ordering of packets: e.g. if the next signature packet
129  * is requested, the function will not return one if it encounters
130  * a user-id.
131  */
132 KBNODE
133 find_next_kbnode( KBNODE node, int pkttype )
134 {
135     for( node=node->next ; node; node = node->next ) {
136         if( !pkttype )
137             return node;
138         else if( pkttype == PKT_USER_ID
139                  && (   node->pkt->pkttype == PKT_PUBLIC_CERT
140                      || node->pkt->pkttype == PKT_SECRET_CERT ) )
141             return NULL;
142         else if( pkttype == PKT_SIGNATURE
143                  && (   node->pkt->pkttype == PKT_USER_ID
144                      || node->pkt->pkttype == PKT_PUBLIC_CERT
145                      || node->pkt->pkttype == PKT_SECRET_CERT ) )
146             return NULL;
147         else if( node->pkt->pkttype == pkttype )
148             return node;
149     }
150     return NULL;
151 }
152
153
154 KBNODE
155 find_kbnode( KBNODE node, int pkttype )
156 {
157     for( ; node; node = node->next ) {
158         if( node->pkt->pkttype == pkttype )
159             return node;
160     }
161     return NULL;
162 }
163
164
165
166 /****************
167  * Walk through a list of kbnodes. This functions returns
168  * the next kbnode for each call; before using the function the first
169  * time, the caller must set CONTEXT to NULL (This has simply the effect
170  * to start with ROOT).
171  */
172 KBNODE
173 walk_kbnode( KBNODE root, KBNODE *context, int all )
174 {
175     KBNODE n;
176
177     do {
178         if( !*context ) {
179             *context = root;
180             return root;
181         }
182
183         n = (*context)->next;
184         *context = n;
185     } while( !all && n && (n->private_flag & 1) );
186
187     return n;
188 }
189
190 void
191 clear_kbnode_flags( KBNODE n )
192 {
193     for( ; n; n = n->next ) {
194         n->flag = 0;
195     }
196 }
197