OPENAFS-SA-2016-002 VldbListByAttributes information leak
[openafs.git] / src / bucoord / dlq.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/stds.h>
12
13 #include <roken.h>
14
15 #include "bc.h"
16 #include <afs/bubasics.h>
17 #include "bucoord_prototypes.h"
18
19 /* protos */
20 int dlqCount(dlqlinkP );
21 void dlqMoveb( dlqlinkP, dlqlinkP);
22 dlqlinkP dlqUnlinkb(dlqlinkP );
23 dlqlinkP dlqUnlinkf(dlqlinkP );
24 dlqlinkP dlqFront(dlqlinkP headptr);
25
26 #define DLQ_ASSERT_HEAD(headptr)                                \
27         if ( (headptr)->dlq_type != DLQ_HEAD )                  \
28         {                                                       \
29             printf("file %s line %d, invalid queue head\n",     \
30                    __FILE__, __LINE__);                         \
31             exit(1);                                            \
32         }
33
34
35 /* dlqEmpty
36  * exit:
37  *      1 - queue is empty
38  *      0 - items on queue
39  */
40
41 int dlqEmpty(dlqlinkP headptr )
42 {
43     DLQ_ASSERT_HEAD(headptr);
44     if (headptr->dlq_next == headptr)
45         return (1);
46     return (0);
47 }
48
49 int dlqInit(dlqlinkP headptr)
50 {
51     headptr->dlq_next = headptr;
52     headptr->dlq_prev = headptr;
53     headptr->dlq_type = DLQ_HEAD;
54     headptr->dlq_structPtr = NULL;
55     return (0);
56 }
57
58 /* dlqLinkf
59  *      link item to front of chain
60  */
61 int dlqLinkf(dlqlinkP headptr, dlqlinkP entryptr)
62 {
63     DLQ_ASSERT_HEAD(headptr);
64     /* link in as first item in chain */
65     entryptr->dlq_next = headptr->dlq_next;
66     headptr->dlq_next->dlq_prev = entryptr;
67     entryptr->dlq_prev = headptr;
68     headptr->dlq_next = entryptr;
69     return (0);
70 }
71
72 /* dlqLinkb
73  *      link item to end of chain
74  */
75
76 int dlqLinkb(dlqlinkP headptr, dlqlinkP entryptr)
77 {
78     DLQ_ASSERT_HEAD(headptr);
79     entryptr->dlq_next = headptr;
80     entryptr->dlq_prev = headptr->dlq_prev;
81
82     headptr->dlq_prev = entryptr;
83     entryptr->dlq_prev->dlq_next = entryptr;
84     return (0);
85 }
86
87 /* dlqMoveb
88  *      move all the items on the fromptr and append to the toptr's list
89  */
90
91 void dlqMoveb( dlqlinkP fromptr, dlqlinkP toptr)
92 {
93     dlqlinkP tailptr;
94
95     DLQ_ASSERT_HEAD(fromptr);
96     DLQ_ASSERT_HEAD(toptr);
97
98     if (dlqEmpty(fromptr))
99         return;
100
101     tailptr = toptr->dlq_prev;
102
103     tailptr->dlq_next = fromptr->dlq_next;
104     tailptr->dlq_next->dlq_prev = tailptr;
105
106     /* now fix up the last item in the new chain */
107     tailptr = fromptr->dlq_prev;
108
109     tailptr->dlq_next = toptr;
110     toptr->dlq_prev = tailptr;
111
112     fromptr->dlq_next = fromptr;
113     fromptr->dlq_prev = fromptr;
114     return;
115 }
116
117 /* dlqUnlinkb
118  *      unlink the last item on the queue
119  */
120
121 dlqlinkP dlqUnlinkb(dlqlinkP headptr)
122 {
123     dlqlinkP ptr;
124     DLQ_ASSERT_HEAD(headptr);
125
126     if (dlqEmpty(headptr))
127         return (0);
128
129     ptr = headptr->dlq_prev;
130     ptr->dlq_prev->dlq_next = headptr;
131     headptr->dlq_prev = ptr->dlq_prev;
132
133     ptr->dlq_next = ptr;
134     ptr->dlq_prev = ptr;
135     return (ptr);
136 }
137
138 /* dlqUnlinkf
139  *      unlink the item on the front of the queue
140  */
141
142 dlqlinkP dlqUnlinkf(dlqlinkP headptr)
143 {
144     dlqlinkP ptr;
145     DLQ_ASSERT_HEAD(headptr);
146
147     if (dlqEmpty(headptr))
148         return (0);
149
150     ptr = headptr->dlq_next;
151
152     headptr->dlq_next = ptr->dlq_next;
153     ptr->dlq_next->dlq_prev = headptr;
154
155     ptr->dlq_next = ptr;
156     ptr->dlq_prev = ptr;
157     return (ptr);
158 }
159
160 /* dlqUnlink
161  *      unlink the specified item from the queue.
162  */
163
164 void dlqUnlink( dlqlinkP ptr)
165 {
166     /* must not be the queue head */
167     if (ptr->dlq_type == DLQ_HEAD) {
168         printf("dlqUnlink: invalid unlink\n");
169         exit(1);
170     }
171
172     ptr->dlq_prev->dlq_next = ptr->dlq_next;
173     ptr->dlq_next->dlq_prev = ptr->dlq_prev;
174
175     ptr->dlq_next = 0;
176     ptr->dlq_prev = 0;
177 }
178
179 /* dlqFront
180  *      return point to item at front of queuen
181  */
182
183 dlqlinkP dlqFront(dlqlinkP headptr)
184 {
185     DLQ_ASSERT_HEAD(headptr);
186
187     if (dlqEmpty(headptr))
188         return (0);
189
190     return (headptr->dlq_next);
191 }
192
193 int dlqCount(dlqlinkP headptr)
194 {
195     dlqlinkP ptr;
196     int count = 0;
197
198     DLQ_ASSERT_HEAD(headptr);
199
200     ptr = headptr->dlq_next;
201     while (ptr != headptr) {
202         ptr = ptr->dlq_next;
203         count++;
204     }
205     return (count);
206 }
207
208 int dlqTraverseQueue(dlqlinkP headptr, int (*fn1)(void *), int (*fn2)(void *))
209 {
210     dlqlinkP ptr, oldPtr;
211
212     DLQ_ASSERT_HEAD(headptr);
213
214     ptr = headptr->dlq_next;
215     while (ptr != headptr) {
216         if (fn2 && ptr->dlq_structPtr)
217             (*fn2) (ptr->dlq_structPtr);
218         oldPtr = ptr;
219         ptr = ptr->dlq_next;
220         if (fn1)
221             (*fn1) (oldPtr);
222     }
223     return (0);
224 }