1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 *	This program is free software; you can redistribute it and/or modify it
7 *	under the terms of the GNU General Public License as published by the
8 *	Free Software Foundation version 2 of the License.
9 */
10
11#ifndef _GNU_SOURCE
12#define _GNU_SOURCE 1
13#endif
14
15#ifdef HAVE_CONFIG_H
16#  include <config.h>
17#endif
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <string.h>
23#include <errno.h>
24#include <ctype.h>
25
26#include "libvolume_id.h"
27#include "util.h"
28
29#define MINIX_SUPERBLOCK_OFFSET			0x400
30
31#define MINIX_SUPER_MAGIC			0x137F
32#define MINIX_SUPER_MAGIC2			0x138F
33#define MINIX2_SUPER_MAGIC			0x2468
34#define MINIX2_SUPER_MAGIC2			0x2478
35#define MINIX3_SUPER_MAGIC			0x4d5a
36
37struct minix_super_block
38{
39	uint16_t	s_ninodes;
40	uint16_t	s_nzones;
41	uint16_t	s_imap_blocks;
42	uint16_t	s_zmap_blocks;
43	uint16_t	s_firstdatazone;
44	uint16_t	s_log_zone_size;
45	uint32_t	s_max_size;
46	uint16_t	s_magic;
47	uint16_t	s_state;
48	uint32_t	s_zones;
49} PACKED;
50
51struct minix3_super_block {
52	uint32_t	s_ninodes;
53	uint16_t	s_pad0;
54	uint16_t	s_imap_blocks;
55	uint16_t	s_zmap_blocks;
56	uint16_t	s_firstdatazone;
57	uint16_t	s_log_zone_size;
58	uint16_t	s_pad1;
59	uint32_t	s_max_size;
60	uint32_t	s_zones;
61	uint16_t	s_magic;
62	uint16_t	s_pad2;
63	uint16_t	s_blocksize;
64	uint8_t 	s_disk_version;
65} PACKED;
66
67int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size)
68{
69	uint8_t *buf;
70	struct minix_super_block *ms;
71	struct minix3_super_block *m3s;
72
73	info("probing at offset 0x%llx", (unsigned long long) off);
74
75	buf = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
76	if (buf == NULL)
77		return -1;
78
79	ms = (struct minix_super_block *) buf;
80
81	if (ms->s_magic == MINIX_SUPER_MAGIC ||
82	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) {
83		strcpy(id->type_version, "1");
84		goto found;
85	}
86	if (ms->s_magic == MINIX_SUPER_MAGIC2 ||
87	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) {
88		strcpy(id->type_version, "1");
89		goto found;
90	}
91	if (ms->s_magic == MINIX2_SUPER_MAGIC ||
92	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) {
93		strcpy(id->type_version, "2");
94		goto found;
95	}
96	if (ms->s_magic == MINIX2_SUPER_MAGIC2 ||
97	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) {
98		strcpy(id->type_version, "2");
99		goto found;
100	}
101
102	m3s = (struct minix3_super_block *) buf;
103	if (m3s->s_magic == MINIX3_SUPER_MAGIC ||
104	    m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) {
105		strcpy(id->type_version, "3");
106		goto found;
107	}
108	goto exit;
109
110found:
111	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
112	id->type = "minix";
113	return 0;
114
115exit:
116	return -1;
117}
118