1 /* @(#)udf.c	1.46 16/11/14 Copyright 2001-2016 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)udf.c	1.46 16/11/14 Copyright 2001-2016 J. Schilling";
6 #endif
7 /*
8  * udf.c - UDF support for mkisofs
9  *
10  * Written by Ben Rudiak-Gould (2001).
11  *
12  * Copyright 2001-2016 J. Schilling.
13  */
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License version 2
17  * as published by the Free Software Foundation.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along with
25  * this program; see the file COPYING.  If not, write to the Free Software
26  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  */
28 
29 /*
30  * Some remaining issues:
31  *
32  * - The following functions create directory entries with 2 or
33  *   more AllocationDescriptors:
34  *
35  *	set_file_entry()
36  *	set_macvolume_filed_entry()
37  *	set_attr_file_entry()
38  *	set_filed_entry()
39  *
40  *   To support files > 236 GB, we need to be able to deal with a list
41  *   of direcoty entries that span more than one sector.
42  *
43  * - The link count may be wrong if -hide-udf is used.
44  *
45  * - Do not forget to edit joliet.c and remove the VIDEO_TS lines after
46  *   we did implement a decent own file name handling for UDF.
47  *
48  * - There's no support for hard links. This could be easily fixed since
49  *   the correct harlink support is available.
50  *
51  * - The file system mirrors the Joliet file system, so files excluded
52  *   from Joliet will also be excluded from UDF, the -jcharset option
53  *   also applies to UDF, file names too long for Joliet will also be
54  *   truncated on UDF, and characters not allowed by Joliet will also
55  *   be translated on UDF. (Fortunately, Joliet is pretty lenient.)
56  *
57  * - convert_to_unicode is always called with in_nls, not hfs_nls. This
58  *   may lead to incorrect name conversion sometimes when using a Mac
59  *   filesystem. See joliet.c for an example of what's supposed to be
60  *   done.
61  *
62  * - DVD-Video discs are supposed to have Copyright Management Information
63  *   in both the ISO and UDF filesystems. This is not implemented in ISO,
64  *   and the code to do it in UDF is currently #ifdef'd out. I'm not sure
65  *   whether discs without this information are actually DVD-Video
66  *   compliant. The Copyright Management Information is described in ECMA
67  *   Technical Report TR/71.
68  *
69  * - Most of the space before sector 256 on the disc (~480K) is wasted,
70  *   because UDF Bridge requires a pointer block at sector 256. ISO 9660
71  *   structures could be moved below sector 256 if they're small enough, but
72  *   this would be ugly to implement since it breaks the output_fragment
73  *   abstraction.
74  *
75  * - Each file must have a File Entry, and each File Entry seems to
76  *   require its own 2K sector. As a result, there is an overhead of more
77  *   than 2K *per file* when using UDF. I couldn't see any way to avoid
78  *   this.
79  *
80  * - Read performance would probably be improved by placing the File Entry
81  *   for each file just before the file itself, instead of at the beginning
82  *   of the disc. But this would not work for DVD-Video files, which have
83  *   to be stored contiguously. So there would have to be an override
84  *   mechanism to handle this case. I don't know if it's worth the trouble.
85  */
86 
87 #include "mkisofs.h"
88 #ifdef UDF
89 #include <schily/time.h>
90 #include <schily/device.h>
91 #include <schily/schily.h>
92 #include <schily/errno.h>
93 
94 #include "udf.h"
95 #include "udf_fs.h"
96 #include "bswap.h"
97 
98 extern	int	use_sparcboot;
99 
100 extern struct directory *root;
101 extern struct timeval	tv_begun;
102 
103 static unsigned lba_main_seq;
104 static unsigned lba_main_seq_copy;
105 static unsigned lba_integ_seq;
106 static unsigned lba_udf_partition_start;
107 static unsigned lba_last_file_entry;
108 static unsigned lba_end_anchor_vol_desc;
109 
110 static unsigned num_udf_files;
111 static unsigned num_udf_directories;
112 
113 static unsigned volume_set_id[2] = { 0, 0 };
114 
115 #define	UDF_MAIN_SEQ_LENGTH (16)
116 #define	UDF_INTEG_SEQ_LENGTH (2)
117 
118 /* only works for granularity a power of 2! */
119 #define	PAD(val, granularity)	(((val)+(granularity)-1)&~((granularity)-1))
120 
121 #define	INSERTMACRESFORK 1
122 /* system bit as defined for es_FileInfo.attr */
123 #define	FI_ATTR_SYSTEM		0x0004
124 
125 /**************** SIZE ****************/
126 
127 LOCAL unsigned long getperms __PR((mode_t mode));
128 LOCAL unsigned long getflags __PR((mode_t mode));
129 LOCAL unsigned int directory_size __PR((struct directory *dpnt));
130 LOCAL void	assign_udf_directory_addresses __PR((struct directory *dpnt));
131 LOCAL void	assign_udf_file_entry_addresses __PR((struct directory *dpnt));
132 LOCAL int	udf_vol_recognition_area_size __PR((UInt32_t starting_extent));
133 LOCAL int	udf_main_seq_size __PR((UInt32_t starting_extent));
134 LOCAL int	udf_main_seq_copy_size __PR((UInt32_t starting_extent));
135 LOCAL int	udf_integ_seq_size __PR((UInt32_t starting_extent));
136 LOCAL int	udf_end_anchor_vol_desc_size __PR((UInt32_t starting_extent));
137 LOCAL int	udf_file_set_desc_size __PR((UInt32_t starting_extent));
138 LOCAL int	udf_dirtree_size __PR((UInt32_t starting_extent));
139 LOCAL int	udf_file_entries_size __PR((UInt32_t starting_extent));
140 LOCAL int	udf_pad_to_sector_32_size __PR((UInt32_t starting_extent));
141 LOCAL int	udf_pad_to_sector_256_size __PR((UInt32_t starting_extent));
142 LOCAL int	udf_padend_avdp_size __PR((UInt32_t starting_extent));
143 LOCAL unsigned int crc_ccitt __PR((unsigned char *buf, unsigned int len));
144 LOCAL void	set16 __PR((udf_Uint16 *dst, unsigned int src));
145 LOCAL void	set32 __PR((udf_Uint32 *dst, unsigned int src));
146 LOCAL void	set64 __PR((udf_Uint64 *dst, ULlong src));
147 LOCAL int	set_ostaunicode __PR((unsigned char *dst, int dst_size, char *src));
148 LOCAL void	set_extent __PR((udf_extent_ad *ext, UInt32_t lba, unsigned int length_bytes));
149 LOCAL void	set_dstring __PR((udf_dstring *dst, char *src, int n));
150 LOCAL void	set_charspec __PR((udf_charspec *dst));
151 LOCAL void	set_impl_ident __PR((udf_EntityID *ent));
152 LOCAL void	set_tag __PR((udf_tag *t, unsigned int tid, UInt32_t lba, int crc_length));
153 LOCAL void	set_timestamp_from_timespec __PR((udf_timestamp	*ts, timesp *tsp));
154 LOCAL void	set_timestamp_from_iso_date __PR((udf_timestamp *ts, const char *iso_date_raw));
155 LOCAL void	set_timestamp_from_time_t __PR((udf_timestamp *ts, time_t t));
156 LOCAL void	set_anchor_volume_desc_pointer __PR((unsigned char *buf, UInt32_t lba));
157 LOCAL void	set_primary_vol_desc __PR((unsigned char *buf, UInt32_t lba));
158 LOCAL void	set_impl_use_vol_desc __PR((unsigned char *buf, UInt32_t lba));
159 LOCAL void	set_partition_desc __PR((unsigned char *buf, UInt32_t lba));
160 LOCAL void	set_domain_ident __PR((udf_EntityID *ent));
161 LOCAL void	set_logical_vol_desc __PR((unsigned char *buf, UInt32_t lba));
162 LOCAL void	set_unallocated_space_desc __PR((unsigned char *buf, UInt32_t lba));
163 LOCAL void	set_terminating_desc __PR((unsigned char *buf, UInt32_t lba));
164 LOCAL void	set_logical_vol_integrity_desc __PR((unsigned char *buf, UInt32_t lba));
165 LOCAL void	set_file_set_desc __PR((unsigned char *buf, UInt32_t rba));
166 LOCAL int	set_file_ident_desc __PR((unsigned char *, UInt32_t, char *, int, UInt32_t, unsigned));
167 LOCAL void	set_file_entry __PR((unsigned char *buf, UInt32_t rba, UInt32_t file_rba,
168 			off_t length, int is_directory,
169 			unsigned link_count, unsigned unique_id, hfsdirent *hfs_ent,
170 			unsigned long res_log_block, struct directory_entry *de));
171 LOCAL void	udf_size_panic	__PR((int n));
172 LOCAL void	set_macvolume_filed_entry __PR((unsigned char *buf, UInt32_t rba, UInt32_t file_rba,
173 			unsigned length, int is_directory,
174 			unsigned link_count, unsigned unique_id, hfsdirent *hfs_ent,
175 			struct directory_entry *de));
176 LOCAL void	set_attr_file_entry __PR((unsigned char *buf, unsigned rba, unsigned file_rba,
177 			off_t length, int is_directory,
178 			unsigned link_count, unsigned unique_id, hfsdirent *hfs_ent,
179 			struct directory_entry *de));
180 LOCAL void	set_filed_entry __PR((unsigned char *buf, unsigned rba, unsigned file_rba,
181 			unsigned length, int is_directory,
182 			unsigned link_count, unsigned unique_id, hfsdirent *hfs_ent,
183 			struct directory_entry *de));
184 LOCAL unsigned int directory_link_count __PR((struct directory *dpnt));
185 LOCAL void	write_one_udf_directory __PR((struct directory *dpnt, FILE *outfile));
186 LOCAL void	write_udf_directories __PR((struct directory *dpnt, FILE *outfile));
187 LOCAL void	write_udf_file_entries __PR((struct directory *dpnt, FILE *outfile));
188 LOCAL int	udf_vol_recognition_area_write __PR((FILE *out));
189 LOCAL int	udf_main_seq_write __PR((FILE *out));
190 LOCAL int	udf_integ_seq_write __PR((FILE *out));
191 LOCAL int	udf_anchor_vol_desc_write __PR((FILE *out));
192 LOCAL int	udf_file_set_desc_write __PR((FILE *out));
193 LOCAL int	udf_dirtree_write __PR((FILE *out));
194 LOCAL int	udf_file_entries_write __PR((FILE *out));
195 LOCAL int	pad_to __PR((UInt32_t last_extent_to_write, FILE *out));
196 LOCAL int	udf_pad_to_sector_32_write __PR((FILE *out));
197 LOCAL int	udf_pad_to_sector_256_write __PR((FILE *out));
198 LOCAL int	udf_padend_avdp_write __PR((FILE *out));
199 
200 EXPORT void	udf_set_extattr_freespace __PR((unsigned char *buf, off_t size, unsigned rba));
201 EXPORT void	udf_set_extattr_macresfork __PR((unsigned char *buf, off_t size, unsigned rba));
202 EXPORT int	assign_dvd_weights __PR((char *name, struct directory *this_dir, int val));
203 EXPORT int	udf_get_symlinkcontents __PR((char *filename, char *contents, off_t *size));
204 
205 /*
206  * get file access modes
207  * although it seems as if UDF modes are the same as UNIX modes
208  * this is just to make sure
209  */
210 LOCAL unsigned long
211 #ifdef	PROTOTYPES
getperms(mode_t mode)212 getperms(mode_t mode)
213 #else
214 getperms(mode)
215 	mode_t	mode;
216 #endif
217 {
218 	long m = 0;
219 
220 	if (mode & S_IRUSR)
221 		m |= UDF_FILEENTRY_PERMISSION_UR;
222 
223 	/* not allowed on DVD read-only media according to TR/71 3.5.4 */
224 	/*
225 	 * but is required if image is used e.g. as backup medium
226 	 * so we implement UDF_FILEENTRY_PERMISSION_UW
227 	 */
228 	if (mode & S_IWUSR)
229 		m |= UDF_FILEENTRY_PERMISSION_UW;
230 
231 	if (mode & S_IXUSR)
232 		m |= UDF_FILEENTRY_PERMISSION_UX;
233 
234 	if (mode & S_IRGRP)
235 		m |= UDF_FILEENTRY_PERMISSION_GR;
236 
237 	/* not allowed on DVD read-only media according to TR/71 3.5.4 */
238 	/*
239 	 * but is required if image is used e.g. as backup medium
240 	 * so we implement UDF_FILEENTRY_PERMISSION_GW
241 	 */
242 	if (mode & S_IWGRP)
243 		m |= UDF_FILEENTRY_PERMISSION_GW;
244 
245 	if (mode & S_IXGRP)
246 		m |= UDF_FILEENTRY_PERMISSION_GX;
247 
248 	if (mode & S_IROTH)
249 		m |= UDF_FILEENTRY_PERMISSION_OR;
250 
251 	/* not allowed on DVD read-only media according to TR/71 3.5.4 */
252 	/*
253 	 * but is required if image is used e.g. as backup medium
254 	 * so we implement UDF_FILEENTRY_PERMISSION_OW
255 	 */
256 	if (mode & S_IWOTH)
257 		m |= UDF_FILEENTRY_PERMISSION_OW;
258 
259 	if (mode & S_IXOTH)
260 		m |= UDF_FILEENTRY_PERMISSION_OX;
261 
262 	return (m);
263 }
264 
265 /*
266  * get UNIX special modes: S_ISUID, S_ISGID, S_ISVTX
267  * The result is not stored in the UDF permisson but in the flags.
268  */
269 LOCAL unsigned long
270 #ifdef	PROTOTYPES
getflags(mode_t mode)271 getflags(mode_t mode)
272 #else
273 getflags(mode)
274 	mode_t	mode;
275 #endif
276 {
277 	long f = 0;
278 
279 	if (mode & S_ISUID)
280 		f |= UDF_ICBTAG_FLAG_SETUID;
281 	if (mode & S_ISGID)
282 		f |= UDF_ICBTAG_FLAG_SETGID;
283 	if (mode & S_ISVTX)
284 		f |= UDF_ICBTAG_FLAG_STICKY;
285 
286 	return (f);
287 }
288 
289 LOCAL unsigned
directory_size(dpnt)290 directory_size(dpnt)
291 	struct directory	*dpnt;
292 {
293 	unsigned size_in_bytes;
294 	struct directory_entry *de;
295 	Uchar dummy_buf[SECTOR_SIZE];
296 
297 	/* parent directory */
298 	size_in_bytes = set_file_ident_desc(dummy_buf, 0, 0, 0, 0, 0);
299 
300 	/* directory contents */
301 	for (de = dpnt->jcontents; de; de = de->jnext) {
302 		if (!(de->de_flags & INHIBIT_UDF_ENTRY)) {
303 			char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
304 			/* skip . and .. */
305 			if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
306 				continue;
307 			size_in_bytes += set_file_ident_desc(dummy_buf, 0, name, 0, 0, 0);
308 		}
309 	}
310 	return (size_in_bytes);
311 }
312 
313 LOCAL void
assign_udf_directory_addresses(dpnt)314 assign_udf_directory_addresses(dpnt)
315 	struct directory	*dpnt;
316 {
317 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
318 		dpnt->self->udf_file_entry_sector = last_extent;
319 		last_extent += 1 + ISO_BLOCKS(directory_size(dpnt));
320 		++num_udf_directories;
321 	}
322 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
323 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
324 			assign_udf_directory_addresses(dpnt);
325 		}
326 	}
327 }
328 
329 LOCAL void
assign_udf_file_entry_addresses(dpnt)330 assign_udf_file_entry_addresses(dpnt)
331 	struct directory	*dpnt;
332 {
333 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
334 		struct directory_entry *de;
335 		for (de = dpnt->jcontents; de; de = de->jnext) {
336 			if (de->de_flags & INHIBIT_UDF_ENTRY)
337 				continue;
338 			if (!(de->de_flags & RELOCATED_DIRECTORY) &&
339 			    !(de->isorec.flags[0] & ISO_DIRECTORY)) {
340 				de->udf_file_entry_sector = last_extent++;
341 				++num_udf_files;
342 #ifdef INSERTMACRESFORK
343 				if (de->assoc) {
344 					last_extent++;
345 					num_udf_files--;
346 				}
347 #endif
348 			}
349 		}
350 	}
351 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
352 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
353 			assign_udf_file_entry_addresses(dpnt);
354 		}
355 	}
356 }
357 
358 /****************************/
359 
360 LOCAL int
udf_vol_recognition_area_size(starting_extent)361 udf_vol_recognition_area_size(starting_extent)
362 	UInt32_t	starting_extent;
363 {
364 	last_extent = starting_extent+3;
365 	return (0);
366 }
367 
368 LOCAL int
udf_main_seq_size(starting_extent)369 udf_main_seq_size(starting_extent)
370 	UInt32_t	starting_extent;
371 {
372 	lba_main_seq = starting_extent;
373 	last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
374 	return (0);
375 }
376 
377 LOCAL int
udf_main_seq_copy_size(starting_extent)378 udf_main_seq_copy_size(starting_extent)
379 	UInt32_t	starting_extent;
380 {
381 	lba_main_seq_copy = starting_extent;
382 	last_extent = starting_extent + UDF_MAIN_SEQ_LENGTH;
383 	return (0);
384 }
385 
386 LOCAL int
udf_integ_seq_size(starting_extent)387 udf_integ_seq_size(starting_extent)
388 	UInt32_t	starting_extent;
389 {
390 	lba_integ_seq = starting_extent;
391 	last_extent = starting_extent + UDF_INTEG_SEQ_LENGTH;
392 	return (0);
393 }
394 
395 LOCAL int
udf_end_anchor_vol_desc_size(starting_extent)396 udf_end_anchor_vol_desc_size(starting_extent)
397 	UInt32_t	starting_extent;
398 {
399 	lba_end_anchor_vol_desc = starting_extent;
400 	last_extent = starting_extent+1;
401 	return (0);
402 }
403 
404 LOCAL int
udf_file_set_desc_size(starting_extent)405 udf_file_set_desc_size(starting_extent)
406 	UInt32_t	starting_extent;
407 {
408 	lba_udf_partition_start = starting_extent;
409 	last_extent = starting_extent+2;
410 	return (0);
411 }
412 
413 LOCAL int
udf_dirtree_size(starting_extent)414 udf_dirtree_size(starting_extent)
415 	UInt32_t	starting_extent;
416 {
417 	num_udf_directories = 0;
418 	assign_udf_directory_addresses(root);
419 	return (0);
420 }
421 
422 LOCAL int
udf_file_entries_size(starting_extent)423 udf_file_entries_size(starting_extent)
424 	UInt32_t	starting_extent;
425 {
426 	num_udf_files = 0;
427 	assign_udf_file_entry_addresses(root);
428 	lba_last_file_entry = last_extent-1;
429 	return (0);
430 }
431 
432 LOCAL int
udf_pad_to_sector_32_size(starting_extent)433 udf_pad_to_sector_32_size(starting_extent)
434 	UInt32_t	starting_extent;
435 {
436 	if (last_extent < session_start+32)
437 		last_extent = session_start+32;
438 	return (0);
439 }
440 
441 LOCAL int
udf_pad_to_sector_256_size(starting_extent)442 udf_pad_to_sector_256_size(starting_extent)
443 	UInt32_t	starting_extent;
444 {
445 	if (last_extent < session_start+256)
446 		last_extent = session_start+256;
447 	return (0);
448 }
449 
450 LOCAL int
udf_padend_avdp_size(starting_extent)451 udf_padend_avdp_size(starting_extent)
452 	UInt32_t	starting_extent;
453 {
454 	lba_end_anchor_vol_desc = starting_extent;
455 
456 	/* add at least 16 and at most 31 sectors, ending at a mult. of 16 */
457 	last_extent = (starting_extent+31) & ~15;
458 	if (!use_sparcboot)
459 		last_extent = starting_extent + 150;
460 	return (0);
461 }
462 
463 /**************** WRITE ****************/
464 
465 LOCAL unsigned
crc_ccitt(buf,len)466 crc_ccitt(buf, len)
467 	unsigned char	*buf;
468 	unsigned	len;
469 {
470 	const unsigned poly = 0x11021;
471 static	unsigned short lookup[256];
472 	unsigned int r;
473 	unsigned int i;
474 
475 	if (lookup[1] == 0) {
476 		unsigned int j, k;
477 		for (j = 0; j < 256; ++j) {
478 			unsigned int temp = j << 8;
479 			for (k = 0; k < 8; ++k) {
480 				unsigned int hibit = temp & 32768;
481 				temp <<= 1;
482 				if (hibit)
483 					temp ^= poly;
484 			}
485 			lookup[j] = temp;
486 		}
487 	}
488 
489 	r = 0;
490 	for (i = 0; i < len; ++i) {
491 		r = (r << 8) ^ lookup[((r >> 8) ^ buf[i]) & 255];
492 	}
493 
494 	return (r & 65535);
495 }
496 
497 #define	set8(dst, src)	do { *(dst) = (src); } while (0)
498 
499 LOCAL void
set16(dst,src)500 set16(dst, src)
501 	udf_Uint16	*dst;
502 	unsigned int	src;
503 {
504 	dst->l = (char)(src);
505 	dst->h = (char)(src>>8);
506 }
507 
508 LOCAL void
set32(dst,src)509 set32(dst, src)
510 	udf_Uint32	*dst;
511 	unsigned	src;
512 {
513 	dst->l  = (char)(src);
514 	dst->ml = (char)(src>>8);
515 	dst->mh = (char)(src>>16);
516 	dst->h  = (char)(src>>24);
517 }
518 
519 LOCAL void
set64(dst,src)520 set64(dst, src)
521 	udf_Uint64	*dst;
522 	ULlong 		src;
523 {
524 	ULlong ll1;
525 	ULlong ll2;
526 
527 	set32(&dst->l, src);
528 	/*
529 	 * src>>32 actually does the wrong thing on x86 with at least
530 	 * one compiler, because of x86's shift count masking.
531 	 * The following code should work with all compilers
532 	 */
533 	/*set32(&dst->h, src>>32);*/
534 	ll1 = src >> 24;
535 	ll2 = ll1 >> 8;
536 	set32(&dst->h, ll2);
537 }
538 
539 LOCAL int
set_ostaunicode(dst,dst_size,src)540 set_ostaunicode(dst, dst_size, src)
541 	unsigned char	*dst;
542 	int		dst_size;
543 	char		*src;
544 {
545 	unsigned char buf[1024];
546 	int i;
547 	int expanded_length;
548 
549 	expanded_length = joliet_strlen(src, 1024, in_nls);
550 	if (expanded_length > 1024)
551 		expanded_length = 1024;
552 	if (expanded_length > (dst_size-1)*2)
553 		expanded_length = (dst_size-1)*2;
554 
555 	convert_to_unicode(buf, expanded_length, src, in_nls);
556 	dst[0] = 8;	/* use 8-bit representation by default */
557 	for (i = 0; i < (expanded_length>>1); ++i) {
558 		dst[i + 1] = buf[i*2+1];
559 		if (buf[i*2] != 0) {
560 			/*
561 			 * There's a Unicode character with value >=256.
562 			 * Use 16-bit representation instead.
563 			 */
564 			int length_to_copy = (dst_size-1) & ~1;
565 			if (length_to_copy > expanded_length)
566 				length_to_copy = expanded_length;
567 			dst[0] = 16;
568 			memcpy(dst+1, buf, length_to_copy);
569 			return (length_to_copy + 1);
570 		}
571 	}
572 	return ((expanded_length>>1) + 1);
573 }
574 
575 LOCAL void
set_extent(ext,lba,length_bytes)576 set_extent(ext, lba, length_bytes)
577 	udf_extent_ad	*ext;
578 	UInt32_t	lba;
579 	unsigned	length_bytes;
580 {
581 	set32(&ext->extent_length, length_bytes);
582 	set32(&ext->extent_location, lba);
583 }
584 
585 LOCAL void
set_dstring(dst,src,n)586 set_dstring(dst, src, n)
587 	udf_dstring	*dst;
588 	char		*src;
589 	int		n;
590 {
591 	dst[n-1] = set_ostaunicode((Uchar *)dst, n-1, src);
592 }
593 
594 LOCAL void
set_charspec(dst)595 set_charspec(dst)
596 	udf_charspec	*dst;
597 {
598 	/*set8(&dst->character_set_type, 0);*/
599 	memcpy(dst->character_set_info, "OSTA Compressed Unicode", 23);
600 }
601 
602 LOCAL void
set_impl_ident(ent)603 set_impl_ident(ent)
604 	udf_EntityID	*ent;
605 {
606 	strcpy((char *)ent->ident, "*mkisofs");
607 }
608 
609 LOCAL void
set_tag(t,tid,lba,crc_length)610 set_tag(t, tid, lba, crc_length)
611 	udf_tag	*t;
612 	unsigned	tid;
613 	UInt32_t	lba;
614 	int		crc_length;
615 {
616 	unsigned char checksum;
617 	int i;
618 
619 	set16(&t->tag_ident, tid);
620 	set16(&t->desc_version, 2);
621 	set16(&t->desc_crc, crc_ccitt((unsigned char *)t+16, crc_length-16));
622 	set16(&t->desc_crc_length, crc_length-16);
623 	set32(&t->tag_location, lba);
624 	set8(&t->tag_checksum, 0);
625 	checksum = 0;
626 	for (i = 0; i < 16; ++i)
627 		checksum += ((unsigned char *)t)[i];
628 	set8(&t->tag_checksum, checksum);
629 }
630 
631 LOCAL void
set_timestamp_from_timespec(ts,tsp)632 set_timestamp_from_timespec(ts, tsp)
633 	udf_timestamp	*ts;
634 	timesp		*tsp;
635 {
636 	struct tm	*tmp = gmtime(&tsp->tv_sec);
637 	int		usec = tsp->tv_nsec / 1000;
638 
639 	set16(&ts->type_and_time_zone, 4096);	/* "Local time" == GMT */
640 	set16(&ts->year, 1900 + tmp->tm_year);
641 	set8(&ts->month, tmp->tm_mon + 1);
642 	set8(&ts->day, tmp->tm_mday);
643 	set8(&ts->hour, tmp->tm_hour);
644 	set8(&ts->minute, tmp->tm_min);
645 	set8(&ts->second, tmp->tm_sec);
646 	set8(&ts->centiseconds, usec / 10000);
647 	usec %= 10000;
648 	set8(&ts->hundreds_of_microseconds, usec / 100);
649 	set8(&ts->microseconds, usec % 100);
650 }
651 
652 LOCAL void
set_timestamp_from_iso_date(ts,iso_date_raw)653 set_timestamp_from_iso_date(ts, iso_date_raw)
654 	udf_timestamp	*ts;
655 	const char	*iso_date_raw;
656 {
657 	struct {
658 		unsigned char years_since_1900;
659 		unsigned char month, day;
660 		unsigned char hour, minute, second;
661 		signed char offset_from_gmt;
662 	} *iso_date = (void *)iso_date_raw;
663 
664 	set16(&ts->type_and_time_zone,
665 		4096 + ((iso_date->offset_from_gmt * 15) & 4095));
666 	set16(&ts->year, 1900 + iso_date->years_since_1900);
667 	set8(&ts->month, iso_date->month);
668 	set8(&ts->day, iso_date->day);
669 	set8(&ts->hour, iso_date->hour);
670 	set8(&ts->minute, iso_date->minute);
671 	set8(&ts->second, iso_date->second);
672 	/*set8(&ts->centiseconds, 0);*/
673 	/*set8(&ts->hundreds_of_microseconds, 0);*/
674 	/*set8(&ts->microseconds, 0);*/
675 }
676 
677 LOCAL void
set_timestamp_from_time_t(ts,t)678 set_timestamp_from_time_t(ts, t)
679 	udf_timestamp	*ts;
680 	time_t		t;
681 {
682 	char iso_date[7];
683 	iso9660_date(iso_date, t);
684 	set_timestamp_from_iso_date(ts, iso_date);
685 }
686 
687 
688 LOCAL void
set_anchor_volume_desc_pointer(buf,lba)689 set_anchor_volume_desc_pointer(buf, lba)
690 	unsigned char	*buf;
691 	UInt32_t	lba;
692 {
693 	udf_anchor_volume_desc_ptr *avdp = (udf_anchor_volume_desc_ptr *)buf;
694 	set_extent(&avdp->main_volume_desc_seq_extent,
695 		lba_main_seq, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
696 	set_extent(&avdp->reserve_volume_desc_seq_extent,
697 		lba_main_seq_copy, SECTOR_SIZE*UDF_MAIN_SEQ_LENGTH);
698 	set_tag(&avdp->desc_tag, UDF_TAGID_ANCHOR_VOLUME_DESC_PTR, lba, 512);
699 }
700 
701 LOCAL void
set_primary_vol_desc(buf,lba)702 set_primary_vol_desc(buf, lba)
703 	unsigned char	*buf;
704 	UInt32_t	lba;
705 {
706 	char temp[17];
707 
708 	udf_primary_volume_desc *pvd = (udf_primary_volume_desc *)buf;
709 	/*set32(&pvd->volume_desc_seq_number, 0);*/
710 	/*set32(&pvd->primary_volume_desc_number, 0);*/
711 	set_dstring(pvd->volume_ident, volume_id, sizeof (pvd->volume_ident));
712 	set16(&pvd->volume_seq_number, 1);
713 	set16(&pvd->maximum_volume_seq_number, 1);
714 	set16(&pvd->interchange_level, 2);
715 	set16(&pvd->maximum_interchange_level, 2);
716 	set32(&pvd->character_set_list, 1);
717 	set32(&pvd->maximum_character_set_list, 1);
718 	sprintf(temp, "%08X%08X", volume_set_id[0], volume_set_id[1]);
719 	set_dstring(pvd->volume_set_ident, temp,
720 					sizeof (pvd->volume_set_ident));
721 	set_charspec(&pvd->desc_character_set);
722 	set_charspec(&pvd->explanatory_character_set);
723 	/*pvd->volume_abstract;*/
724 	/*pvd->volume_copyright_notice;*/
725 	/*pvd->application_ident;*/
726 	set_timestamp_from_time_t(&pvd->recording_date_and_time, tv_begun.tv_sec);
727 	set_impl_ident(&pvd->impl_ident);
728 	set_tag(&pvd->desc_tag, UDF_TAGID_PRIMARY_VOLUME_DESC, lba, 512);
729 }
730 
731 LOCAL void
set_impl_use_vol_desc(buf,lba)732 set_impl_use_vol_desc(buf, lba)
733 	unsigned char	*buf;
734 	UInt32_t	lba;
735 {
736 	udf_impl_use_volume_desc *iuvd = (udf_impl_use_volume_desc *)buf;
737 	set32(&iuvd->volume_desc_seq_number, 1);
738 	strcpy((char *)iuvd->impl_ident.ident, "*UDF LV Info");
739 	iuvd->impl_ident.ident_suffix[0] = 2;
740 	iuvd->impl_ident.ident_suffix[1] = 1;
741 	set_charspec(&iuvd->impl_use.lvi_charset);
742 	set_dstring(iuvd->impl_use.logical_volume_ident, volume_id,
743 		sizeof (iuvd->impl_use.logical_volume_ident));
744 	/*set_dstring(iuvd->impl_use.lv_info1, "", sizeof (iuvd->impl_use.lv_info1));*/
745 	/*set_dstring(iuvd->impl_use.lv_info2, "", sizeof (iuvd->impl_use.lv_info2));*/
746 	/*set_dstring(iuvd->impl_use.lv_info3, "", sizeof (iuvd->impl_use.lv_info3));*/
747 	set_impl_ident(&iuvd->impl_use.impl_id);
748 	set_tag(&iuvd->desc_tag, UDF_TAGID_IMPL_USE_VOLUME_DESC, lba, 512);
749 }
750 
751 LOCAL void
set_partition_desc(buf,lba)752 set_partition_desc(buf, lba)
753 	unsigned char	*buf;
754 	UInt32_t	lba;
755 {
756 	udf_partition_desc *pd = (udf_partition_desc *)buf;
757 	set32(&pd->volume_desc_seq_number, 2);
758 	set16(&pd->partition_flags, UDF_PARTITION_FLAG_ALLOCATED);
759 	/*set16(&pd->partition_number, 0);*/
760 	set8(&pd->partition_contents.flags, UDF_ENTITYID_FLAG_PROTECTED);	/*???*/
761 	strcpy((char *)pd->partition_contents.ident, "+NSR02");
762 	set32(&pd->access_type, UDF_ACCESSTYPE_READONLY);
763 	set32(&pd->partition_starting_location, lba_udf_partition_start);
764 	set32(&pd->partition_length,
765 			lba_end_anchor_vol_desc - lba_udf_partition_start);
766 	set_impl_ident(&pd->impl_ident);
767 	set_tag(&pd->desc_tag, UDF_TAGID_PARTITION_DESC, lba, 512);
768 }
769 
770 LOCAL void
set_domain_ident(ent)771 set_domain_ident(ent)
772 	udf_EntityID	*ent;
773 {
774 	strcpy((char *)ent->ident, "*OSTA UDF Compliant");
775 	memcpy(ent->ident_suffix, "\002\001\003", 3);
776 }
777 
778 LOCAL void
set_logical_vol_desc(buf,lba)779 set_logical_vol_desc(buf, lba)
780 	unsigned char	*buf;
781 	UInt32_t	lba;
782 {
783 	udf_logical_volume_desc *lvd = (udf_logical_volume_desc *)buf;
784 	set32(&lvd->volume_desc_seq_number, 3);
785 	set_charspec(&lvd->desc_character_set);
786 	set_dstring(lvd->logical_volume_ident, volume_id,
787 					sizeof (lvd->logical_volume_ident));
788 	set32(&lvd->logical_block_size, SECTOR_SIZE);
789 	set_domain_ident(&lvd->domain_ident);
790 	set32(&lvd->logical_volume_contents_use.extent_length, 2*SECTOR_SIZE);
791 	/*set32(&lvd->logical_volume_contents_use.extent_location.logical_block_number, 0);*/
792 	/*set16(&lvd->logical_volume_contents_use.extent_location.partition_reference_number, 0);*/
793 	set32(&lvd->map_table_length, 6);
794 	set32(&lvd->number_of_partition_maps, 1);
795 	set_impl_ident(&lvd->impl_ident);
796 	set_extent(&lvd->integrity_seq_extent, lba_integ_seq,
797 					SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH);
798 	set8(&lvd->partition_map[0].partition_map_type,
799 					UDF_PARTITION_MAP_TYPE_1);
800 	set8(&lvd->partition_map[0].partition_map_length, 6);
801 	set16(&lvd->partition_map[0].volume_seq_number, 1);
802 	/*set16(&lvd->partition_map[0].partition_number, 0);*/
803 	set_tag(&lvd->desc_tag, UDF_TAGID_LOGICAL_VOLUME_DESC, lba, 446);
804 }
805 
806 LOCAL void
set_unallocated_space_desc(buf,lba)807 set_unallocated_space_desc(buf, lba)
808 	unsigned char	*buf;
809 	UInt32_t	lba;
810 {
811 	udf_unallocated_space_desc *usd = (udf_unallocated_space_desc *)buf;
812 	set32(&usd->volume_desc_seq_number, 4);
813 	/*set32(&usd->number_of_allocation_descs, 0);*/
814 	set_tag(&usd->desc_tag, UDF_TAGID_UNALLOCATED_SPACE_DESC, lba, 24);
815 }
816 
817 LOCAL void
set_terminating_desc(buf,lba)818 set_terminating_desc(buf, lba)
819 	unsigned char	*buf;
820 	UInt32_t	lba;
821 {
822 	udf_terminating_desc *td = (udf_terminating_desc *)buf;
823 	set_tag(&td->desc_tag, UDF_TAGID_TERMINATING_DESC, lba, 512);
824 }
825 
826 LOCAL void
set_logical_vol_integrity_desc(buf,lba)827 set_logical_vol_integrity_desc(buf, lba)
828 	unsigned char	*buf;
829 	UInt32_t	lba;
830 {
831 	udf_logical_volume_integrity_desc *lvid =
832 				(udf_logical_volume_integrity_desc *)buf;
833 
834 	set_timestamp_from_time_t(&lvid->recording_date, tv_begun.tv_sec);
835 	set32(&lvid->integrity_type, UDF_INTEGRITY_TYPE_CLOSE);
836 	/*lvid->next_integrity_extent;*/
837 	set64(&lvid->logical_volume_contents_use.unique_id,
838 						lba_last_file_entry+1);
839 	set32(&lvid->number_of_partitions, 1);
840 	set32(&lvid->length_of_impl_use, 46);
841 	/*set32(&lvid->free_space_table, 0);*/
842 	set32(&lvid->size_table,
843 			lba_end_anchor_vol_desc - lba_udf_partition_start);
844 	set_impl_ident(&lvid->impl_use.impl_id);
845 	set32(&lvid->impl_use.number_of_files, num_udf_files);
846 	set32(&lvid->impl_use.number_of_directories, num_udf_directories);
847 	/* note by HELIOS: the following three need to be 0x200 if extended file entries are used */
848 	set16(&lvid->impl_use.minimum_udf_read_revision, 0x102);
849 	set16(&lvid->impl_use.minimum_udf_write_revision, 0x102);
850 	set16(&lvid->impl_use.maximum_udf_write_revision, 0x102);
851 	set_tag(&lvid->desc_tag, UDF_TAGID_LOGICAL_VOLUME_INTEGRITY_DESC,
852 								lba, 88+46);
853 }
854 
855 LOCAL void
set_file_set_desc(buf,rba)856 set_file_set_desc(buf, rba)
857 	unsigned char	*buf;
858 	UInt32_t	rba;
859 {
860 	udf_file_set_desc *fsd = (udf_file_set_desc *)buf;
861 
862 	set_timestamp_from_time_t(&fsd->recording_date_and_time, tv_begun.tv_sec);
863 	set16(&fsd->interchange_level, 3);
864 	set16(&fsd->maximum_interchange_level, 3);
865 	set32(&fsd->character_set_list, 1);
866 	set32(&fsd->maximum_character_set_list, 1);
867 	/*set32(&fsd->file_set_number, 0);*/
868 	/*set32(&fsd->file_set_desc_number, 0);*/
869 	set_charspec(&fsd->logical_volume_ident_character_set);
870 	set_dstring(fsd->logical_volume_ident, volume_id,
871 					sizeof (fsd->logical_volume_ident));
872 	set_charspec(&fsd->file_set_character_set);
873 	set_dstring(fsd->file_set_ident, volume_id,
874 					sizeof (fsd->file_set_ident));
875 	/*fsd->copyright_file_ident;*/
876 	/*fsd->abstract_file_ident;*/
877 	set32(&fsd->root_directory_icb.extent_length, SECTOR_SIZE);
878 	set32(&fsd->root_directory_icb.extent_location.logical_block_number,
879 		root->self->udf_file_entry_sector - lba_udf_partition_start);
880 	set_domain_ident(&fsd->domain_ident);
881 	/*fsd->next_extent;*/
882 	set_tag(&fsd->desc_tag, UDF_TAGID_FILE_SET_DESC, rba, 512);
883 }
884 
885 LOCAL int
set_file_ident_desc(buf,rba,name,is_directory,file_entry_rba,unique_id)886 set_file_ident_desc(buf, rba, name, is_directory, file_entry_rba, unique_id)
887 	unsigned char	*buf;
888 	UInt32_t	rba;
889 	char		*name;
890 	int		is_directory;
891 	UInt32_t	file_entry_rba;
892 	unsigned	unique_id;
893 {
894 	udf_file_ident_desc *fid = (udf_file_ident_desc *)buf;
895 	int length_of_file_ident, length, padded_length;
896 	set16(&fid->file_version_number, 1);
897 	set8(&fid->file_characteristics,
898 		(is_directory ? UDF_FILE_CHARACTERISTIC_DIRECTORY : 0)
899 		+ (name == 0) * UDF_FILE_CHARACTERISTIC_PARENT);
900 	set32(&fid->icb.extent_length, SECTOR_SIZE);
901 	set32(&fid->icb.extent_location.logical_block_number, file_entry_rba);
902 	set16(&fid->icb.extent_location.partition_reference_number, 0);
903 	set32(&fid->icb.impl_use.unique_id, unique_id);
904 	set16(&fid->length_of_impl_use, 0);
905 	if (name) {
906 		length_of_file_ident =
907 			set_ostaunicode((Uchar *)fid->file_ident, 256, name);
908 	} else {
909 		length_of_file_ident = 0;
910 	}
911 	set8(&fid->length_of_file_ident, length_of_file_ident);
912 	length = 38 + length_of_file_ident;
913 	padded_length = PAD(length, 4);
914 	while (length < padded_length) {
915 		buf[length++] = 0;
916 	}
917 	set_tag(&fid->desc_tag, UDF_TAGID_FILE_IDENT_DESC, rba, length);
918 	return (length);
919 }
920 
921 LOCAL void
922 #ifdef PROTOTYPES
set_file_entry(unsigned char * buf,UInt32_t rba,UInt32_t file_rba,off_t length,int is_directory,unsigned link_count,unsigned unique_id,hfsdirent * hfs_ent,unsigned long res_log_block,struct directory_entry * de)923 set_file_entry(unsigned char *buf,
924 	UInt32_t rba,
925 	UInt32_t file_rba,
926 	off_t length,
927 	int is_directory,
928 	unsigned link_count,
929 	unsigned unique_id,
930 
931 	hfsdirent *hfs_ent,
932 	unsigned long res_log_block,
933 	struct directory_entry *de)
934 #else
935 set_file_entry(buf, rba, file_rba, length, is_directory, link_count,
936 		unique_id, hfs_ent,
937 		res_log_block, de)
938 	unsigned char	*buf;
939 	UInt32_t	rba;
940 	UInt32_t	file_rba;
941 	off_t		length;
942 	int		is_directory;
943 	unsigned	link_count;
944 	unsigned	unique_id;
945 
946 	hfsdirent	*hfs_ent;
947 	unsigned long	res_log_block;
948 	struct directory_entry *de;
949 #endif
950 {
951 	udf_short_ad	*allocation_desc;
952 	unsigned	chunk;
953 	unsigned short	checksum;
954 	int		i;
955 	unsigned char *p;
956 	unsigned short	flags;
957 	short	macflags;
958 
959 	udf_file_entry *fe = (udf_file_entry *)buf;
960 
961 	/*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
962 	set16(&fe->icb_tag.strategy_type, 4);
963 	/*set16(&fe->icb_tag.strategy_parameter, 0);*/
964 	set16(&fe->icb_tag.maximum_number_of_entries, 1);
965 
966 	switch (de->mode & S_IFMT) {
967 
968 #ifdef	S_IFIFO
969 	case S_IFIFO:
970 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_FIFO);
971 		break;
972 #endif
973 
974 #ifdef	S_IFCHR
975 	case S_IFCHR:
976 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_CHAR_DEV);
977 		break;
978 #endif
979 
980 #ifdef	S_IFBLK
981 	case S_IFBLK:
982 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_BLOCK_DEV);
983 		break;
984 #endif
985 
986 	case S_IFREG:
987 			/* FALLTHROUGH */
988 	default:
989 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_BYTESEQ);
990 		break;
991 
992 #ifdef	S_IFLNK
993 	case S_IFLNK:
994 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_SYMLINK);
995 		break;
996 #endif
997 
998 #ifdef	S_IFSOCK
999 	case S_IFSOCK:
1000 		set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_C_ISSOCK);
1001 		break;
1002 #endif
1003 	}
1004 
1005 	/*fe->icb_tag.parent_icb_location;*/
1006 	/* UDF_ICBTAG_FLAG_SYSTEM shall be set for MS-DOS, OS/2, Win95 and WinNT as of UDF260 3.3.2.1 */
1007 	flags = UDF_ICBTAG_FLAG_NONRELOCATABLE | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS;
1008 	if (hfs_ent) {
1009 		macflags = hfs_ent->fdflags;
1010 		B2N_16(macflags);
1011 		if (macflags & FI_ATTR_SYSTEM) {
1012 			flags |= UDF_ICBTAG_FLAG_SYSTEM;
1013 		}
1014 	}
1015 	flags |= getflags(de->mode);		/* S_ISUID, S_ISGID, S_ISVTX */
1016 	set16(&fe->icb_tag.flags, flags);
1017 
1018 	set32(&fe->permissions, getperms(de->mode));
1019 	if (rationalize_uid)
1020 		set32(&fe->uid, uid_to_use);
1021 	else
1022 		set32(&fe->uid, de->uid);
1023 	if (rationalize_gid)
1024 		set32(&fe->gid, gid_to_use);
1025 	else
1026 		set32(&fe->gid, de->gid);
1027 
1028 
1029 	set16(&fe->file_link_count, link_count);
1030 	/*fe->record_format;*/
1031 	/*fe->record_display_attributes;*/
1032 	/*fe->record_length;*/
1033 	set64(&fe->info_length, length);
1034 	set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
1035 
1036 	set_timestamp_from_timespec(&fe->access_time, &de->atime);
1037 	set_timestamp_from_timespec(&fe->modification_time, &de->mtime);
1038 	set_timestamp_from_timespec(&fe->attribute_time, &de->ctime);
1039 
1040 	set32(&fe->checkpoint, 1);
1041 
1042 	if (res_log_block) {
1043 		set32(&fe->ext_attribute_icb.extent_length, 2048);
1044 		set32(&fe->ext_attribute_icb.extent_location.logical_block_number, res_log_block);
1045 		/* &p->ext_attribute_icb.extent_location.partition_reference_number */
1046 	}
1047 
1048 	set_impl_ident(&fe->impl_ident);
1049 	set64(&fe->unique_id, unique_id);
1050 
1051 	/* write mac finderinfos etc. required for directories and files */
1052 	set32(&fe->length_of_ext_attributes, sizeof (udf_ext_attribute_header_desc) +
1053 		sizeof (udf_ext_attribute_dev_spec) +
1054 		sizeof (udf_ext_attribute_free_ea_space) + sizeof (udf_ext_attribute_dvd_cgms_info) +
1055 		sizeof (udf_ext_attribute_file_macfinderinfo));
1056 
1057 	set32(&fe->ext_attribute_header.impl_attributes_location, sizeof (udf_ext_attribute_header_desc));
1058 	set32(&fe->ext_attribute_header.application_attributes_location, sizeof (udf_ext_attribute_header_desc) +
1059 		sizeof (udf_ext_attribute_dev_spec) +
1060 		sizeof (udf_ext_attribute_free_ea_space) + sizeof (udf_ext_attribute_dvd_cgms_info) +
1061 		sizeof (udf_ext_attribute_file_macfinderinfo));
1062 	set_tag(&fe->ext_attribute_header.desc_tag, UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba,
1063 		sizeof (udf_ext_attribute_header_desc));
1064 
1065 	set32(&fe->ext_attribute_dev_spec.attribute_type, 12);
1066 	set8(&fe->ext_attribute_dev_spec.attribute_subtype, 1);
1067 	set32(&fe->ext_attribute_dev_spec.attribute_length, 24);
1068 	set32(&fe->ext_attribute_dev_spec.impl_use_length, 0);
1069 	if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) {
1070 		set32(&fe->ext_attribute_dev_spec.dev_major, major(de->rdev));
1071 		set32(&fe->ext_attribute_dev_spec.dev_minor, minor(de->rdev));
1072 	} else {
1073 		set32(&fe->ext_attribute_dev_spec.dev_major, 0);
1074 		set32(&fe->ext_attribute_dev_spec.dev_minor, 0);
1075 	}
1076 
1077 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
1078 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
1079 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
1080 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
1081 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident, "*UDF FreeEASpace");
1082 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
1083 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
1084 
1085 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_free_ea_space; i < 48; i++)
1086 		checksum += *p++;
1087 	set16(&fe->ext_attribute_free_ea_space.header_checksum, checksum);
1088 
1089 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
1090 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
1091 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
1092 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
1093 	strcpy((char *)fe->ext_attribute_dvd_cgms_info.impl_ident.ident, "*UDF DVD CGMS Info");
1094 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[0] = 2;
1095 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[1] = 1;
1096 
1097 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_dvd_cgms_info; i < 48; i++)
1098 		checksum += *p++;
1099 	set16(&fe->ext_attribute_dvd_cgms_info.header_checksum, checksum);
1100 
1101 	set32(&fe->ext_attribute_macfinderinfo.attribute_type, EXTATTR_IMP_USE);
1102 	set8(&fe->ext_attribute_macfinderinfo.attribute_subtype, 1);
1103 	set32(&fe->ext_attribute_macfinderinfo.attribute_length, 96);
1104 	set32(&fe->ext_attribute_macfinderinfo.impl_use_length, 48);
1105 	strcpy((char *)fe->ext_attribute_macfinderinfo.impl_ident.ident, "*UDF Mac FinderInfo");
1106 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[0] = 2;
1107 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[1] = 1;
1108 
1109 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_macfinderinfo; i < 48; i++)
1110 		checksum += *p++;
1111 	set16(&fe->ext_attribute_macfinderinfo.finderinfo.headerchecksum, checksum);
1112 
1113 	/* write mac finderinfos etc. required for files */
1114 	if (hfs_ent) {
1115 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdtype.l = hfs_ent->u.file.type[3];
1116 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdtype.ml = hfs_ent->u.file.type[2];
1117 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdtype.mh = hfs_ent->u.file.type[1];
1118 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdtype.h = hfs_ent->u.file.type[0];
1119 
1120 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdcreator.l = hfs_ent->u.file.creator[3];
1121 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdcreator.ml = hfs_ent->u.file.creator[2];
1122 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdcreator.mh = hfs_ent->u.file.creator[1];
1123 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdcreator.h = hfs_ent->u.file.creator[0];
1124 
1125 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdflags.l = ((char *)&macflags)[1];
1126 		fe->ext_attribute_macfinderinfo.finderinfo.fileinfo.fdflags.h = ((char *)&macflags)[0];
1127 
1128 #ifdef INSERTMACRESFORK
1129 		set32(&fe->ext_attribute_macfinderinfo.finderinfo.resourcedatalength, hfs_ent->u.file.rsize);
1130 		set32(&fe->ext_attribute_macfinderinfo.finderinfo.resourcealloclength, hfs_ent->u.file.rsize);
1131 #endif
1132 	}
1133 
1134 	/*
1135 	 * Extended attributes that may (?) be required for DVD-Video
1136 	 * compliance
1137 	 */
1138 #if 0
1139 	set32(&fe->length_of_ext_attributes, 24+52+56);
1140 	set32(&fe->ext_attribute_header.impl_attributes_location, 24);
1141 	set32(&fe->ext_attribute_header.application_attributes_location,
1142 								24+52+56);
1143 	set_tag(&fe->ext_attribute_header.desc_tag,
1144 			UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba, 24 /*???*/);
1145 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
1146 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
1147 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
1148 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
1149 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
1150 							"*UDF FreeAppEASpace");
1151 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
1152 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
1153 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
1154 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
1155 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
1156 							"*UDF DVD CGMS Info");
1157 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
1158 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
1159 #else
1160 	/*set32(&fe->length_of_ext_attributes, 0);*/
1161 #endif
1162 
1163 	allocation_desc = &fe->allocation_desc;
1164 	/*
1165 	 * Only a file size less than 1GB can be expressed by a single
1166 	 * AllocationDescriptor. When the size of a file is larger than 1GB,
1167 	 * 2 or more AllocationDescriptors should be used. We don't know
1168 	 * whether a single 8-byte AllocationDescriptor should be written or no
1169 	 * one should be written if the size of a file is 0 byte. - FIXME.
1170 	 *
1171 	 * XXX We get called with buf[2048]. This allows a max. file size of
1172 	 * XXX 234 GB. With more we would cause a buffer overflow.
1173 	 * XXX We need to check whether UDF would allow files > 234 GB.
1174 	 */
1175 	for (; length > 0; length -= chunk) {
1176 		chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
1177 		set32(&allocation_desc->extent_length, chunk);
1178 		set32(&allocation_desc->extent_position, file_rba);
1179 		file_rba += chunk >> 11;
1180 		allocation_desc++;
1181 	}
1182 	if (((Uchar *)allocation_desc) > &buf[2048])
1183 		udf_size_panic(allocation_desc - &fe->allocation_desc);
1184 
1185 	set32(&fe->length_of_allocation_descs,
1186 				(unsigned char *) allocation_desc -
1187 				(unsigned char *) &fe->allocation_desc);
1188 	set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
1189 		(unsigned char *) allocation_desc - buf);
1190 }
1191 
1192 LOCAL void
udf_size_panic(n)1193 udf_size_panic(n)
1194 	int	n;
1195 {
1196 	comerrno(EX_BAD,
1197 		_("Panic: UDF file size error, too many extents (%d).\n"), n);
1198 }
1199 
1200 
1201 LOCAL void
1202 #ifdef PROTOTYPES
set_macvolume_filed_entry(unsigned char * buf,UInt32_t rba,UInt32_t file_rba,unsigned length,int is_directory,unsigned link_count,unsigned unique_id,hfsdirent * hfs_ent,struct directory_entry * de)1203 set_macvolume_filed_entry(unsigned char *buf,
1204 	UInt32_t rba,
1205 	UInt32_t file_rba,
1206 	unsigned length,
1207 	int is_directory,
1208 	unsigned link_count,
1209 	unsigned unique_id,
1210 	hfsdirent *hfs_ent,
1211 	struct directory_entry	*de
1212 )
1213 #else
1214 set_macvolume_filed_entry(buf, rba, file_rba, length, is_directory, link_count, unique_id, hfs_ent, de)
1215 	unsigned char	*buf;
1216 	UInt32_t	rba;
1217 	UInt32_t	file_rba;
1218 	unsigned	length;
1219 	int		is_directory;
1220 	unsigned	link_count;
1221 	unsigned	unique_id;
1222 	hfsdirent	*hfs_ent;
1223 	struct directory_entry	*de;
1224 #endif
1225 {
1226 	udf_short_ad	*allocation_desc;
1227 	unsigned	chunk;
1228 	unsigned short	checksum;
1229 	int		i;
1230 	unsigned char	*p;
1231 	unsigned short	flags;
1232 	short		macflags;
1233 
1234 	udf_macvolume_filed_entry *fe = (udf_macvolume_filed_entry *)buf;
1235 
1236 	/*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
1237 	set16(&fe->icb_tag.strategy_type, 4);
1238 	/*set16(&fe->icb_tag.strategy_parameter, 0);*/
1239 	set16(&fe->icb_tag.maximum_number_of_entries, 1);
1240 	set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_DIRECTORY);
1241 	/*fe->icb_tag.parent_icb_location;*/
1242 	/* UDF_ICBTAG_FLAG_SYSTEM shall be set for MS-DOS, OS/2, Win95 and WinNT as of UDF260 3.3.2.1 */
1243 	flags = UDF_ICBTAG_FLAG_NONRELOCATABLE | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS;
1244 	if (hfs_ent) {
1245 		macflags = hfs_ent->fdflags;
1246 		B2N_16(macflags);
1247 		if (macflags & FI_ATTR_SYSTEM) {
1248 			flags |= UDF_ICBTAG_FLAG_SYSTEM;
1249 		}
1250 	}
1251 	flags |= getflags(de->mode);		/* S_ISUID, S_ISGID, S_ISVTX */
1252 	set16(&fe->icb_tag.flags, flags);
1253 
1254 	set32(&fe->permissions, getperms(de->mode));
1255 	if (rationalize_uid)
1256 		set32(&fe->uid, uid_to_use);
1257 	else
1258 		set32(&fe->uid, de->uid);
1259 	if (rationalize_gid)
1260 		set32(&fe->gid, gid_to_use);
1261 	else
1262 		set32(&fe->gid, de->gid);
1263 
1264 	set16(&fe->file_link_count, link_count);
1265 	/*fe->record_format;*/
1266 	/*fe->record_display_attributes;*/
1267 	/*fe->record_length;*/
1268 	set64(&fe->info_length, length);
1269 	set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
1270 
1271 	set_timestamp_from_timespec(&fe->access_time, &de->atime);
1272 	set_timestamp_from_timespec(&fe->modification_time, &de->mtime);
1273 	set_timestamp_from_timespec(&fe->attribute_time, &de->ctime);
1274 
1275 	set32(&fe->checkpoint, 1);
1276 	/*fe->ext_attribute_icb;*/
1277 	set_impl_ident(&fe->impl_ident);
1278 	set64(&fe->unique_id, unique_id);
1279 
1280 	/*write mac finderinfos etc. required for directories */
1281 	set32(&fe->length_of_ext_attributes, sizeof (udf_ext_attribute_header_desc) +
1282 		sizeof (udf_ext_attribute_free_ea_space) + sizeof (udf_ext_attribute_dvd_cgms_info) +
1283 		sizeof (udf_ext_attribute_dir_macvolinfo) + sizeof (udf_ext_attribute_dir_macfinderinfo));
1284 
1285 	set32(&fe->ext_attribute_header.impl_attributes_location, sizeof (udf_ext_attribute_header_desc));
1286 	set32(&fe->ext_attribute_header.application_attributes_location, sizeof (udf_ext_attribute_header_desc) +
1287 		sizeof (udf_ext_attribute_free_ea_space) + sizeof (udf_ext_attribute_dvd_cgms_info) +
1288 		sizeof (udf_ext_attribute_dir_macvolinfo) + sizeof (udf_ext_attribute_dir_macfinderinfo));
1289 	set_tag(&fe->ext_attribute_header.desc_tag, UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba,
1290 		sizeof (udf_ext_attribute_header_desc));
1291 
1292 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
1293 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
1294 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
1295 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
1296 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident, "*UDF FreeAppEASpace");
1297 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
1298 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
1299 
1300 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_free_ea_space; i < 48; i++)
1301 		checksum += *p++;
1302 	set16(&fe->ext_attribute_free_ea_space.header_checksum, checksum);
1303 
1304 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
1305 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
1306 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
1307 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
1308 	strcpy((char *)fe->ext_attribute_dvd_cgms_info.impl_ident.ident, "*UDF DVD CGMS Info");
1309 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[0] = 2;
1310 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[1] = 1;
1311 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_dvd_cgms_info; i < 48; i++)
1312 		checksum += *p++;
1313 	set16(&fe->ext_attribute_dvd_cgms_info.header_checksum, checksum);
1314 
1315 	set32(&fe->ext_attribute_macvolumeinfo.attribute_type, EXTATTR_IMP_USE);
1316 	set8(&fe->ext_attribute_macvolumeinfo.attribute_subtype, 1);
1317 	set32(&fe->ext_attribute_macvolumeinfo.attribute_length, 108);
1318 	set32(&fe->ext_attribute_macvolumeinfo.impl_use_length, 60);
1319 	strcpy((char *)fe->ext_attribute_macvolumeinfo.impl_ident.ident, "*UDF Mac VolumeInfo");
1320 	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[0] = 2;
1321 	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[1] = 1;
1322 /*
1323  * This is how tiger's hdiutil mkhybrid -udf writes this, seems to make no difference
1324  *	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[0] = 5;
1325  *	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[1] = 1;
1326  *	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[2] = 3;
1327  *	fe->ext_attribute_macvolumeinfo.impl_ident.ident_suffix[3] = 1;
1328  */
1329 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_macvolumeinfo; i < 48; i++)
1330 		checksum += *p++;
1331 	set16(&fe->ext_attribute_macvolumeinfo.volumeinfo.headerchecksum, checksum);
1332 
1333 	/* write mac volumeinfo */
1334 	if (hfs_ent) {
1335 #ifdef INSERTMACRESFORK
1336 /*
1337  *	todo: don't know what to write in volfinderinfo and unknown
1338  *	moddate and budate are derived from folder entry's modification_time, thus no need to set here
1339  */
1340 #endif
1341 	}
1342 
1343 	set32(&fe->ext_attribute_macfinderinfo.attribute_type, EXTATTR_IMP_USE);
1344 	set8(&fe->ext_attribute_macfinderinfo.attribute_subtype, 1);
1345 	set32(&fe->ext_attribute_macfinderinfo.attribute_length, 88);
1346 	set32(&fe->ext_attribute_macfinderinfo.impl_use_length, 40);
1347 	strcpy((char *)fe->ext_attribute_macfinderinfo.impl_ident.ident, "*UDF Mac FinderInfo");
1348 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[0] = 2;
1349 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[1] = 1;
1350 
1351 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_macfinderinfo; i < 48; i++)
1352 		checksum += *p++;
1353 	set16(&fe->ext_attribute_macfinderinfo.finderinfo.headerchecksum, checksum);
1354 
1355 	/* write mac finderinfos etc. required for directories */
1356 	if (hfs_ent) {
1357 		fe->ext_attribute_macfinderinfo.finderinfo.dirinfo.frflags.l = ((char *)&macflags)[1];
1358 		fe->ext_attribute_macfinderinfo.finderinfo.dirinfo.frflags.h = ((char *)&macflags)[0];
1359 		/* todo: other dirinfo values, other dirextinfo */
1360 #ifdef INSERTMACRESFORK
1361 		/* todo: insert folder resource if available */
1362 #endif
1363 	}
1364 
1365 	allocation_desc = &fe->allocation_desc;
1366 	/*
1367 	 * Only a file size less than 1GB can be expressed by a single
1368 	 * AllocationDescriptor. When the size of a file is larger than 1GB,
1369 	 * 2 or more AllocationDescriptors should be used. We don't know
1370 	 * whether a single 8-byte AllocationDescriptor should be written or no
1371 	 * one should be written if the size of a file is 0 byte. - FIXME.
1372 	 *
1373 	 * XXX We get called with buf[2048]. This allows a max. file size of
1374 	 * XXX 234 GB. With more we would cause a buffer overflow.
1375 	 * XXX We need to check whether UDF would allow files > 234 GB.
1376 	 */
1377 
1378 	for (; length > 0; length -= chunk) {
1379 		chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
1380 		set32(&allocation_desc->extent_length, chunk);
1381 		set32(&allocation_desc->extent_position, file_rba);
1382 		file_rba += chunk >> 11;
1383 		allocation_desc++;
1384 	}
1385 	if (((Uchar *)allocation_desc) > &buf[2048])
1386 		udf_size_panic(allocation_desc - &fe->allocation_desc);
1387 
1388 	set32(&fe->length_of_allocation_descs,
1389 				(unsigned char *) allocation_desc -
1390 				(unsigned char *) &fe->allocation_desc);
1391 	set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
1392 		(unsigned char *) allocation_desc - buf);
1393 }
1394 
1395 LOCAL void
1396 #ifdef	PROTOTYPES
set_attr_file_entry(unsigned char * buf,unsigned rba,unsigned file_rba,off_t length,int is_directory,unsigned link_count,unsigned unique_id,hfsdirent * hfs_ent,struct directory_entry * de)1397 set_attr_file_entry(unsigned char *buf,
1398 	unsigned rba,
1399 	unsigned file_rba,
1400 	off_t length,
1401 	int is_directory,
1402 	unsigned link_count,
1403 	unsigned unique_id,
1404 	hfsdirent *hfs_ent,
1405 	struct directory_entry	*de
1406 )
1407 #else
1408 set_attr_file_entry(buf, rba, file_rba, length, is_directory, link_count, unique_id, hfs_ent, de)
1409 	unsigned char *buf;
1410 	unsigned rba;
1411 	unsigned file_rba;
1412 	off_t length;
1413 	int is_directory;
1414 	unsigned link_count;
1415 	unsigned unique_id;
1416 	hfsdirent *hfs_ent;
1417 	struct directory_entry	*de;
1418 #endif
1419 {
1420 	udf_short_ad	*allocation_desc;
1421 	unsigned	chunk;
1422 	unsigned short	flags;
1423 	short	macflags;
1424 
1425 	udf_attr_file_entry *fe = (udf_attr_file_entry *)buf;
1426 
1427 	/*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
1428 	set16(&fe->icb_tag.strategy_type, 4);
1429 	/*set16(&fe->icb_tag.strategy_parameter, 0);*/
1430 	set16(&fe->icb_tag.maximum_number_of_entries, 1);
1431 	set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_EA);
1432 	/*fe->icb_tag.parent_icb_location;*/
1433 	/* UDF_ICBTAG_FLAG_SYSTEM shall be set for MS-DOS, OS/2, Win95 and WinNT as of UDF260 3.3.2.1 */
1434 	flags = UDF_ICBTAG_FLAG_NONRELOCATABLE | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS;
1435 	if (hfs_ent) {
1436 		macflags = hfs_ent->fdflags;
1437 		B2N_16(macflags);
1438 		if (macflags & FI_ATTR_SYSTEM) {
1439 			flags |= UDF_ICBTAG_FLAG_SYSTEM;
1440 		}
1441 	}
1442 	flags |= getflags(de->mode);		/* S_ISUID, S_ISGID, S_ISVTX */
1443 	set16(&fe->icb_tag.flags, flags);
1444 
1445 	set32(&fe->permissions, getperms(de->mode));
1446 	if (rationalize_uid)
1447 		set32(&fe->uid, uid_to_use);
1448 	else
1449 		set32(&fe->uid, de->uid);
1450 	if (rationalize_gid)
1451 		set32(&fe->gid, gid_to_use);
1452 	else
1453 		set32(&fe->gid, de->gid);
1454 
1455 
1456 	set16(&fe->file_link_count, link_count);
1457 	/*fe->record_format;*/
1458 	/*fe->record_display_attributes;*/
1459 	/*fe->record_length;*/
1460 	if (length % 4)
1461 		length += 4 - (length % 4);
1462 	if (length % 2048)
1463 		length += 2048 - (length % 2048);
1464 	set64(&fe->info_length, length);
1465 	set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
1466 
1467 	set_timestamp_from_timespec(&fe->access_time, &de->atime);
1468 	set_timestamp_from_timespec(&fe->modification_time, &de->mtime);
1469 	set_timestamp_from_timespec(&fe->attribute_time, &de->ctime);
1470 
1471 	set32(&fe->checkpoint, 1);
1472 	/*fe->ext_attribute_icb;*/
1473 	set_impl_ident(&fe->impl_ident);
1474 	set64(&fe->unique_id, unique_id);
1475 
1476 
1477 	allocation_desc = &fe->allocation_desc;
1478 	/*
1479 	 * Only a file size less than 1GB can be expressed by a single
1480 	 * AllocationDescriptor. When the size of a file is larger than 1GB,
1481 	 * 2 or more AllocationDescriptors should be used. We don't know
1482 	 * whether a single 8-byte AllocationDescriptor should be written or no
1483 	 * one should be written if the size of a file is 0 byte. - FIXME.
1484 	 *
1485 	 * XXX We get called with buf[2048]. This allows a max. file size of
1486 	 * XXX 234 GB. With more we would cause a buffer overflow.
1487 	 * XXX We need to check whether UDF would allow files > 234 GB.
1488 	 */
1489 
1490 	for (; length > 0; length -= chunk) {
1491 		chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
1492 		set32(&allocation_desc->extent_length, chunk);
1493 		set32(&allocation_desc->extent_position, file_rba);
1494 		file_rba += chunk >> 11;
1495 		allocation_desc++;
1496 	}
1497 	if (((Uchar *)allocation_desc) > &buf[2048])
1498 		udf_size_panic(allocation_desc - &fe->allocation_desc);
1499 
1500 	set32(&fe->length_of_allocation_descs,
1501 				(unsigned char *) allocation_desc -
1502 				(unsigned char *) &fe->allocation_desc);
1503 	set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
1504 		(unsigned char *) allocation_desc - buf);
1505 }
1506 
1507 LOCAL void
1508 #ifdef	PROTOTYPES
set_filed_entry(unsigned char * buf,unsigned rba,unsigned file_rba,unsigned length,int is_directory,unsigned link_count,unsigned unique_id,hfsdirent * hfs_ent,struct directory_entry * de)1509 set_filed_entry(unsigned char *buf,
1510 	unsigned rba,
1511 	unsigned file_rba,
1512 	unsigned length,
1513 	int is_directory,
1514 	unsigned link_count,
1515 	unsigned unique_id,
1516 	hfsdirent *hfs_ent,
1517 	struct directory_entry	*de)
1518 #else
1519 set_filed_entry(buf, rba, file_rba, length, is_directory, link_count, unique_id, hfs_ent, de)
1520 	unsigned char *buf;
1521 	unsigned rba;
1522 	unsigned file_rba;
1523 	unsigned length;
1524 	int is_directory;
1525 	unsigned link_count;
1526 	unsigned unique_id;
1527 	hfsdirent *hfs_ent;
1528 	struct directory_entry	*de;
1529 #endif
1530 {
1531 	udf_short_ad	*allocation_desc;
1532 	unsigned	chunk;
1533 	unsigned short	checksum;
1534 	int		i;
1535 	unsigned char *p;
1536 	unsigned short	flags;
1537 	short	macflags;
1538 
1539 	udf_filed_entry *fe = (udf_filed_entry *)buf;
1540 
1541 	/*set32(&fe->icb_tag.prior_recorded_number_of_direct_entries, 0);*/
1542 	set16(&fe->icb_tag.strategy_type, 4);
1543 	/*set16(&fe->icb_tag.strategy_parameter, 0);*/
1544 	set16(&fe->icb_tag.maximum_number_of_entries, 1);
1545 	set8(&fe->icb_tag.file_type, UDF_ICBTAG_FILETYPE_DIRECTORY);
1546 	/*fe->icb_tag.parent_icb_location;*/
1547 	/* UDF_ICBTAG_FLAG_SYSTEM shall be set for MS-DOS, OS/2, Win95 and WinNT as of UDF260 3.3.2.1 */
1548 	flags = UDF_ICBTAG_FLAG_NONRELOCATABLE | UDF_ICBTAG_FLAG_ARCHIVE | UDF_ICBTAG_FLAG_CONTIGUOUS;
1549 	if (hfs_ent) {
1550 		macflags = hfs_ent->fdflags;
1551 		B2N_16(macflags);
1552 		if (macflags & FI_ATTR_SYSTEM) {
1553 			flags |= UDF_ICBTAG_FLAG_SYSTEM;
1554 		}
1555 	}
1556 	flags |= getflags(de->mode);		/* S_ISUID, S_ISGID, S_ISVTX */
1557 	set16(&fe->icb_tag.flags, flags);
1558 
1559 	set32(&fe->permissions, getperms(de->mode));
1560 	if (rationalize_uid)
1561 		set32(&fe->uid, uid_to_use);
1562 	else
1563 		set32(&fe->uid, de->uid);
1564 	if (rationalize_gid)
1565 		set32(&fe->gid, gid_to_use);
1566 	else
1567 		set32(&fe->gid, de->gid);
1568 
1569 
1570 	set16(&fe->file_link_count, link_count);
1571 	/*fe->record_format;*/
1572 	/*fe->record_display_attributes;*/
1573 	/*fe->record_length;*/
1574 	set64(&fe->info_length, length);
1575 	set64(&fe->logical_blocks_recorded, ISO_BLOCKS(length));
1576 
1577 	set_timestamp_from_timespec(&fe->access_time, &de->atime);
1578 	set_timestamp_from_timespec(&fe->modification_time, &de->mtime);
1579 	set_timestamp_from_timespec(&fe->attribute_time, &de->ctime);
1580 
1581 	set32(&fe->checkpoint, 1);
1582 	/*fe->ext_attribute_icb;*/
1583 	set_impl_ident(&fe->impl_ident);
1584 	set64(&fe->unique_id, unique_id);
1585 
1586 	/* write mac finderinfos etc. required for directories */
1587 	set32(&fe->length_of_ext_attributes, sizeof (udf_ext_attribute_header_desc) +
1588 		sizeof (udf_ext_attribute_free_ea_space) + sizeof (udf_ext_attribute_dvd_cgms_info) +
1589 		sizeof (udf_ext_attribute_dir_macfinderinfo));
1590 
1591 	set32(&fe->ext_attribute_header.impl_attributes_location, sizeof (udf_ext_attribute_header_desc));
1592 	set32(&fe->ext_attribute_header.application_attributes_location,
1593 		sizeof (udf_ext_attribute_header_desc) + sizeof (udf_ext_attribute_free_ea_space) +
1594 		sizeof (udf_ext_attribute_dvd_cgms_info) + sizeof (udf_ext_attribute_dir_macfinderinfo));
1595 	set_tag(&fe->ext_attribute_header.desc_tag, UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba,
1596 		sizeof (udf_ext_attribute_header_desc));
1597 
1598 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
1599 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
1600 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
1601 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
1602 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident, "*UDF FreeAppEASpace");
1603 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
1604 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
1605 
1606 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_free_ea_space; i < 48; i++)
1607 		checksum += *p++;
1608 	set16(&fe->ext_attribute_free_ea_space.header_checksum, checksum);
1609 
1610 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
1611 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
1612 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
1613 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
1614 	strcpy((char *)fe->ext_attribute_dvd_cgms_info.impl_ident.ident, "*UDF DVD CGMS Info");
1615 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[0] = 2;
1616 	fe->ext_attribute_dvd_cgms_info.impl_ident.ident_suffix[1] = 1;
1617 
1618 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_dvd_cgms_info; i < 48; i++)
1619 		checksum += *p++;
1620 	set16(&fe->ext_attribute_dvd_cgms_info.header_checksum, checksum);
1621 
1622 	set32(&fe->ext_attribute_macfinderinfo.attribute_type, EXTATTR_IMP_USE);
1623 	set8(&fe->ext_attribute_macfinderinfo.attribute_subtype, 1);
1624 	set32(&fe->ext_attribute_macfinderinfo.attribute_length, 88);
1625 	set32(&fe->ext_attribute_macfinderinfo.impl_use_length, 40);
1626 	strcpy((char *)fe->ext_attribute_macfinderinfo.impl_ident.ident, "*UDF Mac FinderInfo");
1627 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[0] = 2;
1628 	fe->ext_attribute_macfinderinfo.impl_ident.ident_suffix[1] = 1;
1629 
1630 	for (i = 0, checksum = 0, p = (unsigned char *)&fe->ext_attribute_macfinderinfo; i < 48; i++)
1631 		checksum += *p++;
1632 	set16(&fe->ext_attribute_macfinderinfo.finderinfo.headerchecksum, checksum);
1633 
1634 	/* write mac finderinfos etc. required for directories */
1635 	if (hfs_ent) {
1636 		fe->ext_attribute_macfinderinfo.finderinfo.dirinfo.frflags.l = ((char *)&macflags)[1];
1637 		fe->ext_attribute_macfinderinfo.finderinfo.dirinfo.frflags.h = ((char *)&macflags)[0];
1638 		/* todo: other dirinfo values, other dirextinfo */
1639 #ifdef INSERTMACRESFORK
1640 		/* todo: insert folder resource if available */
1641 #endif
1642 	}
1643 
1644 	/*
1645 	 * Extended attributes that may (?) be required for DVD-Video
1646 	 * compliance
1647 	 */
1648 #if 0
1649 	set32(&fe->length_of_ext_attributes, 24+52+56);
1650 	set32(&fe->ext_attribute_header.impl_attributes_location, 24);
1651 	set32(&fe->ext_attribute_header.application_attributes_location,
1652 								24+52+56);
1653 	set_tag(&fe->ext_attribute_header.desc_tag,
1654 			UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, rba, 24 /*???*/);
1655 	set32(&fe->ext_attribute_free_ea_space.attribute_type, SECTOR_SIZE);
1656 	set8(&fe->ext_attribute_free_ea_space.attribute_subtype, 1);
1657 	set32(&fe->ext_attribute_free_ea_space.attribute_length, 52);
1658 	set32(&fe->ext_attribute_free_ea_space.impl_use_length, 4);
1659 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
1660 							"*UDF FreeAppEASpace");
1661 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_type, SECTOR_SIZE);
1662 	set8(&fe->ext_attribute_dvd_cgms_info.attribute_subtype, 1);
1663 	set32(&fe->ext_attribute_dvd_cgms_info.attribute_length, 56);
1664 	set32(&fe->ext_attribute_dvd_cgms_info.impl_use_length, 8);
1665 	strcpy((char *)fe->ext_attribute_free_ea_space.impl_ident.ident,
1666 							"*UDF DVD CGMS Info");
1667 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[0] = 2;
1668 	fe->ext_attribute_free_ea_space.impl_ident.ident_suffix[1] = 1;
1669 #else
1670 	/*set32(&fe->length_of_ext_attributes, 0);*/
1671 #endif
1672 
1673 	allocation_desc = &fe->allocation_desc;
1674 	/*
1675 	 * Only a file size less than 1GB can be expressed by a single
1676 	 * AllocationDescriptor. When the size of a file is larger than 1GB,
1677 	 * 2 or more AllocationDescriptors should be used. We don't know
1678 	 * whether a single 8-byte AllocationDescriptor should be written or no
1679 	 * one should be written if the size of a file is 0 byte. - FIXME.
1680 	 *
1681 	 * XXX We get called with buf[2048]. This allows a max. file size of
1682 	 * XXX 234 GB. With more we would cause a buffer overflow.
1683 	 * XXX We need to check whether UDF would allow files > 234 GB.
1684 	 */
1685 	for (; length > 0; length -= chunk) {
1686 		chunk = (length > 0x3ffff800) ? 0x3ffff800 : length;
1687 		set32(&allocation_desc->extent_length, chunk);
1688 		set32(&allocation_desc->extent_position, file_rba);
1689 		file_rba += chunk >> 11;
1690 		allocation_desc++;
1691 	}
1692 	if (((Uchar *)allocation_desc) > &buf[2048])
1693 		udf_size_panic(allocation_desc - &fe->allocation_desc);
1694 
1695 	set32(&fe->length_of_allocation_descs,
1696 				(unsigned char *) allocation_desc -
1697 				(unsigned char *) &fe->allocation_desc);
1698 	set_tag(&fe->desc_tag, UDF_TAGID_FILE_ENTRY, rba,
1699 		(unsigned char *) allocation_desc - buf);
1700 }
1701 
1702 LOCAL unsigned
directory_link_count(dpnt)1703 directory_link_count(dpnt)
1704 	struct directory	*dpnt;
1705 {
1706 	/*
1707 	 * The link count is equal to 1 (for the parent) plus the
1708 	 * number of subdirectories.
1709 	 */
1710 	unsigned link_count = 1;
1711 	struct directory_entry *de;
1712 
1713 	/* count relocated subdirectories */
1714 	for (de = dpnt->jcontents; de; de = de->jnext) {
1715 		if ((de->de_flags &
1716 		    (INHIBIT_UDF_ENTRY | RELOCATED_DIRECTORY)) ==
1717 							RELOCATED_DIRECTORY) {
1718 			link_count++;
1719 		}
1720 	}
1721 	/* count ordinary subdirectories */
1722 	for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
1723 		if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
1724 			link_count++;
1725 		}
1726 	}
1727 	return (link_count);
1728 }
1729 
1730 LOCAL void
write_one_udf_directory(dpnt,outfile)1731 write_one_udf_directory(dpnt, outfile)
1732 	struct directory	*dpnt;
1733 	FILE			*outfile;
1734 {
1735 	unsigned size_in_bytes, padded_size_in_bytes;
1736 	struct directory_entry *de;
1737 	unsigned ident_size;
1738 	UInt32_t base_sector;
1739 	struct directory *parent;
1740 	Uchar buf[SECTOR_SIZE];
1741 
1742 	memset(buf, 0, SECTOR_SIZE);
1743 #ifdef INSERTMACRESFORK
1744 	if (dpnt == root) {
1745 		set_macvolume_filed_entry(
1746 			buf,
1747 			last_extent_written - lba_udf_partition_start,
1748 			last_extent_written+1 - lba_udf_partition_start,
1749 			directory_size(dpnt),
1750 			1,	/* is_directory */
1751 			directory_link_count(dpnt),
1752 			(dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector,
1753 #ifdef APPLE_HYB
1754 			dpnt->hfs_ent,
1755 #else
1756 			NULL,
1757 #endif
1758 			dpnt->self);
1759 	} else {
1760 #endif
1761 		set_filed_entry(
1762 			buf,
1763 			last_extent_written - lba_udf_partition_start,
1764 			last_extent_written+1 - lba_udf_partition_start,
1765 			directory_size(dpnt),
1766 			1,	/* is_directory */
1767 			directory_link_count(dpnt),
1768 			(dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector,
1769 #ifdef APPLE_HYB
1770 			dpnt->hfs_ent,
1771 #else
1772 			NULL,
1773 #endif
1774 			dpnt->self);
1775 #ifdef INSERTMACRESFORK
1776 	}
1777 #endif
1778 	xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
1779 	last_extent_written++;
1780 
1781 	base_sector = last_extent_written - lba_udf_partition_start;
1782 
1783 	/* parent directory */
1784 	parent = dpnt->parent;
1785 	if (parent == reloc_dir) {
1786 		parent = dpnt->self->parent_rec->filedir;
1787 	}
1788 	ident_size = set_file_ident_desc(
1789 		buf,
1790 		base_sector,
1791 		0,
1792 		1,
1793 		parent->self->udf_file_entry_sector - lba_udf_partition_start,
1794 		(parent == root) ? 0 : parent->self->udf_file_entry_sector);
1795 	xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
1796 	size_in_bytes = ident_size;
1797 
1798 	/* directory contents */
1799 	for (de = dpnt->jcontents; de; de = de->jnext) {
1800 		char *name;
1801 		struct directory_entry *de1;
1802 
1803 		if (de->de_flags & INHIBIT_UDF_ENTRY)
1804 			continue;
1805 
1806 		name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
1807 
1808 		/* skip . and .. */
1809 		if (name[0] == '.' && (name[1] == 0 ||
1810 		    (name[1] == '.' && name[2] == 0)))
1811 			continue;
1812 
1813 		/* look in RR_MOVED for relocated directories */
1814 		de1 = de;
1815 		if (de->de_flags & RELOCATED_DIRECTORY) {
1816 			for (de1 = reloc_dir->contents; de1; de1 = de1->next) {
1817 				if (de1->parent_rec == de) {
1818 					break;
1819 				}
1820 			}
1821 			if (!de1) {
1822 				comerrno(EX_BAD,
1823 				_("Unable to locate relocated directory\n"));
1824 			}
1825 		}
1826 
1827 		ident_size = set_file_ident_desc(
1828 			buf,
1829 			base_sector + (size_in_bytes / SECTOR_SIZE),
1830 			name,
1831 			!!(de1->isorec.flags[0] & ISO_DIRECTORY),
1832 			de1->udf_file_entry_sector - lba_udf_partition_start,
1833 			de1->udf_file_entry_sector);
1834 		xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
1835 		size_in_bytes += ident_size;
1836 	}
1837 
1838 	padded_size_in_bytes = PAD(size_in_bytes, SECTOR_SIZE);
1839 	if (size_in_bytes < padded_size_in_bytes) {
1840 		memset(buf, 0, padded_size_in_bytes - size_in_bytes);
1841 		xfwrite(buf, padded_size_in_bytes - size_in_bytes, 1, outfile, 0, FALSE);
1842 	}
1843 
1844 	last_extent_written += padded_size_in_bytes / SECTOR_SIZE;
1845 }
1846 
1847 LOCAL void
write_udf_directories(dpnt,outfile)1848 write_udf_directories(dpnt, outfile)
1849 	struct directory	*dpnt;
1850 	FILE			*outfile;
1851 {
1852 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
1853 		write_one_udf_directory(dpnt, outfile);
1854 	}
1855 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
1856 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
1857 			write_udf_directories(dpnt, outfile);
1858 		}
1859 	}
1860 }
1861 
1862 LOCAL void
write_udf_file_entries(dpnt,outfile)1863 write_udf_file_entries(dpnt, outfile)
1864 	struct directory	*dpnt;
1865 	FILE			*outfile;
1866 {
1867 	Uchar			buf[SECTOR_SIZE];
1868 	unsigned long		logical_block = 0;
1869 	off_t			attr_size = 0;
1870 	struct file_hash 	*s_hash;
1871 	nlink_t			nlink;
1872 	unsigned int		file_id;
1873 
1874 
1875 	memset(buf, 0, SECTOR_SIZE);
1876 
1877 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
1878 		struct directory_entry *de;
1879 		for (de = dpnt->jcontents; de; de = de->jnext) {
1880 			if (de->de_flags & INHIBIT_UDF_ENTRY)
1881 				continue;
1882 			if (!(de->de_flags & RELOCATED_DIRECTORY) &&
1883 			    !(de->isorec.flags[0] & ISO_DIRECTORY)) {
1884 #ifdef INSERTMACRESFORK
1885 				if (de->assoc) {
1886 					logical_block = last_extent_written - lba_udf_partition_start + 1;
1887 				} else {
1888 					logical_block = 0;
1889 				}
1890 #endif
1891 				if (correct_inodes &&
1892 				    (s_hash = find_hash(de)) != NULL) {
1893 					nlink = s_hash->nlink;
1894 					file_id = s_hash->starting_block;
1895 				} else {
1896 					nlink = 1;
1897 					file_id = de->udf_file_entry_sector;
1898 				}
1899 				memset(buf, 0, SECTOR_SIZE);
1900 				set_file_entry(
1901 					buf,
1902 					(last_extent_written++) - lba_udf_partition_start,
1903 					de->starting_block - lba_udf_partition_start,
1904 					de->size,
1905 					0,	/* is_directory */
1906 					nlink,	/* link_count */
1907 					file_id,
1908 #ifdef APPLE_HYB
1909 					de->hfs_ent,
1910 #else
1911 					NULL,
1912 #endif
1913 #ifdef INSERTMACRESFORK
1914 					logical_block,
1915 #else
1916 					0,
1917 #endif
1918 					de);
1919 				xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
1920 
1921 #ifdef INSERTMACRESFORK
1922 				if (de->assoc) {
1923 					if (ISO_ROUND_UP(de->assoc->size) <
1924 					    ISO_ROUND_UP(de->assoc->size + sizeof (udf_ext_attribute_common))) {
1925 						attr_size = sizeof (udf_ext_attribute_common);
1926 					}
1927 
1928 					memset(buf, 0, SECTOR_SIZE);
1929 					set_attr_file_entry(
1930 						buf,
1931 						(last_extent_written++) - lba_udf_partition_start,
1932 						de->assoc->starting_block - lba_udf_partition_start,
1933 						de->assoc->size + SECTOR_SIZE + attr_size,
1934 						0,
1935 						0,
1936 						de->udf_file_entry_sector,
1937 #ifdef APPLE_HYB
1938 						de->hfs_ent,
1939 #else
1940 						NULL,
1941 #endif
1942 						de);
1943 					xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
1944 				}
1945 #endif
1946 			}
1947 		}
1948 	}
1949 	if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
1950 		for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
1951 			write_udf_file_entries(dpnt, outfile);
1952 		}
1953 	}
1954 }
1955 
1956 /****************************/
1957 
1958 LOCAL int
udf_vol_recognition_area_write(out)1959 udf_vol_recognition_area_write(out)
1960 	FILE	*out;
1961 {
1962 static	const char *identifiers[3] = { "BEA01", "NSR02", "TEA01" };
1963 	int i;
1964 	char buf[SECTOR_SIZE];
1965 	udf_volume_recognition_desc *vsd = (udf_volume_recognition_desc *)buf;
1966 
1967 	memset(buf, 0, sizeof (buf));
1968 	/*set8(&vsd->structure_type, 0);*/
1969 	set8(&vsd->structure_version, 1);
1970 	for (i = 0; i < 3; ++i) {
1971 		memcpy(vsd->standard_identifier, identifiers[i], 5);
1972 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1973 	}
1974 	last_extent_written += 3;
1975 	return (0);
1976 }
1977 
1978 LOCAL int
udf_main_seq_write(out)1979 udf_main_seq_write(out)
1980 	FILE	*out;
1981 {
1982 	Uchar buf[SECTOR_SIZE];
1983 	int i;
1984 
1985 	/*
1986 	 * volume_set_id needs to be set to a (64-bit) "unique" number.
1987 	 * This will have to do for now.
1988 	 */
1989 	if (volume_set_id[0] == 0) {
1990 		volume_set_id[0] = tv_begun.tv_sec;
1991 		volume_set_id[1] = (unsigned)tv_begun.tv_usec;
1992 	}
1993 
1994 	memset(buf, 0, sizeof (buf));
1995 	set_primary_vol_desc(buf, last_extent_written++);
1996 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
1997 
1998 	memset(buf, 0, sizeof (buf));
1999 	set_impl_use_vol_desc(buf, last_extent_written++);
2000 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2001 
2002 	memset(buf, 0, sizeof (buf));
2003 	set_partition_desc(buf, last_extent_written++);
2004 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2005 
2006 	memset(buf, 0, sizeof (buf));
2007 	set_logical_vol_desc(buf, last_extent_written++);
2008 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2009 
2010 	memset(buf, 0, sizeof (buf));
2011 	set_unallocated_space_desc(buf, last_extent_written++);
2012 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2013 
2014 	memset(buf, 0, sizeof (buf));
2015 	set_terminating_desc(buf, last_extent_written++);
2016 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2017 
2018 	memset(buf, 0, sizeof (buf));
2019 	for (i = 6; i < UDF_MAIN_SEQ_LENGTH; ++i) {
2020 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2021 		last_extent_written++;
2022 	}
2023 
2024 	return (0);
2025 }
2026 
2027 LOCAL int
udf_integ_seq_write(out)2028 udf_integ_seq_write(out)
2029 	FILE	*out;
2030 {
2031 	Uchar buf[SECTOR_SIZE*UDF_INTEG_SEQ_LENGTH];
2032 
2033 	memset(buf, 0, sizeof (buf));
2034 
2035 	set_logical_vol_integrity_desc(buf+0*SECTOR_SIZE,
2036 						last_extent_written++);
2037 	set_terminating_desc(buf+1*SECTOR_SIZE, last_extent_written++);
2038 
2039 	xfwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, out, 0, FALSE);
2040 	return (0);
2041 }
2042 
2043 LOCAL int
udf_anchor_vol_desc_write(out)2044 udf_anchor_vol_desc_write(out)
2045 	FILE	*out;
2046 {
2047 	Uchar buf[SECTOR_SIZE];
2048 
2049 	memset(buf, 0, sizeof (buf));
2050 	set_anchor_volume_desc_pointer(buf, last_extent_written++);
2051 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2052 	return (0);
2053 }
2054 
2055 LOCAL int
udf_file_set_desc_write(out)2056 udf_file_set_desc_write(out)
2057 	FILE	*out;
2058 {
2059 	Uchar buf[SECTOR_SIZE*2];
2060 
2061 	memset(buf, 0, sizeof (buf));
2062 
2063 	set_file_set_desc(buf+0*SECTOR_SIZE,
2064 			(last_extent_written++) - lba_udf_partition_start);
2065 	set_terminating_desc(buf+1*SECTOR_SIZE,
2066 			(last_extent_written++) - lba_udf_partition_start);
2067 
2068 	xfwrite(buf, SECTOR_SIZE, 2, out, 0, FALSE);
2069 
2070 	return (0);
2071 }
2072 
2073 LOCAL int
udf_dirtree_write(out)2074 udf_dirtree_write(out)
2075 	FILE	*out;
2076 {
2077 	write_udf_directories(root, out);
2078 	return (0);
2079 }
2080 
2081 LOCAL int
udf_file_entries_write(out)2082 udf_file_entries_write(out)
2083 	FILE	*out;
2084 {
2085 	write_udf_file_entries(root, out);
2086 	return (0);
2087 }
2088 
2089 LOCAL int
pad_to(last_extent_to_write,out)2090 pad_to(last_extent_to_write, out)
2091 	UInt32_t	last_extent_to_write;
2092 	FILE		*out;
2093 {
2094 	char buf[SECTOR_SIZE];
2095 	memset(buf, 0, sizeof (buf));
2096 	while (last_extent_written < last_extent_to_write) {
2097 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2098 		++last_extent_written;
2099 	}
2100 	return (0);
2101 }
2102 
2103 LOCAL int
udf_pad_to_sector_32_write(out)2104 udf_pad_to_sector_32_write(out)
2105 	FILE	*out;
2106 {
2107 	return (pad_to(session_start+32, out));
2108 }
2109 
2110 LOCAL int
udf_pad_to_sector_256_write(out)2111 udf_pad_to_sector_256_write(out)
2112 	FILE	*out;
2113 {
2114 	return (pad_to(session_start+256, out));
2115 }
2116 
2117 LOCAL int
udf_padend_avdp_write(out)2118 udf_padend_avdp_write(out)
2119 	FILE	*out;
2120 {
2121 	Uchar	buf[SECTOR_SIZE];
2122 	UInt32_t last_extent_to_write = (last_extent_written+31) & ~15;
2123 
2124 	if (!use_sparcboot)
2125 		last_extent_to_write = last_extent_written + 150;
2126 
2127 	memset(buf, 0, sizeof (buf));
2128 	while (last_extent_written < last_extent_to_write) {
2129 		set_anchor_volume_desc_pointer(buf, last_extent_written++);
2130 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
2131 	}
2132 	return (0);
2133 }
2134 
2135 EXPORT void
udf_set_extattr_freespace(buf,size,rba)2136 udf_set_extattr_freespace(buf, size, rba)
2137 	unsigned char *buf;
2138 	off_t size;
2139 	unsigned rba;
2140 {
2141 	unsigned short	checksum;
2142 	int	i;
2143 	unsigned char *p;
2144 	unsigned long	ls = (unsigned long)size;
2145 	udf_ext_attribute_free_ea_space *ea;
2146 	udf_ext_attribute_header_desc *eahdc = (udf_ext_attribute_header_desc*)buf;
2147 
2148 
2149 	if (ISO_ROUND_UP(ls) < ISO_ROUND_UP(ls + sizeof (udf_ext_attribute_common))) {
2150 		ls += sizeof (udf_ext_attribute_common);
2151 	}
2152 
2153 	set32(&eahdc->impl_attributes_location, sizeof (udf_ext_attribute_header_desc));
2154 	if (ls % 4)
2155 		ls += 4 - (ls % 4);
2156 	if (ls % SECTOR_SIZE)
2157 		ls += SECTOR_SIZE - (ls % SECTOR_SIZE);
2158 
2159 	set32(&eahdc->application_attributes_location, ls + SECTOR_SIZE);
2160 	set_tag(&eahdc->desc_tag, UDF_TAGID_EXT_ATTRIBUTE_HEADER_DESC, last_extent_written - lba_udf_partition_start,
2161 		sizeof (udf_ext_attribute_header_desc));
2162 
2163 	p = (unsigned char *)eahdc;
2164 	p += sizeof (udf_ext_attribute_header_desc);
2165 	ea = (udf_ext_attribute_free_ea_space *)p;
2166 
2167 
2168 	set32(&ea->attribute_type, EXTATTR_IMP_USE);
2169 	set8(&ea->attribute_subtype, 1);
2170 	set32(&ea->attribute_length, 2024);	/* SECTOR_SIZE - sizeof (udf_ext_attribute_header_desc) */
2171 	set32(&ea->impl_use_length, 1976);	/* attribute_length - 48 */
2172 	strcpy((char *)ea->impl_ident.ident, "*UDF FreeEASpace");
2173 	ea->impl_ident.ident_suffix[0] = 2;
2174 	ea->impl_ident.ident_suffix[1] = 1;
2175 
2176 	for (i = 0, checksum = 0, p = (unsigned char *)ea; i < 48; i++)
2177 		checksum += *p++;
2178 	set16(&ea->header_checksum, checksum);
2179 }
2180 
2181 EXPORT void
udf_set_extattr_macresfork(buf,size,rba)2182 udf_set_extattr_macresfork(buf, size, rba)
2183 	unsigned char *buf;
2184 	off_t size;
2185 	unsigned rba;
2186 {
2187 	unsigned short	checksum;
2188 	int	i;
2189 	unsigned char *p;
2190 	unsigned long	ls = (unsigned long)size;
2191 	udf_ext_attribute_common *ea = (udf_ext_attribute_common *)buf;
2192 
2193 
2194 	if (ISO_ROUND_UP(ls) < ISO_ROUND_UP(ls + sizeof (udf_ext_attribute_common))) {
2195 		ls += sizeof (udf_ext_attribute_common);
2196 	}
2197 
2198 	set32(&ea->attribute_type, EXTATTR_IMP_USE);
2199 	set8(&ea->attribute_subtype, 1);
2200 	if (ls % 4)
2201 		ls += 4 - (ls % 4);
2202 	set32(&ea->impl_use_length, ls);
2203 	if (ls % SECTOR_SIZE)
2204 		ls += SECTOR_SIZE - (ls % SECTOR_SIZE);
2205 	set32(&ea->attribute_length, ls);
2206 	strcpy((char *)ea->impl_ident.ident, "*UDF Mac ResourceFork");
2207 	ea->impl_ident.ident_suffix[0] = 2;
2208 	ea->impl_ident.ident_suffix[1] = 1;
2209 
2210 	for (i = 0, checksum = 0, p = (unsigned char *)ea; i < 48; i++)
2211 		checksum += *p++;
2212 	set16(&ea->header_checksum, checksum);
2213 }
2214 
2215 /* BEGIN CSTYLED */
2216 struct output_fragment udf_vol_recognition_area_frag = { NULL, udf_vol_recognition_area_size, NULL, udf_vol_recognition_area_write, "UDF volume recognition area" };
2217 struct output_fragment udf_main_seq_frag = { NULL, udf_main_seq_size, NULL, udf_main_seq_write, "UDF main seq" };
2218 struct output_fragment udf_main_seq_copy_frag = { NULL, udf_main_seq_copy_size, NULL, udf_main_seq_write, "UDF second seq" };
2219 struct output_fragment udf_integ_seq_frag = { NULL, udf_integ_seq_size, NULL, udf_integ_seq_write, "UDF integ seq" };
2220 struct output_fragment udf_anchor_vol_desc_frag = { NULL, oneblock_size, NULL, udf_anchor_vol_desc_write, "UDF Anchor volume" };
2221 struct output_fragment udf_file_set_desc_frag = { NULL, udf_file_set_desc_size, NULL, udf_file_set_desc_write, "UDF file set" };
2222 struct output_fragment udf_dirtree_frag = { NULL, udf_dirtree_size, NULL, udf_dirtree_write, "UDF directory tree" };
2223 struct output_fragment udf_file_entries_frag = { NULL, udf_file_entries_size, NULL, udf_file_entries_write, "UDF file entries" };
2224 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" };
2225 
2226 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" };
2227 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" };
2228 struct output_fragment udf_padend_avdp_frag = { NULL, udf_padend_avdp_size, NULL, udf_padend_avdp_write, "UDF Pad end" };
2229 /* END CSTYLED */
2230 
2231 #ifdef	OLD_DVD_WEIGHTS
2232 /*
2233  * This function assigns weights as follows:
2234  *
2235  * /VIDEO_TS/VIDEO_TS.IFO   11199
2236  * /VIDEO_TS/VIDEO_TS.VOB   11198
2237  * /VIDEO_TS/VIDEO_TS.BUP   11188
2238  * /VIDEO_TS/VTS_01_0.IFO   11187
2239  * /VIDEO_TS/VTS_01_0.VOB   11186
2240  *            :               :
2241  * /VIDEO_TS/VTS_01_9.VOB   11177
2242  * /VIDEO_TS/VTS_01_0.BUP   11176
2243  *            :               :
2244  * /VIDEO_TS/VTS_99_0.BUP   10000
2245  *
2246  * This ensures that DVD-Video files are laid out properly on the disc.
2247  * The same thing is done for AUDIO_TS files, except in the 20000 range
2248  * instead of the 10000 range.
2249  *
2250  * Question: what about JACKET_P files?
2251  *
2252  * Answer: At least as far as I know :)
2253  * JACKET_P files are still images (single frame mpeg video .i.e mp2
2254  * format). The DVD Jacket pictures will be displayed on the TV screen
2255  * when the player is in a stop/resume mode.
2256  * The location is not dependent on IFO information and the only must
2257  * as far as I know is that they are in upper case (both dir and files).
2258  * This sparce information makes me conclude that they don't need any
2259  * weight. This obviously needs to be tested.
2260  */
2261 EXPORT int
assign_dvd_weights(name,this_dir,val)2262 assign_dvd_weights(name, this_dir, val)
2263 	char			*name;
2264 	struct directory	*this_dir;
2265 	int			val;
2266 {
2267 	int ts_number;
2268 	int segment;
2269 	int audio;
2270 
2271 	if (name[0] != 'A' && name[0] != 'V')
2272 		return (val);
2273 
2274 	if (memcmp(name, "VIDEO_TS", 8) == 0) {
2275 		ts_number = 0;
2276 		audio = 0;
2277 	} else if (memcmp(name, "VTS_", 4) == 0) {
2278 		ts_number = 1;
2279 		audio = 0;
2280 	} else if (memcmp(name, "AUDIO_TS", 8) == 0) {
2281 		ts_number = 0;
2282 		audio = 1;
2283 	} else if (memcmp(name, "ATS_", 4) == 0) {
2284 		ts_number = 1;
2285 		audio = 1;
2286 	} else {
2287 		return (val);
2288 	}
2289 
2290 	if (this_dir->parent != root ||
2291 	    strcmp(this_dir->de_name, "VIDEO_TS") != 0)
2292 		return (val);
2293 
2294 	if (ts_number == 0) {
2295 		segment = 0;
2296 	} else {
2297 		if (name[4] >= '0' && name[4] <= '9' &&
2298 		    name[5] >= '0' && name[5] <= '9' &&
2299 		    name[6] == '_' &&
2300 		    name[7] >= '0' && name[7] <= '9') {
2301 			ts_number = name[4] * 10 + name[5] - ('0' * 11);
2302 			segment = name[7] - '0';
2303 		} else {
2304 			return (val);
2305 		}
2306 	}
2307 
2308 	if (strcmp(name+8, audio ? ".AOB" : ".VOB") == 0) {
2309 		return (audio * 10000 - ts_number * 12 - segment + 11198);
2310 	} else if (strcmp(name+8, ".IFO") == 0) {
2311 		return (audio * 10000 - ts_number * 12 + 11199);
2312 	} else if (strcmp(name+8, ".BUP") == 0) {
2313 		return (audio * 10000 - ts_number * 12 + 11188);
2314 	} else {
2315 		return (val);
2316 	}
2317 }
2318 #else	/* !OLD_DVD_WEIGHTS */
2319 
2320 /* ======================================================================== */
2321 /*	DVD-Audio patch							    */
2322 /* ======================================================================== */
2323 
2324 /*
2325  * sorts support for DVD-Audio and DVD-Video for mkisofs
2326  *
2327  * Written by Jerome Brock, adpated by Fabrice Nicol to cdrtools-3.00
2328  *
2329  * (This is a rewrite of the assign_dvd_weights function in cdrtools)
2330  */
2331 
2332 struct ts_info_rec {
2333 	int num;
2334 	int sub;
2335 } ts_info;
2336 
2337 #define	is_digit(c)		((c >= '0') && (c <= '9'))
2338 
2339 #define	get_digit_from_char(c)	(c - '0')
2340 
2341 #define	get_ts_num(name)	(get_digit_from_char(name[4]) * 10 + \
2342 					get_digit_from_char(name[5]))
2343 
2344 #define	get_ts_sub_num(name)	(get_digit_from_char(name[7]))
2345 
2346 /*
2347  * the end of arrays containing a "" signal value
2348  */
2349 #define	list_end(val)		(val[0] == 0)
2350 
2351 /*
2352  * Parses a string representing an {Audio,Video} Title Set
2353  *
2354  * Examples would be: VTS_12_0.IFO, ATS_03_4.AOB, VTS_24_0.BUP
2355  *
2356  * If the string parses correctly, then this function fills the structure
2357  * pointed to by the info parameter with the parsed information and
2358  * returns a pointer to the same structure
2359  *
2360  * returns NULL on failure
2361  */
2362 LOCAL inline struct ts_info_rec *
2363 parse_ts_info  __PR((const char *name, struct ts_info_rec *info));
2364 
2365 LOCAL inline struct ts_info_rec *
parse_ts_info(name,info)2366 parse_ts_info(name, info)
2367 	const char *name;
2368 	struct ts_info_rec *info;
2369 {
2370 	if (!(is_digit(name[4]) && is_digit(name[5]) && is_digit(name[7])))
2371 		return (NULL);
2372 
2373 	info->num =  get_ts_num(name);
2374 	info->sub = get_ts_sub_num(name);
2375 
2376 	/*
2377 	 * legal track numbers are 01-99
2378 	 */
2379 	if (info->num == 0)
2380 		return (NULL);
2381 
2382 	/*
2383 	 * only title set object files can have a non-zero sub
2384 	 */
2385 	if ((strcmp(name+9, "OB") == 0) && (info->sub != 0))
2386 		return (NULL);
2387 
2388 	return (info);
2389 }
2390 
2391 /*
2392  * Searchs array for a string.
2393  *
2394  * The array must contain an empty string, i.e. "", to signal
2395  * that the end of the array has been reached
2396  *
2397  * returns the index of the found string, or -1 if not found
2398  */
2399 LOCAL inline int
2400 search_array __PR((const char *const array[], const char *str));
2401 
2402 LOCAL inline int
search_array(array,str)2403 search_array(array, str)
2404 	const char *const array[];
2405 	const char *str;
2406 {
2407 	int idx = 0;
2408 	const char *curr = array[idx];
2409 
2410 	while (!list_end(curr) && strncmp(str, curr, strlen(curr)) != 0)
2411 		curr = array[++idx];
2412 
2413 	return (list_end(curr) ? -1 : idx);
2414 }
2415 
2416 
2417 #define	MAX_INFO_SIZE	3
2418 
2419 struct dvd_spec_section_rec {
2420 	/*
2421 	 * using "" as end of list marker
2422 	 */
2423 	const char *const pre[MAX_INFO_SIZE + 1]; /* valid file prefixes in sorts order */
2424 	const char *const ext[MAX_INFO_SIZE + 1]; /* valid file extensions in sorts order */
2425 };
2426 
2427 struct dvd_spec_dir_rec {
2428 	const char *const name; /* directory name supported by this spec */
2429 	const int spec; /* the dvd_spec that this dir supports, i.e. DVD_SPEC_* flags */
2430 	const struct dvd_spec_section_rec dvd_spec_section[2]; /* [0]=non-ts [1]=ts */
2431 };
2432 
2433 static const struct dvd_spec_dir_rec dvd_spec_dirs[] =
2434 {
2435 	/*
2436 	 * top-level entries (dvd_spec_dir_rec's) are in sorts order
2437 	 */
2438 	{ "AUDIO_TS", (DVD_SPEC_AUDIO | DVD_SPEC_HYBRD),
2439 	    {	{ 	{"AUDIO_PP", "AUDIO_TS", "AUDIO_SV", ""},
2440 			{".IFO", ".VOB", ".BUP", ""},
2441 		},
2442 		{	{"ATS_", ""},
2443 			{".IFO", ".AOB", ".BUP", ""},
2444 		},
2445 	    },
2446 	},
2447 	{ "VIDEO_TS", (DVD_SPEC_VIDEO | DVD_SPEC_HYBRD),
2448 	    {	{	{"VIDEO_TS", ""},
2449 			{".IFO", ".VOB", ".BUP", ""},
2450 		},
2451 		{	{"VTS_", ""},
2452 			{".IFO", ".VOB", ".BUP", ""},
2453 		},
2454 	    },
2455 	},
2456 };
2457 
2458 #define	DVD_SPEC_DIRS_QTY	(sizeof (dvd_spec_dirs) / sizeof (dvd_spec_dirs[0]))
2459 
2460 /*
2461  * This function assigns weights to DVD-Audio and DVD-Video filenames
2462  *
2463  * The weights ensure that the files will be correctly ordered on the
2464  * finished dvd.  The actual weight values are not important in the
2465  * absolute sense, i.e. it is not true that file X1 "must" have a
2466  * value of Y1.  What is important is that the relative weight values
2467  * maintain the ordering below, i.e. if file X1 is higher on the list
2468  * than file X2, then Y1 > Y2.
2469  *
2470  * Current ordering (and values):
2471  *
2472  * /AUDIO_TS/AUDIO_PP.IFO   20000
2473  * /AUDIO_TS/AUDIO_TS.IFO   19997
2474  * /AUDIO_TS/AUDIO_TS.VOB   19996
2475  * /AUDIO_TS/AUDIO_TS.BUP   19995
2476  * /AUDIO_TS/AUDIO_SV.IFO   19994
2477  * /AUDIO_TS/AUDIO_SV.VOB   19993
2478  * /AUDIO_TS/AUDIO_SV.BUP   19992
2479  * /AUDIO_TS/ATS_01_0.IFO   19970
2480  * /AUDIO_TS/ATS_01_0.AOB   19960
2481  *           :               :
2482  * /AUDIO_TS/ATS_01_9.AOB   19951
2483  * /AUDIO_TS/ATS_01_0.BUP   19950
2484  *           :               :
2485  * /AUDIO_TS/ATS_99_0.BUP   17010
2486  *           :               :
2487  *           :               :
2488  *           :               :
2489  * /VIDEO_TS/VIDEO_TS.IFO   15000
2490  * /VIDEO_TS/VIDEO_TS.VOB   14999
2491  * /VIDEO_TS/VIDEO_TS.BUP   14998
2492  * /VIDEO_TS/VTS_01_0.IFO   14970
2493  * /VIDEO_TS/VTS_01_0.VOB   14960
2494  *           :               :
2495  * /VIDEO_TS/VTS_01_9.VOB   14951
2496  * /VIDEO_TS/VTS_01_0.BUP   14950
2497  *           :               :
2498  * /VIDEO_TS/VTS_99_0.BUP   12010
2499  *
2500  * This ensures that DVD-Audio and Video files are laid out properly on the disc.
2501  *
2502  * Note: JACKET_P files would be easy to add (if they require special sorts handling)
2503  */
2504 EXPORT int assign_dvd_weights __PR((char *name, struct directory *this_dir, int val));
2505 
2506 EXPORT int
assign_dvd_weights(name,this_dir,val)2507 assign_dvd_weights(name, this_dir, val)
2508 	char			*name;
2509 	struct directory	*this_dir;
2510 	int			val;
2511 {
2512 	const int SORT_BASE =		20000;
2513 	const int SORT_TYPE_SIZE =	5000;
2514 
2515 	/*
2516 	 * worst case for PREFIX_SIZE, is
2517 	 *
2518 	 *  {Audio,Video} Object Set for Title,
2519 	 *   i.e. {A,V}TS_dd_0.VOB - {A,V}TS_dd_9.VOB
2520 	 *
2521 	 * so we will allow that much sorts number space for each prefix
2522 	 *
2523 	 * EXTENSION_QTY can't possibly be greater than the space we allocated to store the extensions
2524 	 */
2525 	const int PREFIX_SIZE =		10;
2526 	const int EXTENSION_QTY =	MAX_INFO_SIZE;
2527 	const int TS_SIZE =		EXTENSION_QTY * PREFIX_SIZE;
2528 
2529 	const struct dvd_spec_dir_rec	*dir_spec = NULL;
2530 	const struct dvd_spec_section_rec *curr_section = NULL;
2531 
2532 	unsigned int	sort_type_index = 0;
2533 	int		prefix_index = 0;
2534 	int		extension_index = 0;
2535 	int		is_ts_file = 0;
2536 	int		found = 0;
2537 	int		offset = 0;
2538 	int		sort_type_offset = 0;
2539 
2540 	if (this_dir->parent != root)
2541 		return (val);
2542 
2543 	if (strlen(name) != 12)
2544 		return (val);
2545 
2546 	for (sort_type_index = 0; sort_type_index < DVD_SPEC_DIRS_QTY; sort_type_index++) {
2547 		if (!(dvd_aud_vid_flag & dvd_spec_dirs[sort_type_index].spec))
2548 			continue;
2549 
2550 		if (strcmp(this_dir->de_name, dvd_spec_dirs[sort_type_index].name) != 0)
2551 			continue;
2552 
2553 		dir_spec = &dvd_spec_dirs[sort_type_index];
2554 
2555 		/*
2556 		 * check for a ts file first since its most likely
2557 		 */
2558 		for (is_ts_file = 1; is_ts_file >= 0; is_ts_file--) {
2559 
2560 			curr_section = &(dir_spec->dvd_spec_section[is_ts_file]);
2561 
2562 			if ((prefix_index = search_array(curr_section->pre, name)) == -1)
2563 				continue;
2564 
2565 			if ((extension_index = search_array(curr_section->ext, name+8)) == -1)
2566 				continue;
2567 
2568 			found = 1;
2569 			goto done_searching;  /* break out of both for loops */
2570 		}
2571 	}
2572 	done_searching:
2573 
2574 	if (!found)
2575 		return (val);
2576 
2577 	if (is_ts_file && (parse_ts_info(name, &ts_info) == NULL))
2578 		return (val);
2579 
2580 	if (is_ts_file) {
2581 		offset = (ts_info.num * TS_SIZE) +
2582 			    (extension_index * PREFIX_SIZE) +
2583 			    ts_info.sub;
2584 	} else {
2585 		/*
2586 		 * Since title set numbers start at 01,
2587 		 * we use the space for the "illegal" 00
2588 		 * ts to store the non-ts files.
2589 		 */
2590 		offset = (prefix_index * EXTENSION_QTY) + extension_index;
2591 	}
2592 
2593 	sort_type_offset = sort_type_index * SORT_TYPE_SIZE;
2594 
2595 	return (SORT_BASE - (offset + sort_type_offset));
2596 }
2597 #endif	/* !OLD_DVD_WEIGHTS */
2598 
2599 
2600 #ifndef	ENAMETOOLONG
2601 #define	ENAMETOOLONG	EINVAL
2602 #endif
2603 
2604 EXPORT int
udf_get_symlinkcontents(filename,contents,size)2605 udf_get_symlinkcontents(filename, contents, size)
2606 	char	*filename;
2607 	char	*contents;
2608 	off_t	*size;
2609 {
2610 #ifdef	HAVE_READLINK
2611 	int	nchar = -1;
2612 	char	tgt[8192];
2613 	char	*target;
2614 	char	*cp;
2615 
2616 	memset(contents, 0, *size);
2617 	memset(tgt, 0, sizeof (tgt));
2618 	nchar = readlink(filename, tgt, sizeof (tgt) -1);
2619 	if (nchar < 0) {
2620 		*size = 0;
2621 		return (-1);
2622 	}
2623 	if (*size < 4) {
2624 		seterrno(ENAMETOOLONG);
2625 		*size = 0;
2626 		return (-1);
2627 	}
2628 	target = tgt;
2629 	cp = contents;
2630 	if (*target == '/') {
2631 		*cp++ = 2;	/* Type "root"	*/
2632 		*cp++ = 0;	/* len 0	*/
2633 		*cp++ = 0;
2634 		*cp++ = 0;
2635 		while (*target == '/')
2636 			target++;
2637 	}
2638 	while (*target) {
2639 		char	*sp = target;
2640 
2641 		while (*sp != '\0' && *sp != '/')
2642 			sp++;
2643 		if ((sp - target) == 2 &&
2644 		    target[0] == '.' && target[1] == '.') {
2645 			if (((contents + *size) - cp) < 4) {
2646 				seterrno(ENAMETOOLONG);
2647 				*size = 0;
2648 				return (-1);
2649 			}
2650 			*cp++ = 3;	/* Type ".."	*/
2651 			*cp++ = 0;	/* len 0	*/
2652 			*cp++ = 0;
2653 			*cp++ = 0;
2654 		} else if ((sp - target) == 1 && *target == '.') {
2655 			if (((contents + *size) - cp) < 4) {
2656 				seterrno(ENAMETOOLONG);
2657 				*size = 0;
2658 				return (-1);
2659 			}
2660 			*cp++ = 4;	/* Type "."	*/
2661 			*cp++ = 0;	/* len 0	*/
2662 			*cp++ = 0;
2663 			*cp++ = 0;
2664 		} else {
2665 			int	len;
2666 
2667 			if (((contents + *size) - cp) < 6) {
2668 				seterrno(ENAMETOOLONG);
2669 				*size = 0;
2670 				return (-1);
2671 			}
2672 			*cp++ = 5;	/* Type "path"	*/
2673 			*cp++ = 0;	/* len 0	*/
2674 			*cp++ = 0;
2675 			*cp++ = 0;
2676 			*sp = '\0';
2677 			len = set_ostaunicode((Uchar *)cp,
2678 						((contents + *size) - cp),
2679 						target);
2680 			*sp = '/';
2681 
2682 			if (len > 255) {
2683 				seterrno(ENAMETOOLONG);
2684 				*size = 0;
2685 				return (-1);
2686 			}
2687 			if (((contents + *size) - cp) < (4+len)) {
2688 				seterrno(ENAMETOOLONG);
2689 				*size = 0;
2690 				return (-1);
2691 			}
2692 			cp[-3] = len;
2693 			cp += len;
2694 		}
2695 		while (*sp == '/')
2696 			sp++;
2697 		target = sp;
2698 	}
2699 	nchar = cp - contents;
2700 	*size = nchar;
2701 	return (nchar);
2702 #else
2703 	int	nchar = -1;
2704 
2705 	memset(contents, 0, *size);
2706 	*size = 0;
2707 	return (nchar);
2708 #endif
2709 }
2710 
2711 #endif  /* UDF */
2712