tweak uvldb-making function
[openafs.git] / src / volser / vsutils.c
index 9f936fd..e6cfb79 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID("$Header$");
+#include <roken.h>
 
 #include <afs/stds.h>
+#include <string.h>
+#include <ctype.h>
 #ifdef AFS_NT40_ENV
 #include <fcntl.h>
 #include <winsock2.h>
@@ -26,6 +28,7 @@ RCSID("$Header$");
 #ifdef AFS_AIX_ENV
 #include <sys/statfs.h>
 #endif
+
 #include <errno.h>
 #include <lock.h>
 #include <rx/xdr.h>
@@ -33,7 +36,6 @@ RCSID("$Header$");
 #include <rx/rx_globals.h>
 #include <afs/nfs.h>
 #include <afs/vlserver.h>
-#include <afs/auth.h>
 #include <afs/cellconfig.h>
 #include <afs/keys.h>
 #include <ubik.h>
@@ -44,40 +46,49 @@ RCSID("$Header$");
 #include "volint.h"
 #include "lockdata.h"
 
+#include "vsutils_prototypes.h"
+
 struct ubik_client *cstruct;
-extern int VL_CreateEntry(), VL_CreateEntryN();
-extern int VL_GetEntryByID(), VL_GetEntryByIDN();
-extern int VL_GetEntryByNameO(), VL_GetEntryByNameN();
-extern int VL_ReplaceEntry(), VL_ReplaceEntryN();
-extern int VL_ListAttributes(), VL_ListAttributesN(), VL_ListAttributesN2();
-
-static void ovlentry_to_nvlentry(oentryp, nentryp)
-    struct vldbentry *oentryp;
-    struct nvldbentry *nentryp;
+static rxkad_level vsu_rxkad_level = rxkad_clear;
+
+static void
+ovlentry_to_nvlentry(struct vldbentry *oentryp,
+                     struct nvldbentry *nentryp)
 {
-    register int i;
+    int i;
 
-    bzero(nentryp, sizeof(struct nvldbentry));
+    memset(nentryp, 0, sizeof(struct nvldbentry));
     strncpy(nentryp->name, oentryp->name, sizeof(nentryp->name));
-    for (i=0; i < oentryp->nServers; i++) {
-       nentryp->serverNumber[i] = oentryp->serverNumber[i];
+    for (i = 0; i < oentryp->nServers; i++) {
+        bulkaddrs m_addrs;
+        ListAddrByAttributes m_attrs;
+        afs_int32 m_nentries;
+
+        m_attrs.Mask = VLADDR_IPADDR;
+        m_attrs.ipaddr = oentryp->serverNumber[i];
+        m_nentries = 0;
+        m_addrs.bulkaddrs_val = 0;
+        m_addrs.bulkaddrs_len = 0;
+        nentryp->serverNumber[i] = oentryp->serverNumber[i];
        nentryp->serverPartition[i] = oentryp->serverPartition[i];
        nentryp->serverFlags[i] = oentryp->serverFlags[i];
     }
     nentryp->nServers = oentryp->nServers;
-    for (i=0; i<MAXTYPES; i++)
+    for (i = 0; i < MAXTYPES; i++)
        nentryp->volumeId[i] = oentryp->volumeId[i];
     nentryp->cloneId = oentryp->cloneId;
     nentryp->flags = oentryp->flags;
 }
 
-static nvlentry_to_ovlentry(nentryp, oentryp)
-    struct nvldbentry *nentryp;
-    struct vldbentry *oentryp;
+#if 0
+/* It is here for when we need it.  Not currently used. */
+static int
+nvlentry_to_ovlentry(struct nvldbentry *nentryp,
+                     struct vldbentry *oentryp)
 {
-    register int i;
+    int i;
 
-    bzero(oentryp, sizeof(struct vldbentry));
+    memset(oentryp, 0, sizeof(struct vldbentry));
     strncpy(oentryp->name, nentryp->name, sizeof(oentryp->name));
     if (nentryp->nServers > OMAXNSERVERS) {
        /*
@@ -86,238 +97,610 @@ static nvlentry_to_ovlentry(nentryp, oentryp)
         */
        return VL_BADSERVER;
     }
-    for (i=0; i < nentryp->nServers; i++) {
+    for (i = 0; i < nentryp->nServers; i++) {
        oentryp->serverNumber[i] = nentryp->serverNumber[i];
        oentryp->serverPartition[i] = nentryp->serverPartition[i];
        oentryp->serverFlags[i] = nentryp->serverFlags[i];
     }
     oentryp->nServers = i;
-    for (i=0; i<MAXTYPES; i++)
+    for (i = 0; i < MAXTYPES; i++)
        oentryp->volumeId[i] = nentryp->volumeId[i];
     oentryp->cloneId = nentryp->cloneId;
     oentryp->flags = nentryp->flags;
     return 0;
 }
+#endif
+
+static void
+ovlentry_to_uvlentry(struct vldbentry *oentryp,
+                     struct uvldbentry *uentryp)
+{
+    int i;
+
+    memset(uentryp, 0, sizeof(struct uvldbentry));
+    strncpy(uentryp->name, oentryp->name, sizeof(uentryp->name));
+    for (i = 0; i < oentryp->nServers; i++) {
+        afs_int32 vcode, m_uniq=0;
+        bulkaddrs m_addrs;
+        ListAddrByAttributes m_attrs;
+        afs_int32 m_nentries;
+
+        m_attrs.Mask = VLADDR_IPADDR;
+        m_attrs.ipaddr = oentryp->serverNumber[i];
+        m_nentries = 0;
+        m_addrs.bulkaddrs_val = 0;
+        m_addrs.bulkaddrs_len = 0;
+        vcode =
+            ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
+                               &uentryp->serverNumber[i],
+                               &m_uniq, &m_nentries,
+                               &m_addrs);
+        uentryp->serverUnique[i] = oentryp->serverNumber[i];
+       uentryp->serverPartition[i] = oentryp->serverPartition[i];
+       uentryp->serverFlags[i] = oentryp->serverFlags[i];
+    }
+    uentryp->nServers = oentryp->nServers;
+    for (i = 0; i < MAXTYPES; i++)
+       uentryp->volumeId[i] = oentryp->volumeId[i];
+    uentryp->cloneId = oentryp->cloneId;
+    uentryp->flags = oentryp->flags;
+}
+
+static int
+uvlentry_to_ovlentry(struct uvldbentry *uentryp,
+                     struct vldbentry *oentryp)
+{
+    int i;
+
+    memset(oentryp, 0, sizeof(struct vldbentry));
+    strncpy(oentryp->name, uentryp->name, sizeof(oentryp->name));
+    if (uentryp->nServers > OMAXNSERVERS) {
+       /*
+        * The alternative is to store OMAXSERVERS but it's always better
+        * to know what's going on...
+        */
+       return VL_BADSERVER;
+    }
+    for (i = 0; i < uentryp->nServers; i++) {
+       oentryp->serverNumber[i] = uentryp->serverUnique[i];
+       oentryp->serverPartition[i] = uentryp->serverPartition[i];
+       oentryp->serverFlags[i] = uentryp->serverFlags[i];
+    }
+    oentryp->nServers = i;
+    for (i = 0; i < MAXTYPES; i++)
+       oentryp->volumeId[i] = uentryp->volumeId[i];
+    oentryp->cloneId = uentryp->cloneId;
+    oentryp->flags = uentryp->flags;
+    return 0;
+}
+
+void
+nvlentry_to_uvlentry(struct nvldbentry *nentryp,
+                     struct uvldbentry *uentryp)
+{
+    int i;
+
+    memset(uentryp, 0, sizeof(struct uvldbentry));
+    strncpy(uentryp->name, nentryp->name, sizeof(uentryp->name));
+    for (i = 0; i < nentryp->nServers; i++) {
+        afs_int32 vcode, m_uniq=0;
+        bulkaddrs m_addrs;
+        ListAddrByAttributes m_attrs;
+        afs_int32 m_nentries;
+
+        m_attrs.Mask = VLADDR_IPADDR;
+        m_attrs.ipaddr = nentryp->serverNumber[i];
+        m_nentries = 0;
+        m_addrs.bulkaddrs_val = 0;
+        m_addrs.bulkaddrs_len = 0;
+        vcode =
+            ubik_VL_GetAddrsU(cstruct, 0, &m_attrs,
+                               &uentryp->serverNumber[i],
+                               &m_uniq, &m_nentries,
+                               &m_addrs);
+       uentryp->serverUnique[i] = m_uniq;
+       uentryp->serverPartition[i] = nentryp->serverPartition[i];
+       uentryp->serverFlags[i] = nentryp->serverFlags[i];
+       uentryp->serverFlags[i] |= VLSERVER_FLAG_UUID;
+    }
+    uentryp->nServers = nentryp->nServers;
+    for (i = 0; i < MAXTYPES; i++)
+       uentryp->volumeId[i] = nentryp->volumeId[i];
+    uentryp->cloneId = nentryp->cloneId;
+    uentryp->flags = nentryp->flags;
+    uentryp->matchindex = nentryp->matchindex;
+}
+
+int
+uvlentry_to_nvlentry(struct uvldbentry *uentryp,
+                     struct nvldbentry *nentryp)
+{
+    int i;
+
+    memset(nentryp, 0, sizeof(struct vldbentry));
+    strncpy(nentryp->name, uentryp->name, sizeof(nentryp->name));
+    if (uentryp->nServers > NMAXNSERVERS) {
+       /*
+        * The alternative is to store NMAXSERVERS but it's always better
+        * to know what's going on...
+        */
+       return VL_BADSERVER;
+    }
+    for (i = 0; i < uentryp->nServers; i++) {
+       nentryp->serverNumber[i] = uentryp->serverUnique[i];
+       nentryp->serverPartition[i] = uentryp->serverPartition[i];
+       nentryp->serverFlags[i] = uentryp->serverFlags[i];
+    }
+    nentryp->nServers = i;
+    for (i = 0; i < MAXTYPES; i++)
+       nentryp->volumeId[i] = uentryp->volumeId[i];
+    nentryp->cloneId = uentryp->cloneId;
+    nentryp->flags = uentryp->flags;
+    nentryp->matchindex = uentryp->matchindex;
+    return 0;
+}
+
+enum _vlserver_type {
+    vltype_unknown = 0,
+    vltype_old = 1,
+    vltype_new = 2,
+    vltype_uuid = 3
+};
+
+static enum _vlserver_type newvlserver = vltype_unknown;
 
-static int newvlserver=0;
+int
+VLDB_CreateEntry(struct nvldbentry *entryp)
+{
+    int code;
+    struct uvldbentry uentry;
+
+    nvlentry_to_uvlentry(entryp, &uentry);
+    code = VLDB_CreateEntryU(&uentry);
+    if (!code)
+        code = uvlentry_to_nvlentry(&uentry, entryp);
+    return code;
+}
 
-VLDB_CreateEntry(entryp)
-    struct nvldbentry *entryp;
+int
+VLDB_CreateEntryU(struct uvldbentry *entryp)
 {
-    struct vldbentry oentry;
-    register int code, (*nproc)();
+    struct nvldbentry nentry;
+    int code;
 
-    if (newvlserver == 1) {
-tryold:
-       code = nvlentry_to_ovlentry(entryp, &oentry);
+    if (newvlserver == vltype_old) {
+        struct vldbentry oentry;
+      tryold:
+       code = uvlentry_to_ovlentry(entryp, &oentry);
        if (code)
            return code;
-       code = ubik_Call(VL_CreateEntry, cstruct, 0, &oentry);
+       code = ubik_VL_CreateEntry(cstruct, 0, &oentry);
        return code;
     }
-    code = ubik_Call(VL_CreateEntryN, cstruct, 0, entryp);
-    if (!newvlserver) {
-       if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-           goto tryold;
-       } else if (!code) {
-           newvlserver = 2;
-       }
+
+    code = uvlentry_to_nvlentry(entryp, &nentry);
+    if (code)
+        return code;
+    code = ubik_VL_CreateEntryN(cstruct, 0, &nentry);
+    if (code == RXGEN_OPCODE) {
+        newvlserver = vltype_old;
+        goto tryold;
     }
     return code;
 }
 
-VLDB_GetEntryByID(volid, voltype, entryp)
-    afs_int32 volid, voltype;
-    struct nvldbentry *entryp;
+int
+VLDB_GetEntryByID(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *entryp)
 {
-    struct vldbentry oentry;
-    register int code, (*nproc)();
+    int code;
+    struct uvldbentry uentry;
+
+    nvlentry_to_uvlentry(entryp, &uentry);
+    code = VLDB_GetEntryByIDU(volid, voltype, &uentry);
+    if (!code)
+        code = uvlentry_to_nvlentry(&uentry, entryp);
+    return code;
+}
 
-    if (newvlserver == 1) {
-tryold:
-       code = ubik_Call(VL_GetEntryByID, cstruct, 0, volid, voltype, &oentry);
+int
+VLDB_GetEntryByIDU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp)
+{
+    struct nvldbentry nentry;
+    int code;
+
+    if (newvlserver == vltype_old) {
+        struct vldbentry oentry;
+      tryold:
+       code =
+           ubik_VL_GetEntryByID(cstruct, 0, volid, voltype, &oentry);
        if (!code)
-           ovlentry_to_nvlentry(&oentry, entryp);
+           ovlentry_to_uvlentry(&oentry, entryp);
        return code;
     }
-    code = ubik_Call(VL_GetEntryByIDN, cstruct, 0, volid, voltype, entryp);
-    if (!newvlserver) {
-       if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-           goto tryold;
-       } else if (!code) {
-           newvlserver = 2;
-       }
+
+    code = ubik_VL_GetEntryByIDN(cstruct, 0, volid, voltype, &nentry);
+    if (code == RXGEN_OPCODE) {
+        newvlserver = vltype_old;
+        goto tryold;
     }
+    if (!code)
+        nvlentry_to_uvlentry(&nentry, entryp);
+    return code;
+}
+
+int
+VLDB_GetEntryByName(char *namep, struct nvldbentry *entryp)
+{
+    int code;
+    struct uvldbentry uentry;
+
+    nvlentry_to_uvlentry(entryp, &uentry);
+    code = VLDB_GetEntryByNameU(namep, &uentry);
+    if (!code)
+        code = uvlentry_to_nvlentry(&uentry, entryp);
     return code;
 }
 
-VLDB_GetEntryByName(namep, entryp)
-    char *namep;
-    struct nvldbentry *entryp;
+int
+VLDB_GetEntryByNameU(char *namep, struct uvldbentry *entryp)
 {
-    struct vldbentry oentry;
-    register int code, (*nproc)();
+    int code;
 
-    if (newvlserver == 1) {
-tryold:
-       code = ubik_Call(VL_GetEntryByNameO, cstruct, 0, namep, &oentry);
+    if (newvlserver == vltype_old) {
+        struct vldbentry oentry;
+      tryold:
+       code = ubik_VL_GetEntryByNameO(cstruct, 0, namep, &oentry);
        if (!code)
-           ovlentry_to_nvlentry(&oentry, entryp);
+           ovlentry_to_uvlentry(&oentry, entryp);
        return code;
     }
-    code = ubik_Call(VL_GetEntryByNameN, cstruct, 0, namep, entryp);
-    if (!newvlserver) {
+    if (newvlserver == vltype_new) {
+        struct nvldbentry nentry;
+      trynew:
+        code = ubik_VL_GetEntryByNameN(cstruct, 0, namep, &nentry);
+        if (code == RXGEN_OPCODE) {
+            newvlserver = vltype_old;
+            goto tryold;
+        }
+       if (!code)
+           nvlentry_to_uvlentry(&nentry, entryp);
+    }
+    code = ubik_VL_GetEntryByNameU(cstruct, 0, namep, entryp);
+    if (newvlserver == vltype_unknown) {
        if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-           goto tryold;
+           newvlserver = vltype_new;
+           goto trynew;
        } else if (!code) {
-           newvlserver = 2;
+           newvlserver = vltype_uuid;
        }
     }
     return code;
 }
 
-VLDB_ReplaceEntry(volid, voltype, entryp, releasetype)
-    afs_int32 volid, voltype, releasetype;
-    struct nvldbentry *entryp;
+int
+VLDB_ReplaceEntry(afs_uint32 volid, afs_int32 voltype, struct nvldbentry *nentryp, afs_int32 releasetype)
+{
+    struct uvldbentry uentry;
+    int code;
+
+    nvlentry_to_uvlentry(nentryp, &uentry);
+    code = VLDB_ReplaceEntryU(volid, voltype, &uentry, releasetype);
+    if (!code)
+        code = uvlentry_to_nvlentry(&uentry, nentryp);
+
+    return code;
+}
+
+int
+VLDB_ReplaceEntryU(afs_uint32 volid, afs_int32 voltype, struct uvldbentry *entryp, afs_int32 releasetype)
 {
-    struct vldbentry oentry;
-    register int code, (*nproc)();
+    int code;
+    struct nvldbentry nentry;
 
-    if (newvlserver == 1) {
-tryold:
-       code = nvlentry_to_ovlentry(entryp, &oentry);
+    if (newvlserver == vltype_old) {
+        struct vldbentry oentry;
+      tryold:
+       code = uvlentry_to_ovlentry(entryp, &oentry);
        if (code)
            return code;
-       code = ubik_Call(VL_ReplaceEntry, cstruct, 0, volid, voltype, &oentry, releasetype);
+       code =
+           ubik_VL_ReplaceEntry(cstruct, 0, volid, voltype, &oentry, releasetype);
        return code;
     }
-    code = ubik_Call(VL_ReplaceEntryN, cstruct, 0, volid, voltype, entryp, releasetype);
-    if (!newvlserver) {
-       if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-           goto tryold;
-       } else if (!code) {
-           newvlserver = 2;
-       }
+    code = uvlentry_to_nvlentry(entryp, &nentry);
+    if (code)
+        return code;
+    code = ubik_VL_ReplaceEntryN(cstruct, 0, volid, voltype, &nentry, releasetype);
+    if (code == RXGEN_OPCODE) {
+        newvlserver = vltype_old;
+            goto tryold;
     }
     return code;
 }
 
+static void
+convertBulkToNBulk(bulkentries *bulk, nbulkentries *nbulk) {
+    int i;
+
+    if (bulk->bulkentries_len == 0)
+       return;
 
+    nbulk->nbulkentries_len = bulk->bulkentries_len;
+    nbulk->nbulkentries_val =
+       xdr_alloc(bulk->bulkentries_len * sizeof(struct nvldbentry));
 
-VLDB_ListAttributes(attrp, entriesp, blkentriesp)
-    VldbListByAttributes *attrp;     
-    afs_int32 *entriesp;
-    nbulkentries *blkentriesp;
+    for (i = 0; i < bulk->bulkentries_len; i++) {
+       ovlentry_to_nvlentry(&bulk->bulkentries_val[i],
+                            &nbulk->nbulkentries_val[i]);
+    }
+}
+
+static void
+convertBulkToUBulk(bulkentries *bulk, ubulkentries *ubulk) {
+    int i;
+
+    if (bulk->bulkentries_len == 0)
+       return;
+
+    ubulk->ubulkentries_len = bulk->bulkentries_len;
+    ubulk->ubulkentries_val =
+       xdr_alloc(bulk->bulkentries_len * sizeof(struct uvldbentry));
+    for (i = 0; i < bulk->bulkentries_len; i++) {
+       ovlentry_to_uvlentry(&bulk->bulkentries_val[i],
+                            &ubulk->ubulkentries_val[i]);
+    }
+}
+
+static void
+convertNBulkToUBulk(nbulkentries *nbulk, ubulkentries *ubulk) {
+    int i;
+
+    if (nbulk->nbulkentries_len == 0)
+       return;
+
+    ubulk->ubulkentries_len = nbulk->nbulkentries_len;
+    ubulk->ubulkentries_val =
+        xdr_alloc(nbulk->nbulkentries_len * sizeof(struct uvldbentry));
+    for (i = 0; i < nbulk->nbulkentries_len; i++) {    /* process each entry */
+        nvlentry_to_uvlentry(&nbulk->nbulkentries_val[i],
+                             &ubulk->ubulkentries_val[i]);
+    }
+}
+
+int
+VLDB_ListAttributes(VldbListByAttributes *attrp,
+                    afs_int32 *entriesp,
+                    nbulkentries *blkentriesp)
 {
-    bulkentries arrayEntries;
-    register int code, i;
-
-    if (newvlserver == 1) {
-tryold:
-       bzero(&arrayEntries, sizeof(arrayEntries)); /*initialize to hint the stub  to alloc space */
-       code = ubik_Call(VL_ListAttributes, cstruct, 0, attrp, entriesp, &arrayEntries);
-       if (!code) {
-           blkentriesp->nbulkentries_val = (nvldbentry *)malloc(*entriesp * sizeof(struct nvldbentry));
-           for (i = 0; i < *entriesp; i++) {   /* process each entry */
-               ovlentry_to_nvlentry(&arrayEntries.bulkentries_val[i], &blkentriesp->nbulkentries_val[i]);              
-           }
-       }
-       if (arrayEntries.bulkentries_val) free(arrayEntries.bulkentries_val);
+    int code;
+
+    if (newvlserver == vltype_old) {
+        bulkentries arrayEntries;
+      tryold:
+       memset(&arrayEntries, 0, sizeof(arrayEntries));
+       code =
+           ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
+                     &arrayEntries);
+
+       if (code)
+           return code;
+
+       /* Ensure the number of entries claimed matches the no. returned */
+       if (*entriesp < 0)
+           *entriesp = 0;
+       if (*entriesp > arrayEntries.bulkentries_len)
+           *entriesp = arrayEntries.bulkentries_len;
+
+       convertBulkToNBulk(&arrayEntries, blkentriesp);
+
+       xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
        return code;
     }
-    code = ubik_Call(VL_ListAttributesN, cstruct, 0, attrp, entriesp, blkentriesp);
-    if (!newvlserver) {
-       if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-           goto tryold;
-       } else if (!code) {
-           newvlserver = 2;
-       }
+
+    code =
+        ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, blkentriesp);
+    if (code == RXGEN_OPCODE) {
+        newvlserver = vltype_old;      /* Doesn't support new interface */
+        goto tryold;
+    }
+
+    if (code)
+       return code;
+
+    /* Ensure the number of entries claimed matches the no. returned */
+    if (*entriesp < 0)
+       *entriesp = 0;
+    if (*entriesp > blkentriesp->nbulkentries_len)
+       *entriesp = blkentriesp->nbulkentries_len;
+
+    return code;
+}
+
+int
+VLDB_ListAttributesU(VldbListByAttributes *attrp,
+                    afs_int32 *entriesp,
+                    ubulkentries *blkentriesp)
+{
+    nbulkentries narrayEntries;
+    int code;
+
+    if (newvlserver == vltype_old) {
+        bulkentries arrayEntries;
+      tryold:
+       memset(&arrayEntries, 0, sizeof(arrayEntries));
+       code =
+           ubik_VL_ListAttributes(cstruct, 0, attrp, entriesp,
+                     &arrayEntries);
+       if (code)
+           return code;
+
+       /* Ensure the number of entries claimed matches the no. returned */
+       if (*entriesp < 0)
+           *entriesp = 0;
+       if (*entriesp > arrayEntries.bulkentries_len)
+           *entriesp = arrayEntries.bulkentries_len;
+
+       convertBulkToUBulk(&arrayEntries, blkentriesp);
+
+       xdr_free((xdrproc_t) xdr_bulkentries, &arrayEntries);
+       return code;
+    }
+
+    memset(&narrayEntries, 0, sizeof(narrayEntries));
+    code =
+        ubik_VL_ListAttributesN(cstruct, 0, attrp, entriesp, &narrayEntries);
+    if (code == RXGEN_OPCODE) {
+        newvlserver = vltype_old;      /* Doesn't support new interface */
+        goto tryold;
+    }
+    if (code)
+       return code;
+
+    /* Ensure the number of entries claimed matches the no. returned */
+    if (*entriesp < 0)
+       *entriesp = 0;
+    if (*entriesp > narrayEntries.nbulkentries_len)
+       *entriesp = narrayEntries.nbulkentries_len;
+
+    convertNBulkToUBulk(&narrayEntries, blkentriesp);
+
+    xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
+    return code;
+}
+
+int
+VLDB_ListAttributesN2(VldbListByAttributes *attrp,
+                      char *name,
+                      afs_int32 thisindex,
+                      afs_int32 *nentriesp,
+                      nbulkentries *blkentriesp,
+                      afs_int32 *nextindexp)
+{
+    afs_int32 code = RXGEN_OPCODE;
+
+    if (newvlserver != vltype_old) {
+        code =
+            ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
+                                     thisindex, nentriesp, blkentriesp, nextindexp);
+       if (code)
+           return code;
+
+       /* Ensure the number of entries claimed matches the no. returned */
+       if (*nentriesp < 0)
+           *nentriesp = 0;
+       if (*nentriesp > blkentriesp->nbulkentries_len)
+           *nentriesp = blkentriesp->nbulkentries_len;
     }
     return code;
 }
 
-VLDB_ListAttributesN2(attrp, name, thisindex, nentriesp, blkentriesp, nextindexp)
-  VldbListByAttributes *attrp;
-  char                 *name;
-  afs_int32                thisindex;
-  afs_int32                *nentriesp;
-  nbulkentries         *blkentriesp;
-  afs_int32                *nextindexp;
+int
+VLDB_ListAttributesN2U(VldbListByAttributes *attrp,
+                      char *name,
+                      afs_int32 thisindex,
+                      afs_int32 *nentriesp,
+                      ubulkentries *blkentriesp,
+                      afs_int32 *nextindexp)
 {
-  afs_int32 code;
+    afs_int32 code = RXGEN_OPCODE;
+
+    if (newvlserver != vltype_old) {
+        nbulkentries narrayEntries;
+
+       memset(&narrayEntries, 0, sizeof(narrayEntries));       /*initialize to hint the stub  to alloc space */
+        code =
+            ubik_VL_ListAttributesN2(cstruct, 0, attrp, (name ? name : ""),
+                                     thisindex, nentriesp, &narrayEntries, nextindexp);
+        if (code)
+           return code;
+
+       /* Ensure the number of entries claimed matches the no. returned */
+       if (*nentriesp < 0)
+           *nentriesp = 0;
+       if (*nentriesp > narrayEntries.nbulkentries_len)
+           *nentriesp = narrayEntries.nbulkentries_len;
 
-  code = ubik_Call(VL_ListAttributesN2, cstruct, 0, 
-                  attrp, (name?name:""), thisindex, 
-                  nentriesp, blkentriesp, nextindexp);
-  return code;
+       convertNBulkToUBulk(&narrayEntries, blkentriesp);
+
+       xdr_free((xdrproc_t) xdr_bulkentries, &narrayEntries);
+       return code;
+    }
+    return code;
 }
 
 
-static int vlserverv4=-1;
 struct cacheips {
-    afs_int32 server;
+    afs_uint32 server;
     afs_int32 count;
     afs_uint32 addrs[16];
 };
-struct cacheips cacheips[16];
-int cacheip_index=0;
-extern int VL_GetAddrsU();
-VLDB_IsSameAddrs(serv1, serv2, errorp)
-    afs_int32 serv1, serv2, *errorp;
+/*
+ * Increase cache size.  This avoids high CPU usage by the vlserver
+ * in environments where there are more than 16 fileservers in the
+ * cell.
+ */
+#define GETADDRUCACHESIZE             64
+struct cacheips cacheips[GETADDRUCACHESIZE];
+int cacheip_index = 0;
+
+int
+VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
 {
-    struct vldbentry oentry;
-    register int code, (*nproc)();
+    int code;
     ListAddrByAttributes attrs;
     bulkaddrs addrs;
-    afs_uint32 *addrp, nentries,  unique, i, j, f1, f2;
+    afs_uint32 *addrp, f1, f2;
+    afs_int32 i, j, unique, nentries;
     afsUUID uuid;
     static int initcache = 0;
 
     *errorp = 0;
 
-    if (serv1 == serv2)   
+    if (serv1 == serv2)
        return 1;
-    if (vlserverv4 == 1) {
+    if (newvlserver == vltype_old ||
+        newvlserver == vltype_new) {
        return 0;
     }
     if (!initcache) {
-       for (i=0; i<16; i++) {
-          cacheips[i].server = cacheips[i].count = 0;
+       for (i = 0; i < GETADDRUCACHESIZE; i++) {
+           cacheips[i].server = cacheips[i].count = 0;
        }
        initcache = 1;
     }
 
     /* See if it's cached */
-    for (i=0; i<16; i++) {
-       f1 = f2 = 0;
-       for (j=0; j < cacheips[i].count; j++) {
-         if      (serv1 == cacheips[i].addrs[j]) f1 = 1;
-         else if (serv2 == cacheips[i].addrs[j]) f2 = 1;
-
-         if (f1 && f2)
-            return 1;
-       }       
-       if (f1 || f2)
-         return 0;
-  }
-
-    bzero(&attrs, sizeof(attrs));
+    for (i = 0; i < GETADDRUCACHESIZE; i++) {
+       f1 = f2 = 0;
+       for (j = 0; j < cacheips[i].count; j++) {
+           if (serv1 == cacheips[i].addrs[j])
+               f1 = 1;
+           else if (serv2 == cacheips[i].addrs[j])
+               f2 = 1;
+
+           if (f1 && f2)
+               return 1;
+       }
+       if (f1 || f2)
+           return 0;
+       if (cacheips[i].server == serv1)
+           return 0;
+    }
+
+    memset(&attrs, 0, sizeof(attrs));
     attrs.Mask = VLADDR_IPADDR;
     attrs.ipaddr = serv1;
-    bzero(&addrs, sizeof(addrs));
-    bzero(&uuid, sizeof(uuid));
-    code = ubik_Call(VL_GetAddrsU, cstruct, 0, &attrs, &uuid, &unique, &nentries, &addrs);
-    if (vlserverv4 == -1) {
+    memset(&addrs, 0, sizeof(addrs));
+    memset(&uuid, 0, sizeof(uuid));
+    code =
+       ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid, &unique, &nentries,
+                 &addrs);
+    if (newvlserver == vltype_unknown) {
        if (code == RXGEN_OPCODE) {
-           vlserverv4 = 1;     /* Doesn't support new interface */
+           newvlserver = vltype_new;
            return 0;
        } else if (!code) {
-           vlserverv4 = 2;
+           newvlserver = vltype_uuid;
        }
     }
     if (code == VL_NOENT)
@@ -328,11 +711,14 @@ VLDB_IsSameAddrs(serv1, serv2, errorp)
     }
 
     code = 0;
-    if (++cacheip_index >= 16) cacheip_index = 0;
+    if (nentries > GETADDRUCACHESIZE)
+       nentries = GETADDRUCACHESIZE;   /* safety check; should not happen */
+    if (++cacheip_index >= GETADDRUCACHESIZE)
+       cacheip_index = 0;
     cacheips[cacheip_index].server = serv1;
     cacheips[cacheip_index].count = nentries;
     addrp = addrs.bulkaddrs_val;
-    for (i=0; i<nentries; i++, addrp++) {
+    for (i = 0; i < nentries; i++, addrp++) {
        cacheips[cacheip_index].addrs[i] = *addrp;
        if (serv2 == *addrp) {
            code = 1;
@@ -342,245 +728,98 @@ VLDB_IsSameAddrs(serv1, serv2, errorp)
 }
 
 
-#ifdef notdef
-afs_int32 subik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)
-    register struct ubik_client *aclient;
-    int (*aproc)();
-    afs_int32 aflags;
-    afs_int32 p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16;
+/*
+  Set encryption.  If 'cryptflag' is nonzero, encrpytion is turned on
+  for authenticated connections; if zero, encryption is turned off.
+  Calling this function always results in a level of at least rxkad_auth;
+  to get a rxkad_clear connection, simply don't call this.
+*/
+void
+vsu_SetCrypt(int cryptflag)
 {
-    struct vldbentry vldbentry;
-    register int code, (*nproc)();
-
-    if (newvlserver == 1) {
-    }
-    code = ubik_Call(aproc, aclient, aflags, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16);
-    if (!newvlserver) {
-       if (code == RXGEN_OPCODE) {
-           newvlserver = 1;    /* Doesn't support new interface */
-       } else if (!code) {
-           newvlserver = 2;
-       }
+    if (cryptflag) {
+       vsu_rxkad_level = rxkad_crypt;
+    } else {
+       vsu_rxkad_level = rxkad_auth;
     }
 }
-#endif /* notdef */
 
 
 /*
   Get the appropriate type of ubik client structure out from the system.
 */
-afs_int32 vsu_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp, secproc)
-    int noAuthFlag;
-    int (*secproc)();
-    char *cellName;
-    struct ubik_client **uclientp;
-    char *confDir;
-    afs_int32 sauth;
+afs_int32
+vsu_ClientInit(int noAuthFlag, const char *confDir, char *cellName, afs_int32 sauth,
+               struct ubik_client **uclientp,
+              int (*secproc)(struct rx_securityClass *, afs_int32))
 {
-    afs_int32 code, scIndex, i;
-    struct afsconf_cell info;
-    struct afsconf_dir *tdir;
-    struct ktc_principal sname;
-    struct ktc_token ttoken;
-    struct rx_securityClass *sc;
-    static struct rx_connection *serverconns[VLDB_MAXSERVERS];
-    char cellstr[64];
-
-
-    code = rx_Init(0);
-    if (code) {
-        fprintf(STDERR,"vsu_ClientInit: could not initialize rx.\n");
-        return code;
-    }
-    rx_SetRxDeadTime(90);
-
-    if (sauth) {  /* -localauth */
-        tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
-        if (!tdir) {
-            fprintf(STDERR, "vsu_ClientInit: Could not process files in configuration directory (%s).\n",
-                    AFSDIR_SERVER_ETC_DIRPATH);
-            return -1;
-        }
-        code = afsconf_ClientAuth(tdir, &sc, &scIndex); /* sets sc,scIndex */
-        if (code) {
-            fprintf(STDERR, "vsu_ClientInit: Could not get security object for -localAuth\n");
-            return -1;
-        }
-        code = afsconf_GetCellInfo(tdir, tdir->cellName, AFSCONF_VLDBSERVICE,
-               &info);
-        if (code) {
-            fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n",
-                   cellName, AFSDIR_SERVER_ETC_DIRPATH,AFSDIR_CELLSERVDB_FILE);
-            exit(1);
-        }
-    }
-    else {  /* not -localauth */
-        tdir = afsconf_Open(confDir);
-        if (!tdir) {
-            fprintf(STDERR, "vsu_ClientInit: Could not process files in configuration directory (%s).\n",
-                    confDir);
-            return -1;
-        }
-
-        if (!cellName) {
-            code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr));
-            if (code) {
-                fprintf(STDERR, "vsu_ClientInit: can't get local cellname, check %s/%s\n",
-                        confDir, AFSDIR_THISCELL_FILE);
-                exit(1);
-            }
-            cellName = cellstr;
-        }
-
-        code = afsconf_GetCellInfo(tdir, cellName, AFSCONF_VLDBSERVICE, &info);
-        if (code) {
-            fprintf(STDERR, "vsu_ClientInit: can't find cell %s's hosts in %s/%s\n",
-                    cellName, confDir,AFSDIR_CELLSERVDB_FILE);
-            exit(1);
-        }
-        if (noAuthFlag)    /* -noauth */
-            scIndex = 0;
-        else {             /* not -noauth */
-            strcpy(sname.cell, info.name);
-            sname.instance[0] = 0;
-            strcpy(sname.name, "afs");
-            code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), (char *)0);
-            if (code) {   /* did not get ticket */
-                fprintf(STDERR, "vsu_ClientInit: Could not get afs tokens, running unauthenticated.\n");
-                scIndex = 0;
-            }
-            else {     /* got a ticket */
-                scIndex = 2;
-                if ((ttoken.kvno < 0) || (ttoken.kvno > 255)) {
-                    fprintf(STDERR, "vsu_ClientInit: funny kvno (%d) in ticket, proceeding\n",
-                            ttoken.kvno);
-                }
-            }
-        }
-
-        switch (scIndex) {
-          case 0 :
-            sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
-            break;
-          case 2:
-            sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject(
-                 rxkad_clear, &ttoken.sessionKey, ttoken.kvno,
-                 ttoken.ticketLen, ttoken.ticket);
-            break;
-          default:
-            fprintf(STDERR, "vsu_ClientInit: unsupported security index %d\n",
-                     scIndex);
-            exit(1);
-            break;
-        }
-    }
-
-    if (secproc)     /* tell UV module about default authentication */
-        (*secproc) (sc, scIndex);
-    if (info.numServers > VLDB_MAXSERVERS) {
-        fprintf(STDERR, "vsu_ClientInit: info.numServers=%d (> VLDB_MAXSERVERS=%d)\n",
-                info.numServers, VLDB_MAXSERVERS);
-        exit(1);
-    }
-    for (i=0; i<info.numServers; i++) {
-        serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
-                         info.hostAddr[i].sin_port, USER_SERVICE_ID,
-                         sc, scIndex);
-    }
-    *uclientp = 0;
-    code = ubik_ClientInit(serverconns, uclientp);
-    if (code) {
-        fprintf(STDERR, "vsu_ClientInit: ubik client init failed.\n");
-        return code;
-    }
-    return 0;
+    return ugen_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp,
+                          secproc, "vsu_ClientInit", vsu_rxkad_level,
+                          VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 90,
+                          0, 0, USER_SERVICE_ID);
 }
 
 
 /*extract the name of volume <name> without readonly or backup suffixes
  * and return the result as <rname>.
  */
-vsu_ExtractName(rname,name)
-char rname[],name[];
-{   char sname[32];
-    int total;
+int
+vsu_ExtractName(char rname[], char name[])
+{
+    char sname[VOLSER_OLDMAXVOLNAME + 1];
+    size_t total;
 
-    strcpy(sname,name);
+    strncpy(sname, name, sizeof(sname));
+    sname[sizeof(sname) - 1] = '\0';
     total = strlen(sname);
-    if(!strcmp(&sname[total - 9],".readonly")) {
+    if (!strcmp(&sname[total - 9], ".readonly")) {
        /*discard the last 8 chars */
        sname[total - 9] = '\0';
-       strcpy(rname,sname);
+       strcpy(rname, sname);
        return 0;
-    }
-    else if(!strcmp(&sname[total - 7 ],".backup")) {
+    } else if (!strcmp(&sname[total - 7], ".backup")) {
        /*discard last 6 chars */
        sname[total - 7] = '\0';
-       strcpy(rname,sname);
+       strcpy(rname, sname);
        return 0;
-    }
-    else {
-       strncpy(rname,name,VOLSER_OLDMAXVOLNAME);
+    } else {
+       strncpy(rname, name, VOLSER_OLDMAXVOLNAME);
+       rname[VOLSER_OLDMAXVOLNAME] = '\0';
        return -1;
     }
 }
 
-
 /* returns 0 if failed */
-afs_uint32 vsu_GetVolumeID(astring, acstruct, errp)
-struct ubik_client *acstruct;
-afs_int32 *errp;
-char *astring; {
-    afs_uint32 tc, value;
-
-    char *str,*ptr, volname[VOLSER_OLDMAXVOLNAME+1];
-    int tryname, curval;
-    struct nvldbentry entry;
-    afs_int32 vcode;
-    int total;
+afs_uint32
+vsu_GetVolumeID(char *astring, struct ubik_client *acstruct, afs_int32 *errp)
+{
+    char volname[VOLSER_OLDMAXVOLNAME + 1];
+    struct uvldbentry entry;
+    afs_int32 vcode = 0;
+    size_t total;
 
     *errp = 0;
-    total = strlen(astring);
-    str = astring;
-    ptr = astring;
-    tryname = 0;
-    while (curval = *str++){
-       if(curval < '0' || curval > '9')
-           tryname = 1;
-    }
-
-    if(tryname) {
-       vsu_ExtractName(volname,astring);
-       vcode = VLDB_GetEntryByName(volname, &entry);
-       if(!vcode) {
-           if(!strcmp(&astring[total - 9],".readonly"))
-               return entry.volumeId[ROVOL];
-           else if ((!strcmp(&astring[total - 7 ],".backup")))
-               return entry.volumeId[BACKVOL];
-           else
-               return (entry.volumeId[RWVOL]);   
-       } else {
-           *errp = vcode;
-           return 0;   /* can't find volume */
-       }
-    }
 
-    value = 0;
-    while (tc = *astring++) {
-       if (tc & 0x80) {
-           if(!tryname) fprintf(STDERR,"goofed in volid \n");
-           else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);}
-           *errp = EINVAL;
-           return 0;
-       }
-       if (tc < '0' || tc > '9'){
-           if(!tryname) fprintf(STDERR,"internal error: out of range char in vol ID\n");
-           else {fprintf(STDERR,"Could not get entry from vldb for %s\n",ptr);PrintError("",vcode);}
-           *errp = ERANGE;
-           return 0;
-       }
-       value *= 10;
-       value += (tc - '0');
+    if (isdigit(astring[0])) {
+       char *end;
+       afs_uint32 result;
+       result = strtoul(astring, &end, 10);
+       if (result != UINT_MAX && *end == '\0')
+           return result;
     }
-    return value;
+
+    /* It was not a volume number but something else */
+    total = strlen(astring);
+    vsu_ExtractName(volname, astring);
+    vcode = VLDB_GetEntryByNameU(volname, &entry);
+    if (!vcode) {
+      if ((total >= 9) && (!strcmp(&astring[total - 9], ".readonly")))
+       return entry.volumeId[ROVOL];
+      else if ((total >= 7) && (!strcmp(&astring[total - 7], ".backup")))
+       return entry.volumeId[BACKVOL];
+      else
+       return (entry.volumeId[RWVOL]);
+    }
+    *errp = vcode;
+    return 0;          /* can't find volume */
 }