| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2001, 2002 Scott Long <scottl@freebsd.org> |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | /* ecma167-udf.h */ |
| 30 | /* Structure/definitions/constants a la ECMA 167 rev. 3 */ |
| 31 | |
| 32 | /* Tag identifiers */ |
| 33 | enum { |
| 34 | 	TAGID_PRI_VOL =		1, |
| 35 | 	TAGID_ANCHOR =		2, |
| 36 | 	TAGID_VOL = 		3, |
| 37 | 	TAGID_IMP_VOL =		4, |
| 38 | 	TAGID_PARTITION =	5, |
| 39 | 	TAGID_LOGVOL =		6, |
| 40 | 	TAGID_UNALLOC_SPACE =	7, |
| 41 | 	TAGID_TERM =		8, |
| 42 | 	TAGID_LOGVOL_INTEGRITY = 9, |
| 43 | 	TAGID_FSD =		256, |
| 44 | 	TAGID_FID =		257, |
| 45 | 	TAGID_FENTRY =		261 |
| 46 | }; |
| 47 | |
| 48 | /* Descriptor tag [3/7.2] */ |
| 49 | struct desc_tag { |
| 50 | 	uint16_t	id; |
| 51 | 	uint16_t	descriptor_ver; |
| 52 | 	uint8_t		cksum; |
| 53 | 	uint8_t		reserved; |
| 54 | 	uint16_t	serial_num; |
| 55 | 	uint16_t	desc_crc; |
| 56 | 	uint16_t	desc_crc_len; |
| 57 | 	uint32_t	tag_loc; |
| 58 | } __packed; |
| 59 | |
| 60 | /* Recorded Address [4/7.1] */ |
| 61 | struct lb_addr { |
| 62 | 	uint32_t	lb_num; |
| 63 | 	uint16_t	part_num; |
| 64 | } __packed; |
| 65 | |
| 66 | /* Extent Descriptor [3/7.1] */ |
| 67 | struct extent_ad { |
| 68 | 	uint32_t	len; |
| 69 | 	uint32_t	loc; |
| 70 | } __packed; |
| 71 | |
| 72 | /* Short Allocation Descriptor [4/14.14.1] */ |
| 73 | struct short_ad { |
| 74 | 	uint32_t	len; |
| 75 | 	uint32_t	pos; |
| 76 | } __packed; |
| 77 | |
| 78 | /* Long Allocation Descriptor [4/14.14.2] */ |
| 79 | struct long_ad { |
| 80 | 	uint32_t	len; |
| 81 | 	struct lb_addr	loc; |
| 82 | 	uint16_t	ad_flags; |
| 83 | 	uint32_t	ad_id; |
| 84 | } __packed; |
| 85 | |
| 86 | /* Extended Allocation Descriptor [4/14.14.3] */ |
| 87 | struct ext_ad { |
| 88 | 	uint32_t	ex_len; |
| 89 | 	uint32_t	rec_len; |
| 90 | 	uint32_t	inf_len; |
| 91 | 	struct lb_addr	ex_loc; |
| 92 | 	uint8_t		reserved[2]; |
| 93 | } __packed; |
| 94 | |
| 95 | union icb { |
| 96 | 	struct short_ad	s_ad; |
| 97 | 	struct long_ad	l_ad; |
| 98 | 	struct ext_ad	e_ad; |
| 99 | }; |
| 100 | |
| 101 | /* Character set spec [1/7.2.1] */ |
| 102 | struct charspec { |
| 103 | 	uint8_t		type; |
| 104 | 	uint8_t		inf[63]; |
| 105 | } __packed; |
| 106 | |
| 107 | /* Timestamp [1/7.3] */ |
| 108 | struct timestamp { |
| 109 | 	uint16_t	type_tz; |
| 110 | 	uint16_t	year; |
| 111 | 	uint8_t		month; |
| 112 | 	uint8_t		day; |
| 113 | 	uint8_t		hour; |
| 114 | 	uint8_t		minute; |
| 115 | 	uint8_t		second; |
| 116 | 	uint8_t		centisec; |
| 117 | 	uint8_t		hund_usec; |
| 118 | 	uint8_t		usec; |
| 119 | } __packed; |
| 120 | |
| 121 | /* Entity Identifier [1/7.4] */ |
| 122 | #define	UDF_REGID_ID_SIZE	23 |
| 123 | struct regid { |
| 124 | 	uint8_t		flags; |
| 125 | 	uint8_t		id[UDF_REGID_ID_SIZE]; |
| 126 | 	uint8_t		id_suffix[8]; |
| 127 | } __packed; |
| 128 | |
| 129 | /* ICB Tag [4/14.6] */ |
| 130 | struct icb_tag { |
| 131 | 	uint32_t	prev_num_dirs; |
| 132 | 	uint16_t	strat_type; |
| 133 | 	uint8_t		strat_param[2]; |
| 134 | 	uint16_t	max_num_entries; |
| 135 | 	uint8_t		reserved; |
| 136 | 	uint8_t		file_type; |
| 137 | 	struct lb_addr	parent_icb; |
| 138 | 	uint16_t	flags; |
| 139 | } __packed; |
| 140 | #define	UDF_ICB_TAG_FLAGS_SETUID	0x40 |
| 141 | #define	UDF_ICB_TAG_FLAGS_SETGID	0x80 |
| 142 | #define	UDF_ICB_TAG_FLAGS_STICKY	0x100 |
| 143 | |
| 144 | /* Anchor Volume Descriptor Pointer [3/10.2] */ |
| 145 | struct anchor_vdp { |
| 146 | 	struct desc_tag		tag; |
| 147 | 	struct extent_ad	main_vds_ex; |
| 148 | 	struct extent_ad	reserve_vds_ex; |
| 149 | } __packed; |
| 150 | |
| 151 | /* Volume Descriptor Pointer [3/10.3] */ |
| 152 | struct vol_desc_ptr { |
| 153 | 	struct desc_tag		tag; |
| 154 | 	uint32_t		vds_number; |
| 155 | 	struct extent_ad	next_vds_ex; |
| 156 | } __packed; |
| 157 | |
| 158 | /* Primary Volume Descriptor [3/10.1] */ |
| 159 | struct pri_vol_desc { |
| 160 | 	struct desc_tag		tag; |
| 161 | 	uint32_t		seq_num; |
| 162 | 	uint32_t		pdv_num; |
| 163 | 	char			vol_id[32]; |
| 164 | 	uint16_t		vds_num; |
| 165 | 	uint16_t		max_vol_seq; |
| 166 | 	uint16_t		ichg_lvl; |
| 167 | 	uint16_t		max_ichg_lvl; |
| 168 | 	uint32_t		charset_list; |
| 169 | 	uint32_t		max_charset_list; |
| 170 | 	char			volset_id[128]; |
| 171 | 	struct charspec		desc_charset; |
| 172 | 	struct charspec		explanatory_charset; |
| 173 | 	struct extent_ad	vol_abstract; |
| 174 | 	struct extent_ad	vol_copyright; |
| 175 | 	struct regid		app_id; |
| 176 | 	struct timestamp	time; |
| 177 | 	struct regid		imp_id; |
| 178 | 	uint8_t			imp_use[64]; |
| 179 | 	uint32_t		prev_vds_lov; |
| 180 | 	uint16_t		flags; |
| 181 | 	uint8_t			reserved[22]; |
| 182 | } __packed; |
| 183 | |
| 184 | /* Logical Volume Descriptor [3/10.6] */ |
| 185 | struct logvol_desc { |
| 186 | 	struct desc_tag		tag; |
| 187 | 	uint32_t		seq_num; |
| 188 | 	struct charspec		desc_charset; |
| 189 | 	char			logvol_id[128]; |
| 190 | 	uint32_t		lb_size; |
| 191 | 	struct regid		domain_id; |
| 192 | 	union { |
| 193 | 		struct long_ad	fsd_loc; |
| 194 | 		uint8_t		logvol_content_use[16]; |
| 195 | 	} _lvd_use; |
| 196 | 	uint32_t		mt_l; /* Partition map length */ |
| 197 | 	uint32_t		n_pm; /* Number of partition maps */ |
| 198 | 	struct regid		imp_id; |
| 199 | 	uint8_t			imp_use[128]; |
| 200 | 	struct extent_ad	integrity_seq_id; |
| 201 | 	uint8_t			maps[1]; |
| 202 | } __packed; |
| 203 | |
| 204 | /* Type 1 Partition Map [3/10.7.2] */ |
| 205 | struct part_map_1 { |
| 206 | 	uint8_t			type; |
| 207 | 	uint8_t			len; |
| 208 | 	uint16_t		vol_seq_num; |
| 209 | 	uint16_t		part_num; |
| 210 | } __packed; |
| 211 | |
| 212 | #define	UDF_PMAP_TYPE1_SIZE	6 |
| 213 | |
| 214 | /* Type 2 Partition Map [3/10.7.3] */ |
| 215 | struct part_map_2 { |
| 216 | 	uint8_t			type; |
| 217 | 	uint8_t			len; |
| 218 | 	uint8_t			part_id[62]; |
| 219 | } __packed; |
| 220 | |
| 221 | #define	UDF_PMAP_TYPE2_SIZE	64 |
| 222 | |
| 223 | /* Virtual Partition Map [UDF 2.01/2.2.8] */ |
| 224 | struct part_map_virt { |
| 225 | 	uint8_t			type; |
| 226 | 	uint8_t			len; |
| 227 | 	uint8_t			reserved[2]; |
| 228 | 	struct regid		id; |
| 229 | 	uint16_t		vol_seq_num; |
| 230 | 	uint16_t		part_num; |
| 231 | 	uint8_t			reserved1[24]; |
| 232 | } __packed; |
| 233 | |
| 234 | /* Sparable Partition Map [UDF 2.01/2.2.9] */ |
| 235 | struct part_map_spare { |
| 236 | 	uint8_t			type; |
| 237 | 	uint8_t			len; |
| 238 | 	uint8_t			reserved[2]; |
| 239 | 	struct regid		id; |
| 240 | 	uint16_t		vol_seq_num; |
| 241 | 	uint16_t		part_num; |
| 242 | 	uint16_t		packet_len; |
| 243 | 	uint8_t			n_st;	/* Number of Sparing Tables */ |
| 244 | 	uint8_t			reserved1; |
| 245 | 	uint32_t		st_size; |
| 246 | 	uint32_t		st_loc[]; |
| 247 | } __packed; |
| 248 | |
| 249 | union udf_pmap { |
| 250 | 	struct part_map_1	pm1; |
| 251 | 	struct part_map_2	pm2; |
| 252 | 	struct part_map_virt	pmv; |
| 253 | 	struct part_map_spare	pms; |
| 254 | }; |
| 255 | |
| 256 | /* Sparing Map Entry [UDF 2.01/2.2.11] */ |
| 257 | struct spare_map_entry { |
| 258 | 	uint32_t		org; |
| 259 | 	uint32_t		map; |
| 260 | } __packed; |
| 261 | |
| 262 | /* Sparing Table [UDF 2.01/2.2.11] */ |
| 263 | struct udf_sparing_table { |
| 264 | 	struct desc_tag		tag; |
| 265 | 	struct regid		id; |
| 266 | 	uint16_t		rt_l;	/* Relocation Table len */ |
| 267 | 	uint8_t			reserved[2]; |
| 268 | 	uint32_t		seq_num; |
| 269 | 	struct spare_map_entry	entries[]; |
| 270 | } __packed; |
| 271 | |
| 272 | /* Partition Descriptor [3/10.5] */ |
| 273 | struct part_desc { |
| 274 | 	struct desc_tag	tag; |
| 275 | 	uint32_t	seq_num; |
| 276 | 	uint16_t	flags; |
| 277 | 	uint16_t	part_num; |
| 278 | 	struct regid	contents; |
| 279 | 	uint8_t		contents_use[128]; |
| 280 | 	uint32_t	access_type; |
| 281 | 	uint32_t	start_loc; |
| 282 | 	uint32_t	part_len; |
| 283 | 	struct regid	imp_id; |
| 284 | 	uint8_t		imp_use[128]; |
| 285 | 	uint8_t		reserved[156]; |
| 286 | } __packed; |
| 287 | |
| 288 | /* File Set Descriptor [4/14.1] */ |
| 289 | struct fileset_desc { |
| 290 | 	struct desc_tag		tag; |
| 291 | 	struct timestamp	time; |
| 292 | 	uint16_t		ichg_lvl; |
| 293 | 	uint16_t		max_ichg_lvl; |
| 294 | 	uint32_t		charset_list; |
| 295 | 	uint32_t		max_charset_list; |
| 296 | 	uint32_t		fileset_num; |
| 297 | 	uint32_t		fileset_desc_num; |
| 298 | 	struct charspec		logvol_id_charset; |
| 299 | 	char			logvol_id[128]; |
| 300 | 	struct charspec		fileset_charset; |
| 301 | 	char			fileset_id[32]; |
| 302 | 	char			copyright_file_id[32]; |
| 303 | 	char			abstract_file_id[32]; |
| 304 | 	struct long_ad		rootdir_icb; |
| 305 | 	struct regid		domain_id; |
| 306 | 	struct long_ad		next_ex; |
| 307 | 	struct long_ad		streamdir_icb; |
| 308 | 	uint8_t			reserved[32]; |
| 309 | } __packed; |
| 310 | |
| 311 | /* File Identifier Descriptor [4/14.4] */ |
| 312 | struct fileid_desc { |
| 313 | 	struct desc_tag	tag; |
| 314 | 	uint16_t	file_num; |
| 315 | 	uint8_t		file_char; |
| 316 | 	uint8_t		l_fi;	/* Length of file identifier area */ |
| 317 | 	struct long_ad	icb; |
| 318 | 	uint16_t	l_iu;	/* Length of implementation use area */ |
| 319 | 	uint8_t		data[1]; |
| 320 | } __packed; |
| 321 | #define	UDF_FID_SIZE	38 |
| 322 | #define	UDF_FILE_CHAR_VIS	(1 << 0) /* Visible */ |
| 323 | #define	UDF_FILE_CHAR_DIR	(1 << 1) /* Directory */ |
| 324 | #define	UDF_FILE_CHAR_DEL	(1 << 2) /* Deleted */ |
| 325 | #define	UDF_FILE_CHAR_PAR	(1 << 3) /* Parent Directory */ |
| 326 | #define	UDF_FILE_CHAR_META	(1 << 4) /* Stream metadata */ |
| 327 | |
| 328 | /* File Entry [4/14.9] */ |
| 329 | struct file_entry { |
| 330 | 	struct desc_tag		tag; |
| 331 | 	struct icb_tag		icbtag; |
| 332 | 	uint32_t		uid; |
| 333 | 	uint32_t		gid; |
| 334 | 	uint32_t		perm; |
| 335 | 	uint16_t		link_cnt; |
| 336 | 	uint8_t			rec_format; |
| 337 | 	uint8_t			rec_disp_attr; |
| 338 | 	uint32_t		rec_len; |
| 339 | 	uint64_t		inf_len; |
| 340 | 	uint64_t		logblks_rec; |
| 341 | 	struct timestamp	atime; |
| 342 | 	struct timestamp	mtime; |
| 343 | 	struct timestamp	attrtime; |
| 344 | 	uint32_t		ckpoint; |
| 345 | 	struct long_ad		ex_attr_icb; |
| 346 | 	struct regid		imp_id; |
| 347 | 	uint64_t		unique_id; |
| 348 | 	uint32_t		l_ea;	/* Length of extended attribute area */ |
| 349 | 	uint32_t		l_ad;	/* Length of allocation descriptors */ |
| 350 | 	uint8_t			data[1]; |
| 351 | } __packed; |
| 352 | #define	UDF_FENTRY_SIZE	176 |
| 353 | #define	UDF_FENTRY_PERM_USER_MASK	0x07 |
| 354 | #define	UDF_FENTRY_PERM_GRP_MASK	0xE0 |
| 355 | #define	UDF_FENTRY_PERM_OWNER_MASK	0x1C00 |
| 356 | |
| 357 | /* Path Component [4/14.16.1] */ |
| 358 | struct path_component { |
| 359 | 	uint8_t			type; |
| 360 | 	uint8_t			length; |
| 361 | 	uint16_t		version; |
| 362 | 	uint8_t			identifier[1]; |
| 363 | } __packed; |
| 364 | #define	UDF_PATH_ROOT		2 |
| 365 | #define	UDF_PATH_DOTDOT		3 |
| 366 | #define	UDF_PATH_DOT		4 |
| 367 | #define	UDF_PATH_PATH		5 |
| 368 | |
| 369 | union dscrptr { |
| 370 | 	struct desc_tag		tag; |
| 371 | 	struct anchor_vdp	avdp; |
| 372 | 	struct vol_desc_ptr	vdp; |
| 373 | 	struct pri_vol_desc	pvd; |
| 374 | 	struct logvol_desc	lvd; |
| 375 | 	struct part_desc	pd; |
| 376 | 	struct fileset_desc	fsd; |
| 377 | 	struct fileid_desc	fid; |
| 378 | 	struct file_entry	fe; |
| 379 | }; |
| 380 | |
| 381 | /* Useful defines */ |
| 382 | |
| 383 | #define	GETICB(ad_type, fentry, offset)	\ |
| 384 | 	(struct ad_type *)&fentry->data[offset] |
| 385 | |
| 386 | #define	GETICBLEN(ad_type, icb)	le32toh(((struct ad_type *)(icb))->len) |