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>
12 EXEC SQL INCLUDE sqlca;
14 static char phase1_qc_rcsid[] = "$Header$";
16 EXEC SQL WHENEVER SQLERROR DO dbmserr();
21 printf("User %s (%s, status %d) has duplicate ID\n",
22 u->login, u->fullname, u->status);
26 handle_duplicate_logins(sq)
27 struct save_queue *sq;
29 struct user *u, *uu, *tmp;
31 uu = (struct user *)0;
32 if(sq_get_data(sq,&uu)) {
33 while (sq_get_data(sq, &u)) {
34 if (!strcmp(u->login, uu->login)) {
35 if (uu->status == 1 || u->status == 0) {
40 printf("User %s (%s, status %d) and\n",
41 u->login, u->fullname, u->status);
42 printf("User %s (%s, status %d) have duplicate logins\n",
43 uu->login, uu->fullname, uu->status);
44 if (!strcmp(u->fullname, uu->fullname) &&
45 single_fix("Delete the second one")) {
46 single_delete("users", "users_id", uu->users_id);
47 } else if (single_fix("Unregister the second one"))
49 EXEC SQL BEGIN DECLARE SECTION;
50 int id = uu->users_id, rowcount;
51 EXEC SQL END DECLARE SECTION;
53 EXEC SQL UPDATE users SET login = '#' || CHAR(users.unix_uid),
54 status=0 WHERE users_id = :id;
55 rowcount = sqlca.sqlerrd[2];
57 printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
59 printf("Not fixed\n");
72 u->users_id = generic_fix_id("users", "users_id", "login",
73 u->users_id, u->login);
80 printf("Sorry, don't know how to fix that\n");
86 printf("Machine %s has duplicate ID %d\n", m->name, m->mach_id);
93 printf("Machine %s (%d) has duplicate name\n", m->name, m->mach_id);
100 m->mach_id = generic_fix_id("machine", "mach_id", "name",
101 m->mach_id, m->name);
107 printf("Subnet %s (%d) has duplicate name\n", s->name, s->snet_id);
114 printf("Cluster %s has duplicate ID %d\n", c->name, c->clu_id);
121 printf("Cluster %s (%d) has duplicate name\n", c->name, c->clu_id);
128 c->clu_id = generic_fix_id("cluster", "clu_id", "name", c->clu_id, c->name);
134 printf("List %s has duplicate ID %d\n", l->name, l->list_id);
141 printf("List %s (%d) has duplicate name\n", l->name, l->list_id);
148 l->list_id = generic_fix_id("list", "list_id", "name", l->list_id, l->name);
154 printf("Filesys %s has duplicate ID %d\n", f->name, f->filsys_id);
161 f->filsys_id = generic_fix_id("filesys", "filsys_id", "label",
162 f->filsys_id, f->name);
168 printf("Filesys %s (%d) has duplicate name\n", fs->name, fs->filsys_id);
176 printf("NfsPhys %s:%s has duplicate ID %d\n",
177 ((struct machine *)hash_lookup(machines, n->mach_id))->name,
178 n->dir, n->nfsphys_id);
185 n->nfsphys_id = generic_fix_id("nfsphys", "nfsphys_id", "dir",
186 n->nfsphys_id, n->dir);
192 printf("String %s has duplicate ID %d\n", s->name, s->string_id);
199 printf("String %d is a duplicate\n", id);
203 print_dup_map(key, data, hint)
208 printf("String %d is a duplicate of string %d\n", key, data);
214 EXEC SQL BEGIN DECLARE SECTION;
215 char name[81], name1[81], last[17], first[17], buf[257];
216 int id, id1, id2, id3, aid, aid2, status;
217 int sid, sid2, sid3, sid4, sid5;
218 EXEC SQL END DECLARE SECTION;
219 int i, q, retval, tmp;
220 struct save_queue *sq;
230 printf("Phase 1 - Looking for duplicates\n");
232 /* self-join strings table on "string" to get duplicate strings, then
233 build a duplicates table to merge them. */
235 dprintf("Looking for duplicate strings...\n");
236 string_dups = create_hash( 100 );
237 if(!string_dups) out_of_mem("storing duplicate strings");
239 EXEC SQL DECLARE csr116 CURSOR FOR
240 SELECT s1.string_id, s2.string_id FROM strings s1, strings s2
241 where s1.string = s2.string and s1.string_id < s2.string_id;
242 EXEC SQL OPEN csr116;
243 /* The SELECT gives us two columns, both with non-negative integers.
244 * The number in the left column is always the smaller of the two,
245 * and each row includes string IDs for identical strings. We use
246 * them to make a mapping from id-to-delete to id-to-keep for all
251 EXEC SQL FETCH csr116 INTO :id1, :id2;
252 if (sqlca.sqlcode != 0) break;
254 /* If id2 is already stored, skip this row. */
255 i = int_hash_lookup( string_dups, id2 );
256 if( i > 0 ) { continue; }
257 /* Follow the chain of id1 equivalent IDs back to the lowest one. */
259 while((tmp=int_hash_lookup(string_dups, id))>0)
261 int_hash_store( string_dups, id2, id );
263 EXEC SQL CLOSE csr116;
264 dprintf("found %d duplicates\n", q);
265 int_hash_step(string_dups, print_dup_map, NULL);
266 /* We don't want to delete the duplicates now because if the dbck
267 is cancelled, a LOT of state will be lost. So, we'll just let
268 them not get marked as used and then phase3 will clean them up */
270 dprintf("Loading strings...\n");
272 strings = create_hash(75000);
273 if(!sq || !strings) out_of_mem("loading strings");
275 EXEC SQL DECLARE csr101 CURSOR FOR
276 SELECT string_id, string FROM strings ORDER BY string_id;
277 EXEC SQL OPEN csr101;
280 EXEC SQL FETCH csr101 INTO :id, :buf;
281 if (sqlca.sqlcode != 0) break;
283 s = (struct string *) malloc(sizeof(struct string));
285 out_of_mem("storing strings");
286 s->name = strsave(strtrim(buf));
289 retval = hash_store(strings, id, s);
290 if ( retval == -1 ) {
291 out_of_mem("storing strings in hash table");
292 } else if ( retval == 1 ) { /* duplicate string_id*/
293 sq_save_data(sq, hash_lookup(strings, id));
297 EXEC SQL CLOSE csr101;
298 /* I'm not at all convinced this will work, so...
299 generic_delete(sq, show_str_id, "strings", "string_id", 0);
303 printf("Loaded %d strings\n", q);
305 dprintf("Loading users...\n");
307 users = create_hash(30000);
308 if(!sq || !users) out_of_mem("loading users");
310 EXEC SQL DECLARE csr102 CURSOR FOR
311 SELECT users_id, login, last, first, status, potype, pop_id, box_id,
312 modby, fmodby, pmodby, comments, sigwho FROM users
314 EXEC SQL OPEN csr102;
316 EXEC SQL FETCH csr102 INTO :id, :name, :last, :first, :status,
317 :buf, :id2, :id3, :sid, :sid2, :sid3, :sid4, :sid5;
318 if (sqlca.sqlcode != 0) break;
320 u = (struct user *) malloc(sizeof(struct user));
322 out_of_mem("storing users");
323 strcpy(u->login, strtrim(name));
325 sprintf(buf, "%s, %s", strtrim(last), strtrim(first));
326 u->fullname = strsave(buf);
339 /* If potype is SMTP, box_id is a string_id for the strings tbl */
345 retval = hash_store(users, id, u);
346 if ( retval == -1 ) {
347 out_of_mem("storing users in hash table");
348 } else if ( retval == 1 ) {
349 sq_save_data(sq, hash_lookup(users, id));
353 EXEC SQL CLOSE csr102;
355 generic_fix(sq, show_user_id, "Change ID", fix_user_id, 0);
359 if(!sq) out_of_mem("finding duplicate logins");
361 EXEC SQL DECLARE csr103 CURSOR FOR
362 SELECT u1.users_id FROM users u1, users u2
363 WHERE u1.login = u2.login and u1.rowid != u2.rowid;
364 EXEC SQL OPEN csr103;
366 EXEC SQL FETCH csr103 INTO :id;
367 if (sqlca.sqlcode != 0) break;
368 sq_save_data(sq, hash_lookup(users, id));
370 EXEC SQL CLOSE csr103;
371 handle_duplicate_logins(sq);
375 dprintf("Scanning krbmap...\n");
377 EXEC SQL DECLARE csr113 CURSOR FOR
378 SELECT k1.users_id FROM krbmap k1, krbmap k2
379 WHERE k1.users_id = k2.users_id AND k1.rowid != k2.rowid;
380 EXEC SQL OPEN csr113;
382 EXEC SQL FETCH csr113 INTO :id;
383 if (sqlca.sqlcode != 0) break;
385 printf("User %d is in the krbmap more than once!\n", id);
386 printf("Not fixing this error\n");
388 EXEC SQL CLOSE csr113;
390 EXEC SQL DECLARE csr114 CURSOR FOR
391 SELECT k1.string_id FROM krbmap k1, krbmap k2
392 WHERE k1.string_id = k2.string_id AND k1.rowid != k2.rowid;
393 EXEC SQL OPEN csr114;
395 EXEC SQL FETCH csr114 INTO :id;
396 if (sqlca.sqlcode != 0) break;
398 printf("Principal %d is in the krbmap more than once!\n", id);
399 printf("Not fixing this error\n");
401 EXEC SQL CLOSE csr114;
404 dprintf("Loading machines...\n");
406 machines = create_hash(20000);
407 if(!sq || !machines) out_of_mem("loading machines");
409 EXEC SQL DECLARE csr104 CURSOR FOR
410 SELECT mach_id, name, snet_id, owner_type, owner_id,
411 acomment, ocomment, creator, modby
412 FROM machine ORDER BY mach_id;
413 EXEC SQL OPEN csr104;
415 EXEC SQL FETCH csr104 INTO :id, :name, :id2, :buf, :id3, :sid2,
417 if (sqlca.sqlcode != 0) break;
419 m = (struct machine *) malloc(sizeof(struct machine));
421 out_of_mem("storing machines");
422 strcpy(m->name, strtrim(name));
423 m->owner_type = buf[0];
432 retval = hash_store(machines, id, m);
433 if ( retval == -1 ) {
434 out_of_mem("storing machines in hash table");
435 } else if ( retval == 1 ) {
436 sq_save_data(sq, hash_lookup(machines, id));
440 EXEC SQL CLOSE csr104;
441 generic_fix(sq, show_mach_id, "Change ID", fix_mach_id, 0);
445 if(!sq) out_of_mem("looking for duplicate machine names");
447 EXEC SQL DECLARE csr105 CURSOR FOR
448 SELECT m1.mach_id FROM machine m1, machine m2
449 WHERE m1.name = m2.name AND m1.rowid != m2.rowid;
450 EXEC SQL OPEN csr105;
452 EXEC SQL FETCH csr105 INTO :id;
453 if (sqlca.sqlcode != 0) break;
455 sq_save_data(sq, hash_lookup(machines, id));
457 EXEC SQL CLOSE csr105;
458 generic_fix(sq, show_mach_name, "Change name", cant_fix, 0);
460 EXEC SQL DECLARE csr_hal1 CURSOR FOR
461 SELECT h1.name, m1.mach_id, m2.mach_id
462 FROM hostalias h1, machine m1, hostalias h2, machine m2
463 WHERE h1.name=h2.name AND h1.mach_id!=h2.mach_id
464 AND m1.mach_id=h1.mach_id AND m2.mach_id=h2.mach_id;
465 EXEC SQL OPEN csr_hal1;
467 EXEC SQL FETCH csr_hal1 INTO :name, :id1, :id2;
468 if(sqlca.sqlcode!=0) break;
469 printf("Aliases for machines %d and %d have duplicate name %s\n",
470 id1, id2, strtrim(name));
473 EXEC SQL CLOSE csr_hal1;
475 EXEC SQL DECLARE csr_hal2 CURSOR FOR
476 SELECT h1.name, m1.mach_id, m2.mach_id
477 FROM hostalias h1, machine m1, machine m2
478 WHERE h1.name=m1.name AND h1.mach_id=m2.mach_id;
479 EXEC SQL OPEN csr_hal2;
481 EXEC SQL FETCH csr_hal2 INTO :name, :id1, :id2;
482 if(sqlca.sqlcode!=0) break;
483 printf("Machine %d has alias `%s' that conflicts with machine %d\n",
484 id2, strtrim(name), id1);
487 EXEC SQL CLOSE csr_hal2;
490 dprintf("Loading subnets...\n");
491 subnets = create_hash(254);
492 if(!subnets) out_of_mem("loading subnets");
494 EXEC SQL DECLARE csr115 CURSOR FOR
495 SELECT snet_id, name, owner_type, owner_id, modby from subnet;
496 EXEC SQL OPEN csr115;
498 EXEC SQL FETCH csr115 INTO :id, :name, :buf, :id2, :sid;
499 if (sqlca.sqlcode != 0) break;
501 sn = (struct subnet *) malloc(sizeof(struct machine));
503 out_of_mem("storing subnets");
504 strcpy(sn->name, strtrim(name));
505 sn->owner_type=buf[0];
509 retval = hash_store(subnets, id, sn);
510 if ( retval == -1 ) {
511 out_of_mem("storing subnets in hash table");
512 } else if ( retval == 1 ) {
513 printf("Duplicate subnet ID: %d (%s)\n", id, name);
514 /* should add code to delete */
517 EXEC SQL CLOSE csr115;
521 if(!sq) out_of_mem("looking for duplicate subnet names");
523 EXEC SQL DECLARE csr117 CURSOR FOR
524 SELECT s1.snet_id FROM subnet s1, subnet s2
525 WHERE s1.name = s2.name AND s1.rowid != s2.rowid;
526 EXEC SQL OPEN csr117;
528 EXEC SQL FETCH csr117 INTO :id;
529 if (sqlca.sqlcode != 0) break;
531 sq_save_data(sq, hash_lookup(subnets, id));
533 EXEC SQL CLOSE csr117;
534 generic_fix(sq, show_snet_name, "Change name", cant_fix, 0);
537 dprintf("Loading clusters...\n");
539 clusters = create_hash(100);
540 if(!sq || !clusters) out_of_mem("loading clusters");
542 EXEC SQL DECLARE csr106 CURSOR FOR
543 SELECT clu_id, name, modby FROM clusters;
544 EXEC SQL OPEN csr106;
546 EXEC SQL FETCH csr106 INTO :id, :name, :sid;
547 if (sqlca.sqlcode != 0) break;
549 c = (struct cluster *) malloc(sizeof(struct cluster));
551 out_of_mem("storing clusters");
552 strcpy(c->name, strtrim(name));
555 retval = hash_store(clusters, id, c);
556 if ( retval == -1 ) {
557 out_of_mem("storing clusters in hash table");
558 } else if ( retval == 1 ) {
559 sq_save_data(sq, hash_lookup(clusters, id));
563 EXEC SQL CLOSE csr106;
564 generic_fix(sq, show_clu_id, "Change ID", fix_clu_id, 0);
568 if(!sq) out_of_mem("looking for duplicate cluster names");
570 EXEC SQL DECLARE csr107 CURSOR FOR
571 SELECT c1.clu_id FROM clusters c1, clusters c2
572 WHERE c1.name=c2.name AND c1.rowid != c2.rowid;
573 EXEC SQL OPEN csr107;
575 EXEC SQL FETCH csr107 INTO :id;
576 if (sqlca.sqlcode != 0) break;
578 sq_save_data(sq, hash_lookup(clusters, id));
580 EXEC SQL CLOSE csr107;
581 generic_fix(sq, show_clu_name, "Change name", cant_fix, 0);
584 dprintf("Loading lists...\n");
586 lists = create_hash(50000);
587 if(!sq || !lists) out_of_mem("loading lists");
589 EXEC SQL DECLARE csr108 CURSOR FOR
590 SELECT list_id, name, acl_id, acl_type, modby FROM list
592 EXEC SQL OPEN csr108;
594 EXEC SQL FETCH csr108 INTO :id, :name, :aid, :buf, :sid;
595 if (sqlca.sqlcode != 0) break;
596 l = (struct list *) malloc(sizeof(struct list));
598 out_of_mem("storing lists");
599 strcpy(l->name, strtrim(name));
600 l->acl_type = buf[0];
604 retval = hash_store(lists, id, l);
605 if ( retval == -1 ) {
606 out_of_mem("storing lists in hash table");
607 } else if ( retval == 1 ) {
608 sq_save_data(sq, hash_lookup(lists, id));
612 EXEC SQL CLOSE csr108;
613 generic_fix(sq, show_list_id, "Change ID", fix_list_id, 0);
617 if(!sq) out_of_mem("looking for duplicate list names");
619 EXEC SQL DECLARE csr109 CURSOR FOR
620 SELECT l1.list_id FROM list l1, list l2
621 WHERE l1.name=l2.name AND l1.rowid != l2.rowid;
622 EXEC SQL OPEN csr109;
624 EXEC SQL FETCH csr109 INTO :id;
625 if (sqlca.sqlcode != 0) break;
627 sq_save_data(sq, hash_lookup(lists, id));
629 EXEC SQL CLOSE csr109;
630 generic_fix(sq, show_list_name, "Change name", cant_fix, 0);
633 dprintf("Loading filesys...\n");
635 filesys = create_hash(30000);
636 if(!sq || !filesys) out_of_mem("loading filesys");
638 EXEC SQL DECLARE csr110 CURSOR FOR
639 SELECT filsys_id, label, owner, owners, phys_id, mach_id,
640 type, name, modby FROM filesys ORDER BY filsys_id;
641 EXEC SQL OPEN csr110;
643 EXEC SQL FETCH csr110 INTO :id, :name, :aid, :aid2, :id2, :id3,
645 if (sqlca.sqlcode != 0) break;
647 f = (struct filesys *) malloc(sizeof(struct filesys));
649 out_of_mem("storing filesystems");
650 strcpy(f->name, strtrim(name));
651 strcpy(f->dir, strtrim(name1));
658 retval = hash_store(filesys, id, f);
659 if ( retval == -1 ) {
660 out_of_mem("storing filesys in hash table");
661 } else if ( retval == 1 ) {
662 sq_save_data(sq, hash_lookup(filesys, id));
666 EXEC SQL CLOSE csr110;
668 generic_fix(sq, show_fs_id, "Change ID", fix_fs_id, 0);
672 if(!sq) out_of_mem("looking for duplicate filesys names");
674 EXEC SQL DECLARE csr118 CURSOR FOR
675 SELECT fs1.filsys_id FROM filesys fs1, filesys fs2
676 WHERE fs1.label=fs2.label AND fs1.rowid != fs2.rowid;
677 EXEC SQL OPEN csr118;
679 EXEC SQL FETCH csr118 INTO :id;
680 if (sqlca.sqlcode != 0) break;
682 sq_save_data(sq, hash_lookup(filesys, id));
684 EXEC SQL CLOSE csr118;
685 generic_fix(sq, show_fs_name, "Change name", cant_fix, 0);
688 dprintf("Loading nfsphys...\n");
690 nfsphys = create_hash(500);
691 if(!sq || !nfsphys) out_of_mem("loading nfsphs");
693 EXEC SQL DECLARE csr111 CURSOR FOR
694 SELECT nfsphys_id, dir, mach_id, allocated, modby FROM nfsphys;
695 EXEC SQL OPEN csr111;
697 EXEC SQL FETCH csr111 INTO :id, :name, :id2, :id3, :sid;
698 if (sqlca.sqlcode != 0) break;
700 n = (struct nfsphys *) malloc(sizeof(struct nfsphys));
702 out_of_mem("storing nfsphys");
703 strcpy(n->dir, strtrim(name));
708 retval = hash_store(nfsphys, id, n);
709 if ( retval == -1 ) {
710 out_of_mem("storing nfsphys in hash table");
711 } else if ( retval == 1 ) {
712 sq_save_data(sq, hash_lookup(nfsphys, id));
716 EXEC SQL CLOSE csr111;
718 generic_fix(sq, show_np_id, "Change ID", fix_np_id, 0);
720 dprintf("Checking printcap...\n");
722 EXEC SQL DECLARE csr119 CURSOR FOR
723 SELECT p1.name FROM printcap p1, printcap p2
724 WHERE p1.name=p2.name AND p1.rowid<p2.rowid;
725 EXEC SQL OPEN csr119;
727 EXEC SQL FETCH csr119 INTO :name;
728 if (sqlca.sqlcode != 0) break;
730 printf("Printer %s has duplicate name\n", name);
733 EXEC SQL CLOSE csr119;