Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / libafscp / afscp_volume.c
blob41a4007ba226972fb1a89e353ad21cf373dc4ed2
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <afsconfig.h>
28 #include <afs/param.h>
30 #ifdef HAVE_SEARCH_H
31 #include <search.h>
32 #else
33 #include "afscp_search.h"
34 #endif
36 #include <afs/vlserver.h>
37 #include <afs/vldbint.h>
38 #include <afs/volint.h>
39 #include "afscp.h"
40 #include "afscp_internal.h"
42 static int
43 icompare(const void *pa, const void *pb)
45 const struct afscp_volume *va = pa, *vb = pb;
47 if (va->id > vb->id)
48 return 1;
49 if (va->id < vb->id)
50 return -1;
51 return 0;
54 static int
55 ncompare(const void *pa, const void *pb)
57 const struct afscp_volume *va = pa, *vb = pb;
59 if (va->voltype > vb->voltype)
60 return 1;
61 if (vb->voltype < va->voltype)
62 return -1;
63 return strcmp(va->name, vb->name);
66 union allvldbentry {
67 struct uvldbentry u;
68 struct nvldbentry n;
69 struct vldbentry o;
72 struct afscp_volume *
73 afscp_VolumeByName(struct afscp_cell *cell, const char *vname,
74 afs_int32 intype)
76 union allvldbentry u;
77 struct afscp_volume *ret, key;
78 struct afscp_server *server;
79 afs_int32 code, vtype, type, srv;
80 void *s;
81 #ifdef AFSCP_DEBUG
82 struct in_addr i;
83 #endif
84 if (intype == RWVOL)
85 vtype = VLSF_RWVOL;
86 else if (intype == ROVOL)
87 vtype = VLSF_ROVOL;
88 else if (intype == BACKVOL)
89 vtype = VLSF_BACKVOL;
90 else {
91 afscp_errno = EINVAL;
92 return NULL;
95 memset(&key, 0, sizeof(key));
96 strlcpy(key.name, vname, sizeof(key.name));
97 key.voltype = vtype;
98 s = tfind(&key, &cell->volsbyname, ncompare);
99 if (s) {
100 ret = *(struct afscp_volume **)s;
101 return ret;
104 type = 0;
105 code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u);
106 if (code == RXGEN_OPCODE) {
107 type = 1;
108 code =
109 ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n);
110 if (code == RXGEN_OPCODE) {
111 type = 2;
112 code = ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname,
113 &u.o);
116 if (code != 0) {
117 afscp_errno = code;
118 return NULL;
120 ret = malloc(sizeof(struct afscp_volume));
121 if (ret == NULL) {
122 afscp_errno = ENOMEM;
123 return NULL;
125 memset(ret, 0, sizeof(struct afscp_volume));
126 strlcpy(ret->name, u.u.name, sizeof(ret->name));
127 ret->nservers = 0;
128 ret->cell = cell;
129 switch (type) {
130 case 0:
131 ret->id = u.u.volumeId[intype];
132 for (srv = 0; srv < u.u.nServers; srv++) {
133 if ((u.u.serverFlags[srv] & vtype) == 0)
134 continue;
135 afs_dprintf(("uvldbentry server %d flags: %x\n", srv,
136 u.u.serverFlags[srv]));
138 if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
139 server =
140 afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
141 else
142 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
143 if (!server)
144 continue;
145 ret->servers[ret->nservers++] = server->index;
147 break;
148 case 1:
149 ret->id = u.n.volumeId[intype];
150 for (srv = 0; srv < u.n.nServers; srv++) {
151 if ((u.n.serverFlags[srv] & vtype) == 0)
152 continue;
153 server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
154 if (!server)
155 continue;
156 ret->servers[ret->nservers++] = server->index;
158 break;
159 case 2:
160 ret->id = u.o.volumeId[intype];
161 for (srv = 0; srv < u.o.nServers; srv++) {
162 if ((u.o.serverFlags[srv] & vtype) == 0)
163 continue;
164 server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
165 if (!server)
166 continue;
167 ret->servers[ret->nservers++] = server->index;
169 break;
171 if (!ret->nservers || !ret->id) {
172 free(ret);
173 return NULL;
176 ret->voltype = intype;
177 server = afscp_ServerByIndex(ret->servers[0]);
178 #ifdef AFSCP_DEBUG
179 if (server != NULL)
180 i.s_addr = server->addrs[0];
181 else
182 i.s_addr = 0;
183 #endif
184 afs_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name,
185 afs_printable_uint32_lu(ret->id),
186 inet_ntoa(i), ret->servers[0]));
187 s = tsearch(&key, &cell->volsbyname, ncompare);
188 if (s)
189 *(struct afscp_volume **)s = ret;
190 key.id = ret->id;
191 s = tsearch(&key, &cell->volsbyid, icompare);
192 if (s)
193 *(struct afscp_volume **)s = ret;
194 return ret;
197 struct afscp_volume *
198 afscp_VolumeById(struct afscp_cell *cell, afs_uint32 id)
200 union allvldbentry u;
201 struct afscp_volume *ret, key;
202 struct afscp_server *server;
203 afs_int32 code, vtype, type, srv;
204 int voltype = -1;
205 char idbuffer[16];
206 void *s;
207 #ifdef AFSCP_DEBUG
208 struct in_addr i;
209 #endif
211 memset(&key, 0, sizeof(key));
212 key.id = id;
213 s = tfind(&key, &cell->volsbyid, icompare);
214 if (s) {
215 ret = *(struct afscp_volume **)s;
216 return ret;
219 snprintf(idbuffer, sizeof(idbuffer), "%lu", afs_printable_uint32_lu(id));
220 type = 0;
221 code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u);
222 if (code == RXGEN_OPCODE) {
223 type = 1;
224 code = ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n);
225 if (code == RXGEN_OPCODE) {
226 type = 2;
227 code = ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o);
230 if (code != 0) {
231 afscp_errno = code;
232 return NULL;
234 ret = malloc(sizeof(struct afscp_volume));
235 if (ret == NULL) {
236 afscp_errno = ENOMEM;
237 return NULL;
239 memset(ret, 0, sizeof(struct afscp_volume));
240 strlcpy(ret->name, u.u.name, sizeof(ret->name));
241 ret->nservers = 0;
242 ret->cell = cell;
244 switch (type) {
245 case 0:
246 if (id == u.u.volumeId[RWVOL]) {
247 vtype = VLSF_RWVOL;
248 voltype = RWVOL;
249 } else if (id == u.u.volumeId[ROVOL]) {
250 vtype = VLSF_ROVOL;
251 voltype = ROVOL;
252 } else if (id == u.u.volumeId[BACKVOL]) {
253 vtype = VLSF_BACKVOL;
254 voltype = BACKVOL;
255 } else {
256 vtype = 0;
257 voltype = -1;
259 for (srv = 0; srv < u.u.nServers; srv++) {
260 if ((u.u.serverFlags[srv] & vtype) == 0)
261 continue;
262 if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
263 server =
264 afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
265 else
266 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
267 if (!server)
268 continue;
269 ret->servers[ret->nservers++] = server->index;
271 break;
272 case 1:
273 if (id == u.n.volumeId[RWVOL]) {
274 vtype = VLSF_RWVOL;
275 voltype = RWVOL;
276 } else if (id == u.n.volumeId[ROVOL]) {
277 vtype = VLSF_ROVOL;
278 voltype = ROVOL;
279 } else if (id == u.n.volumeId[BACKVOL]) {
280 vtype = VLSF_BACKVOL;
281 voltype = BACKVOL;
282 } else {
283 vtype = 0;
284 voltype = -1;
286 for (srv = 0; srv < u.n.nServers; srv++) {
287 if ((u.n.serverFlags[srv] & vtype) == 0)
288 continue;
289 server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
290 if (server == NULL)
291 continue;
292 ret->servers[ret->nservers++] = server->index;
294 break;
295 case 2:
296 if (id == u.o.volumeId[RWVOL]) {
297 vtype = VLSF_RWVOL;
298 voltype = RWVOL;
299 } else if (id == u.o.volumeId[ROVOL]) {
300 vtype = VLSF_ROVOL;
301 voltype = ROVOL;
302 } else if (id == u.o.volumeId[BACKVOL]) {
303 vtype = VLSF_BACKVOL;
304 voltype = BACKVOL;
305 } else {
306 vtype = 0;
307 voltype = -1;
309 for (srv = 0; srv < u.o.nServers; srv++) {
310 if ((u.o.serverFlags[srv] & vtype) == 0)
311 continue;
312 server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
313 if (server == NULL)
314 continue;
315 ret->servers[ret->nservers++] = server->index;
317 break;
319 ret->voltype = voltype;
320 server = afscp_ServerByIndex(ret->servers[0]);
321 #ifdef AFSCP_DEBUG
322 if (server)
323 i.s_addr = server->addrs[0];
324 else
325 i.s_addr = 0;
326 #endif
327 afs_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name,
328 afs_printable_uint32_lu(ret->id), inet_ntoa(i),
329 ret->servers[0]));
330 s = tsearch(&key, &cell->volsbyid, icompare);
331 if (s)
332 *(struct afscp_volume **)s = ret;
333 strlcpy(key.name, ret->name, sizeof(key.name));
334 s = tsearch(&key, &cell->volsbyname, ncompare);
335 if (s)
336 *(struct afscp_volume **)s = ret;
337 return ret;