(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
minix.c
       1  /*
       2   * Copyright (C) 1999 by Andries Brouwer
       3   * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
       4   * Copyright (C) 2001 by Andreas Dilger
       5   * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
       6   * Copyright (C) 2008-2013 Karel Zak <kzak@redhat.com>
       7   *
       8   * This file may be redistributed under the terms of the
       9   * GNU Lesser General Public License.
      10   */
      11  
      12  #include <string.h>
      13  #include "superblocks.h"
      14  #include "minix.h"
      15  
      16  #define minix_swab16(doit, num)	((uint16_t) (doit ? swab16(num) : num))
      17  #define minix_swab32(doit, num)	((uint32_t) (doit ? swab32(num) : num))
      18  
      19  static int get_minix_version(const unsigned char *data, int *other_endian)
      20  {
      21  	const struct minix_super_block *sb = (const struct minix_super_block *) data;
      22  	const struct minix3_super_block *sb3 = (const struct minix3_super_block *) data;
      23  	int version = 0;
      24  	char *endian;
      25  
      26  	*other_endian = 0;
      27  
      28  	switch (sb->s_magic) {
      29  	case MINIX_SUPER_MAGIC:
      30  	case MINIX_SUPER_MAGIC2:
      31  		version = 1;
      32  		break;
      33  	case MINIX2_SUPER_MAGIC:
      34  	case MINIX2_SUPER_MAGIC2:
      35  		version = 2;
      36  		break;
      37  	default:
      38  		if (sb3->s_magic == MINIX3_SUPER_MAGIC)
      39  			version = 3;
      40  		break;
      41  	}
      42  
      43  	if (!version) {
      44  		*other_endian = 1;
      45  
      46  		switch (swab16(sb->s_magic)) {
      47  		case MINIX_SUPER_MAGIC:
      48  		case MINIX_SUPER_MAGIC2:
      49  			version = 1;
      50  			break;
      51  		case MINIX2_SUPER_MAGIC:
      52  		case MINIX2_SUPER_MAGIC2:
      53  			version = 2;
      54  			break;
      55  		default:
      56  			if (sb3->s_magic == MINIX3_SUPER_MAGIC)
      57  				version = 3;
      58  			break;
      59  		}
      60  	}
      61  	if (!version)
      62  		return -1;
      63  
      64  #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      65  	endian = *other_endian ? "LE" : "BE";
      66  #else
      67  	endian = *other_endian ? "BE" : "LE";
      68  #endif
      69  	DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version,
      70  			       endian));
      71  	return version;
      72  }
      73  
      74  static int probe_minix(blkid_probe pr,
      75  		const struct blkid_idmag *mag __attribute__((__unused__)))
      76  {
      77  	unsigned char *ext;
      78  	const unsigned char *data;
      79  	int version = 0, swabme = 0;
      80  	unsigned long zones, ninodes, imaps, zmaps;
      81  	off_t firstz;
      82  	size_t zone_size;
      83  	unsigned block_size;
      84  
      85  	data = blkid_probe_get_buffer(pr, 1024,
      86  			max(sizeof(struct minix_super_block),
      87  			    sizeof(struct minix3_super_block)));
      88  	if (!data)
      89  		return errno ? -errno : 1;
      90  	version = get_minix_version(data, &swabme);
      91  	switch (version) {
      92  	case 1:
      93  	case 2: {
      94  		const struct minix_super_block *sb = (const struct minix_super_block *) data;
      95  
      96  		uint16_t state = minix_swab16(swabme, sb->s_state);
      97  		if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
      98  			return 1;
      99  
     100  		zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
     101  				       minix_swab16(swabme, sb->s_nzones);
     102  		ninodes = minix_swab16(swabme, sb->s_ninodes);
     103  		imaps   = minix_swab16(swabme, sb->s_imap_blocks);
     104  		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
     105  		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
     106  		zone_size = sb->s_log_zone_size;
     107  		block_size = 1024;
     108  		break;
     109  	}
     110  	case 3: {
     111  		const struct minix3_super_block *sb = (const struct minix3_super_block *) data;
     112  
     113  		zones = minix_swab32(swabme, sb->s_zones);
     114  		ninodes = minix_swab32(swabme, sb->s_ninodes);
     115  		imaps   = minix_swab16(swabme, sb->s_imap_blocks);
     116  		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
     117  		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
     118  		zone_size = sb->s_log_zone_size;
     119  		block_size = minix_swab16(swabme, sb->s_blocksize);
     120  
     121  		break;
     122  	}
     123  	default:
     124  		return 1;
     125  	}
     126  
     127  	/* sanity checks to be sure that the FS is really minix.
     128  	 * see disk-utils/fsck.minix.c read_superblock
     129  	 */
     130  	if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX)
     131  		return 1;
     132  	if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
     133  		return 1;
     134  	if (firstz > (off_t) zones)
     135  		return 1;
     136  	if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
     137  		return 1;
     138  
     139  	/* unfortunately, some parts of ext3 is sometimes possible to
     140  	 * interpreted as minix superblock. So check for extN magic
     141  	 * string. (For extN magic string and offsets see ext.c.)
     142  	 */
     143  	ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
     144  	if (!ext)
     145  		return errno ? -errno : 1;
     146  
     147  	if (memcmp(ext, "\123\357", 2) == 0)
     148  		return 1;
     149  
     150  	blkid_probe_sprintf_version(pr, "%d", version);
     151  	blkid_probe_set_fsblocksize(pr, block_size);
     152  	blkid_probe_set_block_size(pr, block_size);
     153  	blkid_probe_set_fsendianness(pr, !swabme ?
     154  			BLKID_ENDIANNESS_NATIVE : BLKID_ENDIANNESS_OTHER);
     155  	return 0;
     156  }
     157  
     158  const struct blkid_idinfo minix_idinfo =
     159  {
     160  	.name		= "minix",
     161  	.usage		= BLKID_USAGE_FILESYSTEM,
     162  	.probefunc	= probe_minix,
     163  	.magics		=
     164  	{
     165  		/* version 1 - LE */
     166  		{ .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
     167  		{ .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
     168  
     169  		/* version 1 - BE */
     170  		{ .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 },
     171  		{ .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 },
     172  
     173  		/* version 2 - LE */
     174  		{ .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
     175  		{ .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
     176  
     177  		/* version 2 - BE */
     178  		{ .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 },
     179  		{ .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 },
     180  
     181  		/* version 3 - LE */
     182  		{ .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
     183  
     184  		/* version 3 - BE */
     185  		{ .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 },
     186  
     187  		{ NULL }
     188  	}
     189  };
     190