]> andersk Git - moira.git/blame - afssync/resync.qc
type-check access flags
[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>
9#include "print.h"
10#include "prserver.h"
11#include "prerror.h"
12#include <sms.h>
13#include <sms_app.h>
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
22char *malloc(), *strsave();
23int dbase_fd;
24struct prheader prh;
25
26
27main(argc, argv)
28int argc;
29char **argv;
30{
31 int ingerr();
32
33 if (argc != 2) {
34 fprintf(stderr, "usage: %s dbfile\n", argv[0]);
35 exit(SMS_ARGS);
36 }
37
38 dbase_fd = open(argv[1], O_RDONLY, 0660);
39 if (dbase_fd < 0) {
40 perror("opening file %s", argv[1]);
41 exit(1);
42 }
43 IIseterr(ingerr);
44 initialize_sms_error_table ();
45
46## ingres sms
47## set lockmode session where level = table
48## begin transaction
49
50 get_users();
51 get_groups();
52 get_members();
53
54## end transaction
55## exit
56
57 pr_Read(NULL, 0, 0, &prh, sizeof(prh));
58 check_users_and_groups();
59
60 exit(SMS_SUCCESS);
61}
62
63
64/*
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.
68 */
69#define INGRES_DEADLOCK 4700
70
71static int ingerr(num)
72 int *num;
73{
74 char buf[256];
75 int ingres_errno;
76
77 switch (*num) {
78 case INGRES_DEADLOCK:
79 ingres_errno = SMS_DEADLOCK;
80 break;
81 default:
82 ingres_errno = SMS_INGRES_ERR;
83 }
84 com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
85 exit(ingres_errno);
86}
87
88
89prserror(status, msg, arg1, arg2)
90int status;
91char *msg;
92unsigned long arg1, arg2;
93{
94 char buf[512];
95
96 sprintf(buf, msg, arg1, arg2);
97 switch (status) {
98 case PREXIST:
99 msg = "name already exists";
100 break;
101 case PRIDEXIST:
102 msg = "ID already exists";
103 break;
104 case PRNOIDS:
105 msg = "no IDs available";
106 break;
107 case PRDBFAIL:
108 msg = "database failed";
109 break;
110 case PRNOENT:
111 msg = "no space left in database";
112 break;
113 case PRPERM:
114 msg = "permission denied";
115 break;
116 case PRNOTGROUP:
117 msg = "not a group";
118 break;
119 case PRNOTUSER:
120 msg = "not a user";
121 break;
122 case PRBADNAM:
123 msg = "bad name";
124 break;
125 case 0:
126 msg = "no error";
127 break;
128 default:
129 msg = "unknown code";
130 break;
131 }
132 fprintf(stderr, "%s (%d): %s\n", msg, status, buf);
133}
134
135
136nomem(msg)
137char *msg;
138{
139 fprintf(stderr, "Out of memory: %s\n", msg);
140 exit(1);
141}
142
143
144struct user {
145 char login[9];
146 char flag;
147 short uid;
148};
149
150
151get_users()
152##{
153## char login[9];
154## int uid, id;
155 struct user *u;
156
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 {
163 strtrim(login);
164 u = (struct user *)malloc(sizeof(struct user));
165 if (u == NULL)
166 nomem("loading users");
167 strncpy(u->login, login, 9);
168 u->flag = 0;
169 u->uid = uid;
170 hash_store(users, uid, u);
171 hash_store(usersid, id, u);
172## }
173##}
174
175
176#define CHUNKSIZE 10
177struct chunk {
178 short member[CHUNKSIZE];
179 struct chunk *xmem;
180};
181
182struct group {
183 char name[33];
184 char flag;
185 short gid;
186 short members;
187 struct chunk ch;
188};
189
190
191get_groups()
192##{
193## char name[33];
194## int gid, id;
195 struct group *g;
196
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 {
203 strtrim(name);
204 g = (struct group *)malloc(sizeof(struct group));
205 if (g == NULL)
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);
211## }
212##}
213
214
215get_members()
216##{
217 struct user *u;
218 struct group *g;
219## int id, lid;
220
221 fprintf(stderr, "Fetching members from Moira\n");
222
223## range of m is imembers
224
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;
231 } else {
232 int i = g->members - CHUNKSIZE;
233 struct chunk *c;
234
235 if ((c = g->ch.xmem) == NULL) {
236 c = (struct chunk *) malloc(sizeof(struct chunk));
237 if (c == NULL)
238 nomem("loading members");
239 g->ch.xmem = c;
240 }
241 while (i >= CHUNKSIZE) {
242 i -= CHUNKSIZE;
243 if (c->xmem == NULL) {
244 c->xmem = (struct chunk *) malloc(sizeof(struct chunk));
245 if (c->xmem == NULL)
246 nomem("loading members");
247 }
248 c = c->xmem;
249 }
250 c->member[i] = u->uid;
251 }
252 g->members++;
253 }
254## }
255
256##}
257
258
259
260checkuser(id, u)
261int id;
262struct user *u;
263{
264 if (u->flag == 0)
265 printf("< User %s id %d is in Moira but not in prs\n", u->login, u->uid);
266}
267
268checkgroup(id, g)
269int id;
270struct group *g;
271{
272 register int i, j;
273 struct chunk *c;
274
275 if (g->flag == 0)
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++) {
279 j = i % CHUNKSIZE;
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)
283 c = c->xmem;
284 }
285}
286
287check_users_and_groups()
288{
289 register int i;
290 int offset;
291
292 fprintf(stderr, "Scanning PRS database\n");
293
294 for (i = 0; i < HASHSIZE; i++) {
295 offset = ntohl(prh.idHash[i]);
296 while (offset)
297 offset = check_entry(offset);
298 }
299 hash_step(users, checkuser, NULL);
300 hash_step(groups, checkgroup, NULL);
301}
302
303check_entry(offset)
304int offset;
305{
306 struct prentry entry;
307 int flags, id, status;
308 struct user *u;
309 struct group *g;
310
311 status = pr_Read(NULL, 0, offset, &entry, sizeof(entry));
312 if (status)
313 prserror(status, "reading prentry at %d", offset, 0);
314 flags = ntohl(entry.flags);
315 id = ntohl(entry.id);
316 if ((flags & PRFREE) == 0) {
317 if (flags & PRGRP) {
318 g = (struct group *) hash_lookup(groups, abs(id));
319 if (g == NULL)
320 printf("> Group %s, id %d is in prs but not moira\n",
321 entry.name, id);
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);
325 else {
326 g->flag = 1;
327 if (entry.entries[0])
328 do_members(&entry, g);
329 }
330 } else {
331 u = (struct user *) hash_lookup(users, abs(id));
332 if (u == NULL)
333 printf("> User %s, id %d is in prs but not moira\n",
334 entry.name, id);
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);
338 else
339 u->flag = 1;
340 }
341 }
342 return(ntohl(entry.nextID));
343}
344
345
346do_members(e, g)
347struct prentry *e;
348struct group *g;
349{
350 register int i;
351 int offset;
352 struct contentry prco;
353
354 for (i = 0; i < PRSIZE; i++) {
355 if (e->entries[i] == 0)
356 return;
357 mark_member(g, ntohl(e->entries[i]));
358 }
359 offset = ntohl(e->next);
360 while (offset) {
361 pr_Read(NULL, 0, offset, &prco, sizeof(struct contentry));
362 for (i = 0; i < COSIZE; i++) {
363 if (prco.entries[i] == 0)
364 return;
365 mark_member(g, ntohl(prco.entries[i]));
366 }
367 offset = ntohl(prco.next);
368 }
369}
370
371
372mark_member(g, uid)
373struct group *g;
374int uid;
375{
376 register int i, j;
377
378 if (g->members >= CHUNKSIZE) {
379 short *s = NULL, s1;
380 struct chunk *c = (struct chunk *)&(g->ch);
381
382 for (i = 0; i < g->members; i++) {
383 j = i % CHUNKSIZE;
384 if (c->member[j] == uid) {
385 s = &(c->member[j]);
386 }
387 if (j == CHUNKSIZE - 1) {
388 s1 = c->member[CHUNKSIZE - 1];
389 c = c->xmem;
390 }
391 }
392 if (j != CHUNKSIZE - 1)
393 s1 = c->member[j];
394 if (s) {
395 *s = s1;
396 g->members--;
397 return;
398 }
399 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
400 uid);
401 return;
402 }
403 for (i = 0; i < g->members; i++) {
404 if (g->ch.member[i] == uid) {
405 if (g->members == i + 1)
406 g->ch.member[i] = 0;
407 else {
408 g->ch.member[i] = g->ch.member[g->members];
409 g->ch.member[g->members] = 0;
410 }
411 g->members--;
412 return;
413 }
414 }
415 printf("> Group %s contains user %d in prs but not in Moira\n", g->name,
416 uid);
417}
This page took 0.795458 seconds and 5 git commands to generate.