]> andersk Git - moira.git/blame - dbck/phase2.pc
When we encounter a duplicate user and fail to add them, report their
[moira.git] / dbck / phase2.pc
CommitLineData
7ac48069 1/* $Id$
68bbc9c3 2 *
7ac48069 3 * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
5 * <mit-copyright.h>.
68bbc9c3 6 */
7
8#include <mit-copyright.h>
68bbc9c3 9#include <moira.h>
10#include "dbck.h"
7ac48069 11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
208a4f4a 16EXEC SQL INCLUDE sqlca;
68bbc9c3 17
7ac48069 18RCSID("$Header$");
68bbc9c3 19
4b9e5c72 20EXEC SQL WHENEVER SQLERROR DO dbmserr();
68bbc9c3 21
7ac48069 22int show_mcm_mach(void *id);
23int show_mcm_clu(void *id);
24int show_hostalias(void *id);
dabf20aa 25int show_printer_mach(void *id);
fe0a844a 26int show_printer_server(void *id);
dabf20aa 27int show_printer_loghost(void *id);
28int show_printer_spool(void *id);
29int show_printer_quota(void *id);
30int show_printer_ac(void *id);
31int show_printer_lpc_acl(void *id);
c96b70a5 32void fix_printer_ac(void *id);
33void fix_printer_lpc_acl(void *id);
7ac48069 34void user_check(int id, void *user, void *hint);
35int maybe_fixup_unref_string(int sid, int oid, char *oname, char *table,
36 char *field, char *idfield);
37int maybe_fixup_modby(int sid, int oid, char *oname, char *table,
38 char *field, char *idfield);
c978c079 39int maybe_fixup_unref_string2(char *table, char *field, char *rowid, int sid);
40int maybe_fixup_modby2(char *table, char *field, char *rowid, int id);
7ac48069 41void pobox_check(int id, struct user *u);
42void remove_pobox(int id);
43void fix_smtp_pobox(int id, int sid);
44void mach_check(int id, void *machine, void *hint);
45void subnet_check(int id, void *subnet, void *hint);
46void clear_subnet_owner(struct subnet *s);
47void clear_mach_owner(struct machine *m);
48void cluster_check(int id, void *cluster, void *hint);
49int show_svc(void *id);
50void list_check(int id, void *list, void *hint);
51void fix_list_acl(int id);
ad47bcbe 52void fix_list_memacl(int id);
7ac48069 53int show_member_list(void *id);
54int show_mem_user(void *id);
55int show_mem_list(void *id);
56int show_mem_str(void *id);
57int show_mem_krb(void *id);
58void del_mem_user(void *id);
59void del_mem_list(void *id);
60void del_mem_str(void *id);
61void del_mem_krb(void *id);
62int show_sh(void *id);
63void del_sh_mach(void *id);
64void fsmatch(int id, void *nfsphys, void *filesys);
65void check_fs(int id, void *filesys, void *hint);
66void check_nfsphys(int id, void *nfsphys, void *hint);
fe0a844a 67void check_ps(int id, void *printserver, void *hint);
7ac48069 68int show_fsg_missing(void *id);
69int show_fsg_type(void *filesys);
70void fix_fsg_type(void *filesys);
71int show_fsg_nomember(void *id);
72int show_quota_nouser(void *id);
73int show_quota_nolist(void *id);
74void fix_quota_nouser(void *id);
75void fix_quota_nolist(void *id);
76int show_quota_nofs(void *id);
77void fix_quota_nofs(void *id);
78int show_quota_wrongpid(void *id);
79void fix_quota_physid(void *id);
80int show_srv_user(void *id);
81int show_srv_list(void *id);
82void zero_srv_user(void *id);
83void zero_srv_list(void *id);
84int show_krb_usr(void *id);
85int show_krb_str(void *id);
86int show_pdm_mach(void *id);
87
88int show_mcm_mach(void *id)
208a4f4a 89{
5eaef520 90 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 91 int iid = (int)id, found = 1;
cfc4f91e 92 char name[CLUSTERS_NAME_SIZE];
5eaef520 93 EXEC SQL END DECLARE SECTION;
94
95 EXEC SQL DECLARE csr201 CURSOR FOR
96 SELECT clusters.name FROM clusters, mcmap
97 WHERE clusters.clu_id = mcmap.clu_id AND mcmap.mach_id = :iid;
98 EXEC SQL OPEN csr201;
99 while (1)
100 {
101 EXEC SQL FETCH csr201 INTO :name;
102 if (sqlca.sqlcode)
103 break;
104
105 strtrim(name);
106 found = 0;
7ac48069 107 printf("Cluster %s, non-existant machine %d in cluster map\n",
108 name, iid);
208a4f4a 109 }
5eaef520 110 EXEC SQL CLOSE csr201;
111 return found;
208a4f4a 112}
68bbc9c3 113
7ac48069 114int show_mcm_clu(void *id)
208a4f4a 115{
5eaef520 116 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 117 int iid = (int)id, found = 1;
cfc4f91e 118 char name[MACHINE_NAME_SIZE];
5eaef520 119 EXEC SQL END DECLARE SECTION;
120
121 EXEC SQL DECLARE csr202 CURSOR FOR
122 SELECT machine.name FROM machine, mcmap
123 WHERE machine.mach_id = mcmap.mach_id AND mcmap.clu_id = :iid;
124 EXEC SQL OPEN csr202;
125 while (1)
126 {
127 EXEC SQL FETCH csr202 INTO :name;
128 if (sqlca.sqlcode)
129 break;
130
131 strtrim(name);
132
133 found = 0;
7ac48069 134 printf("Machine %s, non-existant cluster %d in cluster map\n",
135 name, iid);
208a4f4a 136 }
5eaef520 137 EXEC SQL CLOSE csr202;
138 return found;
208a4f4a 139}
68bbc9c3 140
7ac48069 141int show_hostalias(void *id)
ab05f33a 142{
5eaef520 143 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 144 int iid = (int)id, found = 1;
cfc4f91e 145 char name[HOSTALIAS_NAME_SIZE];
5eaef520 146 EXEC SQL END DECLARE SECTION;
147
148 EXEC SQL DECLARE csr234 CURSOR FOR
149 SELECT name FROM hostalias WHERE mach_id = :iid;
150 EXEC SQL OPEN csr234;
151 while (1)
152 {
153 EXEC SQL FETCH csr234 INTO :name;
154 if (sqlca.sqlcode)
155 break;
156
157 strtrim(name);
158
159 found = 0;
7ac48069 160 printf("Alias %s, non-existant machine %d in hostalias map\n",
161 name, iid);
ab05f33a 162 }
5eaef520 163 EXEC SQL CLOSE csr234;
164 return found;
ab05f33a 165}
166
dabf20aa 167int show_printer_mach(void *id)
ab05f33a 168{
5eaef520 169 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 170 int iid = (int)id, found = 1;
dabf20aa 171 char name[PRINTERS_NAME_SIZE];
5eaef520 172 EXEC SQL END DECLARE SECTION;
173
174 EXEC SQL DECLARE csr235 CURSOR FOR
dabf20aa 175 SELECT name FROM printers WHERE mach_id = :iid;
5eaef520 176 EXEC SQL OPEN csr235;
177 while (1)
178 {
179 EXEC SQL FETCH csr235 INTO :name;
180 if (sqlca.sqlcode)
181 break;
182
183 strtrim(name);
184
185 found = 0;
dabf20aa 186 printf("Printer %s, non-existant machine %d in printers table\n",
7ac48069 187 name, iid);
ab05f33a 188 }
5eaef520 189 EXEC SQL CLOSE csr235;
190 return found;
ab05f33a 191}
192
fe0a844a 193int show_printer_server(void *id)
194{
195 EXEC SQL BEGIN DECLARE SECTION;
196 int iid = (int)id, found = 1;
197 char name[PRINTERS_NAME_SIZE];
198 EXEC SQL END DECLARE SECTION;
199
200 EXEC SQL DECLARE csr_sps CURSOR FOR
201 SELECT name FROM printers WHERE mach_id = :iid;
202 EXEC SQL OPEN csr_sps;
203 while (1)
204 {
205 EXEC SQL FETCH csr_sps INTO :name;
206 if (sqlca.sqlcode)
207 break;
208
209 strtrim(name);
210
211 found = 0;
212 printf("Printer %s, non-existant printserver %d in printers table\n",
213 name, iid);
214 }
215 EXEC SQL CLOSE csr_sps;
216 return found;
217}
218
dabf20aa 219int show_printer_loghost(void *id)
ab05f33a 220{
5eaef520 221 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 222 int iid = (int)id, found = 1;
dabf20aa 223 char name[PRINTERS_NAME_SIZE];
224 EXEC SQL END DECLARE SECTION;
225
c96b70a5 226 EXEC SQL DECLARE csr236 CURSOR FOR
dabf20aa 227 SELECT name FROM printers WHERE loghost = :iid;
c96b70a5 228 EXEC SQL OPEN csr236;
dabf20aa 229 while (1)
230 {
c96b70a5 231 EXEC SQL FETCH csr236 INTO :name;
dabf20aa 232 if (sqlca.sqlcode)
233 break;
234
235 strtrim(name);
236
237 found = 0;
238 printf("Printer %s, non-existant spool machine %d in printers table\n",
239 name, iid);
240 }
c96b70a5 241 EXEC SQL CLOSE csr236;
dabf20aa 242 return found;
243}
244
245int show_printer_spool(void *id)
246{
247 EXEC SQL BEGIN DECLARE SECTION;
248 int iid = (int)id, found = 1;
249 char name[PRINTERS_NAME_SIZE];
250 EXEC SQL END DECLARE SECTION;
251
c96b70a5 252 EXEC SQL DECLARE csr237 CURSOR FOR
dabf20aa 253 SELECT name FROM printers WHERE rm = :iid;
c96b70a5 254 EXEC SQL OPEN csr237;
dabf20aa 255 while (1)
256 {
c96b70a5 257 EXEC SQL FETCH csr237 INTO :name;
dabf20aa 258 if (sqlca.sqlcode)
259 break;
260
261 strtrim(name);
262
263 found = 0;
264 printf("Printer %s, non-existant spool machine %d in printers table\n",
265 name, iid);
266 }
c96b70a5 267 EXEC SQL CLOSE csr237;
dabf20aa 268 return found;
269}
270
271int show_printer_quota(void *id)
272{
273 EXEC SQL BEGIN DECLARE SECTION;
274 int iid = (int)id, found = 1;
275 char name[PRINTERS_NAME_SIZE];
276 EXEC SQL END DECLARE SECTION;
277
c96b70a5 278 EXEC SQL DECLARE csr238 CURSOR FOR
dabf20aa 279 SELECT name FROM printers WHERE rq = :iid;
c96b70a5 280 EXEC SQL OPEN csr238;
dabf20aa 281 while (1)
282 {
c96b70a5 283 EXEC SQL FETCH csr238 INTO :name;
dabf20aa 284 if (sqlca.sqlcode)
285 break;
286
287 strtrim(name);
288
289 found = 0;
290 printf("Printer %s, non-existant quota server %d in printers table\n",
291 name, iid);
292 }
c96b70a5 293 EXEC SQL CLOSE csr238;
dabf20aa 294 return found;
295}
296
297int show_printer_ac(void *id)
298{
299 EXEC SQL BEGIN DECLARE SECTION;
300 int iid = (int)id, found = 1;
301 char name[PRINTERS_NAME_SIZE];
5eaef520 302 EXEC SQL END DECLARE SECTION;
303
c96b70a5 304 EXEC SQL DECLARE csr239 CURSOR FOR
dabf20aa 305 SELECT name FROM printers WHERE ac = :iid;
c96b70a5 306 EXEC SQL OPEN csr239;
5eaef520 307 while (1)
308 {
c96b70a5 309 EXEC SQL FETCH csr239 INTO :name;
5eaef520 310 if (sqlca.sqlcode)
311 break;
312
313 strtrim(name);
314
315 found = 0;
dabf20aa 316 printf("Printer %s, non-existant restrict list %d in printers table\n",
7ac48069 317 name, iid);
ab05f33a 318 }
c96b70a5 319 EXEC SQL CLOSE csr239;
5eaef520 320 return found;
ab05f33a 321}
322
dabf20aa 323int show_printer_lpc_acl(void *id)
324{
325 EXEC SQL BEGIN DECLARE SECTION;
326 int iid = (int)id, found = 1;
327 char name[PRINTERS_NAME_SIZE];
328 EXEC SQL END DECLARE SECTION;
329
c96b70a5 330 EXEC SQL DECLARE csr240 CURSOR FOR
dabf20aa 331 SELECT name FROM printers WHERE lpc_acl = :iid;
c96b70a5 332 EXEC SQL OPEN csr240;
dabf20aa 333 while (1)
334 {
c96b70a5 335 EXEC SQL FETCH csr240 INTO :name;
dabf20aa 336 if (sqlca.sqlcode)
337 break;
338
339 strtrim(name);
340
341 found = 0;
342 printf("Printer %s, non-existant lpc ACL %d in printers table\n",
343 name, iid);
344 }
c96b70a5 345 EXEC SQL CLOSE csr240;
dabf20aa 346 return found;
347}
348
c96b70a5 349void fix_printer_ac(void *id)
dabf20aa 350{
351 EXEC SQL BEGIN DECLARE SECTION;
352 int rowcount, iid = (int)id;
353 EXEC SQL END DECLARE SECTION;
354
355 EXEC SQL UPDATE printers SET ac = 0 WHERE ac = :iid;
356 rowcount = sqlca.sqlerrd[2];
357 if (rowcount > 0)
358 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
359 else
360 printf("Not fixed\n");
361 modified("printers");
362}
363
c96b70a5 364void fix_printer_lpc_acl(void *id)
dabf20aa 365{
366 EXEC SQL BEGIN DECLARE SECTION;
367 int rowcount, iid = (int)id;
368 EXEC SQL END DECLARE SECTION;
369
370 EXEC SQL UPDATE printers SET lpc_acl = 0 WHERE lpc_acl = :iid;
371 rowcount = sqlca.sqlerrd[2];
372 if (rowcount > 0)
373 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
374 else
375 printf("Not fixed\n");
376 modified("printers");
377}
378
7ac48069 379void user_check(int id, void *user, void *hint)
ab05f33a 380{
7ac48069 381 struct user *u = user;
382
5eaef520 383 u->comment = maybe_fixup_unref_string(u->comment, id, u->login, "users",
384 "comments", "users_id");
385
386 u->modby = maybe_fixup_modby(u->modby, id, u->login, "users",
387 "modby", "users_id");
ab05f33a 388
5eaef520 389 u->fmodby = maybe_fixup_modby(u->fmodby, id, u->login, "users",
390 "fmodby", "users_id");
ab05f33a 391
5eaef520 392 u->pmodby = maybe_fixup_modby(u->pmodby, id, u->login, "users",
393 "pmodby", "users_id");
ab05f33a 394
5eaef520 395 u->sigwho = maybe_fixup_unref_string(u->sigwho, id, u->login, "users",
396 "sigwho", "users_id");
ab05f33a 397
7ac48069 398 pobox_check(id, u);
ab05f33a 399}
400
5eaef520 401int maybe_fixup_unref_string(int sid, int oid, char *oname, char *table,
402 char *field, char *idfield)
ab05f33a 403{
5eaef520 404 int ret = (sid < 0) ? -sid : sid, doit = 0, newid;
ab05f33a 405 EXEC SQL BEGIN DECLARE SECTION;
406 int rowcount;
407 char stmt_buf[500];
408 EXEC SQL END DECLARE SECTION;
5eaef520 409
7ac48069 410 if ((newid = (int)hash_lookup(string_dups, ret)))
5eaef520 411 {
412 printf("%s entry %s(%d) has a %s with duplicate string %d\n",
413 table, oname, oid, field, ret);
414 if (single_fix("Replace duplicate", 0))
415 {
416 ret = newid;
5eaef520 417 doit = 1;
418 }
fd3a1fc5 419 string_check(ret);
ab05f33a 420 }
5eaef520 421 else if (!string_check(ret))
422 {
423 printf("%s entry %s(%d) has a %s with non-existant string %d\n",
424 table, oname, oid, field, ret);
425 if (single_fix("Delete", 1))
426 {
427 ret = 0;
428 doit = 1;
429 }
430 }
431
432 if (doit)
433 {
434 sprintf(stmt_buf, "UPDATE %s SET %s = %d WHERE %s = %d",
435 table, field, (sid < 0) ? -ret : ret, idfield, oid);
436 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
437 rowcount = sqlca.sqlerrd[2];
438 if (rowcount == 1)
439 printf("Fixed\n");
440 else
441 printf("Not fixed, rowcount = %d\n", rowcount);
442 modified(table);
ab05f33a 443 }
ab05f33a 444
5eaef520 445 return (sid < 0) ? -ret : ret;
ab05f33a 446}
447
5eaef520 448int maybe_fixup_modby(int sid, int oid, char *oname, char *table,
449 char *field, char *idfield)
ab05f33a 450{
451 EXEC SQL BEGIN DECLARE SECTION;
452 char stmt_buf[500];
453 int rowcount;
454 EXEC SQL END DECLARE SECTION;
455
5eaef520 456 if (sid < 0)
ab05f33a 457 return maybe_fixup_unref_string(sid, oid, oname, table, field, idfield);
5eaef520 458 else
459 {
460 if (!hash_lookup(users, sid))
461 {
462 printf("%s entry %s(%d) has a %s with non-existant user %d\n",
463 table, oname, oid, field, sid);
464 if (single_fix("Delete", 1))
465 {
466 sprintf(stmt_buf, "UPDATE %s SET %s = 0 WHERE %s = %d",
467 table, field, idfield, oid);
468 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
469 rowcount = sqlca.sqlerrd[2];
470 if (rowcount == 1)
471 printf("Fixed\n");
472 else
473 printf("Not fixed, rowcount = %d\n", rowcount);
474 modified(table);
475 }
476 return 0;
477 }
ab05f33a 478 }
ab05f33a 479 return sid;
480}
481
c978c079 482int maybe_fixup_unref_string2(char *table, char *field, char *rowid, int sid)
ab05f33a 483{
5eaef520 484 int ret = (sid < 0) ? -sid : sid, doit = 0, newid;
ab05f33a 485 EXEC SQL BEGIN DECLARE SECTION;
486 int rowcount;
487 char stmt_buf[500];
488 EXEC SQL END DECLARE SECTION;
5eaef520 489
7ac48069 490 if ((newid = (int)hash_lookup(string_dups, ret)))
5eaef520 491 {
492 printf("%s entry has a %s with duplicate string %d\n",
493 table, field, ret);
494 if (single_fix("Replace duplicate", 0))
495 {
496 ret = newid;
5eaef520 497 doit = 1;
498 }
fd3a1fc5 499 string_check(ret);
5eaef520 500 }
501 else if (!string_check(ret))
502 {
503 printf("%s entry has a %s with non-existant string %d\n",
504 table, field, ret);
11975951 505 if (single_fix("Clear", 1))
5eaef520 506 {
507 ret = 0;
508 doit = 1;
509 }
ab05f33a 510 }
5eaef520 511
512 if (doit)
513 {
c978c079 514 sprintf(stmt_buf, "UPDATE %s SET %s = %d WHERE rowid = '%s'",
515 table, field, (sid < 0) ? -ret : ret, rowid);
5eaef520 516 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
517 rowcount = sqlca.sqlerrd[2];
518 if (rowcount == 1)
519 printf("Fixed\n");
520 else
521 printf("Not fixed, rowcount = %d\n", rowcount);
522 modified(table);
ab05f33a 523 }
5eaef520 524 return (sid < 0) ? -ret : ret;
ab05f33a 525}
526
c978c079 527int maybe_fixup_modby2(char *table, char *field, char *rowid, int id)
ab05f33a 528{
529 EXEC SQL BEGIN DECLARE SECTION;
530 char stmt_buf[500];
531 int rowcount;
532 EXEC SQL END DECLARE SECTION;
533
5eaef520 534 if (id < 0)
c978c079 535 return maybe_fixup_unref_string2(table, field, rowid, id);
5eaef520 536 else
537 {
538 if (!hash_lookup(users, id))
539 {
540 printf("%s entry has a %s with non-existant user %d\n",
541 table, field, id);
11975951 542 if (single_fix("Clear", 1))
5eaef520 543 {
c978c079 544 sprintf(stmt_buf, "UPDATE %s SET %s = 0 WHERE rowid = '%s'",
545 table, field, rowid);
5eaef520 546 EXEC SQL EXECUTE IMMEDIATE :stmt_buf;
547 rowcount = sqlca.sqlerrd[2];
548 if (rowcount == 1)
549 printf("Fixed\n");
550 else
551 printf("Not fixed, rowcount = %d\n", rowcount);
552 modified(table);
553 }
554 return 0;
555 }
ab05f33a 556 }
ab05f33a 557 return 1;
558}
559
7ac48069 560void pobox_check(int id, struct user *u)
68bbc9c3 561{
fc6165db 562 struct filesys *fs;
563
5eaef520 564 switch (u->potype)
565 {
566 case 'P':
567 if (!hash_lookup(machines, u->pobox_id))
568 {
569 printf("User %s(%s) has P.O.Box on non-existant machine %d\n",
570 u->login, u->fullname, u->pobox_id);
571 if (single_fix("Delete", 0))
572 {
573 remove_pobox(u->users_id);
574 u->potype = 'N';
575 }
576 }
577 break;
fc6165db 578
5eaef520 579 case 'S':
7ac48069 580 if (hash_lookup(string_dups, u->pobox_id))
5eaef520 581 {
582 printf("User %s(%s) has P.O.Box with duplicate string %d\n",
583 u->login, u->fullname, u->pobox_id);
584 if (single_fix("Update", 0))
585 {
586 printf("Replacing box_id dup string ID %d with %d\n",
587 u->pobox_id,
7ac48069 588 (int)hash_lookup(string_dups, u->pobox_id));
589 u->pobox_id = (int)hash_lookup(string_dups, u->pobox_id);
5eaef520 590 fix_smtp_pobox(u->users_id, u->pobox_id);
591 string_check(u->pobox_id);
592 }
593 }
594 else if (!string_check(u->pobox_id))
595 {
596 printf("User %s(%s) has P.O.Box with non-existant string %d\n",
597 u->login, u->fullname, u->pobox_id);
598 if (single_fix("Delete", 0))
599 {
600 remove_pobox(u->users_id);
601 u->potype = 'N';
602 }
603 }
604 break;
fc6165db 605
606 case 'I':
607 fs = hash_lookup(filesys, u->pobox_id);
608 if (!fs)
609 {
610 printf("User %s(%s) has P.O.Box on non-existant filesystem %d\n",
611 u->login, u->fullname, u->pobox_id);
612 if (single_fix("Delete", 0))
613 {
614 remove_pobox(u->users_id);
615 u->potype = 'N';
616 }
617 }
618 else if (fs->type != 'I')
619 {
620 printf("User %s(%s) has IMAP P.O.Box on non-IMAP filesystem %s\n",
621 u->login, u->fullname, fs->name);
622 if (single_fix("Delete", 0))
623 {
624 remove_pobox(u->users_id);
625 u->potype = 'N';
626 }
627 }
628 break;
629
5eaef520 630 default:
631 ;
68bbc9c3 632 }
633}
634
635
7ac48069 636void remove_pobox(int id)
208a4f4a 637{
5eaef520 638 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 639 int rowcount, iid = (int)id;
5eaef520 640 EXEC SQL END DECLARE SECTION;
641
642 EXEC SQL UPDATE users SET potype = 'NONE' WHERE users.users_id = :iid;
643 rowcount = sqlca.sqlerrd[2];
644 if (rowcount > 0)
645 printf("%d entr%s removed\n", rowcount, rowcount == 1 ? "y" : "ies");
646 else
647 printf("Not removed\n");
648 modified("users");
208a4f4a 649}
68bbc9c3 650
7ac48069 651void fix_smtp_pobox(int id, int sid)
ab05f33a 652{
5eaef520 653 EXEC SQL BEGIN DECLARE SECTION;
654 int rowcount, iid = id, isid = sid;
655 EXEC SQL END DECLARE SECTION;
656
657 EXEC SQL UPDATE users SET box_id = :isid WHERE users.users_id = :iid;
658 rowcount = sqlca.sqlerrd[2];
659 if (rowcount > 0)
660 printf("%d entr%s updated\n", rowcount, rowcount == 1 ? "y" : "ies");
661 else
662 printf("Not updated\n");
663 modified("users");
ab05f33a 664}
772b7afc 665
7ac48069 666void mach_check(int id, void *machine, void *hint)
772b7afc 667{
7ac48069 668 struct machine *m = machine;
669
5eaef520 670 if (!hash_lookup(subnets, m->snet_id))
671 {
672 printf("Machine %s is on a non-existant subnet %d\n",
673 m->name, m->snet_id);
674 if (single_fix("Move to null-subnet", 1))
675 {
676 EXEC SQL BEGIN DECLARE SECTION;
677 int rowcount, iid = id;
678 EXEC SQL END DECLARE SECTION;
679
680 EXEC SQL UPDATE machine SET snet_id = 0 WHERE mach_id = :iid;
681 rowcount = sqlca.sqlerrd[2];
682 if (rowcount > 0)
683 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
684 else
685 printf("Not fixed\n");
686 modified("machine");
772b7afc 687 }
688 }
689
5eaef520 690 switch (m->owner_type)
691 {
772b7afc 692 case 'U':
5eaef520 693 if (!hash_lookup(users, m->owner_id))
694 {
695 printf("Machine %s has non-existant USER owner %d\n",
696 m->name, m->owner_id);
697 if (single_fix("Set to no owner", 1))
698 clear_mach_owner(m);
772b7afc 699 }
5eaef520 700 break;
772b7afc 701 case 'L':
5eaef520 702 if (!hash_lookup(lists, m->owner_id))
703 {
704 printf("Machine %s has non-existant LIST owner %d\n",
705 m->name, m->owner_id);
706 if (single_fix("Set to no owner", 1))
707 clear_mach_owner(m);
772b7afc 708 }
5eaef520 709 break;
ab05f33a 710 case 'S':
711 case 'K':
5eaef520 712 if (m->owner_id)
713 m->owner_id = maybe_fixup_unref_string(m->owner_id, id, m->name,
714 "machine", "owner_id",
715 "mach_id");
716 if (m->owner_id == 0)
ab05f33a 717 clear_mach_owner(m);
772b7afc 718 }
ab05f33a 719
5eaef520 720 if (m->acomment)
721 m->acomment = maybe_fixup_unref_string(m->acomment, id, m->name,
ab05f33a 722 "machine", "acomment", "mach_id");
5eaef520 723 if (m->ocomment)
724 m->ocomment = maybe_fixup_unref_string(m->ocomment, id, m->name,
ab05f33a 725 "machine", "ocomment", "mach_id");
5eaef520 726
727 m->creator = maybe_fixup_modby(m->creator, id, m->name, "machine",
ab05f33a 728 "creator", "mach_id");
5eaef520 729 m->modby = maybe_fixup_modby(m->modby, id, m->name, "machine",
ab05f33a 730 "modby", "mach_id");
772b7afc 731}
732
7ac48069 733void subnet_check(int id, void *subnet, void *hint)
ab05f33a 734{
7ac48069 735 struct subnet *s = subnet;
736
5eaef520 737 switch (s->owner_type)
738 {
ab05f33a 739 case 'U':
5eaef520 740 if (!hash_lookup(users, s->owner_id))
741 {
742 printf("Subnet %s has non-existant USER owner %d\n",
743 s->name, s->owner_id);
744 if (single_fix("Set to no owner", 1))
745 clear_subnet_owner(s);
ab05f33a 746 }
5eaef520 747 break;
ab05f33a 748 case 'L':
5eaef520 749 if (!hash_lookup(lists, s->owner_id))
750 {
751 printf("Machine %s has non-existant LIST owner %d\n",
752 s->name, s->owner_id);
753 if (single_fix("Set to no owner", 1))
754 clear_subnet_owner(s);
ab05f33a 755 }
5eaef520 756 break;
ab05f33a 757 case 'S':
758 case 'K':
5eaef520 759 if (s->owner_id)
760 s->owner_id = maybe_fixup_unref_string(s->owner_id, id, s->name,
761 "machine", "owner_id",
762 "mach_id");
763 if (s->owner_id == 0)
ab05f33a 764 clear_subnet_owner(s);
765 }
766
5eaef520 767 s->modby = maybe_fixup_modby(s->modby, id, s->name, "subnet",
ab05f33a 768 "modby", "snet_id");
769}
770
7ac48069 771void clear_subnet_owner(struct subnet *s)
ab05f33a 772{
5eaef520 773 EXEC SQL BEGIN DECLARE SECTION;
774 int rowcount, id = s->snet_id;
775 EXEC SQL END DECLARE SECTION;
776
777 EXEC SQL UPDATE subnet SET owner_type = 'NONE', owner_id = 0
778 WHERE snet_id = :id;
779 rowcount = sqlca.sqlerrd[2];
780 if (rowcount > 0)
781 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
782 else
783 printf("Not fixed\n");
784 modified("subnet");
ab05f33a 785}
772b7afc 786
7ac48069 787void clear_mach_owner(struct machine *m)
772b7afc 788{
5eaef520 789 EXEC SQL BEGIN DECLARE SECTION;
790 int rowcount, id = m->mach_id;
791 EXEC SQL END DECLARE SECTION;
792
793 EXEC SQL UPDATE machine SET owner_type = 'NONE', owner_id = 0
794 WHERE mach_id = :id;
795 rowcount = sqlca.sqlerrd[2];
796 if (rowcount > 0)
797 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
798 else
799 printf("Not fixed\n");
800 modified("machine");
772b7afc 801}
802
7ac48069 803void cluster_check(int id, void *cluster, void *hint)
ab05f33a 804{
7ac48069 805 struct cluster *c = cluster;
806
5eaef520 807 c->modby = maybe_fixup_modby(c->modby, id, c->name, "clusters",
ab05f33a 808 "modby", "clu_id");
809}
810
7ac48069 811int show_svc(void *id)
5eaef520 812{
813 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 814 int iid = (int)id, found = 1;
cfc4f91e 815 char label[SVC_SERV_LABEL_SIZE], data[SVC_SERV_CLUSTER_SIZE];
5eaef520 816 EXEC SQL END DECLARE SECTION;
ab05f33a 817
5eaef520 818 EXEC SQL DECLARE csr203 CURSOR FOR
819 SELECT serv_label, serv_cluster FROM svc
820 WHERE clu_id = :iid;
821 EXEC SQL OPEN csr203;
822 while (1)
823 {
824 EXEC SQL FETCH csr203 INTO :label, :data;
825 if (sqlca.sqlcode)
826 break;
772b7afc 827
5eaef520 828 strtrim(label);
829 strtrim(data);
830 found = 0;
831 printf("Cluster data [%s] %s for non-existant cluster %d\n",
7ac48069 832 label, data, iid);
208a4f4a 833 }
5eaef520 834 EXEC SQL CLOSE csr203;
835 return found;
208a4f4a 836}
68bbc9c3 837
7ac48069 838void list_check(int id, void *list, void *hint)
68bbc9c3 839{
7ac48069 840 struct list *l = list;
841
cfc4f91e 842 l->modby = maybe_fixup_modby(l->modby, id, l->name, "list",
843 "modby", "list_id");
844
5eaef520 845 switch (l->acl_type)
846 {
68bbc9c3 847 case 'L':
5eaef520 848 if (!hash_lookup(lists, l->acl_id))
849 {
850 printf("List %s has bad LIST acl %d\n", l->name, l->acl_id);
851 if (single_fix("Patch", 1))
852 fix_list_acl(l->list_id);
68bbc9c3 853 }
5eaef520 854 break;
68bbc9c3 855 case 'U':
5eaef520 856 if (!hash_lookup(users, l->acl_id))
857 {
858 printf("List %s has bad USER acl %d\n", l->name, l->acl_id);
859 if (single_fix("Patch", 1))
860 fix_list_acl(l->list_id);
68bbc9c3 861 }
5eaef520 862 break;
ab05f33a 863 case 'K':
5eaef520 864 l->acl_id = maybe_fixup_unref_string(l->acl_id, id, l->name,
865 "list", "acl_id", "list_id");
866 if (!l->acl_id)
867 {
868 printf("List %s has bad KERBEROS acl %d\n", l->name, l->acl_id);
869 if (single_fix("Patch", 1))
870 fix_list_acl(l->list_id);
ab05f33a 871 }
5eaef520 872 break;
68bbc9c3 873 }
ad47bcbe 874
875 switch (l->memacl_type)
876 {
877 case 'L':
878 if (!hash_lookup(lists, l->memacl_id))
879 {
880 printf("List %s has bad LIST memacl %d\n", l->name, l->memacl_id);
881 if (single_fix("Patch", 1))
882 fix_list_memacl(l->list_id);
883 }
884 break;
885 case 'U':
886 if (!hash_lookup(users, l->memacl_id))
887 {
888 printf("List %s has bad USER acl %d\n", l->name, l->memacl_id);
889 if (single_fix("Patch", 1))
890 fix_list_memacl(l->list_id);
891 }
892 break;
893 case 'K':
894 l->memacl_id = maybe_fixup_unref_string(l->memacl_id, id, l->name,
895 "list", "memacl_id", "list_id");
896 if (!l->memacl_id)
897 {
898 printf("List %s has bad KERBEROS acl %d\n", l->name,
899 l->memacl_id);
900 if (single_fix("Patch", 1))
901 fix_list_memacl(l->list_id);
902 }
903 break;
904 }
68bbc9c3 905}
906
7ac48069 907void fix_list_acl(int id)
208a4f4a 908{
5eaef520 909 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 910 int rowcount, iid = (int)id;
5eaef520 911 EXEC SQL END DECLARE SECTION;
68bbc9c3 912
5eaef520 913 EXEC SQL UPDATE list SET acl_id = :iid, acl_type = 'LIST'
914 WHERE list_id = :iid;
915 rowcount = sqlca.sqlerrd[2];
ad47bcbe 916 if (rowcount > 0)
917 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
918 else
919 printf("Not fixed\n");
920 modified("list");
921}
922
923void fix_list_memacl(int id)
924{
925 EXEC SQL BEGIN DECLARE SECTION;
926 int rowcount, iid = (int)id;
927 EXEC SQL END DECLARE SECTION;
928
929 EXEC SQL UPDATE list SET memacl_id = 0, memacl_type = 'NONE'
930 WHERE list_id = :iid;
931 rowcount = sqlca.sqlerrd[2];
5eaef520 932 if (rowcount > 0)
933 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
934 else
935 printf("Not fixed\n");
936 modified("list");
937}
68bbc9c3 938
7ac48069 939int show_member_list(void *id)
208a4f4a 940{
5eaef520 941 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 942 int mid, iid = (int)id, found = 1;
8d1c466f 943 char mtype[IMEMBERS_MEMBER_TYPE_SIZE], *name = NULL;
5eaef520 944 EXEC SQL END DECLARE SECTION;
945
946 EXEC SQL DECLARE csr204 CURSOR FOR
947 SELECT member_type, member_id FROM imembers
8d1c466f 948 WHERE list_id = :iid;
5eaef520 949 EXEC SQL OPEN csr204;
950 while (1)
951 {
952 EXEC SQL FETCH csr204 INTO :mtype, :mid;
953 if (sqlca.sqlcode)
954 break;
955
956 strtrim(mtype);
957 found = 0;
958 if (mtype[0] == 'L')
8d1c466f 959 {
960 struct list *l = hash_lookup(lists, mid);
961 if (l)
962 name = l->name;
963 }
5eaef520 964 else if (mtype[0] == 'U')
8d1c466f 965 {
966 struct user *u = hash_lookup(users, mid);
967 if (u)
968 name = u->login;
969 }
5eaef520 970 else if (mtype[0] == 'S' || mtype[0] == 'K')
8d1c466f 971 {
972 struct string *s = hash_lookup(strings, mid);
973 if (s)
974 name = s->name;
975 }
976 if (name)
977 printf("Non-existant list %d has member %s %s\n", iid, mtype, name);
978 else
979 {
980 printf("Non-existant list %d has non-existent member %s %d\n",
981 iid, mtype, mid);
982 }
208a4f4a 983 }
5eaef520 984 EXEC SQL CLOSE csr204;
985 return found;
208a4f4a 986}
68bbc9c3 987
7ac48069 988int show_mem_user(void *id)
208a4f4a 989{
5eaef520 990 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 991 int lid, iid = (int)id, found = 1;
5eaef520 992 EXEC SQL END DECLARE SECTION;
8d1c466f 993 struct list *l;
5eaef520 994
995 EXEC SQL DECLARE csr205 CURSOR FOR
996 SELECT list_id FROM imembers
8d1c466f 997 WHERE member_id = :iid AND member_type = 'USER';
5eaef520 998 EXEC SQL OPEN csr205;
999 while (1)
1000 {
1001 EXEC SQL FETCH csr205 INTO :lid;
1002 if (sqlca.sqlcode)
1003 break;
8d1c466f 1004 l = hash_lookup(lists, lid);
1005 if (!l)
1006 continue;
5eaef520 1007
1008 found = 0;
8d1c466f 1009 printf("List %s has non-existant user member, id %d\n", l->name, iid);
208a4f4a 1010 }
5eaef520 1011 EXEC SQL CLOSE csr205;
1012 return found;
208a4f4a 1013}
68bbc9c3 1014
7ac48069 1015int show_mem_list(void *id)
208a4f4a 1016{
5eaef520 1017 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1018 int lid, iid = (int)id, found = 1;
5eaef520 1019 EXEC SQL END DECLARE SECTION;
8d1c466f 1020 struct list *l;
5eaef520 1021
1022 EXEC SQL DECLARE csr206 CURSOR FOR
1023 SELECT list_id FROM imembers
8d1c466f 1024 WHERE member_id = :iid AND member_type = 'LIST';
5eaef520 1025 EXEC SQL OPEN csr206;
1026 while (1)
1027 {
1028 EXEC SQL FETCH csr206 INTO :lid;
1029 if (sqlca.sqlcode)
1030 break;
8d1c466f 1031 l = hash_lookup(lists, lid);
1032 if (!l)
1033 continue;
5eaef520 1034
1035 found = 0;
8d1c466f 1036 printf("List %s has non-existant list member, id %d\n", l->name, iid);
208a4f4a 1037 }
5eaef520 1038 EXEC SQL CLOSE csr206;
1039 return found;
208a4f4a 1040}
68bbc9c3 1041
7ac48069 1042int show_mem_str(void *id)
208a4f4a 1043{
5eaef520 1044 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1045 int lid, iid = (int)id, found = 1;
5eaef520 1046 EXEC SQL END DECLARE SECTION;
8d1c466f 1047 struct list *l;
5eaef520 1048
1049 EXEC SQL DECLARE csr207 CURSOR FOR
1050 SELECT list_id FROM imembers
8d1c466f 1051 WHERE member_id = :iid AND member_type = 'STRING';
5eaef520 1052 EXEC SQL OPEN csr207;
1053 while (1)
1054 {
1055 EXEC SQL FETCH csr207 INTO :lid;
1056 if (sqlca.sqlcode)
1057 break;
8d1c466f 1058 l = hash_lookup(lists, lid);
1059 if (!l)
1060 continue;
5eaef520 1061
1062 found = 0;
8d1c466f 1063 printf("List %s has non-existant string member, id %d\n", l->name, iid);
208a4f4a 1064 }
5eaef520 1065 EXEC SQL CLOSE csr207;
1066 return found;
208a4f4a 1067}
68bbc9c3 1068
1069
7ac48069 1070int show_mem_krb(void *id)
208a4f4a 1071{
5eaef520 1072 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1073 int lid, iid = (int)id, found = 1;
5eaef520 1074 EXEC SQL END DECLARE SECTION;
8d1c466f 1075 struct list *l;
5eaef520 1076
1077 EXEC SQL DECLARE csr208 CURSOR FOR
1078 SELECT list_id FROM imembers
8d1c466f 1079 WHERE member_id = :iid AND member_type = 'KERBEROS';
5eaef520 1080 EXEC SQL OPEN csr208;
1081 while (1)
1082 {
1083 EXEC SQL FETCH csr208 INTO :lid;
1084 if (sqlca.sqlcode)
1085 break;
8d1c466f 1086 l = hash_lookup(lists, lid);
1087 if (!l)
1088 continue;
5eaef520 1089
1090 found = 0;
1091 printf("List %s has non-existant kerberos member, id %d\n",
8d1c466f 1092 l->name, iid);
208a4f4a 1093 }
5eaef520 1094 EXEC SQL CLOSE csr208;
1095 return found;
208a4f4a 1096}
68bbc9c3 1097
68bbc9c3 1098
7ac48069 1099void del_mem_user(void *id)
208a4f4a 1100{
5eaef520 1101 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1102 int iid = (int)id, rowcount;
5eaef520 1103 EXEC SQL END DECLARE SECTION;
1104
1105 EXEC SQL DELETE FROM imembers WHERE member_type = 'USER' AND
8d1c466f 1106 member_id = :iid;
5eaef520 1107 rowcount = sqlca.sqlerrd[2];
1108 if (rowcount > 0)
1109 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1110 else
1111 printf("Not deleted\n");
1112 modified("imembers");
208a4f4a 1113}
68bbc9c3 1114
7ac48069 1115void del_mem_list(void *id)
208a4f4a 1116{
5eaef520 1117 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1118 int iid = (int)id, rowcount;
5eaef520 1119 EXEC SQL END DECLARE SECTION;
1120
1121 EXEC SQL DELETE FROM imembers WHERE member_type = 'LIST' AND
8d1c466f 1122 member_id = :iid;
5eaef520 1123 rowcount = sqlca.sqlerrd[2];
1124 if (rowcount > 0)
1125 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1126 else
1127 printf("Not deleted\n");
1128 modified("imembers");
208a4f4a 1129}
68bbc9c3 1130
7ac48069 1131void del_mem_str(void *id)
208a4f4a 1132{
5eaef520 1133 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1134 int iid = (int)id, rowcount;
5eaef520 1135 EXEC SQL END DECLARE SECTION;
1136
1137 EXEC SQL DELETE FROM imembers WHERE member_type = 'STRING' AND
8d1c466f 1138 member_id = :iid;
5eaef520 1139 rowcount = sqlca.sqlerrd[2];
1140 if (rowcount > 0)
1141 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1142 else
1143 printf("Not deleted\n");
1144 modified("imembers");
208a4f4a 1145}
68bbc9c3 1146
68bbc9c3 1147
7ac48069 1148void del_mem_krb(void *id)
208a4f4a 1149{
5eaef520 1150 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1151 int iid = (int)id, rowcount;
5eaef520 1152 EXEC SQL END DECLARE SECTION;
1153
1154 EXEC SQL DELETE FROM imembers WHERE member_type = 'KERBEROS' AND
8d1c466f 1155 member_id = :iid;
5eaef520 1156 rowcount = sqlca.sqlerrd[2];
1157 if (rowcount > 0)
1158 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1159 else
1160 printf("Not deleted\n");
1161 modified("imembers");
208a4f4a 1162}
68bbc9c3 1163
1164
7ac48069 1165int show_sh(void *id)
208a4f4a 1166{
5eaef520 1167 EXEC SQL BEGIN DECLARE SECTION;
cfc4f91e 1168 char name[SERVERHOSTS_SERVICE_SIZE];
7ac48069 1169 int iid = (int)id;
5eaef520 1170 EXEC SQL END DECLARE SECTION;
1171 int found = 1;
1172
1173 EXEC SQL DECLARE csr209 CURSOR FOR
1174 SELECT service FROM serverhosts
1175 WHERE mach_id = :iid;
1176 EXEC SQL OPEN csr209;
1177 while (1)
1178 {
1179 EXEC SQL FETCH csr209 INTO :name;
1180 if (sqlca.sqlcode)
1181 break;
1182
1183 found = 0;
1184 printf("ServerHost entry for service %s non-existant host %d\n",
7ac48069 1185 name, iid);
208a4f4a 1186 }
5eaef520 1187 EXEC SQL CLOSE csr209;
1188 return found;
208a4f4a 1189}
68bbc9c3 1190
7ac48069 1191void del_sh_mach(void *id)
208a4f4a 1192{
5eaef520 1193 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1194 int iid = (int)id, rowcount;
5eaef520 1195 EXEC SQL END DECLARE SECTION;
1196
1197 EXEC SQL DELETE FROM serverhosts WHERE mach_id = :iid;
1198 rowcount = sqlca.sqlerrd[2];
1199 if (rowcount > 0)
1200 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1201 else
1202 printf("Not deleted\n");
1203 modified("serverhosts");
208a4f4a 1204}
68bbc9c3 1205
1206
1207static int fnchecklen;
1208
7ac48069 1209void fsmatch(int id, void *nfsphys, void *filesys)
68bbc9c3 1210{
7ac48069 1211 struct nfsphys *n = nfsphys;
1212 struct filesys *f = filesys;
1213
5eaef520 1214 if (n->mach_id == f->mach_id &&
1215 !strncmp(f->dir, n->dir, strlen(n->dir)) &&
1216 strlen(n->dir) > fnchecklen)
1217 {
1218 f->phys_id = id;
1219 fnchecklen = strlen(n->dir);
68bbc9c3 1220 }
1221}
1222
1223
7ac48069 1224void check_fs(int id, void *filesys, void *hint)
208a4f4a 1225{
5eaef520 1226 EXEC SQL BEGIN DECLARE SECTION;
1227 int iid = id, id1, id2, id3, rowcount;
1228 char *dir;
1229 EXEC SQL END DECLARE SECTION;
7ac48069 1230 struct filesys *f = filesys;
5eaef520 1231 struct nfsphys *n;
1232 struct machine *m;
1233
1234 if (!hash_lookup(machines, f->mach_id))
1235 {
1236 printf("Filesys %s with bad machine %d\n", f->name, f->mach_id);
1237 if (single_fix("Fix", 0))
1238 {
1239 EXEC SQL UPDATE filesys SET mach_id = 0 WHERE filsys_id = :iid;
1240 rowcount = sqlca.sqlerrd[2];
1241 if (rowcount > 0)
1242 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1243 else
1244 printf("Not fixed\n");
1245 modified("filesys");
1246 f->mach_id = 0;
68bbc9c3 1247 }
1248 }
1249
5eaef520 1250 if (!hash_lookup(users, f->owner))
1251 {
1252 printf("Filesys %s with bad owning user %d\n", f->name, f->owner);
1253 if (single_fix("Fix", 1))
1254 {
1255 zero_fix("filesys", "owner", "filsys_id", f->filsys_id);
1256 f->owner = 0;
68bbc9c3 1257 }
1258 }
5eaef520 1259 if (!hash_lookup(lists, f->owners))
1260 {
1261 printf("Filesys %s with bad owning group %d\n", f->name, f->owners);
1262 if (single_fix("Fix", 1))
1263 {
1264 zero_fix("filesys", "owners", "filsys_id", f->filsys_id);
1265 f->owners = 0;
68bbc9c3 1266 }
1267 }
1268
fc6165db 1269 if (f->type == 'N' || f->type == 'I')
5eaef520 1270 {
1271 if (!hash_lookup(nfsphys, f->phys_id))
1272 {
7ac48069 1273 m = hash_lookup(machines, f->mach_id);
5eaef520 1274 printf("Filesys %s with bad phys_id %d\n", f->name, f->phys_id);
1275 if (single_fix("Fix", 1))
1276 {
1277 fnchecklen = 0;
1278 hash_step(nfsphys, fsmatch, f);
1279 if (fnchecklen != 0)
1280 {
68bbc9c3 1281 id1 = f->phys_id;
1282 id2 = f->filsys_id;
1283 id3 = f->mach_id;
5eaef520 1284 EXEC SQL UPDATE filesys SET phys_id = :id1
1285 WHERE filsys_id = :id2;
4b9e5c72 1286 rowcount = sqlca.sqlerrd[2];
68bbc9c3 1287 if (rowcount > 0)
5eaef520 1288 printf("%d entr%s fixed\n", rowcount,
1289 rowcount == 1 ? "y" : "ies");
68bbc9c3 1290 else
1291 printf("Not fixed\n");
1292 modified("filesys");
5eaef520 1293 }
1294 else
1295 {
1296 printf("No NFSphys exsits for %s:%s\n", m->name, f->dir);
1297 if (single_fix("Create", 0))
1298 {
1299 dir = f->dir;
1300 id1 = f->phys_id;
1301 id2 = f->filsys_id;
1302 id3 = f->mach_id;
1303 if (set_next_object_id("nfsphys_id", "nfsphys") !=
1304 MR_SUCCESS)
1305 {
1306 printf("Unable to assign unique ID\n");
1307 return;
68bbc9c3 1308 }
5eaef520 1309 EXEC SQL SELECT COUNT(*) INTO :rowcount FROM numvalues
1310 WHERE name = 'nfsphys_id';
1311 if (rowcount != 1)
1312 {
1313 printf("Unable to retrieve unique ID\n");
1314 return;
68bbc9c3 1315 }
5eaef520 1316 EXEC SQL INSERT INTO nfsphys
1317 (nfsphys_id, mach_id, device, dir, status, allocated,
1318 size, modtime, modby, modwith) VALUES
1319 (:id1, :id3, '\?\?\?', :dir, 0, 0, 0, SYSDATE, 0,
1320 'dbck');
4b9e5c72 1321 rowcount = sqlca.sqlerrd[2];
68bbc9c3 1322 if (rowcount > 0)
5eaef520 1323 {
1324 printf("%d entr%s created\n", rowcount,
1325 rowcount == 1 ? "y" : "ies");
1326 }
68bbc9c3 1327 else
1328 printf("Not created\n");
1329 modified("nfsphys");
5eaef520 1330 n = malloc(sizeof(struct nfsphys));
1331 if (!n)
68bbc9c3 1332 out_of_mem("storing new nfsphys");
1333 strcpy(n->dir, dir);
1334 n->mach_id = id3;
1335 n->nfsphys_id = id1;
1336 n->allocated = 0;
1337 n->count = 0;
5eaef520 1338 if (hash_store(nfsphys, id1, n) == -1)
ab05f33a 1339 out_of_mem("storing nfsphys in hash table");
208a4f4a 1340 EXEC SQL UPDATE filesys SET phys_id = :id1
5eaef520 1341 WHERE filsys_id = :id2;
4b9e5c72 1342 rowcount = sqlca.sqlerrd[2];
68bbc9c3 1343 if (rowcount > 0)
5eaef520 1344 {
1345 printf("%d filesys entr%s fixed\n", rowcount,
1346 rowcount == 1 ? "y" : "ies");
1347 }
68bbc9c3 1348 else
1349 printf("Not fixed\n");
1350 modified("filesys");
1351 }
1352 }
1353 }
1354 }
1355 }
208a4f4a 1356}
68bbc9c3 1357
7ac48069 1358void check_nfsphys(int id, void *nfsphys, void *hint)
68bbc9c3 1359{
7ac48069 1360 struct nfsphys *n = nfsphys;
1361
cfc4f91e 1362 n->modby = maybe_fixup_modby(n->modby, id, n->dir, "nfsphys",
1363 "modby", "nfsphys_id");
1364
5eaef520 1365 if (!hash_lookup(machines, n->mach_id))
1366 {
1367 printf("NFSphys %d(%s) on non-existant machine %d\n",
1368 id, n->dir, n->mach_id);
1369 if (single_fix("Delete", 0))
1370 single_delete("nfsphys", "nfsphys_id", id);
68bbc9c3 1371 }
1372}
1373
fe0a844a 1374static void clear_ps_owner(struct printserver *ps)
1375{
1376 EXEC SQL BEGIN DECLARE SECTION;
1377 int rowcount, id = ps->mach_id;
1378 EXEC SQL END DECLARE SECTION;
1379
1380 EXEC SQL UPDATE printserver SET owner_type = 'NONE', owner_id = 0
1381 WHERE mach_id = :id;
1382 rowcount = sqlca.sqlerrd[2];
1383 if (rowcount > 0)
1384 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1385 else
1386 printf("Not fixed\n");
1387 modified("printservers");
1388}
1389
1390static void clear_ps_lpc(struct printserver *ps)
1391{
1392 EXEC SQL BEGIN DECLARE SECTION;
1393 int rowcount, id = ps->mach_id;
1394 EXEC SQL END DECLARE SECTION;
1395
1396 EXEC SQL UPDATE printserver SET lpc_acl = 0
1397 WHERE mach_id = :id;
1398 rowcount = sqlca.sqlerrd[2];
1399 if (rowcount > 0)
1400 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1401 else
1402 printf("Not fixed\n");
1403 modified("printservers");
1404}
1405
1406void check_ps(int id, void *printserver, void *hint)
1407{
1408 struct printserver *ps = printserver;
1409 struct machine *m;
1410 char *name;
1411
1412 m = hash_lookup(machines, id);
1413 if (!m)
1414 {
1415 printf("Printserver on non-existant machine %d\n", id);
1416 if (single_fix("Delete", 0))
1417 {
61eec0b8 1418 single_delete("printservers", "mach_id", id);
fe0a844a 1419 return;
1420 }
1421 else
1422 name = "[UNKNOWN]";
1423 }
1424 else
1425 name = m->name;
1426
61eec0b8 1427 ps->modby = maybe_fixup_modby(ps->modby, id, name, "printservers",
fe0a844a 1428 "modby", "mach_id");
1429 ps->printer_types = maybe_fixup_unref_string(ps->printer_types, id, name,
1430 "printservers", "printer_types",
1431 "mach_id");
1432
1433 switch (ps->owner_type)
1434 {
1435 case 'U':
1436 if (!hash_lookup(users, ps->owner_id))
1437 {
1438 printf("Printserver %s has non-existant USER owner %d\n",
1439 name, ps->owner_id);
1440 if (single_fix("Set to no owner", 1))
1441 clear_ps_owner(ps);
1442 }
1443 break;
1444 case 'L':
1445 if (!hash_lookup(lists, ps->owner_id))
1446 {
1447 printf("Printserver %s has non-existant LIST owner %d\n",
1448 name, ps->owner_id);
1449 if (single_fix("Set to no owner", 1))
1450 clear_ps_owner(ps);
1451 }
1452 break;
1453 case 'K':
1454 if (ps->owner_id)
1455 ps->owner_id = maybe_fixup_unref_string(ps->owner_id, id, name,
1456 "printserver", "owner_id",
1457 "mach_id");
1458 if (ps->owner_id == 0)
1459 clear_ps_owner(ps);
1460 }
1461
1462 if (!hash_lookup(lists, ps->lpc_acl))
1463 {
1464 printf("Printserver %s has non-existent lpc_acl %d\n",
1465 name, ps->lpc_acl);
1466 if (single_fix("Set to no lpc_acl", 1))
1467 clear_ps_lpc(ps);
1468 }
1469}
1470
7ac48069 1471int show_fsg_missing(void *id)
208a4f4a 1472{
5eaef520 1473 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1474 int iid = (int)id, id1, found = 1;
5eaef520 1475 EXEC SQL END DECLARE SECTION;
1476 struct filesys *f;
1477
1478 EXEC SQL DECLARE csr210 CURSOR FOR
1479 SELECT filsys_id FROM fsgroup
1480 WHERE group_id = :iid;
1481 EXEC SQL OPEN csr210;
1482 while (1)
1483 {
1484 EXEC SQL FETCH csr210 INTO :id1;
1485 if (sqlca.sqlcode)
1486 break;
1487
1488 found = 0;
7ac48069 1489 if ((f = hash_lookup(filesys, id1)))
1490 printf("Missing fsgroup %d has member filesystem %s\n", iid, f->name);
5eaef520 1491 else
7ac48069 1492 printf("Missing fsgroup %d has member filesystem %d\n", iid, id1);
208a4f4a 1493 }
5eaef520 1494 EXEC SQL CLOSE csr210;
1495 return found;
208a4f4a 1496}
68bbc9c3 1497
7ac48069 1498int show_fsg_type(void *filesys)
68bbc9c3 1499{
7ac48069 1500 struct filesys *f = filesys;
5eaef520 1501 char *t;
68bbc9c3 1502
5eaef520 1503 switch (f->type)
1504 {
68bbc9c3 1505 case 'N':
5eaef520 1506 t = "NFS";
1507 break;
68bbc9c3 1508 case 'R':
5eaef520 1509 t = "RVD";
1510 break;
68bbc9c3 1511 case 'A':
5eaef520 1512 t = "AFS";
1513 break;
68bbc9c3 1514 case 'E':
5eaef520 1515 t = "ERR";
1516 break;
68bbc9c3 1517 case 'F':
5eaef520 1518 t = "FSGROUP";
1519 break;
68bbc9c3 1520 case 'M':
5eaef520 1521 t = "MUL";
1522 break;
68bbc9c3 1523 default:
5eaef520 1524 t = "\?\?\?";
68bbc9c3 1525 }
5eaef520 1526 printf("FSGroup %s has type %s instead of FSGROUP\n", f->name, t);
1527 return 0;
68bbc9c3 1528}
1529
7ac48069 1530void fix_fsg_type(void *filesys)
208a4f4a 1531{
7ac48069 1532 struct filesys *f = filesys;
5eaef520 1533 EXEC SQL BEGIN DECLARE SECTION;
1534 int rowcount, id = f->filsys_id;
1535 EXEC SQL END DECLARE SECTION;
1536
1537 EXEC SQL UPDATE filesys SET type = 'FSGROUP' WHERE filsys_id = :id;
1538 rowcount = sqlca.sqlerrd[2];
1539 if (rowcount > 0)
1540 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1541 else
1542 printf("Not fixed\n");
1543 modified("filesys");
208a4f4a 1544}
68bbc9c3 1545
7ac48069 1546int show_fsg_nomember(void *id)
208a4f4a 1547{
5eaef520 1548 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1549 int iid = (int)id, id1, found = 1;
5eaef520 1550 EXEC SQL END DECLARE SECTION;
1551 struct filesys *f;
1552
1553 EXEC SQL DECLARE csr211 CURSOR FOR
1554 SELECT group_id FROM fsgroup
1555 WHERE filsys_id = :iid;
1556 EXEC SQL OPEN csr211;
1557 while (1)
1558 {
1559 EXEC SQL FETCH csr211 INTO :id1;
1560 if (sqlca.sqlcode)
1561 break;
1562
1563 found = 0;
7ac48069 1564 if ((f = hash_lookup(filesys, id1)))
1565 printf("FSGroup %s has missing member %d\n", f->name, iid);
5eaef520 1566 else
7ac48069 1567 printf("FSGroup %d has missing member %d\n", id1, iid);
208a4f4a 1568 }
5eaef520 1569 EXEC SQL CLOSE csr211;
1570 return found;
208a4f4a 1571}
1572
7ac48069 1573int show_quota_nouser(void *id)
208a4f4a 1574{
5eaef520 1575 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1576 int iid = (int)id, id1, found = 1;
5eaef520 1577 EXEC SQL END DECLARE SECTION;
1578
1579 EXEC SQL DECLARE csr212 CURSOR FOR
1580 SELECT filsys_id FROM quota
1581 WHERE entity_id = :iid AND type = 'USER';
1582 EXEC SQL OPEN csr212;
1583 while (1)
1584 {
1585 EXEC SQL FETCH csr212 INTO :id1;
1586 if (sqlca.sqlcode)
1587 break;
1588
1589 found = 0;
7ac48069 1590 printf("Quota on fs %d for non-existant user %d\n", id1, iid);
208a4f4a 1591 }
5eaef520 1592 EXEC SQL CLOSE csr212;
1593 return found;
208a4f4a 1594}
1595
7ac48069 1596int show_quota_nolist(void *id)
208a4f4a 1597{
5eaef520 1598 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1599 int iid = (int)id, id1, found = 1;
5eaef520 1600 EXEC SQL END DECLARE SECTION;
1601
1602 EXEC SQL DECLARE csr213 CURSOR FOR
1603 SELECT filsys_id FROM quota
1604 WHERE entity_id = :iid AND type = 'GROUP';
1605 EXEC SQL OPEN csr213;
1606 while (1)
1607 {
1608 EXEC SQL FETCH csr213 INTO :id1;
1609 if (sqlca.sqlcode)
1610 break;
1611
1612 found = 0;
7ac48069 1613 printf("Quota on fs %d for non-existant list %d\n", id1, iid);
208a4f4a 1614 }
5eaef520 1615 EXEC SQL CLOSE csr213;
1616 return found;
208a4f4a 1617}
68bbc9c3 1618
7ac48069 1619void fix_quota_nouser(void *id)
208a4f4a 1620{
5eaef520 1621 EXEC SQL BEGIN DECLARE SECTION;
11975951 1622 int iid = (int)id, rowcount;
5eaef520 1623 EXEC SQL END DECLARE SECTION;
1624
5eaef520 1625 EXEC SQL DELETE FROM quota
1626 WHERE entity_id = :iid AND type = 'USER';
1627 rowcount = sqlca.sqlerrd[2];
1628 if (rowcount > 0)
1629 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1630 else
1631 printf("Not deleted\n");
1632 modified("quota");
208a4f4a 1633}
68bbc9c3 1634
7ac48069 1635void fix_quota_nolist(void *id)
208a4f4a 1636{
5eaef520 1637 EXEC SQL BEGIN DECLARE SECTION;
11975951 1638 int iid = (int)id, rowcount;
5eaef520 1639 EXEC SQL END DECLARE SECTION;
1640
5eaef520 1641 EXEC SQL DELETE FROM quota WHERE entity_id = :iid AND type = 'GROUP';
1642 rowcount = sqlca.sqlerrd[2];
1643 if (rowcount > 0)
1644 printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies");
1645 else
1646 printf("Not deleted\n");
1647 modified("quota");
208a4f4a 1648}
1649
7ac48069 1650int show_quota_nofs(void *id)
208a4f4a 1651{
5eaef520 1652 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1653 int iid = (int)id, id1, found = 1;
cfc4f91e 1654 char type[QUOTA_TYPE_SIZE];
5eaef520 1655 EXEC SQL END DECLARE SECTION;
1656
1657 EXEC SQL DECLARE csr214 CURSOR FOR
1658 SELECT entity_id, type FROM quota
1659 WHERE filsys_id = :iid;
1660 EXEC SQL OPEN csr214;
1661 while (1)
1662 {
1663 EXEC SQL FETCH csr214 INTO :id1, :type;
1664 if (sqlca.sqlcode)
1665 break;
1666
1667 found = 0;
7ac48069 1668 printf("Quota for %s %d on non-existant filesys %d\n", type, id1, iid);
208a4f4a 1669 }
5eaef520 1670 EXEC SQL CLOSE csr214;
1671 return found;
208a4f4a 1672}
68bbc9c3 1673
7ac48069 1674void fix_quota_nofs(void *id)
68bbc9c3 1675{
7ac48069 1676 single_delete("quota", "filsys_id", (int)id);
68bbc9c3 1677}
1678
7ac48069 1679int show_quota_wrongpid(void *id)
208a4f4a 1680{
5eaef520 1681 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1682 int iid = (int)id, id1, found = 1;
cfc4f91e 1683 char type[QUOTA_TYPE_SIZE];
5eaef520 1684 EXEC SQL END DECLARE SECTION;
5eaef520 1685 struct filesys *f;
1686
7ac48069 1687 f = hash_lookup(filesys, iid);
5eaef520 1688 EXEC SQL DECLARE csr215 CURSOR FOR
1689 SELECT entity_id, type FROM quota
1690 WHERE filsys_id = :iid;
1691 EXEC SQL OPEN csr215;
1692 while (1)
1693 {
1694 EXEC SQL FETCH csr215 INTO :id1, :type;
1695 if (sqlca.sqlcode)
1696 break;
1697
1698 found = 0;
1699 printf("Quota for %s %d on filesys %s has wrong phys_id %d\n",
7ac48069 1700 type, id1, f->name, iid);
208a4f4a 1701 }
5eaef520 1702 EXEC SQL CLOSE csr215;
1703 return found;
208a4f4a 1704}
68bbc9c3 1705
7ac48069 1706void fix_quota_physid(void *id)
208a4f4a 1707{
5eaef520 1708 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1709 int iid = (int)id, rowcount, id1;
5eaef520 1710 EXEC SQL END DECLARE SECTION;
1711
7ac48069 1712 id1 = ((struct filesys *)hash_lookup(filesys, iid))->phys_id;
5eaef520 1713 EXEC SQL UPDATE quota SET phys_id = :id1
1714 WHERE filsys_id = :iid AND phys_id != :id1;
1715 rowcount = sqlca.sqlerrd[2];
1716 if (rowcount > 0)
1717 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1718 else
1719 printf("Not fixed\n");
1720 modified("quota");
208a4f4a 1721}
68bbc9c3 1722
7ac48069 1723int show_srv_user(void *id)
208a4f4a 1724{
5eaef520 1725 EXEC SQL BEGIN DECLARE SECTION;
cfc4f91e 1726 char name[SERVERS_NAME_SIZE];
7ac48069 1727 int iid = (int)id;
5eaef520 1728 EXEC SQL END DECLARE SECTION;
1729 int found = 1;
1730
1731 EXEC SQL DECLARE csr216 CURSOR FOR
1732 SELECT name FROM servers
1733 WHERE acl_type = 'USER' and acl_id = :iid;
1734 EXEC SQL OPEN csr216;
1735 while (1)
1736 {
1737 EXEC SQL FETCH csr216 INTO :name;
1738 if (sqlca.sqlcode)
1739 break;
1740
1741 strtrim(name);
7ac48069 1742 printf("Service %s has acl non-existant user %d\n", name, iid);
5eaef520 1743 found = 0;
208a4f4a 1744 }
5eaef520 1745 EXEC SQL CLOSE csr216;
1746 return found;
208a4f4a 1747}
68bbc9c3 1748
7ac48069 1749int show_srv_list(void *id)
208a4f4a 1750{
5eaef520 1751 EXEC SQL BEGIN DECLARE SECTION;
cfc4f91e 1752 char name[SERVERS_NAME_SIZE];
7ac48069 1753 int iid = (int)id;
5eaef520 1754 EXEC SQL END DECLARE SECTION;
1755 int found = 1;
1756
1757 EXEC SQL DECLARE csr217 CURSOR FOR
1758 SELECT name FROM servers
1759 WHERE acl_type = 'LIST' AND acl_id = :iid;
1760 EXEC SQL OPEN csr217;
1761 while (1)
1762 {
1763 EXEC SQL FETCH csr217 INTO :name;
1764 if (sqlca.sqlcode)
1765 break;
1766
1767 strtrim(name);
7ac48069 1768 printf("Service %s has acl non-existant list %d\n", name, iid);
5eaef520 1769 found = 0;
208a4f4a 1770 }
5eaef520 1771 EXEC SQL CLOSE csr217;
1772 return found;
208a4f4a 1773}
68bbc9c3 1774
7ac48069 1775void zero_srv_user(void *id)
208a4f4a 1776{
5eaef520 1777 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1778 int iid = (int)id, rowcount;
5eaef520 1779 EXEC SQL END DECLARE SECTION;
1780
1781 EXEC SQL UPDATE servers SET acl_id = 0 WHERE acl_id = :iid AND
1782 acl_type = 'USER';
1783 rowcount = sqlca.sqlerrd[2];
1784 if (rowcount > 0)
1785 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1786 else
1787 printf("Not fixed\n");
1788 modified("servers");
208a4f4a 1789}
68bbc9c3 1790
7ac48069 1791void zero_srv_list(void *id)
208a4f4a 1792{
5eaef520 1793 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1794 int iid = (int)id, rowcount;
5eaef520 1795 EXEC SQL END DECLARE SECTION;
68bbc9c3 1796
5eaef520 1797 EXEC SQL UPDATE servers SET acl_id = 0 WHERE acl_id = :iid AND
1798 acl_type = 'LIST';
1799 rowcount = sqlca.sqlerrd[2];
1800 if (rowcount > 0)
1801 printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies");
1802 else
1803 printf("Not fixed\n");
1804 modified("servers");
1805}
68bbc9c3 1806
7ac48069 1807int show_krb_usr(void *id)
208a4f4a 1808{
5eaef520 1809 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1810 int iid = (int)id, found = 1, id1;
5eaef520 1811 EXEC SQL END DECLARE SECTION;
1812 struct string *s;
1813 char *ss;
1814
1815 EXEC SQL DECLARE csr218 CURSOR FOR
1816 SELECT string_id FROM krbmap
1817 WHERE users_id = :iid;
1818 EXEC SQL OPEN csr218;
1819 while (1)
1820 {
1821 EXEC SQL FETCH csr218 INTO :id1;
1822 if (sqlca.sqlcode)
1823 break;
1824
7ac48069 1825 if ((s = hash_lookup(strings, id1)))
5eaef520 1826 ss = s->name;
1827 else
1828 ss = "[unknown]";
1829 found = 0;
1830 printf("Kerberos map for non-existant user %d to principal %s\n",
7ac48069 1831 iid, ss);
208a4f4a 1832 }
5eaef520 1833 EXEC SQL CLOSE csr218;
1834 return found;
208a4f4a 1835}
68bbc9c3 1836
7ac48069 1837int show_krb_str(void *id)
208a4f4a 1838{
5eaef520 1839 EXEC SQL BEGIN DECLARE SECTION;
7ac48069 1840 int iid = (int)id, found = 1, id1;
5eaef520 1841 EXEC SQL END DECLARE SECTION;
1842 struct user *u;
1843 char *s;
1844
1845 EXEC SQL DECLARE csr219 CURSOR FOR
1846 SELECT users_id FROM krbmap
1847 WHERE string_id = :iid;
1848 EXEC SQL OPEN csr219;
1849 while (1)
1850 {
1851 EXEC SQL FETCH csr219 INTO :id1;
1852 if (sqlca.sqlcode)
1853 break;
68bbc9c3 1854
7ac48069 1855 if ((u = hash_lookup(users, id1)))
5eaef520 1856 s = u->login;
1857 else
1858 s = "[\?\?\?]";
1859 found = 0;
1860 printf("Kerberos map for user %s (%d) to non-existant string %d\n",
7ac48069 1861 s, id1, iid);
5eaef520 1862 }
1863 EXEC SQL CLOSE csr219;
1864 return found;
1865}
68bbc9c3 1866
7ac48069 1867void phase2(void)
208a4f4a 1868{
fe0a844a 1869 struct save_queue *sq, *sq1, *sq2, *sq3, *sq4, *sq5, *sq6;
5eaef520 1870 struct filesys *f;
1871 struct list *l;
1872 struct nfsphys *n;
1873 struct machine *m;
c978c079 1874 char rowid[32];
5eaef520 1875
1876 printf("Phase 2 - Checking references\n");
1877
1878 dprintf("Checking users...\n");
1879 hash_step(users, user_check, NULL);
1880
1881 dprintf("Checking machines...\n");
1882 hash_step(machines, mach_check, NULL);
1883
1884 dprintf("Checking subnets...\n");
1885 hash_step(subnets, subnet_check, NULL);
1886
1887 dprintf("Checking clusters...\n");
1888 hash_step(clusters, cluster_check, NULL);
1889
1890 dprintf("Checking mcmap...\n");
1891 sq1 = sq_create();
1892 sq2 = sq_create();
1893 EXEC SQL DECLARE csr221 CURSOR FOR
1894 SELECT mach_id, clu_id FROM mcmap;
1895 EXEC SQL OPEN csr221;
1896 while (1)
1897 {
cfc4f91e 1898 EXEC SQL BEGIN DECLARE SECTION;
1899 int mach_id, clu_id;
1900 EXEC SQL END DECLARE SECTION;
1901
1902 EXEC SQL FETCH csr221 INTO :mach_id, :clu_id;
5eaef520 1903 if (sqlca.sqlcode)
1904 break;
1905
cfc4f91e 1906 if (!(m = hash_lookup(machines, mach_id)))
1907 sq_save_unique_data(sq1, (void *)mach_id);
1908 else if (!hash_lookup(clusters, clu_id))
1909 sq_save_unique_data(sq2, (void *)clu_id);
5eaef520 1910 if (m)
1911 m->clucount++;
ab05f33a 1912 }
5eaef520 1913 EXEC SQL CLOSE csr221;
1914 generic_delete(sq1, show_mcm_mach, "mcmap", "mach_id", 1);
1915 generic_delete(sq2, show_mcm_clu, "mcmap", "clu_id", 1);
1916
1917 dprintf("Checking service clusters...\n");
1918 sq1 = sq_create();
1919 EXEC SQL DECLARE csr222 CURSOR FOR
1920 SELECT clu_id FROM svc;
1921 EXEC SQL OPEN csr222;
1922 while (1)
1923 {
cfc4f91e 1924 EXEC SQL BEGIN DECLARE SECTION;
1925 int clu_id;
1926 EXEC SQL END DECLARE SECTION;
1927
1928 EXEC SQL FETCH csr222 INTO :clu_id;
5eaef520 1929 if (sqlca.sqlcode)
1930 break;
1931
cfc4f91e 1932 if (!hash_lookup(clusters, clu_id))
1933 sq_save_unique_data(sq1, (void *)clu_id);
208a4f4a 1934 }
5eaef520 1935 EXEC SQL CLOSE csr222;
1936 generic_delete(sq1, show_svc, "svc", "clu_id", 1);
1937
1938 dprintf("Checking lists...\n");
1939 hash_step(lists, list_check, NULL);
1940
1941 dprintf("Checking members...\n");
1942 sq1 = sq_create();
1943 sq2 = sq_create();
1944 sq3 = sq_create();
1945 sq4 = sq_create();
1946 sq5 = sq_create();
1947
1948 EXEC SQL DECLARE csr223 CURSOR FOR
c0a94410 1949 SELECT list_id, member_type, member_id, tag, ref_count, direct, rowid
5eaef520 1950 FROM imembers FOR UPDATE OF member_id;
1951 EXEC SQL OPEN csr223;
1952 while (1)
1953 {
cfc4f91e 1954 EXEC SQL BEGIN DECLARE SECTION;
c0a94410 1955 int list_id, id, tag, ref_count, direct;
cfc4f91e 1956 char type[IMEMBERS_MEMBER_TYPE_SIZE];
1957 EXEC SQL END DECLARE SECTION;
1958
38da5476 1959 EXEC SQL FETCH csr223 INTO :list_id, :type, :id, :tag,
c978c079 1960 :ref_count, :direct, :rowid;
5eaef520 1961 if (sqlca.sqlcode)
1962 break;
c0a94410 1963 strtrim(rowid);
5eaef520 1964
cfc4f91e 1965 if (!(l = hash_lookup(lists, list_id)))
1966 sq_save_unique_data(sq1, (void *)list_id);
1967 else if (type[0] == 'U' && !hash_lookup(users, id))
1968 sq_save_unique_data(sq2, (void *)id);
1969 else if (type[0] == 'L' && !hash_lookup(lists, id))
1970 sq_save_unique_data(sq3, (void *)id);
c0a94410 1971 else if (type[0] == 'S' && !maybe_fixup_unref_string2("imembers", "member_id", rowid, id))
cfc4f91e 1972 sq_save_unique_data(sq4, (void *)id);
c0a94410 1973 else if (type[0] == 'K' && !maybe_fixup_unref_string2("imembers", "member_id", rowid, id))
cfc4f91e 1974 sq_save_unique_data(sq5, (void *)id);
5eaef520 1975 else
1976 l->members++;
c0a94410 1977 maybe_fixup_unref_string2("imembers", "tag", rowid, tag);
208a4f4a 1978 }
5eaef520 1979 EXEC SQL CLOSE csr223;
1980 generic_delete(sq1, show_member_list, "imembers", "list_id", 1);
1981 generic_fix(sq2, show_mem_user, "Delete", del_mem_user, 1);
1982 generic_fix(sq3, show_mem_list, "Delete", del_mem_list, 1);
1983 generic_fix(sq4, show_mem_str, "Delete", del_mem_str, 1);
1984 generic_fix(sq5, show_mem_krb, "Delete", del_mem_krb, 1);
1985
1986 dprintf("Checking servers...\n");
1987 sq1 = sq_create();
1988 sq2 = sq_create();
1989 EXEC SQL DECLARE csr224 CURSOR FOR
c978c079 1990 SELECT name, acl_type, acl_id, modby, rowid FROM servers
5eaef520 1991 FOR UPDATE of modby;
1992 EXEC SQL OPEN csr224;
1993 while (1)
1994 {
cfc4f91e 1995 EXEC SQL BEGIN DECLARE SECTION;
1996 int acl_id, modby;
1997 char name[SERVERS_NAME_SIZE], acl_type[SERVERS_ACL_TYPE_SIZE];
1998 EXEC SQL END DECLARE SECTION;
1999
c978c079 2000 EXEC SQL FETCH csr224 INTO :name, :acl_type, :acl_id, :modby, :rowid;
5eaef520 2001 if (sqlca.sqlcode)
2002 break;
2003
11975951 2004 maybe_fixup_modby2("servers", "modby", strtrim(rowid), modby);
cfc4f91e 2005 strtrim(acl_type);
2006 if (!strcmp(acl_type, "USER") && !hash_lookup(users, acl_id))
2007 sq_save_data(sq1, (void *)acl_id);
2008 else if (!strcmp(acl_type, "LIST") && !hash_lookup(lists, acl_id))
2009 sq_save_data(sq2, (void *)acl_id);
5eaef520 2010 }
2011 EXEC SQL CLOSE csr224;
2012 generic_fix(sq1, show_srv_user, "Fix", zero_srv_user, 1);
2013 generic_fix(sq2, show_srv_list, "Fix", zero_srv_list, 1);
2014
2015 dprintf("Checking serverhosts...\n");
2016 sq = sq_create();
2017 EXEC SQL DECLARE csr225 CURSOR FOR
c978c079 2018 SELECT mach_id, modby, rowid FROM serverhosts
5eaef520 2019 FOR UPDATE OF modby;
2020 EXEC SQL OPEN csr225;
2021 while (1)
2022 {
cfc4f91e 2023 EXEC SQL BEGIN DECLARE SECTION;
2024 int mach_id, modby;
2025 EXEC SQL END DECLARE SECTION;
2026
c978c079 2027 EXEC SQL FETCH csr225 INTO :mach_id, :modby, :rowid;
5eaef520 2028 if (sqlca.sqlcode)
2029 break;
2030
11975951 2031 maybe_fixup_modby2("serverhosts", "modby", strtrim(rowid), modby);
cfc4f91e 2032 if (!hash_lookup(machines, mach_id))
2033 sq_save_data(sq, (void *)mach_id);
5eaef520 2034 }
2035 EXEC SQL CLOSE csr225;
2036 generic_fix(sq, show_sh, "Delete", del_sh_mach, 0);
2037
2038 dprintf("Checking nfsphys...\n");
2039 hash_step(nfsphys, check_nfsphys, NULL);
2040
2041 dprintf("Checking filesys...\n");
2042 hash_step(filesys, check_fs, NULL);
2043
2044 dprintf("Checking filesystem groups...\n");
2045 sq1 = sq_create();
2046 sq2 = sq_create();
2047 sq3 = sq_create();
2048 EXEC SQL DECLARE csr226 CURSOR FOR
2049 SELECT group_id, filsys_id FROM fsgroup;
2050 EXEC SQL OPEN csr226;
2051 while (1)
2052 {
cfc4f91e 2053 EXEC SQL BEGIN DECLARE SECTION;
2054 int group_id, filsys_id;
2055 EXEC SQL END DECLARE SECTION;
2056
2057 EXEC SQL FETCH csr226 INTO :group_id, :filsys_id;
5eaef520 2058 if (sqlca.sqlcode)
2059 break;
2060
cfc4f91e 2061 if (!(f = hash_lookup(filesys, group_id)))
2062 sq_save_data(sq1, (void *)group_id);
2063 if (!hash_lookup(filesys, filsys_id))
2064 sq_save_data(sq3, (void *)filsys_id);
208a4f4a 2065 }
5eaef520 2066 EXEC SQL CLOSE csr226;
2067 generic_delete(sq1, show_fsg_missing, "fsgroup", "group_id", 0);
2068 generic_delete(sq3, show_fsg_nomember, "fsgroup", "filsys_id", 1);
2069
2070 dprintf("Checking quotas...\n");
2071 sq1 = sq_create();
2072 sq2 = sq_create();
2073 sq3 = sq_create();
2074 sq4 = sq_create();
2075 EXEC SQL DECLARE csr227 CURSOR FOR
c978c079 2076 SELECT entity_id, type, filsys_id, phys_id, quota, modby, rowid
5eaef520 2077 FROM quota FOR UPDATE OF modby;
2078 EXEC SQL OPEN csr227;
2079 while (1)
2080 {
cfc4f91e 2081 EXEC SQL BEGIN DECLARE SECTION;
2082 int entity_id, filsys_id, phys_id, quota, modby;
2083 char type[QUOTA_TYPE_SIZE];
2084 EXEC SQL END DECLARE SECTION;
2085
2086 EXEC SQL FETCH csr227 INTO :entity_id, :type, :filsys_id,
c978c079 2087 :phys_id, :quota, :modby, :rowid;
5eaef520 2088 if (sqlca.sqlcode)
2089 break;
2090
11975951 2091 maybe_fixup_modby2("quota", "modby", strtrim(rowid), modby);
cfc4f91e 2092 if (type[0] == 'U' && entity_id != 0 && !hash_lookup(users, entity_id))
2093 sq_save_data(sq1, (void *)entity_id);
2094 else if (type[0] == 'G' && !hash_lookup(lists, entity_id))
2095 sq_save_data(sq4, (void *)entity_id);
2096 else if (!(f = hash_lookup(filesys, filsys_id)))
2097 sq_save_data(sq2, (void *)filsys_id);
2098 else if (phys_id != f->phys_id || !(n = hash_lookup(nfsphys, phys_id)))
2099 sq_save_data(sq3, (void *)phys_id);
5eaef520 2100 else
cfc4f91e 2101 n->count += quota;
208a4f4a 2102 }
5eaef520 2103 EXEC SQL CLOSE csr227;
2104 generic_fix(sq1, show_quota_nouser, "Delete", fix_quota_nouser, 1);
2105 generic_fix(sq2, show_quota_nofs, "Delete", fix_quota_nofs, 0);
2106 generic_fix(sq3, show_quota_wrongpid, "Fix", fix_quota_physid, 1);
2107 generic_fix(sq4, show_quota_nolist, "Delete", fix_quota_nolist, 1);
2108
37ed4e84 2109 dprintf("Checking zephyr...\n");
2110 EXEC SQL DECLARE csr_zc CURSOR FOR
2111 SELECT class, xmt_type, xmt_id, sub_type, sub_id, iws_type, iws_id,
2112 iui_type, iui_id, modby FROM zephyr;
2113 EXEC SQL OPEN csr_zc;
2114 while(1)
2115 {
2116 EXEC SQL BEGIN DECLARE SECTION;
2117 int xmt_id, sub_id, iws_id, iui_id, modby;
2118 char class[ZEPHYR_CLASS_SIZE];
2119 char xmt_type[ZEPHYR_XMT_TYPE_SIZE];
2120 char sub_type[ZEPHYR_SUB_TYPE_SIZE];
2121 char iws_type[ZEPHYR_IWS_TYPE_SIZE];
2122 char iui_type[ZEPHYR_IUI_TYPE_SIZE];
2123 EXEC SQL END DECLARE SECTION;
2124
2125 EXEC SQL FETCH csr_zc INTO :class, :xmt_type, :xmt_id, :sub_type,
2126 :sub_id, :iws_type, :iws_id, :iui_type, :iui_id, :modby;
2127
2128 if (sqlca.sqlcode)
2129 break;
2130
2131 maybe_fixup_modby2("zephyr", "modby", strtrim(rowid), modby);
2132
2133 strtrim(xmt_type);
2134 if (!strcmp(xmt_type, "USER") && !hash_lookup(users, xmt_id))
2135 {
2136 printf("xmt acl for %s is non-existant user %d\n", class, xmt_id);
2137 printf("Not fixing this error\n");
2138 }
2139 else if (!strcmp(xmt_type, "LIST") && !hash_lookup(lists, xmt_id))
2140 {
2141 printf("xmt acl for %s is non-existant list %d\n", class, xmt_id);
2142 printf("Not fixing this error\n");
2143 }
2144 else if (!strcmp(xmt_type, "STRING") || !strcmp(xmt_type, "KERBEROS"))
2145 maybe_fixup_unref_string2("zephyr", "xmt_id", strtrim(rowid), xmt_id);
2146
2147 strtrim(sub_type);
2148 if (!strcmp(sub_type, "USER") && !hash_lookup(users, sub_id))
2149 {
2150 printf("sub acl for %s is non-existant user %d\n", class, sub_id);
2151 printf("Not fixing this error\n");
2152 }
2153 else if (!strcmp(sub_type, "LIST") && !hash_lookup(lists, sub_id))
2154 {
2155 printf("sub acl for %s is non-existant list %d\n", class, sub_id);
2156 printf("Not fixing this error\n");
2157 }
2158 else if (!strcmp(sub_type, "STRING") || !strcmp(sub_type, "KERBEROS"))
2159 maybe_fixup_unref_string2("zephyr", "sub_id", strtrim(rowid), sub_id);
2160
2161 strtrim(iws_type);
2162 if (!strcmp(iws_type, "USER") && !hash_lookup(users, iws_id))
2163 {
2164 printf("iws acl for %s is non-existant user %d\n", class, iws_id);
2165 printf("Not fixing this error\n");
2166 }
2167 else if (!strcmp(iws_type, "LIST") && !hash_lookup(lists, iws_id))
2168 {
2169 printf("iws acl for %s is non-existant list %d\n", class, iws_id);
2170 printf("Not fixing this error\n");
2171 }
2172 else if (!strcmp(iws_type, "STRING") || !strcmp(iws_type, "KERBEROS"))
2173 maybe_fixup_unref_string2("zephyr", "iws_id", strtrim(rowid), iws_id);
2174
2175 strtrim(iui_type);
2176 if (!strcmp(iui_type, "USER") && !hash_lookup(users, iui_id))
2177 {
2178 printf("iui acl for %s is non-existant user %d\n", class, iui_id);
2179 printf("Not fixing this error\n");
2180 }
2181 else if (!strcmp(iui_type, "LIST") && !hash_lookup(lists, iui_id))
2182 {
2183 printf("iui acl for %s is non-existant list %d\n", class, iui_id);
2184 printf("Not fixing this error\n");
2185 }
2186 else if (!strcmp(iui_type, "STRING") || !strcmp(iui_type, "KERBEROS"))
2187 maybe_fixup_unref_string2("zephyr", "iui_id", strtrim(rowid), iui_id);
2188 }
5eaef520 2189
2190 dprintf("Checking hostaccess...\n");
2191 EXEC SQL DECLARE csr228 CURSOR FOR
c978c079 2192 SELECT mach_id, acl_type, acl_id, modby, rowid FROM hostaccess
5eaef520 2193 FOR UPDATE OF modby;
2194 EXEC SQL OPEN csr228;
2195 while (1)
2196 {
cfc4f91e 2197 EXEC SQL BEGIN DECLARE SECTION;
2198 int mach_id, acl_id, modby;
2199 char acl_type[HOSTACCESS_ACL_TYPE_SIZE];
2200 EXEC SQL END DECLARE SECTION;
2201
c978c079 2202 EXEC SQL FETCH csr228 INTO :mach_id, :acl_type, :acl_id, :modby, :rowid;
5eaef520 2203 if (sqlca.sqlcode)
2204 break;
2205
11975951 2206 maybe_fixup_modby2("hostaccess", "modby", strtrim(rowid), modby);
cfc4f91e 2207 strtrim(acl_type);
2208 if (!hash_lookup(machines, mach_id))
5eaef520 2209 {
cfc4f91e 2210 printf("Hostaccess for non-existant host %d\n", mach_id);
5eaef520 2211 printf("Not fixing this error\n");
68bbc9c3 2212 }
cfc4f91e 2213 if (!strcmp(acl_type, "USER") && !hash_lookup(users, acl_id))
5eaef520 2214 {
cfc4f91e 2215 printf("Hostaccess for %d is non-existant user %d\n", mach_id, acl_id);
5eaef520 2216 printf("Not fixing this error\n");
68bbc9c3 2217 }
cfc4f91e 2218 else if (!strcmp(acl_type, "LIST") && !hash_lookup(lists, acl_id))
5eaef520 2219 {
cfc4f91e 2220 printf("Hostaccess for %d is non-existant list %d\n", mach_id, acl_id);
5eaef520 2221 printf("Not fixing this error\n");
68bbc9c3 2222 }
208a4f4a 2223 }
5eaef520 2224 EXEC SQL CLOSE csr228;
2225
5eaef520 2226 dprintf("Checking krbmap...\n");
2227 sq1 = sq_create();
2228 sq2 = sq_create();
2229 EXEC SQL DECLARE csr230 CURSOR FOR
c978c079 2230 SELECT users_id, string_id, rowid FROM krbmap
5eaef520 2231 FOR UPDATE OF string_id;
2232 EXEC SQL OPEN csr230;
2233 while (1)
2234 {
cfc4f91e 2235 EXEC SQL BEGIN DECLARE SECTION;
2236 int users_id, string_id;
2237 EXEC SQL END DECLARE SECTION;
2238
c978c079 2239 EXEC SQL FETCH csr230 INTO :users_id, :string_id, :rowid;
5eaef520 2240 if (sqlca.sqlcode)
2241 break;
2242
cfc4f91e 2243 if (!hash_lookup(users, users_id))
2244 sq_save_unique_data(sq1, (void *)users_id);
11975951 2245 else if (!maybe_fixup_unref_string2("krbmap", "string_id", strtrim(rowid), string_id))
cfc4f91e 2246 sq_save_unique_data(sq2, (void *)string_id);
5eaef520 2247 }
2248 EXEC SQL CLOSE csr230;
2249 generic_delete(sq1, show_krb_usr, "krbmap", "users_id", 1);
2250 generic_delete(sq2, show_krb_str, "krbmap", "string_id", 1);
2251
2252 dprintf("Checking capacls...\n");
2253 EXEC SQL DECLARE csr231 CURSOR FOR
2254 SELECT list_id, tag FROM capacls;
2255 EXEC SQL OPEN csr231;
2256 while (1)
2257 {
cfc4f91e 2258 EXEC SQL BEGIN DECLARE SECTION;
2259 int list_id;
2260 char tag[CAPACLS_TAG_SIZE];
2261 EXEC SQL END DECLARE SECTION;
2262
2263 EXEC SQL FETCH csr231 INTO :list_id, :tag;
5eaef520 2264 if (sqlca.sqlcode)
2265 break;
2266
cfc4f91e 2267 if (!hash_lookup(lists, list_id))
5eaef520 2268 {
cfc4f91e 2269 printf("Capacl for %s is non-existant list %d\n", tag, list_id);
5eaef520 2270 printf("Not fixing this error\n");
68bbc9c3 2271 }
208a4f4a 2272 }
5eaef520 2273 EXEC SQL CLOSE csr231;
2274
2275 dprintf("Checking hostaliases\n");
2276 sq1 = sq_create();
2277 EXEC SQL DECLARE csr232 CURSOR FOR
2278 SELECT mach_id FROM hostalias;
2279 EXEC SQL OPEN csr232;
2280 while (1)
2281 {
cfc4f91e 2282 EXEC SQL BEGIN DECLARE SECTION;
2283 int mach_id;
2284 EXEC SQL END DECLARE SECTION;
2285
2286 EXEC SQL FETCH csr232 INTO :mach_id;
5eaef520 2287 if (sqlca.sqlcode)
2288 break;
2289
cfc4f91e 2290 if (!hash_lookup(machines, mach_id))
2291 sq_save_unique_data(sq1, (void *)mach_id);
ab05f33a 2292 }
5eaef520 2293 EXEC SQL CLOSE csr232;
2294 generic_delete(sq1, show_hostalias, "hostalias", "mach_id", 1);
2295
dabf20aa 2296 dprintf("Checking printers\n");
5eaef520 2297 sq1 = sq_create();
2298 sq2 = sq_create();
dabf20aa 2299 sq3 = sq_create();
2300 sq4 = sq_create();
2301 sq5 = sq_create();
fe0a844a 2302 sq6 = sq_create();
5eaef520 2303 EXEC SQL DECLARE csr233 CURSOR FOR
c978c079 2304 SELECT mach_id, loghost, rm, rq, ac, lpc_acl, modby, rowid FROM printers;
5eaef520 2305 EXEC SQL OPEN csr233;
2306 while (1)
2307 {
cfc4f91e 2308 EXEC SQL BEGIN DECLARE SECTION;
c96b70a5 2309 int mach_id, loghost, rm, rq, ac, lpc_acl, modby;
cfc4f91e 2310 EXEC SQL END DECLARE SECTION;
2311
11975951 2312 EXEC SQL FETCH csr233 INTO :mach_id, :loghost, :rm, :rq, :ac,
c978c079 2313 :lpc_acl, :modby, :rowid;
5eaef520 2314 if (sqlca.sqlcode)
2315 break;
2316
11975951 2317 maybe_fixup_modby2("printers", "modby", strtrim(rowid), modby);
cfc4f91e 2318 if (!hash_lookup(machines, mach_id))
2319 sq_save_unique_data(sq1, (void *)mach_id);
dabf20aa 2320 else if (!hash_lookup(machines, rm))
2321 sq_save_unique_data(sq2, (void *)rm);
fe0a844a 2322 else if (!hash_lookup(printservers, rm))
2323 sq_save_unique_data(sq6, (void *)mach_id);
dabf20aa 2324 else if (!hash_lookup(machines, rq))
2325 sq_save_unique_data(sq3, (void *)rq);
2326 else {
2327 if (!hash_lookup(lists, ac))
2328 sq_save_unique_data(sq4, (void *)ac);
2329 if (!hash_lookup(lists, lpc_acl))
2330 sq_save_unique_data(sq5, (void *)lpc_acl);
2331 if (!hash_lookup(machines, loghost))
2332 {
2333 show_printer_loghost((void *)loghost);
c96b70a5 2334 cant_fix();
dabf20aa 2335 }
c96b70a5 2336 }
ab05f33a 2337 }
5eaef520 2338 EXEC SQL CLOSE csr233;
dabf20aa 2339 generic_delete(sq1, show_printer_mach, "printers", "mach_id", 1);
fe0a844a 2340 generic_delete(sq6, show_printer_server, "printers", "mach_id", 1);
dabf20aa 2341 generic_delete(sq2, show_printer_spool, "printers", "rm", 1);
2342 generic_delete(sq3, show_printer_quota, "printers", "rq", 1);
2343 generic_fix(sq4, show_printer_ac, "Clear", fix_printer_ac, 1);
2344 generic_fix(sq5, show_printer_lpc_acl, "Clear", fix_printer_lpc_acl, 1);
fe0a844a 2345
2346 dprintf("Checking printservers\n");
2347 hash_step(printservers, check_ps, NULL);
ab05f33a 2348}
c96b70a5 2349
This page took 0.446999 seconds and 5 git commands to generate.