]> andersk Git - moira.git/blob - afssync/resync.qc
Initial revision
[moira.git] / afssync / resync.qc
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))
19 struct hash *users, *groups, *usersid, *groupsid;
20 char *whoami = "sync";
21
22 char *malloc(), *strsave();
23 int dbase_fd;
24 struct prheader prh;
25
26
27 main(argc, argv)
28 int argc;
29 char **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
71 static 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
89 prserror(status, msg, arg1, arg2)
90 int status;
91 char *msg;
92 unsigned 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
136 nomem(msg)
137 char *msg;
138 {
139     fprintf(stderr, "Out of memory: %s\n", msg);
140     exit(1);
141 }
142
143
144 struct user {
145     char login[9];
146     char flag;
147     short uid;
148 };
149
150
151 get_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
177 struct chunk {
178     short member[CHUNKSIZE];
179     struct chunk *xmem;
180 };
181
182 struct group {
183     char name[33];
184     char flag;
185     short gid;
186     short members;
187     struct chunk ch;
188 };
189
190
191 get_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
215 get_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
260 checkuser(id, u)
261 int id;
262 struct 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
268 checkgroup(id, g)
269 int id;
270 struct 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
287 check_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
303 check_entry(offset)
304 int 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
346 do_members(e, g)
347 struct prentry *e;
348 struct 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
372 mark_member(g, uid)
373 struct group *g;
374 int 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.069775 seconds and 5 git commands to generate.