OPENAFS-SA-2016-002 VldbListByAttributes information leak
[openafs.git] / src / libadmin / vos / lockprocs.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/param.h>
12
13 #include <roken.h>
14
15 #include "lockprocs.h"
16
17 /* Finds an index in VLDB entry that matches the volume type, server, and partition.
18  * If type is zero, will match first index of ANY type (RW, BK, or RO).
19  * If server is zero, will match first index of ANY server and partition 
20  * Zero is a valid partition field.
21  */
22 static int
23 FindIndex(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
24           afs_int32 server, afs_int32 part, afs_int32 type)
25 {
26     afs_status_t tst = 0;
27     int e;
28     int equal = 0;
29
30     for (e = 0; (e < entry->nServers) && !tst; e++) {
31         if (!type || (entry->serverFlags[e] & type)) {
32             VLDB_IsSameAddrs(cellHandle, entry->serverNumber[e], server,
33                              &equal, &tst);
34             if ((!server || (entry->serverPartition[e] == part))
35                 && (!server || equal)) {
36                 break;
37             }
38             if (type == VLSF_RWVOL) {
39                 /* quit when we are looking for RW entry (there's only 1) */
40                 return -1;
41             }
42         }
43     }
44
45     if (e >= entry->nServers) {
46         return -1;              /* Didn't find it */
47     }
48
49     return e;                   /* return the index */
50 }
51
52 /* Changes the rw site only */
53 static void
54 SetAValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
55           afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
56           afs_int32 npart, afs_int32 type)
57 {
58     int e;
59
60     e = FindIndex(cellHandle, entry, oserver, opart, type);
61     if (e == -1)
62         return;                 /* If didn't find it, just return */
63
64     entry->serverNumber[e] = nserver;
65     entry->serverPartition[e] = npart;
66
67     /* Now move rest of entries up */
68     if ((nserver == 0L) && (npart == 0L)) {
69         for (e++; e < entry->nServers; e++) {
70             entry->serverNumber[e - 1] = entry->serverNumber[e];
71             entry->serverPartition[e - 1] = entry->serverPartition[e];
72             entry->serverFlags[e - 1] = entry->serverFlags[e];
73         }
74     }
75 }
76
77 /* Changes the RW site only */
78 void
79 Lp_SetRWValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
80               afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
81               afs_int32 npart)
82 {
83     SetAValue(cellHandle, entry, oserver, opart, nserver, npart, VLSF_RWVOL);
84 }
85
86 /* Changes the RO site only */
87 void
88 Lp_SetROValue(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
89               afs_int32 oserver, afs_int32 opart, afs_int32 nserver,
90               afs_int32 npart)
91 {
92     SetAValue(cellHandle, entry, oserver, opart, nserver, npart, VLSF_ROVOL);
93 }
94
95 /* Returns success if this server and partition matches the RW entry */
96 int
97 Lp_Match(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
98          afs_int32 server, afs_int32 part, afs_status_p st)
99 {
100     if (FindIndex(cellHandle, entry, server, part, VLSF_RWVOL) == -1)
101         return 0;
102     return 1;
103 }
104
105 /* Return the index of the RO entry (plus 1) if it exists, else return 0 */
106 int
107 Lp_ROMatch(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
108            afs_int32 server, afs_int32 part, afs_status_p st)
109 {
110     return (FindIndex(cellHandle, entry, server, part, VLSF_ROVOL) + 1);
111 }
112
113 /* Return the index of the RW entry if it exists, else return -1 */
114 int
115 Lp_GetRwIndex(afs_cell_handle_p cellHandle, struct nvldbentry *entry,
116               afs_status_p st)
117 {
118     return (FindIndex(cellHandle, entry, 0, 0, VLSF_RWVOL));
119 }
120
121 /*initialize queue pointed by <ahead>*/
122 void
123 Lp_QInit(struct qHead *ahead)
124 {
125     ahead->count = 0;
126     ahead->next = NULL;
127 }
128
129 /*add <elem> in front of queue <ahead> */
130 void
131 Lp_QAdd(struct qHead *ahead, struct aqueue *elem)
132 {
133     struct aqueue *temp;
134
135     if (ahead->count == 0) {
136         ahead->count += 1;
137         ahead->next = elem;
138         elem->next = NULL;
139     } else {
140         temp = ahead->next;
141         ahead->count += 1;
142         ahead->next = elem;
143         elem->next = temp;
144     }
145 }
146
147 int
148 Lp_QScan(struct qHead *ahead, afs_int32 id, int *success,
149          struct aqueue **elem, afs_status_p st)
150 {
151     struct aqueue *cptr;
152
153     cptr = ahead->next;
154     while (cptr != NULL) {
155         if (cptr->ids[RWVOL] == id) {
156             *success = 1;
157             *elem = cptr;
158             return 0;
159         }
160         cptr = cptr->next;
161     }
162     *success = 0;
163     return 0;
164 }
165
166 /*return the element in the beginning of the queue <ahead>, free
167 *the space used by that element . <success> indicates if enumeration was ok*/
168 void
169 Lp_QEnumerate(struct qHead *ahead, int *success, struct aqueue *elem,
170               afs_status_p st)
171 {
172     int i;
173     struct aqueue *temp;
174
175     if (ahead->count > 0) {     /*more elements left */
176         ahead->count -= 1;
177         temp = ahead->next;
178         ahead->next = ahead->next->next;
179         strncpy(elem->name, temp->name, VOLSER_OLDMAXVOLNAME);
180         for (i = 0; i < 3; i++) {
181             elem->ids[i] = temp->ids[i];
182             elem->copyDate[i] = temp->copyDate[i];
183             elem->isValid[i] = temp->isValid[i];
184         }
185         elem->next = NULL;
186         *success = 1;
187         free(temp);
188     } else                      /*queue is empty */
189         *success = 0;
190 }