summaryrefslogtreecommitdiffstats
path: root/libblkid/src/superblocks/sysv.c
blob: 421660e556a2b7c129ab57c8a731c096ababa4de (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
 *
 * This is written from scratch according to Linux kernel fs/sysv/super.c file.
 * It seems that sysv probing code in libvolume_id and also in the original
 * blkid is useless.
 *
 * 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 <stdint.h>
#include <stddef.h>

#include "superblocks.h"

#define XENIX_NICINOD				100
#define XENIX_NICFREE				100

struct xenix_super_block {
	uint16_t	s_isize;
	uint32_t	s_fsize;
	uint16_t	s_nfree;
	uint32_t	s_free[XENIX_NICFREE];
	uint16_t	s_ninode;
	uint16_t	s_inode[XENIX_NICINOD];
	uint8_t		s_flock;
	uint8_t		s_ilock;
	uint8_t		s_fmod;
	uint8_t		s_ronly;
	uint32_t	s_time;
	uint32_t	s_tfree;
	uint16_t	s_tinode;
	uint16_t	s_dinfo[4];
	uint8_t		s_fname[6];
	uint8_t		s_fpack[6];
	uint8_t		s_clean;
	uint8_t		s_fill[371];
	uint32_t	s_magic;
	uint32_t	s_type;
} __attribute__((packed));


#define SYSV_NICINOD			100
#define SYSV_NICFREE			50

struct sysv_super_block
{
	uint16_t	s_isize;
	uint16_t	s_pad0;
	uint32_t	s_fsize;
	uint16_t	s_nfree;
	uint16_t	s_pad1;
	uint32_t	s_free[SYSV_NICFREE];
	uint16_t	s_ninode;
	uint16_t	s_pad2;
	uint16_t	s_inode[SYSV_NICINOD];
	uint8_t		s_flock;
	uint8_t		s_ilock;
	uint8_t		s_fmod;
	uint8_t		s_ronly;
	uint32_t	s_time;
	uint16_t	s_dinfo[4];
	uint32_t	s_tfree;
	uint16_t	s_tinode;
	uint16_t	s_pad3;
	uint8_t		s_fname[6];
	uint8_t		s_fpack[6];
	uint32_t	s_fill[12];
	uint32_t	s_state;
	uint32_t	s_magic;
	uint32_t	s_type;
};

static int probe_xenix(blkid_probe pr, const struct blkid_idmag *mag)
{
	struct xenix_super_block *sb;

	sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block);
	if (!sb)
		return errno ? -errno : 1;
	blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname));
	return 0;
}

#define SYSV_BLOCK_SIZE	1024

/* Note that we don't probe for Coherent FS, this FS does not have
 * magic string. (It requires to probe fname/fpack field..)
 */
static int probe_sysv(blkid_probe pr,
		const struct blkid_idmag *mag __attribute__((__unused__)))
{
	struct sysv_super_block *sb;
	int blocks[] = {0, 9, 15, 18};
	size_t i;

	for (i = 0; i < ARRAY_SIZE(blocks); i++) {
		int off = blocks[i] * SYSV_BLOCK_SIZE + SYSV_BLOCK_SIZE/2;

		sb = (struct sysv_super_block *)
			blkid_probe_get_buffer(pr,
					off,
					sizeof(struct sysv_super_block));
		if (!sb)
			return errno ? -errno : 1;

		if (sb->s_magic == cpu_to_le32(0xfd187e20) ||
		    sb->s_magic == cpu_to_be32(0xfd187e20)) {

			if (blkid_probe_set_label(pr, sb->s_fname,
						sizeof(sb->s_fname)))
				return 1;

			if (blkid_probe_set_magic(pr,
					off + offsetof(struct sysv_super_block,
								s_magic),
					sizeof(sb->s_magic),
					(unsigned char *) &sb->s_magic))
				return 1;

			return 0;
		}
	}
	return 1;
}

const struct blkid_idinfo xenix_idinfo =
{
	.name		= "xenix",
	.usage		= BLKID_USAGE_FILESYSTEM,
	.probefunc	= probe_xenix,
	.magics		=
	{
		{ .magic = "\x2b\x55\x44", .len = 3, .kboff = 1, .sboff = 0x400 },
		{ .magic = "\x44\x55\x2b", .len = 3, .kboff = 1, .sboff = 0x400 },
		{ NULL }
	}
};

const struct blkid_idinfo sysv_idinfo =
{
	.name		= "sysv",
	.usage		= BLKID_USAGE_FILESYSTEM,
	.probefunc	= probe_sysv,

	/* SYSV is BE and LE and superblock could be on four positions. It's
	 * simpler to probe for the magic string by .probefunc().
	 */
	.magics		= BLKID_NONE_MAGIC
};