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
;
360 static grub_dl_t my_mod
;
364 grub_udf_get_block (struct grub_udf_data
*data
,
365 grub_uint16_t part_ref
, grub_uint32_t block
)
367 part_ref
= U16 (part_ref
);
369 if (part_ref
>= data
->npm
)
371 grub_error (GRUB_ERR_BAD_FS
, "invalid part ref");
375 return (U32 (data
->pds
[data
->pms
[part_ref
]->type1
.part_num
].start
)
380 grub_udf_read_icb (struct grub_udf_data
*data
,
381 struct grub_udf_long_ad
*icb
,
382 struct grub_fshelp_node
*node
)
386 block
= grub_udf_get_block (data
,
388 icb
->block
.block_num
);
393 if (grub_disk_read (data
->disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
394 sizeof (struct grub_udf_file_entry
),
398 if ((U16 (node
->fe
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FE
) &&
399 (U16 (node
->fe
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_EFE
))
400 return grub_error (GRUB_ERR_BAD_FS
, "invalid fe/efe descriptor");
402 node
->part_ref
= icb
->block
.part_ref
;
407 static grub_disk_addr_t
408 grub_udf_read_block (grub_fshelp_node_t node
, grub_disk_addr_t fileblock
)
413 if (U16 (node
->fe
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_FE
)
415 ptr
= (char *) &node
->fe
.ext_attr
[0] + U32 (node
->fe
.ext_attr_length
);
416 len
= U32 (node
->fe
.alloc_descs_length
);
420 ptr
= (char *) &node
->efe
.ext_attr
[0] + U32 (node
->efe
.ext_attr_length
);
421 len
= U32 (node
->efe
.alloc_descs_length
);
424 if ((U16 (node
->fe
.icbtag
.flags
) & GRUB_UDF_ICBTAG_FLAG_AD_MASK
)
425 == GRUB_UDF_ICBTAG_FLAG_AD_SHORT
)
427 struct grub_udf_short_ad
*ad
= (struct grub_udf_short_ad
*) ptr
;
429 len
/= sizeof (struct grub_udf_short_ad
);
432 if (fileblock
< U32 (ad
->length
))
433 return ((U32 (ad
->position
) & GRUB_UDF_EXT_MASK
) ? 0 :
434 (grub_udf_get_block (node
->data
,
439 fileblock
-= U32 (ad
->length
);
446 struct grub_udf_long_ad
*ad
= (struct grub_udf_long_ad
*) ptr
;
448 len
/= sizeof (struct grub_udf_long_ad
);
451 if (fileblock
< U32 (ad
->length
))
452 return ((U32 (ad
->block
.block_num
) & GRUB_UDF_EXT_MASK
) ? 0 :
453 (grub_udf_get_block (node
->data
,
458 fileblock
-= U32 (ad
->length
);
468 grub_udf_read_file (grub_fshelp_node_t node
,
469 void NESTED_FUNC_ATTR
470 (*read_hook
) (grub_disk_addr_t sector
,
471 unsigned offset
, unsigned length
),
472 int pos
, grub_size_t len
, char *buf
)
474 switch (U16 (node
->fe
.icbtag
.flags
) & GRUB_UDF_ICBTAG_FLAG_AD_MASK
)
476 case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB
:
480 ptr
= ((U16 (node
->fe
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_FE
) ?
481 ((char *) &node
->fe
.ext_attr
[0]
482 + U32 (node
->fe
.ext_attr_length
)) :
483 ((char *) &node
->efe
.ext_attr
[0]
484 + U32 (node
->efe
.ext_attr_length
)));
486 grub_memcpy (buf
, ptr
+ pos
, len
);
491 case GRUB_UDF_ICBTAG_FLAG_AD_EXT
:
492 grub_error (GRUB_ERR_BAD_FS
, "invalid extent type");
496 return grub_fshelp_read_file (node
->data
->disk
, node
, read_hook
,
497 pos
, len
, buf
, grub_udf_read_block
,
498 U64 (node
->fe
.file_size
),
499 GRUB_UDF_LOG2_BLKSZ
);
502 static int sblocklist
[] = { 256, 512, 0 };
504 static struct grub_udf_data
*
505 grub_udf_mount (grub_disk_t disk
)
507 struct grub_udf_data
*data
= 0;
508 struct grub_udf_fileset root_fs
;
509 int *sblklist
= sblocklist
;
513 data
= grub_malloc (sizeof (struct grub_udf_data
));
519 /* Search for Volume Recognition Sequence (VRS). */
520 for (block
= 16;; block
++)
522 struct grub_udf_vrs vrs
;
524 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
525 sizeof (struct grub_udf_vrs
), (char *) &vrs
))
527 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
531 if ((!grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_NSR03
, 5)) ||
532 (!grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_NSR02
, 5)))
535 if ((grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_BEA01
, 5)) &&
536 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_BOOT2
, 5)) &&
537 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_CD001
, 5)) &&
538 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_CDW02
, 5)) &&
539 (grub_memcmp (vrs
.magic
, GRUB_UDF_STD_IDENT_TEA01
, 5)))
541 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
546 /* Search for Anchor Volume Descriptor Pointer (AVDP). */
549 struct grub_udf_avdp avdp
;
551 if (grub_disk_read (disk
, *sblklist
<< GRUB_UDF_LOG2_BLKSZ
, 0,
552 sizeof (struct grub_udf_avdp
), (char *) &avdp
))
554 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
558 if (U16 (avdp
.tag
.tag_ident
) == GRUB_UDF_TAG_IDENT_AVDP
)
560 block
= U32 (avdp
.vds
.start
);
567 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
572 data
->npd
= data
->npm
= 0;
573 /* Locate Partiton Descriptor (PD) and Logical Volume Descriptor (LVD). */
576 struct grub_udf_tag tag
;
578 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
579 sizeof (struct grub_udf_tag
), (char *) &tag
))
581 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
585 tag
.tag_ident
= U16 (tag
.tag_ident
);
586 if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_PD
)
588 if (data
->npd
>= GRUB_UDF_MAX_PDS
)
590 grub_error (GRUB_ERR_BAD_FS
, "too many PDs");
594 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
595 sizeof (struct grub_udf_pd
),
596 (char *) &data
->pds
[data
->npd
]))
598 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
604 else if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_LVD
)
608 struct grub_udf_partmap
*ppm
;
610 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
611 sizeof (struct grub_udf_lvd
),
612 (char *) &data
->lvd
))
614 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
618 if (data
->npm
+ U32 (data
->lvd
.num_part_maps
) > GRUB_UDF_MAX_PMS
)
620 grub_error (GRUB_ERR_BAD_FS
, "too many partition maps");
624 ppm
= (struct grub_udf_partmap
*) &data
->lvd
.part_maps
;
625 for (k
= U32 (data
->lvd
.num_part_maps
); k
> 0; k
--)
627 if (ppm
->type
!= GRUB_UDF_PARTMAP_TYPE_1
)
629 grub_error (GRUB_ERR_BAD_FS
, "partmap type not supported");
633 data
->pms
[data
->npm
++] = ppm
;
634 ppm
= (struct grub_udf_partmap
*) ((char *) ppm
+
638 else if (tag
.tag_ident
> GRUB_UDF_TAG_IDENT_TD
)
640 grub_error (GRUB_ERR_BAD_FS
, "invalid tag ident");
643 else if (tag
.tag_ident
== GRUB_UDF_TAG_IDENT_TD
)
649 for (i
= 0; i
< data
->npm
; i
++)
653 for (j
= 0; j
< data
->npd
; j
++)
654 if (data
->pms
[i
]->type1
.part_num
== data
->pds
[j
].part_num
)
656 data
->pms
[i
]->type1
.part_num
= j
;
662 grub_error (GRUB_ERR_BAD_FS
, "can\'t find PD");
667 block
= grub_udf_get_block (data
,
668 data
->lvd
.root_fileset
.block
.part_ref
,
669 data
->lvd
.root_fileset
.block
.block_num
);
674 if (grub_disk_read (disk
, block
<< GRUB_UDF_LOG2_BLKSZ
, 0,
675 sizeof (struct grub_udf_fileset
), (char *) &root_fs
))
677 grub_error (GRUB_ERR_BAD_FS
, "not an udf filesystem");
681 if (U16 (root_fs
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FSD
)
683 grub_error (GRUB_ERR_BAD_FS
, "invalid fileset descriptor");
687 data
->root_icb
= root_fs
.root_icb
;
697 grub_udf_iterate_dir (grub_fshelp_node_t dir
,
699 (*hook
) (const char *filename
,
700 enum grub_fshelp_filetype filetype
,
701 grub_fshelp_node_t node
))
703 grub_fshelp_node_t child
;
704 struct grub_udf_file_ident dirent
;
705 grub_uint32_t offset
= 0;
707 child
= grub_malloc (sizeof (struct grub_fshelp_node
));
711 /* The current directory is not stored. */
712 grub_memcpy ((char *) child
, (char *) dir
,
713 sizeof (struct grub_fshelp_node
));
715 if (hook (".", GRUB_FSHELP_DIR
, child
))
718 while (offset
< U64 (dir
->fe
.file_size
))
720 if (grub_udf_read_file (dir
, 0, offset
, sizeof (dirent
),
721 (char *) &dirent
) != sizeof (dirent
))
724 if (U16 (dirent
.tag
.tag_ident
) != GRUB_UDF_TAG_IDENT_FID
)
726 grub_error (GRUB_ERR_BAD_FS
, "invalid fid tag");
730 child
= grub_malloc (sizeof (struct grub_fshelp_node
));
734 if (grub_udf_read_icb (dir
->data
, &dirent
.icb
, child
))
737 offset
+= sizeof (dirent
) + U16 (dirent
.imp_use_length
);
738 if (dirent
.characteristics
& GRUB_UDF_FID_CHAR_PARENT
)
740 /* This is the parent directory. */
741 if (hook ("..", GRUB_FSHELP_DIR
, child
))
746 enum grub_fshelp_filetype type
;
747 char filename
[dirent
.file_ident_length
+ 1];
749 type
= ((dirent
.characteristics
& GRUB_UDF_FID_CHAR_DIRECTORY
) ?
750 (GRUB_FSHELP_DIR
) : (GRUB_FSHELP_REG
));
752 if ((grub_udf_read_file (dir
, 0, offset
,
753 dirent
.file_ident_length
, filename
))
754 != dirent
.file_ident_length
)
757 filename
[dirent
.file_ident_length
] = 0;
758 if (hook (&filename
[1], type
, child
))
762 /* Align to dword boundary. */
763 offset
= (offset
+ dirent
.file_ident_length
+ 3) & (~3);
770 grub_udf_dir (grub_device_t device
, const char *path
,
771 int (*hook
) (const char *filename
, int dir
))
773 struct grub_udf_data
*data
= 0;
774 struct grub_fshelp_node rootnode
;
775 struct grub_fshelp_node
*foundnode
;
777 auto int NESTED_FUNC_ATTR
iterate (const char *filename
,
778 enum grub_fshelp_filetype filetype
,
779 grub_fshelp_node_t node
);
781 int NESTED_FUNC_ATTR
iterate (const char *filename
,
782 enum grub_fshelp_filetype filetype
,
783 grub_fshelp_node_t node
)
787 if (filetype
== GRUB_FSHELP_DIR
)
788 return hook (filename
, 1);
790 return hook (filename
, 0);
796 grub_dl_ref (my_mod
);
799 data
= grub_udf_mount (device
->disk
);
803 if (grub_udf_read_icb (data
, &data
->root_icb
, &rootnode
))
806 if (grub_fshelp_find_file (path
, &rootnode
,
808 grub_udf_iterate_dir
, 0, GRUB_FSHELP_DIR
))
811 grub_udf_iterate_dir (foundnode
, iterate
);
813 if (foundnode
!= &rootnode
)
814 grub_free (foundnode
);
820 grub_dl_unref (my_mod
);
827 grub_udf_open (struct grub_file
*file
, const char *name
)
829 struct grub_udf_data
*data
;
830 struct grub_fshelp_node rootnode
;
831 struct grub_fshelp_node
*foundnode
;
834 grub_dl_ref (my_mod
);
837 data
= grub_udf_mount (file
->device
->disk
);
841 if (grub_udf_read_icb (data
, &data
->root_icb
, &rootnode
))
844 if (grub_fshelp_find_file (name
, &rootnode
,
846 grub_udf_iterate_dir
, 0, GRUB_FSHELP_REG
))
849 file
->data
= foundnode
;
851 file
->size
= U64 (foundnode
->fe
.file_size
);
857 grub_dl_unref (my_mod
);
866 grub_udf_read (grub_file_t file
, char *buf
, grub_size_t len
)
868 struct grub_fshelp_node
*node
= (struct grub_fshelp_node
*) file
->data
;
870 return grub_udf_read_file (node
, file
->read_hook
, file
->offset
, len
, buf
);
874 grub_udf_close (grub_file_t file
)
878 struct grub_fshelp_node
*node
= (struct grub_fshelp_node
*) file
->data
;
880 grub_free (node
->data
);
885 grub_dl_unref (my_mod
);
888 return GRUB_ERR_NONE
;
892 grub_udf_label (grub_device_t device
, char **label
)
894 struct grub_udf_data
*data
;
895 data
= grub_udf_mount (device
->disk
);
899 *label
= grub_strdup ((char *) &data
->lvd
.ident
[1]);
908 static struct grub_fs grub_udf_fs
= {
911 .open
= grub_udf_open
,
912 .read
= grub_udf_read
,
913 .close
= grub_udf_close
,
914 .label
= grub_udf_label
,
920 grub_fs_register (&grub_udf_fs
);
928 grub_fs_unregister (&grub_udf_fs
);