xorriso  1.5.4.pl02
About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

joliet.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Vreixo Formoso
3  * Copyright (c) 2007 Mario Danic
4  * Copyright (c) 2011-2018 Thomas Schmitt
5  *
6  * This file is part of the libisofs project; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License version 2
8  * or later as published by the Free Software Foundation.
9  * See COPYING file for details.
10  */
11 
12 #ifdef HAVE_CONFIG_H
13 #include "../config.h"
14 #endif
15 
16 #include "joliet.h"
17 #include "messages.h"
18 #include "writer.h"
19 #include "image.h"
20 #include "filesrc.h"
21 #include "eltorito.h"
22 #include "libisofs.h"
23 #include "util.h"
24 #include "ecma119.h"
25 
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 /* @param flag bit0= Do not issue error messages
32 */
33 int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid,
34  char *node_name, enum IsoNodeType node_type,
35  size_t *joliet_ucs2_failures,
36  uint16_t **name, int flag)
37 {
38  int ret = ISO_SUCCESS;
39  uint16_t *ucs_name = NULL, *utf16_name = NULL;
40  uint16_t *jname = NULL;
41 
42  if (node_name == NULL) {
43  /* it is not necessarily an error, it can be the root */
44  *name = NULL;
45  return ISO_SUCCESS;
46  }
47 
48  if (opts->joliet_utf16) {
49  ret = str2utf16be(input_charset, node_name, &ucs_name);
50  if (ret < 0) {
51  if (!(flag & 512))
52  iso_msg_debug(imgid, "Cannot convert to UTF-16 : \"%s\"",
53  node_name);
54  goto ex;
55  }
56  } else {
57  ret = str2ucs(input_charset, node_name, &ucs_name);
58  if (ret < 0) {
59  if (!(flag & 512))
60  iso_msg_debug(imgid, "Cannot convert to UCS-2 : \"%s\"",
61  node_name);
62  goto ex;
63  }
64  ret = str2utf16be(input_charset, node_name, &utf16_name);
65  if (ret == ISO_SUCCESS) {
66  if (ucscmp(ucs_name, utf16_name) != 0) {
67  (*joliet_ucs2_failures)++;
68  if (*joliet_ucs2_failures <= ISO_JOLIET_UCS2_WARN_MAX &&
69  !(flag & 512)) {
71  "Filename not suitable for Joliet character set UCS-2 : \"%s\"",
72  node_name);
73  }
74  }
75  }
76  }
77  if (node_type == LIBISO_DIR) {
78  jname = iso_j_dir_id(ucs_name, opts->joliet_long_names << 1);
79  } else {
80  jname = iso_j_file_id(ucs_name,
81  (opts->joliet_long_names << 1) | !!(opts->no_force_dots & 2));
82  }
83  ret = ISO_SUCCESS;
84 ex:;
85  if (ucs_name != NULL)
86  free(ucs_name);
87  if (utf16_name != NULL)
88  free(utf16_name);
89  if (ret != ISO_SUCCESS) {
90  if (jname != NULL)
91  free(jname);
92  return ret;
93  } else if (jname != NULL) {
94  *name = jname;
95  return ISO_SUCCESS;
96  } else {
97  /*
98  * only possible if mem error, as check for empty names is done
99  * in public tree
100  */
101  return ISO_OUT_OF_MEM;
102  }
103 }
104 
105 static
106 int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
107 {
108  int ret;
109 
110  ret = iso_get_joliet_name(t->opts, t->input_charset, t->image->id,
111  iso->name, iso->type, &(t->joliet_ucs2_failures),
112  name, 0);
113 
114  return ret;
115 }
116 
117 
118 static
120 {
121  if (node == NULL) {
122  return;
123  }
124  if (node->type == JOLIET_DIR) {
125  size_t i;
126  for (i = 0; i < node->info.dir->nchildren; i++) {
127  joliet_node_free(node->info.dir->children[i]);
128  }
129  if (node->info.dir->children != NULL)
130  free(node->info.dir->children);
131  free(node->info.dir);
132  }
133  iso_node_unref(node->node);
134  free(node->name);
135  free(node);
136 }
137 
138 /**
139  * Create a low level Joliet node
140  * @return
141  * 1 success, 0 ignored, < 0 error
142  */
143 static
145 {
146  int ret;
147  JolietNode *joliet;
148 
149  joliet = calloc(1, sizeof(JolietNode));
150  if (joliet == NULL) {
151  return ISO_OUT_OF_MEM;
152  }
153 
154  if (iso->type == LIBISO_DIR) {
155  IsoDir *dir = (IsoDir*) iso;
156  joliet->info.dir = calloc(1, sizeof(struct joliet_dir_info));
157  if (joliet->info.dir == NULL) {
158  free(joliet);
159  return ISO_OUT_OF_MEM;
160  }
161  joliet->info.dir->children = NULL;
162  if (dir->nchildren > 0) {
163  joliet->info.dir->children = calloc(sizeof(void*), dir->nchildren);
164  if (joliet->info.dir->children == NULL) {
165  free(joliet->info.dir);
166  free(joliet);
167  return ISO_OUT_OF_MEM;
168  }
169  }
170  joliet->type = JOLIET_DIR;
171  } else if (iso->type == LIBISO_FILE) {
172  /* it's a file */
173  off_t size;
174  IsoFileSrc *src;
175  IsoFile *file = (IsoFile*) iso;
176 
177  size = iso_stream_get_size(file->stream);
178  if (size > (off_t)MAX_ISO_FILE_SECTION_SIZE &&
179  t->opts->iso_level != 3) {
180  char *ipath = iso_tree_get_node_path(iso);
181  free(joliet);
182  ret = iso_msg_submit(t->image->id, ISO_FILE_TOO_BIG, 0,
183  "File \"%s\" can't be added to image because is "
184  "greater than 4GB", ipath);
185  free(ipath);
186  return ret;
187  }
188 
189  ret = iso_file_src_create(t, file, &src);
190  if (ret < 0) {
191  free(joliet);
192  return ret;
193  }
194  joliet->info.file = src;
195  joliet->type = JOLIET_FILE;
196  } else if (iso->type == LIBISO_BOOT) {
197  /* it's a el-torito boot catalog, that we write as a file */
198  IsoFileSrc *src;
199 
200  ret = el_torito_catalog_file_src_create(t, &src);
201  if (ret < 0) {
202  free(joliet);
203  return ret;
204  }
205  joliet->info.file = src;
206  joliet->type = JOLIET_FILE;
207  } else {
208  /* should never happen */
209  free(joliet);
210  return ISO_ASSERT_FAILURE;
211  }
212 
213  /* take a ref to the IsoNode */
214  joliet->node = iso;
215  iso_node_ref(iso);
216 
217  *node = joliet;
218  return ISO_SUCCESS;
219 }
220 
221 /**
222  * Create the low level Joliet tree from the high level ISO tree.
223  *
224  * @return
225  * 1 success, 0 file ignored, < 0 error
226  */
227 static
228 int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
229 {
230  int ret, max_path;
231  JolietNode *node = NULL;
232  uint16_t *jname = NULL;
233 
234  if (t == NULL || iso == NULL || tree == NULL) {
235  return ISO_NULL_POINTER;
236  }
237 
238  if (iso->hidden & LIBISO_HIDE_ON_JOLIET) {
239  /* file will be ignored */
240  return 0;
241  }
242  ret = get_joliet_name(t, iso, &jname);
243  if (ret < 0) {
244  return ret;
245  }
246  max_path = pathlen + 1 + (jname ? ucslen(jname) * 2 : 0);
247  if (!t->opts->joliet_longer_paths && max_path > 240) {
248  char *ipath = iso_tree_get_node_path(iso);
249  /*
250  * Wow!! Joliet is even more restrictive than plain ISO-9660,
251  * that allows up to 255 bytes!!
252  */
254  "File \"%s\" can't be added to Joliet tree, because "
255  "its path length is larger than 240", ipath);
256  free(jname);
257  free(ipath);
258  return ret;
259  }
260 
261  switch (iso->type) {
262  case LIBISO_FILE:
263  ret = create_node(t, iso, &node);
264  break;
265  case LIBISO_DIR:
266  {
267  IsoNode *pos;
268  IsoDir *dir = (IsoDir*)iso;
269  ret = create_node(t, iso, &node);
270  if (ret < 0) {
271  free(jname);
272  return ret;
273  }
274  pos = dir->children;
275  while (pos) {
276  int cret;
277  JolietNode *child;
278  cret = create_tree(t, pos, &child, max_path);
279  if (cret < 0) {
280  /* error */
281  joliet_node_free(node);
282  ret = cret;
283  break;
284  } else if (cret == ISO_SUCCESS) {
285  /* add child to this node */
286  int nchildren = node->info.dir->nchildren++;
287  node->info.dir->children[nchildren] = child;
288  child->parent = node;
289  }
290  pos = pos->next;
291  }
292  }
293  break;
294  case LIBISO_BOOT:
295  if (t->eltorito) {
296  ret = create_node(t, iso, &node);
297  } else {
298  /* log and ignore */
299  ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
300  "El-Torito catalog found on a image without El-Torito.");
301  }
302  break;
303  case LIBISO_SYMLINK:
304  case LIBISO_SPECIAL:
305  {
306  char *ipath = iso_tree_get_node_path(iso);
307  ret = iso_msg_submit(t->image->id, ISO_FILE_IGNORED, 0,
308  "Cannot add %s to Joliet tree. %s can only be added to a "
309  "Rock Ridge tree.", ipath, (iso->type == LIBISO_SYMLINK ?
310  "Symlinks" : "Special files"));
311  free(ipath);
312  }
313  break;
314  default:
315  /* should never happen */
316  return ISO_ASSERT_FAILURE;
317  }
318  if (ret <= 0) {
319  free(jname);
320  return ret;
321  }
322  node->name = jname;
323  *tree = node;
324  return ISO_SUCCESS;
325 }
326 
327 static int
328 cmp_node(const void *f1, const void *f2)
329 {
330  JolietNode *f = *((JolietNode**)f1);
331  JolietNode *g = *((JolietNode**)f2);
332  return ucscmp(f->name, g->name);
333 }
334 
335 static
337 {
338  size_t i;
339 
340  if (root->info.dir->children == NULL)
341  return;
342  qsort(root->info.dir->children, root->info.dir->nchildren,
343  sizeof(void*), cmp_node);
344  for (i = 0; i < root->info.dir->nchildren; i++) {
345  JolietNode *child = root->info.dir->children[i];
346  if (child->type == JOLIET_DIR)
347  sort_tree(child);
348  }
349 }
350 
351 static
352 int cmp_node_name(const void *f1, const void *f2)
353 {
354  JolietNode *f = *((JolietNode**)f1);
355  JolietNode *g = *((JolietNode**)f2);
356  return ucscmp(f->name, g->name);
357 }
358 
359 static
360 int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
361  int number, uint16_t *ext)
362 {
363  int ret, pos;
364  uint16_t *ucsnumber;
365  char fmt[16];
366  char nstr[72];
367  /* was: The only caller of this function allocates dest
368  with 66 elements and limits digits to < 8
369  But this does not match the usage of nstr which has to take
370  the decimal representation of an int.
371  */
372 
373  if (digits >= 8)
374  return ISO_ASSERT_FAILURE;
375 
376  sprintf(fmt, "%%0%dd", digits);
377  sprintf(nstr, fmt, number);
378 
379  ret = str2ucs("ASCII", nstr, &ucsnumber);
380  if (ret < 0) {
381  return ret;
382  }
383 
384  /* copy name */
385  pos = ucslen(src);
386  ucsncpy(dest, src, pos);
387 
388  /* copy number */
389  ucsncpy(dest + pos, ucsnumber, digits);
390  pos += digits;
391 
392  if (ext[0] != (uint16_t)0) {
393  size_t extlen = ucslen(ext);
394  iso_msb((uint8_t *) (dest + pos), 0x002E, 2); /* '.' in UCS */
395  pos++;
396  ucsncpy(dest + pos, ext, extlen);
397  pos += extlen;
398  }
399  iso_msb((uint8_t *) (dest + pos), 0, 2);
400  free(ucsnumber);
401  return ISO_SUCCESS;
402 }
403 
404 /*
405  * From Joliet specs:
406  * "ISO 9660 (Section 7.5.1) states that the sum of the following shall not
407  * exceed 30:
408  * - If there is a file name, the length of the file name.
409  * - If there is a file name extension, the length of the file name extension.
410  * On Joliet compliant media, however, the sum as calculated above shall not
411  * exceed 128 [bytes], to allow for longer file identifiers."
412  *
413  * I.e. the dot does not count.
414  *
415  * (We have an option to lift the limit from 64*2 to 103*2, which is the
416  * maximum to fit into an ISO 9660 directory record.)
417  */
418 static
420 {
421  int ret;
422  int i, nchildren, maxchar = 64;
423  JolietNode **children;
424  IsoHTable *table = NULL;
425  int need_sort = 0;
426  uint16_t *full_name = NULL;
427  uint16_t *tmp = NULL;
428 
429  nchildren = dir->info.dir->nchildren;
430  if (nchildren <= 0) {
431  ret = ISO_SUCCESS;
432  goto ex;
433  }
434  children = dir->info.dir->children;
435  LIBISO_ALLOC_MEM(full_name, uint16_t, LIBISO_JOLIET_NAME_MAX);
437 
438  if (t->opts->joliet_long_names)
439  maxchar = 103;
440 
441  /* a hash table will temporary hold the names, for fast searching */
442  ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
443  (compare_function_t)ucscmp, &table);
444  if (ret < 0) {
445  goto ex;
446  }
447  for (i = 0; i < nchildren; ++i) {
448  uint16_t *name = children[i]->name;
449  ret = iso_htable_add(table, name, name);
450  if (ret < 0) {
451  goto mangle_cleanup;
452  }
453  }
454 
455  for (i = 0; i < nchildren; ++i) {
456  uint16_t *name, *ext;
457  int max; /* computed max len for name, without extension */
458  int j = i;
459  int digits = 1; /* characters to change per name */
460 
461  /* first, find all child with same name */
462  while (j + 1 < nchildren &&
463  !cmp_node_name(children + i, children + j + 1)) {
464  ++j;
465  }
466  if (j == i) {
467  /* name is unique */
468  continue;
469  }
470 
471  /*
472  * A max of 7 characters is good enough, it allows handling up to
473  * 9,999,999 files with same name.
474  */
475  /* Important: joliet_create_mangled_name() relies on digits < 8 */
476 
477  while (digits < 8) {
478  int ok, k;
479  uint16_t *dot;
480  int change = 0; /* number to be written */
481 
482  /* copy name to buffer */
483  ucscpy(full_name, children[i]->name);
484 
485  /* compute name and extension */
486  dot = ucsrchr(full_name, '.');
487  if (dot != NULL && children[i]->type != JOLIET_DIR) {
488 
489  /*
490  * File (not dir) with extension
491  */
492  int extlen;
493  full_name[dot - full_name] = 0;
494  name = full_name;
495  ext = dot + 1;
496 
497  extlen = ucslen(ext);
498  max = maxchar - extlen - digits;
499  if (max <= 0) {
500  /*
501  * This can happen if the extension is too long.
502  * Reduce its length, to give name at least one
503  * original character, if it has any.
504  */
505  max = (dot > full_name);
506  extlen = maxchar - max - digits;
507  if (extlen < 3) {
508  /*
509  * error, we do not reduce extensions to length < 3
510  *
511  * This cannot happen with current limit of digits
512  * because maxchar is at least 64 and digits at most 7.
513  */
514  ret = ISO_ERROR;
515  goto mangle_cleanup;
516  }
517  ext[extlen] = 0;
518  }
519  /* ok, reduce name by digits */
520  if (name + max < dot) {
521  name[max] = 0;
522  }
523  } else {
524  /* Directory, or file without extension */
525  if (children[i]->type == JOLIET_DIR) {
526  max = maxchar - digits;
527  dot = NULL; /* dots have no meaning in dirs */
528  } else {
529  max = maxchar - digits;
530  }
531  name = full_name;
532  if ((size_t) max < ucslen(name)) {
533  name[max] = 0;
534  }
535  /* let ext be an empty string */
536  ext = name + ucslen(name);
537  }
538 
539  ok = 1;
540  /* change name of each file */
541  for (k = i; k <= j; ++k) {
542  while (1) {
543  ret = joliet_create_mangled_name(tmp, name, digits,
544  change, ext);
545  if (ret < 0) {
546  goto mangle_cleanup;
547  }
548  ++change;
549  if (change > int_pow(10, digits)) {
550  ok = 0;
551  break;
552  }
553  if (!iso_htable_get(table, tmp, NULL)) {
554  /* the name is unique, so it can be used */
555  break;
556  }
557  }
558  if (ok) {
559  uint16_t *new = ucsdup(tmp);
560  if (new == NULL) {
561  ret = ISO_OUT_OF_MEM;
562  goto mangle_cleanup;
563  }
564 
565  iso_htable_remove_ptr(table, children[k]->name, NULL);
566  free(children[k]->name);
567  children[k]->name = new;
568  iso_htable_add(table, new, new);
569 
570  /*
571  * if we change a name we need to sort again children
572  * at the end
573  */
574  need_sort = 1;
575  } else {
576  /* we need to increment digits */
577  break;
578  }
579  }
580  if (ok) {
581  break;
582  } else {
583  ++digits;
584  }
585  }
586  if (digits == 8) {
588  goto mangle_cleanup;
589  }
590  i = j;
591  }
592 
593  /*
594  * If needed, sort again the files inside dir
595  */
596  if (need_sort) {
597  qsort(children, nchildren, sizeof(void*), cmp_node_name);
598  }
599 
600  ret = ISO_SUCCESS;
601 
602 mangle_cleanup : ;
603 ex:;
604  iso_htable_destroy(table, NULL);
605  LIBISO_FREE_MEM(tmp);
606  LIBISO_FREE_MEM(full_name);
607  return ret;
608 }
609 
610 static
612 {
613  int ret;
614  size_t i;
615 
616  ret = mangle_single_dir(t, dir);
617  if (ret < 0) {
618  return ret;
619  }
620 
621  /* recurse */
622  for (i = 0; i < dir->info.dir->nchildren; ++i) {
623  if (dir->info.dir->children[i]->type == JOLIET_DIR) {
624  ret = mangle_tree(t, dir->info.dir->children[i]);
625  if (ret < 0) {
626  /* error */
627  return ret;
628  }
629  }
630  }
631  return ISO_SUCCESS;
632 }
633 
634 static
636 {
637  int ret;
638  JolietNode *root;
639 
640  if (t == NULL) {
641  return ISO_NULL_POINTER;
642  }
643 
644  ret = create_tree(t, (IsoNode*)t->image->root, &root, 0);
645  if (ret <= 0) {
646  if (ret == 0) {
647  /* unexpected error, root ignored!! This can't happen */
648  ret = ISO_ASSERT_FAILURE;
649  }
650  return ret;
651  }
652 
653  /* the Joliet tree is stored in Ecma119Image target */
654  if (t->eff_partition_offset > 0) {
655  t->j_part_root = root;
656  } else {
657  t->joliet_root = root;
658  }
659 
660  iso_msg_debug(t->image->id, "Sorting the Joliet tree...");
661  sort_tree(root);
662 
663  iso_msg_debug(t->image->id, "Mangling Joliet names...");
664  ret = mangle_tree(t, root);
665  if (ret < 0)
666  return ret;
667  return ISO_SUCCESS;
668 }
669 
670 /**
671  * Compute the size of a directory entry for a single node
672  */
673 static
675 {
676  /* note than name len is always even, so we always need the pad byte */
677  int ret = n->name ? ucslen(n->name) * 2 + 34 : 34;
678  if (n->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) {
679  /* take into account version numbers */
680  ret += 4;
681  }
682  return ret;
683 }
684 
685 /**
686  * Computes the total size of all directory entries of a single joliet dir.
687  * This is like ECMA-119 6.8.1.1, but taking care that names are stored in
688  * UCS.
689  */
690 static
692 {
693  size_t i, len;
694 
695  /* size of "." and ".." entries */
696  len = 34 + 34;
697 
698  for (i = 0; i < dir->info.dir->nchildren; ++i) {
699  size_t remaining;
700  int section, nsections;
701  JolietNode *child = dir->info.dir->children[i];
702  size_t dirent_len = calc_dirent_len(t, child);
703 
704  nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
705  for (section = 0; section < nsections; ++section) {
706  remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
707  if (dirent_len > remaining) {
708  /* child directory entry doesn't fit on block */
709  len += remaining + dirent_len;
710  } else {
711  len += dirent_len;
712  }
713  }
714  }
715 
716  /*
717  * The size of a dir is always a multiple of block size, as we must add
718  * the size of the unused space after the last directory record
719  * (ECMA-119, 6.8.1.3)
720  */
721  len = ROUND_UP(len, BLOCK_SIZE);
722 
723  /* cache the len */
724  dir->info.dir->len = len;
725  return len;
726 }
727 
728 static
730 {
731  size_t i, len;
732 
733  t->joliet_ndirs++;
734  dir->info.dir->block = t->curblock;
735  len = calc_dir_size(t, dir);
736  t->curblock += DIV_UP(len, BLOCK_SIZE);
737  for (i = 0; i < dir->info.dir->nchildren; i++) {
738  JolietNode *child = dir->info.dir->children[i];
739  if (child->type == JOLIET_DIR) {
740  calc_dir_pos(t, child);
741  }
742  }
743 }
744 
745 /**
746  * Compute the length of the joliet path table, in bytes.
747  */
748 static
750 {
751  uint32_t size;
752  size_t i;
753 
754  /* size of path table for this entry */
755  size = 8;
756  size += dir->name ? ucslen(dir->name) * 2 : 2;
757 
758  /* and recurse */
759  for (i = 0; i < dir->info.dir->nchildren; i++) {
760  JolietNode *child = dir->info.dir->children[i];
761  if (child->type == JOLIET_DIR) {
762  size += calc_path_table_size(child);
763  }
764  }
765  return size;
766 }
767 
768 static
770 {
771  Ecma119Image *t;
772  uint32_t path_table_size;
773  size_t ndirs;
774 
775  if (writer == NULL) {
776  return ISO_OUT_OF_MEM;
777  }
778 
779  t = writer->target;
780 
781  /* compute position of directories */
782  iso_msg_debug(t->image->id, "Computing position of Joliet dir structure");
783  t->joliet_ndirs = 0;
784  calc_dir_pos(t, t->joliet_root);
785 
786  /* compute length of pathlist */
787  iso_msg_debug(t->image->id, "Computing length of Joliet pathlist");
788  path_table_size = calc_path_table_size(t->joliet_root);
789 
790  /* compute location for path tables */
792  t->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
794  t->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
795  t->joliet_path_table_size = path_table_size;
796 
797  if (t->opts->partition_offset > 0) {
798  /* Take into respect second directory tree */
799  ndirs = t->joliet_ndirs;
800  t->joliet_ndirs = 0;
801  calc_dir_pos(t, t->j_part_root);
802  if (t->joliet_ndirs != ndirs) {
804  "Number of directories differs in Joliet partiton_tree");
805  return ISO_ASSERT_FAILURE;
806  }
807  /* Take into respect second set of path tables */
808  path_table_size = calc_path_table_size(t->j_part_root);
810  t->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
812  t->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
813  }
814 
815  return ISO_SUCCESS;
816 }
817 
818 /**
819  * Write a single directory record for Joliet. It is like (ECMA-119, 9.1),
820  * but file identifier is stored in UCS.
821  *
822  * @param file_id
823  * if >= 0, we use it instead of the filename (for "." and ".." entries).
824  * @param len_fi
825  * Computed length of the file identifier. Total size of the directory
826  * entry will be len + 34 (ECMA-119, 9.1.12), as padding is always needed
827  */
828 static
829 void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
830  uint8_t *buf, size_t len_fi, int extent)
831 {
832  uint32_t len;
833  uint32_t block;
834  uint8_t len_dr; /*< size of dir entry */
835  int multi_extend = 0;
836  uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
837  : (uint8_t*)node->name;
838 
839  struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
840  IsoNode *iso;
841 
842  len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
843 
844  memcpy(rec->file_id, name, len_fi);
845 
846  if (node->type == JOLIET_FILE && !(t->opts->omit_version_numbers & 3)) {
847  len_dr += 4;
848  rec->file_id[len_fi++] = 0;
849  rec->file_id[len_fi++] = ';';
850  rec->file_id[len_fi++] = 0;
851  rec->file_id[len_fi++] = '1';
852  }
853 
854  if (node->type == JOLIET_DIR) {
855  /* use the cached length */
856  len = node->info.dir->len;
857  block = node->info.dir->block;
858  } else if (node->type == JOLIET_FILE) {
859  block = node->info.file->sections[extent].block;
860  len = node->info.file->sections[extent].size;
861  multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
862  } else {
863  /*
864  * for nodes other than files and dirs, we set both
865  * len and block to 0
866  */
867  len = 0;
868  block = 0;
869  }
870 
871  /*
872  * For ".." entry we need to write the parent info!
873  */
874  if (file_id == 1 && node->parent)
875  node = node->parent;
876 
877  rec->len_dr[0] = len_dr;
878  iso_bb(rec->block, block - t->eff_partition_offset, 4);
879  iso_bb(rec->length, len, 4);
880 
881  /* was: iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt);
882  */
883  iso= node->node;
884  iso_datetime_7(rec->recording_time,
885  (t->opts->dir_rec_mtime & 2) ? ( t->replace_timestamps ?
886  t->timestamp : iso->mtime )
887  : t->now, t->opts->always_gmt);
888 
889  rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
890  iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
891  rec->len_fi[0] = len_fi;
892 }
893 
894 /**
895  * Copy up to \p max characters from \p src to \p dest. If \p src has less than
896  * \p max characters, we pad dest with " " characters.
897  */
898 static
899 void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max)
900 {
901  char *cdest, *csrc;
902  size_t len, i;
903 
904  cdest = (char*)dest;
905  csrc = (char*)src;
906 
907  if (src != NULL) {
908  len = MIN(ucslen(src) * 2, max - (max % 2));
909  } else {
910  len = 0;
911  }
912 
913  for (i = 0; i < len; ++i)
914  cdest[i] = csrc[i];
915  if (len >= 2)
916  iso_handle_split_utf16(dest + (len / 2 - 1));
917 
918  for (i = len; i + 1 < max; i += 2) {
919  cdest[i] = '\0';
920  cdest[i + 1] = ' ';
921  }
922  if (max % 2)
923  cdest[max - 1] = 0;
924 }
925 
927 {
928  IsoImage *image;
929  Ecma119Image *t;
930  struct ecma119_sup_vol_desc vol;
931 
932  uint16_t *vol_id = NULL, *pub_id = NULL, *data_id = NULL;
933  uint16_t *volset_id = NULL, *system_id = NULL, *application_id = NULL;
934  uint16_t *copyright_file_id = NULL, *abstract_file_id = NULL;
935  uint16_t *biblio_file_id = NULL;
936 
937  if (writer == NULL) {
938  return ISO_OUT_OF_MEM;
939  }
940 
941  t = writer->target;
942  image = t->image;
943 
944  iso_msg_debug(image->id, "Write SVD for Joliet");
945 
946  memset(&vol, 0, sizeof(struct ecma119_sup_vol_desc));
947 
948  str2ucs(t->input_charset, image->volume_id, &vol_id);
949  str2ucs(t->input_charset, image->publisher_id, &pub_id);
950  str2ucs(t->input_charset, image->data_preparer_id, &data_id);
951  str2ucs(t->input_charset, image->volset_id, &volset_id);
952 
957  str2ucs(t->input_charset, image->biblio_file_id, &biblio_file_id);
958 
959  vol.vol_desc_type[0] = 2;
960  memcpy(vol.std_identifier, "CD001", 5);
961  vol.vol_desc_version[0] = 1;
962  ucsncpy_pad((uint16_t*)vol.volume_id, vol_id, 32);
963 
964  /* make use of UCS-2 Level 3 */
965  memcpy(vol.esc_sequences, "%/E", 3);
967  4);
968  iso_bb(vol.vol_set_size, (uint32_t) 1, 2);
969  iso_bb(vol.vol_seq_number, (uint32_t) 1, 2);
970  iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2);
972 
973  if (t->eff_partition_offset > 0) {
974  /* Point to second tables and second root */
979  write_one_dir_record(t, t->j_part_root, 0, vol.root_dir_record, 1, 0);
980  } else {
983  write_one_dir_record(t, t->joliet_root, 0, vol.root_dir_record, 1, 0);
984  }
985 
986  ucsncpy_pad((uint16_t*)vol.vol_set_id, volset_id, 128);
987  ucsncpy_pad((uint16_t*)vol.publisher_id, pub_id, 128);
988  ucsncpy_pad((uint16_t*)vol.data_prep_id, data_id, 128);
989 
990  ucsncpy_pad((uint16_t*)vol.system_id, system_id, 32);
991 
992  ucsncpy_pad((uint16_t*)vol.application_id, application_id, 128);
993  ucsncpy_pad((uint16_t*)vol.copyright_file_id, copyright_file_id, 37);
994  ucsncpy_pad((uint16_t*)vol.abstract_file_id, abstract_file_id, 37);
995  ucsncpy_pad((uint16_t*)vol.bibliographic_file_id, biblio_file_id, 37);
996 
997  ecma119_set_voldescr_times(writer, (struct ecma119_pri_vol_desc *) &vol);
998  vol.file_structure_version[0] = 1;
999 
1000  free(vol_id);
1001  free(volset_id);
1002  free(pub_id);
1003  free(data_id);
1004  free(system_id);
1005  free(application_id);
1006  free(copyright_file_id);
1007  free(abstract_file_id);
1008  free(biblio_file_id);
1009 
1010  /* Finally write the Volume Descriptor */
1011  return iso_write(t, &vol, sizeof(struct ecma119_sup_vol_desc));
1012 }
1013 
1014 static
1016 {
1017  int ret;
1018  uint8_t *buffer = NULL;
1019  size_t i;
1020  size_t fi_len, len;
1021 
1022  /* buf will point to current write position on buffer */
1023  uint8_t *buf;
1024 
1025  /* initialize buffer with 0s */
1026  LIBISO_ALLOC_MEM(buffer, uint8_t, BLOCK_SIZE);
1027  buf = buffer;
1028 
1029  /* write the "." and ".." entries first */
1030  write_one_dir_record(t, dir, 0, buf, 1, 0);
1031  buf += 34;
1032  write_one_dir_record(t, dir, 1, buf, 1, 0);
1033  buf += 34;
1034 
1035  for (i = 0; i < dir->info.dir->nchildren; i++) {
1036  int section, nsections;
1037  JolietNode *child = dir->info.dir->children[i];
1038 
1039  /* compute len of directory entry */
1040  fi_len = ucslen(child->name) * 2;
1041  len = fi_len + 34;
1042  if (child->type == JOLIET_FILE &&
1043  !(t->opts->omit_version_numbers & 3)) {
1044  len += 4;
1045  }
1046 
1047  nsections = (child->type == JOLIET_FILE) ? child->info.file->nsections : 1;
1048 
1049  for (section = 0; section < nsections; ++section) {
1050 
1051  if ( (buf + len - buffer) > BLOCK_SIZE) {
1052  /* dir doesn't fit in current block */
1053  ret = iso_write(t, buffer, BLOCK_SIZE);
1054  if (ret < 0) {
1055  goto ex;
1056  }
1057  memset(buffer, 0, BLOCK_SIZE);
1058  buf = buffer;
1059  }
1060  /* write the directory entry in any case */
1061  write_one_dir_record(t, child, -1, buf, fi_len, section);
1062  buf += len;
1063  }
1064  }
1065 
1066  /* write the last block */
1067  ret = iso_write(t, buffer, BLOCK_SIZE);
1068 ex:;
1070  return ret;
1071 }
1072 
1073 static
1075 {
1076  int ret;
1077  size_t i;
1078 
1079  /* write all directory entries for this dir */
1080  ret = write_one_dir(t, root);
1081  if (ret < 0) {
1082  return ret;
1083  }
1084 
1085  /* recurse */
1086  for (i = 0; i < root->info.dir->nchildren; i++) {
1087  JolietNode *child = root->info.dir->children[i];
1088  if (child->type == JOLIET_DIR) {
1089  ret = write_dirs(t, child);
1090  if (ret < 0) {
1091  return ret;
1092  }
1093  }
1094  }
1095  return ISO_SUCCESS;
1096 }
1097 
1098 static
1099 int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
1100 {
1101  size_t i, len;
1102  uint8_t *buf = NULL;
1103  struct ecma119_path_table_record *rec;
1104  void (*write_int)(uint8_t*, uint32_t, int);
1105  JolietNode *dir;
1106  uint32_t path_table_size;
1107  int parent = 0;
1108  int ret= ISO_SUCCESS;
1109  uint8_t *zeros = NULL;
1110 
1111  /* 256 is just a convenient size large enough */
1112  LIBISO_ALLOC_MEM(buf, uint8_t, 256);
1113  LIBISO_ALLOC_MEM(zeros, uint8_t, BLOCK_SIZE);
1114  path_table_size = 0;
1115  write_int = l_type ? iso_lsb : iso_msb;
1116 
1117  for (i = 0; i < t->joliet_ndirs; i++) {
1118  dir = pathlist[i];
1119 
1120  /* find the index of the parent in the table */
1121  while ((i) && pathlist[parent] != dir->parent) {
1122  parent++;
1123  }
1124 
1125  /* write the Path Table Record (ECMA-119, 9.4) */
1126  memset(buf, 0, 256);
1127  rec = (struct ecma119_path_table_record*) buf;
1128  rec->len_di[0] = dir->parent ? (uint8_t) ucslen(dir->name) * 2 : 1;
1129  rec->len_xa[0] = 0;
1130  write_int(rec->block, dir->info.dir->block - t->eff_partition_offset,
1131  4);
1132  write_int(rec->parent, parent + 1, 2);
1133  if (dir->parent) {
1134  memcpy(rec->dir_id, dir->name, rec->len_di[0]);
1135  }
1136  len = 8 + rec->len_di[0] + (rec->len_di[0] % 2);
1137  ret = iso_write(t, buf, len);
1138  if (ret < 0) {
1139  /* error */
1140  goto ex;
1141  }
1142  path_table_size += len;
1143  }
1144 
1145  /* we need to fill the last block with zeros */
1146  path_table_size %= BLOCK_SIZE;
1147  if (path_table_size) {
1148  len = BLOCK_SIZE - path_table_size;
1149  memset(zeros, 0, len);
1150  ret = iso_write(t, zeros, len);
1151  }
1152 ex:;
1153  LIBISO_FREE_MEM(zeros);
1154  LIBISO_FREE_MEM(buf);
1155  return ret;
1156 }
1157 
1158 static
1160 {
1161  int ret;
1162  size_t i, j, cur;
1163  JolietNode **pathlist;
1164 
1165  iso_msg_debug(t->image->id, "Writing Joliet Path tables");
1166 
1167  /* allocate temporal pathlist */
1168  pathlist = malloc(sizeof(void*) * t->joliet_ndirs);
1169  if (pathlist == NULL) {
1170  return ISO_OUT_OF_MEM;
1171  }
1172 
1173  if (t->eff_partition_offset > 0) {
1174  pathlist[0] = t->j_part_root;
1175  } else {
1176  pathlist[0] = t->joliet_root;
1177  }
1178  cur = 1;
1179 
1180  for (i = 0; i < t->joliet_ndirs; i++) {
1181  JolietNode *dir = pathlist[i];
1182  for (j = 0; j < dir->info.dir->nchildren; j++) {
1183  JolietNode *child = dir->info.dir->children[j];
1184  if (child->type == JOLIET_DIR) {
1185  pathlist[cur++] = child;
1186  }
1187  }
1188  }
1189 
1190  /* Write L Path Table */
1191  ret = write_path_table(t, pathlist, 1);
1192  if (ret < 0) {
1193  goto write_path_tables_exit;
1194  }
1195 
1196  /* Write L Path Table */
1197  ret = write_path_table(t, pathlist, 0);
1198 
1199  write_path_tables_exit: ;
1200  free(pathlist);
1201  return ret;
1202 }
1203 
1204 static
1206 {
1207  int ret;
1208  Ecma119Image *t;
1209  JolietNode *root;
1210 
1211  t = writer->target;
1212 
1213  /* first of all, we write the directory structure */
1214  if (t->eff_partition_offset > 0) {
1215  root = t->j_part_root;
1216  } else {
1217  root = t->joliet_root;
1218  }
1219  ret = write_dirs(t, root);
1220  if (ret < 0) {
1221  return ret;
1222  }
1223 
1224  /* and write the path tables */
1225  ret = write_path_tables(t);
1226 
1227  return ret;
1228 }
1229 
1230 static
1232 {
1233  int ret;
1234  Ecma119Image *t;
1235 
1236  if (writer == NULL) {
1237  return ISO_NULL_POINTER;
1238  }
1239  t = writer->target;
1240 
1241  ret = joliet_writer_write_dirs(writer);
1242  if (ret < 0)
1243  return ret;
1244 
1245  if (t->opts->partition_offset > 0) {
1247  ret = joliet_writer_write_dirs(writer);
1248  t->eff_partition_offset = 0;
1249  if (ret < 0)
1250  return ret;
1251  }
1252  return ISO_SUCCESS;
1253 }
1254 
1255 static
1257 {
1258  /* free the Joliet tree */
1259  Ecma119Image *t = writer->target;
1261  if (t->j_part_root != NULL)
1263  t->j_part_root = NULL;
1264  return ISO_SUCCESS;
1265 }
1266 
1268 {
1269  int ret;
1270  IsoImageWriter *writer;
1271 
1272  writer = malloc(sizeof(IsoImageWriter));
1273  if (writer == NULL) {
1274  return ISO_OUT_OF_MEM;
1275  }
1276 
1281  writer->data = NULL;
1282  writer->target = target;
1283 
1284  iso_msg_debug(target->image->id, "Creating low level Joliet tree...");
1285  ret = joliet_tree_create(target);
1286  if (ret < 0) {
1287  free((char *) writer);
1288  return ret;
1289  }
1290 
1291  /* add this writer to image */
1292  target->writers[target->nwriters++] = writer;
1293 
1294  if(target->opts->partition_offset > 0) {
1295  /* Create second tree */
1296  target->eff_partition_offset = target->opts->partition_offset;
1297  ret = joliet_tree_create(target);
1298  if (ret < 0) {
1299  return ret;
1300  }
1301  target->eff_partition_offset = 0;
1302  }
1303 
1304  /* we need the volume descriptor */
1305  target->curblock++;
1306  return ISO_SUCCESS;
1307 }
#define BLOCK_SIZE
Definition: buffer.h:23
int iso_write(Ecma119Image *target, void *buf, size_t count)
Definition: ecma119.c:3471
void ecma119_set_voldescr_times(IsoImageWriter *writer, struct ecma119_pri_vol_desc *vol)
Definition: ecma119.c:475
#define ISO_JOLIET_UCS2_WARN_MAX
Definition: ecma119.h:93
#define MAX_ISO_FILE_SECTION_SIZE
Definition: ecma119.h:33
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
Definition: eltorito.c:1199
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
Definition: filesrc.c:69
int joliet_writer_create(Ecma119Image *target)
Definition: joliet.c:1267
static void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id, uint8_t *buf, size_t len_fi, int extent)
Definition: joliet.c:829
static int joliet_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: joliet.c:769
static void sort_tree(JolietNode *root)
Definition: joliet.c:336
static void calc_dir_pos(Ecma119Image *t, JolietNode *dir)
Definition: joliet.c:729
int iso_get_joliet_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, size_t *joliet_ucs2_failures, uint16_t **name, int flag)
Definition: joliet.c:33
static int joliet_tree_create(Ecma119Image *t)
Definition: joliet.c:635
static int joliet_writer_write_dirs(IsoImageWriter *writer)
Definition: joliet.c:1205
int joliet_writer_write_vol_desc(IsoImageWriter *writer)
Definition: joliet.c:926
static size_t calc_dirent_len(Ecma119Image *t, JolietNode *n)
Definition: joliet.c:674
static void joliet_node_free(JolietNode *node)
Definition: joliet.c:119
static void ucsncpy_pad(uint16_t *dest, const uint16_t *src, size_t max)
Definition: joliet.c:899
static uint32_t calc_path_table_size(JolietNode *dir)
Definition: joliet.c:749
static int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits, int number, uint16_t *ext)
Definition: joliet.c:360
static int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
Definition: joliet.c:419
static int cmp_node_name(const void *f1, const void *f2)
Definition: joliet.c:352
static int write_path_table(Ecma119Image *t, JolietNode **pathlist, int l_type)
Definition: joliet.c:1099
static int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
Definition: joliet.c:228
static int mangle_tree(Ecma119Image *t, JolietNode *dir)
Definition: joliet.c:611
static int write_path_tables(Ecma119Image *t)
Definition: joliet.c:1159
static size_t calc_dir_size(Ecma119Image *t, JolietNode *dir)
Definition: joliet.c:691
static int joliet_writer_write_data(IsoImageWriter *writer)
Definition: joliet.c:1231
static int write_one_dir(Ecma119Image *t, JolietNode *dir)
Definition: joliet.c:1015
static int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
Definition: joliet.c:144
static int write_dirs(Ecma119Image *t, JolietNode *root)
Definition: joliet.c:1074
static int cmp_node(const void *f1, const void *f2)
Definition: joliet.c:328
static int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
Definition: joliet.c:106
static int joliet_writer_free_data(IsoImageWriter *writer)
Definition: joliet.c:1256
@ JOLIET_FILE
Definition: joliet.h:26
@ JOLIET_DIR
Definition: joliet.h:27
#define LIBISO_JOLIET_NAME_MAX
Definition: joliet.h:23
int str2ucs(const char *icharset, const char *input, uint16_t **output)
Definition: util.c:558
void iso_datetime_7(unsigned char *buf, time_t t, int always_gmt)
Definition: util.c:1574
uint16_t * iso_j_dir_id(const uint16_t *src, int flag)
Definition: util.c:1298
void iso_bb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1502
void iso_msb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1494
int ucscmp(const uint16_t *s1, const uint16_t *s2)
Definition: util.c:1371
int str2utf16be(const char *icharset, const char *input, uint16_t **output)
Definition: util.c:687
uint16_t * ucsdup(const uint16_t *str)
Definition: util.c:1352
uint16_t * ucscpy(uint16_t *dest, const uint16_t *src)
Definition: util.c:1394
void iso_handle_split_utf16(uint16_t *utf_word)
Definition: util.c:2326
int int_pow(int base, int power)
Definition: util.c:159
uint16_t * ucsrchr(const uint16_t *str, char c)
Definition: util.c:1340
size_t ucslen(const uint16_t *str)
Definition: util.c:1331
uint16_t * iso_j_file_id(const uint16_t *src, int flag)
Definition: util.c:1215
void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1478
uint16_t * ucsncpy(uint16_t *dest, const uint16_t *src, size_t n)
Definition: util.c:1401
int iso_htable_remove_ptr(IsoHTable *table, void *key, hfree_data_t free_data)
Definition: util_htable.c:236
#define MIN(a, b)
Definition: util.h:35
int iso_htable_add(IsoHTable *table, void *key, void *data)
Definition: util_htable.c:70
int(* compare_function_t)(const void *a, const void *b)
Definition: util.h:343
int iso_htable_create(size_t size, hash_funtion_t hash, compare_function_t compare, IsoHTable **table)
Definition: util_htable.c:321
#define LIBISO_FREE_MEM(pt)
Definition: util.h:627
#define ROUND_UP(n, mul)
Definition: util.h:39
void iso_htable_destroy(IsoHTable *table, hfree_data_t free_data)
Definition: util_htable.c:290
#define DIV_UP(n, div)
Definition: util.h:38
unsigned int iso_str_hash(const void *key)
Definition: util_htable.c:270
#define LIBISO_ALLOC_MEM(pt, typ, count)
Definition: util.h:615
int iso_htable_get(IsoHTable *table, void *key, void **data)
Definition: util_htable.c:144
void iso_node_unref(IsoNode *node)
Definition: node.c:56
#define ISO_SUCCESS
Definition: libisofs.h:8719
IsoNodeType
Definition: libisofs.h:228
@ LIBISO_BOOT
Definition: libisofs.h:233
@ LIBISO_DIR
Definition: libisofs.h:229
@ LIBISO_FILE
Definition: libisofs.h:230
@ LIBISO_SYMLINK
Definition: libisofs.h:231
@ LIBISO_SPECIAL
Definition: libisofs.h:232
#define ISO_NAME_NOT_UCS2
Definition: libisofs.h:9162
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
char * iso_tree_get_node_path(IsoNode *node)
Definition: tree.c:1247
off_t iso_stream_get_size(IsoStream *stream)
Definition: stream.c:810
#define ISO_FILE_IMGPATH_WRONG
Definition: libisofs.h:8852
#define ISO_FILE_TOO_BIG
Definition: libisofs.h:8835
#define ISO_FILE_IGNORED
Definition: libisofs.h:8832
void iso_node_ref(IsoNode *node)
Definition: node.c:46
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
@ LIBISO_HIDE_ON_JOLIET
Definition: libisofs.h:304
#define ISO_ERROR
Definition: libisofs.h:8734
#define ISO_MANGLE_TOO_MUCH_FILES
Definition: libisofs.h:8868
#define ISO_ASSERT_FAILURE
Definition: libisofs.h:8737
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt,...)
Definition: messages.c:579
void iso_msg_debug(int imgid, const char *fmt,...)
Definition: messages.c:253
Definition: node.h:140
IsoNode * children
Definition: node.h:144
size_t nchildren
Definition: node.h:143
struct iso_file_section * sections
Definition: filesrc.h:56
int nsections
Definition: filesrc.h:57
Definition: node.h:149
IsoStream * stream
Definition: node.h:166
Ecma119Image * target
Definition: writer.h:28
int(* write_data)(IsoImageWriter *writer)
Definition: writer.h:23
void * data
Definition: writer.h:27
int(* compute_data_blocks)(IsoImageWriter *writer)
Definition: writer.h:19
int(* write_vol_desc)(IsoImageWriter *writer)
Definition: writer.h:21
int(* free_data)(IsoImageWriter *writer)
Definition: writer.h:25
int id
Definition: image.h:97
char * abstract_file_id
Definition: image.h:53
char * data_preparer_id
Definition: image.h:49
char * volume_id
Definition: image.h:47
char * volset_id
Definition: image.h:45
char * publisher_id
Definition: image.h:48
char * application_id
Definition: image.h:51
IsoDir * root
Definition: image.h:43
char * biblio_file_id
Definition: image.h:54
char * system_id
Definition: image.h:50
char * copyright_file_id
Definition: image.h:52
Definition: node.h:100
char * name
Definition: node.h:113
enum IsoNodeType type
Definition: node.h:111
int hidden
Definition: node.h:124
IsoNode * next
Definition: node.h:131
time_t mtime
Definition: node.h:121
JolietNode * joliet_root
Definition: ecma119.h:643
uint32_t vol_space_size
Definition: ecma119.h:602
IsoImage * image
Definition: ecma119.h:560
size_t joliet_ndirs
Definition: ecma119.h:644
uint32_t joliet_l_path_table_pos
Definition: ecma119.h:646
time_t now
Definition: ecma119.h:594
unsigned int eltorito
Definition: ecma119.h:566
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t j_part_l_path_table_pos
Definition: ecma119.h:803
unsigned int replace_timestamps
Definition: ecma119.h:581
char * input_charset
Definition: ecma119.h:591
IsoImageWriter ** writers
Definition: ecma119.h:753
JolietNode * j_part_root
Definition: ecma119.h:802
size_t joliet_ucs2_failures
Definition: ecma119.h:648
size_t nwriters
Definition: ecma119.h:752
uint32_t curblock
Definition: ecma119.h:618
uint32_t joliet_m_path_table_pos
Definition: ecma119.h:647
time_t timestamp
Definition: ecma119.h:588
uint32_t joliet_path_table_size
Definition: ecma119.h:645
uint32_t eff_partition_offset
Definition: ecma119.h:794
uint32_t j_part_m_path_table_pos
Definition: ecma119.h:804
uint8_t len_di[(1) -(1)+1]
Definition: ecma119.h:1029
uint8_t dir_id[(9) -(9)+1]
Definition: ecma119.h:1033
uint8_t parent[(8) -(7)+1]
Definition: ecma119.h:1032
uint8_t len_xa[(2) -(2)+1]
Definition: ecma119.h:1030
uint8_t block[(6) -(3)+1]
Definition: ecma119.h:1031
uint8_t esc_sequences[(120) -(89)+1]
Definition: ecma119.h:969
uint8_t m_path_table_pos[(152) -(149)+1]
Definition: ecma119.h:976
uint8_t vol_seq_number[(128) -(125)+1]
Definition: ecma119.h:971
uint8_t vol_space_size[(88) -(81)+1]
Definition: ecma119.h:968
uint8_t vol_set_size[(124) -(121)+1]
Definition: ecma119.h:970
uint8_t root_dir_record[(190) -(157)+1]
Definition: ecma119.h:978
uint8_t data_prep_id[(574) -(447)+1]
Definition: ecma119.h:981
uint8_t volume_id[(72) -(41)+1]
Definition: ecma119.h:966
uint8_t file_structure_version[(882) -(882)+1]
Definition: ecma119.h:990
uint8_t system_id[(40) -(9)+1]
Definition: ecma119.h:965
uint8_t std_identifier[(6) -(2)+1]
Definition: ecma119.h:962
uint8_t copyright_file_id[(739) -(703)+1]
Definition: ecma119.h:983
uint8_t vol_desc_version[(7) -(7)+1]
Definition: ecma119.h:963
uint8_t block_size[(132) -(129)+1]
Definition: ecma119.h:972
uint8_t vol_desc_type[(1) -(1)+1]
Definition: ecma119.h:961
uint8_t path_table_size[(140) -(133)+1]
Definition: ecma119.h:973
uint8_t abstract_file_id[(776) -(740)+1]
Definition: ecma119.h:984
uint8_t l_path_table_pos[(144) -(141)+1]
Definition: ecma119.h:974
uint8_t application_id[(702) -(575)+1]
Definition: ecma119.h:982
uint8_t vol_set_id[(318) -(191)+1]
Definition: ecma119.h:979
uint8_t publisher_id[(446) -(319)+1]
Definition: ecma119.h:980
uint8_t bibliographic_file_id[(813) -(777)+1]
Definition: ecma119.h:985
uint32_t size
Definition: libisofs.h:259
uint32_t block
Definition: libisofs.h:258
unsigned int joliet_longer_paths
Definition: ecma119.h:194
unsigned int dir_rec_mtime
Definition: ecma119.h:244
uint32_t partition_offset
Definition: ecma119.h:451
unsigned int no_force_dots
Definition: ecma119.h:163
unsigned int joliet_utf16
Definition: ecma119.h:204
unsigned int always_gmt
Definition: ecma119.h:115
unsigned int joliet_long_names
Definition: ecma119.h:199
unsigned int omit_version_numbers
Definition: ecma119.h:136
size_t len
Definition: joliet.h:33
size_t nchildren
Definition: joliet.h:32
JolietNode ** children
Definition: joliet.h:31
size_t block
Definition: joliet.h:34
JolietNode * parent
Definition: joliet.h:41
struct joliet_dir_info * dir
Definition: joliet.h:48
uint16_t * name
Definition: joliet.h:39
IsoNode * node
Definition: joliet.h:43
enum joliet_node_type type
Definition: joliet.h:45
IsoFileSrc * file
Definition: joliet.h:47
union joliet_node::@5 info