1 /* udf.c - Universal Disk Format filesystem. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/file.h>
23 #include <grub/misc.h>
24 #include <grub/disk.h>
26 #include <grub/types.h>
27 #include <grub/fshelp.h>
29 #define GRUB_UDF_MAX_PDS 2
30 #define GRUB_UDF_MAX_PMS 6
32 #define U16 grub_le_to_cpu16
33 #define U32 grub_le_to_cpu32
34 #define U64 grub_le_to_cpu64
36 #define GRUB_UDF_LOG2_BLKSZ 2
37 #define GRUB_UDF_BLKSZ 2048
39 #define GRUB_UDF_TAG_IDENT_PVD 0x0001
40 #define GRUB_UDF_TAG_IDENT_AVDP 0x0002
41 #define GRUB_UDF_TAG_IDENT_VDP 0x0003
42 #define GRUB_UDF_TAG_IDENT_IUVD 0x0004
43 #define GRUB_UDF_TAG_IDENT_PD 0x0005
44 #define GRUB_UDF_TAG_IDENT_LVD 0x0006
45 #define GRUB_UDF_TAG_IDENT_USD 0x0007
46 #define GRUB_UDF_TAG_IDENT_TD 0x0008
47 #define GRUB_UDF_TAG_IDENT_LVID 0x0009
49 #define GRUB_UDF_TAG_IDENT_FSD 0x0100
50 #define GRUB_UDF_TAG_IDENT_FID 0x0101
51 #define GRUB_UDF_TAG_IDENT_AED 0x0102
52 #define GRUB_UDF_TAG_IDENT_IE 0x0103
53 #define GRUB_UDF_TAG_IDENT_TE 0x0104
54 #define GRUB_UDF_TAG_IDENT_FE 0x0105
55 #define GRUB_UDF_TAG_IDENT_EAHD 0x0106
56 #define GRUB_UDF_TAG_IDENT_USE 0x0107
57 #define GRUB_UDF_TAG_IDENT_SBD 0x0108
58 #define GRUB_UDF_TAG_IDENT_PIE 0x0109
59 #define GRUB_UDF_TAG_IDENT_EFE 0x010A
61 #define GRUB_UDF_ICBTAG_TYPE_UNDEF 0x00
62 #define GRUB_UDF_ICBTAG_TYPE_USE 0x01
63 #define GRUB_UDF_ICBTAG_TYPE_PIE 0x02
64 #define GRUB_UDF_ICBTAG_TYPE_IE 0x03
65 #define GRUB_UDF_ICBTAG_TYPE_DIRECTORY 0x04
66 #define GRUB_UDF_ICBTAG_TYPE_REGULAR 0x05
67 #define GRUB_UDF_ICBTAG_TYPE_BLOCK 0x06
68 #define GRUB_UDF_ICBTAG_TYPE_CHAR 0x07
69 #define GRUB_UDF_ICBTAG_TYPE_EA 0x08
70 #define GRUB_UDF_ICBTAG_TYPE_FIFO 0x09
71 #define GRUB_UDF_ICBTAG_TYPE_SOCKET 0x0A
72 #define GRUB_UDF_ICBTAG_TYPE_TE 0x0B
73 #define GRUB_UDF_ICBTAG_TYPE_SYMLINK 0x0C
74 #define GRUB_UDF_ICBTAG_TYPE_STREAMDIR 0x0D
76 #define GRUB_UDF_ICBTAG_FLAG_AD_MASK 0x0007
77 #define GRUB_UDF_ICBTAG_FLAG_AD_SHORT 0x0000
78 #define GRUB_UDF_ICBTAG_FLAG_AD_LONG 0x0001
79 #define GRUB_UDF_ICBTAG_FLAG_AD_EXT 0x0002
80 #define GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB 0x0003
82 #define GRUB_UDF_EXT_NORMAL 0x00000000
83 #define GRUB_UDF_EXT_NREC_ALLOC 0x40000000
84 #define GRUB_UDF_EXT_NREC_NALLOC 0x80000000
85 #define GRUB_UDF_EXT_MASK 0xC0000000
87 #define GRUB_UDF_FID_CHAR_HIDDEN 0x01
88 #define GRUB_UDF_FID_CHAR_DIRECTORY 0x02
89 #define GRUB_UDF_FID_CHAR_DELETED 0x04
90 #define GRUB_UDF_FID_CHAR_PARENT 0x08
91 #define GRUB_UDF_FID_CHAR_METADATA 0x10
93 #define GRUB_UDF_STD_IDENT_BEA01 "BEA01"
94 #define GRUB_UDF_STD_IDENT_BOOT2 "BOOT2"
95 #define GRUB_UDF_STD_IDENT_CD001 "CD001"
96 #define GRUB_UDF_STD_IDENT_CDW02 "CDW02"
97 #define GRUB_UDF_STD_IDENT_NSR02 "NSR02"
98 #define GRUB_UDF_STD_IDENT_NSR03 "NSR03"
99 #define GRUB_UDF_STD_IDENT_TEA01 "TEA01"
101 #define GRUB_UDF_CHARSPEC_TYPE_CS0 0x00
102 #define GRUB_UDF_CHARSPEC_TYPE_CS1 0x01
103 #define GRUB_UDF_CHARSPEC_TYPE_CS2 0x02
104 #define GRUB_UDF_CHARSPEC_TYPE_CS3 0x03
105 #define GRUB_UDF_CHARSPEC_TYPE_CS4 0x04
106 #define GRUB_UDF_CHARSPEC_TYPE_CS5 0x05
107 #define GRUB_UDF_CHARSPEC_TYPE_CS6 0x06
108 #define GRUB_UDF_CHARSPEC_TYPE_CS7 0x07
109 #define GRUB_UDF_CHARSPEC_TYPE_CS8 0x08
111 #define GRUB_UDF_PARTMAP_TYPE_1 1
112 #define GRUB_UDF_PARTMAP_TYPE_2 2
114 struct grub_udf_lb_addr
116 grub_uint32_t block_num
;
117 grub_uint16_t part_ref
;
118 } __attribute__ ((packed
));
120 struct grub_udf_short_ad
122 grub_uint32_t length
;
123 grub_uint32_t position
;
124 } __attribute__ ((packed
));
126 struct grub_udf_long_ad
128 grub_uint32_t length
;
129 struct grub_udf_lb_addr block
;
130 grub_uint8_t imp_use
[6];
131 } __attribute__ ((packed
));
133 struct grub_udf_extent_ad
135 grub_uint32_t length
;
137 } __attribute__ ((packed
));
139 struct grub_udf_charspec
141 grub_uint8_t charset_type
;
142 grub_uint8_t charset_info
[63];
143 } __attribute__ ((packed
));
145 struct grub_udf_timestamp
147 grub_uint16_t type_and_timezone
;
154 grub_uint8_t centi_seconds
;
155 grub_uint8_t hundreds_of_micro_seconds
;
156 grub_uint8_t micro_seconds
;
157 } __attribute__ ((packed
));
159 struct grub_udf_regid
162 grub_uint8_t ident
[23];
163 grub_uint8_t ident_suffix
[8];
164 } __attribute__ ((packed
));
168 grub_uint16_t tag_ident
;
169 grub_uint16_t desc_version
;
170 grub_uint8_t tag_checksum
;
171 grub_uint8_t reserved
;
172 grub_uint16_t tag_serial_number
;
173 grub_uint16_t desc_crc
;
174 grub_uint16_t desc_crc_length
;
175 grub_uint32_t tag_location
;
176 } __attribute__ ((packed
));
178 struct grub_udf_fileset
180 struct grub_udf_tag tag
;
181 struct grub_udf_timestamp datetime
;
182 grub_uint16_t interchange_level
;
183 grub_uint16_t max_interchange_level
;
184 grub_uint32_t charset_list
;
185 grub_uint32_t max_charset_list
;
186 grub_uint32_t fileset_num
;
187 grub_uint32_t fileset_desc_num
;
188 struct grub_udf_charspec vol_charset
;
189 grub_uint8_t vol_ident
[128];
190 struct grub_udf_charspec fileset_charset
;
191 grub_uint8_t fileset_ident
[32];
192 grub_uint8_t copyright_file_ident
[32];
193 grub_uint8_t abstract_file_ident
[32];
194 struct grub_udf_long_ad root_icb
;
195 struct grub_udf_regid domain_ident
;
196 struct grub_udf_long_ad next_ext
;
197 struct grub_udf_long_ad streamdir_icb
;
198 } __attribute__ ((packed
));
200 struct grub_udf_icbtag
202 grub_uint32_t prior_recorded_num_direct_entries
;
203 grub_uint16_t strategy_type
;
204 grub_uint16_t strategy_parameter
;
205 grub_uint16_t num_entries
;
206 grub_uint8_t reserved
;
207 grub_uint8_t file_type
;
208 struct grub_udf_lb_addr parent_idb
;
210 } __attribute__ ((packed
));
212 struct grub_udf_file_ident
214 struct grub_udf_tag tag
;
215 grub_uint16_t version_num
;
216 grub_uint8_t characteristics
;
217 grub_uint8_t file_ident_length
;
218 struct grub_udf_long_ad icb
;
219 grub_uint16_t imp_use_length
;
220 } __attribute__ ((packed
));
222 struct grub_udf_file_entry
224 struct grub_udf_tag tag
;
225 struct grub_udf_icbtag icbtag
;
228 grub_uint32_t permissions
;
229 grub_uint16_t link_count
;
230 grub_uint8_t record_format
;
231 grub_uint8_t record_display_attr
;
232 grub_uint32_t record_length
;
233 grub_uint64_t file_size
;
234 grub_uint64_t blocks_recorded
;
235 struct grub_udf_timestamp access_time
;
236 struct grub_udf_timestamp modification_time
;
237 struct grub_udf_timestamp attr_time
;
238 grub_uint32_t checkpoint
;
239 struct grub_udf_long_ad extended_attr_idb
;
240 struct grub_udf_regid imp_ident
;
241 grub_uint64_t unique_id
;
242 grub_uint32_t ext_attr_length
;
243 grub_uint32_t alloc_descs_length
;
244 grub_uint8_t ext_attr
[1872];
245 } __attribute__ ((packed
));
247 struct grub_udf_extended_file_entry
249 struct grub_udf_tag tag
;
250 struct grub_udf_icbtag icbtag
;
253 grub_uint32_t permissions
;
254 grub_uint16_t link_count
;
255 grub_uint8_t record_format
;
256 grub_uint8_t record_display_attr
;
257 grub_uint32_t record_length
;
258 grub_uint64_t file_size
;
259 grub_uint64_t object_size
;
260 grub_uint64_t blocks_recorded
;
261 struct grub_udf_timestamp access_time
;
262 struct grub_udf_timestamp modification_time
;
263 struct grub_udf_timestamp create_time
;
264 struct grub_udf_timestamp attr_time
;
265 grub_uint32_t checkpoint
;
266 grub_uint32_t reserved
;
267 struct grub_udf_long_ad extended_attr_icb
;
268 struct grub_udf_long_ad streamdir_icb
;
269 struct grub_udf_regid imp_ident
;
270 grub_uint64_t unique_id
;
271 grub_uint32_t ext_attr_length
;
272 grub_uint32_t alloc_descs_length
;
273 grub_uint8_t ext_attr
[1832];
274 } __attribute__ ((packed
));
279 grub_uint8_t magic
[5];
280 grub_uint8_t version
;
281 } __attribute__ ((packed
));
285 struct grub_udf_tag tag
;
286 struct grub_udf_extent_ad vds
;
287 } __attribute__ ((packed
));
291 struct grub_udf_tag tag
;
292 grub_uint32_t seq_num
;
294 grub_uint16_t part_num
;
295 struct grub_udf_regid contents
;
296 grub_uint8_t contents_use
[128];
297 grub_uint32_t access_type
;
299 grub_uint32_t length
;
300 } __attribute__ ((packed
));
302 struct grub_udf_partmap
310 grub_uint16_t seq_num
;
311 grub_uint16_t part_num
;
316 grub_uint8_t ident
[62];
323 struct grub_udf_tag tag
;
324 grub_uint32_t seq_num
;
325 struct grub_udf_charspec charset
;
326 grub_uint8_t ident
[128];
328 struct grub_udf_regid domain_ident
;
329 struct grub_udf_long_ad root_fileset
;
330 grub_uint32_t map_table_length
;
331 grub_uint32_t num_part_maps
;
332 struct grub_udf_regid imp_ident
;
333 grub_uint8_t imp_use
[128];
334 struct grub_udf_extent_ad integrity_seq_ext
;
335 grub_uint8_t part_maps
[1608];
336 } __attribute__ ((packed
));
341 struct grub_udf_lvd lvd
;
342 struct grub_udf_pd pds
[GRUB_UDF_MAX_PDS
];
343 struct grub_udf_partmap
*pms
[GRUB_UDF_MAX_PMS
];
344 struct grub_udf_long_ad root_icb
;
348 struct grub_fshelp_node
350 struct grub_udf_data
*data
;
353 struct grub_udf_file_entry fe
;
354 struct grub_udf_extended_file_entry efe
;
359 static grub_dl_t my_mod
;
362 grub_udf_get_block (struct grub_udf_data
*data
,
363 grub_uint16_t part_ref
, grub_uint32_t block
)
365 part_ref
= U16 (part_ref
);
367 if (part_ref
>= data
->npm
)
369 grub_error (GRUB_ERR_BAD_FS
, "invalid part ref");
373 return (U32 (data
->pds
[data
->pms
[part_ref
]->type1
.part_num
].start
)
378 grub_udf_read_icb (struct grub_udf_data
*data
,
379 struct grub_udf_long_ad
*icb
,
380 struct grub_fshelp_node
*node
)
384 block
= grub_udf_get_block (data
,
386 icb
->block
.block_num
);
391 if (grub_disk_read (data
->disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
392 sizeof (struct grub_udf_file_entry
),
396 if ((U16 (node
->fe
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FE
) &&
397 (U16 (node
->fe
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_EFE
))
398 return grub_error (GRUB_ERR_BAD_FS
, "invalid fe/efe descriptor");
400 node
->part_ref
= icb
->block
.part_ref
;
405 static grub_disk_addr_t
406 grub_udf_read_block (grub_fshelp_node_t node
, grub_disk_addr_t fileblock
)
411 if (U16 (node
->fe
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_FE
)
413 ptr
= (char *) &node
->fe
.ext_attr
[0] + U32 (node
->fe
.ext_attr_length
);
414 len
= U32 (node
->fe
.alloc_descs_length
);
418 ptr
= (char *) &node
->efe
.ext_attr
[0] + U32 (node
->efe
.ext_attr_length
);
419 len
= U32 (node
->efe
.alloc_descs_length
);
422 if ((U16 (node
->fe
.icbtag
.flags
) & GRUB_UDF_ICBTAG_FLAG_AD_MASK
)
423 == GRUB_UDF_ICBTAG_FLAG_AD_SHORT
)
425 struct grub_udf_short_ad
*ad
= (struct grub_udf_short_ad
*) ptr
;
427 len
/= sizeof (struct grub_udf_short_ad
);
430 if (fileblock
< U32 (ad
->length
))
431 return ((U32 (ad
->position
) & GRUB_UDF_EXT_MASK
) ? 0 :
432 (grub_udf_get_block (node
->data
,
437 fileblock
-= U32 (ad
->length
);
444 struct grub_udf_long_ad
*ad
= (struct grub_udf_long_ad
*) ptr
;
446 len
/= sizeof (struct grub_udf_long_ad
);
449 if (fileblock
< U32 (ad
->length
))
450 return ((U32 (ad
->block
.block_num
) & GRUB_UDF_EXT_MASK
) ? 0 :
451 (grub_udf_get_block (node
->data
,
456 fileblock
-= U32 (ad
->length
);
466 grub_udf_read_file (grub_fshelp_node_t node
,
467 void NESTED_FUNC_ATTR
468 (*read_hook
) (grub_disk_addr_t sector
,
469 unsigned offset
, unsigned length
),
470 int pos
, grub_size_t len
, char *buf
)
472 switch (U16 (node
->fe
.icbtag
.flags
) & GRUB_UDF_ICBTAG_FLAG_AD_MASK
)
474 case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB
:
478 ptr
= ((U16 (node
->fe
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_FE
) ?
479 ((char *) &node
->fe
.ext_attr
[0]
480 + U32 (node
->fe
.ext_attr_length
)) :
481 ((char *) &node
->efe
.ext_attr
[0]
482 + U32 (node
->efe
.ext_attr_length
)));
484 grub_memcpy (buf
, ptr
+ pos
, len
);
489 case GRUB_UDF_ICBTAG_FLAG_AD_EXT
:
490 grub_error (GRUB_ERR_BAD_FS
, "invalid extent type");
494 return grub_fshelp_read_file (node
->data
->disk
, node
, read_hook
,
495 pos
, len
, buf
, grub_udf_read_block
,
496 U64 (node
->fe
.file_size
),
497 GRUB_UDF_LOG2_BLKSZ
);
500 static int sblocklist
[] = { 256, 512, 0 };
502 static struct grub_udf_data
*
503 grub_udf_mount (grub_disk_t disk
)
505 struct grub_udf_data
*data
= 0;
506 struct grub_udf_fileset root_fs
;
507 int *sblklist
= sblocklist
;
511 data
= grub_malloc (sizeof (struct grub_udf_data
));
517 /* Search for Volume Recognition Sequence (VRS). */
518 for (block
= 16;; block
++)
520 struct grub_udf_vrs vrs
;
522 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
523 sizeof (struct grub_udf_vrs
), &vrs
))
525 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
529 if ((!grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_NSR03
, 5)) ||
530 (!grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_NSR02
, 5)))
533 if ((grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_BEA01
, 5)) &&
534 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_BOOT2
, 5)) &&
535 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_CD001
, 5)) &&
536 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_CDW02
, 5)) &&
537 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_TEA01
, 5)))
539 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
544 /* Search for Anchor Volume Descriptor Pointer (AVDP). */
547 struct grub_udf_avdp avdp
;
549 if (grub_disk_read (disk
, *sblklist
<< GRUB_UDF_LOG2_BLKSZ
, 0,
550 sizeof (struct grub_udf_avdp
), &avdp
))
552 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
556 if (U16 (avdp
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_AVDP
)
558 block
= U32 (avdp
.vds
.start
);
565 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
570 data
->npd
= data
->npm
= 0;
571 /* Locate Partition Descriptor (PD) and Logical Volume Descriptor (LVD). */
574 struct grub_udf_tag tag
;
576 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
577 sizeof (struct grub_udf_tag
), &tag
))
579 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
583 tag
.tag_ident
= U16 (tag
.tag_ident
);
584 if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_PD
)
586 if (data
->npd
>= GRUB_UDF_MAX_PDS
)
588 grub_error (GRUB_ERR_BAD_FS
, "too many PDs");
592 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
593 sizeof (struct grub_udf_pd
),
594 &data
->pds
[data
->npd
]))
596 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
602 else if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_LVD
)
606 struct grub_udf_partmap
*ppm
;
608 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
609 sizeof (struct grub_udf_lvd
),
612 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
616 if (data
->npm
+ U32 (data
->lvd
.num_part_maps
) > GRUB_UDF_MAX_PMS
)
618 grub_error (GRUB_ERR_BAD_FS
, "too many partition maps");
622 ppm
= (struct grub_udf_partmap
*) &data
->lvd
.part_maps
;
623 for (k
= U32 (data
->lvd
.num_part_maps
); k
> 0; k
--)
625 if (ppm
->type
!= GRUB_UDF_PARTMAP_TYPE_1
)
627 grub_error (GRUB_ERR_BAD_FS
, "partmap type not supported");
631 data
->pms
[data
->npm
++] = ppm
;
632 ppm
= (struct grub_udf_partmap
*) ((char *) ppm
+
636 else if (tag
.tag_ident
> GRUB_UDF_TAG_IDENT_TD
)
638 grub_error (GRUB_ERR_BAD_FS
, "invalid tag ident");
641 else if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_TD
)
647 for (i
= 0; i
< data
->npm
; i
++)
651 for (j
= 0; j
< data
->npd
; j
++)
652 if (data
->pms
[i
]->type1
.part_num
== data
->pds
[j
].part_num
)
654 data
->pms
[i
]->type1
.part_num
= j
;
660 grub_error (GRUB_ERR_BAD_FS
, "can\'t find PD");
665 block
= grub_udf_get_block (data
,
666 data
->lvd
.root_fileset
.block
.part_ref
,
667 data
->lvd
.root_fileset
.block
.block_num
);
672 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
673 sizeof (struct grub_udf_fileset
), &root_fs
))
675 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
679 if (U16 (root_fs
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FSD
)
681 grub_error (GRUB_ERR_BAD_FS
, "invalid fileset descriptor");
685 data
->root_icb
= root_fs
.root_icb
;
695 grub_udf_iterate_dir (grub_fshelp_node_t dir
,
697 (*hook
) (const char *filename
,
698 enum grub_fshelp_filetype filetype
,
699 grub_fshelp_node_t node
))
701 grub_fshelp_node_t child
;
702 struct grub_udf_file_ident dirent
;
703 grub_uint32_t offset
= 0;
705 child
= grub_malloc (sizeof (struct grub_fshelp_node
));
709 /* The current directory is not stored. */
710 grub_memcpy ((char *) child
, (char *) dir
,
711 sizeof (struct grub_fshelp_node
));
713 if (hook (".", GRUB_FSHELP_DIR
, child
))
716 while (offset
< U64 (dir
->fe
.file_size
))
718 if (grub_udf_read_file (dir
, 0, offset
, sizeof (dirent
),
719 (char *) &dirent
) != sizeof (dirent
))
722 if (U16 (dirent
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FID
)
724 grub_error (GRUB_ERR_BAD_FS
, "invalid fid tag");
728 child
= grub_malloc (sizeof (struct grub_fshelp_node
));
732 if (grub_udf_read_icb (dir
->data
, &dirent
.icb
, child
))
735 offset
+= sizeof (dirent
) + U16 (dirent
.imp_use_length
);
736 if (dirent
.characteristics
& GRUB_UDF_FID_CHAR_PARENT
)
738 /* This is the parent directory. */
739 if (hook ("..", GRUB_FSHELP_DIR
, child
))
744 enum grub_fshelp_filetype type
;
745 char filename
[dirent
.file_ident_length
+ 1];
747 type
= ((dirent
.characteristics
& GRUB_UDF_FID_CHAR_DIRECTORY
) ?
748 (GRUB_FSHELP_DIR
) : (GRUB_FSHELP_REG
));
750 if ((grub_udf_read_file (dir
, 0, offset
,
751 dirent
.file_ident_length
, filename
))
752 != dirent
.file_ident_length
)
755 filename
[dirent
.file_ident_length
] = 0;
756 if (hook (&filename
[1], type
, child
))
760 /* Align to dword boundary. */
761 offset
= (offset
+ dirent
.file_ident_length
+ 3) & (~3);
768 grub_udf_dir (grub_device_t device
, const char *path
,
769 int (*hook
) (const char *filename
,
770 const struct grub_dirhook_info
*info
))
772 struct grub_udf_data
*data
= 0;
773 struct grub_fshelp_node rootnode
;
774 struct grub_fshelp_node
*foundnode
;
776 auto int NESTED_FUNC_ATTR
iterate (const char *filename
,
777 enum grub_fshelp_filetype filetype
,
778 grub_fshelp_node_t node
);
780 int NESTED_FUNC_ATTR
iterate (const char *filename
,
781 enum grub_fshelp_filetype filetype
,
782 grub_fshelp_node_t node
)
784 struct grub_dirhook_info info
;
785 grub_memset (&info
, 0, sizeof (info
));
786 info
.dir
= ((filetype
& GRUB_FSHELP_TYPE_MASK
) == GRUB_FSHELP_DIR
);
788 return hook (filename
, &info
);
791 grub_dl_ref (my_mod
);
793 data
= grub_udf_mount (device
->disk
);
797 if (grub_udf_read_icb (data
, &data
->root_icb
, &rootnode
))
800 if (grub_fshelp_find_file (path
, &rootnode
,
802 grub_udf_iterate_dir
, 0, GRUB_FSHELP_DIR
))
805 grub_udf_iterate_dir (foundnode
, iterate
);
807 if (foundnode
!= &rootnode
)
808 grub_free (foundnode
);
813 grub_dl_unref (my_mod
);
819 grub_udf_open (struct grub_file
*file
, const char *name
)
821 struct grub_udf_data
*data
;
822 struct grub_fshelp_node rootnode
;
823 struct grub_fshelp_node
*foundnode
;
825 grub_dl_ref (my_mod
);
827 data
= grub_udf_mount (file
->device
->disk
);
831 if (grub_udf_read_icb (data
, &data
->root_icb
, &rootnode
))
834 if (grub_fshelp_find_file (name
, &rootnode
,
836 grub_udf_iterate_dir
, 0, GRUB_FSHELP_REG
))
839 file
->data
= foundnode
;
841 file
->size
= U64 (foundnode
->fe
.file_size
);
846 grub_dl_unref (my_mod
);
854 grub_udf_read (grub_file_t file
, char *buf
, grub_size_t len
)
856 struct grub_fshelp_node
*node
= (struct grub_fshelp_node
*) file
->data
;
858 return grub_udf_read_file (node
, file
->read_hook
, file
->offset
, len
, buf
);
862 grub_udf_close (grub_file_t file
)
866 struct grub_fshelp_node
*node
= (struct grub_fshelp_node
*) file
->data
;
868 grub_free (node
->data
);
872 grub_dl_unref (my_mod
);
874 return GRUB_ERR_NONE
;
878 grub_udf_label (grub_device_t device
, char **label
)
880 struct grub_udf_data
*data
;
881 data
= grub_udf_mount (device
->disk
);
885 *label
= grub_strdup ((char *) &data
->lvd
.ident
[1]);
894 static struct grub_fs grub_udf_fs
= {
897 .open
= grub_udf_open
,
898 .read
= grub_udf_read
,
899 .close
= grub_udf_close
,
900 .label
= grub_udf_label
,
906 grub_fs_register (&grub_udf_fs
);
912 grub_fs_unregister (&grub_udf_fs
);