/src/util-linux/libblkid/src/superblocks/iso9660.c
Line | Count | Source |
1 | | /* |
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> |
7 | | * |
8 | | * Inspired also by libvolume_id by |
9 | | * Kay Sievers <kay.sievers@vrfy.org> |
10 | | * |
11 | | * This file may be redistributed under the terms of the |
12 | | * GNU Lesser General Public License. |
13 | | */ |
14 | | #include <stdio.h> |
15 | | #include <stdlib.h> |
16 | | #include <unistd.h> |
17 | | #include <string.h> |
18 | | #include <stdint.h> |
19 | | #include <ctype.h> |
20 | | |
21 | | #include "superblocks.h" |
22 | | #include "cctype.h" |
23 | | #include "iso9660.h" |
24 | | |
25 | | struct hs_date { |
26 | | unsigned char year[4]; |
27 | | unsigned char month[2]; |
28 | | unsigned char day[2]; |
29 | | unsigned char hour[2]; |
30 | | unsigned char minute[2]; |
31 | | unsigned char second[2]; |
32 | | unsigned char hundredth[2]; |
33 | | } __attribute__ ((packed)); |
34 | | |
35 | | struct iso9660_date { |
36 | | struct hs_date common; |
37 | | unsigned char offset; |
38 | | } __attribute__ ((packed)); |
39 | | |
40 | | /* PVD - Primary volume descriptor */ |
41 | | struct iso_volume_descriptor { |
42 | | /* High Sierra has 8 bytes before descriptor with Volume Descriptor LBN value, those are skipped by blkid_probe_get_buffer() */ |
43 | | unsigned char vd_type; |
44 | | unsigned char vd_id[5]; |
45 | | unsigned char vd_version; |
46 | | unsigned char flags; |
47 | | unsigned char system_id[32]; |
48 | | unsigned char volume_id[32]; |
49 | | unsigned char unused[8]; |
50 | | unsigned char space_size[8]; |
51 | | unsigned char escape_sequences[32]; |
52 | | unsigned char set_size[4]; |
53 | | unsigned char vol_seq_num[4]; |
54 | | unsigned char logical_block_size[4]; |
55 | | unsigned char path_table_size[8]; |
56 | | union { |
57 | | struct { |
58 | | unsigned char type_l_path_table[4]; |
59 | | unsigned char opt_type_l_path_table[4]; |
60 | | unsigned char type_m_path_table[4]; |
61 | | unsigned char opt_type_m_path_table[4]; |
62 | | unsigned char root_dir_record[34]; |
63 | | unsigned char volume_set_id[128]; |
64 | | unsigned char publisher_id[128]; |
65 | | unsigned char data_preparer_id[128]; |
66 | | unsigned char application_id[128]; |
67 | | unsigned char copyright_file_id[37]; |
68 | | unsigned char abstract_file_id[37]; |
69 | | unsigned char bibliographic_file_id[37]; |
70 | | struct iso9660_date created; |
71 | | struct iso9660_date modified; |
72 | | struct iso9660_date expiration; |
73 | | struct iso9660_date effective; |
74 | | unsigned char std_version; |
75 | | } iso; /* ISO9660 */ |
76 | | struct { |
77 | | unsigned char type_l_path_table[4]; |
78 | | unsigned char opt1_type_l_path_table[4]; |
79 | | unsigned char opt2_type_l_path_table[4]; |
80 | | unsigned char opt3_type_l_path_table[4]; |
81 | | unsigned char type_m_path_table[4]; |
82 | | unsigned char opt1_type_m_path_table[4]; |
83 | | unsigned char opt2_type_m_path_table[4]; |
84 | | unsigned char opt3_type_m_path_table[4]; |
85 | | unsigned char root_dir_record[34]; |
86 | | unsigned char volume_set_id[128]; |
87 | | unsigned char publisher_id[128]; |
88 | | unsigned char data_preparer_id[128]; |
89 | | unsigned char application_id[128]; |
90 | | unsigned char copyright_file_id[32]; |
91 | | unsigned char abstract_file_id[32]; |
92 | | struct hs_date created; |
93 | | struct hs_date modified; |
94 | | struct hs_date expiration; |
95 | | struct hs_date effective; |
96 | | unsigned char std_version; |
97 | | } hs; /* High Sierra */ |
98 | | }; |
99 | | } __attribute__((packed)); |
100 | | |
101 | | /* Boot Record */ |
102 | | struct boot_record { |
103 | | /* High Sierra has 8 bytes before descriptor with Volume Descriptor LBN value, those are skipped by blkid_probe_get_buffer() */ |
104 | | unsigned char vd_type; |
105 | | unsigned char vd_id[5]; |
106 | | unsigned char vd_version; |
107 | | unsigned char boot_system_id[32]; |
108 | | unsigned char boot_id[32]; |
109 | | unsigned char unused[1]; |
110 | | } __attribute__((packed)); |
111 | | |
112 | 402 | #define ISO_SUPERBLOCK_OFFSET 0x8000 |
113 | 5.25k | #define ISO_SECTOR_SIZE 0x800 |
114 | 1.95k | #define ISO_VD_BOOT_RECORD 0x0 |
115 | 3.69k | #define ISO_VD_PRIMARY 0x1 |
116 | 3.29k | #define ISO_VD_SUPPLEMENTARY 0x2 |
117 | 4.93k | #define ISO_VD_END 0xff |
118 | 10.5k | #define ISO_VD_MAX 16 |
119 | | /* maximal string field size used anywhere in ISO; update if necessary */ |
120 | | #define ISO_MAX_FIELDSIZ sizeof_member(struct iso_volume_descriptor, iso.volume_set_id) |
121 | | |
122 | | static int probe_iso9660_set_uuid (blkid_probe pr, const struct hs_date *date, unsigned char offset) |
123 | 237 | { |
124 | 237 | unsigned char buffer[16]; |
125 | 237 | unsigned int i, zeros = 0; |
126 | | |
127 | 237 | buffer[0] = date->year[0]; |
128 | 237 | buffer[1] = date->year[1]; |
129 | 237 | buffer[2] = date->year[2]; |
130 | 237 | buffer[3] = date->year[3]; |
131 | 237 | buffer[4] = date->month[0]; |
132 | 237 | buffer[5] = date->month[1]; |
133 | 237 | buffer[6] = date->day[0]; |
134 | 237 | buffer[7] = date->day[1]; |
135 | 237 | buffer[8] = date->hour[0]; |
136 | 237 | buffer[9] = date->hour[1]; |
137 | 237 | buffer[10] = date->minute[0]; |
138 | 237 | buffer[11] = date->minute[1]; |
139 | 237 | buffer[12] = date->second[0]; |
140 | 237 | buffer[13] = date->second[1]; |
141 | 237 | buffer[14] = date->hundredth[0]; |
142 | 237 | buffer[15] = date->hundredth[1]; |
143 | | |
144 | | /* count the number of zeros ('0') in the date buffer */ |
145 | 4.02k | for (i = 0, zeros = 0; i < sizeof(buffer); i++) |
146 | 3.79k | if (buffer[i] == '0') |
147 | 306 | zeros++; |
148 | | |
149 | | /* due to the iso9660 standard if all date fields are '0' and offset is 0, the date is unset */ |
150 | 237 | if (zeros == sizeof(buffer) && offset == 0) |
151 | 5 | return 0; |
152 | | |
153 | | /* generate an UUID using this date and return success */ |
154 | 232 | blkid_probe_sprintf_uuid (pr, buffer, sizeof(buffer), |
155 | 232 | "%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c", |
156 | 232 | buffer[0], buffer[1], buffer[2], buffer[3], |
157 | 232 | buffer[4], buffer[5], |
158 | 232 | buffer[6], buffer[7], |
159 | 232 | buffer[8], buffer[9], |
160 | 232 | buffer[10], buffer[11], |
161 | 232 | buffer[12], buffer[13], |
162 | 232 | buffer[14], buffer[15]); |
163 | | |
164 | 232 | return 1; |
165 | 237 | } |
166 | | |
167 | | static int is_str_empty(const unsigned char *str, size_t len) |
168 | 699 | { |
169 | 699 | size_t i; |
170 | | |
171 | 699 | if (!str || !*str) |
172 | 195 | return 1; |
173 | | |
174 | 7.27k | for (i = 0; i < len; i++) |
175 | 7.24k | if (!isspace(str[i])) |
176 | 480 | return 0; |
177 | 24 | return 1; |
178 | 504 | } |
179 | | |
180 | | static int is_utf16be_str_empty(unsigned char *utf16, size_t len) |
181 | 213 | { |
182 | 213 | size_t i; |
183 | | |
184 | 238 | for (i = 0; i < len; i += 2) { |
185 | 238 | if (utf16[i] != 0x0 || !isspace(utf16[i + 1])) |
186 | 213 | return 0; |
187 | 238 | } |
188 | 0 | return 1; |
189 | 213 | } |
190 | | |
191 | | /* if @utf16 is prefix of @ascii (ignoring non-representable characters and upper-case conversion) |
192 | | * then reconstruct prefix from @utf16 and @ascii, append suffix from @ascii, fill it into @out |
193 | | * and returns length of bytes written into @out; otherwise returns zero */ |
194 | | static size_t merge_utf16be_ascii(unsigned char *out, size_t out_len, const unsigned char *utf16, const unsigned char *ascii, size_t len) |
195 | 360 | { |
196 | 360 | size_t o, a, u; |
197 | | |
198 | 1.29k | for (o = 0, a = 0, u = 0; u + 1 < len && a < len && o + 1 < out_len; o += 2, a++, u += 2) { |
199 | | /* Surrogate pair with code point above U+FFFF */ |
200 | 1.27k | if (utf16[u] >= 0xD8 && utf16[u] <= 0xDB && u + 3 < len && |
201 | 126 | utf16[u + 2] >= 0xDC && utf16[u + 2] <= 0xDF) { |
202 | 10 | out[o++] = utf16[u++]; |
203 | 10 | out[o++] = utf16[u++]; |
204 | 10 | } |
205 | | /* Value '_' is replacement for non-representable character */ |
206 | 1.27k | if (ascii[a] == '_') { |
207 | 626 | out[o] = utf16[u]; |
208 | 626 | out[o + 1] = utf16[u + 1]; |
209 | 652 | } else if (utf16[u] == 0x00 && utf16[u + 1] == '_') { |
210 | 6 | out[o] = 0x00; |
211 | 6 | out[o + 1] = ascii[a]; |
212 | 646 | } else if (utf16[u] == 0x00 && c_toupper(ascii[a]) == c_toupper(utf16[u + 1])) { |
213 | 302 | out[o] = 0x00; |
214 | 302 | out[o + 1] = c_isupper(ascii[a]) ? utf16[u + 1] : ascii[a]; |
215 | 344 | } else { |
216 | 344 | return 0; |
217 | 344 | } |
218 | 1.27k | } |
219 | | |
220 | 416 | for (; a < len && o + 1 < out_len; o += 2, a++) { |
221 | 400 | out[o] = 0x00; |
222 | 400 | out[o + 1] = ascii[a]; |
223 | 400 | } |
224 | | |
225 | 16 | return o; |
226 | 360 | } |
227 | | |
228 | | /* iso9660 [+ Microsoft Joliet Extension] */ |
229 | | static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag) |
230 | 402 | { |
231 | 402 | struct boot_record *boot = NULL; |
232 | 402 | struct iso_volume_descriptor *pvd = NULL; |
233 | 402 | struct iso_volume_descriptor *joliet = NULL; |
234 | | /* space for merge_utf16be_ascii(ISO_ID_BUFSIZ bytes) */ |
235 | 402 | unsigned char buf[ISO_MAX_FIELDSIZ * 5 / 2]; |
236 | 402 | const struct hs_date *modified; |
237 | 402 | const struct hs_date *created; |
238 | 402 | unsigned char modified_offset; |
239 | 402 | unsigned char created_offset; |
240 | 402 | size_t len; |
241 | 402 | int is_hs; |
242 | 402 | int is_unicode_empty; |
243 | 402 | int is_ascii_hs_empty; |
244 | 402 | int is_ascii_iso_empty; |
245 | 402 | int i; |
246 | 402 | uint64_t off; |
247 | | |
248 | 402 | if (blkid_probe_get_hint(pr, mag->hoff, &off) < 0) |
249 | 402 | off = 0; |
250 | | |
251 | 402 | if (off % ISO_SECTOR_SIZE) |
252 | 0 | return 1; |
253 | | |
254 | 402 | is_hs = (strcmp(mag->magic, "CDROM") == 0); |
255 | | |
256 | 5.25k | for (i = 0, off += ISO_SUPERBLOCK_OFFSET; i < ISO_VD_MAX && (!boot || !pvd || (!is_hs && !joliet)); i++, off += ISO_SECTOR_SIZE) { |
257 | 4.93k | const unsigned char *desc = |
258 | 4.93k | blkid_probe_get_buffer(pr, |
259 | 4.93k | off + (is_hs ? 8 : 0), /* High Sierra has 8 bytes before descriptor with Volume Descriptor LBN value */ |
260 | 4.93k | max(sizeof(struct boot_record), |
261 | 4.93k | sizeof(struct iso_volume_descriptor))); |
262 | | |
263 | 4.93k | if (desc == NULL || desc[0] == ISO_VD_END) |
264 | 78 | break; |
265 | 4.85k | else if (!boot && desc[0] == ISO_VD_BOOT_RECORD) |
266 | 366 | boot = (struct boot_record *)desc; |
267 | 4.48k | else if (!pvd && desc[0] == ISO_VD_PRIMARY) |
268 | 233 | pvd = (struct iso_volume_descriptor *)desc; |
269 | 4.25k | else if (!is_hs && !joliet && desc[0] == ISO_VD_SUPPLEMENTARY) { |
270 | 425 | joliet = (struct iso_volume_descriptor *)desc; |
271 | 425 | if (memcmp(joliet->escape_sequences, "%/@", 3) != 0 && |
272 | 395 | memcmp(joliet->escape_sequences, "%/C", 3) != 0 && |
273 | 360 | memcmp(joliet->escape_sequences, "%/E", 3) != 0) |
274 | 341 | joliet = NULL; |
275 | 425 | } |
276 | 4.93k | } |
277 | | |
278 | 402 | if (!pvd) |
279 | 169 | return errno ? -errno : 1; |
280 | | |
281 | 233 | uint16_t logical_block_size = isonum_723(pvd->logical_block_size, false); |
282 | 233 | uint32_t space_size = isonum_733(pvd->space_size, false); |
283 | | |
284 | 233 | blkid_probe_set_fsblocksize(pr, logical_block_size); |
285 | 233 | blkid_probe_set_block_size(pr, logical_block_size); |
286 | 233 | blkid_probe_set_fssize(pr, (uint64_t) space_size * logical_block_size); |
287 | | |
288 | 233 | if (joliet && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->system_id, pvd->system_id, sizeof(pvd->system_id))) != 0) |
289 | 6 | blkid_probe_set_utf8_id_label(pr, "SYSTEM_ID", buf, len, UL_ENCODE_UTF16BE); |
290 | 227 | else if (joliet) |
291 | 65 | blkid_probe_set_utf8_id_label(pr, "SYSTEM_ID", joliet->system_id, sizeof(joliet->system_id), UL_ENCODE_UTF16BE); |
292 | 162 | else |
293 | 162 | blkid_probe_set_id_label(pr, "SYSTEM_ID", pvd->system_id, sizeof(pvd->system_id)); |
294 | | |
295 | 233 | if (joliet && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->iso.volume_set_id, pvd->iso.volume_set_id, sizeof(pvd->iso.volume_set_id))) != 0) |
296 | 3 | blkid_probe_set_utf8_id_label(pr, "VOLUME_SET_ID", buf, len, UL_ENCODE_UTF16BE); |
297 | 230 | else if (joliet) |
298 | 68 | blkid_probe_set_utf8_id_label(pr, "VOLUME_SET_ID", joliet->iso.volume_set_id, sizeof(joliet->iso.volume_set_id), UL_ENCODE_UTF16BE); |
299 | 162 | else if (is_hs) |
300 | 67 | blkid_probe_set_id_label(pr, "VOLUME_SET_ID", pvd->hs.volume_set_id, sizeof(pvd->hs.volume_set_id)); |
301 | 95 | else |
302 | 95 | blkid_probe_set_id_label(pr, "VOLUME_SET_ID", pvd->iso.volume_set_id, sizeof(pvd->iso.volume_set_id)); |
303 | | |
304 | 233 | is_ascii_hs_empty = (!is_hs || is_str_empty(pvd->hs.publisher_id, sizeof(pvd->hs.publisher_id)) || pvd->hs.publisher_id[0] == '_'); |
305 | 233 | is_ascii_iso_empty = (is_hs || is_str_empty(pvd->iso.publisher_id, sizeof(pvd->iso.publisher_id)) || pvd->iso.publisher_id[0] == '_'); |
306 | 233 | is_unicode_empty = (!joliet || is_utf16be_str_empty(joliet->iso.publisher_id, sizeof(joliet->iso.publisher_id)) || (joliet->iso.publisher_id[0] == 0x00 && joliet->iso.publisher_id[1] == '_')); |
307 | 233 | if (!is_unicode_empty && !is_ascii_iso_empty && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->iso.publisher_id, pvd->iso.publisher_id, sizeof(pvd->iso.publisher_id))) != 0) |
308 | 0 | blkid_probe_set_utf8_id_label(pr, "PUBLISHER_ID", buf, len, UL_ENCODE_UTF16BE); |
309 | 233 | else if (!is_unicode_empty) |
310 | 71 | blkid_probe_set_utf8_id_label(pr, "PUBLISHER_ID", joliet->iso.publisher_id, sizeof(joliet->iso.publisher_id), UL_ENCODE_UTF16BE); |
311 | 162 | else if (!is_ascii_hs_empty) |
312 | 48 | blkid_probe_set_id_label(pr, "PUBLISHER_ID", pvd->hs.publisher_id, sizeof(pvd->hs.publisher_id)); |
313 | 114 | else if (!is_ascii_iso_empty) |
314 | 60 | blkid_probe_set_id_label(pr, "PUBLISHER_ID", pvd->iso.publisher_id, sizeof(pvd->iso.publisher_id)); |
315 | | |
316 | 233 | is_ascii_hs_empty = (!is_hs || is_str_empty(pvd->hs.data_preparer_id, sizeof(pvd->hs.data_preparer_id)) || pvd->hs.data_preparer_id[0] == '_'); |
317 | 233 | is_ascii_iso_empty = (is_hs || is_str_empty(pvd->iso.data_preparer_id, sizeof(pvd->iso.data_preparer_id)) || pvd->iso.data_preparer_id[0] == '_'); |
318 | 233 | is_unicode_empty = (!joliet || is_utf16be_str_empty(joliet->iso.data_preparer_id, sizeof(joliet->iso.data_preparer_id)) || (joliet->iso.data_preparer_id[0] == 0x00 && joliet->iso.data_preparer_id[1] == '_')); |
319 | 233 | if (!is_unicode_empty && !is_ascii_iso_empty && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->iso.data_preparer_id, pvd->iso.data_preparer_id, sizeof(pvd->iso.data_preparer_id))) != 0) |
320 | 0 | blkid_probe_set_utf8_id_label(pr, "DATA_PREPARER_ID", buf, len, UL_ENCODE_UTF16BE); |
321 | 233 | else if (!is_unicode_empty) |
322 | 71 | blkid_probe_set_utf8_id_label(pr, "DATA_PREPARER_ID", joliet->iso.data_preparer_id, sizeof(joliet->iso.data_preparer_id), UL_ENCODE_UTF16BE); |
323 | 162 | else if (!is_ascii_hs_empty) |
324 | 49 | blkid_probe_set_id_label(pr, "DATA_PREPARER_ID", pvd->hs.data_preparer_id, sizeof(pvd->hs.data_preparer_id)); |
325 | 113 | else if (!is_ascii_iso_empty) |
326 | 63 | blkid_probe_set_id_label(pr, "DATA_PREPARER_ID", pvd->iso.data_preparer_id, sizeof(pvd->iso.data_preparer_id)); |
327 | | |
328 | 233 | is_ascii_hs_empty = (!is_hs || is_str_empty(pvd->hs.application_id, sizeof(pvd->hs.application_id)) || pvd->hs.application_id[0] == '_'); |
329 | 233 | is_ascii_iso_empty = (is_hs || is_str_empty(pvd->iso.application_id, sizeof(pvd->iso.application_id)) || pvd->iso.application_id[0] == '_'); |
330 | 233 | is_unicode_empty = (!joliet || is_utf16be_str_empty(joliet->iso.application_id, sizeof(joliet->iso.application_id)) || (joliet->iso.application_id[0] == 0x00 && joliet->iso.application_id[1] == '_')); |
331 | 233 | if (!is_unicode_empty && !is_ascii_iso_empty && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->iso.application_id, pvd->iso.application_id, sizeof(pvd->iso.application_id))) != 0) |
332 | 0 | blkid_probe_set_utf8_id_label(pr, "APPLICATION_ID", buf, len, UL_ENCODE_UTF16BE); |
333 | 233 | else if (!is_unicode_empty) |
334 | 71 | blkid_probe_set_utf8_id_label(pr, "APPLICATION_ID", joliet->iso.application_id, sizeof(joliet->iso.application_id), UL_ENCODE_UTF16BE); |
335 | 162 | else if (!is_ascii_hs_empty) |
336 | 39 | blkid_probe_set_id_label(pr, "APPLICATION_ID", pvd->hs.application_id, sizeof(pvd->hs.application_id)); |
337 | 123 | else if (!is_ascii_iso_empty) |
338 | 56 | blkid_probe_set_id_label(pr, "APPLICATION_ID", pvd->iso.application_id, sizeof(pvd->iso.application_id)); |
339 | | |
340 | 233 | if (is_hs) { |
341 | 67 | modified = &pvd->hs.modified; |
342 | 67 | created = &pvd->hs.created; |
343 | 67 | modified_offset = 0; |
344 | 67 | created_offset = 0; |
345 | 166 | } else { |
346 | 166 | modified = &pvd->iso.modified.common; |
347 | 166 | created = &pvd->iso.created.common; |
348 | 166 | modified_offset = pvd->iso.modified.offset; |
349 | 166 | created_offset = pvd->iso.created.offset; |
350 | 166 | } |
351 | | |
352 | | /* create an UUID using the modified/created date */ |
353 | 233 | if (! probe_iso9660_set_uuid(pr, modified, modified_offset)) |
354 | 4 | probe_iso9660_set_uuid(pr, created, created_offset); |
355 | | |
356 | 233 | if (boot) |
357 | 221 | blkid_probe_set_id_label(pr, "BOOT_SYSTEM_ID", |
358 | 221 | boot->boot_system_id, |
359 | 221 | sizeof(boot->boot_system_id)); |
360 | | |
361 | 233 | if (joliet) |
362 | 71 | blkid_probe_set_version(pr, "Joliet Extension"); |
363 | 162 | else if (is_hs) |
364 | 67 | blkid_probe_set_version(pr, "High Sierra"); |
365 | | |
366 | | /* Label in Joliet is UNICODE (UTF16BE) but can contain only 16 characters. Label in PVD is |
367 | | * subset of ASCII but can contain up to the 32 characters. Non-representable characters are |
368 | | * stored as replacement character '_'. Label in Joliet is in most cases trimmed but UNICODE |
369 | | * version of label in PVD. Based on these facts try to reconstruct original label if label |
370 | | * in Joliet is prefix of the label in PVD (ignoring non-representable characters). |
371 | | */ |
372 | 233 | if (joliet && (len = merge_utf16be_ascii(buf, sizeof(buf), joliet->volume_id, pvd->volume_id, sizeof(pvd->volume_id))) != 0) |
373 | 7 | blkid_probe_set_utf8label(pr, buf, len, UL_ENCODE_UTF16BE); |
374 | 226 | else if (joliet) |
375 | 64 | blkid_probe_set_utf8label(pr, joliet->volume_id, sizeof(joliet->volume_id), UL_ENCODE_UTF16BE); |
376 | 162 | else |
377 | 162 | blkid_probe_set_label(pr, pvd->volume_id, sizeof(pvd->volume_id)); |
378 | | |
379 | 233 | return 0; |
380 | 402 | } |
381 | | |
382 | | const struct blkid_idinfo iso9660_idinfo = |
383 | | { |
384 | | .name = "iso9660", |
385 | | .usage = BLKID_USAGE_FILESYSTEM, |
386 | | .probefunc = probe_iso9660, |
387 | | .flags = BLKID_IDINFO_TOLERANT, |
388 | | .magics = |
389 | | { |
390 | | /* |
391 | | * Due to different location of vd_id[] in ISO9660 and High Sierra, IS9660 can match |
392 | | * also High Sierra vd_id[]. So always check ISO9660 (CD001) before High Sierra (CDROM). |
393 | | */ |
394 | | { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1, .hoff = "session_offset" }, |
395 | | { .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9, .hoff = "session_offset" }, |
396 | | { NULL } |
397 | | } |
398 | | }; |
399 | | |