447d39a117d0c6276e60631a641c9757b4dccd9b
[openafs.git] / src / volser / vsutils.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 <afs/stds.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef AFS_NT40_ENV
19 #include <fcntl.h>
20 #include <winsock2.h>
21 #else
22 #include <sys/types.h>
23 #include <sys/file.h>
24 #include <netdb.h>
25 #include <netinet/in.h>
26 #endif /* AFS_NT40_ENV */
27 #include <sys/stat.h>
28 #ifdef AFS_AIX_ENV
29 #include <sys/statfs.h>
30 #endif
31
32 #include <errno.h>
33 #include <lock.h>
34 #include <rx/xdr.h>
35 #include <rx/rx.h>
36 #include <rx/rx_globals.h>
37 #include <afs/nfs.h>
38 #include <afs/vlserver.h>
39 #include <afs/cellconfig.h>
40 #include <afs/keys.h>
41 #include <ubik.h>
42 #include <afs/afsint.h>
43 #include <afs/cmd.h>
44 #include <rx/rxkad.h>
45 #include "volser.h"
46 #include "volint.h"
47 #include "lockdata.h"
48
49 #include "vsutils_prototypes.h"
50
51 struct ubik_client *cstruct;
52 static rxkad_level vsu_rxkad_level = rxkad_clear;
53
54 static void
55 ovlentry_to_nvlentry(struct vldbentry *oentryp,
56                      struct nvldbentry *nentryp)
57 {
58     int i;
59
60     memset(nentryp, 0, sizeof(struct nvldbentry));
61     strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
62     for (i = 0; i < oentryp->nServers; i++) {
63         bulkaddrs m_addrs;
64         ListAddrByAttributes m_attrs;
65         afs_int32 m_nentries;
66
67         m_attrs.Mask = VLADDR_IPADDR;
68         m_attrs.ipaddr = oentryp->serverNumber[i];
69         m_nentries = 0;
70         m_addrs.bulkaddrs_val = 0;
71         m_addrs.bulkaddrs_len = 0;
72         nentryp->serverNumber[i] = oentryp->serverNumber[i];
73         nentryp->serverPartition[i] = oentryp->serverPartition[i];
74         nentryp->serverFlags[i] = oentryp->serverFlags[i];
75     }
76     nentryp->nServers = oentryp->nServers;
77     for (i = 0; i < MAXTYPES; i++)
78         nentryp->volumeId[i] = oentryp->volumeId[i];
79     nentryp->cloneId = oentryp->cloneId;
80     nentryp->flags = oentryp->flags;
81 }
82
83 #if 0
84 /* It is here for when we need it.  Not currently used. */
85 static int
86 nvlentry_to_ovlentry(struct nvldbentry *nentryp,
87                      struct vldbentry *oentryp)
88 {
89     int i;
90
91     memset(oentryp, 0, sizeof(struct vldbentry));
92     strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
93     if (nentryp->nServers > OMAXNSERVERS) {
94         /*
95          * The alternative is to store OMAXSERVERS but it's always better
96          * to know what's going on...
97          */
98         return VL_BADSERVER;
99     }
100     for (i = 0; i < nentryp->nServers; i++) {
101         oentryp->serverNumber[i] = nentryp->serverNumber[i];
102         oentryp->serverPartition[i] = nentryp->serverPartition[i];
103         oentryp->serverFlags[i] = nentryp->serverFlags[i];
104     }
105     oentryp->nServers = i;
106     for (i = 0; i < MAXTYPES; i++)
107         oentryp->volumeId[i] = nentryp->volumeId[i];
108     oentryp->cloneId = nentryp->cloneId;
109     oentryp->flags = nentryp->flags;
110     return 0;
111 }
112 #endif
113
114 static void
115 ovlentry_to_uvlentry(struct vldbentry *oentryp,
116                      struct uvldbentry *uentryp)
117 {
118     int i;
119
120     memset(uentryp, 0, sizeof(struct uvldbentry));
121     strncpy(uentryp->name, oentryp->name, sizeof(uentryp->name));
122     for (i = 0; i < oentryp->nServers; i++) {
123         afs_int32 vcode, m_uniq=0;
124         bulkaddrs m_addrs;
125         ListAddrByAttributes m_attrs;
126         afs_int32 m_nentries;
127
128         m_attrs.Mask = VLADDR_IPADDR;
129         m_attrs.ipaddr = oentryp->serverNumber[i];
130         m_nentries = 0;
131         m_addrs.bulkaddrs_val = 0;
132         m_addrs.bulkaddrs_len = 0;
133         vcode =
134             ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
135                                &uentryp->serverNumber[i],
136                                &m_uniq, &m_nentries,
137                                &m_addrs);
138         uentryp->serverUnique[i] = oentryp->serverNumber[i];
139         uentryp->serverPartition[i] = oentryp->serverPartition[i];
140         uentryp->serverFlags[i] = oentryp->serverFlags[i];
141     }
142     uentryp->nServers = oentryp->nServers;
143     for (i = 0; i < MAXTYPES; i++)
144         uentryp->volumeId[i] = oentryp->volumeId[i];
145     uentryp->cloneId = oentryp->cloneId;
146     uentryp->flags = oentryp->flags;
147 }
148
149 static int
150 uvlentry_to_ovlentry(struct uvldbentry *uentryp,
151                      struct vldbentry *oentryp)
152 {
153     int i;
154
155     memset(oentryp, 0, sizeof(struct vldbentry));
156     strncpy(oentryp->name, uentryp->name, sizeof(oentryp->name));
157     if (uentryp->nServers > OMAXNSERVERS) {
158         /*
159          * The alternative is to store OMAXSERVERS but it's always better
160          * to know what's going on...
161          */
162         return VL_BADSERVER;
163     }
164     for (i = 0; i < uentryp->nServers; i++) {
165         oentryp->serverNumber[i] = uentryp->serverUnique[i];
166         oentryp->serverPartition[i] = uentryp->serverPartition[i];
167         oentryp->serverFlags[i] = uentryp->serverFlags[i];
168     }
169     oentryp->nServers = i;
170     for (i = 0; i < MAXTYPES; i++)
171         oentryp->volumeId[i] = uentryp->volumeId[i];
172     oentryp->cloneId = uentryp->cloneId;
173     oentryp->flags = uentryp->flags;
174     return 0;
175 }
176
177 void
178 nvlentry_to_uvlentry(struct nvldbentry *nentryp,
179                      struct uvldbentry *uentryp)
180 {
181     int i;
182
183     memset(uentryp, 0, sizeof(struct uvldbentry));
184     strncpy(uentryp->name, nentryp->name, sizeof(uentryp->name));
185     for (i = 0; i < nentryp->nServers; i++) {
186         afs_int32 vcode, m_uniq=0;
187         bulkaddrs m_addrs;
188         ListAddrByAttributes m_attrs;
189         afs_int32 m_nentries;
190
191         m_attrs.Mask = VLADDR_IPADDR;
192         m_attrs.ipaddr = nentryp->serverNumber[i];
193         m_nentries = 0;
194         m_addrs.bulkaddrs_val = 0;
195         m_addrs.bulkaddrs_len = 0;
196         vcode =
197             ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
198                                &uentryp->serverNumber[i],
199                                &m_uniq, &m_nentries,
200                                &m_addrs);
201         uentryp->serverUnique[i] = nentryp->serverNumber[i];
202         uentryp->serverPartition[i] = nentryp->serverPartition[i];
203         uentryp->serverFlags[i] = nentryp->serverFlags[i];
204     }
205     uentryp->nServers = nentryp->nServers;
206     for (i = 0; i < MAXTYPES; i++)
207         uentryp->volumeId[i] = nentryp->volumeId[i];
208     uentryp->cloneId = nentryp->cloneId;
209     uentryp->flags = nentryp->flags;
210     uentryp->matchindex = nentryp->matchindex;
211 }
212
213 int
214 uvlentry_to_nvlentry(struct uvldbentry *uentryp,
215                      struct nvldbentry *nentryp)
216 {
217     int i;
218
219     memset(nentryp, 0, sizeof(struct vldbentry));
220     strncpy(nentryp->name, uentryp->name, sizeof(nentryp->name));
221     if (uentryp->nServers > NMAXNSERVERS) {
222         /*
223          * The alternative is to store NMAXSERVERS but it's always better
224          * to know what's going on...
225          */
226         return VL_BADSERVER;
227     }
228     for (i = 0; i < uentryp->nServers; i++) {
229         nentryp->serverNumber[i] = uentryp->serverUnique[i];
230         nentryp->serverPartition[i] = uentryp->serverPartition[i];
231         nentryp->serverFlags[i] = uentryp->serverFlags[i];
232     }
233     nentryp->nServers = i;
234     for (i = 0; i < MAXTYPES; i++)
235         nentryp->volumeId[i] = uentryp->volumeId[i];
236     nentryp->cloneId = uentryp->cloneId;
237     nentryp->flags = uentryp->flags;
238     nentryp->matchindex = uentryp->matchindex;
239     return 0;
240 }
241
242 enum _vlserver_type {
243     vltype_unknown = 0,
244     vltype_old = 1,
245     vltype_new = 2,
246     vltype_uuid = 3
247 };
248
249 static enum _vlserver_type newvlserver = vltype_unknown;
250
251 int
252 VLDB_CreateEntry(struct nvldbentry *entryp)
253 {
254     int code;
255     struct uvldbentry uentry;
256
257     nvlentry_to_uvlentry(entryp, &uentry);
258     code = VLDB_CreateEntryU(&uentry);
259     if (!code)
260         code = uvlentry_to_nvlentry(&uentry, entryp);
261     return code;
262 }
263
264 int
265 VLDB_CreateEntryU(struct uvldbentry *entryp)
266 {
267     struct nvldbentry nentry;
268     int code;
269
270     if (newvlserver == vltype_old) {
271         struct vldbentry oentry;
272       tryold:
273         code = uvlentry_to_ovlentry(entryp, &oentry);
274         if (code)
275             return code;
276         code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
277         return code;
278     }
279
280     code = uvlentry_to_nvlentry(entryp, &nentry);
281     if (code)
282         return code;
283     code = ubik_VL_CreateEntryN(cstruct, 0, &nentry);
284     if (code == RXGEN_OPCODE) {
285         newvlserver = vltype_old;
286         goto tryold;
287     }
288     return code;
289 }
290
291 int
292 VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
293 {
294     int code;
295     struct uvldbentry uentry;
296
297     nvlentry_to_uvlentry(entryp, &uentry);
298     code = VLDB_GetEntryByIDU(volid, voltype, &uentry);
299     if (!code)
300         code = uvlentry_to_nvlentry(&uentry, entryp);
301     return code;
302 }
303
304 int
305 VLDB_GetEntryByIDU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp)
306 {
307     struct nvldbentry nentry;
308     int code;
309
310     if (newvlserver == vltype_old) {
311         struct vldbentry oentry;
312       tryold:
313         code =
314             ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
315         if (!code)
316             ovlentry_to_uvlentry(&oentry, entryp);
317         return code;
318     }
319
320     code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, &nentry);
321     if (code == RXGEN_OPCODE) {
322         newvlserver = vltype_old;
323         goto tryold;
324     }
325     if (!code)
326         nvlentry_to_uvlentry(&nentry, entryp);
327     return code;
328 }
329
330 int
331 VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
332 {
333     int code;
334     struct uvldbentry uentry;
335
336     nvlentry_to_uvlentry(entryp, &uentry);
337     code = VLDB_GetEntryByNameU(namep, &uentry);
338     if (!code)
339         code = uvlentry_to_nvlentry(&uentry, entryp);
340     return code;
341 }
342
343 int
344 VLDB_GetEntryByNameU(char *namep, struct uvldbentry *entryp)
345 {
346     int code;
347
348     if (newvlserver == vltype_old) {
349         struct vldbentry oentry;
350       tryold:
351         code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
352         if (!code)
353             ovlentry_to_uvlentry(&oentry, entryp);
354         return code;
355     }
356     if (newvlserver == vltype_new) {
357         struct nvldbentry nentry;
358       trynew:
359         code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, &nentry);
360         if (code == RXGEN_OPCODE) {
361             newvlserver = vltype_old;
362             goto tryold;
363         }
364         if (!code)
365             nvlentry_to_uvlentry(&nentry, entryp);
366     }
367     code = ubik_VL_GetEntryByNameU(cstruct, 0, namep, entryp);
368     if (newvlserver == vltype_unknown) {
369         if (code == RXGEN_OPCODE) {
370             newvlserver = vltype_new;
371             goto trynew;
372         } else if (!code) {
373             newvlserver = vltype_uuid;
374         }
375     }
376     return code;
377 }
378
379 int
380 VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *nentryp, afs_int32 releasetype)
381 {
382     struct uvldbentry uentry;
383     int code;
384
385     nvlentry_to_uvlentry(nentryp, &uentry);
386     code = VLDB_ReplaceEntryU(volid, voltype, &uentry, releasetype);
387     if (!code)
388         code = uvlentry_to_nvlentry(&uentry, nentryp);
389
390     return code;
391 }
392
393 int
394 VLDB_ReplaceEntryU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp, afs_int32 releasetype)
395 {
396     int code;
397     struct nvldbentry nentry;
398
399     if (newvlserver == vltype_old) {
400         struct vldbentry oentry;
401       tryold:
402         code = uvlentry_to_ovlentry(entryp, &oentry);
403         if (code)
404             return code;
405         code =
406             ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry, releasetype);
407         return code;
408     }
409     code = uvlentry_to_nvlentry(entryp, &nentry);
410     if (code)
411         return code;
412     code = ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, &nentry, releasetype);
413     if (code == RXGEN_OPCODE) {
414         newvlserver = vltype_old;
415             goto tryold;
416     }
417     return code;
418 }
419
420 static void
421 convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
422     int i;
423
424     if (bulk->bulkentries_len == 0)
425         return;
426
427     nbulk->nbulkentries_len = bulk->bulkentries_len;
428     nbulk->nbulkentries_val =
429         xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
430
431     for (i = 0; i < bulk->bulkentries_len; i++) {
432         ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
433                              &nbulk->nbulkentries_val[i]);
434     }
435 }
436
437 static void
438 convertBulkToUBulk(bulkentries *bulk, ubulkentries *ubulk) {
439     int i;
440
441     if (bulk->bulkentries_len == 0)
442         return;
443
444     ubulk->ubulkentries_len = bulk->bulkentries_len;
445     ubulk->ubulkentries_val =
446         xdr_alloc(bulk->bulkentries_len * sizeof(struct uvldbentry));
447     for (i = 0; i < bulk->bulkentries_len; i++) {
448         ovlentry_to_uvlentry(&bulk->bulkentries_val[i],
449                              &ubulk->ubulkentries_val[i]);
450     }
451 }
452
453 static void
454 convertNBulkToUBulk(nbulkentries *nbulk, ubulkentries *ubulk) {
455     int i;
456
457     if (nbulk->nbulkentries_len == 0)
458         return;
459
460     ubulk->ubulkentries_len = nbulk->nbulkentries_len;
461     ubulk->ubulkentries_val =
462         xdr_alloc(nbulk->nbulkentries_len * sizeof(struct uvldbentry));
463     for (i = 0; i < nbulk->nbulkentries_len; i++) {     /* process each entry */
464         nvlentry_to_uvlentry(&nbulk->nbulkentries_val[i],
465                              &ubulk->ubulkentries_val[i]);
466     }
467 }
468
469 int
470 VLDB_ListAttributes(VldbListByAttributes *attrp,
471                     afs_int32 *entriesp,
472                     nbulkentries *blkentriesp)
473 {
474     int code;
475
476     if (newvlserver == vltype_old) {
477         bulkentries arrayEntries;
478       tryold:
479         memset(&arrayEntries, 0, sizeof(arrayEntries));
480         code =
481             ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
482                       &arrayEntries);
483
484         if (code)
485             return code;
486
487         convertBulkToNBulk(&arrayEntries, blkentriesp);
488
489         xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
490         return code;
491     }
492
493     code =
494         ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
495     if (code == RXGEN_OPCODE) {
496         newvlserver = vltype_old;       /* Doesn't support new interface */
497         goto tryold;
498     }
499     return code;
500 }
501
502 int
503 VLDB_ListAttributesU(VldbListByAttributes *attrp,
504                     afs_int32 *entriesp,
505                     ubulkentries *blkentriesp)
506 {
507     nbulkentries narrayEntries;
508     int code;
509
510     if (newvlserver == vltype_old) {
511         bulkentries arrayEntries;
512       tryold:
513         memset(&arrayEntries, 0, sizeof(arrayEntries));
514         code =
515             ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
516                       &arrayEntries);
517         if (code)
518             return code;
519
520         convertBulkToUBulk(&arrayEntries, blkentriesp);
521
522         xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
523         return code;
524     }
525
526     memset(&narrayEntries, 0, sizeof(narrayEntries));
527     code =
528         ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, &narrayEntries);
529     if (code == RXGEN_OPCODE) {
530         newvlserver = vltype_old;       /* Doesn't support new interface */
531         goto tryold;
532     }
533
534     if (code)
535         return code;
536
537     convertNBulkToUBulk(&narrayEntries, blkentriesp);
538
539     xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
540     return code;
541 }
542
543 int
544 VLDB_ListAttributesN2(VldbListByAttributes *attrp,
545                       char *name,
546                       afs_int32 thisindex,
547                       afs_int32 *nentriesp,
548                       nbulkentries *blkentriesp,
549                       afs_int32 *nextindexp)
550 {
551     afs_int32 code = RXGEN_OPCODE;
552
553     if (newvlserver != vltype_old) {
554         code =
555             ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
556                                      thisindex, nentriesp, blkentriesp, nextindexp);
557     }
558     return code;
559 }
560
561 int
562 VLDB_ListAttributesN2U(VldbListByAttributes *attrp,
563                       char *name,
564                       afs_int32 thisindex,
565                       afs_int32 *nentriesp,
566                       ubulkentries *blkentriesp,
567                       afs_int32 *nextindexp)
568 {
569     afs_int32 code = RXGEN_OPCODE;
570
571     if (newvlserver != vltype_old) {
572         nbulkentries narrayEntries;
573
574         memset(&narrayEntries, 0, sizeof(narrayEntries));       /*initialize to hint the stub  to alloc space */
575         code =
576             ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
577                                      thisindex, nentriesp, &narrayEntries, nextindexp);
578         if (code)
579             return code;
580
581         convertNBulkToUBulk(&narrayEntries, blkentriesp);
582
583         xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
584         return code;
585     }
586     return code;
587 }
588
589
590 struct cacheips {
591     afs_uint32 server;
592     afs_int32 count;
593     afs_uint32 addrs[16];
594 };
595 /*
596  * Increase cache size.  This avoids high CPU usage by the vlserver
597  * in environments where there are more than 16 fileservers in the
598  * cell.
599  */
600 #define GETADDRUCACHESIZE             64
601 struct cacheips cacheips[GETADDRUCACHESIZE];
602 int cacheip_index = 0;
603
604 int
605 VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
606 {
607     int code;
608     ListAddrByAttributes attrs;
609     bulkaddrs addrs;
610     afs_uint32 *addrp, f1, f2;
611     afs_int32 i, j, unique, nentries;
612     afsUUID uuid;
613     static int initcache = 0;
614
615     *errorp = 0;
616
617     if (serv1 == serv2)
618         return 1;
619     if (newvlserver == vltype_old ||
620         newvlserver == vltype_new) {
621         return 0;
622     }
623     if (!initcache) {
624         for (i = 0; i < GETADDRUCACHESIZE; i++) {
625             cacheips[i].server = cacheips[i].count = 0;
626         }
627         initcache = 1;
628     }
629
630     /* See if it's cached */
631     for (i = 0; i < GETADDRUCACHESIZE; i++) {
632         f1 = f2 = 0;
633         for (j = 0; j < cacheips[i].count; j++) {
634             if (serv1 == cacheips[i].addrs[j])
635                 f1 = 1;
636             else if (serv2 == cacheips[i].addrs[j])
637                 f2 = 1;
638
639             if (f1 && f2)
640                 return 1;
641         }
642         if (f1 || f2)
643             return 0;
644         if (cacheips[i].server == serv1)
645             return 0;
646     }
647
648     memset(&attrs, 0, sizeof(attrs));
649     attrs.Mask = VLADDR_IPADDR;
650     attrs.ipaddr = serv1;
651     memset(&addrs, 0, sizeof(addrs));
652     memset(&uuid, 0, sizeof(uuid));
653     code =
654         ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
655                   &addrs);
656     if (newvlserver == vltype_unknown) {
657         if (code == RXGEN_OPCODE) {
658             newvlserver = vltype_new;
659             return 0;
660         } else if (!code) {
661             newvlserver = vltype_uuid;
662         }
663     }
664     if (code == VL_NOENT)
665         return 0;
666     if (code) {
667         *errorp = code;
668         return 0;
669     }
670
671     code = 0;
672     if (nentries > GETADDRUCACHESIZE)
673         nentries = GETADDRUCACHESIZE;   /* safety check; should not happen */
674     if (++cacheip_index >= GETADDRUCACHESIZE)
675         cacheip_index = 0;
676     cacheips[cacheip_index].server = serv1;
677     cacheips[cacheip_index].count = nentries;
678     addrp = addrs.bulkaddrs_val;
679     for (i = 0; i < nentries; i++, addrp++) {
680         cacheips[cacheip_index].addrs[i] = *addrp;
681         if (serv2 == *addrp) {
682             code = 1;
683         }
684     }
685     return code;
686 }
687
688
689 /*
690   Set encryption.  If 'cryptflag' is nonzero, encrpytion is turned on
691   for authenticated connections; if zero, encryption is turned off.
692   Calling this function always results in a level of at least rxkad_auth;
693   to get a rxkad_clear connection, simply don't call this.
694 */
695 void
696 vsu_SetCrypt(int cryptflag)
697 {
698     if (cryptflag) {
699         vsu_rxkad_level = rxkad_crypt;
700     } else {
701         vsu_rxkad_level = rxkad_auth;
702     }
703 }
704
705
706 /*
707   Get the appropriate type of ubik client structure out from the system.
708 */
709 afs_int32
710 vsu_ClientInit(int noAuthFlag, const char *confDir, char *cellName, afs_int32 sauth,
711                struct ubik_client **uclientp,
712                int (*secproc)(struct rx_securityClass *, afs_int32))
713 {
714     return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp,
715                            secproc, "vsu_ClientInit", vsu_rxkad_level,
716                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
717                            0, 0, USER_SERVICE_ID);
718 }
719
720
721 /*extract the name of volume <name> without readonly or backup suffixes
722  * and return the result as <rname>.
723  */
724 int
725 vsu_ExtractName(char rname[], char name[])
726 {
727     char sname[VOLSER_OLDMAXVOLNAME + 1];
728     size_t total;
729
730     strncpy(sname, name, sizeof(sname));
731     sname[sizeof(sname) - 1] = '\0';
732     total = strlen(sname);
733     if (!strcmp(&sname[total - 9], ".readonly")) {
734         /*discard the last 8 chars */
735         sname[total - 9] = '\0';
736         strcpy(rname, sname);
737         return 0;
738     } else if (!strcmp(&sname[total - 7], ".backup")) {
739         /*discard last 6 chars */
740         sname[total - 7] = '\0';
741         strcpy(rname, sname);
742         return 0;
743     } else {
744         strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
745         rname[VOLSER_OLDMAXVOLNAME] = '\0';
746         return -1;
747     }
748 }
749
750 /* returns 0 if failed */
751 afs_uint32
752 vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
753 {
754     char volname[VOLSER_OLDMAXVOLNAME + 1];
755     struct uvldbentry entry;
756     afs_int32 vcode = 0;
757     size_t total;
758
759     *errp = 0;
760
761     if (isdigit(astring[0])) {
762         char *end;
763         afs_uint32 result;
764         result = strtoul(astring, &end, 10);
765         if (result != UINT_MAX && *end == '\0')
766             return result;
767     }
768
769     /* It was not a volume number but something else */
770     total = strlen(astring);
771     vsu_ExtractName(volname, astring);
772     vcode = VLDB_GetEntryByNameU(volname, &entry);
773     if (!vcode) {
774       if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
775         return entry.volumeId[ROVOL];
776       else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
777         return entry.volumeId[BACKVOL];
778       else
779         return (entry.volumeId[RWVOL]);
780     }
781     *errp = vcode;
782     return 0;           /* can't find volume */
783 }