2 * Copyright (C) 1999 by Andries Brouwer
3 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4 * Copyright (C) 2001 by Andreas Dilger
5 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
8 * Inspired also by libvolume_id by
9 * Kay Sievers <kay.sievers@vrfy.org>
11 * This file may be redistributed under the terms of the
12 * GNU Lesser General Public License.
22 /* PVD - Primary volume descriptor */
23 struct iso_volume_descriptor {
24 unsigned char vd_type;
25 unsigned char vd_id[5];
26 unsigned char vd_version;
28 unsigned char system_id[32];
29 unsigned char volume_id[32];
30 unsigned char unused[8];
31 unsigned char space_size[8];
32 unsigned char escape_sequences[8];
33 } __attribute__((packed));
35 #define ISO_SUPERBLOCK_OFFSET 0x8000
36 #define ISO_SECTOR_SIZE 0x800
37 #define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
38 #define ISO_VD_SUPPLEMENTARY 0x2
39 #define ISO_VD_END 0xff
42 struct high_sierra_volume_descriptor {
46 unsigned char version;
47 unsigned char unused1;
48 unsigned char system_id[32];
49 unsigned char volume_id[32];
50 } __attribute__((packed));
52 /* returns 1 if the begin of @ascii is equal to @utf16 string.
54 static int ascii_eq_utf16be(unsigned char *ascii,
55 unsigned char *utf16, size_t len)
59 for (a = 0, u = 0; u < len; a++, u += 2) {
60 if (utf16[u] != 0x0 || ascii[a] != utf16[u + 1])
66 /* old High Sierra format */
67 static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag)
69 struct high_sierra_volume_descriptor *iso;
71 iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor);
75 blkid_probe_set_version(pr, "High Sierra");
76 blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id));
80 /* iso9660 [+ Microsoft Joliet Extension] */
81 static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
83 struct iso_volume_descriptor *iso;
84 unsigned char label[32];
88 if (strcmp(mag->magic, "CDROM") == 0)
89 return probe_iso9660_hsfs(pr, mag);
91 iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor);
95 memcpy(label, iso->volume_id, sizeof(label));
97 /* Joliet Extension */
99 for (i = 0; i < ISO_VD_MAX; i++) {
100 iso = (struct iso_volume_descriptor *)
101 blkid_probe_get_buffer(pr,
103 sizeof(struct iso_volume_descriptor));
105 if (iso == NULL || iso->vd_type == ISO_VD_END)
107 if (iso->vd_type != ISO_VD_SUPPLEMENTARY)
110 if (memcmp(iso->escape_sequences, "%/@", 3) == 0 ||
111 memcmp(iso->escape_sequences, "%/C", 3) == 0 ||
112 memcmp(iso->escape_sequences, "%/E", 3) == 0) {
114 /* Is the Joliet (UTF16BE) label equal to the label in
115 * the PVD? If yes, use PVD label. The Jolied version
116 * of the label could be trimed (because UTF16..).
118 if (ascii_eq_utf16be(label, iso->volume_id, 32))
121 blkid_probe_set_utf8label(pr,
123 sizeof(iso->volume_id),
126 blkid_probe_set_version(pr, "Joliet Extension");
129 off += ISO_SECTOR_SIZE;
132 /* Joliet not found, let use standard iso label */
133 blkid_probe_set_label(pr, label, sizeof(label));
140 const struct blkid_idinfo iso9660_idinfo =
143 .usage = BLKID_USAGE_FILESYSTEM,
144 .probefunc = probe_iso9660,
145 .flags = BLKID_IDINFO_TOLERANT,
148 { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
149 { .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9 },