3 * (c) Copyright 1988 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
8 #include <mit-copyright.h>
13 EXEC SQL INCLUDE sqlca;
15 static char phase1_qc_rcsid[] = "$Header$";
17 EXEC SQL WHENEVER SQLERROR DO dbmserr();
19 int show_user_id(struct user *u)
21 printf("User %s (%s, status %d) has duplicate ID\n",
22 u->login, u->fullname, u->status);
26 handle_duplicate_logins(struct save_queue *sq)
28 struct user *u, *uu, *tmp;
31 if (sq_get_data(sq, &uu))
33 while (sq_get_data(sq, &u))
35 if (!strcmp(u->login, uu->login))
37 if (uu->status == 1 || u->status == 0)
43 printf("User %s (%s, status %d) and\n",
44 u->login, u->fullname, u->status);
45 printf("User %s (%s, status %d) have duplicate logins\n",
46 uu->login, uu->fullname, uu->status);
47 if (!strcmp(u->fullname, uu->fullname) &&
48 single_fix("Delete the second one"))
49 single_delete("users", "users_id", uu->users_id);
50 else if (single_fix("Unregister the second one"))
52 EXEC SQL BEGIN DECLARE SECTION;
53 int id = uu->users_id, rowcount;
54 EXEC SQL END DECLARE SECTION;
57 SET login = '#' || CHAR(users.unix_uid), status = 0
59 rowcount = sqlca.sqlerrd[2];
62 printf("%d entr%s fixed\n", rowcount,
63 rowcount == 1 ? "y" : "ies");
66 printf("Not fixed\n");
76 fix_user_id(struct user *u)
78 u->users_id = generic_fix_id("users", "users_id", "login",
79 u->users_id, u->login);
85 printf("Sorry, don't know how to fix that\n");
88 int show_mach_id(struct machine *m)
90 printf("Machine %s has duplicate ID %d\n", m->name, m->mach_id);
94 int show_mach_name(struct machine *m)
96 printf("Machine %s (%d) has duplicate name\n", m->name, m->mach_id);
100 fix_mach_id(struct machine *m)
102 m->mach_id = generic_fix_id("machine", "mach_id", "name",
103 m->mach_id, m->name);
106 int show_snet_name(struct subnet *s)
108 printf("Subnet %s (%d) has duplicate name\n", s->name, s->snet_id);
112 int show_clu_id(struct cluster *c)
114 printf("Cluster %s has duplicate ID %d\n", c->name, c->clu_id);
118 int show_clu_name(struct cluster *c)
120 printf("Cluster %s (%d) has duplicate name\n", c->name, c->clu_id);
124 fix_clu_id(struct cluster *c)
126 c->clu_id = generic_fix_id("cluster", "clu_id", "name", c->clu_id, c->name);
129 int show_list_id(struct list *l)
131 printf("List %s has duplicate ID %d\n", l->name, l->list_id);
135 int show_list_name(struct list *l)
137 printf("List %s (%d) has duplicate name\n", l->name, l->list_id);
141 fix_list_id(struct list *l)
143 l->list_id = generic_fix_id("list", "list_id", "name", l->list_id, l->name);
146 int show_fs_id(struct filesys *f)
148 printf("Filesys %s has duplicate ID %d\n", f->name, f->filsys_id);
152 fix_fs_id(struct filesys *f)
154 f->filsys_id = generic_fix_id("filesys", "filsys_id", "label",
155 f->filsys_id, f->name);
158 int show_fs_name(struct filesys *fs)
160 printf("Filesys %s (%d) has duplicate name\n", fs->name, fs->filsys_id);
164 int show_np_id(struct nfsphys *n)
166 printf("NfsPhys %s:%s has duplicate ID %d\n",
167 ((struct machine *)hash_lookup(machines, n->mach_id))->name,
168 n->dir, n->nfsphys_id);
172 fix_np_id(struct nfsphys *n)
174 n->nfsphys_id = generic_fix_id("nfsphys", "nfsphys_id", "dir",
175 n->nfsphys_id, n->dir);
178 int show_str_id(struct string *s)
180 printf("String %s has duplicate ID %d\n", s->name, s->string_id);
184 int print_str_id(int id)
186 printf("String %d is a duplicate\n", id);
190 print_dup_map(int key, int data, char *hint)
192 printf("String %d is a duplicate of string %d\n", key, data);
197 EXEC SQL BEGIN DECLARE SECTION;
198 char name[81], name1[81], last[17], first[17], buf[257];
199 int id, id1, id2, id3, aid, aid2, status;
200 int sid, sid2, sid3, sid4, sid5;
201 EXEC SQL END DECLARE SECTION;
202 int i, q, retval, tmp;
203 struct save_queue *sq;
213 printf("Phase 1 - Looking for duplicates\n");
215 /* self-join strings table on "string" to get duplicate strings, then
216 build a duplicates table to merge them. */
218 dprintf("Looking for duplicate strings...\n");
219 string_dups = create_hash(100);
221 out_of_mem("storing duplicate strings");
223 EXEC SQL DECLARE csr116 CURSOR FOR
224 SELECT s1.string_id, s2.string_id FROM strings s1, strings s2
225 WHERE s1.string = s2.string and s1.string_id < s2.string_id;
226 EXEC SQL OPEN csr116;
227 /* The SELECT gives us two columns, both with non-negative integers.
228 * The number in the left column is always the smaller of the two,
229 * and each row includes string IDs for identical strings. We use
230 * them to make a mapping from id-to-delete to id-to-keep for all
236 EXEC SQL FETCH csr116 INTO :id1, :id2;
240 /* If id2 is already stored, skip this row. */
241 i = int_hash_lookup(string_dups, id2);
244 /* Follow the chain of id1 equivalent IDs back to the lowest one. */
246 while ((tmp = int_hash_lookup(string_dups, id)) > 0)
248 int_hash_store(string_dups, id2, id);
250 EXEC SQL CLOSE csr116;
251 dprintf("found %d duplicates\n", q);
252 int_hash_step(string_dups, print_dup_map, NULL);
253 /* We don't want to delete the duplicates now because if the dbck
254 is cancelled, a LOT of state will be lost. So, we'll just let
255 them not get marked as used and then phase3 will clean them up */
257 dprintf("Loading strings...\n");
259 strings = create_hash(75000);
261 out_of_mem("loading strings");
263 EXEC SQL DECLARE csr101 CURSOR FOR
264 SELECT string_id, string FROM strings ORDER BY string_id;
265 EXEC SQL OPEN csr101;
269 EXEC SQL FETCH csr101 INTO :id, :buf;
273 s = malloc(sizeof(struct string));
275 out_of_mem("storing strings");
276 s->name = strsave(strtrim(buf));
279 retval = hash_store(strings, id, s);
281 out_of_mem("storing strings in hash table");
282 else if (retval == 1) /* duplicate string_id */
284 sq_save_data(sq, hash_lookup(strings, id));
288 EXEC SQL CLOSE csr101;
289 /* keep string id 0 (the empty string) even if unreferenced */
292 printf("Loaded %d strings\n", q);
294 dprintf("Loading users...\n");
296 users = create_hash(30000);
298 out_of_mem("loading users");
300 EXEC SQL DECLARE csr102 CURSOR FOR
301 SELECT users_id, login, last, first, status, potype, pop_id, box_id,
302 modby, fmodby, pmodby, comments, sigwho FROM users
304 EXEC SQL OPEN csr102;
307 EXEC SQL FETCH csr102 INTO :id, :name, :last, :first, :status,
308 :buf, :id2, :id3, :sid, :sid2, :sid3, :sid4, :sid5;
312 u = malloc(sizeof(struct user));
314 out_of_mem("storing users");
315 strcpy(u->login, strtrim(name));
317 sprintf(buf, "%s, %s", strtrim(last), strtrim(first));
318 u->fullname = strsave(buf);
332 /* If potype is SMTP, box_id is a string_id for the strings tbl */
338 retval = hash_store(users, id, u);
340 out_of_mem("storing users in hash table");
341 else if (retval == 1)
343 sq_save_data(sq, hash_lookup(users, id));
347 EXEC SQL CLOSE csr102;
349 generic_fix(sq, show_user_id, "Change ID", fix_user_id, 0);
355 out_of_mem("finding duplicate logins");
357 EXEC SQL DECLARE csr103 CURSOR FOR
358 SELECT u1.users_id FROM users u1, users u2
359 WHERE u1.login = u2.login and u1.rowid != u2.rowid;
360 EXEC SQL OPEN csr103;
363 EXEC SQL FETCH csr103 INTO :id;
366 sq_save_data(sq, hash_lookup(users, id));
368 EXEC SQL CLOSE csr103;
369 handle_duplicate_logins(sq);
374 dprintf("Scanning krbmap...\n");
376 EXEC SQL DECLARE csr113 CURSOR FOR
377 SELECT k1.users_id FROM krbmap k1, krbmap k2
378 WHERE k1.users_id = k2.users_id AND k1.rowid != k2.rowid;
379 EXEC SQL OPEN csr113;
382 EXEC SQL FETCH csr113 INTO :id;
386 printf("User %d is in the krbmap more than once!\n", id);
387 printf("Not fixing this error\n");
389 EXEC SQL CLOSE csr113;
391 EXEC SQL DECLARE csr114 CURSOR FOR
392 SELECT k1.string_id FROM krbmap k1, krbmap k2
393 WHERE k1.string_id = k2.string_id AND k1.rowid != k2.rowid;
394 EXEC SQL OPEN csr114;
397 EXEC SQL FETCH csr114 INTO :id;
401 printf("Principal %d is in the krbmap more than once!\n", id);
402 printf("Not fixing this error\n");
404 EXEC SQL CLOSE csr114;
407 dprintf("Loading machines...\n");
409 machines = create_hash(20000);
410 if (!sq || !machines)
411 out_of_mem("loading machines");
413 EXEC SQL DECLARE csr104 CURSOR FOR
414 SELECT mach_id, name, snet_id, owner_type, owner_id,
415 acomment, ocomment, creator, modby
416 FROM machine ORDER BY mach_id;
417 EXEC SQL OPEN csr104;
420 EXEC SQL FETCH csr104 INTO :id, :name, :id2, :buf, :id3, :sid2,
425 m = malloc(sizeof(struct machine));
427 out_of_mem("storing machines");
428 strcpy(m->name, strtrim(name));
429 m->owner_type = buf[0];
438 retval = hash_store(machines, id, m);
440 out_of_mem("storing machines in hash table");
441 else if (retval == 1)
443 sq_save_data(sq, hash_lookup(machines, id));
447 EXEC SQL CLOSE csr104;
448 generic_fix(sq, show_mach_id, "Change ID", fix_mach_id, 0);
454 out_of_mem("looking for duplicate machine names");
456 EXEC SQL DECLARE csr105 CURSOR FOR
457 SELECT m1.mach_id FROM machine m1, machine m2
458 WHERE m1.name = m2.name AND m1.rowid != m2.rowid;
459 EXEC SQL OPEN csr105;
462 EXEC SQL FETCH csr105 INTO :id;
466 sq_save_data(sq, hash_lookup(machines, id));
468 EXEC SQL CLOSE csr105;
469 generic_fix(sq, show_mach_name, "Change name", cant_fix, 0);
471 EXEC SQL DECLARE csr_hal1 CURSOR FOR
472 SELECT h1.name, m1.mach_id, m2.mach_id
473 FROM hostalias h1, machine m1, hostalias h2, machine m2
474 WHERE h1.name = h2.name AND h1.mach_id != h2.mach_id
475 AND m1.mach_id = h1.mach_id AND m2.mach_id = h2.mach_id;
476 EXEC SQL OPEN csr_hal1;
479 EXEC SQL FETCH csr_hal1 INTO :name, :id1, :id2;
482 printf("Aliases for machines %d and %d have duplicate name %s\n",
483 id1, id2, strtrim(name));
486 EXEC SQL CLOSE csr_hal1;
488 EXEC SQL DECLARE csr_hal2 CURSOR FOR
489 SELECT h1.name, m1.mach_id, m2.mach_id
490 FROM hostalias h1, machine m1, machine m2
491 WHERE h1.name = m1.name AND h1.mach_id = m2.mach_id;
492 EXEC SQL OPEN csr_hal2;
495 EXEC SQL FETCH csr_hal2 INTO :name, :id1, :id2;
498 printf("Machine %d has alias %s that conflicts with machine %d\n",
499 id2, strtrim(name), id1);
502 EXEC SQL CLOSE csr_hal2;
505 dprintf("Loading subnets...\n");
506 subnets = create_hash(254);
508 out_of_mem("loading subnets");
510 EXEC SQL DECLARE csr115 CURSOR FOR
511 SELECT snet_id, name, owner_type, owner_id, modby from subnet;
512 EXEC SQL OPEN csr115;
515 EXEC SQL FETCH csr115 INTO :id, :name, :buf, :id2, :sid;
519 sn = malloc(sizeof(struct machine));
521 out_of_mem("storing subnets");
522 strcpy(sn->name, strtrim(name));
523 sn->owner_type = buf[0];
527 retval = hash_store(subnets, id, sn);
529 out_of_mem("storing subnets in hash table");
530 else if (retval == 1)
532 printf("Duplicate subnet ID: %d (%s)\n", id, name);
533 /* should add code to delete */
537 EXEC SQL CLOSE csr115;
543 out_of_mem("looking for duplicate subnet names");
545 EXEC SQL DECLARE csr117 CURSOR FOR
546 SELECT s1.snet_id FROM subnet s1, subnet s2
547 WHERE s1.name = s2.name AND s1.rowid != s2.rowid;
548 EXEC SQL OPEN csr117;
551 EXEC SQL FETCH csr117 INTO :id;
555 sq_save_data(sq, hash_lookup(subnets, id));
557 EXEC SQL CLOSE csr117;
558 generic_fix(sq, show_snet_name, "Change name", cant_fix, 0);
561 dprintf("Loading clusters...\n");
563 clusters = create_hash(100);
564 if (!sq || !clusters)
565 out_of_mem("loading clusters");
567 EXEC SQL DECLARE csr106 CURSOR FOR
568 SELECT clu_id, name, modby FROM clusters;
569 EXEC SQL OPEN csr106;
572 EXEC SQL FETCH csr106 INTO :id, :name, :sid;
576 c = malloc(sizeof(struct cluster));
578 out_of_mem("storing clusters");
579 strcpy(c->name, strtrim(name));
582 retval = hash_store(clusters, id, c);
584 out_of_mem("storing clusters in hash table");
585 else if (retval == 1)
587 sq_save_data(sq, hash_lookup(clusters, id));
591 EXEC SQL CLOSE csr106;
592 generic_fix(sq, show_clu_id, "Change ID", fix_clu_id, 0);
598 out_of_mem("looking for duplicate cluster names");
600 EXEC SQL DECLARE csr107 CURSOR FOR
601 SELECT c1.clu_id FROM clusters c1, clusters c2
602 WHERE c1.name = c2.name AND c1.rowid != c2.rowid;
603 EXEC SQL OPEN csr107;
606 EXEC SQL FETCH csr107 INTO :id;
610 sq_save_data(sq, hash_lookup(clusters, id));
612 EXEC SQL CLOSE csr107;
613 generic_fix(sq, show_clu_name, "Change name", cant_fix, 0);
616 dprintf("Loading lists...\n");
618 lists = create_hash(50000);
620 out_of_mem("loading lists");
622 EXEC SQL DECLARE csr108 CURSOR FOR
623 SELECT list_id, name, acl_id, acl_type, modby FROM list
625 EXEC SQL OPEN csr108;
628 EXEC SQL FETCH csr108 INTO :id, :name, :aid, :buf, :sid;
631 l = malloc(sizeof(struct list));
633 out_of_mem("storing lists");
634 strcpy(l->name, strtrim(name));
635 l->acl_type = buf[0];
639 retval = hash_store(lists, id, l);
641 out_of_mem("storing lists in hash table");
642 else if (retval == 1)
644 sq_save_data(sq, hash_lookup(lists, id));
648 EXEC SQL CLOSE csr108;
649 generic_fix(sq, show_list_id, "Change ID", fix_list_id, 0);
655 out_of_mem("looking for duplicate list names");
657 EXEC SQL DECLARE csr109 CURSOR FOR
658 SELECT l1.list_id FROM list l1, list l2
659 WHERE l1.name = l2.name AND l1.rowid != l2.rowid;
660 EXEC SQL OPEN csr109;
663 EXEC SQL FETCH csr109 INTO :id;
667 sq_save_data(sq, hash_lookup(lists, id));
669 EXEC SQL CLOSE csr109;
670 generic_fix(sq, show_list_name, "Change name", cant_fix, 0);
673 dprintf("Loading filesys...\n");
675 filesys = create_hash(30000);
677 out_of_mem("loading filesys");
679 EXEC SQL DECLARE csr110 CURSOR FOR
680 SELECT filsys_id, label, owner, owners, phys_id, mach_id,
681 type, name, modby FROM filesys ORDER BY filsys_id;
682 EXEC SQL OPEN csr110;
685 EXEC SQL FETCH csr110 INTO :id, :name, :aid, :aid2, :id2, :id3,
690 f = malloc(sizeof(struct filesys));
692 out_of_mem("storing filesystems");
693 strcpy(f->name, strtrim(name));
694 strcpy(f->dir, strtrim(name1));
701 retval = hash_store(filesys, id, f);
703 out_of_mem("storing filesys in hash table");
704 else if (retval == 1)
706 sq_save_data(sq, hash_lookup(filesys, id));
710 EXEC SQL CLOSE csr110;
712 generic_fix(sq, show_fs_id, "Change ID", fix_fs_id, 0);
718 out_of_mem("looking for duplicate filesys names");
720 EXEC SQL DECLARE csr118 CURSOR FOR
721 SELECT fs1.filsys_id FROM filesys fs1, filesys fs2
722 WHERE fs1.label = fs2.label AND fs1.rowid != fs2.rowid;
723 EXEC SQL OPEN csr118;
726 EXEC SQL FETCH csr118 INTO :id;
730 sq_save_data(sq, hash_lookup(filesys, id));
732 EXEC SQL CLOSE csr118;
733 generic_fix(sq, show_fs_name, "Change name", cant_fix, 0);
736 dprintf("Loading nfsphys...\n");
738 nfsphys = create_hash(500);
740 out_of_mem("loading nfsphs");
742 EXEC SQL DECLARE csr111 CURSOR FOR
743 SELECT nfsphys_id, dir, mach_id, allocated, modby FROM nfsphys;
744 EXEC SQL OPEN csr111;
747 EXEC SQL FETCH csr111 INTO :id, :name, :id2, :id3, :sid;
751 n = malloc(sizeof(struct nfsphys));
753 out_of_mem("storing nfsphys");
754 strcpy(n->dir, strtrim(name));
759 retval = hash_store(nfsphys, id, n);
761 out_of_mem("storing nfsphys in hash table");
762 else if (retval == 1)
764 sq_save_data(sq, hash_lookup(nfsphys, id));
768 EXEC SQL CLOSE csr111;
770 generic_fix(sq, show_np_id, "Change ID", fix_np_id, 0);
772 dprintf("Checking printcap...\n");
774 EXEC SQL DECLARE csr119 CURSOR FOR
775 SELECT p1.name FROM printcap p1, printcap p2
776 WHERE p1.name = p2.name AND p1.rowid < p2.rowid;
777 EXEC SQL OPEN csr119;
780 EXEC SQL FETCH csr119 INTO :name;
784 printf("Printer %s has duplicate name\n", name);
787 EXEC SQL CLOSE csr119;