6a0978d014232339794ef9faf06a151e9710f7c4
[openafs.git] / src / libafscp / afscp_volume.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
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.
15
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.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <search.h>
33
34 #include <afs/vlserver.h>
35 #include <afs/vldbint.h>
36 #include <afs/volint.h>
37 #include "afscp.h"
38 #include "afscp_internal.h"
39
40 static int
41 icompare(const void *pa, const void *pb)
42 {
43     const struct afscp_volume *va = pa, *vb = pb;
44
45     if (va->id > vb->id)
46         return 1;
47     if (va->id < vb->id)
48         return -1;
49     return 0;
50 }
51
52 static int
53 ncompare(const void *pa, const void *pb)
54 {
55     const struct afscp_volume *va = pa, *vb = pb;
56
57     if (va->voltype > vb->voltype)
58         return 1;
59     if (vb->voltype < va->voltype)
60         return -1;
61     return strcmp(va->name, vb->name);
62 }
63
64 union allvldbentry {
65     struct uvldbentry u;
66     struct nvldbentry n;
67     struct vldbentry o;
68 };
69
70 struct afscp_volume *
71 afscp_VolumeByName(struct afscp_cell *cell, const char *vname,
72                    afs_int32 intype)
73 {
74     union allvldbentry u;
75     struct afscp_volume *ret, key;
76     struct afscp_server *server;
77     afs_int32 code, vtype, type, srv;
78     void *s;
79     /* struct in_addr i; */
80
81     if (intype == RWVOL)
82         vtype = VLSF_RWVOL;
83     else if (intype == ROVOL)
84         vtype = VLSF_ROVOL;
85     else if (intype == BACKVOL)
86         vtype = VLSF_BACKVOL;
87     else {
88         afscp_errno = EINVAL;
89         return NULL;
90     }
91
92     memset(&key, 0, sizeof(key));
93     strlcpy(key.name, vname, sizeof(key.name));
94     key.voltype = vtype;
95     s = tfind(&key, &cell->volsbyname, ncompare);
96     if (s) {
97         ret = *(struct afscp_volume **)s;
98         return ret;
99     }
100
101     type = 0;
102     code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, (char *)vname, &u.u);
103     if (code == RXGEN_OPCODE) {
104         type = 1;
105         code =
106             ubik_VL_GetEntryByNameN(cell->vlservers, 0, (char *)vname, &u.n);
107         if (code == RXGEN_OPCODE) {
108             type = 2;
109             code = ubik_VL_GetEntryByNameO(cell->vlservers, 0, (char *)vname,
110                                            &u.o);
111         }
112     }
113     if (code != 0) {
114         afscp_errno = code;
115         return NULL;
116     }
117     ret = malloc(sizeof(struct afscp_volume));
118     if (ret == NULL) {
119         afscp_errno = ENOMEM;
120         return NULL;
121     }
122     memset(ret, 0, sizeof(struct afscp_volume));
123     strlcpy(ret->name, u.u.name, sizeof(ret->name));
124     ret->nservers = 0;
125     ret->cell = cell;
126     switch (type) {
127     case 0:
128         ret->id = u.u.volumeId[intype];
129         for (srv = 0; srv < u.u.nServers; srv++) {
130             if ((u.u.serverFlags[srv] & vtype) == 0)
131                 continue;
132             afs_dprintf(("uvldbentry server %d flags: %x\n", srv,
133                          u.u.serverFlags[srv]));
134
135             if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
136                 server =
137                     afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
138             else
139                 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
140             if (!server)
141                 continue;
142             ret->servers[ret->nservers++] = server->index;
143         }
144         break;
145     case 1:
146         ret->id = u.n.volumeId[intype];
147         for (srv = 0; srv < u.n.nServers; srv++) {
148             if ((u.n.serverFlags[srv] & vtype) == 0)
149                 continue;
150             server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
151             if (!server)
152                 continue;
153             ret->servers[ret->nservers++] = server->index;
154         }
155         break;
156     case 2:
157         ret->id = u.o.volumeId[intype];
158         for (srv = 0; srv < u.o.nServers; srv++) {
159             if ((u.o.serverFlags[srv] & vtype) == 0)
160                 continue;
161             server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
162             if (!server)
163                 continue;
164             ret->servers[ret->nservers++] = server->index;
165         }
166         break;
167     }
168     if (!ret->nservers || !ret->id) {
169         free(ret);
170         return NULL;
171     }
172
173     ret->voltype = intype;
174     server = afscp_ServerByIndex(ret->servers[0]);
175     /* if (server != NULL)
176      * i.s_addr = server->addrs[0];
177      * else
178      * i.s_addr = 0; */
179     /* i.s_addr is set but not used later */
180     afs_dprintf(("New volume BYNAME %s (%lu) on %s (%d)\n", ret->name,
181                  afs_printable_uint32_lu(ret->id),
182                  inet_ntoa(i), ret->servers[0]));
183     s = tsearch(&key, &cell->volsbyname, ncompare);
184     if (s)
185         *(struct afscp_volume **)s = ret;
186     key.id = ret->id;
187     s = tsearch(&key, &cell->volsbyid, icompare);
188     if (s)
189         *(struct afscp_volume **)s = ret;
190     return ret;
191 }
192
193 struct afscp_volume *
194 afscp_VolumeById(struct afscp_cell *cell, afs_uint32 id)
195 {
196     union allvldbentry u;
197     struct afscp_volume *ret, key;
198     struct afscp_server *server;
199     afs_int32 code, vtype, type, srv;
200     int voltype = -1;
201     char idbuffer[16];
202     void *s;
203     /* struct in_addr i; */
204
205     memset(&key, 0, sizeof(key));
206     key.id = id;
207     s = tfind(&key, &cell->volsbyid, icompare);
208     if (s) {
209         ret = *(struct afscp_volume **)s;
210         return ret;
211     }
212
213     snprintf(idbuffer, sizeof(idbuffer), "%lu", afs_printable_uint32_lu(id));
214     type = 0;
215     code = ubik_VL_GetEntryByNameU(cell->vlservers, 0, idbuffer, &u.u);
216     if (code == RXGEN_OPCODE) {
217         type = 1;
218         code = ubik_VL_GetEntryByIDN(cell->vlservers, 0, id, -1, &u.n);
219         if (code == RXGEN_OPCODE) {
220             type = 2;
221             code = ubik_VL_GetEntryByID(cell->vlservers, 0, id, -1, &u.o);
222         }
223     }
224     if (code != 0) {
225         afscp_errno = code;
226         return NULL;
227     }
228     ret = malloc(sizeof(struct afscp_volume));
229     if (ret == NULL) {
230         afscp_errno = ENOMEM;
231         return NULL;
232     }
233     memset(ret, 0, sizeof(struct afscp_volume));
234     strlcpy(ret->name, u.u.name, sizeof(ret->name));
235     ret->nservers = 0;
236     ret->cell = cell;
237
238     switch (type) {
239     case 0:
240         if (id == u.u.volumeId[RWVOL]) {
241             vtype = VLSF_RWVOL;
242             voltype = RWVOL;
243         } else if (id == u.u.volumeId[ROVOL]) {
244             vtype = VLSF_ROVOL;
245             voltype = ROVOL;
246         } else if (id == u.u.volumeId[BACKVOL]) {
247             vtype = VLSF_BACKVOL;
248             voltype = BACKVOL;
249         } else {
250             vtype = 0;
251             voltype = -1;
252         }
253         for (srv = 0; srv < u.u.nServers; srv++) {
254             if ((u.u.serverFlags[srv] & vtype) == 0)
255                 continue;
256             if ((u.u.serverFlags[srv] & VLSERVER_FLAG_UUID) == 0)
257                 server =
258                     afscp_ServerByAddr(cell, u.u.serverNumber[srv].time_low);
259             else
260                 server = afscp_ServerById(cell, &u.u.serverNumber[srv]);
261             if (!server)
262                 continue;
263             ret->servers[ret->nservers++] = server->index;
264         }
265         break;
266     case 1:
267         if (id == u.n.volumeId[RWVOL]) {
268             vtype = VLSF_RWVOL;
269             voltype = RWVOL;
270         } else if (id == u.n.volumeId[ROVOL]) {
271             vtype = VLSF_ROVOL;
272             voltype = ROVOL;
273         } else if (id == u.n.volumeId[BACKVOL]) {
274             vtype = VLSF_BACKVOL;
275             voltype = BACKVOL;
276         } else {
277             vtype = 0;
278             voltype = -1;
279         }
280         for (srv = 0; srv < u.n.nServers; srv++) {
281             if ((u.n.serverFlags[srv] & vtype) == 0)
282                 continue;
283             server = afscp_ServerByAddr(cell, u.n.serverNumber[srv]);
284             if (server == NULL)
285                 continue;
286             ret->servers[ret->nservers++] = server->index;
287         }
288         break;
289     case 2:
290         if (id == u.o.volumeId[RWVOL]) {
291             vtype = VLSF_RWVOL;
292             voltype = RWVOL;
293         } else if (id == u.o.volumeId[ROVOL]) {
294             vtype = VLSF_ROVOL;
295             voltype = ROVOL;
296         } else if (id == u.o.volumeId[BACKVOL]) {
297             vtype = VLSF_BACKVOL;
298             voltype = BACKVOL;
299         } else {
300             vtype = 0;
301             voltype = -1;
302         }
303         for (srv = 0; srv < u.o.nServers; srv++) {
304             if ((u.o.serverFlags[srv] & vtype) == 0)
305                 continue;
306             server = afscp_ServerByAddr(cell, u.o.serverNumber[srv]);
307             if (server == NULL)
308                 continue;
309             ret->servers[ret->nservers++] = server->index;
310         }
311         break;
312     }
313     ret->voltype = voltype;
314     server = afscp_ServerByIndex(ret->servers[0]);
315     /* if (server)
316      * i.s_addr = server->addrs[0];
317      * else
318      * i.s_addr = 0; */
319     /* i.s_addr is set but not referenced later */
320     afs_dprintf(("New volume BYID %s (%lu) on %s (%d)\n", ret->name,
321                  afs_printable_uint32_lu(ret->id), inet_ntoa(i),
322                  ret->servers[0]));
323     s = tsearch(&key, &cell->volsbyid, icompare);
324     if (s)
325         *(struct afscp_volume **)s = ret;
326     strlcpy(key.name, ret->name, sizeof(key.name));
327     s = tsearch(&key, &cell->volsbyname, ncompare);
328     if (s)
329         *(struct afscp_volume **)s = ret;
330     return ret;
331 }