--- /dev/null
+/* $Header$
+ *
+ * Declarations for SMS database consistancy checker
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <sms_app.h>
+#include <mit-copyright.h>
+
+#define MODE_ASK 1
+#define MODE_NO 2
+#define MODE_PREEN 3
+#define MODE_YES 4
+
+extern int debug, mode, fast, dcmenable;
+extern struct hash *users, *machines, *clusters, *lists;
+extern struct hash *filesys, *nfsphys, *strings;
+
+#define MAX_ID_VALUE 32765
+#define MIN_ID_VALUE 100
+
+#define dprintf if (debug) printf
+
+struct user {
+ char login[9];
+ char potype;
+ char *fullname;
+ int status;
+ int users_id;
+ int pobox_id;
+};
+
+struct machine {
+ char name[33];
+ int mach_id;
+ int clucount;
+};
+
+struct cluster {
+ char name[33];
+ int clu_id;
+};
+
+struct list {
+ char name[33];
+ char acl_type;
+ int list_id;
+ int acl_id;
+ int members;
+};
+
+struct string {
+ char *name;
+ int string_id;
+ int refc;
+};
+
+struct filesys {
+ char name[33];
+ char dir[33];
+ char type;
+ int filsys_id;
+ int mach_id;
+ int owner;
+ int owners;
+ int phys_id;
+};
+
+struct nfsphys {
+ char dir[33];
+ int mach_id;
+ int nfsphys_id;
+ int allocated;
+ int count;
+};
--- /dev/null
+/* $Header$
+ *
+ * SMS database consistency checker
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <strings.h>
+#include <signal.h>
+#include "dbck.h"
+
+
+int debug = 1;
+int mode = MODE_ASK;
+int fast = 0;
+struct hash *users, *machines, *clusters, *lists, *filesys, *nfsphys, *strings;
+##int dcmenable;
+int cleanup();
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ char **arg = argv;
+## char *database;
+ int ingerr();
+ int countonly = 0;
+
+ database = "sms";
+
+ while (++arg - argv < argc) {
+ if (**arg == '-')
+ switch ((*arg)[1]) {
+ case 'd':
+ debug = atoi((*arg)[2] ? *arg+2 : *++arg);
+ break;
+ case 'n':
+ mode = MODE_NO;
+ break;
+ case 'y':
+ mode = MODE_YES;
+ break;
+ case 'p':
+ mode = MODE_PREEN;
+ break;
+ case 'a':
+ mode = MODE_ASK;
+ break;
+ case 'c':
+ countonly++;
+ break;
+ case 'f':
+ fast++;
+ break;
+ }
+ else
+ database = *arg;
+ }
+ if (countonly)
+ printf("Only doing counts\n");
+ else if (fast)
+ printf("Doing fast version (skipping some checks)\n");
+ if (mode == MODE_NO)
+ printf("Will NOT modify the database\n");
+ else if (mode == MODE_PREEN)
+ printf("Will fix simple things without asking\n");
+ else if (mode == MODE_YES)
+ printf("Will fix everything without asking\n");
+ if (debug)
+ printf("Debug level is %d\n", debug);
+
+ signal(SIGHUP, cleanup);
+ signal(SIGQUIT, cleanup);
+ signal(SIGINT, cleanup);
+
+ IIseterr(ingerr);
+ printf("Opening database %s...", database);
+ fflush(stdout);
+## ingres database
+ printf("done\n");
+## retrieve (dcmenable = values.value) where values.name = "dcm_enable"
+ dprintf("DCM disabled (was %d)\n", dcmenable);
+## replace values (value = 0) where values.name = "dcm_enable"
+
+## begin transaction
+
+ if (!countonly) {
+ phase1();
+ phase2();
+ phase3();
+ } else {
+ printf("Skipping to counts\n");
+ count_only_setup();
+ }
+ phase4();
+
+## end transaction
+## replace values (value = dcmenable) where values.name = "dcm_enable"
+ printf("Done.\n");
+## exit
+ exit(0);
+}
+
+ingerr(num)
+int *num;
+{
+ printf("An ingres error occuurred, code %d\n", *num);
+ printf("Aborting...\n");
+## abort
+ exit(1);
+}
+
+
+int cleanup()
+##{
+ printf("Signal caught, aborting transaction\n");
+## abort
+## replace values (value = dcmenable) where values.name = "dcm_enable"
+## exit
+ exit(0);
+##}
--- /dev/null
+/* $Header$
+ *
+ * User interface routines for dbck (SMS database consistency checker)
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <sms.h>
+#include <stdio.h>
+#include "dbck.h"
+
+
+##char *_table;
+##char *_idfield;
+
+##generic_ffunc(id)
+##int id;
+##{
+## int rowcount;
+
+## delete _table where _table._idfield = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not deleted\n");
+##}
+
+
+generic_delete(sq, pfunc, table, idfield, preen)
+struct save_queue *sq;
+void (*pfunc)();
+char *table, *idfield;
+int preen;
+{
+ _table = table;
+ _idfield = idfield;
+ generic_fix(sq, pfunc, "Delete", generic_ffunc, preen);
+}
+
+
+single_delete(table, idfield, id)
+char *table, *idfield;
+int id;
+{
+ _table = table;
+ _idfield = idfield;
+ generic_ffunc(id);
+}
+
+
+##zero_fix(table, zrfield, idfield, id)
+##char *table, *zrfield, *idfield;
+##int id;
+##{
+## int rowcount;
+
+## replace table (zrfield = 0) where table.idfield = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+##}
+
+
+generic_fix(sq, pfunc, msg, ffunc, preen)
+struct save_queue *sq;
+char *msg;
+int (*pfunc)(), (*ffunc)();
+int preen;
+{
+ int id;
+
+ while (sq_get_data(sq, &id)) {
+ if ((*pfunc)(id) == 0 && singe_fix(msg, preen))
+ (*ffunc)(id);
+ }
+ sq_destroy(sq);
+}
+
+
+int single_fix(msg, preen)
+char *msg;
+int preen;
+{
+ int lmode;
+
+ lmode = mode;
+ if (mode == MODE_PREEN) {
+ if (preen)
+ lmode = MODE_YES;
+ else
+ lmode = MODE_NO;
+ }
+
+ switch (lmode) {
+ case MODE_ASK:
+ if (!prompt(msg))
+ break;
+ case MODE_YES:
+ return(1);
+ break;
+ case MODE_NO:
+ ;
+ }
+ return(0);
+}
+
+
+int prompt(msg)
+char *msg;
+{
+ char buf[BUFSIZ];
+## extern int dcmenable;
+
+ while (1) {
+ printf("%s (Y/N/Q)? ", msg);
+ fflush(stdout);
+ gets(buf);
+ if (buf[0] == 'Y' || buf[0] == 'y')
+ return(1);
+ if (buf[0] == 'N' || buf[0] == 'n')
+ return(0);
+ if (buf[0] == 'Q' || buf[0] == 'q') {
+ if (prompt("Are you sure you want to quit")) {
+ if (prompt("Save database changes")) {
+## end transaction
+## replace values (value = dcmenable)
+## where values.name = "dcm_enable"
+## exit
+ exit(0);
+ } else {
+ cleanup();
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ ** set_next_object_id - set next object id in values table
+ **
+ ** Inputs: object - object name in values table and in objects
+ ** table - name of table objects are found in
+ **
+ ** - called before an APPEND operation to set the next object id to
+ ** be used for the new record to the next free value
+ **
+ **/
+
+int set_next_object_id(object, table)
+ char *object;
+ char *table;
+##{
+## char *name, *tbl;
+## int rowcount, exists, value;
+
+ name = object;
+ tbl = table;
+## range of v is values
+## repeat retrieve (value = v.#value) where v.#name = @name
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount != 1)
+ return(SMS_NO_ID);
+
+## retrieve (exists = any(tbl.name where tbl.name = value))
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount != 1)
+ return(SMS_NO_ID);
+ while (exists) {
+ value++;
+ if (value > MAX_ID_VALUE)
+ value = MIN_ID_VALUE;
+## retrieve (exists = any(tbl.name where tbl.name = value))
+ }
+
+ printf("setting ID %s to %d", name, value);
+## repeat replace v (#value = @value) where v.#name = @name
+ return(SMS_SUCCESS);
+##}
+
+
+##generic_fix_id(table, idfield, txtfield, oldid, name)
+##char *table;
+##char *idfield;
+##char *txtfield;
+##int oldid;
+##char *name;
+##{
+## int rowcount, id;
+
+ set_next_object_id(table, idfield);
+## retrieve (id = values.value) where values.#name = idfield
+## replace table (idfield = values.value) where values.#name = idfield and
+## table.idfield = oldid and table.txtfield = name
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount == 1)
+ printf("Fixed\n");
+ else
+ printf("Not fixed, rowcount = %d\n", rowcount);
+ return(id);
+##}
--- /dev/null
+/* $Header$
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include "dbck.h"
+
+
+show_user_id(u)
+struct user *u;
+{
+ printf("User %s (%s, status %d) has duplicate ID\n",
+ u->login, u->fullname, u->status);
+ return(0);
+}
+
+handle_duplicate_logins(sq)
+struct save_queue *sq;
+{
+ struct user *u, *uu, *tmp;
+
+ uu = (struct user *)0;
+ while (sq_get_data(sq, &u)) {
+ if (!strcmp(u->login, uu->login)) {
+ if (uu->status == 1 || u->status == 0) {
+ tmp = u;
+ u = uu;
+ uu = tmp;
+ }
+ printf("User %s (%s, status %d) and\n",
+ u->login, u->fullname, u->status);
+ printf("User %s (%s, status %d) have duplicate logins\n",
+ uu->login, uu->fullname, uu->status);
+ if (!strcmp(u->fullname, uu->fullname) &&
+ single_fix("Delete the second one")) {
+ single_delete("users", "users_id", uu->users_id);
+ } else if (single_fix("Unregister the second one"))
+## {
+## int id = uu->users_id, rowcount;
+
+## replace users (login = "#"+text(users.uid), status = 0)
+## where users.users_id = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+## }
+ } else {
+ uu = u;
+ }
+ }
+}
+
+fix_user_id(u)
+struct user *u;
+{
+ u->users_id = generic_fix_id("users", "users_id", "login",
+ u->users_id, u->login);
+}
+
+
+cant_fix(id)
+int id;
+{
+ printf("Sorry, don't know how to fix that\n");
+}
+
+show_mach_id(m)
+struct machine *m;
+{
+ printf("Machine %s has duplicate ID %d\n", m->name, m->mach_id);
+ return(0);
+}
+
+show_mach_name(m)
+struct machine *m;
+{
+ printf("Machine %s (%d) has duplicate name\n", m->name, m->mach_id);
+ return(0);
+}
+
+fix_mach_id(m)
+struct machine *m;
+{
+ m->mach_id = generic_fix_id("machine", "mach_id", "name",
+ m->mach_id, m->name);
+}
+
+show_clu_id(c)
+struct cluster *c;
+{
+ printf("Cluster %s has duplicate ID %d\n", c->name, c->clu_id);
+ return(0);
+}
+
+show_clu_name(c)
+struct cluster *c;
+{
+ printf("Cluster %s (%d) has duplicate name\n", c->name, c->clu_id);
+ return(0);
+}
+
+fix_clu_id(c)
+struct cluster *c;
+{
+ c->clu_id = generic_fix_id("cluster", "clu_id", "name", c->clu_id, c->name);
+}
+
+show_list_id(l)
+struct list *l;
+{
+ printf("List %s has duplicate ID %d\n", l->name, l->list_id);
+ return(0);
+}
+
+show_list_name(l)
+struct list *l;
+{
+ printf("List %s (%d) has duplicate name\n", l->name, l->list_id);
+ return(0);
+}
+
+fix_list_id(l)
+struct list *l;
+{
+ l->list_id = generic_fix_id("list", "list_id", "name", l->list_id, l->name);
+}
+
+show_fs_id(f)
+struct filesys *f;
+{
+ printf("Filesys %s has duplicate ID %d\n", f->name, f->filsys_id);
+ return(0);
+}
+
+fix_fs_id(f)
+struct filesys *f;
+{
+ f->filsys_id = generic_fix_id("filesys", "filsys_id", "label",
+ f->filsys_id, f->name);
+}
+
+
+show_np_id(n)
+struct nfsphys *n;
+{
+ printf("NfsPhys %s:%s has duplicate ID %d\n",
+ ((struct machine *)hash_lookup(machines, n->mach_id))->name,
+ n->dir, n->nfsphys_id);
+ return(0);
+}
+
+fix_np_id(n)
+struct nfsphys *n;
+{
+ n->nfsphys_id = generic_fix_id("nfsphys", "nfsphys_id", "dir",
+ n->nfsphys_id, n->dir);
+}
+
+show_str_id(s)
+struct string *s;
+{
+ printf("String %s has duplicate ID %d\n", s->name, s->string_id);
+ return(0);
+}
+
+
+phase1()
+##{
+## char name[33], name1[33], last[17], first[17], buf[257];
+## int id, id2, id3, aid, aid2, status;
+ struct save_queue *sq;
+ struct user *u;
+ struct machine *m;
+ struct list *l;
+ struct cluster *c;
+ struct string *s;
+ struct filesys *f;
+ struct nfsphys *n;
+
+ printf("Phase 1 - Looking for duplicates\n");
+
+ dprintf("Loading users...\n");
+ sq = sq_create();
+ users = create_hash(10000);
+## range of u is users
+## retrieve (id = u.users_id, name = u.login, last = u.#last,
+## first = u.#first, status = u.#status, buf = u.potype,
+## id2 = u.pop_id, id3 = u.box_id) {
+ u = (struct user *) malloc(sizeof(struct user));
+ strcpy(u->login, strtrim(name));
+ u->potype = buf[0];
+ sprintf(buf, "%s, %s", strtrim(last), strtrim(first));
+ u->fullname = strsave(buf);
+ u->status = status;
+ u->users_id = id;
+ switch (u->potype) {
+ case 'P':
+ u->pobox_id = id2;
+ break;
+ case 'S':
+ u->pobox_id = id3;
+ break;
+ default:
+ u->pobox_id = 0;
+ }
+ if (hash_store(users, id, u)) {
+ sq_save_data(sq, hash_lookup(users, id));
+ sq_save_data(sq, u);
+ }
+## }
+ generic_fix(sq, show_user_id, "Change ID", fix_user_id, 0);
+
+ if (!fast) {
+ sq = sq_create();
+## retrieve (id = u.users_id)
+## where u.login = users.login and u.tid != users.tid {
+ sq_save_data(sq, hash_lookup(users, id));
+## }
+ handle_duplicate_logins(sq);
+ }
+
+ dprintf("Loading machines...\n");
+ machines = create_hash(1000);
+ sq = sq_create();
+## range of m is machine
+## retrieve (id = m.mach_id, name = m.#name) {
+ m = (struct machine *) malloc(sizeof(struct machine));
+ strcpy(m->name, strtrim(name));
+ m->mach_id = id;
+ m->clucount = 0;
+ if (hash_store(machines, id, m)) {
+ sq_save_data(sq, hash_lookup(machines, id));
+ sq_save_data(sq, m);
+ }
+## }
+ generic_fix(sq, show_mach_id, "Change ID", fix_mach_id, 0);
+
+ if (!fast) {
+ sq = sq_create();
+## retrieve (id = m.mach_id)
+## where m.#name = machine.#name and m.tid != machine.tid {
+ sq_save_data(sq, hash_lookup(machines, id));
+## }
+ generic_fix(sq, show_mach_name, "Change name", cant_fix, 0);
+ }
+
+ dprintf("Loading clusters...\n");
+ sq = sq_create();
+ clusters = create_hash(100);
+## range of c is cluster
+## retrieve (id = cluster.clu_id, name = cluster.#name) {
+ c = (struct cluster *) malloc(sizeof(struct cluster));
+ strcpy(c->name, strtrim(name));
+ c->clu_id = id;
+ if (hash_store(clusters, id, c)) {
+ sq_save_data(sq, hash_lookup(clusters, id));
+ sq_save_data(sq, c);
+ }
+## }
+ generic_fix(sq, show_clu_id, "Change ID", fix_clu_id, 0);
+
+ if (!fast) {
+ sq = sq_create();
+## retrieve (id = c.clu_id)
+## where c.#name = cluster.#name and c.tid != cluster.tid {
+ sq_save_data(sq, hash_lookup(clusters, id));
+## }
+ generic_fix(sq, show_clu_name, "Change name", cant_fix, 0);
+ }
+
+ dprintf("Loading lists...\n");
+ sq = sq_create();
+ lists = create_hash(10000);
+## range of l is list
+## retrieve (id = l.list_id, name = l.#name,
+## aid = l.acl_id, buf = l.acl_type) {
+ l = (struct list *) malloc(sizeof(struct list));
+ strcpy(l->name, strtrim(name));
+ l->acl_type = buf[0];
+ l->acl_id = aid;
+ l->list_id = id;
+ l->members = 0;
+ if (hash_store(lists, id, l)) {
+ sq_save_data(sq, hash_lookup(lists, id));
+ sq_save_data(sq, l);
+ }
+## }
+ generic_fix(sq, show_list_id, "Change ID", fix_list_id, 0);
+
+ if (!fast) {
+ sq = sq_create();
+## retrieve (id = l.list_id)
+## where l.#name = list.#name and l.tid != list.tid {
+ sq_save_data(sq, hash_lookup(lists, id));
+## }
+ generic_fix(sq, show_list_name, "Change name", cant_fix, 0);
+ }
+
+ dprintf("Loading filesys...\n");
+ sq = sq_create();
+ filesys = create_hash(10000);
+## retrieve (id = filesys.filsys_id, name = filesys.label, aid = filesys.owner,
+## aid2 = filesys.owners, id2 = filesys.phys_id,
+## id3 = filesys.mach_id, buf = filesys.type,
+## name1 = filesys.#name) {
+ f = (struct filesys *) malloc(sizeof(struct filesys));
+ strcpy(f->name, strtrim(name));
+ strcpy(f->dir, strtrim(name1));
+ f->filsys_id = id;
+ f->owner = aid;
+ f->owners = aid2;
+ f->phys_id = id2;
+ f->mach_id = id3;
+ f->type = buf[0];
+ if (hash_store(filesys, id, f)) {
+ sq_save_data(sq, hash_lookup(filesys, id));
+ sq_save_data(sq, f);
+ }
+## }
+ generic_fix(sq, show_fs_id, "Change ID", fix_fs_id, 0);
+
+ dprintf("Loading nfsphys...\n");
+ sq = sq_create();
+ nfsphys = create_hash(500);
+## retrieve (id = nfsphys.nfsphys_id, name = nfsphys.dir,
+## id2 = nfsphys.mach_id, id3 = nfsphys.allocated) {
+ n = (struct nfsphys *) malloc(sizeof(struct nfsphys));
+ strcpy(n->dir, strtrim(name));
+ n->mach_id = id2;
+ n->nfsphys_id = id;
+ n->allocated = id3;
+ n->count = 0;
+ if (hash_store(nfsphys, id, n)) {
+ sq_save_data(sq, hash_lookup(nfsphys, id));
+ sq_save_data(sq, n);
+ }
+## }
+ generic_fix(sq, show_np_id, "Change ID", fix_np_id, 0);
+
+ dprintf("Loading strings...\n");
+ sq = sq_create();
+ strings = create_hash(5000);
+## range of s is strings
+## retrieve (id = s.string_id, buf = s.string) {
+ s = (struct string *) malloc(sizeof(struct string));
+ s->name = strsave(strtrim(buf));
+ s->string_id = id;
+ s->refc = 0;
+ if (hash_store(strings, id, s)) {
+ sq_save_data(sq, hash_lookup(strings, id));
+ sq_save_data(sq, s);
+ }
+## }
+ generic_delete(sq, show_str_id, "strings", "string_id", 0);
+
+ if (!fast) {
+## retrieve (id = s.string_id, buf = s.string)
+## where s.string = strings.string and s.tid != strings.tid {
+ printf("String %s(%d) is a duplicate!\n", strtrim(buf), id);
+## }
+ }
+##}
+
--- /dev/null
+/* $Header$
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <sms.h>
+#include "dbck.h"
+
+show_mcm_mach(id)
+int id;
+##{
+## int iid = id, found = 1;
+## char name[33];
+
+## retrieve (name = cluster.#name) where cluster.clu_id = mcmap.clu_id
+## and mcmap.mach_id = iid {
+ strtrim(name);
+ found = 0;
+ printf("Cluster %s, non-existant machine %d in cluster map\n", name, id);
+## }
+ return(found);
+##}
+
+show_mcm_clu(id)
+int id;
+##{
+## int iid = id, found = 1;
+## char name[33];
+
+## retrieve (name = machine.#name) where machine.mach_id = mcmap.mach_id
+## and mcmap.clu_id = iid {
+ strtrim(name);
+ found = 0;
+ printf("Machine %s, non-existant cluster %d in cluster map\n", name, id);
+## }
+ return(found);
+##}
+
+pobox_check(id, u, hint)
+int id;
+struct user *u;
+int hint;
+{
+ switch (u->potype) {
+ case 'P':
+ if (!hash_lookup(machines, u->pobox_id)) {
+ printf("User %s(%s) has P.O.Box on non-existant machine %d\n",
+ u->login, u->fullname, u->pobox_id);
+ if (single_fix("Delete", 0)) {
+ remove_pobox(u->users_id);
+ u->potype = 'N';
+ }
+ }
+ break;
+ case 'S':
+ if (!string_check(u->pobox_id)) {
+ printf("User %s(%s) has P.O.Box with non-existant string %d\n",
+ u->login, u->fullname, u->pobox_id);
+ if (single_fix("Delete", 0)) {
+ remove_pobox(u->users_id);
+ u->potype = 'N';
+ }
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+
+remove_pobox(id)
+int id;
+##{
+## int rowcount, iid = id;
+## replace users (potype = "NONE") where users.users_id = iid
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s removed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not removed\n");
+##}
+
+show_svc(id)
+int id;
+##{
+## int iid = id, found = 1;
+## char label[17], data[33];
+
+## retrieve (label = svc.serv_label, data = svc.serv_cluster)
+## where svc.clu_id = iid {
+ strtrim(label);
+ strtrim(data);
+ found = 0;
+ printf("Cluster data [%s] %s for non-existant cluster %d\n",
+ label, data, id);
+## }
+ return(found);
+##}
+
+list_check(id, l, hint)
+int id;
+struct list *l;
+int hint;
+{
+ switch (l->acl_type) {
+ case 'L':
+ if (!hash_lookup(lists, l->acl_id)) {
+ printf("List %s has bad LIST acl %d\n", l->name, l->acl_id);
+ if (single_fix("Patch", 1)) {
+ fix_list_acl(l->list_id);
+ }
+ }
+ break;
+ case 'U':
+ if (!hash_lookup(users, l->acl_id)) {
+ printf("List %s has bad USER acl %d\n", l->name, l->acl_id);
+ if (single_fix("Patch", 1)) {
+ fix_list_acl(l->list_id);
+ }
+ }
+ break;
+ }
+}
+
+fix_list_acl(id)
+int id;
+##{
+## int rowcount, iid = id;
+## replace list (acl_id = iid, acl_type = "LIST") where list.list_id = iid
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+##}
+
+
+show_member_list(id)
+int id;
+##{
+## int mid, iid = id, found = 1;
+## char mtype[9], *name;
+
+## retrieve (mtype = member.member_type, mid = member.member_id)
+## where member.list_id = iid {
+ strtrim(mtype);
+ found = 0;
+ if (mtype[0] == 'L')
+ strcpy(name, ((struct list *) hash_lookup(lists, mid))->name);
+ else if (mtype[0] == 'U')
+ strcpy(name, ((struct user *) hash_lookup(users, mid))->login);
+ else if (mtype[0] == 'S')
+ strcpy(name, ((struct string *) hash_lookup(strings, mid))->name);
+ printf("Non-existant list %d has member %s %s\n", iid, mtype, name);
+## }
+ return(found);
+##}
+
+show_mem_user(id)
+int id;
+##{
+## int lid, iid = id, found = 1;
+## char name[33];
+
+## retrieve (lid = members.list_id)
+## where members.member_id = iid and members.member_type = "USER" {
+ found = 0;
+ printf("List %s has non-existant user member, id %d\n",
+ ((struct list *)hash_lookup(lists, lid))->name, iid);
+## }
+ return(found);
+##}
+
+show_mem_list(id)
+int id;
+##{
+## int lid, iid = id, found = 1;
+## char name[33];
+
+## retrieve (lid = members.list_id)
+## where members.member_id = iid and members.member_type = "LIST" {
+ found = 0;
+ printf("List %s has non-existant list member, id %d\n",
+ ((struct list *)hash_lookup(lists, lid))->name, iid);
+## }
+ return(found);
+##}
+
+show_mem_str(id)
+int id;
+##{
+## int lid, iid = id, found = 1;
+## char name[33];
+
+## retrieve (lid = members.list_id)
+## where members.member_id = iid and members.member_type = "STRING" {
+ found = 0;
+ printf("List %s has non-existant string member, id %d\n",
+ ((struct list *)hash_lookup(lists, lid))->name, iid);
+## }
+ return(found);
+##}
+
+
+##del_mem_user(id)
+##int id;
+##{
+## int rowcount;
+
+## delete members where members.member_type = "USER" and
+## members.member_id = id
+## inquire_equel(rowcount = "rowcount");
+ if (rowcount > 0)
+ printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not deleted\n");
+##}
+
+##del_mem_list(id)
+##int id;
+##{
+## int rowcount;
+
+## delete members where members.member_type = "LIST" and
+## members.member_id = id
+## inquire_equel(rowcount = "rowcount");
+ if (rowcount > 0)
+ printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not deleted\n");
+##}
+
+##del_mem_str(id)
+##int id;
+##{
+## int rowcount;
+
+## delete members where members.member_type = "STRING" and
+## members.member_id = id
+## inquire_equel(rowcount = "rowcount");
+ if (rowcount > 0)
+ printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not deleted\n");
+##}
+
+
+##show_sh(id)
+##int id;
+##{
+## char name[33];
+ int found = 1;
+
+## retrieve (name = serverhosts.service) where serverhosts.mach_id = id {
+ found = 0;
+ printf("ServerHost entry for service %s non-existant host %d\n",
+ name, id);
+## }
+ return(found);
+##}
+
+##del_sh_mach(id)
+##int id;
+##{
+## int rowcount;
+
+## delete serverhosts where serverhosts.mach_id = id
+## inquire_equel(rowcount = "rowcount");
+ if (rowcount > 0)
+ printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not deleted\n");
+##}
+
+
+static int fnchecklen;
+
+fsmatch(id, n, f)
+int id;
+struct nfsphys *n;
+struct filesys *f;
+{
+ if (n->mach_id == f->mach_id &&
+ !strncmp(f->dir, n->dir, strlen(n->dir)) &&
+ strlen(n->dir) > fnchecklen) {
+ f->phys_id = id;
+ fnchecklen = strlen(n->dir);
+ }
+}
+
+
+##check_fs(id, f, hint)
+##int id;
+register struct filesys *f;
+int hint;
+##{
+## int id1, id2, id3, rowcount;
+## char *dir;
+ struct nfsphys *n;
+ struct machine *m;
+
+ if (f->type == 'N' || f->type == 'R') {
+ if (!hash_lookup(machines, f->mach_id)) {
+ printf("Filesys %s with bad machine %d\n", f->name, f->mach_id);
+ if (single_fix("Fix", 0)) {
+## replace filesys (mach_id = 0) where filesys.filsys_id = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n",rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+ f->mach_id = 0;
+ }
+ }
+ if (!hash_lookup(users, f->owner)) {
+ printf("Filesys %s with bad owning user %d\n", f->name, f->owner);
+ if (single_fix("Fix", 1)) {
+ zero_fix("filesys", "owner", "filsys_id", f->filsys_id);
+ f->owner = 0;
+ }
+ }
+ if (!hash_lookup(lists, f->owners)) {
+ printf("Filesys %s with bad owning group %d\n", f->name, f->owners);
+ if (single_fix("Fix", 1)) {
+ zero_fix("filesys", "owners", "filsys_id", f->filsys_id);
+ f->owners = 0;
+ }
+ }
+ }
+
+ if (f->type == 'N') {
+ if (!hash_lookup(nfsphys, f->phys_id)) {
+ m = (struct machine *)hash_lookup(machines, f->mach_id);
+ printf("Filesys %s with bad phys_id %d\n", f->name, f->phys_id);
+ if (single_fix("Fix", 1)) {
+ fnchecklen = 0;
+ hash_step(nfsphys, fsmatch, f);
+ if (fnchecklen != 0) {
+ id1 = f->phys_id;
+ id2 = f->filsys_id;
+ id3 = f->mach_id;
+## replace filesys (phys_id = id1) where filesys.filsys_id = id2
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n",rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+ } else {
+ printf("No NFSphys exsits for %s:%s\n", m->name, f->dir);
+ if (single_fix("Create", 0)) {
+ dir = f->dir;
+ id1 = f->phys_id;
+ id2 = f->filsys_id;
+ id3 = f->mach_id;
+ if (set_next_object_id("nfsphys_id", "nfsphys") !=
+ SMS_SUCCESS) {
+ printf("Unable to assign unique ID\n");
+ return;
+ }
+## retrieve (id1 = values.value)
+## where values.name = "nfsphys_id"
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount != 1) {
+ printf("Unable to retrieve unique ID\n");
+ return;
+ }
+## append nfsphys (nfsphys_id = id1, mach_id = id3,
+## device = "???", #dir = dir, status = 0,
+## allocated = 0, size = 0,
+## modtime = "now", modby = 0,
+## modwith = "dbck")
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s created\n", rowcount,
+ rowcount==1?"y":"ies");
+ else
+ printf("Not created\n");
+ n = (struct nfsphys *)malloc(sizeof(struct nfsphys));
+ strcpy(n->dir, dir);
+ n->mach_id = id3;
+ n->nfsphys_id = id1;
+ n->allocated = 0;
+ n->count = 0;
+ hash_store(nfsphys, id1, n);
+## replace filesys (phys_id = id1)
+## where filesys.filsys_id = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d filesys entr%s fixed\n", rowcount,
+ rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+ }
+ }
+ }
+ }
+ }
+##}
+
+
+check_nfsphys(id, n, hint)
+int id;
+struct nfsphys *n;
+int hint;
+{
+ if (!hash_lookup(machines, n->mach_id)) {
+ printf("NFSphys %d(%s) on non-existant machine %d\n",
+ id, n->dir, n->mach_id);
+ if (single_fix("Delete", 0))
+ single_delete("nfsphys", "nfsphys_id", id);
+ }
+}
+
+##show_quota_nouser(id)
+##int id;
+##{
+## int id1, found = 1;
+
+## retrieve (id1 = nfsquota.filsys_id) where nfsquota.users_id = id {
+ found = 0;
+ printf("NFSquota on fs %d for non-existant user %d\n", id1, id);
+## }
+ return(found);
+##}
+
+fix_quota_nouser(id)
+{
+ single_delete("nfsquota", "users_id", id);
+}
+
+##show_quota_nofs(id)
+##int id;
+##{
+## int id1, found = 1;
+ struct user *u;
+
+## retrieve (id1 = nfsquota.users_id) where nfsquota.filsys_id = id {
+ u = (struct user *)hash_lookup(users, id1);
+ found = 0;
+ printf("NFSquota for user %s on non-existant filesys %d\n", u->login, id);
+## }
+ return(found);
+##}
+
+fix_quota_nofs(id)
+{
+ single_delete("nfsquota", "filsys_id", id);
+}
+
+##show_quota_wrongpid(id)
+##int id;
+##{
+## int id1, found = 1;
+ struct user *u;
+ struct filesys *f;
+
+ f = (struct filesys *)hash_lookup(filesys, id);
+## retrieve (id1 = nfsquota.users_id) where nfsquota.filsys_id = id {
+ u = (struct user *)hash_lookup(users, id1);
+ found = 0;
+ printf("NFSquota for user %s on filesys %s has wrong phys_id %d\n",
+ u->login, f->name, id);
+## }
+ return(found);
+##}
+
+##fix_quota_physid(id)
+##int id;
+##{
+## int rowcount, id1;
+
+ id1 = ((struct filesys *)hash_lookup(filesys, id))->phys_id;
+## replace nfsquota (phys_id = id1) where nfsquota.filsys_id = id and
+## nfsquota.phys_id != id1
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n",rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+##}
+
+
+phase2()
+##{
+## int id1, id2, id3, id4, id5;
+## char type[9], name[33];
+ struct save_queue *sq, *sq1, *sq2, *sq3, *sq4;
+ struct filesys *f;
+ struct list *l;
+ struct nfsphys *n;
+ struct machine *m;
+
+ printf("Phase 2 - Checking references\n");
+
+ dprintf("Checking users...\n");
+ hash_step(users, pobox_check, NULL);
+
+ dprintf("Checking mcmap...\n");
+ sq1 = sq_create();
+ sq2 = sq_create();
+## retrieve (id1 = mcmap.mach_id, id2 = mcmap.clu_id) {
+ if (!(m = (struct machine *)hash_lookup(machines, id1)))
+ sq_save_unique_data(sq1, id1);
+ if (!hash_lookup(clusters, id2))
+ sq_save_unique_data(sq2, id2);
+ m->clucount++;
+## }
+ generic_delete(sq1, show_mcm_mach, "mcmap", "mach_id", 1);
+ generic_delete(sq2, show_mcm_clu, "mcmap", "clu_id", 1);
+
+ dprintf("Checking service clusters...\n");
+ sq1 = sq_create();
+## retrieve (id1 = svc.clu_id) {
+ if (!hash_lookup(clusters, id1))
+ sq_save_unique_data(sq1, id1);
+## }
+ generic_delete(sq1, show_svc, "svc", "clu_id", 1);
+
+ dprintf("Checking lists...\n");
+ hash_step(lists, list_check, NULL);
+
+ dprintf("Checking members...\n");
+ sq1 = sq_create();
+ sq2 = sq_create();
+ sq3 = sq_create();
+ sq4 = sq_create();
+## range of m is members
+## retrieve (id1 = m.list_id, type = m.member_type, id2 = m.member_id) {
+ strtrim(type);
+ if ((l = (struct list *) hash_lookup(lists, id1)) == NULL)
+ sq_save_unique_data(sq1, id1);
+ l->members++;
+ if (!strcmp(type, "USER") && !hash_lookup(users, id2))
+ sq_save_unique_data(sq2, id2);
+ else if (!strcmp(type, "LIST") && !hash_lookup(lists, id2))
+ sq_save_unique_data(sq3, id2);
+ else if (!strcmp(type, "STRING") && !string_check(id2))
+ sq_save_unique_data(sq4, id2);
+## }
+ generic_delete(sq1, show_member_list, "members", "list_id", 1);
+ generic_fix(sq2, show_mem_user, "Delete", del_mem_user, 1);
+ generic_fix(sq3, show_mem_list, "Delete", del_mem_list, 1);
+ generic_fix(sq4, show_mem_str, "Delete", del_mem_str, 1);
+
+ dprintf("Checking servers...\n");
+## range of s is servers
+## retrieve (name = s.#name, type = s.acl_type, id1 = s.acl_id) {
+ strtrim(type);
+ if (!strcmp(type, "USER") && !hash_lookup(users, id1))
+ printf("Service %s has acl non-existant user %d\n", name, id1);
+ else if (!strcmp(type, "LIST") && !hash_lookup(lists, id1))
+ printf("Service %s has acl non-existant list %d\n", name, id1);
+## }
+
+ dprintf("Checking servershosts...\n");
+ sq = sq_create();
+## retrieve (id1 = serverhosts.mach_id) {
+ if (!hash_lookup(machines, id1))
+ sq_save_data(sq, id1);
+## }
+ generic_fix(sq, show_sh, "Delete", del_sh_mach, 1);
+
+ dprintf("Checking nfsphys...\n");
+ hash_step(nfsphys, check_nfsphys, NULL);
+
+ dprintf("Checking filesys...\n");
+ hash_step(filesys, check_fs, NULL);
+
+ dprintf("Checking nfsquota...\n");
+ sq1 = sq_create();
+ sq2 = sq_create();
+ sq3 = sq_create();
+## retrieve (id1 = nfsquota.users_id, id2 = nfsquota.filsys_id,
+## id3 = nfsquota.phys_id, id4 = nfsquota.quota) {
+ if (!hash_lookup(users, id1))
+ sq_save_data(sq1, id1);
+ else if (!(f = (struct filesys *) hash_lookup(filesys, id2)))
+ sq_save_data(sq2, id2);
+ else if (id3 != f->phys_id ||
+ ((n = (struct nfsphys*) hash_lookup(nfsphys, id3)) ==
+ (struct nfsphys *)NULL))
+ sq_save_data(sq3, id2);
+ else
+ n->count += id4;
+## }
+ generic_fix(sq1, show_quota_nouser, "Delete", fix_quota_nouser, 1);
+ generic_fix(sq2, show_quota_nofs, "Delete", fix_quota_nofs, 0);
+ generic_fix(sq3, show_quota_wrongpid, "Fix", fix_quota_physid, 1);
+
+ dprintf("Not checking zephyr.\n");
+
+ dprintf("Checking hostaccess...\n");
+## range of h is hostaccess
+## retrieve (id1 = h.mach_id, type = h.acl_type, id2 = h.acl_id) {
+ strtrim(type);
+ if (!hash_lookup(machines, id1))
+ printf("Hostaccess for non-existant host %d\n", id1);
+ if (!strcmp(type, "USER") && !hash_lookup(users, id2))
+ printf("Hostaccess for %d is non-existant user %d\n", id1, id2);
+ else if (!strcmp(type, "LIST") && !hash_lookup(lists, id2))
+ printf("Hostaccess for %d is non-existant list %d\n", id1, id2);
+## }
+
+ dprintf("Checking capacls...\n");
+## retrieve (id1 = capacls.list_id, name = capacls.tag) {
+ if (!hash_lookup(lists, id1))
+ printf("Capacl for %s is non-existant list %d\n", name, id1);
+## }
+
+##}
+
--- /dev/null
+/* $Header$
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include "dbck.h"
+
+#define NULL 0
+
+
+empty_list_check(id, l, hint)
+int id, hint;
+struct list *l;
+{
+ if (l->members == 0 && l->list_id != 0)
+ printf("Warning: List %s is empty\n", l->name);
+}
+
+
+/* Used by other parts of the program to check that a string_id is good.
+ * This returns TRUE if it is, or FALSE if it is not, and as a side effect
+ * increments the string reference count.
+ */
+
+int string_check(id)
+int id;
+{
+ register struct string *s;
+
+ s = (struct string *) hash_lookup(strings, id);
+ if (s == NULL)
+ return(0);
+ s->refc++;
+ return(1);
+}
+
+
+unref_string_check(id, s, hint)
+int id, hint;
+struct string *s;
+{
+ if (s->refc == 0) {
+ printf("Unreferenced string %s id %d\n", s->name, id);
+ if (single_fix("Delete", 1))
+ single_delete("strings", "string_id", id);
+ }
+}
+
+
+noclu_mach_check(id, m, hint)
+int id, hint;
+struct machine *m;
+{
+ if (m->clucount == 0)
+ printf("Warning: machine %s is not in any clusters\n", m->name);
+}
+
+
+phase3()
+##{
+ printf("Phase 3 - Finding unused objects\n");
+
+ dprintf("Checking machines...\n");
+ hash_step(machines, noclu_mach_check, NULL);
+
+ dprintf("Checking lists...\n");
+ hash_step(lists, empty_list_check, NULL);
+
+ dprintf("Checking strings...\n");
+ hash_step(strings, unref_string_check, NULL);
+
+##}
+
--- /dev/null
+/* $Header$
+ *
+ * (c) Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include "dbck.h"
+
+
+count_boxes(id, u, boxes)
+int id;
+struct user *u;
+struct hash *boxes;
+{
+ int i;
+
+ if (u->potype == 'P') {
+ if (i = (int) hash_lookup(boxes, u->pobox_id))
+ hash_store(boxes, u->pobox_id, i+1);
+ else
+ printf("User %s(%s) has pobox on non-POP server %d\n",
+ u->fullname, u->login, u->pobox_id);
+ }
+}
+
+
+##check_box_counts(id, cnt, counts)
+##int id, cnt;
+struct hash *counts;
+##{
+## int newval, rowcount, error;
+
+ newval = (int) hash_lookup(counts, id);
+ if (newval != cnt - 1) {
+ printf("Count wrong on POBox machine %s; is %d in db, counted %d\n",
+ ((struct machine *) hash_lookup(machines, id))->name,
+ newval, cnt - 1);
+ if (single_fix("Update", 1)) {
+## range of s is serverhosts
+## replace s (value1 = newval) where
+## s.service = "POP" and s.mach_id = id
+## inquire_equel(rowcount = "rowcount", error = "errorno")
+ if (error != 0)
+ printf("Error = %d\n", error);
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+ }
+ }
+##}
+
+
+##check_nfs_counts(id, n, hint)
+##int id, hint;
+struct nfsphys *n;
+##{
+## int val, rowcount;
+
+ val = n->count;
+ if (n->allocated != val) {
+ printf("Count wrong on NFSphys %s:%s; is %d in db, counted %d\n",
+ ((struct machine *) hash_lookup(machines, n->mach_id))->name,
+ n->dir, n->allocated, val);
+ if (single_fix("Update", 1)) {
+## replace nfsphys (allocated = val) where nfsphys.nfsphys_id = id
+## inquire_equel(rowcount = "rowcount")
+ if (rowcount > 0)
+ printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
+ else
+ printf("Not fixed\n");
+ }
+ }
+##}
+
+
+phase4()
+##{
+ struct hash *boxes, *counts;
+## int id, cnt;
+
+ printf("Phase 4 - Checking counts\n");
+
+ dprintf("Doing POBoxes...\n");
+ boxes = create_hash(10);
+ counts = create_hash(10);
+## retrieve (id = serverhosts.mach_id, cnt = serverhosts.value1)
+## where serverhosts.service = "POP" {
+ hash_store(boxes, id, 1);
+ hash_store(counts, id, cnt);
+## }
+ hash_step(users, count_boxes, boxes);
+ hash_step(boxes, check_box_counts, counts);
+
+ dprintf("Doing NFSphys...\n");
+ hash_step(nfsphys, check_nfs_counts, 0);
+##}
+
+
+count_only_setup()
+##{
+## int id, status, id2, id3;
+## char name[33], last[17], first[17], buf[257];
+ struct save_queue *sq;
+ struct user *u;
+ struct nfsphys *n;
+ struct machine *m;
+
+ dprintf("Loading users...\n");
+ users = create_hash(10000);
+## range of u is users
+## retrieve (id = u.users_id, name = u.login, last = u.#last,
+## first = u.#first, status = u.#status, buf = u.potype,
+## id2 = u.pop_id, id3 = u.box_id)
+## where u.potype != "NONE" {
+ u = (struct user *) malloc(sizeof(struct user));
+ strcpy(u->login, strtrim(name));
+ u->potype = buf[0];
+ sprintf(buf, "%s, %s", strtrim(last), strtrim(first));
+ u->fullname = strsave(buf);
+ u->status = status;
+ u->users_id = id;
+ switch (u->potype) {
+ case 'P':
+ u->pobox_id = id2;
+ break;
+ case 'S':
+ u->pobox_id = id3;
+ break;
+ default:
+ u->pobox_id = 0;
+ }
+ hash_store(users, id, u);
+## }
+
+ dprintf("Loading machines...\n");
+ machines = create_hash(1000);
+## range of m is machine
+## retrieve (id = m.mach_id, name = m.#name) {
+ m = (struct machine *) malloc(sizeof(struct machine));
+ strcpy(m->name, strtrim(name));
+ m->mach_id = id;
+ hash_store(machines, id, m);
+## }
+
+ dprintf("Loading nfsphys...\n");
+ nfsphys = create_hash(500);
+## retrieve (id = nfsphys.nfsphys_id, name = nfsphys.dir,
+## id2 = nfsphys.mach_id, id3 = nfsphys.allocated) {
+ n = (struct nfsphys *) malloc(sizeof(struct nfsphys));
+ strcpy(n->dir, strtrim(name));
+ n->mach_id = id2;
+ n->nfsphys_id = id;
+ n->allocated = id3;
+ n->count = 0;
+ hash_store(nfsphys, id, n);
+## }
+
+ dprintf("Counting quotas...\n");
+## retrieve (id = nfsquota.phys_id, id2 = nfsquota.quota) {
+ if (n = (struct nfsphys *) hash_lookup(nfsphys, id)) {
+ n->count += id2;
+ }
+## }
+##}