summaryrefslogtreecommitdiffstats
path: root/libblkid/src/superblocks/reiserfs.c
blob: 6c5e5b0d7103b96d2b6f5e858ca14f994810916d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 1999, 2001 by Andries Brouwer
 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

#include "superblocks.h"

struct reiserfs_super_block {
	uint32_t	rs_blocks_count;
	uint32_t	rs_free_blocks;
	uint32_t	rs_root_block;
	uint32_t	rs_journal_block;
	uint32_t	rs_journal_dev;
	uint32_t	rs_orig_journal_size;
	uint32_t	rs_dummy2[5];
	uint16_t	rs_blocksize;
	uint16_t	rs_dummy3[3];
	unsigned char	rs_magic[12];
	uint32_t	rs_dummy4[5];
	unsigned char	rs_uuid[16];
	char		rs_label[16];
} __attribute__((packed));

struct reiser4_super_block {
	unsigned char	rs4_magic[16];
	uint8_t		rs4_dummy[3];
	uint8_t		rs4_blocksize;
	unsigned char	rs4_uuid[16];
	unsigned char	rs4_label[16];
	uint64_t	rs4_dummy2;
} __attribute__((packed));

static int probe_reiser(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct reiserfs_super_block *rs;
	unsigned int blocksize;

	rs = blkid_probe_get_sb(pr, mag, struct reiserfs_super_block);
	if (!rs)
		return errno ? -errno : 1;

	blocksize = le16_to_cpu(rs->rs_blocksize);

	/* The blocksize must be at least 512B */
	if ((blocksize >> 9) == 0)
		return 1;

	/* If the superblock is inside the journal, we have the wrong one */
	if (mag->kboff / (blocksize >> 9) > le32_to_cpu(rs->rs_journal_block) / 2)
		return 1;

	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
	if (mag->magic[6] == '2' || mag->magic[6] == '3') {
		if (*rs->rs_label)
			blkid_probe_set_label(pr,
					(unsigned char *) rs->rs_label,
					sizeof(rs->rs_label));
		blkid_probe_set_uuid(pr, rs->rs_uuid);
	}

	if (mag->magic[6] == '3')
		blkid_probe_set_version(pr, "JR");
	else if (mag->magic[6] == '2')
		blkid_probe_set_version(pr, "3.6");
	else
		blkid_probe_set_version(pr, "3.5");

	blkid_probe_set_block_size(pr, blocksize);

	return 0;
}

static int probe_reiser4(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct reiser4_super_block *rs4;
	unsigned int blocksize;

	rs4 = blkid_probe_get_sb(pr, mag, struct reiser4_super_block);
	if (!rs4)
		return errno ? -errno : 1;

	blocksize = rs4->rs4_blocksize * 256;

	if (*rs4->rs4_label)
		blkid_probe_set_label(pr, rs4->rs4_label, sizeof(rs4->rs4_label));
	blkid_probe_set_uuid(pr, rs4->rs4_uuid);
	blkid_probe_set_version(pr, "4");

	blkid_probe_set_block_size(pr, blocksize);

	return 0;
}


const struct blkid_idinfo reiser_idinfo =
{
	.name		= "reiserfs",
	.usage		= BLKID_USAGE_FILESYSTEM,
	.probefunc	= probe_reiser,
	.minsz		= 128 * 1024,
	.magics		=
	{
		{ .magic = "ReIsErFs",  .len = 8, .kboff = 8,  .sboff = 0x34 },
		{ .magic = "ReIsEr2Fs", .len = 9, .kboff = 64, .sboff = 0x34 },
		{ .magic = "ReIsEr3Fs", .len = 9, .kboff = 64, .sboff = 0x34 },
		{ .magic = "ReIsErFs",  .len = 8, .kboff = 64, .sboff = 0x34 },
		{ .magic = "ReIsErFs",  .len = 8, .kboff =  8, .sboff = 20   },
		{ NULL }
	}
};

const struct blkid_idinfo reiser4_idinfo =
{
	.name		= "reiser4",
	.usage		= BLKID_USAGE_FILESYSTEM,
	.probefunc	= probe_reiser4,
	.minsz		= 128 * 1024,
	.magics		=
	{
		{ .magic = "ReIsEr4", .len = 7, .kboff = 64 },
		{ NULL }
	}
};