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