1  | 
     | 
     | 
    /*	$OpenBSD: pass5.c,v 1.18 2015/01/16 06:39:57 deraadt Exp $	*/  | 
    
    
    2  | 
     | 
     | 
    /*	$NetBSD: pass5.c,v 1.7 2000/01/28 16:01:46 bouyer Exp $ */  | 
    
    
    3  | 
     | 
     | 
     | 
    
    
    4  | 
     | 
     | 
    /*  | 
    
    
    5  | 
     | 
     | 
     * Copyright (c) 1997 Manuel Bouyer.  | 
    
    
    6  | 
     | 
     | 
     * Copyright (c) 1980, 1986, 1993  | 
    
    
    7  | 
     | 
     | 
     *	The Regents of the University of California.  All rights reserved.  | 
    
    
    8  | 
     | 
     | 
     *  | 
    
    
    9  | 
     | 
     | 
     * Redistribution and use in source and binary forms, with or without  | 
    
    
    10  | 
     | 
     | 
     * modification, are permitted provided that the following conditions  | 
    
    
    11  | 
     | 
     | 
     * are met:  | 
    
    
    12  | 
     | 
     | 
     * 1. Redistributions of source code must retain the above copyright  | 
    
    
    13  | 
     | 
     | 
     *    notice, this list of conditions and the following disclaimer.  | 
    
    
    14  | 
     | 
     | 
     * 2. Redistributions in binary form must reproduce the above copyright  | 
    
    
    15  | 
     | 
     | 
     *    notice, this list of conditions and the following disclaimer in the  | 
    
    
    16  | 
     | 
     | 
     *    documentation and/or other materials provided with the distribution.  | 
    
    
    17  | 
     | 
     | 
     * 3. Neither the name of the University nor the names of its contributors  | 
    
    
    18  | 
     | 
     | 
     *    may be used to endorse or promote products derived from this software  | 
    
    
    19  | 
     | 
     | 
     *    without specific prior written permission.  | 
    
    
    20  | 
     | 
     | 
     *  | 
    
    
    21  | 
     | 
     | 
     * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND  | 
    
    
    22  | 
     | 
     | 
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  | 
    
    
    23  | 
     | 
     | 
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  | 
    
    
    24  | 
     | 
     | 
     * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE  | 
    
    
    25  | 
     | 
     | 
     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  | 
    
    
    26  | 
     | 
     | 
     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  | 
    
    
    27  | 
     | 
     | 
     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  | 
    
    
    28  | 
     | 
     | 
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  | 
    
    
    29  | 
     | 
     | 
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  | 
    
    
    30  | 
     | 
     | 
     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  | 
    
    
    31  | 
     | 
     | 
     * SUCH DAMAGE.  | 
    
    
    32  | 
     | 
     | 
     */  | 
    
    
    33  | 
     | 
     | 
     | 
    
    
    34  | 
     | 
     | 
    #include <sys/param.h>	/* setbit isset */  | 
    
    
    35  | 
     | 
     | 
    #include <sys/time.h>  | 
    
    
    36  | 
     | 
     | 
    #include <ufs/ufs/dinode.h>  | 
    
    
    37  | 
     | 
     | 
    #include <ufs/ext2fs/ext2fs_dinode.h>  | 
    
    
    38  | 
     | 
     | 
    #include <ufs/ext2fs/ext2fs.h>  | 
    
    
    39  | 
     | 
     | 
    #include <string.h>  | 
    
    
    40  | 
     | 
     | 
    #include <stdio.h>  | 
    
    
    41  | 
     | 
     | 
    #include <stdlib.h>  | 
    
    
    42  | 
     | 
     | 
     | 
    
    
    43  | 
     | 
     | 
    #include "fsutil.h"  | 
    
    
    44  | 
     | 
     | 
    #include "fsck.h"  | 
    
    
    45  | 
     | 
     | 
    #include "extern.h"  | 
    
    
    46  | 
     | 
     | 
     | 
    
    
    47  | 
     | 
     | 
     | 
    
    
    48  | 
     | 
     | 
    void print_bmap(u_char *,u_int32_t);  | 
    
    
    49  | 
     | 
     | 
     | 
    
    
    50  | 
     | 
     | 
    void  | 
    
    
    51  | 
     | 
     | 
    pass5(void)  | 
    
    
    52  | 
     | 
     | 
    { | 
    
    
    53  | 
     | 
     | 
    	int c;  | 
    
    
    54  | 
     | 
     | 
    	struct m_ext2fs *fs = &sblock;  | 
    
    
    55  | 
     | 
     | 
    	daddr32_t dbase, dmax;  | 
    
    
    56  | 
     | 
     | 
    	daddr32_t d;  | 
    
    
    57  | 
     | 
     | 
    	long i, j;  | 
    
    
    58  | 
     | 
     | 
    	struct inodesc idesc[3];  | 
    
    
    59  | 
     | 
     | 
    	struct bufarea *ino_bitmap = NULL, *blk_bitmap = NULL;  | 
    
    
    60  | 
     | 
     | 
    	char *ibmap, *bbmap;  | 
    
    
    61  | 
     | 
     | 
    	u_int32_t cs_ndir, cs_nbfree, cs_nifree;  | 
    
    
    62  | 
     | 
     | 
    	char msg[255];  | 
    
    
    63  | 
     | 
     | 
     | 
    
    
    64  | 
     | 
     | 
    	cs_ndir = 0;  | 
    
    
    65  | 
     | 
     | 
    	cs_nbfree = 0;  | 
    
    
    66  | 
     | 
     | 
    	cs_nifree = 0;  | 
    
    
    67  | 
     | 
     | 
     | 
    
    
    68  | 
     | 
     | 
    	ibmap = malloc(fs->e2fs_bsize);  | 
    
    
    69  | 
     | 
     | 
    	bbmap = malloc(fs->e2fs_bsize);  | 
    
    
    70  | 
     | 
     | 
    	if (ibmap == NULL || bbmap == NULL) { | 
    
    
    71  | 
     | 
     | 
    		errexit("out of memory\n"); | 
    
    
    72  | 
     | 
     | 
    	}  | 
    
    
    73  | 
     | 
     | 
     | 
    
    
    74  | 
     | 
     | 
    	for (c = 0; c < fs->e2fs_ncg; c++) { | 
    
    
    75  | 
     | 
     | 
    		u_int32_t nbfree = 0;  | 
    
    
    76  | 
     | 
     | 
    		u_int32_t nifree = 0;  | 
    
    
    77  | 
     | 
     | 
    		u_int32_t ndirs = 0;  | 
    
    
    78  | 
     | 
     | 
     | 
    
    
    79  | 
     | 
     | 
    		nbfree = 0;  | 
    
    
    80  | 
     | 
     | 
    		nifree = fs->e2fs.e2fs_ipg;  | 
    
    
    81  | 
     | 
     | 
    		ndirs = 0;  | 
    
    
    82  | 
     | 
     | 
     | 
    
    
    83  | 
     | 
     | 
    		if (blk_bitmap == NULL) { | 
    
    
    84  | 
     | 
     | 
    			blk_bitmap = getdatablk(letoh32(fs->e2fs_gd[c].ext2bgd_b_bitmap),  | 
    
    
    85  | 
     | 
     | 
    				fs->e2fs_bsize);  | 
    
    
    86  | 
     | 
     | 
    		} else { | 
    
    
    87  | 
     | 
     | 
    			getblk(blk_bitmap, letoh32(fs->e2fs_gd[c].ext2bgd_b_bitmap),  | 
    
    
    88  | 
     | 
     | 
    				fs->e2fs_bsize);  | 
    
    
    89  | 
     | 
     | 
    		}  | 
    
    
    90  | 
     | 
     | 
    		if (ino_bitmap == NULL) { | 
    
    
    91  | 
     | 
     | 
    			ino_bitmap = getdatablk(letoh32(fs->e2fs_gd[c].ext2bgd_i_bitmap),  | 
    
    
    92  | 
     | 
     | 
    				fs->e2fs_bsize);  | 
    
    
    93  | 
     | 
     | 
    		} else { | 
    
    
    94  | 
     | 
     | 
    			getblk(ino_bitmap, letoh32(fs->e2fs_gd[c].ext2bgd_i_bitmap),  | 
    
    
    95  | 
     | 
     | 
    				fs->e2fs_bsize);  | 
    
    
    96  | 
     | 
     | 
    		}  | 
    
    
    97  | 
     | 
     | 
    		memset(bbmap, 0, fs->e2fs_bsize);  | 
    
    
    98  | 
     | 
     | 
    		memset(ibmap, 0, fs->e2fs_bsize);  | 
    
    
    99  | 
     | 
     | 
    		memset(&idesc[0], 0, sizeof idesc);  | 
    
    
    100  | 
     | 
     | 
    		for (i = 0; i < 3; i++) { | 
    
    
    101  | 
     | 
     | 
    			idesc[i].id_type = ADDR;  | 
    
    
    102  | 
     | 
     | 
    		}  | 
    
    
    103  | 
     | 
     | 
     | 
    
    
    104  | 
     | 
     | 
    		j = fs->e2fs.e2fs_ipg * c + 1;  | 
    
    
    105  | 
     | 
     | 
     | 
    
    
    106  | 
     | 
     | 
    		for (i = 0; i < fs->e2fs.e2fs_ipg; j++, i++) { | 
    
    
    107  | 
     | 
     | 
    			if ((j < EXT2_FIRSTINO) && (j != EXT2_ROOTINO)) { | 
    
    
    108  | 
     | 
     | 
    				setbit(ibmap, i);  | 
    
    
    109  | 
     | 
     | 
    				nifree--;  | 
    
    
    110  | 
     | 
     | 
    				continue;  | 
    
    
    111  | 
     | 
     | 
    			}  | 
    
    
    112  | 
     | 
     | 
    			if (j > fs->e2fs.e2fs_icount) { | 
    
    
    113  | 
     | 
     | 
    				setbit(ibmap, i);  | 
    
    
    114  | 
     | 
     | 
    				continue;  | 
    
    
    115  | 
     | 
     | 
    			}  | 
    
    
    116  | 
     | 
     | 
    			switch (statemap[j]) { | 
    
    
    117  | 
     | 
     | 
     | 
    
    
    118  | 
     | 
     | 
    			case USTATE:  | 
    
    
    119  | 
     | 
     | 
    				break;  | 
    
    
    120  | 
     | 
     | 
     | 
    
    
    121  | 
     | 
     | 
    			case DSTATE:  | 
    
    
    122  | 
     | 
     | 
    			case DCLEAR:  | 
    
    
    123  | 
     | 
     | 
    			case DFOUND:  | 
    
    
    124  | 
     | 
     | 
    				ndirs++;  | 
    
    
    125  | 
     | 
     | 
    				/* fall through */  | 
    
    
    126  | 
     | 
     | 
     | 
    
    
    127  | 
     | 
     | 
    			case FSTATE:  | 
    
    
    128  | 
     | 
     | 
    			case FCLEAR:  | 
    
    
    129  | 
     | 
     | 
    				nifree--;  | 
    
    
    130  | 
     | 
     | 
    				setbit(ibmap, i);  | 
    
    
    131  | 
     | 
     | 
    				break;  | 
    
    
    132  | 
     | 
     | 
     | 
    
    
    133  | 
     | 
     | 
    			default:  | 
    
    
    134  | 
     | 
     | 
    				errexit("BAD STATE %d FOR INODE I=%llu\n", | 
    
    
    135  | 
     | 
     | 
    				    statemap[j], (unsigned long long)j);  | 
    
    
    136  | 
     | 
     | 
    			}  | 
    
    
    137  | 
     | 
     | 
    		}  | 
    
    
    138  | 
     | 
     | 
     | 
    
    
    139  | 
     | 
     | 
    		/* fill in unused par of the inode map */  | 
    
    
    140  | 
     | 
     | 
    		for (i = fs->e2fs.e2fs_ipg / NBBY; i < fs->e2fs_bsize; i++)  | 
    
    
    141  | 
     | 
     | 
    			ibmap[i] = 0xff;  | 
    
    
    142  | 
     | 
     | 
     | 
    
    
    143  | 
     | 
     | 
    		dbase = c * sblock.e2fs.e2fs_bpg +  | 
    
    
    144  | 
     | 
     | 
    		    sblock.e2fs.e2fs_first_dblock;  | 
    
    
    145  | 
     | 
     | 
    		dmax = (c+1) * sblock.e2fs.e2fs_bpg +  | 
    
    
    146  | 
     | 
     | 
    		    sblock.e2fs.e2fs_first_dblock;  | 
    
    
    147  | 
     | 
     | 
     | 
    
    
    148  | 
     | 
     | 
    		for (i = 0, d = dbase;  | 
    
    
    149  | 
     | 
     | 
    		     d < dmax;  | 
    
    
    150  | 
     | 
     | 
    		     d ++, i ++) { | 
    
    
    151  | 
     | 
     | 
    			if (testbmap(d) || d >= sblock.e2fs.e2fs_bcount) { | 
    
    
    152  | 
     | 
     | 
    				setbit(bbmap, i);  | 
    
    
    153  | 
     | 
     | 
    				continue;  | 
    
    
    154  | 
     | 
     | 
    			} else { | 
    
    
    155  | 
     | 
     | 
    				nbfree++;  | 
    
    
    156  | 
     | 
     | 
    			}  | 
    
    
    157  | 
     | 
     | 
     | 
    
    
    158  | 
     | 
     | 
    		}  | 
    
    
    159  | 
     | 
     | 
    		cs_nbfree += nbfree;  | 
    
    
    160  | 
     | 
     | 
    		cs_nifree += nifree;  | 
    
    
    161  | 
     | 
     | 
    		cs_ndir += ndirs;  | 
    
    
    162  | 
     | 
     | 
     | 
    
    
    163  | 
     | 
     | 
    		if (debug && (letoh16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||  | 
    
    
    164  | 
     | 
     | 
    		    letoh16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||  | 
    
    
    165  | 
     | 
     | 
    		    letoh16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs)) { | 
    
    
    166  | 
     | 
     | 
    			printf("summary info for cg %d is %d, %d, %d," | 
    
    
    167  | 
     | 
     | 
    					"should be %d, %d, %d\n", c,  | 
    
    
    168  | 
     | 
     | 
    					letoh16(fs->e2fs_gd[c].ext2bgd_nbfree),  | 
    
    
    169  | 
     | 
     | 
    					letoh16(fs->e2fs_gd[c].ext2bgd_nifree),  | 
    
    
    170  | 
     | 
     | 
    					letoh16(fs->e2fs_gd[c].ext2bgd_ndirs),  | 
    
    
    171  | 
     | 
     | 
    					nbfree,  | 
    
    
    172  | 
     | 
     | 
    					nifree,  | 
    
    
    173  | 
     | 
     | 
    					ndirs);  | 
    
    
    174  | 
     | 
     | 
    		}  | 
    
    
    175  | 
     | 
     | 
    		(void)snprintf(msg, sizeof(msg),  | 
    
    
    176  | 
     | 
     | 
    		    "SUMMARY INFORMATIONS WRONG FOR CG #%d", c);  | 
    
    
    177  | 
     | 
     | 
    		if ((letoh16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||  | 
    
    
    178  | 
     | 
     | 
    			letoh16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||  | 
    
    
    179  | 
     | 
     | 
    			letoh16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs) &&  | 
    
    
    180  | 
     | 
     | 
    			dofix(&idesc[0], msg)) { | 
    
    
    181  | 
     | 
     | 
    			fs->e2fs_gd[c].ext2bgd_nbfree = htole16(nbfree);  | 
    
    
    182  | 
     | 
     | 
    			fs->e2fs_gd[c].ext2bgd_nifree = htole16(nifree);  | 
    
    
    183  | 
     | 
     | 
    			fs->e2fs_gd[c].ext2bgd_ndirs = htole16(ndirs);  | 
    
    
    184  | 
     | 
     | 
    			sbdirty();  | 
    
    
    185  | 
     | 
     | 
    		}  | 
    
    
    186  | 
     | 
     | 
     | 
    
    
    187  | 
     | 
     | 
    		if (debug && memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize)) { | 
    
    
    188  | 
     | 
     | 
    			printf("blk_bitmap:\n"); | 
    
    
    189  | 
     | 
     | 
    			print_bmap(blk_bitmap->b_un.b_buf, fs->e2fs_bsize);  | 
    
    
    190  | 
     | 
     | 
    			printf("bbmap:\n"); | 
    
    
    191  | 
     | 
     | 
    			print_bmap(bbmap, fs->e2fs_bsize);  | 
    
    
    192  | 
     | 
     | 
    		}  | 
    
    
    193  | 
     | 
     | 
     | 
    
    
    194  | 
     | 
     | 
    		(void)snprintf(msg, sizeof(msg),  | 
    
    
    195  | 
     | 
     | 
    		    "BLK(S) MISSING IN BIT MAPS #%d", c);  | 
    
    
    196  | 
     | 
     | 
    		if (memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize) &&  | 
    
    
    197  | 
     | 
     | 
    			dofix(&idesc[1], msg)) { | 
    
    
    198  | 
     | 
     | 
    			memcpy(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize);  | 
    
    
    199  | 
     | 
     | 
    			dirty(blk_bitmap);  | 
    
    
    200  | 
     | 
     | 
    		}  | 
    
    
    201  | 
     | 
     | 
    		if (debug && memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize)) { | 
    
    
    202  | 
     | 
     | 
    			printf("ino_bitmap:\n"); | 
    
    
    203  | 
     | 
     | 
    			print_bmap(ino_bitmap->b_un.b_buf, fs->e2fs_bsize);  | 
    
    
    204  | 
     | 
     | 
    			printf("ibmap:\n"); | 
    
    
    205  | 
     | 
     | 
    			print_bmap(ibmap, fs->e2fs_bsize);  | 
    
    
    206  | 
     | 
     | 
    		}  | 
    
    
    207  | 
     | 
     | 
    		(void)snprintf(msg, sizeof(msg),  | 
    
    
    208  | 
     | 
     | 
    		    "INODE(S) MISSING IN BIT MAPS #%d", c);  | 
    
    
    209  | 
     | 
     | 
    		if (memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize) &&  | 
    
    
    210  | 
     | 
     | 
    			dofix(&idesc[1], msg)) { | 
    
    
    211  | 
     | 
     | 
    			memcpy(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize);  | 
    
    
    212  | 
     | 
     | 
    			dirty(ino_bitmap);  | 
    
    
    213  | 
     | 
     | 
    		}  | 
    
    
    214  | 
     | 
     | 
     | 
    
    
    215  | 
     | 
     | 
    	}  | 
    
    
    216  | 
     | 
     | 
    	if (debug && (fs->e2fs.e2fs_fbcount != cs_nbfree ||  | 
    
    
    217  | 
     | 
     | 
    		fs->e2fs.e2fs_ficount != cs_nifree)) { | 
    
    
    218  | 
     | 
     | 
    		printf("summary info bad in superblock: %d, %d should be %d, %d\n", | 
    
    
    219  | 
     | 
     | 
    		fs->e2fs.e2fs_fbcount, fs->e2fs.e2fs_ficount,  | 
    
    
    220  | 
     | 
     | 
    		cs_nbfree, cs_nifree);  | 
    
    
    221  | 
     | 
     | 
    	}  | 
    
    
    222  | 
     | 
     | 
    	if ((fs->e2fs.e2fs_fbcount != cs_nbfree ||  | 
    
    
    223  | 
     | 
     | 
    		fs->e2fs.e2fs_ficount != cs_nifree)  | 
    
    
    224  | 
     | 
     | 
    	    && dofix(&idesc[0], "SUPERBLK SUMMARY INFORMATION BAD")) { | 
    
    
    225  | 
     | 
     | 
    		fs->e2fs.e2fs_fbcount = cs_nbfree;  | 
    
    
    226  | 
     | 
     | 
    		fs->e2fs.e2fs_ficount = cs_nifree;  | 
    
    
    227  | 
     | 
     | 
    		sbdirty();  | 
    
    
    228  | 
     | 
     | 
    	}  | 
    
    
    229  | 
     | 
     | 
    	free(ibmap);  | 
    
    
    230  | 
     | 
     | 
    	free(bbmap);  | 
    
    
    231  | 
     | 
     | 
    }  | 
    
    
    232  | 
     | 
     | 
     | 
    
    
    233  | 
     | 
     | 
    void  | 
    
    
    234  | 
     | 
     | 
    print_bmap(u_char *map, u_int32_t size)  | 
    
    
    235  | 
     | 
     | 
    { | 
    
    
    236  | 
     | 
     | 
    	int i, j;  | 
    
    
    237  | 
     | 
     | 
     | 
    
    
    238  | 
     | 
     | 
    	i = 0;  | 
    
    
    239  | 
     | 
     | 
    	while (i < size) { | 
    
    
    240  | 
     | 
     | 
    		printf("%u: ",i); | 
    
    
    241  | 
     | 
     | 
    		for (j = 0; j < 16; j++, i++)  | 
    
    
    242  | 
     | 
     | 
    			printf("%2x ", (u_int)map[i] & 0xff); | 
    
    
    243  | 
     | 
     | 
    		printf("\n"); | 
    
    
    244  | 
     | 
     | 
    	}  | 
    
    
    245  | 
     | 
     | 
    }  |