findsuper.c revision 74a74d22d8ed60587afd55c798f08531115f4920
1/*
2 * findsuper --- quick hacked up program to find ext2 superblocks.
3 *
4 * This is a hack, and really shouldn't be installed anywhere.  If you
5 * need a program which does this sort of functionality, please try
6 * using gpart program.
7 *
8 * Portions Copyright 1998-2000, Theodore Ts'o.
9 *
10 * This program may be used under the provisions of the GNU Public
11 * License, *EXCEPT* that it may not be included in the Debian
12 * distribution.  (Yes, this violates the Debian Free Software
13 * Guidelines.  That's the point.  I don't want this program being
14 * distributed in Debian, because I don't care to support it, and the
15 * maintainer, Yann Dirson, doesn't seem to pay attention to my wishes
16 * on this matter.  So I'm delibiately adding this clause so it
17 * violates the Debian Free Software Guidelines to force him to take
18 * it out.  If this doesn't work, I'll have to remove it from the
19 * upstream source distribution on the next release.  So there.  :-)
20 *
21 * Well, here's my linux version of findsuper.
22 * I'm sure you coulda done it faster.  :)
23 * IMHO there isn't as much interesting data to print in the
24 * linux superblock as there is in the SunOS superblock--disk geometry is
25 * not there...and linux seems to update the dates in all the superblocks.
26 * SunOS doesn't ever touch the backup superblocks after the fs is created,
27 * as far as I can tell, so the date is more interesting IMHO and certainly
28 * marks which superblocks are backup ones.
29 *
30 * This still doesn't handle disks >2G.
31 *
32 * I wanted to add msdos support, but I couldn't make heads or tails
33 * of the kernel include files to find anything I could look for in msdos.
34 *
35 * Reading every block of a Sun partition is fairly quick.  Doing the
36 * same under linux (slower hardware I suppose) just isn't the same.
37 * It might be more useful to default to reading the first (second?) block
38 * on each cyl; however, if the disk geometry is wrong, this is useless.
39 * But ya could still get the cyl size to print the numbers as cyls instead
40 * of blocks...
41 *
42 * run this as (for example)
43 *   findsuper /dev/hda
44 *   findsuper /dev/hda 437760 1024   (my disk has cyls of 855*512)
45 *
46 * I suppose the next step is to figgure out a way to determine if
47 * the block found is the first superblock somehow, and if so, build
48 * a partition table from the superblocks found... but this is still
49 * useful as is.
50 *
51 *		Steve
52 * ssd@nevets.oau.org
53 * ssd@mae.engr.ucf.edu
54 *
55 */
56
57/*
58 * Documentation addendum added by Andreas dwguest@win.tue.nl/aeb@cwi.nl
59 *
60 * The program findsuper is a utility that scans a disk and finds
61 * copies of ext2 superblocks (by checking for the ext2 signature; it
62 * will occasionally find other blocks that by coincidence have this
63 * signature - often these can be recognised by their ridiculous
64 * dates).
65 *
66 * For each superblock found, it prints the offset in bytes, the
67 * offset in 1024-byte blocks, the size of ext2 partition in 1024-byte
68 * blocks, the filesystem blocksize (given as log(blocksize)-10, so
69 * that 0 means 1024), the block group number (0 for older ext2
70 * systems), and a timestamp (s_mtime).
71 *
72 * This program can be used to retrieve partitions that have been
73 * lost.  The superblock for block group 0 is found 1 block (2
74 * sectors) after the partition start.
75 *
76 * For new systems that have a block group number in the superblock it
77 * is immediately clear which superblock is the first of a partition.
78 * For old systems where no group numbers are given, the first
79 * superblock can be recognised by the timestamp: all superblock
80 * copies have the creation time in s_mtime, except the first, which
81 * has the last time e2fsck or tune2fs wrote to the filesystem.
82 *
83 */
84
85
86#include <stdio.h>
87#include <stdlib.h>
88#include <time.h>
89
90#include <linux/ext2_fs.h>
91#include "nls-enable.h"
92
93
94main(int argc, char *argv[])
95{
96	int i;
97	int skiprate=512;		/* one sector */
98	long sk=0;			/* limited to 2G filesystems!! */
99	FILE *f;
100	char *s;
101	time_t tm;
102
103	struct ext2_super_block ext2;
104	/* interesting fields: EXT2_SUPER_MAGIC
105	 *      s_blocks_count s_log_block_size s_mtime s_magic s_lastcheck */
106
107#ifdef ENABLE_NLS
108	setlocale(LC_MESSAGES, "");
109	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
110	textdomain(NLS_CAT_NAME);
111#endif
112	if (argc<2) {
113		fprintf(stderr,
114			_("Usage:  findsuper device [skiprate [start]]\n"));
115		exit(1);
116	}
117	if (argc>2)
118		skiprate=atoi(argv[2]);
119	if (skiprate<512) {
120		fprintf(stderr,
121			_("Do you really want to skip less than a sector??\n"));
122		exit(2);
123	}
124	if (argc>3)
125		sk=atol(argv[3]);
126	if (sk<0) {
127		fprintf(stderr,_("Have to start at 0 or greater,not %ld\n"),sk);
128		exit(1);
129	}
130	f=fopen(argv[1],"r");
131	if (!f) {
132		perror(argv[1]);
133		exit(1);
134	}
135
136	/* Now, go looking for the superblock ! */
137	printf("  thisoff     block fs_blk_sz  blksz grp last_mount\n");
138	for (;!feof(f) &&  (i=fseek(f,sk,SEEK_SET))!= -1; sk+=skiprate){
139		if (i=fread(&ext2,sizeof(ext2),1, f)!=1) {
140			perror(_("read failed"));
141		}
142		if (ext2.s_magic != EXT2_SUPER_MAGIC)
143			continue;
144
145		tm = ext2.s_mtime;
146		s=ctime(&tm);
147		s[24]=0;
148		printf("%9ld %9ld %9ld %5ld %4d %s\n", sk,
149		       sk/1024, ext2.s_blocks_count,
150		       ext2.s_log_block_size,
151		       ext2.s_block_group_nr, s);
152	}
153	printf(_("Failed on %d at %ld\n"), i, sk);
154	fclose(f);
155}
156