]> andersk Git - moira.git/blame - afssync/resync.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / afssync / resync.qc
CommitLineData
a04caf14 1/* $Header$
2 *
3 */
4
5#include <mit-copyright.h>
6#include <stdio.h>
7#include <sys/file.h>
8#include <rx/xdr.h>
dba0cf81 9#include <afs/ptint.h>
10#include <afs/ptserver.h>
11#include <afs/pterror.h>
e88f0823 12#include <moira.h>
13#include <moira_site.h>
a04caf14 14#include <ctype.h>
15
16
17#define min(x,y) ((x) < (y) ? (x) : (y))
18#define abs(x) (((x) > 0) ? (x) : -(x))
19struct hash *users, *groups, *usersid, *groupsid;
20char *whoami = "sync";
21
e88f0823 22char *malloc(), *strsave(), *perm_malloc();
a04caf14 23int dbase_fd;
e88f0823 24int replaceflag = 0;
a04caf14 25struct prheader prh;
26
27
28main(argc, argv)
29int argc;
30char **argv;
31{
e88f0823 32 int i;
33 char *file = NULL;
a04caf14 34 int ingerr();
35
e88f0823 36 for (i = 1; i < argc; i++) {
37 if (argv[i][0] == '-') {
38 switch (argv[i][1]) {
39 case 'r':
40 replaceflag++;
41 break;
42 default:
43 usage(argv[0]);
44 }
45 } else {
46 if (file == NULL)
47 file = argv[i];
48 else
49 usage(argv[0]);
50 }
a04caf14 51 }
52
e88f0823 53 i = O_RDONLY;
54 if (replaceflag)
55 i = O_RDWR;
56 dbase_fd = open(file, i, 0660);
a04caf14 57 if (dbase_fd < 0) {
e88f0823 58 perror("opening file %s", file);
a04caf14 59 exit(1);
60 }
61 IIseterr(ingerr);
62 initialize_sms_error_table ();
63
64## ingres sms
65## set lockmode session where level = table
66## begin transaction
67
68 get_users();
69 get_groups();
70 get_members();
71
72## end transaction
73## exit
74
75 pr_Read(NULL, 0, 0, &prh, sizeof(prh));
76 check_users_and_groups();
77
e88f0823 78 exit(MR_SUCCESS);
79}
80
81usage(name)
82char *name;
83{
84 fprintf(stderr, "usage: %s [-r] dbfile\n", name);
85 exit(MR_ARGS);
a04caf14 86}
87
88
89/*
90 * ingerr: (supposedly) called when Ingres indicates an error.
91 * I have not yet been able to get this to work to intercept a
92 * database open error.
93 */
94#define INGRES_DEADLOCK 4700
95
96static int ingerr(num)
97 int *num;
98{
99 char buf[256];
100 int ingres_errno;
101
102 switch (*num) {
103 case INGRES_DEADLOCK:
e88f0823 104 ingres_errno = MR_DEADLOCK;
a04caf14 105 break;
106 default:
e88f0823 107 ingres_errno = MR_INGRES_ERR;
a04caf14 108 }
e88f0823 109 com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
a04caf14 110 exit(ingres_errno);
111}
112
113
114prserror(status, msg, arg1, arg2)
115int status;
116char *msg;
117unsigned long arg1, arg2;
118{
119 char buf[512];
120
121 sprintf(buf, msg, arg1, arg2);
122 switch (status) {
123 case PREXIST:
124 msg = "name already exists";
125 break;
126 case PRIDEXIST:
127 msg = "ID already exists";
128 break;
129 case PRNOIDS:
130 msg = "no IDs available";
131 break;
132 case PRDBFAIL:
133 msg = "database failed";
134 break;
135 case PRNOENT:
136 msg = "no space left in database";
137 break;
138 case PRPERM:
139 msg = "permission denied";
140 break;
141 case PRNOTGROUP:
142 msg = "not a group";
143 break;
144 case PRNOTUSER:
145 msg = "not a user";
146 break;
147 case PRBADNAM:
148 msg = "bad name";
149 break;
150 case 0:
151 msg = "no error";
152 break;
153 default:
154 msg = "unknown code";
155 break;
156 }
157 fprintf(stderr, "%s (%d): %s\n", msg, status, buf);
158}
159
160
161nomem(msg)
162char *msg;
163{
164 fprintf(stderr, "Out of memory: %s\n", msg);
165 exit(1);
166}
167
168
169struct user {
170 char login[9];
171 char flag;
172 short uid;
173};
174
175
176get_users()
177##{
178## char login[9];
179## int uid, id;
180 struct user *u;
181
182 fprintf(stderr, "Loading users from Moira\n");
183 users = create_hash(10000);
184 usersid = create_hash(10000);
185## range of u is users
186## retrieve (login = u.#login, uid = u.#uid, id = u.users_id)
187## where u.#status = 1 {
188 strtrim(login);
e88f0823 189 u = (struct user *)perm_malloc(sizeof(struct user));
a04caf14 190 if (u == NULL)
191 nomem("loading users");
192 strncpy(u->login, login, 9);
193 u->flag = 0;
194 u->uid = uid;
195 hash_store(users, uid, u);
196 hash_store(usersid, id, u);
197## }
198##}
199
200
e88f0823 201#define CHUNKSIZE 5
a04caf14 202struct chunk {
203 short member[CHUNKSIZE];
204 struct chunk *xmem;
205};
206
207struct group {
208 char name[33];
209 char flag;
210 short gid;
211 short members;
212 struct chunk ch;
213};
214
215
216get_groups()
217##{
218## char name[33];
219## int gid, id;
220 struct group *g;
221
222 fprintf(stderr, "Loading groups from Moira\n");
223 groups = create_hash(10000);
224 groupsid = create_hash(10000);
225## range of l is list
226## retrieve (name = l.#name, gid = l.#gid, id = l.list_id)
227## where l.#active = 1 and l.#group = 1 {
228 strtrim(name);
e88f0823 229 g = (struct group *)perm_malloc(sizeof(struct group));
a04caf14 230 if (g == NULL)
231 nomem("loading groups");
232 bzero(g, sizeof(struct group));
233 strncpy(g->name, name, 33);
e88f0823 234 g->gid = gid;
a04caf14 235 hash_store(groups, gid, g);
236 hash_store(groupsid, id, g);
237## }
238##}
239
240
241get_members()
242##{
243 struct user *u;
244 struct group *g;
245## int id, lid;
246
247 fprintf(stderr, "Fetching members from Moira\n");
248
249## range of m is imembers
250
251## retrieve (lid = m.list_id, id = m.member_id)
252## where m.member_type = "USER" {
253 if ((u = (struct user *) hash_lookup(usersid, id)) &&
254 (g = (struct group *) hash_lookup(groupsid, lid))) {
255 if (g->members < CHUNKSIZE) {
256 g->ch.member[g->members] = u->uid;
257 } else {
258 int i = g->members - CHUNKSIZE;
259 struct chunk *c;
260
261 if ((c = g->ch.xmem) == NULL) {
e88f0823 262 c = (struct chunk *) perm_malloc(sizeof(struct chunk));
a04caf14 263 if (c == NULL)
264 nomem("loading members");
265 g->ch.xmem = c;
266 }
267 while (i >= CHUNKSIZE) {
268 i -= CHUNKSIZE;
269 if (c->xmem == NULL) {
e88f0823 270 c->xmem = (struct chunk *) perm_malloc(sizeof(struct chunk));
a04caf14 271 if (c->xmem == NULL)
272 nomem("loading members");
273 }
274 c = c->xmem;
275 }
276 c->member[i] = u->uid;
277 }
278 g->members++;
279 }
280## }
281
282##}
283
284
285
286checkuser(id, u)
287int id;
288struct user *u;
289{
e88f0823 290 int status;
291
292 if (u->flag == 0) {
293 printf("< User %s id %d is in Moira but not in prs\n",
294 u->login, u->uid);
295 if (replaceflag) {
296 status = PR_INewEntry(NULL, u->login, u->uid, 0);
297 if (status) {
298 prserror(status, "adding user %s uid %d to prs database",
299 u->login, u->uid);
300 }
301 }
302 }
a04caf14 303}
304
305checkgroup(id, g)
306int id;
307struct group *g;
308{
e88f0823 309 register int i, j, status;
a04caf14 310 struct chunk *c;
311
e88f0823 312 if (g->flag == 0) {
313 printf("< Group %s id %d is in Moira but not in prs\n",
314 g->name, g->gid);
315 if (replaceflag) {
316 char namebuf[64];
317 sprintf(namebuf, "system:%s", g->name);
318 status = PR_INewEntry(NULL, namebuf, -g->gid, SYSADMINID);
319 if (status)
320 prserror(status, "adding list %s gid %d to prs database",
321 namebuf, -g->gid);
322 }
323 }
a04caf14 324 c = (struct chunk *)&(g->ch);
325 for (i = 0; i < g->members; i++) {
326 j = i % CHUNKSIZE;
327 printf("< Group %s contains user %d in Moira but not in prs\n",
328 g->name, c->member[j]);
e88f0823 329 if (replaceflag) {
330 status = PR_AddToGroup(NULL, c->member[j], -g->gid);
331 if (status)
332 prserror(status, "adding %d to group %d in prs",
333 c->member[j], -g->gid);
334 }
a04caf14 335 if (j == CHUNKSIZE - 1)
336 c = c->xmem;
337 }
338}
339
340check_users_and_groups()
341{
342 register int i;
343 int offset;
344
345 fprintf(stderr, "Scanning PRS database\n");
346
347 for (i = 0; i < HASHSIZE; i++) {
348 offset = ntohl(prh.idHash[i]);
349 while (offset)
350 offset = check_entry(offset);
351 }
352 hash_step(users, checkuser, NULL);
353 hash_step(groups, checkgroup, NULL);
354}
355
356check_entry(offset)
357int offset;
358{
359 struct prentry entry;
360 int flags, id, status;
361 struct user *u;
362 struct group *g;
363
364 status = pr_Read(NULL, 0, offset, &entry, sizeof(entry));
365 if (status)
366 prserror(status, "reading prentry at %d", offset, 0);
367 flags = ntohl(entry.flags);
368 id = ntohl(entry.id);
369 if ((flags & PRFREE) == 0) {
370 if (flags & PRGRP) {
371 g = (struct group *) hash_lookup(groups, abs(id));
e88f0823 372 if (g == NULL) {
373 if (!strncmp(entry.name, "system:", 7)) {
374 printf("> Group %s, id %d is in prs but not moira\n",
375 entry.name, id);
376 if (replaceflag) {
377 status = PR_Delete(NULL, id);
378 if (status)
379 prserror(status, "deleting group %d from prs", id);
380 }
381 }
382 } else if (strcasecmp(g->name, index(entry.name, ':')+1)) {
383 printf("> GID %d in prs is %s, but GID %d in moira is %s\n",
384 id, entry.name, -id, g->name);
385 if (replaceflag) {
386 printf("*** Dont' know how to fix this!!!!!\n");
387 }
388 } else {
a04caf14 389 g->flag = 1;
390 if (entry.entries[0])
391 do_members(&entry, g);
392 }
393 } else {
394 u = (struct user *) hash_lookup(users, abs(id));
e88f0823 395 if (u == NULL) {
396 printf("> User %s, id %d is in prs but not moira\n",
397 entry.name, id);
398 if (replaceflag) {
399 status = PR_Delete(NULL, id);
400 if (status)
401 prserror(status, "while deleting user %d from prs", id);
402 }
403 } else if (strcasecmp(u->login, entry.name)) {
404 printf("> User id %d in prs is %s, but UID %d in moira is %s\n",
405 id, entry.name, id, u->login);
406 if (replaceflag) {
407 printf("*** don't know how to fix this!!!!!\n");
408 }
409 } else
a04caf14 410 u->flag = 1;
411 }
412 }
413 return(ntohl(entry.nextID));
414}
415
416
417do_members(e, g)
418struct prentry *e;
419struct group *g;
420{
421 register int i;
422 int offset;
423 struct contentry prco;
424
425 for (i = 0; i < PRSIZE; i++) {
426 if (e->entries[i] == 0)
427 return;
428 mark_member(g, ntohl(e->entries[i]));
429 }
430 offset = ntohl(e->next);
431 while (offset) {
432 pr_Read(NULL, 0, offset, &prco, sizeof(struct contentry));
433 for (i = 0; i < COSIZE; i++) {
434 if (prco.entries[i] == 0)
435 return;
436 mark_member(g, ntohl(prco.entries[i]));
437 }
438 offset = ntohl(prco.next);
439 }
440}
441
442
443mark_member(g, uid)
444struct group *g;
445int uid;
446{
e88f0823 447 register int i, j, status;
a04caf14 448
e88f0823 449 if (uid == PRBADID)
450 return;
a04caf14 451 if (g->members >= CHUNKSIZE) {
452 short *s = NULL, s1;
453 struct chunk *c = (struct chunk *)&(g->ch);
454
455 for (i = 0; i < g->members; i++) {
456 j = i % CHUNKSIZE;
457 if (c->member[j] == uid) {
458 s = &(c->member[j]);
459 }
460 if (j == CHUNKSIZE - 1) {
461 s1 = c->member[CHUNKSIZE - 1];
462 c = c->xmem;
463 }
464 }
465 if (j != CHUNKSIZE - 1)
466 s1 = c->member[j];
467 if (s) {
468 *s = s1;
469 g->members--;
470 return;
471 }
472 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
473 uid);
e88f0823 474 if (replaceflag) {
475 status = PR_RemoveFromGroup(NULL, uid, -g->gid);
476 if (status)
477 prserror(status, "While removing user %d from group %d in prs",
478 uid, g->gid);
479 }
a04caf14 480 return;
481 }
482 for (i = 0; i < g->members; i++) {
483 if (g->ch.member[i] == uid) {
484 if (g->members == i + 1)
485 g->ch.member[i] = 0;
486 else {
487 g->ch.member[i] = g->ch.member[g->members];
488 g->ch.member[g->members] = 0;
489 }
490 g->members--;
491 return;
492 }
493 }
494 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
495 uid);
e88f0823 496 if (replaceflag) {
497 status = PR_RemoveFromGroup(NULL, uid, -g->gid);
498 if (status)
499 prserror(status, "While removing user %d from group %d in prs",
500 uid, g->gid);
501 }
a04caf14 502}
e88f0823 503
504
505#define MALLOC_BLOCK 102400
506
507char *perm_malloc(size)
508unsigned size;
509{
510 static char *pool = NULL;
511 static unsigned pool_size = 0;
512 register char *ret;
513
514 if (size > pool_size) {
515 pool = (char *) malloc(MALLOC_BLOCK);
516 pool_size = MALLOC_BLOCK;
517 }
518 ret = pool;
519 pool += size;
520 pool = (char *)(((unsigned) (pool + 1)) & ~1);
521 pool_size -= (pool - ret);
522 return(ret);
523}
524
This page took 0.244088 seconds and 5 git commands to generate.