1*b9fc9a72Sderaadt /* $OpenBSD: pass5.c,v 1.18 2015/01/16 06:39:57 deraadt Exp $ */
20190393fSart /* $NetBSD: pass5.c,v 1.7 2000/01/28 16:01:46 bouyer Exp $ */
38c424e8eSdownsj
48c424e8eSdownsj /*
55ff4e0c8Sdownsj * Copyright (c) 1997 Manuel Bouyer.
68c424e8eSdownsj * Copyright (c) 1980, 1986, 1993
78c424e8eSdownsj * The Regents of the University of California. All rights reserved.
88c424e8eSdownsj *
98c424e8eSdownsj * Redistribution and use in source and binary forms, with or without
108c424e8eSdownsj * modification, are permitted provided that the following conditions
118c424e8eSdownsj * are met:
128c424e8eSdownsj * 1. Redistributions of source code must retain the above copyright
138c424e8eSdownsj * notice, this list of conditions and the following disclaimer.
148c424e8eSdownsj * 2. Redistributions in binary form must reproduce the above copyright
158c424e8eSdownsj * notice, this list of conditions and the following disclaimer in the
168c424e8eSdownsj * documentation and/or other materials provided with the distribution.
171ef0d710Smillert * 3. Neither the name of the University nor the names of its contributors
188c424e8eSdownsj * may be used to endorse or promote products derived from this software
198c424e8eSdownsj * without specific prior written permission.
208c424e8eSdownsj *
218c424e8eSdownsj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228c424e8eSdownsj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238c424e8eSdownsj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248c424e8eSdownsj * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258c424e8eSdownsj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268c424e8eSdownsj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278c424e8eSdownsj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288c424e8eSdownsj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298c424e8eSdownsj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308c424e8eSdownsj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318c424e8eSdownsj * SUCH DAMAGE.
328c424e8eSdownsj */
338c424e8eSdownsj
34*b9fc9a72Sderaadt #include <sys/param.h> /* setbit isset */
358c424e8eSdownsj #include <sys/time.h>
368a68c314Sderaadt #include <ufs/ufs/dinode.h>
378c424e8eSdownsj #include <ufs/ext2fs/ext2fs_dinode.h>
388c424e8eSdownsj #include <ufs/ext2fs/ext2fs.h>
398c424e8eSdownsj #include <string.h>
408c424e8eSdownsj #include <stdio.h>
41ce18c919Sdownsj #include <stdlib.h>
428c424e8eSdownsj
438c424e8eSdownsj #include "fsutil.h"
448c424e8eSdownsj #include "fsck.h"
458c424e8eSdownsj #include "extern.h"
468c424e8eSdownsj
478c424e8eSdownsj
48c72b5b24Smillert void print_bmap(u_char *,u_int32_t);
498c424e8eSdownsj
508c424e8eSdownsj void
pass5(void)518809fabbSderaadt pass5(void)
528c424e8eSdownsj {
5365348f21Sjasoni int c;
540190393fSart struct m_ext2fs *fs = &sblock;
55b6d2e2d5Sderaadt daddr32_t dbase, dmax;
56b6d2e2d5Sderaadt daddr32_t d;
570190393fSart long i, j;
588c424e8eSdownsj struct inodesc idesc[3];
598c424e8eSdownsj struct bufarea *ino_bitmap = NULL, *blk_bitmap = NULL;
608c424e8eSdownsj char *ibmap, *bbmap;
618c424e8eSdownsj u_int32_t cs_ndir, cs_nbfree, cs_nifree;
628c424e8eSdownsj char msg[255];
638c424e8eSdownsj
648c424e8eSdownsj cs_ndir = 0;
658c424e8eSdownsj cs_nbfree = 0;
668c424e8eSdownsj cs_nifree = 0;
678c424e8eSdownsj
688c424e8eSdownsj ibmap = malloc(fs->e2fs_bsize);
698c424e8eSdownsj bbmap = malloc(fs->e2fs_bsize);
708c424e8eSdownsj if (ibmap == NULL || bbmap == NULL) {
718c424e8eSdownsj errexit("out of memory\n");
728c424e8eSdownsj }
738c424e8eSdownsj
748c424e8eSdownsj for (c = 0; c < fs->e2fs_ncg; c++) {
758c424e8eSdownsj u_int32_t nbfree = 0;
768c424e8eSdownsj u_int32_t nifree = 0;
778c424e8eSdownsj u_int32_t ndirs = 0;
788c424e8eSdownsj
798c424e8eSdownsj nbfree = 0;
808c424e8eSdownsj nifree = fs->e2fs.e2fs_ipg;
818c424e8eSdownsj ndirs = 0;
828c424e8eSdownsj
838c424e8eSdownsj if (blk_bitmap == NULL) {
8460a51e06Spelikan blk_bitmap = getdatablk(letoh32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
858c424e8eSdownsj fs->e2fs_bsize);
868c424e8eSdownsj } else {
8760a51e06Spelikan getblk(blk_bitmap, letoh32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
888c424e8eSdownsj fs->e2fs_bsize);
898c424e8eSdownsj }
908c424e8eSdownsj if (ino_bitmap == NULL) {
9160a51e06Spelikan ino_bitmap = getdatablk(letoh32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
928c424e8eSdownsj fs->e2fs_bsize);
938c424e8eSdownsj } else {
9460a51e06Spelikan getblk(ino_bitmap, letoh32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
958c424e8eSdownsj fs->e2fs_bsize);
968c424e8eSdownsj }
978c424e8eSdownsj memset(bbmap, 0, fs->e2fs_bsize);
988c424e8eSdownsj memset(ibmap, 0, fs->e2fs_bsize);
998c424e8eSdownsj memset(&idesc[0], 0, sizeof idesc);
1008c424e8eSdownsj for (i = 0; i < 3; i++) {
1018c424e8eSdownsj idesc[i].id_type = ADDR;
1028c424e8eSdownsj }
1038c424e8eSdownsj
1048c424e8eSdownsj j = fs->e2fs.e2fs_ipg * c + 1;
1058c424e8eSdownsj
1068c424e8eSdownsj for (i = 0; i < fs->e2fs.e2fs_ipg; j++, i++) {
1078c424e8eSdownsj if ((j < EXT2_FIRSTINO) && (j != EXT2_ROOTINO)) {
1088c424e8eSdownsj setbit(ibmap, i);
1098c424e8eSdownsj nifree--;
1108c424e8eSdownsj continue;
1118c424e8eSdownsj }
1128c424e8eSdownsj if (j > fs->e2fs.e2fs_icount) {
1138c424e8eSdownsj setbit(ibmap, i);
1148c424e8eSdownsj continue;
1158c424e8eSdownsj }
1168c424e8eSdownsj switch (statemap[j]) {
1178c424e8eSdownsj
1188c424e8eSdownsj case USTATE:
1198c424e8eSdownsj break;
1208c424e8eSdownsj
1218c424e8eSdownsj case DSTATE:
1228c424e8eSdownsj case DCLEAR:
1238c424e8eSdownsj case DFOUND:
1248c424e8eSdownsj ndirs++;
1258c424e8eSdownsj /* fall through */
1268c424e8eSdownsj
1278c424e8eSdownsj case FSTATE:
1288c424e8eSdownsj case FCLEAR:
1298c424e8eSdownsj nifree--;
1308c424e8eSdownsj setbit(ibmap, i);
1318c424e8eSdownsj break;
1328c424e8eSdownsj
1338c424e8eSdownsj default:
1343b92bd08Sderaadt errexit("BAD STATE %d FOR INODE I=%llu\n",
1353b92bd08Sderaadt statemap[j], (unsigned long long)j);
1368c424e8eSdownsj }
1378c424e8eSdownsj }
1388c424e8eSdownsj
1398c424e8eSdownsj /* fill in unused par of the inode map */
1408c424e8eSdownsj for (i = fs->e2fs.e2fs_ipg / NBBY; i < fs->e2fs_bsize; i++)
1418c424e8eSdownsj ibmap[i] = 0xff;
1428c424e8eSdownsj
14365348f21Sjasoni dbase = c * sblock.e2fs.e2fs_bpg +
14465348f21Sjasoni sblock.e2fs.e2fs_first_dblock;
14565348f21Sjasoni dmax = (c+1) * sblock.e2fs.e2fs_bpg +
14665348f21Sjasoni sblock.e2fs.e2fs_first_dblock;
1478c424e8eSdownsj
14865348f21Sjasoni for (i = 0, d = dbase;
1498c424e8eSdownsj d < dmax;
1508c424e8eSdownsj d ++, i ++) {
1518c424e8eSdownsj if (testbmap(d) || d >= sblock.e2fs.e2fs_bcount) {
1528c424e8eSdownsj setbit(bbmap, i);
1538c424e8eSdownsj continue;
1548c424e8eSdownsj } else {
1558c424e8eSdownsj nbfree++;
1568c424e8eSdownsj }
1578c424e8eSdownsj
1588c424e8eSdownsj }
1598c424e8eSdownsj cs_nbfree += nbfree;
1608c424e8eSdownsj cs_nifree += nifree;
1618c424e8eSdownsj cs_ndir += ndirs;
1628c424e8eSdownsj
16360a51e06Spelikan if (debug && (letoh16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
16460a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
16560a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs)) {
1668c424e8eSdownsj printf("summary info for cg %d is %d, %d, %d,"
1678c424e8eSdownsj "should be %d, %d, %d\n", c,
16860a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_nbfree),
16960a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_nifree),
17060a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_ndirs),
1718c424e8eSdownsj nbfree,
1728c424e8eSdownsj nifree,
1738c424e8eSdownsj ndirs);
1748c424e8eSdownsj }
17565348f21Sjasoni (void)snprintf(msg, sizeof(msg),
17665348f21Sjasoni "SUMMARY INFORMATIONS WRONG FOR CG #%d", c);
17760a51e06Spelikan if ((letoh16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
17860a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
17960a51e06Spelikan letoh16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs) &&
1808c424e8eSdownsj dofix(&idesc[0], msg)) {
18160a51e06Spelikan fs->e2fs_gd[c].ext2bgd_nbfree = htole16(nbfree);
18260a51e06Spelikan fs->e2fs_gd[c].ext2bgd_nifree = htole16(nifree);
18360a51e06Spelikan fs->e2fs_gd[c].ext2bgd_ndirs = htole16(ndirs);
1848c424e8eSdownsj sbdirty();
1858c424e8eSdownsj }
1868c424e8eSdownsj
1878c424e8eSdownsj if (debug && memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize)) {
1888c424e8eSdownsj printf("blk_bitmap:\n");
1898c424e8eSdownsj print_bmap(blk_bitmap->b_un.b_buf, fs->e2fs_bsize);
1908c424e8eSdownsj printf("bbmap:\n");
1918c424e8eSdownsj print_bmap(bbmap, fs->e2fs_bsize);
1928c424e8eSdownsj }
1938c424e8eSdownsj
19465348f21Sjasoni (void)snprintf(msg, sizeof(msg),
19565348f21Sjasoni "BLK(S) MISSING IN BIT MAPS #%d", c);
1968c424e8eSdownsj if (memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize) &&
1978c424e8eSdownsj dofix(&idesc[1], msg)) {
1988c424e8eSdownsj memcpy(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize);
1998c424e8eSdownsj dirty(blk_bitmap);
2008c424e8eSdownsj }
2018c424e8eSdownsj if (debug && memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize)) {
2028c424e8eSdownsj printf("ino_bitmap:\n");
2038c424e8eSdownsj print_bmap(ino_bitmap->b_un.b_buf, fs->e2fs_bsize);
2048c424e8eSdownsj printf("ibmap:\n");
2058c424e8eSdownsj print_bmap(ibmap, fs->e2fs_bsize);
2068c424e8eSdownsj }
20765348f21Sjasoni (void)snprintf(msg, sizeof(msg),
20865348f21Sjasoni "INODE(S) MISSING IN BIT MAPS #%d", c);
2098c424e8eSdownsj if (memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize) &&
2108c424e8eSdownsj dofix(&idesc[1], msg)) {
2118c424e8eSdownsj memcpy(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize);
2128c424e8eSdownsj dirty(ino_bitmap);
2138c424e8eSdownsj }
2148c424e8eSdownsj
2158c424e8eSdownsj }
2168c424e8eSdownsj if (debug && (fs->e2fs.e2fs_fbcount != cs_nbfree ||
2178c424e8eSdownsj fs->e2fs.e2fs_ficount != cs_nifree)) {
2188c424e8eSdownsj printf("summary info bad in superblock: %d, %d should be %d, %d\n",
2198c424e8eSdownsj fs->e2fs.e2fs_fbcount, fs->e2fs.e2fs_ficount,
2208c424e8eSdownsj cs_nbfree, cs_nifree);
2218c424e8eSdownsj }
2228c424e8eSdownsj if ((fs->e2fs.e2fs_fbcount != cs_nbfree ||
2238c424e8eSdownsj fs->e2fs.e2fs_ficount != cs_nifree)
2248c424e8eSdownsj && dofix(&idesc[0], "SUPERBLK SUMMARY INFORMATION BAD")) {
2258c424e8eSdownsj fs->e2fs.e2fs_fbcount = cs_nbfree;
2268c424e8eSdownsj fs->e2fs.e2fs_ficount = cs_nifree;
2278c424e8eSdownsj sbdirty();
2288c424e8eSdownsj }
2295e12154eSdhill free(ibmap);
2305e12154eSdhill free(bbmap);
2318c424e8eSdownsj }
2328c424e8eSdownsj
2338c424e8eSdownsj void
print_bmap(u_char * map,u_int32_t size)2348809fabbSderaadt print_bmap(u_char *map, u_int32_t size)
2358c424e8eSdownsj {
2368c424e8eSdownsj int i, j;
2378c424e8eSdownsj
2388c424e8eSdownsj i = 0;
2398c424e8eSdownsj while (i < size) {
2408c424e8eSdownsj printf("%u: ",i);
2418c424e8eSdownsj for (j = 0; j < 16; j++, i++)
2422e7e8d8bSderaadt printf("%2x ", (u_int)map[i] & 0xff);
2438c424e8eSdownsj printf("\n");
2448c424e8eSdownsj }
2458c424e8eSdownsj }
246