5 #include <mit-copyright.h>
17 #define min(x,y) ((x) < (y) ? (x) : (y))
18 #define abs(x) (((x) > 0) ? (x) : -(x))
19 struct hash *users, *groups, *usersid, *groupsid;
20 char *whoami = "sync";
22 char *malloc(), *strsave();
34 fprintf(stderr, "usage: %s dbfile\n", argv[0]);
38 dbase_fd = open(argv[1], O_RDONLY, 0660);
40 perror("opening file %s", argv[1]);
44 initialize_sms_error_table ();
47 ## set lockmode session where level = table
57 pr_Read(NULL, 0, 0, &prh, sizeof(prh));
58 check_users_and_groups();
65 * ingerr: (supposedly) called when Ingres indicates an error.
66 * I have not yet been able to get this to work to intercept a
67 * database open error.
69 #define INGRES_DEADLOCK 4700
71 static int ingerr(num)
79 ingres_errno = SMS_DEADLOCK;
82 ingres_errno = SMS_INGRES_ERR;
84 com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
89 prserror(status, msg, arg1, arg2)
92 unsigned long arg1, arg2;
96 sprintf(buf, msg, arg1, arg2);
99 msg = "name already exists";
102 msg = "ID already exists";
105 msg = "no IDs available";
108 msg = "database failed";
111 msg = "no space left in database";
114 msg = "permission denied";
129 msg = "unknown code";
132 fprintf(stderr, "%s (%d): %s\n", msg, status, buf);
139 fprintf(stderr, "Out of memory: %s\n", msg);
157 fprintf(stderr, "Loading users from Moira\n");
158 users = create_hash(10000);
159 usersid = create_hash(10000);
160 ## range of u is users
161 ## retrieve (login = u.#login, uid = u.#uid, id = u.users_id)
162 ## where u.#status = 1 {
164 u = (struct user *)malloc(sizeof(struct user));
166 nomem("loading users");
167 strncpy(u->login, login, 9);
170 hash_store(users, uid, u);
171 hash_store(usersid, id, u);
178 short member[CHUNKSIZE];
197 fprintf(stderr, "Loading groups from Moira\n");
198 groups = create_hash(10000);
199 groupsid = create_hash(10000);
200 ## range of l is list
201 ## retrieve (name = l.#name, gid = l.#gid, id = l.list_id)
202 ## where l.#active = 1 and l.#group = 1 {
204 g = (struct group *)malloc(sizeof(struct group));
206 nomem("loading groups");
207 bzero(g, sizeof(struct group));
208 strncpy(g->name, name, 33);
209 hash_store(groups, gid, g);
210 hash_store(groupsid, id, g);
221 fprintf(stderr, "Fetching members from Moira\n");
223 ## range of m is imembers
225 ## retrieve (lid = m.list_id, id = m.member_id)
226 ## where m.member_type = "USER" {
227 if ((u = (struct user *) hash_lookup(usersid, id)) &&
228 (g = (struct group *) hash_lookup(groupsid, lid))) {
229 if (g->members < CHUNKSIZE) {
230 g->ch.member[g->members] = u->uid;
232 int i = g->members - CHUNKSIZE;
235 if ((c = g->ch.xmem) == NULL) {
236 c = (struct chunk *) malloc(sizeof(struct chunk));
238 nomem("loading members");
241 while (i >= CHUNKSIZE) {
243 if (c->xmem == NULL) {
244 c->xmem = (struct chunk *) malloc(sizeof(struct chunk));
246 nomem("loading members");
250 c->member[i] = u->uid;
265 printf("< User %s id %d is in Moira but not in prs\n", u->login, u->uid);
276 printf("< Group %s id %d is in Moira but not in prs\n", g->name, g->gid);
277 c = (struct chunk *)&(g->ch);
278 for (i = 0; i < g->members; i++) {
280 printf("< Group %s contains user %d in Moira but not in prs\n",
281 g->name, c->member[j]);
282 if (j == CHUNKSIZE - 1)
287 check_users_and_groups()
292 fprintf(stderr, "Scanning PRS database\n");
294 for (i = 0; i < HASHSIZE; i++) {
295 offset = ntohl(prh.idHash[i]);
297 offset = check_entry(offset);
299 hash_step(users, checkuser, NULL);
300 hash_step(groups, checkgroup, NULL);
306 struct prentry entry;
307 int flags, id, status;
311 status = pr_Read(NULL, 0, offset, &entry, sizeof(entry));
313 prserror(status, "reading prentry at %d", offset, 0);
314 flags = ntohl(entry.flags);
315 id = ntohl(entry.id);
316 if ((flags & PRFREE) == 0) {
318 g = (struct group *) hash_lookup(groups, abs(id));
320 printf("> Group %s, id %d is in prs but not moira\n",
322 else if (strcasecmp(g->name, index(entry.name, ':')+1))
323 printf("> Group id %d in prs is %s, but GID %d in moira is %s\n",
324 id, entry.name, -id, g->name);
327 if (entry.entries[0])
328 do_members(&entry, g);
331 u = (struct user *) hash_lookup(users, abs(id));
333 printf("> User %s, id %d is in prs but not moira\n",
335 else if (strcasecmp(u->login, entry.name))
336 printf("> User id %d in prs is %s, but UID %d in moira is %s\n",
337 id, entry.name, id, u->login);
342 return(ntohl(entry.nextID));
352 struct contentry prco;
354 for (i = 0; i < PRSIZE; i++) {
355 if (e->entries[i] == 0)
357 mark_member(g, ntohl(e->entries[i]));
359 offset = ntohl(e->next);
361 pr_Read(NULL, 0, offset, &prco, sizeof(struct contentry));
362 for (i = 0; i < COSIZE; i++) {
363 if (prco.entries[i] == 0)
365 mark_member(g, ntohl(prco.entries[i]));
367 offset = ntohl(prco.next);
378 if (g->members >= CHUNKSIZE) {
380 struct chunk *c = (struct chunk *)&(g->ch);
382 for (i = 0; i < g->members; i++) {
384 if (c->member[j] == uid) {
387 if (j == CHUNKSIZE - 1) {
388 s1 = c->member[CHUNKSIZE - 1];
392 if (j != CHUNKSIZE - 1)
399 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
403 for (i = 0; i < g->members; i++) {
404 if (g->ch.member[i] == uid) {
405 if (g->members == i + 1)
408 g->ch.member[i] = g->ch.member[g->members];
409 g->ch.member[g->members] = 0;
415 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,