1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12 
13 /* @(#)udf.c	1.14 04/04/15 Copyright 2001 J. Schilling */
14 /*
15  * udf.c - UDF support for genisoimage
16  *
17  * Written by Ben Rudiak-Gould (2001).
18  *
19  * Copyright 2001 J. Schilling.
20  */
21 /*
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License version 2
24  * as published by the Free Software Foundation.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License along with
32  * this program; see the file COPYING.  If not, write to the Free Software
33  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35 
36 /*
37  * Some remaining issues:
38  *
39  * - Do not forget to edit joliet.c and remove the VIDEO_TS lines after
40  *   we did implement a decent own file name handling for UDF.
41  *
42  * - UDF supports UNIX-style file permissions and uid/gid, but currently
43  *   this code just sets them to default values and ignores their Rock
44  *   Ridge counterparts. This would be easy to fix.
45  *
46  * - There's no support for symlinks, Mac type/creator, or Mac resource
47  *   forks. Hard links and followed symlinks may work, but if so, it's
48  *   only by accident.
49  *
50  * - The file system mirrors the Joliet file system, so files excluded
51  *   from Joliet will also be excluded from UDF, the -jcharset option
52  *   also applies to UDF, file names too long for Joliet will also be
53  *   truncated on UDF, and characters not allowed by Joliet will also
54  *   be translated on UDF. (Fortunately, Joliet is pretty lenient.)
55  *
56  * - convert_to_unicode is always called with in_nls, not hfs_nls. This
57  *   may lead to incorrect name conversion sometimes when using a Mac
58  *   filesystem. See joliet.c for an example of what's supposed to be
59  *   done.
60  *
61  * - DVD-Video discs are supposed to have Copyright Management Information
62  *   in both the ISO and UDF filesystems. This is not implemented in ISO,
63  *   and the code to do it in UDF is currently #ifdef'd out. I'm not sure
64  *   whether discs without this information are actually DVD-Video
65  *   compliant. The Copyright Management Information is described in ECMA
66  *   Technical Report TR/71.
67  *
68  * - Most of the space before sector 256 on the disc (~480K) is wasted,
69  *   because UDF Bridge requires a pointer block at sector 256. ISO 9660
70  *   structures could be moved below sector 256 if they're small enough, but
71  *   this would be ugly to implement since it breaks the output_fragment
72  *   abstraction.
73  *
74  * - Each file must have a File Entry, and each File Entry seems to
75  *   require its own 2K sector. As a result, there is an overhead of more
76  *   than 2K *per file* when using UDF. I couldn't see any way to avoid
77  *   this.
78  *
79  * - Read performance would probably be improved by placing the File Entry
80  *   for each file just before the file itself, instead of at the beginning
81  *   of the disc. But this would not work for DVD-Video files, which have
82  *   to be stored contiguously. So there would have to be an override
83  *   mechanism to handle this case. I don't know if it's worth the trouble.
84  */
85 
86 #ifdef UDF
87 
88 #include "config.h"
89 #include "genisoimage.h"
90 #include <timedefs.h>
91 #include <schily.h>
92 
93 #include "udf.h"
94 #include "udf_fs.h"
95 
96 extern	int	use_sparcboot;
97 
98 extern struct directory *root;
99 extern time_t		begun;
100 
101 static unsigned lba_main_seq;
102 static unsigned lba_main_seq_copy;
103 static unsigned lba_integ_seq;
104 static unsigned lba_udf_partition_start;
105 static unsigned lba_last_file_entry;
106 static unsigned lba_end_anchor_vol_desc;
107 
108 static unsigned num_udf_files;
109 static unsigned num_udf_directories;
110 
111 static unsigned volume_set_id[2];
112 
113 #define	UDF_MAIN_SEQ_LENGTH (16)
114 #define	UDF_INTEG_SEQ_LENGTH (2)
115 
116 /* only works for granularity a power of 2! */
117 #define	PAD(val, granularity)	(((val)+(granularity)-1)&~((granularity)-1))
118 
119 #define	read_733(field) ((0[field]&255)+(1[field]&255)*256+(2[field]&255)*65536+(3[field]&255)*16777216)
120 
121 
122 /**************** SIZE ****************/
123 
124 static int set_file_ident_desc(unsigned char *, unsigned, char *, int,
125 										 unsigned, unsigned);
126 
127 static unsigned
directory_size(struct directory * dpnt)128 directory_size(struct directory *dpnt)
129 {
130 	unsigned size_in_bytes;
131 	struct directory_entry *de;
132 	Uchar dummy_buf[SECTOR_SIZE];
133 
134 	/* parent directory */
135 	size_in_bytes = set_file_ident_desc(dummy_buf, 0, 0, 0, 0, 0);
136 
137 	/* directory contents */
138 	for (de = dpnt->jcontents; de; de = de->jnext) {
139 		if (!(de->de_flags & INHIBIT_JOLIET_ENTRY)) {
140 			char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
141 			/* skip . and .. */
142 			if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
143 				continue;
144 			size_in_bytes += set_file_ident_desc(dummy_buf, 0, name, 0, 0, 0);
145 		}
146 	}
147 	return (size_in_bytes);
148 }
149 
150 static void
assign_udf_directory_addresses(struct directory * dpnt)151 assign_udf_directory_addresses(struct directory *dpnt)
152 {
153 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
154 		dpnt->self->udf_file_entry_sector = last_extent;
155 		last_extent += 1 + ISO_BLOCKS(directory_size(dpnt));
156 		++num_udf_directories;
157 	}
158 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
159 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
160 			assign_udf_directory_addresses(dpnt);
161 		}
162 	}
163 }
164 
165 static void
assign_udf_file_entry_addresses(struct directory * dpnt)166 assign_udf_file_entry_addresses(struct directory *dpnt)
167 {
168 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
169 		struct directory_entry *de;
170 		for (de = dpnt->jcontents; de; de = de->jnext) {
171 			if (!(de->de_flags & RELOCATED_DIRECTORY) &&
172 			    !(de->isorec.flags[0] & ISO_DIRECTORY)) {
173 				de->udf_file_entry_sector = last_extent++;
174 				++num_udf_files;
175 			}
176 		}
177 	}
178 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
179 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
180 			assign_udf_file_entry_addresses(dpnt);
181 		}
182 	}
183 }
184 
185 /****************************/
186 
187 static int
udf_vol_recognition_area_size(int starting_extent)188 udf_vol_recognition_area_size(int starting_extent)
189 {
190 	last_extent = starting_extent+3;
191 	return (0);
192 }
193 
194 static int
udf_main_seq_size(int starting_extent)195 udf_main_seq_size(int starting_extent)
196 {
197 	lba_main_seq = starting_extent;
198 	last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
199 	return (0);
200 }
201 
202 static int
udf_main_seq_copy_size(int starting_extent)203 udf_main_seq_copy_size(int starting_extent)
204 {
205 	lba_main_seq_copy = starting_extent;
206 	last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
207 	return (0);
208 }
209 
210 static int
udf_integ_seq_size(int starting_extent)211 udf_integ_seq_size(int starting_extent)
212 {
213 	lba_integ_seq = starting_extent;
214 	last_extent = starting_extent + UDF_INTEG_SEQ_LENGTH;
215 	return (0);
216 }
217 
218 static int
udf_end_anchor_vol_desc_size(int starting_extent)219 udf_end_anchor_vol_desc_size(int starting_extent)
220 {
221 	lba_end_anchor_vol_desc = starting_extent;
222 	last_extent = starting_extent+1;
223 	return (0);
224 }
225 
226 static int
udf_file_set_desc_size(int starting_extent)227 udf_file_set_desc_size(int starting_extent)
228 {
229 	lba_udf_partition_start = starting_extent;
230 	last_extent = starting_extent+2;
231 	return (0);
232 }
233 
234 static int
udf_dirtree_size(int starting_extent)235 udf_dirtree_size(int starting_extent)
236 {
237 	num_udf_directories = 0;
238 	assign_udf_directory_addresses(root);
239 	return (0);
240 }
241 
242 static int
udf_file_entries_size(int starting_extent)243 udf_file_entries_size(int starting_extent)
244 {
245 	num_udf_files = 0;
246 	assign_udf_file_entry_addresses(root);
247 	lba_last_file_entry = last_extent-1;
248 	return (0);
249 }
250 
251 static int
udf_pad_to_sector_32_size(int starting_extent)252 udf_pad_to_sector_32_size(int starting_extent)
253 {
254 	if (last_extent < session_start+32)
255 		last_extent = session_start+32;
256 	return (0);
257 }
258 
259 static int
udf_pad_to_sector_256_size(int starting_extent)260 udf_pad_to_sector_256_size(int starting_extent)
261 {
262 	if (last_extent < session_start+256)
263 		last_extent = session_start+256;
264 	return (0);
265 }
266 
267 static int
udf_padend_avdp_size(int starting_extent)268 udf_padend_avdp_size(int starting_extent)
269 {
270 	lba_end_anchor_vol_desc = starting_extent;
271 
272 	/* add at least 16 and at most 31 sectors, ending at a mult. of 16 */
273 	last_extent = (starting_extent+31) & ~15;
274 	if (!use_sparcboot)
275 		last_extent = starting_extent + 150;
276 	return (0);
277 }
278 
279 extern int oneblock_size(int);
280 
281 /**************** WRITE ****************/
282 
283 static unsigned
crc_ccitt(unsigned char * buf,unsigned len)284 crc_ccitt(unsigned char *buf, unsigned len)
285 {
286 	const unsigned poly = 0x11021;
287 	static unsigned short lookup[256];
288 	unsigned int r;
289 	unsigned int i;
290 
291 	if (lookup[1] == 0) {
292 		unsigned int j, k;
293 		for (j = 0; j < 256; ++j) {
294 			unsigned int temp = j << 8;
295 			for (k = 0; k < 8; ++k) {
296 				unsigned int hibit = temp & 32768;
297 				temp <<= 1;
298 				if (hibit)
299 					temp ^= poly;
300 			}
301 			lookup[j] = temp;
302 		}
303 	}
304 
305 	r = 0;
306 	for (i = 0; i < len; ++i) {
307 		r = (r << 8) ^ lookup[((r >> 8) ^ buf[i]) & 255];
308 	}
309 
310 	return (r & 65535);
311 }
312 
313 #define	set8(dst, src)	do { *(dst) = (src); } while (0)
314 
315 static void
set16(udf_Uint16 * dst,unsigned int src)316 set16(udf_Uint16 *dst, unsigned int src)
317 {
318 	dst->l = (char)(src);
319 	dst->h = (char)(src>>8);
320 }
321 
322 static void
set32(udf_Uint32 * dst,unsigned src)323 set32(udf_Uint32 *dst, unsigned src)
324 {
325 	dst->l  = (char)(src);
326 	dst->ml = (char)(src>>8);
327 	dst->mh = (char)(src>>16);
328 	dst->h  = (char)(src>>24);
329 }
330 
331 static void
set64(udf_Uint64 * dst,uint64_t src)332 set64(udf_Uint64 *dst, uint64_t src)
333 {
334 	set32(&dst->l, src);
335 	set32(&dst->h, src>>32);
336 }
337 
338 static int
set_ostaunicode(unsigned char * dst,int dst_size,char * src)339 set_ostaunicode(unsigned char *dst, int dst_size, char *src)
340 {
341 	unsigned char buf[1024];
342 	int i;
343 	int expanded_length;
344 
345 	expanded_length = joliet_strlen(src, in_nls);
346 	if (expanded_length > 1024)
347 		expanded_length = 1024;
348 	if (expanded_length > (dst_size-1)*2)
349 		expanded_length = (dst_size-1)*2;
350 
351 	convert_to_unicode(buf, expanded_length, src, in_nls);
352 	dst[0] = 8;	/* use 8-bit representation by default */
353 	for (i = 0; i < (expanded_length>>1); ++i) {
354 		dst[i + 1] = buf[i*2+1];
355 		if (buf[i*2] != 0) {
356 			/*
357 			 * There's a Unicode character with value >=256.
358 			 * Use 16-bit representation instead.
359 			 */
360 			int length_to_copy = (dst_size-1) & ~1;
361 			if (length_to_copy > expanded_length)
362 				length_to_copy = expanded_length;
363 			dst[0] = 16;
364 			memcpy(dst+1, buf, length_to_copy);
365 			return (length_to_copy + 1);
366 		}
367 	}
368 	return ((expanded_length>>1) + 1);
369 }
370 
371 static void
set_extent(udf_extent_ad * ext,unsigned lba,unsigned length_bytes)372 set_extent(udf_extent_ad *ext, unsigned lba, unsigned length_bytes)
373 {
374 	set32(&ext->extent_length, length_bytes);
375 	set32(&ext->extent_location, lba);
376 }
377 
378 static void
set_dstring(udf_dstring * dst,char * src,int n)379 set_dstring(udf_dstring *dst, char *src, int n)
380 {
381 	dst[n-1] = set_ostaunicode((Uchar *)dst, n-1, src);
382 }
383 
384 static void
set_charspec(udf_charspec * dst)385 set_charspec(udf_charspec *dst)
386 {
387 	/*set8(&dst->character_set_type, 0);*/
388 	memcpy(dst->character_set_info, "OSTA Compressed Unicode", 23);
389 }
390 
391 static void
set_impl_ident(udf_EntityID * ent)392 set_impl_ident(udf_EntityID *ent)
393 {
394 	strcpy((char *)ent->ident, "*genisoimage");
395 }
396 
397 static void
set_tag(udf_tag * t,unsigned tid,unsigned lba,int crc_length)398 set_tag(udf_tag *t, unsigned tid, unsigned lba, int crc_length)
399 {
400 	unsigned char checksum;
401 	int i;
402 
403 	set16(&t->tag_ident, tid);
404 	set16(&t->desc_version, 2);
405 	set16(&t->desc_crc, crc_ccitt((unsigned char *)t+16, crc_length-16));
406 	set16(&t->desc_crc_length, crc_length-16);
407 	set32(&t->tag_location, lba);
408 	set8(&t->tag_checksum, 0);
409 	checksum = 0;
410 	for (i = 0; i < 16; ++i)
411 		checksum += ((unsigned char *)t)[i];
412 	set8(&t->tag_checksum, checksum);
413 }
414 
415 static void
set_timestamp_from_iso_date(udf_timestamp * ts,const char * iso_date_raw)416 set_timestamp_from_iso_date(udf_timestamp *ts, const char *iso_date_raw)
417 {
418 	struct {
419 		unsigned char years_since_1900;
420 		unsigned char month, day;
421 		unsigned char hour, minute, second;
422 		signed char offset_from_gmt;
423 	} *iso_date = (void *)iso_date_raw;
424 
425 	set16(&ts->type_and_time_zone,
426 		4096 + ((iso_date->offset_from_gmt * 15) & 4095));
427 	set16(&ts->year, 1900 + iso_date->years_since_1900);
428 	set8(&ts->month, iso_date->month);
429 	set8(&ts->day, iso_date->day);
430 	set8(&ts->hour, iso_date->hour);
431 	set8(&ts->minute, iso_date->minute);
432 	set8(&ts->second, iso_date->second);
433 	/*set8(&ts->centiseconds, 0);*/
434 	/*set8(&ts->hundreds_of_microseconds, 0);*/
435 	/*set8(&ts->microseconds, 0);*/
436 }
437 
438 static void
set_timestamp_from_time_t(udf_timestamp * ts,time_t t)439 set_timestamp_from_time_t(udf_timestamp *ts, time_t t)
440 {
441 	char iso_date[7];
442 	iso9660_date(iso_date, t);
443 	set_timestamp_from_iso_date(ts, iso_date);
444 }
445 
446 
447 static void
set_anchor_volume_desc_pointer(unsigned char * buf,unsigned lba)448 set_anchor_volume_desc_pointer(unsigned char *buf, unsigned lba)
449 {
450 	udf_anchor_volume_desc_ptr *avdp = (udf_anchor_volume_desc_ptr *)buf;
451 	set_extent(&avdp->main_volume_desc_seq_extent,
452 		lba_main_seq, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
453 	set_extent(&avdp->reserve_volume_desc_seq_extent,
454 		lba_main_seq_copy, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
455 	set_tag(&avdp->desc_tag, UDF_TAGID_ANCHOR_VOLUME_DESC_PTR, lba, 512);
456 }
457 
458 static void
set_primary_vol_desc(unsigned char * buf,unsigned lba)459 set_primary_vol_desc(unsigned char *buf, unsigned lba)
460 {
461 	char temp[17];
462 
463 	udf_primary_volume_desc *pvd = (udf_primary_volume_desc *)buf;
464 	/*set32(&pvd->volume_desc_seq_number, 0);*/
465 	/*set32(&pvd->primary_volume_desc_number, 0);*/
466 	set_dstring(pvd->volume_ident, volume_id, sizeof (pvd->volume_ident));
467 	set16(&pvd->volume_seq_number, 1);
468 	set16(&pvd->maximum_volume_seq_number, 1);
469 	set16(&pvd->interchange_level, 2);
470 	set16(&pvd->maximum_interchange_level, 2);
471 	set32(&pvd->character_set_list, 1);
472 	set32(&pvd->maximum_character_set_list, 1);
473 	sprintf(temp, "%08X%08X", volume_set_id[0], volume_set_id[1]);
474 	set_dstring(pvd->volume_set_ident, temp,
475 					sizeof (pvd->volume_set_ident));
476 	set_charspec(&pvd->desc_character_set);
477 	set_charspec(&pvd->explanatory_character_set);
478 	/*pvd->volume_abstract;*/
479 	/*pvd->volume_copyright_notice;*/
480 	/*pvd->application_ident;*/
481 	set_timestamp_from_time_t(&pvd->recording_date_and_time, begun);
482 	set_impl_ident(&pvd->impl_ident);
483 	set_tag(&pvd->desc_tag, UDF_TAGID_PRIMARY_VOLUME_DESC, lba, 512);
484 }
485 
486 static void
set_impl_use_vol_desc(unsigned char * buf,unsigned lba)487 set_impl_use_vol_desc(unsigned char *buf, unsigned lba)
488 {
489 	udf_impl_use_volume_desc *iuvd = (udf_impl_use_volume_desc *)buf;
490 	set32(&iuvd->volume_desc_seq_number, 1);
491 	strcpy((char *)iuvd->impl_ident.ident, "*UDF LV Info");
492 	iuvd->impl_ident.ident_suffix[0] = 2;
493 	iuvd->impl_ident.ident_suffix[1] = 1;
494 	set_charspec(&iuvd->impl_use.lvi_charset);
495 	set_dstring(iuvd->impl_use.logical_volume_ident, volume_id,
496 		sizeof (iuvd->impl_use.logical_volume_ident));
497 	/*set_dstring(iuvd->impl_use.lv_info1, "", sizeof (iuvd->impl_use.lv_info1));*/
498 	/*set_dstring(iuvd->impl_use.lv_info2, "", sizeof (iuvd->impl_use.lv_info2));*/
499 	/*set_dstring(iuvd->impl_use.lv_info3, "", sizeof (iuvd->impl_use.lv_info3));*/
500 	set_impl_ident(&iuvd->impl_use.impl_id);
501 	set_tag(&iuvd->desc_tag, UDF_TAGID_IMPL_USE_VOLUME_DESC, lba, 512);
502 }
503 
504 static void
set_partition_desc(unsigned char * buf,unsigned lba)505 set_partition_desc(unsigned char *buf, unsigned lba)
506 {
507 	udf_partition_desc *pd = (udf_partition_desc *)buf;
508 	set32(&pd->volume_desc_seq_number, 2);
509 	set16(&pd->partition_flags, UDF_PARTITION_FLAG_ALLOCATED);
510 	/*set16(&pd->partition_number, 0);*/
511 	set8(&pd->partition_contents.flags, UDF_ENTITYID_FLAG_PROTECTED);	/*???*/
512 	strcpy((char *)pd->partition_contents.ident, "+NSR02");
513 	set32(&pd->access_type, UDF_ACCESSTYPE_READONLY);
514 	set32(&pd->partition_starting_location, lba_udf_partition_start);
515 	set32(&pd->partition_length,
516 			lba_end_anchor_vol_desc - lba_udf_partition_start);
517 	set_impl_ident(&pd->impl_ident);
518 	set_tag(&pd->desc_tag, UDF_TAGID_PARTITION_DESC, lba, 512);
519 }
520 
521 static void
set_domain_ident(udf_EntityID * ent)522 set_domain_ident(udf_EntityID *ent)
523 {
524 	strcpy((char *)ent->ident, "*OSTA UDF Compliant");
525 	memcpy(ent->ident_suffix, "\002\001\003", 3);
526 }
527 
528 static void
set_logical_vol_desc(unsigned char * buf,unsigned lba)529 set_logical_vol_desc(unsigned char *buf, unsigned lba)
530 {
531 	udf_logical_volume_desc *lvd = (udf_logical_volume_desc *)buf;
532 	set32(&lvd->volume_desc_seq_number, 3);
533 	set_charspec(&lvd->desc_character_set);
534 	set_dstring(lvd->logical_volume_ident, volume_id,
535 					sizeof (lvd->logical_volume_ident));
536 	set32(&lvd->logical_block_size, SECTOR_SIZE);
537 	set_domain_ident(&lvd->domain_ident);
538 	set32(&lvd->logical_volume_contents_use.extent_length, 2*SECTOR_SIZE);
539 	/*set32(&lvd->logical_volume_contents_use.extent_location.logical_block_number, 0);*/
540 	/*set16(&lvd->logical_volume_contents_use.extent_location.partition_reference_number, 0);*/
541 	set32(&lvd->map_table_length, 6);
542 	set32(&lvd->number_of_partition_maps, 1);
543 	set_impl_ident(&lvd->impl_ident);
544 	set_extent(&lvd->integrity_seq_extent, lba_integ_seq,
545 					SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH);
546 	set8(&lvd->partition_map[0].partition_map_type,
547 					UDF_PARTITION_MAP_TYPE_1);
548 	set8(&lvd->partition_map[0].partition_map_length, 6);
549 	set16(&lvd->partition_map[0].volume_seq_number, 1);
550 	/*set16(&lvd->partition_map[0].partition_number, 0);*/
551 	set_tag(&lvd->desc_tag, UDF_TAGID_LOGICAL_VOLUME_DESC, lba, 446);
552 }
553 
554 static void
set_unallocated_space_desc(unsigned char * buf,unsigned lba)555 set_unallocated_space_desc(unsigned char *buf, unsigned lba)
556 {
557 	udf_unallocated_space_desc *usd = (udf_unallocated_space_desc *)buf;
558 	set32(&usd->volume_desc_seq_number, 4);
559 	/*set32(&usd->number_of_allocation_descs, 0);*/
560 	set_tag(&usd->desc_tag, UDF_TAGID_UNALLOCATED_SPACE_DESC, lba, 24);
561 }
562 
563 static void
set_terminating_desc(unsigned char * buf,unsigned lba)564 set_terminating_desc(unsigned char *buf, unsigned lba)
565 {
566 	udf_terminating_desc *td = (udf_terminating_desc *)buf;
567 	set_tag(&td->desc_tag, UDF_TAGID_TERMINATING_DESC, lba, 512);
568 }
569 
570 static void
set_logical_vol_integrity_desc(unsigned char * buf,unsigned lba)571 set_logical_vol_integrity_desc(unsigned char *buf, unsigned lba)
572 {
573 	udf_logical_volume_integrity_desc *lvid =
574 				(udf_logical_volume_integrity_desc *)buf;
575 
576 	set_timestamp_from_time_t(&lvid->recording_date, begun);
577 	set32(&lvid->integrity_type, UDF_INTEGRITY_TYPE_CLOSE);
578 	/*lvid->next_integrity_extent;*/
579 	set64(&lvid->logical_volume_contents_use.unique_id,
580 						lba_last_file_entry+1);
581 	set32(&lvid->number_of_partitions, 1);
582 	set32(&lvid->length_of_impl_use, 46);
583 	/*set32(&lvid->free_space_table, 0);*/
584 	set32(&lvid->size_table,
585 			lba_end_anchor_vol_desc - lba_udf_partition_start);
586 	set_impl_ident(&lvid->impl_use.impl_id);
587 	set32(&lvid->impl_use.number_of_files, num_udf_files);
588 	set32(&lvid->impl_use.number_of_directories, num_udf_directories);
589 	set16(&lvid->impl_use.minimum_udf_read_revision, 0x102);
590 	set16(&lvid->impl_use.minimum_udf_write_revision, 0x102);
591 	set16(&lvid->impl_use.maximum_udf_write_revision, 0x102);
592 	set_tag(&lvid->desc_tag, UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC,
593 								lba, 88+46);
594 }
595 
596 static void
set_file_set_desc(unsigned char * buf,unsigned rba)597 set_file_set_desc(unsigned char *buf, unsigned rba)
598 {
599 	udf_file_set_desc *fsd = (udf_file_set_desc *)buf;
600 
601 	set_timestamp_from_time_t(&fsd->recording_date_and_time, begun);
602 	set16(&fsd->interchange_level, 3);
603 	set16(&fsd->maximum_interchange_level, 3);
604 	set32(&fsd->character_set_list, 1);
605 	set32(&fsd->maximum_character_set_list, 1);
606 	/*set32(&fsd->file_set_number, 0);*/
607 	/*set32(&fsd->file_set_desc_number, 0);*/
608 	set_charspec(&fsd->logical_volume_ident_character_set);
609 	set_dstring(fsd->logical_volume_ident, volume_id,
610 					sizeof (fsd->logical_volume_ident));
611 	set_charspec(&fsd->file_set_character_set);
612 	set_dstring(fsd->file_set_ident, volume_id,
613 					sizeof (fsd->file_set_ident));
614 	/*fsd->copyright_file_ident;*/
615 	/*fsd->abstract_file_ident;*/
616 	set32(&fsd->root_directory_icb.extent_length, SECTOR_SIZE);
617 	set32(&fsd->root_directory_icb.extent_location.logical_block_number,
618 		root->self->udf_file_entry_sector - lba_udf_partition_start);
619 	set_domain_ident(&fsd->domain_ident);
620 	/*fsd->next_extent;*/
621 	set_tag(&fsd->desc_tag, UDF_TAGID_FILE_SET_DESC, rba, 512);
622 }
623 
624 static int
set_file_ident_desc(unsigned char * buf,unsigned rba,char * name,int is_directory,unsigned file_entry_rba,unsigned unique_id)625 set_file_ident_desc(unsigned char *buf, unsigned rba, char *name,
626 						  int is_directory, unsigned file_entry_rba,
627 						  unsigned unique_id)
628 {
629 	udf_file_ident_desc *fid = (udf_file_ident_desc *)buf;
630 	int length_of_file_ident, length, padded_length;
631 	set16(&fid->file_version_number, 1);
632 	set8(&fid->file_characteristics,
633 		(is_directory ? UDF_FILE_CHARACTERISTIC_DIRECTORY : 0)
634 		+ (name == 0) * UDF_FILE_CHARACTERISTIC_PARENT);
635 	set32(&fid->icb.extent_length, SECTOR_SIZE);
636 	set32(&fid->icb.extent_location.logical_block_number, file_entry_rba);
637 	set16(&fid->icb.extent_location.partition_reference_number, 0);
638 	set32(&fid->icb.impl_use.unique_id, unique_id);
639 	set16(&fid->length_of_impl_use, 0);
640 	if (name) {
641 		length_of_file_ident =
642 			set_ostaunicode((Uchar *)fid->file_ident, 512, name);
643 	} else {
644 		length_of_file_ident = 0;
645 	}
646 	set8(&fid->length_of_file_ident, length_of_file_ident);
647 	length = 38 + length_of_file_ident;
648 	padded_length = PAD(length, 4);
649 	while (length < padded_length) {
650 		buf[length++] = 0;
651 	}
652 	set_tag(&fid->desc_tag, UDF_TAGID_FILE_IDENT_DESC, rba, length);
653 	return (length);
654 }
655 
656 static void
set_file_entry(unsigned char * buf,unsigned rba,unsigned file_rba,uint64_t length,const char * iso_date,int is_directory,unsigned link_count,unsigned unique_id)657 set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba,
658 					uint64_t length, const char *iso_date, int is_directory,
659 					unsigned link_count, unsigned unique_id)
660 {
661 	udf_short_ad	*allocation_desc;
662 	unsigned	chunk;
663 
664 	udf_file_entry *fe = (udf_file_entry *)buf;
665 
666 	/*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
667 	set16(&fe->icb_tag.strategy_type, 4);
668 	/*set16(&fe->icb_tag.strategy_parameter, 0);*/
669 	set16(&fe->icb_tag.maximum_number_of_entries, 1);
670 	set8(&fe->icb_tag.file_type, is_directory
671 		? UDF_ICBTAG_FILETYPE_DIRECTORY : UDF_ICBTAG_FILETYPE_BYTESEQ);
672 	/*fe->icb_tag.parent_icb_location;*/
673 	set16(&fe->icb_tag.flags, UDF_ICBTAG_FLAG_NONRELOCATABLE
674 		| UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS);
675 	if (rationalize_uid)
676 		set32(&fe->uid, uid_to_use);
677 	else
678 		set32(&fe->uid, -1);
679 	if (rationalize_gid)
680 		set32(&fe->gid, gid_to_use);
681 	else
682 		set32(&fe->gid, -1);
683 	if (is_directory) {
684 		set32(&fe->permissions,
685 		    UDF_FILEENTRY_PERMISSION_OR | UDF_FILEENTRY_PERMISSION_OX |
686 		    UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_GX |
687 		    UDF_FILEENTRY_PERMISSION_UR | UDF_FILEENTRY_PERMISSION_UX);
688 	} else {
689 		set32(&fe->permissions, UDF_FILEENTRY_PERMISSION_OR
690 		| UDF_FILEENTRY_PERMISSION_GR | UDF_FILEENTRY_PERMISSION_UR);
691 	}
692 	set16(&fe->file_link_count, link_count);
693 	/*fe->record_format;*/
694 	/*fe->record_display_attributes;*/
695 	/*fe->record_length;*/
696 	set64(&fe->info_length, length);
697 	set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
698 	if (iso_date) {
699 		set_timestamp_from_iso_date(&fe->access_time, iso_date);
700 		fe->modification_time = fe->access_time;
701 		fe->attribute_time = fe->access_time;
702 	}
703 	set32(&fe->checkpoint, 1);
704 	/*fe->ext_attribute_icb;*/
705 	set_impl_ident(&fe->impl_ident);
706 	set64(&fe->unique_id, unique_id);
707 	/*
708 	 * Extended attributes that may (?) be required for DVD-Video
709 	 * compliance
710 	 */
711 #if 0
712 	set32(&fe->length_of_ext_attributes, 24+52+56);
713 	set32(&fe->ext_attribute_header.impl_attributes_location, 24);
714 	set32(&fe->ext_attribute_header.application_attributes_location,
715 								24+52+56);
716 	set_tag(&fe->ext_attribute_header.desc_tag,
717 			UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba, 24 /*???*/);
718 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
719 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
720 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
721 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
722 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
723 							"*UDF FreeAppEASpace");
724 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
725 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
726 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
727 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
728 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
729 							"*UDF DVD CGMS Info");
730 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
731 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
732 #else
733 	/*set32(&fe->length_of_ext_attributes, 0);*/
734 #endif
735 
736 	allocation_desc = &fe->allocation_desc;
737 	/*
738 	 * Only a file size less than 1GB can be expressed by a single
739 	 * AllocationDescriptor. When the size of a file is larger than 1GB,
740 	 * 2 or more AllocationDescriptors should be used. We don't know
741 	 * whether a singl 8-byte AllocationDescriptor should be written or no
742 	 * one should be written if the size of a file is 0 byte. - FIXME.
743 	 *
744 	 * XXX We get called with buf[2048]. This allows a max. file size of
745 	 * XXX 234 GB. With more we would cause a buffer overflow.
746 	 * XXX We need to check whether UDF would allow files > 234 GB.
747 	 */
748 	for (; length > 0; length -= chunk) {
749 		chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
750 		set32(&allocation_desc->extent_length, chunk);
751 		set32(&allocation_desc->extent_position, file_rba);
752 		file_rba += chunk >> 11;
753 		allocation_desc++;
754 	}
755 	set32(&fe->length_of_allocation_descs,
756 				(unsigned char *) allocation_desc -
757 				(unsigned char *) &fe->allocation_desc);
758 	set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
759 		(unsigned char *) allocation_desc - buf);
760 }
761 
762 static unsigned
directory_link_count(struct directory * dpnt)763 directory_link_count(struct directory *dpnt)
764 {
765 	/*
766 	 * The link count is equal to 1 (for the parent) plus the
767 	 * number of subdirectories.
768 	 */
769 	unsigned link_count = 1;
770 	struct directory_entry *de;
771 
772 	/* count relocated subdirectories */
773 	for (de = dpnt->jcontents; de; de = de->jnext) {
774 		if ((de->de_flags &
775 		    (INHIBIT_JOLIET_ENTRY | RELOCATED_DIRECTORY)) ==
776 							RELOCATED_DIRECTORY) {
777 			link_count++;
778 		}
779 	}
780 	/* count ordinary subdirectories */
781 	for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
782 		if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
783 			link_count++;
784 		}
785 	}
786 	return (link_count);
787 }
788 
789 static void
write_one_udf_directory(struct directory * dpnt,FILE * outfile)790 write_one_udf_directory(struct directory *dpnt, FILE *outfile)
791 {
792 	unsigned size_in_bytes, padded_size_in_bytes;
793 	struct directory_entry *de;
794 	unsigned ident_size;
795 	unsigned base_sector;
796 	struct directory *parent;
797 	Uchar buf[SECTOR_SIZE];
798 
799 	memset(buf, 0, SECTOR_SIZE);
800 	set_file_entry(
801 		buf,
802 		last_extent_written - lba_udf_partition_start,
803 		last_extent_written+1 - lba_udf_partition_start,
804 		directory_size(dpnt),
805 		dpnt->self->isorec.date,
806 		1,	/* is_directory */
807 		directory_link_count(dpnt),
808 		(dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector);
809 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
810 	xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
811 	last_extent_written++;
812 
813 	base_sector = last_extent_written - lba_udf_partition_start;
814 
815 	/* parent directory */
816 	parent = dpnt->parent;
817 	if (parent == reloc_dir) {
818 		parent = dpnt->self->parent_rec->filedir;
819 	}
820 	ident_size = set_file_ident_desc(
821 		buf,
822 		base_sector,
823 		0,
824 		1,
825 		parent->self->udf_file_entry_sector - lba_udf_partition_start,
826 		(parent == root) ? 0 : parent->self->udf_file_entry_sector);
827 	jtwrite(buf, ident_size, 1, 0, FALSE);
828 	xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
829 	size_in_bytes = ident_size;
830 
831 	/* directory contents */
832 	for (de = dpnt->jcontents; de; de = de->jnext) {
833 		char *name;
834 		struct directory_entry *de1;
835 
836 		if (de->de_flags & INHIBIT_JOLIET_ENTRY)
837 			continue;
838 
839 		name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
840 
841 		/* skip . and .. */
842 		if (name[0] == '.' && (name[1] == 0 ||
843 		    (name[1] == '.' && name[2] == 0)))
844 			continue;
845 
846 		/* look in RR_MOVED for relocated directories */
847 		de1 = de;
848 		if (de->de_flags & RELOCATED_DIRECTORY) {
849 			for (de1 = reloc_dir->contents; de1; de1 = de1->next) {
850 				if (de1->parent_rec == de) {
851 					break;
852 				}
853 			}
854 			if (!de1) {
855 #ifdef	USE_LIBSCHILY
856 				comerrno(EX_BAD,
857 				"Unable to locate relocated directory\n");
858 #else
859 				fprintf(stderr,
860 				"Unable to locate relocated directory\n");
861 				exit(1);
862 #endif
863 			}
864 		}
865 
866 		ident_size = set_file_ident_desc(
867 			buf,
868 			base_sector + (size_in_bytes / SECTOR_SIZE),
869 			name,
870 			!!(de1->isorec.flags[0] & ISO_DIRECTORY),
871 			de1->udf_file_entry_sector - lba_udf_partition_start,
872 			de1->udf_file_entry_sector);
873 		jtwrite(buf, ident_size, 1, 0, FALSE);
874 		xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
875 		size_in_bytes += ident_size;
876 	}
877 
878 	padded_size_in_bytes = PAD(size_in_bytes, SECTOR_SIZE);
879 	if (size_in_bytes < padded_size_in_bytes) {
880 		memset(buf, 0, padded_size_in_bytes - size_in_bytes);
881 		jtwrite(buf, padded_size_in_bytes - size_in_bytes, 1, 0, FALSE);
882 		xfwrite(buf, padded_size_in_bytes - size_in_bytes, 1, outfile, 0, FALSE);
883 	}
884 
885 	last_extent_written += padded_size_in_bytes / SECTOR_SIZE;
886 }
887 
888 static void
write_udf_directories(struct directory * dpnt,FILE * outfile)889 write_udf_directories(struct directory *dpnt, FILE *outfile)
890 {
891 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
892 		write_one_udf_directory(dpnt, outfile);
893 	}
894 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
895 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
896 			write_udf_directories(dpnt, outfile);
897 		}
898 	}
899 }
900 
901 static void
write_udf_file_entries(struct directory * dpnt,FILE * outfile)902 write_udf_file_entries(struct directory *dpnt, FILE *outfile)
903 {
904 	Uchar buf[SECTOR_SIZE];
905 
906 	memset(buf, 0, SECTOR_SIZE);
907 
908 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
909 		struct directory_entry *de;
910 		for (de = dpnt->jcontents; de; de = de->jnext) {
911 			if (!(de->de_flags & RELOCATED_DIRECTORY) &&
912 			    !(de->isorec.flags[0] & ISO_DIRECTORY)) {
913 
914 				memset(buf, 0, 512);
915 				set_file_entry(
916 					buf,
917 					(last_extent_written++) - lba_udf_partition_start,
918 					read_733(de->isorec.extent) - lba_udf_partition_start,
919 					de->realsize,
920 					de->isorec.date,
921 					0,	/* is_directory */
922 					1,	/* link_count */
923 					de->udf_file_entry_sector);
924 				jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
925 				xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
926 			}
927 		}
928 	}
929 	if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
930 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
931 			write_udf_file_entries(dpnt, outfile);
932 		}
933 	}
934 }
935 
936 /****************************/
937 
938 static int
udf_vol_recognition_area_write(FILE * out)939 udf_vol_recognition_area_write(FILE *out)
940 {
941 	static const char *identifiers[3] = { "BEA01", "NSR02", "TEA01" };
942 	int i;
943 	char buf[SECTOR_SIZE];
944 	udf_volume_recognition_desc *vsd = (udf_volume_recognition_desc *)buf;
945 
946 	memset(buf, 0, sizeof (buf));
947 	/*set8(&vsd->structure_type, 0);*/
948 	set8(&vsd->structure_version, 1);
949 	for (i = 0; i < 3; ++i) {
950 		memcpy(vsd->standard_identifier, identifiers[i], 5);
951 		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
952 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
953 	}
954 	last_extent_written += 3;
955 	return (0);
956 }
957 
958 static int
udf_main_seq_write(FILE * out)959 udf_main_seq_write(FILE *out)
960 {
961 	Uchar buf[SECTOR_SIZE];
962 	int i;
963 
964 	/*
965 	 * volume_set_id needs to be set to a (64-bit) "unique" number.
966 	 * This will have to do for now.
967 	 */
968 	volume_set_id[0] = begun;
969 	volume_set_id[1] = (unsigned)clock();	/* XXX Maybe non-portable */
970 
971 	memset(buf, 0, sizeof (buf));
972 	set_primary_vol_desc(buf, last_extent_written++);
973 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
974 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
975 
976 	memset(buf, 0, sizeof (buf));
977 	set_impl_use_vol_desc(buf, last_extent_written++);
978 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
979 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
980 
981 	memset(buf, 0, sizeof (buf));
982 	set_partition_desc(buf, last_extent_written++);
983 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
984 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
985 
986 	memset(buf, 0, sizeof (buf));
987 	set_logical_vol_desc(buf, last_extent_written++);
988 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
989 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
990 
991 	memset(buf, 0, sizeof (buf));
992 	set_unallocated_space_desc(buf, last_extent_written++);
993 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
994 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
995 
996 	memset(buf, 0, sizeof (buf));
997 	set_terminating_desc(buf, last_extent_written++);
998 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
999 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1000 
1001 	memset(buf, 0, sizeof (buf));
1002 	for (i = 6; i < UDF_MAIN_SEQ_LENGTH; ++i) {
1003         jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
1004 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1005 		last_extent_written++;
1006 	}
1007 
1008 	return (0);
1009 }
1010 
1011 static int
udf_integ_seq_write(FILE * out)1012 udf_integ_seq_write(FILE *out)
1013 {
1014 	Uchar buf[SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH];
1015 
1016 	memset(buf, 0, sizeof (buf));
1017 
1018 	set_logical_vol_integrity_desc(buf+0*SECTOR_SIZE,
1019 						last_extent_written++);
1020 	set_terminating_desc(buf+1*SECTOR_SIZE, last_extent_written++);
1021 
1022 	jtwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, 0, FALSE);
1023 	xfwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, out, 0, FALSE);
1024 	return (0);
1025 }
1026 
1027 static int
udf_anchor_vol_desc_write(FILE * out)1028 udf_anchor_vol_desc_write(FILE *out)
1029 {
1030 	Uchar buf[SECTOR_SIZE];
1031 
1032 	memset(buf, 0, sizeof (buf));
1033 	set_anchor_volume_desc_pointer(buf, last_extent_written++);
1034 	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
1035 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1036 	return (0);
1037 }
1038 
1039 static int
udf_file_set_desc_write(FILE * out)1040 udf_file_set_desc_write(FILE *out)
1041 {
1042 	Uchar buf[SECTOR_SIZE*2];
1043 
1044 	memset(buf, 0, sizeof (buf));
1045 
1046 	set_file_set_desc(buf+0*SECTOR_SIZE,
1047 			(last_extent_written++) - lba_udf_partition_start);
1048 	set_terminating_desc(buf+1*SECTOR_SIZE,
1049 			(last_extent_written++) - lba_udf_partition_start);
1050 
1051 	jtwrite(buf, SECTOR_SIZE, 2, 0, FALSE);
1052 	xfwrite(buf, SECTOR_SIZE, 2, out, 0, FALSE);
1053 
1054 	return (0);
1055 }
1056 
1057 static int
udf_dirtree_write(FILE * out)1058 udf_dirtree_write(FILE *out)
1059 {
1060 	write_udf_directories(root, out);
1061 	return (0);
1062 }
1063 
1064 static int
udf_file_entries_write(FILE * out)1065 udf_file_entries_write(FILE *out)
1066 {
1067 	write_udf_file_entries(root, out);
1068 	return (0);
1069 }
1070 
1071 static int
pad_to(unsigned last_extent_to_write,FILE * out)1072 pad_to(unsigned last_extent_to_write, FILE *out)
1073 {
1074 	char buf[SECTOR_SIZE];
1075 	memset(buf, 0, sizeof (buf));
1076 	while (last_extent_written < last_extent_to_write) {
1077 		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
1078 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1079 		++last_extent_written;
1080 	}
1081 	return (0);
1082 }
1083 
1084 static int
udf_pad_to_sector_32_write(FILE * out)1085 udf_pad_to_sector_32_write(FILE *out)
1086 {
1087 	return (pad_to(session_start+32, out));
1088 }
1089 
1090 static int
udf_pad_to_sector_256_write(FILE * out)1091 udf_pad_to_sector_256_write(FILE *out)
1092 {
1093 	return (pad_to(session_start+256, out));
1094 }
1095 
1096 static int
udf_padend_avdp_write(FILE * out)1097 udf_padend_avdp_write(FILE *out)
1098 {
1099 	Uchar buf[SECTOR_SIZE];
1100 	unsigned last_extent_to_write = (last_extent_written+31) & ~15;
1101 
1102 	if (!use_sparcboot)
1103 		last_extent_to_write = last_extent_written + 150;
1104 
1105 	memset(buf, 0, sizeof (buf));
1106 	while (last_extent_written < last_extent_to_write) {
1107 		set_anchor_volume_desc_pointer(buf, last_extent_written++);
1108 		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
1109 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1110 	}
1111 	return (0);
1112 }
1113 
1114 
1115 struct output_fragment udf_vol_recognition_area_frag = { NULL, udf_vol_recognition_area_size, NULL, udf_vol_recognition_area_write, "UDF volume recognition area" };
1116 struct output_fragment udf_main_seq_frag = { NULL, udf_main_seq_size, NULL, udf_main_seq_write, "UDF main seq" };
1117 struct output_fragment udf_main_seq_copy_frag = { NULL, udf_main_seq_copy_size, NULL, udf_main_seq_write, "UDF second seq" };
1118 struct output_fragment udf_integ_seq_frag = { NULL, udf_integ_seq_size, NULL, udf_integ_seq_write, "UDF integ seq" };
1119 struct output_fragment udf_anchor_vol_desc_frag = { NULL, oneblock_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor volume" };
1120 struct output_fragment udf_file_set_desc_frag = { NULL, udf_file_set_desc_size, NULL, udf_file_set_desc_write, "UDF file set" };
1121 struct output_fragment udf_dirtree_frag = { NULL, udf_dirtree_size, NULL, udf_dirtree_write, "UDF directory tree" };
1122 struct output_fragment udf_file_entries_frag = { NULL, udf_file_entries_size, NULL, udf_file_entries_write, "UDF file entries" };
1123 struct output_fragment udf_end_anchor_vol_desc_frag = { NULL, udf_end_anchor_vol_desc_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor end volume" };
1124 
1125 struct output_fragment udf_pad_to_sector_32_frag = { NULL, udf_pad_to_sector_32_size, NULL, udf_pad_to_sector_32_write, "UDF pad to sector 32" };
1126 struct output_fragment udf_pad_to_sector_256_frag = { NULL, udf_pad_to_sector_256_size, NULL, udf_pad_to_sector_256_write, "UDF pad to sector 256" };
1127 struct output_fragment udf_padend_avdp_frag = { NULL, udf_padend_avdp_size, NULL, udf_padend_avdp_write, "UDF Pad end" };
1128 
1129 /*
1130  * This function assigns weights as follows:
1131  *
1132  * /VIDEO_TS/VIDEO_TS.IFO   11199
1133  * /VIDEO_TS/VIDEO_TS.VOB   11198
1134  * /VIDEO_TS/VIDEO_TS.BUP   11188
1135  * /VIDEO_TS/VTS_01_0.IFO   11187
1136  * /VIDEO_TS/VTS_01_0.VOB   11186
1137  *            :               :
1138  * /VIDEO_TS/VTS_01_9.VOB   11177
1139  * /VIDEO_TS/VTS_01_0.BUP   11176
1140  *            :               :
1141  * /VIDEO_TS/VTS_99_0.BUP   10000
1142  *
1143  * This ensures that DVD-Video files are laid out properly on the disc.
1144  * The same thing is done for AUDIO_TS files, except in the 20000 range
1145  * instead of the 10000 range.
1146  *
1147  * Question: what about JACKET_P files?
1148  *
1149  * Answer: At least as far as I know :)
1150  * JACKET_P files are still images (single frame mpeg video .i.e mp2
1151  * format). The DVD Jacket pictures will be displayed on the TV screen
1152  * when the player is in a stop/resume mode.
1153  * The location is not dependent on IFO information and the only must
1154  * as far as I know is that they are in upper case (both dir and files).
1155  * This sparce information makes me conclude that they don't need any
1156  * weight. This obviously needs to be tested.
1157  */
1158 int
assign_dvd_weights(char * name,struct directory * this_dir,int val)1159 assign_dvd_weights(char *name, struct directory *this_dir, int val)
1160 {
1161 	int ts_number;
1162 	int segment;
1163 	int audio;
1164 
1165 	if (name[0] != 'A' && name[0] != 'V')
1166 		return (val);
1167 
1168 	if (memcmp(name, "VIDEO_TS", 8) == 0) {
1169 		ts_number = 0;
1170 		audio = 0;
1171 	} else if (memcmp(name, "VTS_", 4) == 0) {
1172 		ts_number = 1;
1173 		audio = 0;
1174 	} else if (memcmp(name, "AUDIO_TS", 8) == 0) {
1175 		ts_number = 0;
1176 		audio = 1;
1177 	} else if (memcmp(name, "ATS_", 4) == 0) {
1178 		ts_number = 1;
1179 		audio = 1;
1180 	} else {
1181 		return (val);
1182 	}
1183 
1184 	if (this_dir->parent != root ||
1185 	    strcmp(this_dir->de_name, "VIDEO_TS") != 0)
1186 		return (val);
1187 
1188 	if (ts_number == 0) {
1189 		segment = 0;
1190 	} else {
1191 		if (name[4] >= '0' && name[4] <= '9' &&
1192 		    name[5] >= '0' && name[5] <= '9' &&
1193 		    name[6] == '_' &&
1194 		    name[7] >= '0' && name[7] <= '9') {
1195 			ts_number = name[4] * 10 + name[5] - ('0' * 11);
1196 			segment = name[7] - '0';
1197 		} else {
1198 			return (val);
1199 		}
1200 	}
1201 
1202 	if (strcmp(name+8, audio ? ".AOB" : ".VOB") == 0) {
1203 		return (audio * 10000 - ts_number * 12 - segment + 11198);
1204 	} else if (strcmp(name+8, ".IFO") == 0) {
1205 		return (audio * 10000 - ts_number * 12 + 11199);
1206 	} else if (strcmp(name+8, ".BUP") == 0) {
1207 		return (audio * 10000 - ts_number * 12 + 11188);
1208 	} else {
1209 		return (val);
1210 	}
1211 }
1212 
1213 #endif  /* UDF */
1214