prdb_check: check for continuation entries in owner chains
[openafs.git] / src / ptserver / db_verify.c
index 47861a8..4803076 100644 (file)
@@ -1,18 +1,17 @@
 /*
  * 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>
+#include <afs/stds.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
 
 /*
  *                      (3) Define a structure, idused, instead of an
@@ -32,39 +31,28 @@ RCSID
  *                          conditions.
  */
 
-#include <afs/stds.h>
-#include <sys/types.h>
+
 #ifdef AFS_NT40_ENV
-#include <winsock2.h>
 #include <WINNT/afsevent.h>
-#include <io.h>
 #else
-#include <netdb.h>
-#include <netinet/in.h>
 #include <sys/file.h>
 #endif
-#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#include <errno.h>
-#include <fcntl.h>
+
 #include <afs/cellconfig.h>
 #include <afs/afsutil.h>
 #include <ubik.h>
 #include <afs/cmd.h>
+#include <afs/com_err.h>
 
 #include "ptint.h"
 #include "pterror.h"
 #include "ptserver.h"
+#include "ptuser.h"
+#include "display.h"
 
 struct prheader cheader;
 int fd;
-char *pr_dbaseName;
+const char *pr_dbaseName;
 char *whoami = "db_verify";
 #define UBIK_HEADERSIZE 64
 
@@ -90,7 +78,7 @@ printheader(struct prheader *h)
 }
 
 static afs_int32
-pr_Read(afs_int32 pos, char *buff, afs_int32 len)
+pr_Read(afs_int32 pos, void *buff, afs_int32 len)
 {
     afs_int32 code;
 
@@ -115,13 +103,13 @@ pr_Read(afs_int32 pos, char *buff, afs_int32 len)
  */
 
 afs_int32
-ReadHeader()
+ReadHeader(void)
 {
     afs_int32 code;
 
     code = pr_Read(0, (char *)&cheader, sizeof(cheader));
     if (code) {
-       com_err(whoami, code, "couldn't read header");
+       afs_com_err(whoami, code, "couldn't read header");
        return code;
     }
     /* Check and see if database exists and is approximately OK. */
@@ -129,7 +117,7 @@ ReadHeader()
        || ntohl(cheader.eofPtr) == 0) {
        if (code)
            return code;
-       com_err(whoami, PRDBBAD, "header is bad");
+       afs_com_err(whoami, PRDBBAD, "header is bad");
        return PRDBBAD;
     }
     return 0;
@@ -143,14 +131,14 @@ IDHash(afs_int32 x)
 }
 
 static afs_int32
-NameHash(register unsigned char *aname)
+NameHash(char *aname)
 {
     /* returns hash bucket for aname */
-    register unsigned int hash = 0;
-    register int i;
+    unsigned int hash = 0;
+    int i;
 /* stolen directly from the HashString function in the vol package */
     for (i = strlen(aname), aname += i - 1; i--; aname--)
-       hash = (hash * 31) + (*aname - 31);
+       hash = (hash * 31) + (*(unsigned char *)aname - 31);
     return (hash % HASHSIZE);
 }
 
@@ -216,13 +204,13 @@ readUbikHeader(struct misc_data *misc)
     /* now read the info */
     r = read(fd, &uheader, sizeof(uheader));
     if (r != sizeof(uheader)) {
-       printf("error: read of %d bytes failed: %d %d\n", sizeof(uheader), r,
-              errno);
+       printf("error: read of %" AFS_SIZET_FMT " bytes failed: %d %d\n",
+              sizeof(uheader), r, errno);
        return (-1);
     }
 
     uheader.magic = ntohl(uheader.magic);
-    uheader.size = ntohl(uheader.size);
+    uheader.size = ntohs(uheader.size);
     uheader.version.epoch = ntohl(uheader.version.epoch);
     uheader.version.counter = ntohl(uheader.version.counter);
 
@@ -313,7 +301,7 @@ WalkHashTable(afs_int32 hashtable[],        /* hash table to walk */
 
            id = ntohl(e.id);
 
-           if (((ntohl(e.flags) & (PRGRP | PRINST)) == 0)
+           if (((e.flags & htonl((PRGRP | PRINST))) == 0)
                && (strchr(e.name, '@'))) {
                /* Foreign user */
                if (id > misc->maxForId)
@@ -400,13 +388,14 @@ WalkNextChain(char map[],         /* one byte per db entry */
     struct prentry c;          /* continuation entry */
     afs_int32 na;              /* next thread */
     int ni;
-    afs_int32 eid;
-    int count;                 /* number of members */
+    afs_int32 eid = 0;
+    int count = 0;             /* number of members, set to > 9999 if */
+                               /* list ends early */
     int i;
     int noErrors = 1;
     int length;                        /* length of chain */
 #if defined(SUPERGROUPS)
-    int sgcount;               /* number of sgentrys */
+    int sgcount = 0;           /* number of sgentrys */
     afs_int32 sghead;
 #define g (((struct prentryg *)e))
 #endif
@@ -415,9 +404,7 @@ WalkNextChain(char map[],           /* one byte per db entry */
        head = ntohl(e->next);
        eid = ntohl(e->id);
        bit = MAP_CONT;
-       count = 0;              /* set to >9999 if list ends early */
 #if defined(SUPERGROUPS)
-       sgcount = 0;
        sghead = ntohl(g->next);
 #endif
        for (i = 0; i < PRSIZE; i++) {
@@ -468,8 +455,8 @@ WalkNextChain(char map[],           /* one byte per db entry */
                break;
        }
 #if defined(SUPERGROUPS)
-       sghead = g->nextsg;
-       if ((e->flags & PRGRP)) {
+       sghead = ntohl(g->nextsg);
+       if ((e->flags & htonl(PRGRP))) {
            for (i = 0; i < SGSIZE; ++i) {
                afs_int32 id = ntohl(g->supergroup[i]);
                if (id == PRBADID)
@@ -501,7 +488,7 @@ WalkNextChain(char map[],           /* one byte per db entry */
     for (na = sghead; na; na = ntohl(c.next)) {
        code = ConvertDiskAddress(na, &ni);
        if (code) {
-           fprintf(stderr, "Bad continuation ptr %d", na);
+           fprintf(stderr, "Bad SGcontinuation ptr %d", na);
            if (PrintEntryError(misc, ea, e, 2))
                return PRDBBAD;
            if (na != sghead) {
@@ -542,17 +529,13 @@ WalkNextChain(char map[],         /* one byte per db entry */
            if (id == PRBADID)
                continue;
            else if (id) {
-               int eid_s, id_s;
+               int id_s;
                sgcount++;
                /* in case the ids are large, convert to pure sign. */
                if (id > 0)
                    id_s = 1;
                else
                    id_s = -1;
-               if (eid > 0)
-                   eid_s = 1;
-               else
-                   eid_s = -1;
                if (id_s > 0) {
                    fprintf(stderr,
                            "User can't be member of supergroup list\n");
@@ -688,7 +671,7 @@ WalkNextChain(char map[],           /* one byte per db entry */
 #if defined(SUPERGROUPS)
        noErrors = 0;
     }
-    if (e && (e->flags & PRGRP) && (sgcount != ntohl(g->countsg))) {
+    if (e && (e->flags & htonl(PRGRP)) && (sgcount != ntohl(g->countsg))) {
        fprintf(stderr, "SGCount was %d should be %d\n", sgcount,
                ntohl(g->countsg));
        if (PrintEntryError(misc, ea, e, 2))
@@ -715,10 +698,10 @@ WalkOwnedChain(char map[],                /* one byte per db entry */
 {
     afs_int32 head;
     afs_int32 code;
-    struct prentry c;          /* continuation entry */
+    struct prentry te;         /* next entry in owner chain */
     afs_int32 na;              /* next thread */
     int ni;
-    afs_int32 eid;
+    afs_int32 eid = 0;
     int length;                        /* length of chain */
 
     if (e) {
@@ -728,7 +711,7 @@ WalkOwnedChain(char map[],          /* one byte per db entry */
        head = ntohl(cheader.orphan);
 
     length = 0;
-    for (na = head; na; na = ntohl(c.nextOwned)) {
+    for (na = head; na; na = ntohl(te.nextOwned)) {
        code = ConvertDiskAddress(na, &ni);
        if (code) {
            fprintf(stderr, "Bad owned list ptr %d", na);
@@ -738,23 +721,33 @@ WalkOwnedChain(char map[],                /* one byte per db entry */
                return PRDBBAD;
            if (na != head) {
                fprintf(stderr, "last block: \n");
-               if (PrintEntryError(misc, na, &c, 4))
+               if (PrintEntryError(misc, na, &te, 4))
                    return PRDBBAD;
            }
            return 0;
        }
-       code = pr_Read(na, (char *)&c, sizeof(c));
+       code = pr_Read(na, (char *)&te, sizeof(te));
        if (code)
            return code;
        length++;
 
+       if ((ntohl(te.flags) & PRTYPE) == PRCONT) {
+           fprintf(stderr, "Continuation entry found on owner chain\n");
+           if (e == 0)
+               fprintf(stderr, "walking orphan list");
+           else if (PrintEntryError(misc, ea, e, 2))
+               return PRDBBAD;
+           if (PrintEntryError(misc, na, &te, 4))
+               return PRDBBAD;
+           break;
+       }
        if (map[ni] & MAP_OWNED) {
            fprintf(stderr, "Entry on multiple owner chains\n");
            if (e == 0)
                fprintf(stderr, "walking orphan list");
            else if (PrintEntryError(misc, ea, e, 2))
                return PRDBBAD;
-           if (PrintEntryError(misc, na, &c, 4))
+           if (PrintEntryError(misc, na, &te, 4))
                return PRDBBAD;
            break;
        }
@@ -766,16 +759,16 @@ WalkOwnedChain(char map[],                /* one byte per db entry */
                fprintf(stderr, "walking orphan list");
            else if (PrintEntryError(misc, ea, e, 2))
                return PRDBBAD;
-           if (PrintEntryError(misc, na, &c, 4))
+           if (PrintEntryError(misc, na, &te, 4))
                return PRDBBAD;
            continue;
        }
        if (e) {
-           if (ntohl(c.owner) != eid) {
+           if (ntohl(te.owner) != eid) {
                fprintf(stderr, "Owner id mismatch\n");
                goto abort;
            }
-       } else /* orphan */ if (c.owner) {
+       } else /* orphan */ if (te.owner) {
            fprintf(stderr, "Orphan group owner not zero\n");
            goto abort;
        }
@@ -890,7 +883,7 @@ WalkChains(char map[],              /* one byte per db entry */
            case PRFOREIGN:
                fprintf(stderr,
                        "ENTRY IS unexpected type [PRFOREIGN] (flags=0x%x)\n",
-                       e.flags);
+                       ntohl(e.flags));
                break;
            case PRINST:
                misc->ninsts++;
@@ -937,12 +930,12 @@ GC(char map[], struct misc_data *misc)
            id = ntohl(e.id);
 #if defined(SUPERGROUPS)
            if ((id != ANONYMOUSID)
-               && ((refCount = idcount(&misc->idmap, id)) != ntohl(e.count))) 
+               && ((refCount = idcount(&misc->idmap, id)) != ntohl(e.count)))
 #else
            if ((id >= misc->minId) && (id <= misc->maxId)
                && (id != ANONYMOUSID)
                && ((refCount = misc->idmap[id - misc->minId]) !=
-                   ntohl(e.count))) 
+                   ntohl(e.count)))
 #endif /* SUPERGROUPS */
              {
                afs_int32 na;
@@ -975,10 +968,8 @@ QuoteName(char *s)
 {
     char *qs;
     if (strpbrk(s, " \t")) {
-       qs = (char *)malloc(strlen(s) + 3);
-       strcpy(qs, "\"");
-       strcat(qs, s);
-       strcat(qs, "\"");
+       if (asprintf(&qs, "\"%s\"", s) < 0)
+           qs = "<<-OUT-OF-MEMORY->>";
     } else
        qs = s;
     return qs;
@@ -1046,9 +1037,9 @@ DumpRecreate(char map[], struct misc_data *misc)
                /* check for duplicate id.  This may still lead to duplicate
                 * names. */
 #if defined(SUPERGROUPS)
-               if (idcount(&idmap, id)) 
+               if (idcount(&idmap, id))
 #else
-               if (idmap[id - misc->minId]) 
+               if (idmap[id - misc->minId])
 #endif
                  {
                    fprintf(stderr, "Skipping entry with duplicate id %di\n",
@@ -1157,9 +1148,9 @@ DumpRecreate(char map[], struct misc_data *misc)
 
            owner = ntohl(e.owner);
 #if defined(SUPERGROUPS)
-           if (!idcount(&idmap, owner)) 
+           if (!idcount(&idmap, owner))
 #else
-           if (idmap[owner - misc->minId] == 0) 
+           if (idmap[owner - misc->minId] == 0)
 #endif
              {
                fprintf(stderr,
@@ -1186,9 +1177,6 @@ DumpRecreate(char map[], struct misc_data *misc)
            if ((id < 0) && (flags & PRGRP)) {
                int count = 0;
                afs_int32 na;
-#if defined(SUPERGROUPS)
-               afs_int32 ng;
-#endif
                int i;
                for (i = 0; i < PRSIZE; i++) {
                    afs_int32 uid = ntohl(e.entries[i]);
@@ -1207,43 +1195,6 @@ DumpRecreate(char map[], struct misc_data *misc)
                                id);
 #endif
                }
-#if defined(SUPERGROUPS)
-#define g      (*((struct prentryg *)&e))
-               ng = ntohl(g.nextsg);
-               for (i = 0; i < SGSIZE; i++) {
-                   afs_int32 uid = ntohl(g.supergroup[i]);
-                   if (uid == 0)
-                       break;
-                   if (uid == PRBADID)
-                       continue;
-                   fprintf(rc, "au %d %d\n", uid, id);
-                   count++;
-               }
-               while (ng) {
-                   struct prentry c;
-                   code = pr_Read(ng, (char *)&c, sizeof(c));
-                   if (code)
-                       return code;
-
-                   if ((id == ntohl(c.id)) && (ntohl(c.flags) & PRCONT)) {
-                       for (i = 0; i < COSIZE; i++) {
-                           afs_int32 uid = ntohl(c.entries[i]);
-                           if (uid == 0)
-                               break;
-                           if (uid == PRBADID)
-                               continue;
-                           fprintf(rc, "au %d %d\n", uid, id);
-                           count++;
-                       }
-                   } else {
-                       fprintf(stderr, "Skipping continuation block at %d\n",
-                               ng);
-                       break;
-                   }
-                   ng = ntohl(c.next);
-               }
-#undef g
-#endif /* SUPERGROUPS */
                na = ntohl(e.next);
                while (na) {
                    struct prentry c;
@@ -1251,7 +1202,7 @@ DumpRecreate(char map[], struct misc_data *misc)
                    if (code)
                        return code;
 
-                   if ((id == ntohl(c.id)) && (ntohl(c.flags) & PRCONT)) {
+                   if ((id == ntohl(c.id)) && (c.flags & htonl(PRCONT))) {
                        for (i = 0; i < COSIZE; i++) {
                            afs_int32 uid = ntohl(c.entries[i]);
                            if (uid == 0)
@@ -1301,15 +1252,15 @@ CheckPrDatabase(struct misc_data *misc) /* info & statistics */
     n = eof / sizeof(struct prentry);
     if ((eof < 0) || (n * sizeof(struct prentry) != eof)) {
        code = PRDBBAD;
-       com_err(whoami, code, "eof ptr no good: eof=%d, sizeof(prentry)=%d",
+       afs_com_err(whoami, code,
+                   "eof ptr no good: eof=%d, sizeof(prentry)=%" AFS_SIZET_FMT,
                eof, sizeof(struct prentry));
       abort:
        return code;
     }
     if (misc->verbose)
        printf("Database has %d entries\n", n);
-    map = (char *)malloc(n);
-    memset(map, 0, n);
+    map = calloc(1, n);
     misc->nEntries = n;
 
     if (misc->verbose) {
@@ -1318,7 +1269,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = WalkHashTable(cheader.nameHash, MAP_NAMEHASH, map, misc);
     if (code) {
-       com_err(whoami, code, "walking name hash");
+       afs_com_err(whoami, code, "walking name hash");
        goto abort;
     }
     if (misc->verbose) {
@@ -1327,7 +1278,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = WalkHashTable(cheader.idHash, MAP_IDHASH, map, misc);
     if (code) {
-       com_err(whoami, code, "walking id hash");
+       afs_com_err(whoami, code, "walking id hash");
        goto abort;
     }
 
@@ -1337,14 +1288,13 @@ CheckPrDatabase(struct misc_data *misc) /* info & statistics */
 #else
     n = ((misc->maxId > misc->maxForId) ? misc->maxId : misc->maxForId);
     misc->idRange = n - misc->minId + 1;
-    misc->idmap = (afs_int32 *) malloc(misc->idRange * sizeof(afs_int32));
+    misc->idmap = calloc(misc->idRange, sizeof(afs_int32));
     if (!misc->idmap) {
-       com_err(whoami, 0, "Unable to malloc space for max ids of %d",
+       afs_com_err(whoami, 0, "Unable to malloc space for max ids of %d",
                misc->idRange);
        code = -1;
        goto abort;
     }
-    memset(misc->idmap, 0, misc->idRange * sizeof(misc->idmap[0]));
 #endif /* SUPERGROUPS */
 
     if (misc->verbose) {
@@ -1353,7 +1303,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = WalkChains(map, misc);
     if (code) {
-       com_err(whoami, code, "walking chains");
+       afs_com_err(whoami, code, "walking chains");
        goto abort;
     }
     if (misc->verbose) {
@@ -1362,7 +1312,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = WalkNextChain(map, misc, 0, 0);
     if (code) {
-       com_err(whoami, code, "walking free list");
+       afs_com_err(whoami, code, "walking free list");
        goto abort;
     }
     if (misc->verbose) {
@@ -1371,7 +1321,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = WalkOwnedChain(map, misc, 0, 0);
     if (code) {
-       com_err(whoami, code, "walking orphan list");
+       afs_com_err(whoami, code, "walking orphan list");
        goto abort;
     }
 
@@ -1381,7 +1331,7 @@ CheckPrDatabase(struct misc_data *misc)   /* info & statistics */
     }
     code = GC(map, misc);
     if (code) {
-       com_err(whoami, code, "looking for unreferenced entries");
+       afs_com_err(whoami, code, "looking for unreferenced entries");
        goto abort;
     }
 
@@ -1428,11 +1378,11 @@ CheckPrDatabase(struct misc_data *misc) /* info & statistics */
     free(map);
     return code;
 }
-    
+
 #include "AFS_component_version_number.c"
 
 int
-WorkerBee(struct cmd_syndesc *as, char *arock)
+WorkerBee(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     char *recreateFile;
@@ -1453,7 +1403,7 @@ WorkerBee(struct cmd_syndesc *as, char *arock)
 
     fd = open(pr_dbaseName, O_RDONLY, 0);
     if (fd == -1) {
-       com_err(whoami, errno, "Open failed on db %s", pr_dbaseName);
+       afs_com_err(whoami, errno, "Open failed on db %s", pr_dbaseName);
        exit(2);
     }
 
@@ -1471,7 +1421,7 @@ WorkerBee(struct cmd_syndesc *as, char *arock)
     if (recreateFile) {
        misc.recreate = fopen(recreateFile, "w");
        if (misc.recreate == 0) {
-           com_err(whoami, errno,
+           afs_com_err(whoami, errno,
                    "can't create file for recreation instructions: %s",
                    recreateFile);
            exit(4);
@@ -1479,7 +1429,7 @@ WorkerBee(struct cmd_syndesc *as, char *arock)
     }
     code = CheckPrDatabase(&misc);
     if (code) {
-       com_err(whoami, code, "Checking prserver database");
+       afs_com_err(whoami, code, "Checking prserver database");
        exit(3);
     }
     exit(0);
@@ -1492,7 +1442,7 @@ main(int argc, char *argv[])
 
     setlinebuf(stdout);
 
-    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, "PRDB check");
+    ts = cmd_CreateSyntax(NULL, WorkerBee, NULL, 0, "PRDB check");
     cmd_AddParm(ts, "-database", CMD_SINGLE, CMD_REQUIRED, "ptdb_file");
     cmd_AddParm(ts, "-uheader", CMD_FLAG, CMD_OPTIONAL,
                "Display UBIK header");
@@ -1515,7 +1465,7 @@ void
 zeromap(struct idused *idmap)
 {
     while (idmap) {
-       bzero((char *)idmap->idcount, sizeof idmap->idcount);
+       memset(idmap->idcount, 0, sizeof idmap->idcount);
        idmap = idmap->idnext;
     }
 }
@@ -1529,18 +1479,17 @@ inccount(struct idused **idmapp, int id)
        fprintf(stderr, "IDCOUNT must be power of 2!\n");
        exit(1);
     }
-    while (idmap = *idmapp) {
+    while ((idmap = *idmapp) != NULL) {
        if (idmap->idstart == (id & ~(IDCOUNT - 1)))
            break;
        idmapp = &idmap->idnext;
     }
     if (!idmap) {
-       idmap = (struct idused *)malloc(sizeof *idmap);
+       idmap = calloc(1, sizeof *idmap);
        if (!idmap) {
            perror("idmap");
            exit(1);
        }
-       bzero((char *)idmap, sizeof idmap);
        idmap->idstart = id & ~(IDCOUNT - 1);
        idmap->idnext = *idmapp;
        *idmapp = idmap;
@@ -1557,7 +1506,7 @@ idcount(struct idused **idmapp, int id)
        fprintf(stderr, "IDCOUNT must be power of 2!\n");
        exit(1);
     }
-    while (idmap = *idmapp) {
+    while ((idmap = *idmapp) != NULL) {
        if (idmap->idstart == (id & ~(IDCOUNT - 1))) {
            return idmap->idcount[id & (IDCOUNT - 1)];
        }