1 /*
2  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3  *
4  * This is written from sratch according to Linux kernel fs/sysv/super.c file.
5  * It seems that sysv probing code in libvolume_id and also in the original
6  * blkid is useless.
7  *
8  * This file may be redistributed under the terms of the
9  * GNU Lesser General Public License.
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdint.h>
15 #include <stddef.h>
16 
17 #include "superblocks.h"
18 
19 #define XENIX_NICINOD				100
20 #define XENIX_NICFREE				100
21 
22 struct xenix_super_block {
23 	uint16_t	s_isize;
24 	uint32_t	s_fsize;
25 	uint16_t	s_nfree;
26 	uint32_t	s_free[XENIX_NICFREE];
27 	uint16_t	s_ninode;
28 	uint16_t	s_inode[XENIX_NICINOD];
29 	uint8_t		s_flock;
30 	uint8_t		s_ilock;
31 	uint8_t		s_fmod;
32 	uint8_t		s_ronly;
33 	uint32_t	s_time;
34 	uint32_t	s_tfree;
35 	uint16_t	s_tinode;
36 	uint16_t	s_dinfo[4];
37 	uint8_t		s_fname[6];
38 	uint8_t		s_fpack[6];
39 	uint8_t		s_clean;
40 	uint8_t		s_fill[371];
41 	uint32_t	s_magic;
42 	uint32_t	s_type;
43 } __attribute__((packed));
44 
45 
46 #define SYSV_NICINOD			100
47 #define SYSV_NICFREE			50
48 
49 struct sysv_super_block
50 {
51 	uint16_t	s_isize;
52 	uint16_t	s_pad0;
53 	uint32_t	s_fsize;
54 	uint16_t	s_nfree;
55 	uint16_t	s_pad1;
56 	uint32_t	s_free[SYSV_NICFREE];
57 	uint16_t	s_ninode;
58 	uint16_t	s_pad2;
59 	uint16_t	s_inode[SYSV_NICINOD];
60 	uint8_t		s_flock;
61 	uint8_t		s_ilock;
62 	uint8_t		s_fmod;
63 	uint8_t		s_ronly;
64 	uint32_t	s_time;
65 	uint16_t	s_dinfo[4];
66 	uint32_t	s_tfree;
67 	uint16_t	s_tinode;
68 	uint16_t	s_pad3;
69 	uint8_t		s_fname[6];
70 	uint8_t		s_fpack[6];
71 	uint32_t	s_fill[12];
72 	uint32_t	s_state;
73 	uint32_t	s_magic;
74 	uint32_t	s_type;
75 };
76 
probe_xenix(blkid_probe pr,const struct blkid_idmag * mag)77 static int probe_xenix(blkid_probe pr, const struct blkid_idmag *mag)
78 {
79 	struct xenix_super_block *sb;
80 
81 	sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block);
82 	if (!sb)
83 		return errno ? -errno : 1;
84 	blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname));
85 	return 0;
86 }
87 
88 #define SYSV_BLOCK_SIZE	1024
89 
90 /* Note that we don't probe for Coherent FS, this FS does not have
91  * magic string. (It requires to probe fname/fpack field..)
92  */
probe_sysv(blkid_probe pr,const struct blkid_idmag * mag)93 static int probe_sysv(blkid_probe pr,
94 		const struct blkid_idmag *mag __attribute__((__unused__)))
95 {
96 	struct sysv_super_block *sb;
97 	int blocks[] = {0, 9, 15, 18};
98 	size_t i;
99 
100 	for (i = 0; i < ARRAY_SIZE(blocks); i++) {
101 		int off = blocks[i] * SYSV_BLOCK_SIZE + SYSV_BLOCK_SIZE/2;
102 
103 		sb = (struct sysv_super_block *)
104 			blkid_probe_get_buffer(pr,
105 					off,
106 					sizeof(struct sysv_super_block));
107 		if (!sb)
108 			return errno ? -errno : 1;
109 
110 		if (sb->s_magic == cpu_to_le32(0xfd187e20) ||
111 		    sb->s_magic == cpu_to_be32(0xfd187e20)) {
112 
113 			if (blkid_probe_set_label(pr, sb->s_fname,
114 						sizeof(sb->s_fname)))
115 				return 1;
116 
117 			if (blkid_probe_set_magic(pr,
118 					off + offsetof(struct sysv_super_block,
119 								s_magic),
120 					sizeof(sb->s_magic),
121 					(unsigned char *) &sb->s_magic))
122 				return 1;
123 
124 			return 0;
125 		}
126 	}
127 	return 1;
128 }
129 
130 const struct blkid_idinfo xenix_idinfo =
131 {
132 	.name		= "xenix",
133 	.usage		= BLKID_USAGE_FILESYSTEM,
134 	.probefunc	= probe_xenix,
135 	.magics		=
136 	{
137 		{ .magic = "\x2b\x55\x44", .len = 3, .kboff = 1, .sboff = 0x400 },
138 		{ .magic = "\x44\x55\x2b", .len = 3, .kboff = 1, .sboff = 0x400 },
139 		{ NULL }
140 	}
141 };
142 
143 const struct blkid_idinfo sysv_idinfo =
144 {
145 	.name		= "sysv",
146 	.usage		= BLKID_USAGE_FILESYSTEM,
147 	.probefunc	= probe_sysv,
148 
149 	/* SYSV is BE and LE and superblock could be on four positions. It's
150 	 * simpler to probe for the magic string by .probefunc().
151 	 */
152 	.magics		= BLKID_NONE_MAGIC
153 };
154 
155