aboutsummaryrefslogtreecommitdiff
path: root/util-linux/volume_id
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-18 21:08:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-18 21:08:49 +0000
commitde7684a309ad20c1b889d048d741cb1dd52245f7 (patch)
treeefae3387e1978cdd128ff2a922b734d0e9d0180f /util-linux/volume_id
parent27dd495b98a6135554b1d839fefe436ba3c6ca71 (diff)
downloadbusybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.tar.gz
busybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.tar.bz2
busybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.zip
support for mount by label (not yet tested)
Also adds findfs applet. Closes bug 1143.
Diffstat (limited to 'util-linux/volume_id')
-rw-r--r--util-linux/volume_id/Kbuild41
-rw-r--r--util-linux/volume_id/cramfs.c58
-rw-r--r--util-linux/volume_id/ext.c71
-rw-r--r--util-linux/volume_id/fat.c333
-rw-r--r--util-linux/volume_id/get_devname.c399
-rw-r--r--util-linux/volume_id/hfs.c292
-rw-r--r--util-linux/volume_id/highpoint.c86
-rw-r--r--util-linux/volume_id/hpfs.c50
-rw-r--r--util-linux/volume_id/iso9660.c118
-rw-r--r--util-linux/volume_id/isw_raid.c58
-rw-r--r--util-linux/volume_id/jfs.c59
-rw-r--r--util-linux/volume_id/linux_raid.c79
-rw-r--r--util-linux/volume_id/linux_swap.c73
-rw-r--r--util-linux/volume_id/lsi_raid.c52
-rw-r--r--util-linux/volume_id/luks.c76
-rw-r--r--util-linux/volume_id/lvm.c91
-rw-r--r--util-linux/volume_id/mac.c125
-rw-r--r--util-linux/volume_id/minix.c76
-rw-r--r--util-linux/volume_id/msdos.c196
-rw-r--r--util-linux/volume_id/ntfs.c193
-rw-r--r--util-linux/volume_id/nvidia_raid.c56
-rw-r--r--util-linux/volume_id/ocfs2.c105
-rw-r--r--util-linux/volume_id/promise_raid.c63
-rw-r--r--util-linux/volume_id/reiserfs.c105
-rw-r--r--util-linux/volume_id/romfs.c54
-rw-r--r--util-linux/volume_id/silicon_raid.c69
-rw-r--r--util-linux/volume_id/sysv.c125
-rw-r--r--util-linux/volume_id/udf.c172
-rw-r--r--util-linux/volume_id/ufs.c206
-rw-r--r--util-linux/volume_id/util.c260
-rw-r--r--util-linux/volume_id/via_raid.c68
-rw-r--r--util-linux/volume_id/volume_id.c214
-rw-r--r--util-linux/volume_id/volume_id_internal.h220
-rw-r--r--util-linux/volume_id/xfs.c59
34 files changed, 4302 insertions, 0 deletions
diff --git a/util-linux/volume_id/Kbuild b/util-linux/volume_id/Kbuild
new file mode 100644
index 000000000..c2eb01564
--- /dev/null
+++ b/util-linux/volume_id/Kbuild
@@ -0,0 +1,41 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7lib-y:=
8
9lib-$(CONFIG_FINDFS) += get_devname.o
10lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
11
12lib-$(CONFIG_VOLUMEID) += volume_id.o util.o
13lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
14lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
15lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
16lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
17lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
18lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
19lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
20lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
21lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
22lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
23lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
24lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
25lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
26lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
27lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
28lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
29lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
30lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
31lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
32lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
33lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
34lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
35lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
36lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
37lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
38lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
39lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
40lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
41lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c
new file mode 100644
index 000000000..fd6e87522
--- /dev/null
+++ b/util-linux/volume_id/cramfs.c
@@ -0,0 +1,58 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct cramfs_super {
24 uint8_t magic[4];
25 uint32_t size;
26 uint32_t flags;
27 uint32_t future;
28 uint8_t signature[16];
29 struct cramfs_info {
30 uint32_t crc;
31 uint32_t edition;
32 uint32_t blocks;
33 uint32_t files;
34 } __attribute__((__packed__)) info;
35 uint8_t name[16];
36} __attribute__((__packed__));
37
38int volume_id_probe_cramfs(struct volume_id *id, uint64_t off)
39{
40 struct cramfs_super *cs;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 cs = volume_id_get_buffer(id, off, 0x200);
45 if (cs == NULL)
46 return -1;
47
48 if (memcmp(cs->magic, "\x45\x3d\xcd\x28", 4) == 0) {
49 volume_id_set_label_raw(id, cs->name, 16);
50 volume_id_set_label_string(id, cs->name, 16);
51
52 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
53 id->type = "cramfs";
54 return 0;
55 }
56
57 return -1;
58}
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c
new file mode 100644
index 000000000..3c07f5301
--- /dev/null
+++ b/util-linux/volume_id/ext.c
@@ -0,0 +1,71 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ext2_super_block {
24 uint32_t inodes_count;
25 uint32_t blocks_count;
26 uint32_t r_blocks_count;
27 uint32_t free_blocks_count;
28 uint32_t free_inodes_count;
29 uint32_t first_data_block;
30 uint32_t log_block_size;
31 uint32_t dummy3[7];
32 uint8_t magic[2];
33 uint16_t state;
34 uint32_t dummy5[8];
35 uint32_t feature_compat;
36 uint32_t feature_incompat;
37 uint32_t feature_ro_compat;
38 uint8_t uuid[16];
39 uint8_t volume_name[16];
40} __attribute__((__packed__));
41
42#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
43#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
44#define EXT_SUPERBLOCK_OFFSET 0x400
45
46int volume_id_probe_ext(struct volume_id *id, uint64_t off)
47{
48 struct ext2_super_block *es;
49
50 dbg("probing at offset 0x%llx", (unsigned long long) off);
51
52 es = volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
53 if (es == NULL)
54 return -1;
55
56 if (es->magic[0] != 0123 ||
57 es->magic[1] != 0357)
58 return -1;
59
60 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
61 volume_id_set_label_raw(id, es->volume_name, 16);
62 volume_id_set_label_string(id, es->volume_name, 16);
63 volume_id_set_uuid(id, es->uuid, UUID_DCE);
64
65 if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
66 id->type = "ext3";
67 else
68 id->type = "ext2";
69
70 return 0;
71}
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c
new file mode 100644
index 000000000..4c2a91749
--- /dev/null
+++ b/util-linux/volume_id/fat.c
@@ -0,0 +1,333 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define FAT12_MAX 0xff5
24#define FAT16_MAX 0xfff5
25#define FAT_ATTR_VOLUME_ID 0x08
26#define FAT_ATTR_DIR 0x10
27#define FAT_ATTR_LONG_NAME 0x0f
28#define FAT_ATTR_MASK 0x3f
29#define FAT_ENTRY_FREE 0xe5
30
31struct vfat_super_block {
32 uint8_t boot_jump[3];
33 uint8_t sysid[8];
34 uint16_t sector_size;
35 uint8_t sectors_per_cluster;
36 uint16_t reserved;
37 uint8_t fats;
38 uint16_t dir_entries;
39 uint16_t sectors;
40 uint8_t media;
41 uint16_t fat_length;
42 uint16_t secs_track;
43 uint16_t heads;
44 uint32_t hidden;
45 uint32_t total_sect;
46 union {
47 struct fat_super_block {
48 uint8_t unknown[3];
49 uint8_t serno[4];
50 uint8_t label[11];
51 uint8_t magic[8];
52 uint8_t dummy2[192];
53 uint8_t pmagic[2];
54 } __attribute__((__packed__)) fat;
55 struct fat32_super_block {
56 uint32_t fat32_length;
57 uint16_t flags;
58 uint8_t version[2];
59 uint32_t root_cluster;
60 uint16_t insfo_sector;
61 uint16_t backup_boot;
62 uint16_t reserved2[6];
63 uint8_t unknown[3];
64 uint8_t serno[4];
65 uint8_t label[11];
66 uint8_t magic[8];
67 uint8_t dummy2[164];
68 uint8_t pmagic[2];
69 } __attribute__((__packed__)) fat32;
70 } __attribute__((__packed__)) type;
71} __attribute__((__packed__));
72
73struct vfat_dir_entry {
74 uint8_t name[11];
75 uint8_t attr;
76 uint16_t time_creat;
77 uint16_t date_creat;
78 uint16_t time_acc;
79 uint16_t date_acc;
80 uint16_t cluster_high;
81 uint16_t time_write;
82 uint16_t date_write;
83 uint16_t cluster_low;
84 uint32_t size;
85} __attribute__((__packed__));
86
87static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned count)
88{
89 unsigned i;
90
91 for (i = 0; i < count; i++) {
92 /* end marker */
93 if (dir[i].name[0] == 0x00) {
94 dbg("end of dir");
95 break;
96 }
97
98 /* empty entry */
99 if (dir[i].name[0] == FAT_ENTRY_FREE)
100 continue;
101
102 /* long name */
103 if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
104 continue;
105
106 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
107 /* labels do not have file data */
108 if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
109 continue;
110
111 dbg("found ATTR_VOLUME_ID id in root dir");
112 return dir[i].name;
113 }
114
115 dbg("skip dir entry");
116 }
117
118 return NULL;
119}
120
121int volume_id_probe_vfat(struct volume_id *id, uint64_t off)
122{
123 struct vfat_super_block *vs;
124 struct vfat_dir_entry *dir;
125 uint16_t sector_size;
126 uint16_t dir_entries;
127 uint32_t sect_count;
128 uint16_t reserved;
129 uint32_t fat_size;
130 uint32_t root_cluster;
131 uint32_t dir_size;
132 uint32_t cluster_count;
133 uint32_t fat_length;
134 uint64_t root_start;
135 uint32_t start_data_sect;
136 uint16_t root_dir_entries;
137 uint8_t *buf;
138 uint32_t buf_size;
139 uint8_t *label = NULL;
140 uint32_t next;
141 int maxloop;
142
143 dbg("probing at offset 0x%llx", (unsigned long long) off);
144
145 vs = volume_id_get_buffer(id, off, 0x200);
146 if (vs == NULL)
147 return -1;
148
149 /* believe only that's fat, don't trust the version
150 * the cluster_count will tell us
151 */
152 if (memcmp(vs->sysid, "NTFS", 4) == 0)
153 return -1;
154
155 if (memcmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
156 goto valid;
157
158 if (memcmp(vs->type.fat32.magic, "FAT32 ", 8) == 0)
159 goto valid;
160
161 if (memcmp(vs->type.fat.magic, "FAT16 ", 8) == 0)
162 goto valid;
163
164 if (memcmp(vs->type.fat.magic, "MSDOS", 5) == 0)
165 goto valid;
166
167 if (memcmp(vs->type.fat.magic, "FAT12 ", 8) == 0)
168 goto valid;
169
170 /*
171 * There are old floppies out there without a magic, so we check
172 * for well known values and guess if it's a fat volume
173 */
174
175 /* boot jump address check */
176 if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
177 vs->boot_jump[0] != 0xe9)
178 return -1;
179
180 /* heads check */
181 if (vs->heads == 0)
182 return -1;
183
184 /* cluster size check*/
185 if (vs->sectors_per_cluster == 0 ||
186 (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
187 return -1;
188
189 /* media check */
190 if (vs->media < 0xf8 && vs->media != 0xf0)
191 return -1;
192
193 /* fat count*/
194 if (vs->fats != 2)
195 return -1;
196
197 valid:
198 /* sector size check */
199 sector_size = le16_to_cpu(vs->sector_size);
200 if (sector_size != 0x200 && sector_size != 0x400 &&
201 sector_size != 0x800 && sector_size != 0x1000)
202 return -1;
203
204 dbg("sector_size 0x%x", sector_size);
205 dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
206
207 dir_entries = le16_to_cpu(vs->dir_entries);
208 reserved = le16_to_cpu(vs->reserved);
209 dbg("reserved 0x%x", reserved);
210
211 sect_count = le16_to_cpu(vs->sectors);
212 if (sect_count == 0)
213 sect_count = le32_to_cpu(vs->total_sect);
214 dbg("sect_count 0x%x", sect_count);
215
216 fat_length = le16_to_cpu(vs->fat_length);
217 if (fat_length == 0)
218 fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
219 dbg("fat_length 0x%x", fat_length);
220
221 fat_size = fat_length * vs->fats;
222 dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
223 (sector_size-1)) / sector_size;
224 dbg("dir_size 0x%x", dir_size);
225
226 cluster_count = sect_count - (reserved + fat_size + dir_size);
227 cluster_count /= vs->sectors_per_cluster;
228 dbg("cluster_count 0x%x", cluster_count);
229
230 if (cluster_count < FAT12_MAX) {
231 strcpy(id->type_version, "FAT12");
232 } else if (cluster_count < FAT16_MAX) {
233 strcpy(id->type_version, "FAT16");
234 } else {
235 strcpy(id->type_version, "FAT32");
236 goto fat32;
237 }
238
239 /* the label may be an attribute in the root directory */
240 root_start = (reserved + fat_size) * sector_size;
241 dbg("root dir start 0x%llx", (unsigned long long) root_start);
242 root_dir_entries = le16_to_cpu(vs->dir_entries);
243 dbg("expected entries 0x%x", root_dir_entries);
244
245 buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
246 buf = volume_id_get_buffer(id, off + root_start, buf_size);
247 if (buf == NULL)
248 goto found;
249
250 dir = (struct vfat_dir_entry*) buf;
251
252 label = get_attr_volume_id(dir, root_dir_entries);
253
254 vs = volume_id_get_buffer(id, off, 0x200);
255 if (vs == NULL)
256 return -1;
257
258 if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
259 volume_id_set_label_raw(id, label, 11);
260 volume_id_set_label_string(id, label, 11);
261 } else if (memcmp(vs->type.fat.label, "NO NAME ", 11) != 0) {
262 volume_id_set_label_raw(id, vs->type.fat.label, 11);
263 volume_id_set_label_string(id, vs->type.fat.label, 11);
264 }
265 volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
266 goto found;
267
268 fat32:
269 /* FAT32 root dir is a cluster chain like any other directory */
270 buf_size = vs->sectors_per_cluster * sector_size;
271 root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
272 dbg("root dir cluster %u", root_cluster);
273 start_data_sect = reserved + fat_size;
274
275 next = root_cluster;
276 maxloop = 100;
277 while (--maxloop) {
278 uint32_t next_sect_off;
279 uint64_t next_off;
280 uint64_t fat_entry_off;
281 int count;
282
283 dbg("next cluster %u", next);
284 next_sect_off = (next - 2) * vs->sectors_per_cluster;
285 next_off = (start_data_sect + next_sect_off) * sector_size;
286 dbg("cluster offset 0x%llx", (unsigned long long) next_off);
287
288 /* get cluster */
289 buf = volume_id_get_buffer(id, off + next_off, buf_size);
290 if (buf == NULL)
291 goto found;
292
293 dir = (struct vfat_dir_entry*) buf;
294 count = buf_size / sizeof(struct vfat_dir_entry);
295 dbg("expected entries 0x%x", count);
296
297 label = get_attr_volume_id(dir, count);
298 if (label)
299 break;
300
301 /* get FAT entry */
302 fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t));
303 buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size);
304 if (buf == NULL)
305 goto found;
306
307 /* set next cluster */
308 next = le32_to_cpu(*((uint32_t *) buf) & 0x0fffffff);
309 if (next == 0)
310 break;
311 }
312 if (maxloop == 0)
313 dbg("reached maximum follow count of root cluster chain, give up");
314
315 vs = volume_id_get_buffer(id, off, 0x200);
316 if (vs == NULL)
317 return -1;
318
319 if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
320 volume_id_set_label_raw(id, label, 11);
321 volume_id_set_label_string(id, label, 11);
322 } else if (memcmp(vs->type.fat32.label, "NO NAME ", 11) != 0) {
323 volume_id_set_label_raw(id, vs->type.fat32.label, 11);
324 volume_id_set_label_string(id, vs->type.fat32.label, 11);
325 }
326 volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);
327
328 found:
329 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
330 id->type = "vfat";
331
332 return 0;
333}
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c
new file mode 100644
index 000000000..75060b0d8
--- /dev/null
+++ b/util-linux/volume_id/get_devname.c
@@ -0,0 +1,399 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Support functions for mounting devices by label/uuid
4 *
5 * Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
6 * Some portions cribbed from e2fsprogs, util-linux, dosfstools
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */
10
11#include "volume_id_internal.h"
12
13#define BLKGETSIZE64 _IOR(0x12,114,size_t)
14
15#define PROC_PARTITIONS "/proc/partitions"
16#define PROC_CDROMS "/proc/sys/dev/cdrom/info"
17#define DEVLABELDIR "/dev"
18#define SYS_BLOCK "/sys/block"
19
20static struct uuidCache_s {
21 struct uuidCache_s *next;
22 char uuid[16];
23 char *device;
24 char *label;
25 int major, minor;
26} *uuidCache;
27
28/* for now, only ext2, ext3 and xfs are supported */
29static int
30get_label_uuid(const char *device, char **label, char **uuid, int iso_only)
31{
32 int rv = 1;
33 uint64_t size;
34 struct volume_id *vid;
35
36 vid = volume_id_open_node(device);
37
38 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) {
39 size = 0;
40 }
41
42#if ENABLE_FEATURE_VOLUMEID_ISO9660
43 if (iso_only ?
44 volume_id_probe_iso9660(vid, 0) != 0 :
45 volume_id_probe_all(vid, 0, size) != 0) {
46 goto ret;
47 }
48#else
49 if (volume_id_probe_all(vid, 0, size) != 0) {
50 goto ret;
51 }
52#endif
53
54 if (vid->label[0] != '\0') {
55 *label = xstrndup(vid->label, sizeof(vid->label));
56 *uuid = xstrndup(vid->uuid, sizeof(vid->uuid));
57 printf("Found label %s on %s (uuid:%s)\n", *label, device, *uuid);
58 rv = 0;
59 }
60 ret:
61 free_volume_id(vid);
62 return rv;
63}
64
65static void
66uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid)
67{
68 struct uuidCache_s *last;
69
70 if (!uuidCache) {
71 last = uuidCache = xzalloc(sizeof(*uuidCache));
72 } else {
73 for (last = uuidCache; last->next; last = last->next)
74 continue;
75 last->next = xzalloc(sizeof(*uuidCache));
76 last = last->next;
77 }
78 /*last->next = NULL; - xzalloc did it*/
79 last->label = label;
80 last->device = device;
81 last->major = major;
82 last->minor = minor;
83 memcpy(last->uuid, uuid, sizeof(last->uuid));
84}
85
86static void
87uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only)
88{
89 char device[110];
90 char *uuid = NULL, *label = NULL;
91 char *ptr;
92 char *deviceDir = NULL;
93 int mustRemove = 0;
94 int mustRemoveDir = 0;
95 int i;
96
97 sprintf(device, "%s/%s", DEVLABELDIR, device_name);
98 if (access(device, F_OK)) {
99 ptr = device;
100 i = 0;
101 while (*ptr)
102 if (*ptr++ == '/')
103 i++;
104 if (i > 2) {
105 deviceDir = alloca(strlen(device) + 1);
106 strcpy(deviceDir, device);
107 ptr = deviceDir + (strlen(device) - 1);
108 while (*ptr != '/')
109 *ptr-- = '\0';
110 if (mkdir(deviceDir, 0644)) {
111 printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
112 } else {
113 mustRemoveDir = 1;
114 }
115 }
116
117 mknod(device, S_IFBLK | 0600, makedev(ma, mi));
118 mustRemove = 1;
119 }
120 if (!get_label_uuid(device, &label, &uuid, iso_only))
121 uuidcache_addentry(strdup(device), ma, mi,
122 label, uuid);
123
124 if (mustRemove) unlink(device);
125 if (mustRemoveDir) rmdir(deviceDir);
126}
127
128static void
129uuidcache_init_partitions(void)
130{
131 char line[100];
132 int ma, mi;
133 unsigned long long sz;
134 FILE *procpt;
135 int firstPass;
136 int handleOnFirst;
137 char *chptr;
138
139 procpt = xfopen(PROC_PARTITIONS, "r");
140/*
141# cat /proc/partitions
142major minor #blocks name
143
144 8 0 293036184 sda
145 8 1 6835626 sda1
146 8 2 1 sda2
147 8 5 979933 sda5
148 8 6 15623181 sda6
149 8 7 97659103 sda7
150 8 8 171935631 sda8
151*/
152 for (firstPass = 1; firstPass >= 0; firstPass--) {
153 fseek(procpt, 0, SEEK_SET);
154
155 while (fgets(line, sizeof(line), procpt)) {
156 /* The original version of this code used sscanf, but
157 diet's sscanf is quite limited */
158 chptr = line;
159 if (*chptr != ' ') continue;
160 chptr++;
161
162 ma = bb_strtou(chptr, &chptr, 0);
163 if (ma < 0) continue;
164 chptr = skip_whitespace(chptr);
165
166 mi = bb_strtou(chptr, &chptr, 0);
167 if (mi < 0) continue;
168 chptr = skip_whitespace(chptr);
169
170 sz = bb_strtoull(chptr, &chptr, 0);
171 if ((long long)sz == -1LL) continue;
172 chptr = skip_whitespace(chptr);
173
174 /* skip extended partitions (heuristic: size 1) */
175 if (sz == 1)
176 continue;
177
178 *strchrnul(chptr, '\n') = '\0';
179 /* now chptr => device name */
180 if (!chptr[0])
181 continue;
182
183 /* look only at md devices on first pass */
184 handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd');
185 if (firstPass != handleOnFirst)
186 continue;
187
188 /* heuristic: partition name ends in a digit */
189 if (isdigit(chptr[strlen(chptr) - 1])) {
190 uuidcache_check_device(chptr, ma, mi, 0);
191 }
192 }
193 }
194
195 fclose(procpt);
196}
197
198static int
199dev_get_major_minor(char *device_name, int *major, int *minor)
200{
201 char * dev_path;
202 int fd;
203 char dev[7];
204 char *major_ptr, *minor_ptr;
205
206 dev_path = alloca(strlen(SYS_BLOCK) + strlen(device_name) + 6);
207 sprintf(dev_path, "%s/%s/dev", SYS_BLOCK, device_name);
208
209 fd = open(dev_path, O_RDONLY);
210 if (fd < 0) return 1;
211 full_read(fd, dev, sizeof(dev));
212 close(fd);
213
214 major_ptr = dev;
215 minor_ptr = strchr(dev, ':');
216 if (!minor_ptr) return 1;
217 *minor_ptr++ = '\0';
218
219 *major = strtol(major_ptr, NULL, 10);
220 *minor = strtol(minor_ptr, NULL, 10);
221
222 return 0;
223}
224
225static void
226uuidcache_init_cdroms(void)
227{
228 char line[100];
229 int ma, mi;
230 FILE *proccd;
231
232 proccd = fopen(PROC_CDROMS, "r");
233 if (!proccd) {
234 static smallint warn = 0;
235 if (!warn) {
236 warn = 1;
237 bb_error_msg("mount: could not open %s, so UUID and LABEL "
238 "conversion cannot be done for CD-Roms.",
239 PROC_CDROMS);
240 }
241 return;
242 }
243
244 while (fgets(line, sizeof(line), proccd)) {
245 const char *drive_name_string = "drive name:\t\t";
246 if (!strncmp(line, drive_name_string, strlen(drive_name_string))) {
247 char *device_name;
248 device_name = strtok(line + strlen(drive_name_string), "\t\n");
249 while (device_name) {
250 dev_get_major_minor(device_name, &ma, &mi);
251 uuidcache_check_device(device_name, ma, mi, 1);
252 device_name = strtok(NULL, "\t\n");
253 }
254 break;
255 }
256 }
257
258 fclose(proccd);
259}
260
261static void
262uuidcache_init(void)
263{
264 if (uuidCache)
265 return;
266
267 uuidcache_init_partitions();
268 uuidcache_init_cdroms();
269}
270
271#define UUID 1
272#define VOL 2
273
274#ifdef UNUSED
275static char *
276get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr)
277{
278 struct uuidCache_s *uc;
279
280 uuidcache_init();
281 uc = uuidCache;
282
283 while(uc) {
284 switch (n) {
285 case UUID:
286 if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
287 *majorPtr = uc->major;
288 *minorPtr = uc->minor;
289 return uc->device;
290 }
291 break;
292 case VOL:
293 if (!strcmp(t, uc->label)) {
294 *majorPtr = uc->major;
295 *minorPtr = uc->minor;
296 return uc->device;
297 }
298 break;
299 }
300 uc = uc->next;
301 }
302 return NULL;
303}
304
305static unsigned char
306fromhex(char c)
307{
308 if (isdigit(c))
309 return (c - '0');
310 if (islower(c))
311 return (c - 'a' + 10);
312 return (c - 'A' + 10);
313}
314
315static char *
316get_spec_by_uuid(const char *s, int * major, int * minor)
317{
318 unsigned char uuid[16];
319 int i;
320
321 if (strlen(s) != 36 ||
322 s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
323 goto bad_uuid;
324 for (i=0; i<16; i++) {
325 if (*s == '-') s++;
326 if (!isxdigit(s[0]) || !isxdigit(s[1]))
327 goto bad_uuid;
328 uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
329 s += 2;
330 }
331 return get_spec_by_x(UUID, (char *)uuid, major, minor);
332
333 bad_uuid:
334 fprintf(stderr, _("mount: bad UUID"));
335 return 0;
336}
337
338static char *
339get_spec_by_volume_label(const char *s, int *major, int *minor)
340{
341 return get_spec_by_x(VOL, s, major, minor);
342}
343
344static int display_uuid_cache(void)
345{
346 struct uuidCache_s *u;
347 size_t i;
348
349 uuidcache_init();
350
351 u = uuidCache;
352 while (u) {
353 printf("%s %s ", u->device, u->label);
354 for (i = 0; i < sizeof(u->uuid); i++) {
355 if (i == 4 || i == 6 || i == 8 || i == 10)
356 printf("-");
357 printf("%x", u->uuid[i] & 0xff);
358 }
359 printf("\n");
360 u = u->next;
361 }
362
363 return 0;
364}
365#endif // UNUSED
366
367
368/* Used by mount and findfs */
369
370char *get_devname_from_label(const char *spec)
371{
372 struct uuidCache_s *uc;
373 int spec_len = strlen(spec);
374
375 uuidcache_init();
376 uc = uuidCache;
377 while (uc) {
378 if (uc->label && !strncmp(spec, uc->label, spec_len)) {
379 return xstrdup(uc->device);
380 }
381 uc = uc->next;
382 }
383 return NULL;
384}
385
386char *get_devname_from_uuid(const char *spec)
387{
388 struct uuidCache_s *uc;
389
390 uuidcache_init();
391 uc = uuidCache;
392 while (uc) {
393 if (!memcmp(spec, uc->uuid, sizeof(uc->uuid))) {
394 return xstrdup(uc->device);
395 }
396 uc = uc->next;
397 }
398 return NULL;
399}
diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c
new file mode 100644
index 000000000..71a3df0b8
--- /dev/null
+++ b/util-linux/volume_id/hfs.c
@@ -0,0 +1,292 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hfs_finder_info{
24 uint32_t boot_folder;
25 uint32_t start_app;
26 uint32_t open_folder;
27 uint32_t os9_folder;
28 uint32_t reserved;
29 uint32_t osx_folder;
30 uint8_t id[8];
31} __attribute__((__packed__));
32
33struct hfs_mdb {
34 uint8_t signature[2];
35 uint32_t cr_date;
36 uint32_t ls_Mod;
37 uint16_t atrb;
38 uint16_t nm_fls;
39 uint16_t vbm_st;
40 uint16_t alloc_ptr;
41 uint16_t nm_al_blks;
42 uint32_t al_blk_size;
43 uint32_t clp_size;
44 uint16_t al_bl_st;
45 uint32_t nxt_cnid;
46 uint16_t free_bks;
47 uint8_t label_len;
48 uint8_t label[27];
49 uint32_t vol_bkup;
50 uint16_t vol_seq_num;
51 uint32_t wr_cnt;
52 uint32_t xt_clump_size;
53 uint32_t ct_clump_size;
54 uint16_t num_root_dirs;
55 uint32_t file_count;
56 uint32_t dir_count;
57 struct hfs_finder_info finder_info;
58 uint8_t embed_sig[2];
59 uint16_t embed_startblock;
60 uint16_t embed_blockcount;
61} __attribute__((__packed__));
62
63struct hfsplus_bnode_descriptor {
64 uint32_t next;
65 uint32_t prev;
66 uint8_t type;
67 uint8_t height;
68 uint16_t num_recs;
69 uint16_t reserved;
70} __attribute__((__packed__));
71
72struct hfsplus_bheader_record {
73 uint16_t depth;
74 uint32_t root;
75 uint32_t leaf_count;
76 uint32_t leaf_head;
77 uint32_t leaf_tail;
78 uint16_t node_size;
79} __attribute__((__packed__));
80
81struct hfsplus_catalog_key {
82 uint16_t key_len;
83 uint32_t parent_id;
84 uint16_t unicode_len;
85 uint8_t unicode[255 * 2];
86} __attribute__((__packed__));
87
88struct hfsplus_extent {
89 uint32_t start_block;
90 uint32_t block_count;
91} __attribute__((__packed__));
92
93#define HFSPLUS_EXTENT_COUNT 8
94struct hfsplus_fork {
95 uint64_t total_size;
96 uint32_t clump_size;
97 uint32_t total_blocks;
98 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
99} __attribute__((__packed__));
100
101struct hfsplus_vol_header {
102 uint8_t signature[2];
103 uint16_t version;
104 uint32_t attributes;
105 uint32_t last_mount_vers;
106 uint32_t reserved;
107 uint32_t create_date;
108 uint32_t modify_date;
109 uint32_t backup_date;
110 uint32_t checked_date;
111 uint32_t file_count;
112 uint32_t folder_count;
113 uint32_t blocksize;
114 uint32_t total_blocks;
115 uint32_t free_blocks;
116 uint32_t next_alloc;
117 uint32_t rsrc_clump_sz;
118 uint32_t data_clump_sz;
119 uint32_t next_cnid;
120 uint32_t write_count;
121 uint64_t encodings_bmp;
122 struct hfs_finder_info finder_info;
123 struct hfsplus_fork alloc_file;
124 struct hfsplus_fork ext_file;
125 struct hfsplus_fork cat_file;
126 struct hfsplus_fork attr_file;
127 struct hfsplus_fork start_file;
128} __attribute__((__packed__));
129
130#define HFS_SUPERBLOCK_OFFSET 0x400
131#define HFS_NODE_LEAF 0xff
132#define HFSPLUS_POR_CNID 1
133
134int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off)
135{
136 unsigned blocksize;
137 unsigned cat_block;
138 unsigned ext_block_start;
139 unsigned ext_block_count;
140 int ext;
141 unsigned leaf_node_head;
142 unsigned leaf_node_count;
143 unsigned leaf_node_size;
144 unsigned leaf_block;
145 uint64_t leaf_off;
146 unsigned alloc_block_size;
147 unsigned alloc_first_block;
148 unsigned embed_first_block;
149 unsigned record_count;
150 struct hfsplus_vol_header *hfsplus;
151 struct hfsplus_bnode_descriptor *descr;
152 struct hfsplus_bheader_record *bnode;
153 struct hfsplus_catalog_key *key;
154 unsigned label_len;
155 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
156 struct hfs_mdb *hfs;
157 const uint8_t *buf;
158
159 dbg("probing at offset 0x%llx", (unsigned long long) off);
160
161 buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
162 if (buf == NULL)
163 return -1;
164
165 hfs = (struct hfs_mdb *) buf;
166 if (hfs->signature[0] != 'B' || hfs->signature[1] != 'D')
167 goto checkplus;
168
169 /* it may be just a hfs wrapper for hfs+ */
170 if (memcmp(hfs->embed_sig, "H+", 2) == 0) {
171 alloc_block_size = be32_to_cpu(hfs->al_blk_size);
172 dbg("alloc_block_size 0x%x", alloc_block_size);
173
174 alloc_first_block = be16_to_cpu(hfs->al_bl_st);
175 dbg("alloc_first_block 0x%x", alloc_first_block);
176
177 embed_first_block = be16_to_cpu(hfs->embed_startblock);
178 dbg("embed_first_block 0x%x", embed_first_block);
179
180 off += (alloc_first_block * 512) +
181 (embed_first_block * alloc_block_size);
182 dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);
183
184 buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
185 if (buf == NULL)
186 return -1;
187 goto checkplus;
188 }
189
190 if (hfs->label_len > 0 && hfs->label_len < 28) {
191 volume_id_set_label_raw(id, hfs->label, hfs->label_len);
192 volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
193 }
194
195 volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
196
197 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
198 id->type = "hfs";
199
200 return 0;
201
202 checkplus:
203 hfsplus = (struct hfsplus_vol_header *) buf;
204 if (hfs->signature[0] == 'H')
205 if (hfs->signature[1] == '+' || hfs->signature[1] == 'X')
206 goto hfsplus;
207 return -1;
208
209 hfsplus:
210 volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
211
212 blocksize = be32_to_cpu(hfsplus->blocksize);
213 dbg("blocksize %u", blocksize);
214
215 memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
216 cat_block = be32_to_cpu(extents[0].start_block);
217 dbg("catalog start block 0x%x", cat_block);
218
219 buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
220 if (buf == NULL)
221 goto found;
222
223 bnode = (struct hfsplus_bheader_record *)
224 &buf[sizeof(struct hfsplus_bnode_descriptor)];
225
226 leaf_node_head = be32_to_cpu(bnode->leaf_head);
227 dbg("catalog leaf node 0x%x", leaf_node_head);
228
229 leaf_node_size = be16_to_cpu(bnode->node_size);
230 dbg("leaf node size 0x%x", leaf_node_size);
231
232 leaf_node_count = be32_to_cpu(bnode->leaf_count);
233 dbg("leaf node count 0x%x", leaf_node_count);
234 if (leaf_node_count == 0)
235 goto found;
236
237 leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
238
239 /* get physical location */
240 for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
241 ext_block_start = be32_to_cpu(extents[ext].start_block);
242 ext_block_count = be32_to_cpu(extents[ext].block_count);
243 dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
244
245 if (ext_block_count == 0)
246 goto found;
247
248 /* this is our extent */
249 if (leaf_block < ext_block_count)
250 break;
251
252 leaf_block -= ext_block_count;
253 }
254 if (ext == HFSPLUS_EXTENT_COUNT)
255 goto found;
256 dbg("found block in extent %i", ext);
257
258 leaf_off = (ext_block_start + leaf_block) * blocksize;
259
260 buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
261 if (buf == NULL)
262 goto found;
263
264 descr = (struct hfsplus_bnode_descriptor *) buf;
265 dbg("descriptor type 0x%x", descr->type);
266
267 record_count = be16_to_cpu(descr->num_recs);
268 dbg("number of records %u", record_count);
269 if (record_count == 0)
270 goto found;
271
272 if (descr->type != HFS_NODE_LEAF)
273 goto found;
274
275 key = (struct hfsplus_catalog_key *)
276 &buf[sizeof(struct hfsplus_bnode_descriptor)];
277
278 dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
279 if (key->parent_id != cpu_to_be32(HFSPLUS_POR_CNID))
280 goto found;
281
282 label_len = be16_to_cpu(key->unicode_len) * 2;
283 dbg("label unicode16 len %i", label_len);
284 volume_id_set_label_raw(id, key->unicode, label_len);
285 volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
286
287 found:
288 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
289 id->type = "hfsplus";
290
291 return 0;
292}
diff --git a/util-linux/volume_id/highpoint.c b/util-linux/volume_id/highpoint.c
new file mode 100644
index 000000000..de31a2a26
--- /dev/null
+++ b/util-linux/volume_id/highpoint.c
@@ -0,0 +1,86 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hpt37x_meta {
24 uint8_t filler1[32];
25 uint32_t magic;
26} __attribute__((packed));
27
28struct hpt45x_meta {
29 uint32_t magic;
30} __attribute__((packed));
31
32#define HPT37X_CONFIG_OFF 0x1200
33#define HPT37X_MAGIC_OK 0x5a7816f0
34#define HPT37X_MAGIC_BAD 0x5a7816fd
35
36#define HPT45X_MAGIC_OK 0x5a7816f3
37#define HPT45X_MAGIC_BAD 0x5a7816fd
38
39
40int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off)
41{
42 struct hpt37x_meta *hpt;
43 uint32_t magic;
44
45 dbg("probing at offset 0x%llx", (unsigned long long) off);
46
47 hpt = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
48 if (hpt == NULL)
49 return -1;
50
51 magic = hpt->magic;
52 if (magic != cpu_to_le32(HPT37X_MAGIC_OK) && magic != cpu_to_le32(HPT37X_MAGIC_BAD))
53 return -1;
54
55 volume_id_set_usage(id, VOLUME_ID_RAID);
56 id->type = "highpoint_raid_member";
57
58 return 0;
59}
60
61int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size)
62{
63 struct hpt45x_meta *hpt;
64 uint64_t meta_off;
65 uint32_t magic;
66
67 dbg("probing at offset 0x%llx, size 0x%llx",
68 (unsigned long long) off, (unsigned long long) size);
69
70 if (size < 0x10000)
71 return -1;
72
73 meta_off = ((size / 0x200)-11) * 0x200;
74 hpt = volume_id_get_buffer(id, off + meta_off, 0x200);
75 if (hpt == NULL)
76 return -1;
77
78 magic = hpt->magic;
79 if (magic != cpu_to_le32(HPT45X_MAGIC_OK) && magic != cpu_to_le32(HPT45X_MAGIC_BAD))
80 return -1;
81
82 volume_id_set_usage(id, VOLUME_ID_RAID);
83 id->type = "highpoint_raid_member";
84
85 return 0;
86}
diff --git a/util-linux/volume_id/hpfs.c b/util-linux/volume_id/hpfs.c
new file mode 100644
index 000000000..b43fb79b5
--- /dev/null
+++ b/util-linux/volume_id/hpfs.c
@@ -0,0 +1,50 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hpfs_super
24{
25 uint8_t magic[4];
26 uint8_t version;
27} __attribute__((__packed__));
28
29#define HPFS_SUPERBLOCK_OFFSET 0x2000
30
31int volume_id_probe_hpfs(struct volume_id *id, uint64_t off)
32{
33 struct hpfs_super *hs;
34
35 dbg("probing at offset 0x%llx", (unsigned long long) off);
36
37 hs = volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200);
38 if (hs == NULL)
39 return -1;
40
41 if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) == 0) {
42 sprintf(id->type_version, "%u", hs->version);
43
44 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
45 id->type = "hpfs";
46 return 0;
47 }
48
49 return -1;
50}
diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c
new file mode 100644
index 000000000..fa9227746
--- /dev/null
+++ b/util-linux/volume_id/iso9660.c
@@ -0,0 +1,118 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define ISO_SUPERBLOCK_OFFSET 0x8000
24#define ISO_SECTOR_SIZE 0x800
25#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
26#define ISO_VD_PRIMARY 0x1
27#define ISO_VD_SUPPLEMENTARY 0x2
28#define ISO_VD_END 0xff
29#define ISO_VD_MAX 16
30
31struct iso_volume_descriptor {
32 uint8_t vd_type;
33 uint8_t vd_id[5];
34 uint8_t vd_version;
35 uint8_t flags;
36 uint8_t system_id[32];
37 uint8_t volume_id[32];
38 uint8_t unused[8];
39 uint8_t space_size[8];
40 uint8_t escape_sequences[8];
41} __attribute__((__packed__));
42
43struct high_sierra_volume_descriptor {
44 uint8_t foo[8];
45 uint8_t type;
46 uint8_t id[4];
47 uint8_t version;
48} __attribute__((__packed__));
49
50int volume_id_probe_iso9660(struct volume_id *id, uint64_t off)
51{
52 uint8_t *buf;
53 struct iso_volume_descriptor *is;
54 struct high_sierra_volume_descriptor *hs;
55
56 dbg("probing at offset 0x%llx", (unsigned long long) off);
57
58 buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
59 if (buf == NULL)
60 return -1;
61
62 is = (struct iso_volume_descriptor *) buf;
63
64 if (memcmp(is->vd_id, "CD001", 5) == 0) {
65 int vd_offset;
66 int i;
67
68 dbg("read label from PVD");
69 volume_id_set_label_raw(id, is->volume_id, 32);
70 volume_id_set_label_string(id, is->volume_id, 32);
71
72 dbg("looking for SVDs");
73 vd_offset = ISO_VD_OFFSET;
74 for (i = 0; i < ISO_VD_MAX; i++) {
75 uint8_t svd_label[64];
76
77 is = volume_id_get_buffer(id, off + vd_offset, 0x200);
78 if (is == NULL || is->vd_type == ISO_VD_END)
79 break;
80 if (is->vd_type != ISO_VD_SUPPLEMENTARY)
81 continue;
82
83 dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset));
84 if (memcmp(is->escape_sequences, "%/@", 3) == 0||
85 memcmp(is->escape_sequences, "%/C", 3) == 0||
86 memcmp(is->escape_sequences, "%/E", 3) == 0) {
87 dbg("Joliet extension found");
88 volume_id_set_unicode16((char *)svd_label, sizeof(svd_label), is->volume_id, BE, 32);
89 if (memcmp(id->label, svd_label, 16) == 0) {
90 dbg("SVD label is identical, use the possibly longer PVD one");
91 break;
92 }
93
94 volume_id_set_label_raw(id, is->volume_id, 32);
95 volume_id_set_label_string(id, svd_label, 32);
96 strcpy(id->type_version, "Joliet Extension");
97 goto found;
98 }
99 vd_offset += ISO_SECTOR_SIZE;
100 }
101 goto found;
102 }
103
104 hs = (struct high_sierra_volume_descriptor *) buf;
105
106 if (memcmp(hs->id, "CDROM", 5) == 0) {
107 strcpy(id->type_version, "High Sierra");
108 goto found;
109 }
110
111 return -1;
112
113 found:
114 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
115 id->type = "iso9660";
116
117 return 0;
118}
diff --git a/util-linux/volume_id/isw_raid.c b/util-linux/volume_id/isw_raid.c
new file mode 100644
index 000000000..8f55f49d9
--- /dev/null
+++ b/util-linux/volume_id/isw_raid.c
@@ -0,0 +1,58 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct isw_meta {
24 uint8_t sig[32];
25 uint32_t check_sum;
26 uint32_t mpb_size;
27 uint32_t family_num;
28 uint32_t generation_num;
29} __attribute__((packed));
30
31#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. "
32
33
34int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size)
35{
36 uint64_t meta_off;
37 struct isw_meta *isw;
38
39 dbg("probing at offset 0x%llx, size 0x%llx",
40 (unsigned long long) off, (unsigned long long) size);
41
42 if (size < 0x10000)
43 return -1;
44
45 meta_off = ((size / 0x200)-2) * 0x200;
46 isw = volume_id_get_buffer(id, off + meta_off, 0x200);
47 if (isw == NULL)
48 return -1;
49
50 if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
51 return -1;
52
53 volume_id_set_usage(id, VOLUME_ID_RAID);
54 memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6);
55 id->type = "isw_raid_member";
56
57 return 0;
58}
diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c
new file mode 100644
index 000000000..28b4eb694
--- /dev/null
+++ b/util-linux/volume_id/jfs.c
@@ -0,0 +1,59 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct jfs_super_block {
24 uint8_t magic[4];
25 uint32_t version;
26 uint64_t size;
27 uint32_t bsize;
28 uint32_t dummy1;
29 uint32_t pbsize;
30 uint32_t dummy2[27];
31 uint8_t uuid[16];
32 uint8_t label[16];
33 uint8_t loguuid[16];
34} __attribute__((__packed__));
35
36#define JFS_SUPERBLOCK_OFFSET 0x8000
37
38int volume_id_probe_jfs(struct volume_id *id, uint64_t off)
39{
40 struct jfs_super_block *js;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 js = volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
45 if (js == NULL)
46 return -1;
47
48 if (memcmp(js->magic, "JFS1", 4) != 0)
49 return -1;
50
51 volume_id_set_label_raw(id, js->label, 16);
52 volume_id_set_label_string(id, js->label, 16);
53 volume_id_set_uuid(id, js->uuid, UUID_DCE);
54
55 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
56 id->type = "jfs";
57
58 return 0;
59}
diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c
new file mode 100644
index 000000000..bb9b3c5cf
--- /dev/null
+++ b/util-linux/volume_id/linux_raid.c
@@ -0,0 +1,79 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct mdp_super_block {
24 uint32_t md_magic;
25 uint32_t major_version;
26 uint32_t minor_version;
27 uint32_t patch_version;
28 uint32_t gvalid_words;
29 uint32_t set_uuid0;
30 uint32_t ctime;
31 uint32_t level;
32 uint32_t size;
33 uint32_t nr_disks;
34 uint32_t raid_disks;
35 uint32_t md_minor;
36 uint32_t not_persistent;
37 uint32_t set_uuid1;
38 uint32_t set_uuid2;
39 uint32_t set_uuid3;
40} __attribute__((packed));
41
42#define MD_RESERVED_BYTES 0x10000
43#define MD_MAGIC 0xa92b4efc
44
45int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size)
46{
47 uint64_t sboff;
48 uint8_t uuid[16];
49 struct mdp_super_block *mdp;
50
51 dbg("probing at offset 0x%llx, size 0x%llx",
52 (unsigned long long) off, (unsigned long long) size);
53
54 if (size < 0x10000)
55 return -1;
56
57 sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
58 mdp = volume_id_get_buffer(id, off + sboff, 0x800);
59 if (mdp == NULL)
60 return -1;
61
62 if (mdp->md_magic != cpu_to_le32(MD_MAGIC))
63 return -1;
64
65 memcpy(uuid, &mdp->set_uuid0, 4);
66 memcpy(&uuid[4], &mdp->set_uuid1, 12);
67 volume_id_set_uuid(id, uuid, UUID_DCE);
68
69 snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
70 le32_to_cpu(mdp->major_version),
71 le32_to_cpu(mdp->minor_version),
72 le32_to_cpu(mdp->patch_version));
73
74 dbg("found raid signature");
75 volume_id_set_usage(id, VOLUME_ID_RAID);
76 id->type = "linux_raid_member";
77
78 return 0;
79}
diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c
new file mode 100644
index 000000000..56b5d5085
--- /dev/null
+++ b/util-linux/volume_id/linux_swap.c
@@ -0,0 +1,73 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct swap_header_v1_2 {
24 uint8_t bootbits[1024];
25 uint32_t version;
26 uint32_t last_page;
27 uint32_t nr_badpages;
28 uint8_t uuid[16];
29 uint8_t volume_name[16];
30} __attribute__((__packed__));
31
32#define LARGEST_PAGESIZE 0x4000
33
34int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off)
35{
36 struct swap_header_v1_2 *sw;
37 const uint8_t *buf;
38 unsigned page;
39
40 dbg("probing at offset 0x%llx", (unsigned long long) off);
41
42 /* the swap signature is at the end of the PAGE_SIZE */
43 for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
44 buf = volume_id_get_buffer(id, off + page-10, 10);
45 if (buf == NULL)
46 return -1;
47
48 if (memcmp(buf, "SWAP-SPACE", 10) == 0) {
49 id->type_version[0] = '1';
50 id->type_version[1] = '\0';
51 goto found;
52 }
53
54 if (memcmp(buf, "SWAPSPACE2", 10) == 0) {
55 sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
56 if (sw == NULL)
57 return -1;
58 id->type_version[0] = '2';
59 id->type_version[1] = '\0';
60 volume_id_set_label_raw(id, sw->volume_name, 16);
61 volume_id_set_label_string(id, sw->volume_name, 16);
62 volume_id_set_uuid(id, sw->uuid, UUID_DCE);
63 goto found;
64 }
65 }
66 return -1;
67
68found:
69 volume_id_set_usage(id, VOLUME_ID_OTHER);
70 id->type = "swap";
71
72 return 0;
73}
diff --git a/util-linux/volume_id/lsi_raid.c b/util-linux/volume_id/lsi_raid.c
new file mode 100644
index 000000000..0eab1c709
--- /dev/null
+++ b/util-linux/volume_id/lsi_raid.c
@@ -0,0 +1,52 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct lsi_meta {
24 uint8_t sig[6];
25} __attribute__((packed));
26
27#define LSI_SIGNATURE "$XIDE$"
28
29int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size)
30{
31 uint64_t meta_off;
32 struct lsi_meta *lsi;
33
34 dbg("probing at offset 0x%llx, size 0x%llx",
35 (unsigned long long) off, (unsigned long long) size);
36
37 if (size < 0x10000)
38 return -1;
39
40 meta_off = ((size / 0x200)-1) * 0x200;
41 lsi = volume_id_get_buffer(id, off + meta_off, 0x200);
42 if (lsi == NULL)
43 return -1;
44
45 if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
46 return -1;
47
48 volume_id_set_usage(id, VOLUME_ID_RAID);
49 id->type = "lsi_mega_raid_member";
50
51 return 0;
52}
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c
new file mode 100644
index 000000000..e73ce3a03
--- /dev/null
+++ b/util-linux/volume_id/luks.c
@@ -0,0 +1,76 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 W. Michael Petullo <mike@flyn.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define SECTOR_SHIFT 9
24#define SECTOR_SIZE (1 << SECTOR_SHIFT)
25
26#define LUKS_CIPHERNAME_L 32
27#define LUKS_CIPHERMODE_L 32
28#define LUKS_HASHSPEC_L 32
29#define LUKS_DIGESTSIZE 20
30#define LUKS_SALTSIZE 32
31#define LUKS_NUMKEYS 8
32
33static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe };
34#define LUKS_MAGIC_L 6
35#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
36#define UUID_STRING_L 40
37
38struct luks_phdr {
39 uint8_t magic[LUKS_MAGIC_L];
40 uint16_t version;
41 uint8_t cipherName[LUKS_CIPHERNAME_L];
42 uint8_t cipherMode[LUKS_CIPHERMODE_L];
43 uint8_t hashSpec[LUKS_HASHSPEC_L];
44 uint32_t payloadOffset;
45 uint32_t keyBytes;
46 uint8_t mkDigest[LUKS_DIGESTSIZE];
47 uint8_t mkDigestSalt[LUKS_SALTSIZE];
48 uint32_t mkDigestIterations;
49 uint8_t uuid[UUID_STRING_L];
50 struct {
51 uint32_t active;
52 uint32_t passwordIterations;
53 uint8_t passwordSalt[LUKS_SALTSIZE];
54 uint32_t keyMaterialOffset;
55 uint32_t stripes;
56 } keyblock[LUKS_NUMKEYS];
57};
58
59int volume_id_probe_luks(struct volume_id *id, uint64_t off)
60{
61 struct luks_phdr *header;
62
63 header = volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
64 if (header == NULL)
65 return -1;
66
67 if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
68 return -1;
69
70 volume_id_set_usage(id, VOLUME_ID_CRYPTO);
71 volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING);
72
73 id->type = "crypto_LUKS";
74
75 return 0;
76}
diff --git a/util-linux/volume_id/lvm.c b/util-linux/volume_id/lvm.c
new file mode 100644
index 000000000..baa8456db
--- /dev/null
+++ b/util-linux/volume_id/lvm.c
@@ -0,0 +1,91 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct lvm1_super_block {
24 uint8_t id[2];
25} __attribute__((packed));
26
27struct lvm2_super_block {
28 uint8_t id[8];
29 uint64_t sector_xl;
30 uint32_t crc_xl;
31 uint32_t offset_xl;
32 uint8_t type[8];
33} __attribute__((packed));
34
35#define LVM1_SB_OFF 0x400
36#define LVM1_MAGIC "HM"
37
38int volume_id_probe_lvm1(struct volume_id *id, uint64_t off)
39{
40 const uint8_t *buf;
41 struct lvm1_super_block *lvm;
42
43 dbg("probing at offset 0x%llx", (unsigned long long) off);
44
45 buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800);
46 if (buf == NULL)
47 return -1;
48
49 lvm = (struct lvm1_super_block *) buf;
50
51 if (memcmp(lvm->id, LVM1_MAGIC, 2) != 0)
52 return -1;
53
54 volume_id_set_usage(id, VOLUME_ID_RAID);
55 id->type = "LVM1_member";
56
57 return 0;
58}
59
60#define LVM2_LABEL_ID "LABELONE"
61#define LVM2LABEL_SCAN_SECTORS 4
62
63int volume_id_probe_lvm2(struct volume_id *id, uint64_t off)
64{
65 const uint8_t *buf;
66 unsigned soff;
67 struct lvm2_super_block *lvm;
68
69 dbg("probing at offset 0x%llx", (unsigned long long) off);
70
71 buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
72 if (buf == NULL)
73 return -1;
74
75
76 for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
77 lvm = (struct lvm2_super_block *) &buf[soff];
78
79 if (memcmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
80 goto found;
81 }
82
83 return -1;
84
85 found:
86 memcpy(id->type_version, lvm->type, 8);
87 volume_id_set_usage(id, VOLUME_ID_RAID);
88 id->type = "LVM2_member";
89
90 return 0;
91}
diff --git a/util-linux/volume_id/mac.c b/util-linux/volume_id/mac.c
new file mode 100644
index 000000000..94a99bee0
--- /dev/null
+++ b/util-linux/volume_id/mac.c
@@ -0,0 +1,125 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct mac_driver_desc {
24 uint8_t signature[2];
25 uint16_t block_size;
26 uint32_t block_count;
27} __attribute__((__packed__));
28
29struct mac_partition {
30 uint8_t signature[2];
31 uint16_t res1;
32 uint32_t map_count;
33 uint32_t start_block;
34 uint32_t block_count;
35 uint8_t name[32];
36 uint8_t type[32];
37} __attribute__((__packed__));
38
39int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off)
40{
41 const uint8_t *buf;
42 struct mac_driver_desc *driver;
43 struct mac_partition *part;
44
45 dbg("probing at offset 0x%llx", (unsigned long long) off);
46
47 buf = volume_id_get_buffer(id, off, 0x200);
48 if (buf == NULL)
49 return -1;
50
51 part = (struct mac_partition *) buf;
52 if ((memcmp(part->signature, "PM", 2) == 0) &&
53 (memcmp(part->type, "Apple_partition_map", 19) == 0)) {
54 /* linux creates an own subdevice for the map
55 * just return the type if the drive header is missing */
56 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
57 id->type = "mac_partition_map";
58 return 0;
59 }
60
61 driver = (struct mac_driver_desc *) buf;
62 if (memcmp(driver->signature, "ER", 2) == 0) {
63 /* we are on a main device, like a CD
64 * just try to probe the first partition from the map */
65 unsigned bsize = be16_to_cpu(driver->block_size);
66 int part_count;
67 int i;
68
69 /* get first entry of partition table */
70 buf = volume_id_get_buffer(id, off + bsize, 0x200);
71 if (buf == NULL)
72 return -1;
73
74 part = (struct mac_partition *) buf;
75 if (memcmp(part->signature, "PM", 2) != 0)
76 return -1;
77
78 part_count = be32_to_cpu(part->map_count);
79 dbg("expecting %d partition entries", part_count);
80
81 if (id->partitions != NULL)
82 free(id->partitions);
83 id->partitions =
84 malloc(part_count * sizeof(struct volume_id_partition));
85 if (id->partitions == NULL)
86 return -1;
87 memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
88
89 id->partition_count = part_count;
90
91 for (i = 0; i < part_count; i++) {
92 uint64_t poff;
93 uint64_t plen;
94
95 buf = volume_id_get_buffer(id, off + ((i+1) * bsize), 0x200);
96 if (buf == NULL)
97 return -1;
98
99 part = (struct mac_partition *) buf;
100 if (memcmp(part->signature, "PM", 2) != 0)
101 return -1;
102
103 poff = be32_to_cpu(part->start_block) * bsize;
104 plen = be32_to_cpu(part->block_count) * bsize;
105 dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
106 part->type, (unsigned long long) poff, (unsigned long long) plen);
107
108 id->partitions[i].off = poff;
109 id->partitions[i].len = plen;
110
111 if (memcmp(part->type, "Apple_Free", 10) == 0) {
112 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNUSED);
113 } else if (memcmp(part->type, "Apple_partition_map", 19) == 0) {
114 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_PARTITIONTABLE);
115 } else {
116 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNPROBED);
117 }
118 }
119 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
120 id->type = "mac_partition_map";
121 return 0;
122 }
123
124 return -1;
125}
diff --git a/util-linux/volume_id/minix.c b/util-linux/volume_id/minix.c
new file mode 100644
index 000000000..ede23cb24
--- /dev/null
+++ b/util-linux/volume_id/minix.c
@@ -0,0 +1,76 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct minix_super_block
24{
25 uint16_t s_ninodes;
26 uint16_t s_nzones;
27 uint16_t s_imap_blocks;
28 uint16_t s_zmap_blocks;
29 uint16_t s_firstdatazone;
30 uint16_t s_log_zone_size;
31 uint32_t s_max_size;
32 uint16_t s_magic;
33 uint16_t s_state;
34 uint32_t s_zones;
35} __attribute__((__packed__));
36
37#define MINIX_SUPERBLOCK_OFFSET 0x400
38
39int volume_id_probe_minix(struct volume_id *id, uint64_t off)
40{
41 struct minix_super_block *ms;
42
43 dbg("probing at offset 0x%llx", (unsigned long long) off);
44
45 ms = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
46 if (ms == NULL)
47 return -1;
48
49 if (le16_to_cpu(ms->s_magic) == 0x137f) {
50 id->type_version[0] = '1';
51 goto found;
52 }
53
54 if (le16_to_cpu(ms->s_magic) == 0x1387) {
55 id->type_version[0] = '1';
56 goto found;
57 }
58
59 if (le16_to_cpu(ms->s_magic) == 0x2468) {
60 id->type_version[0] = '2';
61 goto found;
62 }
63
64 if (le16_to_cpu(ms->s_magic) == 0x2478) {
65 id->type_version[0] = '2';
66 goto found;
67 }
68
69 return -1;
70
71 found:
72 id->type_version[1] = '\0';
73 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
74 id->type = "minix";
75 return 0;
76}
diff --git a/util-linux/volume_id/msdos.c b/util-linux/volume_id/msdos.c
new file mode 100644
index 000000000..b4b6711dc
--- /dev/null
+++ b/util-linux/volume_id/msdos.c
@@ -0,0 +1,196 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct msdos_partition_entry {
24 uint8_t boot_ind;
25 uint8_t head;
26 uint8_t sector;
27 uint8_t cyl;
28 uint8_t sys_ind;
29 uint8_t end_head;
30 uint8_t end_sector;
31 uint8_t end_cyl;
32 uint32_t start_sect;
33 uint32_t nr_sects;
34} __attribute__((packed));
35
36#define MSDOS_MAGIC "\x55\xaa"
37#define MSDOS_PARTTABLE_OFFSET 0x1be
38#define MSDOS_SIG_OFF 0x1fe
39#define BSIZE 0x200
40#define DOS_EXTENDED_PARTITION 0x05
41#define LINUX_EXTENDED_PARTITION 0x85
42#define WIN98_EXTENDED_PARTITION 0x0f
43#define LINUX_RAID_PARTITION 0xfd
44#define is_extended(type) \
45 (type == DOS_EXTENDED_PARTITION || \
46 type == WIN98_EXTENDED_PARTITION || \
47 type == LINUX_EXTENDED_PARTITION)
48#define is_raid(type) \
49 (type == LINUX_RAID_PARTITION)
50
51int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off)
52{
53 const uint8_t *buf;
54 int i;
55 uint64_t poff;
56 uint64_t plen;
57 uint64_t extended = 0;
58 uint64_t current;
59 uint64_t next;
60 int limit;
61 int empty = 1;
62 struct msdos_partition_entry *part;
63 struct volume_id_partition *p;
64
65 dbg("probing at offset 0x%llx", (unsigned long long) off);
66
67 buf = volume_id_get_buffer(id, off, 0x200);
68 if (buf == NULL)
69 return -1;
70
71 if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
72 return -1;
73
74 /* check flags on all entries for a valid partition table */
75 part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
76 for (i = 0; i < 4; i++) {
77 if (part[i].boot_ind != 0 &&
78 part[i].boot_ind != 0x80)
79 return -1;
80
81 if (part[i].nr_sects != 0)
82 empty = 0;
83 }
84 if (empty == 1)
85 return -1;
86
87 if (id->partitions != NULL)
88 free(id->partitions);
89 id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
90 sizeof(struct volume_id_partition));
91 if (id->partitions == NULL)
92 return -1;
93 memset(id->partitions, 0x00,
94 VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
95
96 for (i = 0; i < 4; i++) {
97 poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
98 plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
99
100 if (plen == 0)
101 continue;
102
103 p = &id->partitions[i];
104
105 p->partition_type_raw = part[i].sys_ind;
106
107 if (is_extended(part[i].sys_ind)) {
108 dbg("found extended partition at 0x%llx", (unsigned long long) poff);
109 volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
110 p->type = "msdos_extended_partition";
111 if (extended == 0)
112 extended = off + poff;
113 } else {
114 dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
115 part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
116
117 if (is_raid(part[i].sys_ind))
118 volume_id_set_usage_part(p, VOLUME_ID_RAID);
119 else
120 volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
121 }
122
123 p->off = off + poff;
124 p->len = plen;
125 id->partition_count = i+1;
126 }
127
128 next = extended;
129 current = extended;
130 limit = 50;
131
132 /* follow extended partition chain and add data partitions */
133 while (next != 0) {
134 if (limit-- == 0) {
135 dbg("extended chain limit reached");
136 break;
137 }
138
139 buf = volume_id_get_buffer(id, current, 0x200);
140 if (buf == NULL)
141 break;
142
143 part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
144
145 if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
146 break;
147
148 next = 0;
149
150 for (i = 0; i < 4; i++) {
151 poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
152 plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
153
154 if (plen == 0)
155 continue;
156
157 if (is_extended(part[i].sys_ind)) {
158 dbg("found extended partition at 0x%llx", (unsigned long long) poff);
159 if (next == 0)
160 next = extended + poff;
161 } else {
162 dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
163 part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
164
165 /* we always start at the 5th entry */
166 while (id->partition_count < 4)
167 volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
168
169 p = &id->partitions[id->partition_count];
170
171 if (is_raid(part[i].sys_ind))
172 volume_id_set_usage_part(p, VOLUME_ID_RAID);
173 else
174 volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
175
176 p->off = current + poff;
177 p->len = plen;
178 id->partition_count++;
179
180 p->partition_type_raw = part[i].sys_ind;
181
182 if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
183 dbg("too many partitions");
184 next = 0;
185 }
186 }
187 }
188
189 current = next;
190 }
191
192 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
193 id->type = "msdos_partition_table";
194
195 return 0;
196}
diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c
new file mode 100644
index 000000000..cbd5d5bba
--- /dev/null
+++ b/util-linux/volume_id/ntfs.c
@@ -0,0 +1,193 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ntfs_super_block {
24 uint8_t jump[3];
25 uint8_t oem_id[8];
26 uint16_t bytes_per_sector;
27 uint8_t sectors_per_cluster;
28 uint16_t reserved_sectors;
29 uint8_t fats;
30 uint16_t root_entries;
31 uint16_t sectors;
32 uint8_t media_type;
33 uint16_t sectors_per_fat;
34 uint16_t sectors_per_track;
35 uint16_t heads;
36 uint32_t hidden_sectors;
37 uint32_t large_sectors;
38 uint16_t unused[2];
39 uint64_t number_of_sectors;
40 uint64_t mft_cluster_location;
41 uint64_t mft_mirror_cluster_location;
42 int8_t cluster_per_mft_record;
43 uint8_t reserved1[3];
44 int8_t cluster_per_index_record;
45 uint8_t reserved2[3];
46 uint8_t volume_serial[8];
47 uint16_t checksum;
48} __attribute__((__packed__));
49
50struct master_file_table_record {
51 uint8_t magic[4];
52 uint16_t usa_ofs;
53 uint16_t usa_count;
54 uint64_t lsn;
55 uint16_t sequence_number;
56 uint16_t link_count;
57 uint16_t attrs_offset;
58 uint16_t flags;
59 uint32_t bytes_in_use;
60 uint32_t bytes_allocated;
61} __attribute__((__packed__));
62
63struct file_attribute {
64 uint32_t type;
65 uint32_t len;
66 uint8_t non_resident;
67 uint8_t name_len;
68 uint16_t name_offset;
69 uint16_t flags;
70 uint16_t instance;
71 uint32_t value_len;
72 uint16_t value_offset;
73} __attribute__((__packed__));
74
75struct volume_info {
76 uint64_t reserved;
77 uint8_t major_ver;
78 uint8_t minor_ver;
79} __attribute__((__packed__));
80
81#define MFT_RECORD_VOLUME 3
82#define MFT_RECORD_ATTR_VOLUME_NAME 0x60
83#define MFT_RECORD_ATTR_VOLUME_INFO 0x70
84#define MFT_RECORD_ATTR_OBJECT_ID 0x40
85#define MFT_RECORD_ATTR_END 0xffffffffu
86
87int volume_id_probe_ntfs(struct volume_id *id, uint64_t off)
88{
89 unsigned sector_size;
90 unsigned cluster_size;
91 uint64_t mft_cluster;
92 uint64_t mft_off;
93 unsigned mft_record_size;
94 unsigned attr_type;
95 unsigned attr_off;
96 unsigned attr_len;
97 unsigned val_off;
98 unsigned val_len;
99 struct master_file_table_record *mftr;
100 struct ntfs_super_block *ns;
101 const uint8_t *buf;
102 const uint8_t *val;
103
104 dbg("probing at offset 0x%llx", (unsigned long long) off);
105
106 ns = volume_id_get_buffer(id, off, 0x200);
107 if (ns == NULL)
108 return -1;
109
110 if (memcmp(ns->oem_id, "NTFS", 4) != 0)
111 return -1;
112
113 volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
114
115 sector_size = le16_to_cpu(ns->bytes_per_sector);
116 cluster_size = ns->sectors_per_cluster * sector_size;
117 mft_cluster = le64_to_cpu(ns->mft_cluster_location);
118 mft_off = mft_cluster * cluster_size;
119
120 if (ns->cluster_per_mft_record < 0)
121 /* size = -log2(mft_record_size); normally 1024 Bytes */
122 mft_record_size = 1 << -ns->cluster_per_mft_record;
123 else
124 mft_record_size = ns->cluster_per_mft_record * cluster_size;
125
126 dbg("sectorsize 0x%x", sector_size);
127 dbg("clustersize 0x%x", cluster_size);
128 dbg("mftcluster %llu", (unsigned long long) mft_cluster);
129 dbg("mftoffset 0x%llx", (unsigned long long) mft_off);
130 dbg("cluster per mft_record %i", ns->cluster_per_mft_record);
131 dbg("mft record size %i", mft_record_size);
132
133 buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
134 mft_record_size);
135 if (buf == NULL)
136 goto found;
137
138 mftr = (struct master_file_table_record*) buf;
139
140 dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
141 if (memcmp(mftr->magic, "FILE", 4) != 0)
142 goto found;
143
144 attr_off = le16_to_cpu(mftr->attrs_offset);
145 dbg("file $Volume's attributes are at offset %i", attr_off);
146
147 while (1) {
148 struct file_attribute *attr;
149
150 attr = (struct file_attribute*) &buf[attr_off];
151 attr_type = le32_to_cpu(attr->type);
152 attr_len = le16_to_cpu(attr->len);
153 val_off = le16_to_cpu(attr->value_offset);
154 val_len = le32_to_cpu(attr->value_len);
155 attr_off += attr_len;
156
157 if (attr_len == 0)
158 break;
159
160 if (attr_off >= mft_record_size)
161 break;
162
163 if (attr_type == MFT_RECORD_ATTR_END)
164 break;
165
166 dbg("found attribute type 0x%x, len %i, at offset %i",
167 attr_type, attr_len, attr_off);
168
169 if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
170 struct volume_info *info;
171 dbg("found info, len %i", val_len);
172 info = (struct volume_info*) (((uint8_t *) attr) + val_off);
173 snprintf(id->type_version, sizeof(id->type_version)-1,
174 "%u.%u", info->major_ver, info->minor_ver);
175 }
176
177 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
178 dbg("found label, len %i", val_len);
179 if (val_len > VOLUME_ID_LABEL_SIZE)
180 val_len = VOLUME_ID_LABEL_SIZE;
181
182 val = ((uint8_t *) attr) + val_off;
183 volume_id_set_label_raw(id, val, val_len);
184 volume_id_set_label_unicode16(id, val, LE, val_len);
185 }
186 }
187
188 found:
189 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
190 id->type = "ntfs";
191
192 return 0;
193}
diff --git a/util-linux/volume_id/nvidia_raid.c b/util-linux/volume_id/nvidia_raid.c
new file mode 100644
index 000000000..8619565c9
--- /dev/null
+++ b/util-linux/volume_id/nvidia_raid.c
@@ -0,0 +1,56 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct nvidia_meta {
24 uint8_t vendor[8];
25 uint32_t size;
26 uint32_t chksum;
27 uint16_t version;
28} __attribute__((packed));
29
30#define NVIDIA_SIGNATURE "NVIDIA"
31
32int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size)
33{
34 uint64_t meta_off;
35 struct nvidia_meta *nv;
36
37 dbg("probing at offset 0x%llx, size 0x%llx",
38 (unsigned long long) off, (unsigned long long) size);
39
40 if (size < 0x10000)
41 return -1;
42
43 meta_off = ((size / 0x200)-2) * 0x200;
44 nv = volume_id_get_buffer(id, off + meta_off, 0x200);
45 if (nv == NULL)
46 return -1;
47
48 if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
49 return -1;
50
51 volume_id_set_usage(id, VOLUME_ID_RAID);
52 snprintf(id->type_version, sizeof(id->type_version)-1, "%u", le16_to_cpu(nv->version));
53 id->type = "nvidia_raid_member";
54
55 return 0;
56}
diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c
new file mode 100644
index 000000000..bc490df57
--- /dev/null
+++ b/util-linux/volume_id/ocfs2.c
@@ -0,0 +1,105 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) Andre Masella <andre@masella.no-ip.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23/* All these values are taken from ocfs2-tools's ocfs2_fs.h */
24#define OCFS2_VOL_UUID_LEN 16
25#define OCFS2_MAX_VOL_LABEL_LEN 64
26#define OCFS2_SUPERBLOCK_OFFSET 0x2000
27
28
29/* This is the superblock. The OCFS2 header files have structs in structs.
30This is one has been simplified since we only care about the superblock.
31*/
32
33struct ocfs2_super_block {
34 uint8_t i_signature[8]; /* Signature for validation */
35 uint32_t i_generation; /* Generation number */
36 int16_t i_suballoc_slot; /* Slot suballocator this inode belongs to */
37 uint16_t i_suballoc_bit; /* Bit offset in suballocator block group */
38 uint32_t i_reserved0;
39 uint32_t i_clusters; /* Cluster count */
40 uint32_t i_uid; /* Owner UID */
41 uint32_t i_gid; /* Owning GID */
42 uint64_t i_size; /* Size in bytes */
43 uint16_t i_mode; /* File mode */
44 uint16_t i_links_count; /* Links count */
45 uint32_t i_flags; /* File flags */
46 uint64_t i_atime; /* Access time */
47 uint64_t i_ctime; /* Creation time */
48 uint64_t i_mtime; /* Modification time */
49 uint64_t i_dtime; /* Deletion time */
50 uint64_t i_blkno; /* Offset on disk, in blocks */
51 uint64_t i_last_eb_blk; /* Pointer to last extent block */
52 uint32_t i_fs_generation; /* Generation per fs-instance */
53 uint32_t i_atime_nsec;
54 uint32_t i_ctime_nsec;
55 uint32_t i_mtime_nsec;
56 uint64_t i_reserved1[9];
57 uint64_t i_pad1; /* Generic way to refer to this 64bit union */
58 /* Normally there is a union of the different block types, but we only care about the superblock. */
59 uint16_t s_major_rev_level;
60 uint16_t s_minor_rev_level;
61 uint16_t s_mnt_count;
62 int16_t s_max_mnt_count;
63 uint16_t s_state; /* File system state */
64 uint16_t s_errors; /* Behaviour when detecting errors */
65 uint32_t s_checkinterval; /* Max time between checks */
66 uint64_t s_lastcheck; /* Time of last check */
67 uint32_t s_creator_os; /* OS */
68 uint32_t s_feature_compat; /* Compatible feature set */
69 uint32_t s_feature_incompat; /* Incompatible feature set */
70 uint32_t s_feature_ro_compat; /* Readonly-compatible feature set */
71 uint64_t s_root_blkno; /* Offset, in blocks, of root directory dinode */
72 uint64_t s_system_dir_blkno; /* Offset, in blocks, of system directory dinode */
73 uint32_t s_blocksize_bits; /* Blocksize for this fs */
74 uint32_t s_clustersize_bits; /* Clustersize for this fs */
75 uint16_t s_max_slots; /* Max number of simultaneous mounts before tunefs required */
76 uint16_t s_reserved1;
77 uint32_t s_reserved2;
78 uint64_t s_first_cluster_group; /* Block offset of 1st cluster group header */
79 uint8_t s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
80 uint8_t s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */
81} __attribute__((__packed__));
82
83int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off)
84{
85 struct ocfs2_super_block *os;
86
87 dbg("probing at offset 0x%llx", (unsigned long long) off);
88
89 os = volume_id_get_buffer(id, off + OCFS2_SUPERBLOCK_OFFSET, 0x200);
90 if (os == NULL)
91 return -1;
92
93 if (memcmp(os->i_signature, "OCFSV2", 6) != 0) {
94 return -1;
95 }
96
97 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
98 volume_id_set_label_raw(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
99 OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
100 volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
101 OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
102 volume_id_set_uuid(id, os->s_uuid, UUID_DCE);
103 id->type = "ocfs2";
104 return 0;
105}
diff --git a/util-linux/volume_id/promise_raid.c b/util-linux/volume_id/promise_raid.c
new file mode 100644
index 000000000..9195c637b
--- /dev/null
+++ b/util-linux/volume_id/promise_raid.c
@@ -0,0 +1,63 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct promise_meta {
24 uint8_t sig[24];
25} __attribute__((packed));
26
27#define PDC_CONFIG_OFF 0x1200
28#define PDC_SIGNATURE "Promise Technology, Inc."
29
30int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size)
31{
32 static const unsigned short sectors[] = {
33 63, 255, 256, 16, 399
34 };
35
36 struct promise_meta *pdc;
37 unsigned i;
38
39 dbg("probing at offset 0x%llx, size 0x%llx",
40 (unsigned long long) off, (unsigned long long) size);
41
42 if (size < 0x40000)
43 return -1;
44
45 for (i = 0; i < ARRAY_SIZE(sectors); i++) {
46 uint64_t meta_off;
47
48 meta_off = ((size / 0x200) - sectors[i]) * 0x200;
49 pdc = volume_id_get_buffer(id, off + meta_off, 0x200);
50 if (pdc == NULL)
51 return -1;
52
53 if (memcmp(pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0)
54 goto found;
55 }
56 return -1;
57
58 found:
59 volume_id_set_usage(id, VOLUME_ID_RAID);
60 id->type = "promise_fasttrack_raid_member";
61
62 return 0;
63}
diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c
new file mode 100644
index 000000000..98ecec23a
--- /dev/null
+++ b/util-linux/volume_id/reiserfs.c
@@ -0,0 +1,105 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 * Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "volume_id_internal.h"
23
24struct reiserfs_super_block {
25 uint32_t blocks_count;
26 uint32_t free_blocks;
27 uint32_t root_block;
28 uint32_t journal_block;
29 uint32_t journal_dev;
30 uint32_t orig_journal_size;
31 uint32_t dummy2[5];
32 uint16_t blocksize;
33 uint16_t dummy3[3];
34 uint8_t magic[12];
35 uint32_t dummy4[5];
36 uint8_t uuid[16];
37 uint8_t label[16];
38} __attribute__((__packed__));
39
40struct reiser4_super_block {
41 uint8_t magic[16];
42 uint16_t dummy[2];
43 uint8_t uuid[16];
44 uint8_t label[16];
45 uint64_t dummy2;
46} __attribute__((__packed__));
47
48#define REISERFS1_SUPERBLOCK_OFFSET 0x2000
49#define REISERFS_SUPERBLOCK_OFFSET 0x10000
50
51int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off)
52{
53 struct reiserfs_super_block *rs;
54 struct reiser4_super_block *rs4;
55
56 dbg("probing at offset 0x%llx", (unsigned long long) off);
57
58 rs = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
59 if (rs == NULL)
60 return -1;
61
62 if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
63 strcpy(id->type_version, "3.5");
64 goto found;
65 }
66 if (memcmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
67 strcpy(id->type_version, "3.6");
68 goto found_label;
69 }
70 if (memcmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
71 strcpy(id->type_version, "JR");
72 goto found_label;
73 }
74
75 rs4 = (struct reiser4_super_block *) rs;
76 if (memcmp(rs4->magic, "ReIsEr4", 7) == 0) {
77 strcpy(id->type_version, "4");
78 volume_id_set_label_raw(id, rs4->label, 16);
79 volume_id_set_label_string(id, rs4->label, 16);
80 volume_id_set_uuid(id, rs4->uuid, UUID_DCE);
81 goto found;
82 }
83
84 rs = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
85 if (rs == NULL)
86 return -1;
87
88 if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
89 strcpy(id->type_version, "3.5");
90 goto found;
91 }
92
93 return -1;
94
95 found_label:
96 volume_id_set_label_raw(id, rs->label, 16);
97 volume_id_set_label_string(id, rs->label, 16);
98 volume_id_set_uuid(id, rs->uuid, UUID_DCE);
99
100 found:
101 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
102 id->type = "reiserfs";
103
104 return 0;
105}
diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c
new file mode 100644
index 000000000..7c4fc0f70
--- /dev/null
+++ b/util-linux/volume_id/romfs.c
@@ -0,0 +1,54 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct romfs_super {
24 uint8_t magic[8];
25 uint32_t size;
26 uint32_t checksum;
27 uint8_t name[0];
28} __attribute__((__packed__));
29
30int volume_id_probe_romfs(struct volume_id *id, uint64_t off)
31{
32 struct romfs_super *rfs;
33
34 dbg("probing at offset 0x%llx", (unsigned long long) off);
35
36 rfs = volume_id_get_buffer(id, off, 0x200);
37 if (rfs == NULL)
38 return -1;
39
40 if (memcmp(rfs->magic, "-rom1fs-", 4) == 0) {
41 size_t len = strlen((char *)rfs->name);
42
43 if (len) {
44 volume_id_set_label_raw(id, rfs->name, len);
45 volume_id_set_label_string(id, rfs->name, len);
46 }
47
48 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
49 id->type = "romfs";
50 return 0;
51 }
52
53 return -1;
54}
diff --git a/util-linux/volume_id/silicon_raid.c b/util-linux/volume_id/silicon_raid.c
new file mode 100644
index 000000000..ea001745f
--- /dev/null
+++ b/util-linux/volume_id/silicon_raid.c
@@ -0,0 +1,69 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct silicon_meta {
24 uint8_t unknown0[0x2E];
25 uint8_t ascii_version[0x36 - 0x2E];
26 uint8_t diskname[0x56 - 0x36];
27 uint8_t unknown1[0x60 - 0x56];
28 uint32_t magic;
29 uint32_t unknown1a[0x6C - 0x64];
30 uint32_t array_sectors_low;
31 uint32_t array_sectors_high;
32 uint8_t unknown2[0x78 - 0x74];
33 uint32_t thisdisk_sectors;
34 uint8_t unknown3[0x100 - 0x7C];
35 uint8_t unknown4[0x104 - 0x100];
36 uint16_t product_id;
37 uint16_t vendor_id;
38 uint16_t minor_ver;
39 uint16_t major_ver;
40} __attribute__((packed));
41
42#define SILICON_MAGIC 0x2F000000
43
44int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size)
45{
46 uint64_t meta_off;
47 struct silicon_meta *sil;
48
49 dbg("probing at offset 0x%llx, size 0x%llx",
50 (unsigned long long) off, (unsigned long long) size);
51
52 if (size < 0x10000)
53 return -1;
54
55 meta_off = ((size / 0x200)-1) * 0x200;
56 sil = volume_id_get_buffer(id, off + meta_off, 0x200);
57 if (sil == NULL)
58 return -1;
59
60 if (sil->magic != cpu_to_le32(SILICON_MAGIC))
61 return -1;
62
63 volume_id_set_usage(id, VOLUME_ID_RAID);
64 snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
65 le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
66 id->type = "silicon_medley_raid_member";
67
68 return 0;
69}
diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c
new file mode 100644
index 000000000..71c0fd496
--- /dev/null
+++ b/util-linux/volume_id/sysv.c
@@ -0,0 +1,125 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define SYSV_NICINOD 100
24#define SYSV_NICFREE 50
25
26struct sysv_super
27{
28 uint16_t s_isize;
29 uint16_t s_pad0;
30 uint32_t s_fsize;
31 uint16_t s_nfree;
32 uint16_t s_pad1;
33 uint32_t s_free[SYSV_NICFREE];
34 uint16_t s_ninode;
35 uint16_t s_pad2;
36 uint16_t s_inode[SYSV_NICINOD];
37 uint8_t s_flock;
38 uint8_t s_ilock;
39 uint8_t s_fmod;
40 uint8_t s_ronly;
41 uint32_t s_time;
42 uint16_t s_dinfo[4];
43 uint32_t s_tfree;
44 uint16_t s_tinode;
45 uint16_t s_pad3;
46 uint8_t s_fname[6];
47 uint8_t s_fpack[6];
48 uint32_t s_fill[12];
49 uint32_t s_state;
50 uint32_t s_magic;
51 uint32_t s_type;
52} __attribute__((__packed__));
53
54#define XENIX_NICINOD 100
55#define XENIX_NICFREE 100
56
57struct xenix_super {
58 uint16_t s_isize;
59 uint32_t s_fsize;
60 uint16_t s_nfree;
61 uint32_t s_free[XENIX_NICFREE];
62 uint16_t s_ninode;
63 uint16_t s_inode[XENIX_NICINOD];
64 uint8_t s_flock;
65 uint8_t s_ilock;
66 uint8_t s_fmod;
67 uint8_t s_ronly;
68 uint32_t s_time;
69 uint32_t s_tfree;
70 uint16_t s_tinode;
71 uint16_t s_dinfo[4];
72 uint8_t s_fname[6];
73 uint8_t s_fpack[6];
74 uint8_t s_clean;
75 uint8_t s_fill[371];
76 uint32_t s_magic;
77 uint32_t s_type;
78} __attribute__((__packed__));
79
80#define SYSV_SUPERBLOCK_BLOCK 0x01
81#define SYSV_MAGIC 0xfd187e20
82#define XENIX_SUPERBLOCK_BLOCK 0x18
83#define XENIX_MAGIC 0x2b5544
84#define SYSV_MAX_BLOCKSIZE 0x800
85
86int volume_id_probe_sysv(struct volume_id *id, uint64_t off)
87{
88 struct sysv_super *vs;
89 struct xenix_super *xs;
90 unsigned boff;
91
92 dbg("probing at offset 0x%llx", (unsigned long long) off);
93
94 for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
95 vs = volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
96 if (vs == NULL)
97 return -1;
98
99 if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
100 volume_id_set_label_raw(id, vs->s_fname, 6);
101 volume_id_set_label_string(id, vs->s_fname, 6);
102 id->type = "sysv";
103 goto found;
104 }
105 }
106
107 for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
108 xs = volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
109 if (xs == NULL)
110 return -1;
111
112 if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
113 volume_id_set_label_raw(id, xs->s_fname, 6);
114 volume_id_set_label_string(id, xs->s_fname, 6);
115 id->type = "xenix";
116 goto found;
117 }
118 }
119
120 return -1;
121
122 found:
123 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
124 return 0;
125}
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c
new file mode 100644
index 000000000..5cdb49c31
--- /dev/null
+++ b/util-linux/volume_id/udf.c
@@ -0,0 +1,172 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct volume_descriptor {
24 struct descriptor_tag {
25 uint16_t id;
26 uint16_t version;
27 uint8_t checksum;
28 uint8_t reserved;
29 uint16_t serial;
30 uint16_t crc;
31 uint16_t crc_len;
32 uint32_t location;
33 } __attribute__((__packed__)) tag;
34 union {
35 struct anchor_descriptor {
36 uint32_t length;
37 uint32_t location;
38 } __attribute__((__packed__)) anchor;
39 struct primary_descriptor {
40 uint32_t seq_num;
41 uint32_t desc_num;
42 struct dstring {
43 uint8_t clen;
44 uint8_t c[31];
45 } __attribute__((__packed__)) ident;
46 } __attribute__((__packed__)) primary;
47 } __attribute__((__packed__)) type;
48} __attribute__((__packed__));
49
50struct volume_structure_descriptor {
51 uint8_t type;
52 uint8_t id[5];
53 uint8_t version;
54} __attribute__((__packed__));
55
56#define UDF_VSD_OFFSET 0x8000
57
58int volume_id_probe_udf(struct volume_id *id, uint64_t off)
59{
60 struct volume_descriptor *vd;
61 struct volume_structure_descriptor *vsd;
62 unsigned bs;
63 unsigned b;
64 unsigned type;
65 unsigned count;
66 unsigned loc;
67 unsigned clen;
68
69 dbg("probing at offset 0x%llx", (unsigned long long) off);
70
71 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
72 if (vsd == NULL)
73 return -1;
74
75 if (memcmp(vsd->id, "NSR02", 5) == 0)
76 goto blocksize;
77 if (memcmp(vsd->id, "NSR03", 5) == 0)
78 goto blocksize;
79 if (memcmp(vsd->id, "BEA01", 5) == 0)
80 goto blocksize;
81 if (memcmp(vsd->id, "BOOT2", 5) == 0)
82 goto blocksize;
83 if (memcmp(vsd->id, "CD001", 5) == 0)
84 goto blocksize;
85 if (memcmp(vsd->id, "CDW02", 5) == 0)
86 goto blocksize;
87 if (memcmp(vsd->id, "TEA03", 5) == 0)
88 goto blocksize;
89 return -1;
90
91blocksize:
92 /* search the next VSD to get the logical block size of the volume */
93 for (bs = 0x800; bs < 0x8000; bs += 0x800) {
94 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
95 if (vsd == NULL)
96 return -1;
97 dbg("test for blocksize: 0x%x", bs);
98 if (vsd->id[0] != '\0')
99 goto nsr;
100 }
101 return -1;
102
103nsr:
104 /* search the list of VSDs for a NSR descriptor */
105 for (b = 0; b < 64; b++) {
106 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
107 if (vsd == NULL)
108 return -1;
109
110 dbg("vsd: %c%c%c%c%c",
111 vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
112
113 if (vsd->id[0] == '\0')
114 return -1;
115 if (memcmp(vsd->id, "NSR02", 5) == 0)
116 goto anchor;
117 if (memcmp(vsd->id, "NSR03", 5) == 0)
118 goto anchor;
119 }
120 return -1;
121
122anchor:
123 /* read anchor volume descriptor */
124 vd = volume_id_get_buffer(id, off + (256 * bs), 0x200);
125 if (vd == NULL)
126 return -1;
127
128 type = le16_to_cpu(vd->tag.id);
129 if (type != 2) /* TAG_ID_AVDP */
130 goto found;
131
132 /* get desriptor list address and block count */
133 count = le32_to_cpu(vd->type.anchor.length) / bs;
134 loc = le32_to_cpu(vd->type.anchor.location);
135 dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
136
137 /* pick the primary descriptor from the list */
138 for (b = 0; b < count; b++) {
139 vd = volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
140 if (vd == NULL)
141 return -1;
142
143 type = le16_to_cpu(vd->tag.id);
144 dbg("descriptor type %i", type);
145
146 /* check validity */
147 if (type == 0)
148 goto found;
149 if (le32_to_cpu(vd->tag.location) != loc + b)
150 goto found;
151
152 if (type == 1) /* TAG_ID_PVD */
153 goto pvd;
154 }
155 goto found;
156
157 pvd:
158 volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
159
160 clen = vd->type.primary.ident.clen;
161 dbg("label string charsize=%i bit", clen);
162 if (clen == 8)
163 volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
164 else if (clen == 16)
165 volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE, 31);
166
167 found:
168 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
169 id->type = "udf";
170
171 return 0;
172}
diff --git a/util-linux/volume_id/ufs.c b/util-linux/volume_id/ufs.c
new file mode 100644
index 000000000..768670e9d
--- /dev/null
+++ b/util-linux/volume_id/ufs.c
@@ -0,0 +1,206 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ufs_super_block {
24 uint32_t fs_link;
25 uint32_t fs_rlink;
26 uint32_t fs_sblkno;
27 uint32_t fs_cblkno;
28 uint32_t fs_iblkno;
29 uint32_t fs_dblkno;
30 uint32_t fs_cgoffset;
31 uint32_t fs_cgmask;
32 uint32_t fs_time;
33 uint32_t fs_size;
34 uint32_t fs_dsize;
35 uint32_t fs_ncg;
36 uint32_t fs_bsize;
37 uint32_t fs_fsize;
38 uint32_t fs_frag;
39 uint32_t fs_minfree;
40 uint32_t fs_rotdelay;
41 uint32_t fs_rps;
42 uint32_t fs_bmask;
43 uint32_t fs_fmask;
44 uint32_t fs_bshift;
45 uint32_t fs_fshift;
46 uint32_t fs_maxcontig;
47 uint32_t fs_maxbpg;
48 uint32_t fs_fragshift;
49 uint32_t fs_fsbtodb;
50 uint32_t fs_sbsize;
51 uint32_t fs_csmask;
52 uint32_t fs_csshift;
53 uint32_t fs_nindir;
54 uint32_t fs_inopb;
55 uint32_t fs_nspf;
56 uint32_t fs_optim;
57 uint32_t fs_npsect_state;
58 uint32_t fs_interleave;
59 uint32_t fs_trackskew;
60 uint32_t fs_id[2];
61 uint32_t fs_csaddr;
62 uint32_t fs_cssize;
63 uint32_t fs_cgsize;
64 uint32_t fs_ntrak;
65 uint32_t fs_nsect;
66 uint32_t fs_spc;
67 uint32_t fs_ncyl;
68 uint32_t fs_cpg;
69 uint32_t fs_ipg;
70 uint32_t fs_fpg;
71 struct ufs_csum {
72 uint32_t cs_ndir;
73 uint32_t cs_nbfree;
74 uint32_t cs_nifree;
75 uint32_t cs_nffree;
76 } __attribute__((__packed__)) fs_cstotal;
77 int8_t fs_fmod;
78 int8_t fs_clean;
79 int8_t fs_ronly;
80 int8_t fs_flags;
81 union {
82 struct {
83 int8_t fs_fsmnt[512];
84 uint32_t fs_cgrotor;
85 uint32_t fs_csp[31];
86 uint32_t fs_maxcluster;
87 uint32_t fs_cpc;
88 uint16_t fs_opostbl[16][8];
89 } __attribute__((__packed__)) fs_u1;
90 struct {
91 int8_t fs_fsmnt[468];
92 uint8_t fs_volname[32];
93 uint64_t fs_swuid;
94 int32_t fs_pad;
95 uint32_t fs_cgrotor;
96 uint32_t fs_ocsp[28];
97 uint32_t fs_contigdirs;
98 uint32_t fs_csp;
99 uint32_t fs_maxcluster;
100 uint32_t fs_active;
101 int32_t fs_old_cpc;
102 int32_t fs_maxbsize;
103 int64_t fs_sparecon64[17];
104 int64_t fs_sblockloc;
105 struct ufs2_csum_total {
106 uint64_t cs_ndir;
107 uint64_t cs_nbfree;
108 uint64_t cs_nifree;
109 uint64_t cs_nffree;
110 uint64_t cs_numclusters;
111 uint64_t cs_spare[3];
112 } __attribute__((__packed__)) fs_cstotal;
113 struct ufs_timeval {
114 int32_t tv_sec;
115 int32_t tv_usec;
116 } __attribute__((__packed__)) fs_time;
117 int64_t fs_size;
118 int64_t fs_dsize;
119 uint64_t fs_csaddr;
120 int64_t fs_pendingblocks;
121 int32_t fs_pendinginodes;
122 } __attribute__((__packed__)) fs_u2;
123 } fs_u11;
124 union {
125 struct {
126 int32_t fs_sparecon[53];
127 int32_t fs_reclaim;
128 int32_t fs_sparecon2[1];
129 int32_t fs_state;
130 uint32_t fs_qbmask[2];
131 uint32_t fs_qfmask[2];
132 } __attribute__((__packed__)) fs_sun;
133 struct {
134 int32_t fs_sparecon[53];
135 int32_t fs_reclaim;
136 int32_t fs_sparecon2[1];
137 uint32_t fs_npsect;
138 uint32_t fs_qbmask[2];
139 uint32_t fs_qfmask[2];
140 } __attribute__((__packed__)) fs_sunx86;
141 struct {
142 int32_t fs_sparecon[50];
143 int32_t fs_contigsumsize;
144 int32_t fs_maxsymlinklen;
145 int32_t fs_inodefmt;
146 uint32_t fs_maxfilesize[2];
147 uint32_t fs_qbmask[2];
148 uint32_t fs_qfmask[2];
149 int32_t fs_state;
150 } __attribute__((__packed__)) fs_44;
151 } fs_u2;
152 int32_t fs_postblformat;
153 int32_t fs_nrpos;
154 int32_t fs_postbloff;
155 int32_t fs_rotbloff;
156 uint32_t fs_magic;
157 uint8_t fs_space[1];
158} __attribute__((__packed__));
159
160#define UFS_MAGIC 0x00011954
161#define UFS2_MAGIC 0x19540119
162#define UFS_MAGIC_FEA 0x00195612
163#define UFS_MAGIC_LFN 0x00095014
164
165int volume_id_probe_ufs(struct volume_id *id, uint64_t off)
166{
167 static const short offsets[] = { 0, 8, 64, 256 };
168
169 uint32_t magic;
170 int i;
171 struct ufs_super_block *ufs;
172
173 dbg("probing at offset 0x%llx", (unsigned long long) off);
174
175 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
176 ufs = volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
177 if (ufs == NULL)
178 return -1;
179
180 dbg("offset 0x%x", offsets[i] * 0x400);
181 magic = ufs->fs_magic;
182 if ((magic == cpu_to_be32(UFS_MAGIC))
183 || (magic == cpu_to_be32(UFS2_MAGIC))
184 || (magic == cpu_to_be32(UFS_MAGIC_FEA))
185 || (magic == cpu_to_be32(UFS_MAGIC_LFN))
186 ) {
187 dbg("magic 0x%08x(be)", magic);
188 goto found;
189 }
190 if ((magic == cpu_to_le32(UFS_MAGIC))
191 || (magic == cpu_to_le32(UFS2_MAGIC))
192 || (magic == cpu_to_le32(UFS_MAGIC_FEA))
193 || (magic == cpu_to_le32(UFS_MAGIC_LFN))
194 ) {
195 dbg("magic 0x%08x(le)", magic);
196 goto found;
197 }
198 }
199 return -1;
200
201 found:
202 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
203 id->type = "ufs";
204
205 return 0;
206}
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c
new file mode 100644
index 000000000..d2265c249
--- /dev/null
+++ b/util-linux/volume_id/util.c
@@ -0,0 +1,260 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
24{
25 unsigned i, j;
26 uint16_t c;
27
28 j = 0;
29 for (i = 0; i + 2 <= count; i += 2) {
30 if (endianess == LE)
31 c = (buf[i+1] << 8) | buf[i];
32 else
33 c = (buf[i] << 8) | buf[i+1];
34 if (c == 0) {
35 str[j] = '\0';
36 break;
37 } else if (c < 0x80) {
38 if (j+1 >= len)
39 break;
40 str[j++] = (uint8_t) c;
41 } else if (c < 0x800) {
42 if (j+2 >= len)
43 break;
44 str[j++] = (uint8_t) (0xc0 | (c >> 6));
45 str[j++] = (uint8_t) (0x80 | (c & 0x3f));
46 } else {
47 if (j+3 >= len)
48 break;
49 str[j++] = (uint8_t) (0xe0 | (c >> 12));
50 str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
51 str[j++] = (uint8_t) (0x80 | (c & 0x3f));
52 }
53 }
54 str[j] = '\0';
55}
56
57static const char *usage_to_string(enum volume_id_usage usage_id)
58{
59 switch (usage_id) {
60 case VOLUME_ID_FILESYSTEM:
61 return "filesystem";
62 case VOLUME_ID_PARTITIONTABLE:
63 return "partitiontable";
64 case VOLUME_ID_OTHER:
65 return "other";
66 case VOLUME_ID_RAID:
67 return "raid";
68 case VOLUME_ID_DISKLABEL:
69 return "disklabel";
70 case VOLUME_ID_CRYPTO:
71 return "crypto";
72 case VOLUME_ID_UNPROBED:
73 return "unprobed";
74 case VOLUME_ID_UNUSED:
75 return "unused";
76 }
77 return NULL;
78}
79
80void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id)
81{
82 part->usage_id = usage_id;
83 part->usage = usage_to_string(usage_id);
84}
85
86void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id)
87{
88 id->usage_id = usage_id;
89 id->usage = usage_to_string(usage_id);
90}
91
92void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count)
93{
94 memcpy(id->label_raw, buf, count);
95 id->label_raw_len = count;
96}
97
98#ifdef NOT_NEEDED
99static size_t strnlen(const char *s, size_t maxlen)
100{
101 size_t i;
102 if (!maxlen) return 0;
103 if (!s) return 0;
104 for (i = 0; *s && i < maxlen; ++s) ++i;
105 return i;
106}
107#endif
108
109void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
110{
111 unsigned i;
112
113 memcpy(id->label, buf, count);
114
115 /* remove trailing whitespace */
116 i = strnlen(id->label, count);
117 while (i--) {
118 if (!isspace(id->label[i]))
119 break;
120 }
121 id->label[i+1] = '\0';
122}
123
124void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count)
125{
126 volume_id_set_unicode16(id->label, sizeof(id->label), buf, endianess, count);
127}
128
129void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format)
130{
131 unsigned i;
132 unsigned count = 0;
133
134 switch(format) {
135 case UUID_DOS:
136 count = 4;
137 break;
138 case UUID_NTFS:
139 case UUID_HFS:
140 count = 8;
141 break;
142 case UUID_DCE:
143 count = 16;
144 break;
145 case UUID_DCE_STRING:
146 count = 36;
147 break;
148 }
149 memcpy(id->uuid_raw, buf, count);
150 id->uuid_raw_len = count;
151
152 /* if set, create string in the same format, the native platform uses */
153 for (i = 0; i < count; i++)
154 if (buf[i] != 0)
155 goto set;
156 return;
157
158set:
159 switch(format) {
160 case UUID_DOS:
161 sprintf(id->uuid, "%02X%02X-%02X%02X",
162 buf[3], buf[2], buf[1], buf[0]);
163 break;
164 case UUID_NTFS:
165 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
166 buf[7], buf[6], buf[5], buf[4],
167 buf[3], buf[2], buf[1], buf[0]);
168 break;
169 case UUID_HFS:
170 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
171 buf[0], buf[1], buf[2], buf[3],
172 buf[4], buf[5], buf[6], buf[7]);
173 break;
174 case UUID_DCE:
175 sprintf(id->uuid,
176 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
177 buf[0], buf[1], buf[2], buf[3],
178 buf[4], buf[5],
179 buf[6], buf[7],
180 buf[8], buf[9],
181 buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
182 break;
183 case UUID_DCE_STRING:
184 memcpy(id->uuid, buf, count);
185 id->uuid[count] = '\0';
186 break;
187 }
188}
189
190void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
191{
192 ssize_t buf_len;
193
194 dbg("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len);
195 /* check if requested area fits in superblock buffer */
196 if (off + len <= SB_BUFFER_SIZE) {
197 if (id->sbbuf == NULL) {
198 id->sbbuf = xmalloc(SB_BUFFER_SIZE);
199 }
200
201 /* check if we need to read */
202 if ((off + len) > id->sbbuf_len) {
203 dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len));
204 xlseek(id->fd, 0, SEEK_SET);
205 buf_len = full_read(id->fd, id->sbbuf, off + len);
206 if (buf_len < 0) {
207 dbg("read failed (%s)", strerror(errno));
208 return NULL;
209 }
210 dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
211 id->sbbuf_len = buf_len;
212 if (buf_len < off + len) {
213 dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
214 return NULL;
215 }
216 }
217
218 return &(id->sbbuf[off]);
219 }
220
221 if (len > SEEK_BUFFER_SIZE) {
222 dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
223 return NULL;
224 }
225
226 /* get seek buffer */
227 if (id->seekbuf == NULL) {
228 id->seekbuf = xmalloc(SEEK_BUFFER_SIZE);
229 }
230
231 /* check if we need to read */
232 if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
233 dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len);
234 xlseek(id->fd, off, SEEK_SET);
235 buf_len = full_read(id->fd, id->seekbuf, len);
236 if (buf_len < 0) {
237 dbg("read failed (%s)", strerror(errno));
238 return NULL;
239 }
240 dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
241 id->seekbuf_off = off;
242 id->seekbuf_len = buf_len;
243 if (buf_len < len) {
244 dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
245 return NULL;
246 }
247 }
248
249 return &(id->seekbuf[off - id->seekbuf_off]);
250}
251
252void volume_id_free_buffer(struct volume_id *id)
253{
254 free(id->sbbuf);
255 id->sbbuf = NULL;
256 id->sbbuf_len = 0;
257 free(id->seekbuf);
258 id->seekbuf = NULL;
259 id->seekbuf_len = 0;
260}
diff --git a/util-linux/volume_id/via_raid.c b/util-linux/volume_id/via_raid.c
new file mode 100644
index 000000000..a9bd5b7b9
--- /dev/null
+++ b/util-linux/volume_id/via_raid.c
@@ -0,0 +1,68 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct via_meta {
24 uint16_t signature;
25 uint8_t version_number;
26 struct via_array {
27 uint16_t disk_bits;
28 uint8_t disk_array_ex;
29 uint32_t capacity_low;
30 uint32_t capacity_high;
31 uint32_t serial_checksum;
32 } __attribute((packed)) array;
33 uint32_t serial_checksum[8];
34 uint8_t checksum;
35} __attribute__((packed));
36
37#define VIA_SIGNATURE 0xAA55
38
39int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size)
40{
41 uint64_t meta_off;
42 struct via_meta *via;
43
44 dbg("probing at offset 0x%llx, size 0x%llx",
45 (unsigned long long) off, (unsigned long long) size);
46
47 if (size < 0x10000)
48 return -1;
49
50 meta_off = ((size / 0x200)-1) * 0x200;
51
52 via = volume_id_get_buffer(id, off + meta_off, 0x200);
53 if (via == NULL)
54 return -1;
55
56 if (via->signature != cpu_to_le16(VIA_SIGNATURE))
57 return -1;
58
59 if (via->version_number > 1)
60 return -1;
61
62 volume_id_set_usage(id, VOLUME_ID_RAID);
63 id->type_version[0] = '0' + via->version_number;
64 id->type_version[1] = '\0';
65 id->type = "via_raid_member";
66
67 return 0;
68}
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c
new file mode 100644
index 000000000..809884a41
--- /dev/null
+++ b/util-linux/volume_id/volume_id.c
@@ -0,0 +1,214 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23typedef int (*raid_probe_fptr)(struct volume_id *id, uint64_t off, uint64_t size);
24typedef int (*probe_fptr)(struct volume_id *id, uint64_t off);
25
26static const raid_probe_fptr raid1[] = {
27#if ENABLE_FEATURE_VOLUMEID_LINUXRAID
28 volume_id_probe_linux_raid,
29#endif
30#if ENABLE_FEATURE_VOLUMEID_ISWRAID
31 volume_id_probe_intel_software_raid,
32#endif
33#if ENABLE_FEATURE_VOLUMEID_LSIRAID
34 volume_id_probe_lsi_mega_raid,
35#endif
36#if ENABLE_FEATURE_VOLUMEID_VIARAID
37 volume_id_probe_via_raid,
38#endif
39#if ENABLE_FEATURE_VOLUMEID_SILICONRAID
40 volume_id_probe_silicon_medley_raid,
41#endif
42#if ENABLE_FEATURE_VOLUMEID_NVIDIARAID
43 volume_id_probe_nvidia_raid,
44#endif
45#if ENABLE_FEATURE_VOLUMEID_PROMISERAID
46 volume_id_probe_promise_fasttrack_raid,
47#endif
48#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
49 volume_id_probe_highpoint_45x_raid,
50#endif
51};
52
53static const probe_fptr raid2[] = {
54#if ENABLE_FEATURE_VOLUMEID_LVM
55 volume_id_probe_lvm1,
56 volume_id_probe_lvm2,
57#endif
58#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
59 volume_id_probe_highpoint_37x_raid,
60#endif
61#if ENABLE_FEATURE_VOLUMEID_LUKS
62 volume_id_probe_luks,
63#endif
64};
65
66/* signature in the first block, only small buffer needed */
67static const probe_fptr fs1[] = {
68#if ENABLE_FEATURE_VOLUMEID_FAT
69 volume_id_probe_vfat,
70#endif
71#if ENABLE_FEATURE_VOLUMEID_MAC
72 volume_id_probe_mac_partition_map,
73#endif
74#if ENABLE_FEATURE_VOLUMEID_XFS
75 volume_id_probe_xfs,
76#endif
77};
78
79/* fill buffer with maximum */
80static const probe_fptr fs2[] = {
81#if ENABLE_FEATURE_VOLUMEID_LINUXSWAP
82 volume_id_probe_linux_swap,
83#endif
84#if ENABLE_FEATURE_VOLUMEID_EXT
85 volume_id_probe_ext,
86#endif
87#if ENABLE_FEATURE_VOLUMEID_REISERFS
88 volume_id_probe_reiserfs,
89#endif
90#if ENABLE_FEATURE_VOLUMEID_JFS
91 volume_id_probe_jfs,
92#endif
93#if ENABLE_FEATURE_VOLUMEID_UDF
94 volume_id_probe_udf,
95#endif
96#if ENABLE_FEATURE_VOLUMEID_ISO9660
97 volume_id_probe_iso9660,
98#endif
99#if ENABLE_FEATURE_VOLUMEID_HFS
100 volume_id_probe_hfs_hfsplus,
101#endif
102#if ENABLE_FEATURE_VOLUMEID_UFS
103 volume_id_probe_ufs,
104#endif
105#if ENABLE_FEATURE_VOLUMEID_NTFS
106 volume_id_probe_ntfs,
107#endif
108#if ENABLE_FEATURE_VOLUMEID_CRAMFS
109 volume_id_probe_cramfs,
110#endif
111#if ENABLE_FEATURE_VOLUMEID_ROMFS
112 volume_id_probe_romfs,
113#endif
114#if ENABLE_FEATURE_VOLUMEID_HPFS
115 volume_id_probe_hpfs,
116#endif
117#if ENABLE_FEATURE_VOLUMEID_SYSV
118 volume_id_probe_sysv,
119#endif
120#if ENABLE_FEATURE_VOLUMEID_MINIX
121 volume_id_probe_minix,
122#endif
123#if ENABLE_FEATURE_VOLUMEID_OCFS2
124 volume_id_probe_ocfs2,
125#endif
126};
127
128int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
129{
130 int i;
131
132 if (id == NULL)
133 return -EINVAL;
134
135 /* probe for raid first, cause fs probes may be successful on raid members */
136 if (size) {
137 for (i = 0; i < ARRAY_SIZE(raid1); i++)
138 if (raid1[i](id, off, size) == 0)
139 goto ret;
140 }
141
142 for (i = 0; i < ARRAY_SIZE(raid2); i++)
143 if (raid2[i](id, off) == 0)
144 goto ret;
145
146 /* signature in the first block, only small buffer needed */
147 for (i = 0; i < ARRAY_SIZE(fs1); i++)
148 if (fs1[i](id, off) == 0)
149 goto ret;
150
151 /* fill buffer with maximum */
152 volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);
153
154 for (i = 0; i < ARRAY_SIZE(fs2); i++)
155 if (fs2[i](id, off) == 0)
156 goto ret;
157 return -1;
158
159 ret:
160 /* If the filestystem in recognized, we free the allocated buffers,
161 otherwise they will stay in place for the possible next probe call */
162 volume_id_free_buffer(id);
163
164 return 0;
165}
166
167/* open volume by device node */
168struct volume_id *volume_id_open_node(const char *path)
169{
170 struct volume_id *id;
171 int fd;
172
173 fd = xopen(path, O_RDONLY);
174 id = xzalloc(sizeof(struct volume_id));
175 id->fd = fd;
176 ///* close fd on device close */
177 //id->fd_close = 1;
178
179 return id;
180}
181
182#ifdef UNUSED
183/* open volume by major/minor */
184struct volume_id *volume_id_open_dev_t(dev_t devt)
185{
186 struct volume_id *id;
187 char *tmp_node[VOLUME_ID_PATH_MAX];
188
189 tmp_node = xasprintf("/dev/.volume_id-%u-%u-%u",
190 (unsigned)getpid(), (unsigned)major(devt), (unsigned)minor(devt));
191
192 /* create temporary node to open block device */
193 unlink(tmp_node);
194 if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
195 bb_perror_msg_and_die("cannot mknod(%s)", tmp_node);
196
197 id = volume_id_open_node(tmp_node);
198 unlink(tmp_node);
199 free(tmp_node);
200 return id;
201}
202#endif
203
204void free_volume_id(struct volume_id *id)
205{
206 if (id == NULL)
207 return;
208
209 //if (id->fd_close != 0) - always true
210 close(id->fd);
211 volume_id_free_buffer(id);
212 free(id->partitions);
213 free(id);
214}
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h
new file mode 100644
index 000000000..5a38562f4
--- /dev/null
+++ b/util-linux/volume_id/volume_id_internal.h
@@ -0,0 +1,220 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "libbb.h"
22#include "volume_id.h"
23
24
25#define dbg(...) ((void)0)
26
27
28/* volume_id.h */
29
30#define VOLUME_ID_VERSION 48
31
32#define VOLUME_ID_LABEL_SIZE 64
33#define VOLUME_ID_UUID_SIZE 36
34#define VOLUME_ID_FORMAT_SIZE 32
35#define VOLUME_ID_PARTITIONS_MAX 256
36
37enum volume_id_usage {
38 VOLUME_ID_UNUSED,
39 VOLUME_ID_UNPROBED,
40 VOLUME_ID_OTHER,
41 VOLUME_ID_FILESYSTEM,
42 VOLUME_ID_PARTITIONTABLE,
43 VOLUME_ID_RAID,
44 VOLUME_ID_DISKLABEL,
45 VOLUME_ID_CRYPTO,
46};
47
48struct volume_id_partition {
49 enum volume_id_usage usage_id;
50 const char *usage;
51 const char *type;
52 uint64_t off;
53 uint64_t len;
54 uint8_t partition_type_raw;
55};
56
57struct volume_id {
58 uint8_t label_raw[VOLUME_ID_LABEL_SIZE];
59 size_t label_raw_len;
60 char label[VOLUME_ID_LABEL_SIZE+1];
61 uint8_t uuid_raw[VOLUME_ID_UUID_SIZE];
62 size_t uuid_raw_len;
63 char uuid[VOLUME_ID_UUID_SIZE+1];
64 enum volume_id_usage usage_id;
65 const char *usage;
66 const char *type;
67 char type_version[VOLUME_ID_FORMAT_SIZE];
68
69 struct volume_id_partition *partitions;
70 size_t partition_count;
71
72 int fd;
73 uint8_t *sbbuf;
74 uint8_t *seekbuf;
75 size_t sbbuf_len;
76 uint64_t seekbuf_off;
77 size_t seekbuf_len;
78// int fd_close:1;
79};
80
81struct volume_id *volume_id_open_node(const char *path);
82int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
83void free_volume_id(struct volume_id *id);
84
85/* util.h */
86
87/* size of superblock buffer, reiserfs block is at 64k */
88#define SB_BUFFER_SIZE 0x11000
89/* size of seek buffer, FAT cluster is 32k max */
90#define SEEK_BUFFER_SIZE 0x10000
91
92#define bswap16(x) (uint16_t) ( \
93 (((uint16_t)(x) & 0x00ffu) << 8) | \
94 (((uint16_t)(x) & 0xff00u) >> 8))
95
96#define bswap32(x) (uint32_t) ( \
97 (((uint32_t)(x) & 0xff000000u) >> 24) | \
98 (((uint32_t)(x) & 0x00ff0000u) >> 8) | \
99 (((uint32_t)(x) & 0x0000ff00u) << 8) | \
100 (((uint32_t)(x) & 0x000000ffu) << 24))
101
102#define bswap64(x) (uint64_t) ( \
103 (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
104 (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
105 (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
106 (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
107 (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
108 (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
109 (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
110 (((uint64_t)(x) & 0x00000000000000ffull) << 56))
111
112#if BB_LITTLE_ENDIAN
113#define le16_to_cpu(x) (x)
114#define le32_to_cpu(x) (x)
115#define le64_to_cpu(x) (x)
116#define be16_to_cpu(x) bswap16(x)
117#define be32_to_cpu(x) bswap32(x)
118#define cpu_to_le16(x) (x)
119#define cpu_to_le32(x) (x)
120#define cpu_to_be32(x) bswap32(x)
121#else
122#define le16_to_cpu(x) bswap16(x)
123#define le32_to_cpu(x) bswap32(x)
124#define le64_to_cpu(x) bswap64(x)
125#define be16_to_cpu(x) (x)
126#define be32_to_cpu(x) (x)
127#define cpu_to_le16(x) bswap16(x)
128#define cpu_to_le32(x) bswap32(x)
129#define cpu_to_be32(x) (x)
130#endif
131
132enum uuid_format {
133 UUID_DCE_STRING,
134 UUID_DCE,
135 UUID_DOS,
136 UUID_NTFS,
137 UUID_HFS,
138};
139
140enum endian {
141 LE = 0,
142 BE = 1
143};
144
145void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count);
146void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
147void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id);
148void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count);
149void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count);
150void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count);
151void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format);
152void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len);
153void volume_id_free_buffer(struct volume_id *id);
154
155
156/* Probe routines */
157
158/* RAID */
159
160int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off);
161int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size);
162
163int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size);
164
165int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size);
166
167int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size);
168
169int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size);
170
171int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size);
172
173int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size);
174
175int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size);
176
177int volume_id_probe_lvm1(struct volume_id *id, uint64_t off);
178int volume_id_probe_lvm2(struct volume_id *id, uint64_t off);
179
180/* FS */
181
182int volume_id_probe_cramfs(struct volume_id *id, uint64_t off);
183
184int volume_id_probe_ext(struct volume_id *id, uint64_t off);
185
186int volume_id_probe_vfat(struct volume_id *id, uint64_t off);
187
188int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off);
189
190int volume_id_probe_hpfs(struct volume_id *id, uint64_t off);
191
192int volume_id_probe_iso9660(struct volume_id *id, uint64_t off);
193
194int volume_id_probe_jfs(struct volume_id *id, uint64_t off);
195
196int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off);
197
198int volume_id_probe_luks(struct volume_id *id, uint64_t off);
199
200int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off);
201
202int volume_id_probe_minix(struct volume_id *id, uint64_t off);
203
204int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off);
205
206int volume_id_probe_ntfs(struct volume_id *id, uint64_t off);
207
208int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off);
209
210int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off);
211
212int volume_id_probe_romfs(struct volume_id *id, uint64_t off);
213
214int volume_id_probe_sysv(struct volume_id *id, uint64_t off);
215
216int volume_id_probe_udf(struct volume_id *id, uint64_t off);
217
218int volume_id_probe_ufs(struct volume_id *id, uint64_t off);
219
220int volume_id_probe_xfs(struct volume_id *id, uint64_t off);
diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c
new file mode 100644
index 000000000..343ac7015
--- /dev/null
+++ b/util-linux/volume_id/xfs.c
@@ -0,0 +1,59 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct xfs_super_block {
24 uint8_t magic[4];
25 uint32_t blocksize;
26 uint64_t dblocks;
27 uint64_t rblocks;
28 uint32_t dummy1[2];
29 uint8_t uuid[16];
30 uint32_t dummy2[15];
31 uint8_t fname[12];
32 uint32_t dummy3[2];
33 uint64_t icount;
34 uint64_t ifree;
35 uint64_t fdblocks;
36} __attribute__((__packed__));
37
38int volume_id_probe_xfs(struct volume_id *id, uint64_t off)
39{
40 struct xfs_super_block *xs;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 xs = volume_id_get_buffer(id, off, 0x200);
45 if (xs == NULL)
46 return -1;
47
48 if (memcmp(xs->magic, "XFSB", 4) != 0)
49 return -1;
50
51 volume_id_set_label_raw(id, xs->fname, 12);
52 volume_id_set_label_string(id, xs->fname, 12);
53 volume_id_set_uuid(id, xs->uuid, UUID_DCE);
54
55 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
56 id->type = "xfs";
57
58 return 0;
59}