From: mar Date: Tue, 26 Sep 1989 12:10:47 +0000 (+0000) Subject: Initial revision X-Git-Tag: ASRSNAP1001~2 X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/commitdiff_plain/a04caf146da019bfb94e5cd5541625e6da793ba1 Initial revision --- diff --git a/afssync/Makefile b/afssync/Makefile new file mode 100644 index 00000000..c3e4fd96 --- /dev/null +++ b/afssync/Makefile @@ -0,0 +1,36 @@ +# $Header$ + +CFLAGS = -I/mit/afsdev/build/vax/include -I../include -O + +OBJS = prprocs.o prutils.o utils.o ubik.o +LIBS= -L../lib -lsms -lcom_err \ + /usr/rtingres/lib/libqlib /usr/rtingres/lib/compatlib + +.SUFFIXES: .qc + +.qc.c: + rm -f $*.c + /usr/rtingres/bin/eqc -p $* + +all: sync resync + +sync: sync.o $(OBJS) + cc -o sync sync.o $(OBJS) $(LIBS) +sync.c: sync.qc + +resync: resync.o $(OBJS) + cc -o resync resync.o $(OBJS) $(LIBS) +resync.c: resync.qc + +prnewuser: prnewuser.o $(OBJS) + cc -o prnewuser prnewuser.o $(OBJS) + +prnewlist: prnewlist.o $(OBJS) + cc -o prnewlist prnewlist.o $(OBJS) + +startsync: startsync.o + cc -o startsync startsync.o + + +clean: + rm -f *.o resync.c sync.c resync sync startsync prnewlist prnewuser diff --git a/afssync/resync.qc b/afssync/resync.qc new file mode 100644 index 00000000..e81d30f5 --- /dev/null +++ b/afssync/resync.qc @@ -0,0 +1,417 @@ +/* $Header$ + * + */ + +#include +#include +#include +#include +#include "print.h" +#include "prserver.h" +#include "prerror.h" +#include +#include +#include + + +#define min(x,y) ((x) < (y) ? (x) : (y)) +#define abs(x) (((x) > 0) ? (x) : -(x)) +struct hash *users, *groups, *usersid, *groupsid; +char *whoami = "sync"; + +char *malloc(), *strsave(); +int dbase_fd; +struct prheader prh; + + +main(argc, argv) +int argc; +char **argv; +{ + int ingerr(); + + if (argc != 2) { + fprintf(stderr, "usage: %s dbfile\n", argv[0]); + exit(SMS_ARGS); + } + + dbase_fd = open(argv[1], O_RDONLY, 0660); + if (dbase_fd < 0) { + perror("opening file %s", argv[1]); + exit(1); + } + IIseterr(ingerr); + initialize_sms_error_table (); + +## ingres sms +## set lockmode session where level = table +## begin transaction + + get_users(); + get_groups(); + get_members(); + +## end transaction +## exit + + pr_Read(NULL, 0, 0, &prh, sizeof(prh)); + check_users_and_groups(); + + exit(SMS_SUCCESS); +} + + +/* + * ingerr: (supposedly) called when Ingres indicates an error. + * I have not yet been able to get this to work to intercept a + * database open error. + */ +#define INGRES_DEADLOCK 4700 + +static int ingerr(num) + int *num; +{ + char buf[256]; + int ingres_errno; + + switch (*num) { + case INGRES_DEADLOCK: + ingres_errno = SMS_DEADLOCK; + break; + default: + ingres_errno = SMS_INGRES_ERR; + } + com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num); + exit(ingres_errno); +} + + +prserror(status, msg, arg1, arg2) +int status; +char *msg; +unsigned long arg1, arg2; +{ + char buf[512]; + + sprintf(buf, msg, arg1, arg2); + switch (status) { + case PREXIST: + msg = "name already exists"; + break; + case PRIDEXIST: + msg = "ID already exists"; + break; + case PRNOIDS: + msg = "no IDs available"; + break; + case PRDBFAIL: + msg = "database failed"; + break; + case PRNOENT: + msg = "no space left in database"; + break; + case PRPERM: + msg = "permission denied"; + break; + case PRNOTGROUP: + msg = "not a group"; + break; + case PRNOTUSER: + msg = "not a user"; + break; + case PRBADNAM: + msg = "bad name"; + break; + case 0: + msg = "no error"; + break; + default: + msg = "unknown code"; + break; + } + fprintf(stderr, "%s (%d): %s\n", msg, status, buf); +} + + +nomem(msg) +char *msg; +{ + fprintf(stderr, "Out of memory: %s\n", msg); + exit(1); +} + + +struct user { + char login[9]; + char flag; + short uid; +}; + + +get_users() +##{ +## char login[9]; +## int uid, id; + struct user *u; + + fprintf(stderr, "Loading users from Moira\n"); + users = create_hash(10000); + usersid = create_hash(10000); +## range of u is users +## retrieve (login = u.#login, uid = u.#uid, id = u.users_id) +## where u.#status = 1 { + strtrim(login); + u = (struct user *)malloc(sizeof(struct user)); + if (u == NULL) + nomem("loading users"); + strncpy(u->login, login, 9); + u->flag = 0; + u->uid = uid; + hash_store(users, uid, u); + hash_store(usersid, id, u); +## } +##} + + +#define CHUNKSIZE 10 +struct chunk { + short member[CHUNKSIZE]; + struct chunk *xmem; +}; + +struct group { + char name[33]; + char flag; + short gid; + short members; + struct chunk ch; +}; + + +get_groups() +##{ +## char name[33]; +## int gid, id; + struct group *g; + + fprintf(stderr, "Loading groups from Moira\n"); + groups = create_hash(10000); + groupsid = create_hash(10000); +## range of l is list +## retrieve (name = l.#name, gid = l.#gid, id = l.list_id) +## where l.#active = 1 and l.#group = 1 { + strtrim(name); + g = (struct group *)malloc(sizeof(struct group)); + if (g == NULL) + nomem("loading groups"); + bzero(g, sizeof(struct group)); + strncpy(g->name, name, 33); + hash_store(groups, gid, g); + hash_store(groupsid, id, g); +## } +##} + + +get_members() +##{ + struct user *u; + struct group *g; +## int id, lid; + + fprintf(stderr, "Fetching members from Moira\n"); + +## range of m is imembers + +## retrieve (lid = m.list_id, id = m.member_id) +## where m.member_type = "USER" { + if ((u = (struct user *) hash_lookup(usersid, id)) && + (g = (struct group *) hash_lookup(groupsid, lid))) { + if (g->members < CHUNKSIZE) { + g->ch.member[g->members] = u->uid; + } else { + int i = g->members - CHUNKSIZE; + struct chunk *c; + + if ((c = g->ch.xmem) == NULL) { + c = (struct chunk *) malloc(sizeof(struct chunk)); + if (c == NULL) + nomem("loading members"); + g->ch.xmem = c; + } + while (i >= CHUNKSIZE) { + i -= CHUNKSIZE; + if (c->xmem == NULL) { + c->xmem = (struct chunk *) malloc(sizeof(struct chunk)); + if (c->xmem == NULL) + nomem("loading members"); + } + c = c->xmem; + } + c->member[i] = u->uid; + } + g->members++; + } +## } + +##} + + + +checkuser(id, u) +int id; +struct user *u; +{ + if (u->flag == 0) + printf("< User %s id %d is in Moira but not in prs\n", u->login, u->uid); +} + +checkgroup(id, g) +int id; +struct group *g; +{ + register int i, j; + struct chunk *c; + + if (g->flag == 0) + printf("< Group %s id %d is in Moira but not in prs\n", g->name, g->gid); + c = (struct chunk *)&(g->ch); + for (i = 0; i < g->members; i++) { + j = i % CHUNKSIZE; + printf("< Group %s contains user %d in Moira but not in prs\n", + g->name, c->member[j]); + if (j == CHUNKSIZE - 1) + c = c->xmem; + } +} + +check_users_and_groups() +{ + register int i; + int offset; + + fprintf(stderr, "Scanning PRS database\n"); + + for (i = 0; i < HASHSIZE; i++) { + offset = ntohl(prh.idHash[i]); + while (offset) + offset = check_entry(offset); + } + hash_step(users, checkuser, NULL); + hash_step(groups, checkgroup, NULL); +} + +check_entry(offset) +int offset; +{ + struct prentry entry; + int flags, id, status; + struct user *u; + struct group *g; + + status = pr_Read(NULL, 0, offset, &entry, sizeof(entry)); + if (status) + prserror(status, "reading prentry at %d", offset, 0); + flags = ntohl(entry.flags); + id = ntohl(entry.id); + if ((flags & PRFREE) == 0) { + if (flags & PRGRP) { + g = (struct group *) hash_lookup(groups, abs(id)); + if (g == NULL) + printf("> Group %s, id %d is in prs but not moira\n", + entry.name, id); + else if (strcasecmp(g->name, index(entry.name, ':')+1)) + printf("> Group id %d in prs is %s, but GID %d in moira is %s\n", + id, entry.name, -id, g->name); + else { + g->flag = 1; + if (entry.entries[0]) + do_members(&entry, g); + } + } else { + u = (struct user *) hash_lookup(users, abs(id)); + if (u == NULL) + printf("> User %s, id %d is in prs but not moira\n", + entry.name, id); + else if (strcasecmp(u->login, entry.name)) + printf("> User id %d in prs is %s, but UID %d in moira is %s\n", + id, entry.name, id, u->login); + else + u->flag = 1; + } + } + return(ntohl(entry.nextID)); +} + + +do_members(e, g) +struct prentry *e; +struct group *g; +{ + register int i; + int offset; + struct contentry prco; + + for (i = 0; i < PRSIZE; i++) { + if (e->entries[i] == 0) + return; + mark_member(g, ntohl(e->entries[i])); + } + offset = ntohl(e->next); + while (offset) { + pr_Read(NULL, 0, offset, &prco, sizeof(struct contentry)); + for (i = 0; i < COSIZE; i++) { + if (prco.entries[i] == 0) + return; + mark_member(g, ntohl(prco.entries[i])); + } + offset = ntohl(prco.next); + } +} + + +mark_member(g, uid) +struct group *g; +int uid; +{ + register int i, j; + + if (g->members >= CHUNKSIZE) { + short *s = NULL, s1; + struct chunk *c = (struct chunk *)&(g->ch); + + for (i = 0; i < g->members; i++) { + j = i % CHUNKSIZE; + if (c->member[j] == uid) { + s = &(c->member[j]); + } + if (j == CHUNKSIZE - 1) { + s1 = c->member[CHUNKSIZE - 1]; + c = c->xmem; + } + } + if (j != CHUNKSIZE - 1) + s1 = c->member[j]; + if (s) { + *s = s1; + g->members--; + return; + } + printf("> Group %s contains user %d in prs but not in Moira\n", g->name, + uid); + return; + } + for (i = 0; i < g->members; i++) { + if (g->ch.member[i] == uid) { + if (g->members == i + 1) + g->ch.member[i] = 0; + else { + g->ch.member[i] = g->ch.member[g->members]; + g->ch.member[g->members] = 0; + } + g->members--; + return; + } + } + printf("> Group %s contains user %d in prs but not in Moira\n", g->name, + uid); +}