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)  

ecma119.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007 Vreixo Formoso
3  * Copyright (c) 2007 Mario Danic
4  * Copyright (c) 2009 - 2019 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 /*
17  Use the copy of the struct burn_source definition in libisofs.h
18 */
19 #define LIBISOFS_WITHOUT_LIBBURN yes
20 #include "libisofs.h"
21 
22 #include "ecma119.h"
23 #include "joliet.h"
24 #include "hfsplus.h"
25 #include "iso1999.h"
26 #include "eltorito.h"
27 #include "ecma119_tree.h"
28 #include "filesrc.h"
29 #include "image.h"
30 #include "writer.h"
31 #include "messages.h"
32 #include "rockridge.h"
33 #include "util.h"
34 #include "system_area.h"
35 #include "md5.h"
36 
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <time.h>
40 #include <string.h>
41 #include <locale.h>
42 #include <langinfo.h>
43 #include <stdio.h>
44 
45 #ifdef Xorriso_standalonE
46 
47 #ifdef Xorriso_with_libjtE
48 #include "../libjte/libjte.h"
49 #endif
50 
51 #else
52 
53 #ifdef Libisofs_with_libjtE
54 #include <libjte/libjte.h>
55 #endif
56 
57 #endif /* ! Xorriso_standalonE */
58 
59 
60 int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag);
61 
62 
63 /*
64  * TODO #00011 : guard against bad path table usage with more than 65535 dirs
65  * image with more than 65535 directories have path_table related problems
66  * due to 16 bits parent id. Note that this problem only affects to folders
67  * that are parent of another folder.
68  */
69 
70 static
72 {
73  size_t i;
74 
75  if (t == NULL)
76  return;
77 
78  if (t->refcount > 1) {
79  t->refcount--;
80  return;
81  }
82 
83  if (t->root != NULL)
85  if (t->opts != NULL)
87  if (t->image != NULL)
89  if (t->files != NULL)
91  if (t->ecma119_hidden_list != NULL)
93  if (t->buffer != NULL)
95 
96  for (i = 0; i < t->nwriters; ++i) {
97  IsoImageWriter *writer = t->writers[i];
98  writer->free_data(writer);
99  free(writer);
100  }
101  if (t->input_charset != NULL)
102  free(t->input_charset);
103  if (t->output_charset != NULL)
104  free(t->output_charset);
105  if (t->bootsrc != NULL)
106  free(t->bootsrc);
107  if (t->boot_appended_idx != NULL)
108  free(t->boot_appended_idx);
109  if (t->boot_intvl_start != NULL)
110  free(t->boot_intvl_start);
111  if (t->boot_intvl_size != NULL)
112  free(t->boot_intvl_size);
113  if (t->system_area_data != NULL)
114  free(t->system_area_data);
115  if (t->checksum_ctx != NULL) { /* dispose checksum context */
116  char md5[16];
117  iso_md5_end(&(t->checksum_ctx), md5);
118  }
119  if (t->checksum_buffer != NULL)
120  free(t->checksum_buffer);
121  if (t->writers != NULL)
122  free(t->writers);
123  if (t->partition_root != NULL)
125  for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
126  if (t->hfsplus_blessed[i] != NULL)
128  for (i = 0; (int) i < t->apm_req_count; i++)
129  if (t->apm_req[i] != NULL)
130  free(t->apm_req[i]);
131  for (i = 0; (int) i < t->mbr_req_count; i++)
132  if (t->mbr_req[i] != NULL)
133  free(t->mbr_req[i]);
134  for (i = 0; (int) i < t->gpt_req_count; i++)
135  if (t->gpt_req[i] != NULL)
136  free(t->gpt_req[i]);
137 
138  free(t);
139 }
140 
141 static int show_chunk_to_jte(Ecma119Image *target, char *buf, int count)
142 {
143 
144 #ifdef Libisofs_with_libjtE
145 
146  int ret;
147 
148  if (target->opts->libjte_handle == NULL)
149  return ISO_SUCCESS;
150  ret = libjte_show_data_chunk(target->opts->libjte_handle, buf, count, 1);
151  if (ret <= 0) {
152  iso_libjte_forward_msgs(target->opts->libjte_handle,
153  target->image->id, ISO_LIBJTE_FILE_FAILED, 0);
154  return ISO_LIBJTE_FILE_FAILED;
155  }
156 
157 #endif /* Libisofs_with_libjtE */
158 
159  return ISO_SUCCESS;
160 }
161 
162 /**
163  * Check if we should add version number ";" to the given node name.
164  */
165 static
167 {
168  if ((opts->omit_version_numbers & 1) ||
169  opts->max_37_char_filenames || opts->untranslated_name_len > 0) {
170  return 0;
171  }
172  if (node_type == ECMA119_DIR || node_type == ECMA119_PLACEHOLDER) {
173  return 0;
174  } else {
175  return 1;
176  }
177 }
178 
179 /**
180  * Compute the size of a directory entry for a single node
181  */
182 static
184 {
185  int ret = n->iso_name ? strlen(n->iso_name) + 33 : 34;
186  if (need_version_number(t->opts, n->type)) {
187  ret += 2; /* take into account version numbers */
188  }
189  if (ret % 2)
190  ret++;
191  return ret;
192 }
193 
194 /**
195  * Computes the total size of all directory entries of a single dir,
196  * according to ECMA-119 6.8.1.1
197  *
198  * This also take into account the size needed for RR entries and
199  * SUSP continuation areas (SUSP, 5.1).
200  *
201  * @param ce
202  * Will be filled with the size needed for Continuation Areas
203  * @return
204  * The size needed for all dir entries of the given dir, without
205  * taking into account the continuation areas.
206  */
207 static
208 size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
209 {
210  size_t i, len;
211  size_t ce_len = 0;
212 
213  /* size of "." and ".." entries */
214  len = 34 + 34;
215  if (t->opts->rockridge) {
216  len += rrip_calc_len(t, dir, 1, 34, &ce_len, *ce);
217  *ce += ce_len;
218  len += rrip_calc_len(t, dir, 2, 34, &ce_len, *ce);
219  *ce += ce_len;
220  }
221 
222  for (i = 0; i < dir->info.dir->nchildren; ++i) {
223  size_t remaining;
224  int section, nsections;
225  Ecma119Node *child = dir->info.dir->children[i];
226 
227  nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
228  for (section = 0; section < nsections; ++section) {
229  size_t dirent_len = calc_dirent_len(t, child);
230  if (t->opts->rockridge) {
231  dirent_len += rrip_calc_len(t, child, 0, dirent_len, &ce_len,
232  *ce);
233  *ce += ce_len;
234  }
235  remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
236  if (dirent_len > remaining) {
237  /* child directory entry doesn't fit on block */
238  len += remaining + dirent_len;
239  } else {
240  len += dirent_len;
241  }
242  }
243  }
244 
245  /*
246  * The size of a dir is always a multiple of block size, as we must add
247  * the size of the unused space after the last directory record
248  * (ECMA-119, 6.8.1.3)
249  */
250  len = ROUND_UP(len, BLOCK_SIZE);
251 
252  /* cache the len */
253  dir->info.dir->len = len;
254  return len;
255 }
256 
257 static
259 {
260  size_t i, len;
261  size_t ce_len = 0;
262 
263  t->ndirs++;
264  dir->info.dir->block = t->curblock;
265  len = calc_dir_size(t, dir, &ce_len);
266  t->curblock += DIV_UP(len, BLOCK_SIZE);
267  if (t->opts->rockridge) {
268  t->curblock += DIV_UP(ce_len, BLOCK_SIZE);
269  }
270  for (i = 0; i < dir->info.dir->nchildren; i++) {
271  Ecma119Node *child = dir->info.dir->children[i];
272  if (child->type == ECMA119_DIR) {
273  calc_dir_pos(t, child);
274  }
275  }
276 }
277 
278 /**
279  * Compute the length of the path table, in bytes.
280  */
281 static
283 {
284  uint32_t size;
285  size_t i;
286 
287  /* size of path table for this entry */
288  size = 8;
289  size += dir->iso_name ? strlen(dir->iso_name) : 1;
290  size += (size % 2);
291 
292  /* and recurse */
293  for (i = 0; i < dir->info.dir->nchildren; i++) {
294  Ecma119Node *child = dir->info.dir->children[i];
295  if (child->type == ECMA119_DIR) {
296  size += calc_path_table_size(child);
297  }
298  }
299  return size;
300 }
301 
302 static
304 {
305  Ecma119Image *target;
306  uint32_t path_table_size;
307  size_t ndirs;
308 
309  if (writer == NULL) {
310  return ISO_ASSERT_FAILURE;
311  }
312 
313  target = writer->target;
314 
315  /* compute position of directories */
316  iso_msg_debug(target->image->id, "Computing position of dir structure");
317  target->ndirs = 0;
318  calc_dir_pos(target, target->root);
319 
320  /* compute length of pathlist */
321  iso_msg_debug(target->image->id, "Computing length of pathlist");
322  path_table_size = calc_path_table_size(target->root);
323 
324  /* compute location for path tables */
325  target->l_path_table_pos = target->curblock;
326  target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
327  target->m_path_table_pos = target->curblock;
328  target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
329  target->path_table_size = path_table_size;
330 
331  if (target->opts->md5_session_checksum) {
332  /* Account for first tree checksum tag */
333  target->checksum_tree_tag_pos = target->curblock;
334  target->curblock++;
335  }
336 
337  if (target->opts->partition_offset > 0) {
338  /* Take into respect the second directory tree */
339  ndirs = target->ndirs;
340  target->ndirs = 0;
341  calc_dir_pos(target, target->partition_root);
342  if (target->ndirs != ndirs) {
344  "Number of directories differs in ECMA-119 partiton_tree");
345  return ISO_ASSERT_FAILURE;
346  }
347  /* Take into respect the second set of path tables */
348  path_table_size = calc_path_table_size(target->partition_root);
349  target->partition_l_table_pos = target->curblock;
350  target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
351  target->partition_m_table_pos = target->curblock;
352  target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
353 
354  /* >>> TWINTREE: >>> For now, checksum tags are only for the
355  image start and not for the partition */;
356 
357  }
358 
359  target->tree_end_block = target->curblock;
360 
361  return ISO_SUCCESS;
362 }
363 
364 /**
365  * Write a single directory record (ECMA-119, 9.1)
366  *
367  * @param file_id
368  * if >= 0, we use it instead of the filename (for "." and ".." entries).
369  * @param len_fi
370  * Computed length of the file identifier. Total size of the directory
371  * entry will be len + 33 + padding if needed (ECMA-119, 9.1.12)
372  * @param info
373  * SUSP entries for the given directory record. It will be NULL for the
374  * root directory record in the PVD (ECMA-119, 8.4.18) (in order to
375  * distinguish it from the "." entry in the root directory)
376  */
377 static
378 void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
379  uint8_t *buf, size_t len_fi, struct susp_info *info,
380  int extent)
381 {
382  uint32_t len;
383  uint32_t block;
384  uint8_t len_dr; /*< size of dir entry without SUSP fields */
385  int multi_extend = 0;
386  uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
387  : (uint8_t*)node->iso_name;
388 
389  struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
390  IsoNode *iso;
391 
392  len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
393 
394  memcpy(rec->file_id, name, len_fi);
395 
396  if (need_version_number(t->opts, node->type)) {
397  len_dr += 2;
398  rec->file_id[len_fi++] = ';';
399  rec->file_id[len_fi++] = '1';
400  }
401 
402  if (node->type == ECMA119_DIR) {
403  /* use the cached length */
404  len = node->info.dir->len;
405  block = node->info.dir->block;
406  } else if (node->type == ECMA119_FILE) {
407  block = node->info.file->sections[extent].block;
408  len = node->info.file->sections[extent].size;
409  multi_extend = (node->info.file->nsections - 1 == extent) ? 0 : 1;
410  } else {
411  /*
412  * for nodes other than files and dirs, we set len to 0, and
413  * the content block address to a dummy value.
414  */
415  len = 0;
416  if (! t->opts->old_empty)
417  block = t->empty_file_block;
418  else
419  block = 0;
420  }
421 
422  /*
423  * For ".." entry we need to write the parent info!
424  */
425  if (file_id == 1 && node->parent)
426  node = node->parent;
427 
428  rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0);
429  iso_bb(rec->block, block - t->eff_partition_offset, 4);
430  iso_bb(rec->length, len, 4);
431  if (t->opts->dir_rec_mtime & 1) {
432  iso= node->node;
433  iso_datetime_7(rec->recording_time,
434  t->replace_timestamps ? t->timestamp : iso->mtime,
435  t->opts->always_gmt);
436  } else {
437  iso_datetime_7(rec->recording_time, t->now, t->opts->always_gmt);
438  }
439  rec->flags[0] = ((node->type == ECMA119_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
440  iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
441  rec->len_fi[0] = len_fi;
442 
443  /*
444  * and finally write the SUSP fields.
445  */
446  if (info != NULL) {
447  rrip_write_susp_fields(t, info, buf + len_dr);
448  }
449 }
450 
451 static
452 char *get_relaxed_vol_id(Ecma119Image *t, const char *name)
453 {
454  int ret;
455  if (name == NULL) {
456  return NULL;
457  }
458  if (strcmp(t->input_charset, t->output_charset)) {
459  /* charset conversion needed */
460  char *str;
461  ret = strconv(name, t->input_charset, t->output_charset, &str);
462  if (ret == ISO_SUCCESS) {
463  return str;
464  }
466  "Charset conversion error. Cannot convert from %s to %s",
468  }
469  return strdup(name);
470 }
471 
472 /**
473  * Set the timestamps of Primary, Supplementary, or Enhanced Volume Descriptor.
474  */
476  struct ecma119_pri_vol_desc *vol)
477 {
478  Ecma119Image *t = writer->target;
479  IsoWriteOpts *o;
480  int i;
481 
482  o = t->opts;
483  if (o->vol_uuid[0]) {
484  for(i = 0; i < 16; i++)
485  if(o->vol_uuid[i] < '0' || o->vol_uuid[i] > '9')
486  break;
487  else
488  vol->vol_creation_time[i] = o->vol_uuid[i];
489  for(; i < 16; i++)
490  vol->vol_creation_time[i] = '1';
491  vol->vol_creation_time[16] = 0;
492  } else if (o->vol_creation_time > 0)
494  o->always_gmt);
495  else
497 
498  if (o->vol_uuid[0]) {
499  for(i = 0; i < 16; i++)
500  if(o->vol_uuid[i] < '0' || o->vol_uuid[i] > '9')
501  break;
502  else
503  vol->vol_modification_time[i] = o->vol_uuid[i];
504  for(; i < 16; i++)
505  vol->vol_modification_time[i] = '1';
506  vol->vol_modification_time[16] = 0;
507  } else if (o->vol_modification_time > 0)
509  o->always_gmt);
510  else
512 
513  if (o->vol_expiration_time > 0) {
515  o->always_gmt);
516  } else {
517  for(i = 0; i < 16; i++)
518  vol->vol_expiration_time[i] = '0';
519  vol->vol_expiration_time[16] = 0;
520  }
521 
522  if (o->vol_effective_time > 0) {
524  o->always_gmt);
525  } else {
526  for(i = 0; i < 16; i++)
527  vol->vol_effective_time[i] = '0';
528  vol->vol_effective_time[16] = 0;
529  }
530 }
531 
532 /**
533  * Write the Primary Volume Descriptor (ECMA-119, 8.4)
534  */
535 static
537 {
538  IsoImage *image;
539  Ecma119Image *t;
540  struct ecma119_pri_vol_desc vol;
541  char *vol_id, *pub_id, *data_id, *volset_id;
543  char *abstract_file_id, *biblio_file_id;
544 
545  if (writer == NULL) {
546  return ISO_ASSERT_FAILURE;
547  }
548 
549  t = writer->target;
550  image = t->image;
551 
552  iso_msg_debug(image->id, "Write Primary Volume Descriptor");
553 
554  memset(&vol, 0, sizeof(struct ecma119_pri_vol_desc));
555 
556  if (t->opts->relaxed_vol_atts) {
557  vol_id = get_relaxed_vol_id(t, image->volume_id);
558  volset_id = get_relaxed_vol_id(t, image->volset_id);
559  } else {
560  str2d_char(t->input_charset, image->volume_id, &vol_id);
561  str2d_char(t->input_charset, image->volset_id, &volset_id);
562  }
563  str2a_char(t->input_charset, image->publisher_id, &pub_id);
564  str2a_char(t->input_charset, image->data_preparer_id, &data_id);
569  str2d_char(t->input_charset, image->biblio_file_id, &biblio_file_id);
570 
571  vol.vol_desc_type[0] = 1;
572  memcpy(vol.std_identifier, "CD001", 5);
573  vol.vol_desc_version[0] = 1;
574  strncpy_pad((char*)vol.system_id, system_id, 32);
575  strncpy_pad((char*)vol.volume_id, vol_id, 32);
576  if (t->pvd_size_is_total_size && t->eff_partition_offset <= 0) {
577  iso_bb(vol.vol_space_size, t->total_size / 2048, 4);
578  } else {
581  }
582  iso_bb(vol.vol_set_size, (uint32_t) 1, 2);
583  iso_bb(vol.vol_seq_number, (uint32_t) 1, 2);
584  iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2);
586 
587  if (t->eff_partition_offset > 0) {
588  /* Point to second tables and second root */
594  vol.root_dir_record, 1, NULL, 0);
595  } else {
598  write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL, 0);
599  }
600 
601  strncpy_pad((char*)vol.vol_set_id, volset_id, 128);
602  strncpy_pad((char*)vol.publisher_id, pub_id, 128);
603  strncpy_pad((char*)vol.data_prep_id, data_id, 128);
604 
605  strncpy_pad((char*)vol.application_id, application_id, 128);
608  strncpy_pad((char*)vol.bibliographic_file_id, biblio_file_id, 37);
609 
610  ecma119_set_voldescr_times(writer, &vol);
611  vol.file_structure_version[0] = 1;
612 
613  memcpy(vol.app_use, image->application_use, 512);
614 
615  free(vol_id);
616  free(volset_id);
617  free(pub_id);
618  free(data_id);
619  free(system_id);
620  free(application_id);
621  free(copyright_file_id);
622  free(abstract_file_id);
623  free(biblio_file_id);
624 
625  /* Finally write the Volume Descriptor */
626  return iso_write(t, &vol, sizeof(struct ecma119_pri_vol_desc));
627 }
628 
629 static
631 {
632  int ret;
633  uint8_t *buffer = NULL;
634  size_t i;
635  size_t fi_len, len;
636  struct susp_info info;
637 
638  /* buf will point to current write position on buffer */
639  uint8_t *buf;
640 
642  buf = buffer;
643 
644  /*
645  * set susp_info to 0's, this way code for both plain ECMA-119 and
646  * RR is very similar
647  */
648  memset(&info, 0, sizeof(struct susp_info));
649  if (t->opts->rockridge) {
650  /* initialize the ce_block, it might be needed */
651  info.ce_block = dir->info.dir->block + DIV_UP(dir->info.dir->len,
652  BLOCK_SIZE);
653  info.ce_susp_fields = NULL;
654  }
655 
656  /* write the "." and ".." entries first */
657  if (t->opts->rockridge) {
658  ret = rrip_get_susp_fields(t, dir, 1, 34, &info);
659  if (ret < 0) {
660  goto ex;
661  }
662  }
663  len = 34 + info.suf_len;
664  write_one_dir_record(t, dir, 0, buf, 1, &info, 0);
665  buf += len;
666 
667  if (t->opts->rockridge) {
668  ret = rrip_get_susp_fields(t, dir, 2, 34, &info);
669  if (ret < 0) {
670  goto ex;
671  }
672  }
673  len = 34 + info.suf_len;
674  write_one_dir_record(t, parent, 1, buf, 1, &info, 0);
675  buf += len;
676 
677  for (i = 0; i < dir->info.dir->nchildren; i++) {
678  int section, nsections;
679  Ecma119Node *child = dir->info.dir->children[i];
680 
681  fi_len = strlen(child->iso_name);
682 
683  nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
684  for (section = 0; section < nsections; ++section) {
685 
686  /* compute len of directory entry */
687  len = fi_len + 33 + ((fi_len % 2) ? 0 : 1);
688  if (need_version_number(t->opts, child->type)) {
689  len += 2;
690  }
691 
692  /* get the SUSP fields if rockridge is enabled */
693  if (t->opts->rockridge) {
694  ret = rrip_get_susp_fields(t, child, 0, len, &info);
695  if (ret < 0) {
696  goto ex;
697  }
698  len += info.suf_len;
699  }
700 
701  if ( (buf + len - buffer) > BLOCK_SIZE) {
702  /* dir doesn't fit in current block */
703  ret = iso_write(t, buffer, BLOCK_SIZE);
704  if (ret < 0) {
705  goto ex;
706  }
707  memset(buffer, 0, BLOCK_SIZE);
708  buf = buffer;
709  }
710  /* write the directory entry in any case */
711  write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
712  buf += len;
713  }
714  }
715 
716  /* write the last block */
717  ret = iso_write(t, buffer, BLOCK_SIZE);
718  if (ret < 0) {
719  goto ex;
720  }
721 
722  /* write the Continuation Area if needed */
723  if (info.ce_len > 0) {
724  ret = rrip_write_ce_fields(t, &info);
725  }
726 
727 ex:;
729  return ret;
730 }
731 
732 static
734 {
735  int ret;
736  size_t i;
737 
738  /* write all directory entries for this dir */
739  ret = write_one_dir(t, root, parent);
740  if (ret < 0) {
741  return ret;
742  }
743 
744  /* recurse */
745  for (i = 0; i < root->info.dir->nchildren; i++) {
746  Ecma119Node *child = root->info.dir->children[i];
747  if (child->type == ECMA119_DIR) {
748  ret = write_dirs(t, child, root);
749  if (ret < 0) {
750  return ret;
751  }
752  }
753  }
754  return ISO_SUCCESS;
755 }
756 
757 static
758 int write_path_table(Ecma119Image *t, Ecma119Node **pathlist, int l_type)
759 {
760  size_t i, len;
761  uint8_t buf[64]; /* 64 is just a convenient size larger enough */
762  struct ecma119_path_table_record *rec;
763  void (*write_int)(uint8_t*, uint32_t, int);
764  Ecma119Node *dir;
765  uint32_t path_table_size;
766  int parent = 0;
767  int ret= ISO_SUCCESS;
768  uint8_t *zeros = NULL;
769 
770  path_table_size = 0;
771  write_int = l_type ? iso_lsb : iso_msb;
772 
773  for (i = 0; i < t->ndirs; i++) {
774  dir = pathlist[i];
775 
776  /* find the index of the parent in the table */
777  while ((i) && pathlist[parent] != dir->parent) {
778  parent++;
779  }
780 
781  /* write the Path Table Record (ECMA-119, 9.4) */
782  memset(buf, 0, 64);
783  rec = (struct ecma119_path_table_record*) buf;
784  rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->iso_name) : 1;
785  rec->len_xa[0] = 0;
786  write_int(rec->block, dir->info.dir->block - t->eff_partition_offset,
787  4);
788  write_int(rec->parent, parent + 1, 2);
789  if (dir->parent) {
790  memcpy(rec->dir_id, dir->iso_name, rec->len_di[0]);
791  }
792  len = 8 + rec->len_di[0] + (rec->len_di[0] % 2);
793  ret = iso_write(t, buf, len);
794  if (ret < 0) {
795  /* error */
796  goto ex;
797  }
798  path_table_size += len;
799  }
800 
801  /* we need to fill the last block with zeros */
802  path_table_size %= BLOCK_SIZE;
803  if (path_table_size) {
804  len = BLOCK_SIZE - path_table_size;
805  LIBISO_ALLOC_MEM(zeros, uint8_t, len);
806  ret = iso_write(t, zeros, len);
807  }
808 ex:;
809  LIBISO_FREE_MEM(zeros);
810  return ret;
811 }
812 
813 static
815 {
816  int ret;
817  size_t i, j, cur;
818  Ecma119Node **pathlist;
819 
820  iso_msg_debug(t->image->id, "Writing ISO Path tables");
821 
822  /* allocate temporal pathlist */
823  pathlist = malloc(sizeof(void*) * t->ndirs);
824  if (pathlist == NULL) {
825  return ISO_OUT_OF_MEM;
826  }
827 
828  if (t->eff_partition_offset > 0) {
829  pathlist[0] = t->partition_root;
830  } else {
831  pathlist[0] = t->root;
832  }
833  cur = 1;
834 
835  for (i = 0; i < t->ndirs; i++) {
836  Ecma119Node *dir = pathlist[i];
837  for (j = 0; j < dir->info.dir->nchildren; j++) {
838  Ecma119Node *child = dir->info.dir->children[j];
839  if (child->type == ECMA119_DIR) {
840  pathlist[cur++] = child;
841  }
842  }
843  }
844 
845  /* Write L Path Table */
846  ret = write_path_table(t, pathlist, 1);
847  if (ret < 0) {
848  goto write_path_tables_exit;
849  }
850 
851  /* Write L Path Table */
852  ret = write_path_table(t, pathlist, 0);
853 
854  write_path_tables_exit: ;
855  free(pathlist);
856  return ret;
857 }
858 
859 
860 /**
861  * Write the directory structure (ECMA-119, 6.8) and the L and M
862  * Path Tables (ECMA-119, 6.9).
863  */
864 static
866 {
867  int ret, isofs_ca_changed = 0;
868  Ecma119Image *t;
869  Ecma119Node *root;
870  char *value = NULL;
871  size_t value_length;
872 
873  t = writer->target;
874 
875  /* first of all, we write the directory structure */
876  if (t->eff_partition_offset > 0) {
877  root = t->partition_root;
878 
879  if ((t->opts->md5_file_checksums & 1) ||
881  /* Take into respect the address offset in "isofs.ca" */
882  ret = iso_node_lookup_attr((IsoNode *) t->image->root, "isofs.ca",
883  &value_length, &value, 0);
884  if (value != NULL)
885  free(value);
886  if (ret == 1 && value_length == 20) {
887  /* "isofs.ca" does really exist and has the expected length */
888  ret = iso_root_set_isofsca((IsoNode *) t->image->root,
891  t->checksum_idx_counter + 2, 16, "MD5", 0);
892  if (ret < 0)
893  return ret;
894  isofs_ca_changed = 1;
895  }
896  }
897  } else {
898  root = t->root;
899  }
900  ret = write_dirs(t, root, root);
901  if (ret < 0) {
902  return ret;
903  }
904 
905  /* and write the path tables */
906  ret = write_path_tables(t);
907  if (ret < 0)
908  return ret;
909  if (t->opts->md5_session_checksum) {
910  /* Write tree checksum tag */
911  if (t->eff_partition_offset > 0) {
912  /* >>> TWINTREE: >>> For now, tags are only for the
913  image start and not for the partition */;
914  } else {
915  ret = iso_md5_write_tag(t, 3);
916  }
917  }
918  if (isofs_ca_changed) {
919  /* Restore old addresses offset in "isofs.ca" of root node */
920  ret = iso_root_set_isofsca((IsoNode *) t->image->root,
923  t->checksum_idx_counter + 2, 16, "MD5", 0);
924  if (ret < 0)
925  return ret;
926  }
927  return ret;
928 }
929 
930 /**
931  * Write directory structure and Path Tables of the ECMA-119 tree.
932  * This happens eventually a second time for the duplicates which use
933  * addresses with partition offset.
934  */
935 static
937 {
938  int ret;
939  Ecma119Image *t;
940  uint32_t curblock;
941  char *msg = NULL;
942 
943  if (writer == NULL)
944  {ret = ISO_ASSERT_FAILURE; goto ex;}
945 
946  t = writer->target;
947 
948  ret = ecma119_writer_write_dirs(writer);
949  if (ret < 0)
950  goto ex;
951 
952  if (t->opts->partition_offset > 0) {
954  ret = ecma119_writer_write_dirs(writer);
955  t->eff_partition_offset = 0;
956  if (ret < 0)
957  goto ex;
958  }
959 
960  curblock = (t->bytes_written / 2048) + t->opts->ms_block;
961  if (curblock != t->tree_end_block) {
962  LIBISO_ALLOC_MEM(msg, char, 100);
963  sprintf(msg,
964  "Calculated and written ECMA-119 tree end differ: %lu <> %lu",
965  (unsigned long) t->tree_end_block,
966  (unsigned long) curblock);
967  iso_msgs_submit(0, msg, 0, "WARNING", 0);
968 
969  t->tree_end_block = 1;/* Mark for harsher reaction at end of writing */
970  }
971  ret = ISO_SUCCESS;
972 ex:;
973  LIBISO_FREE_MEM(msg);
974  return ret;
975 }
976 
977 static
979 {
980  /* nothing to do */
981  return ISO_SUCCESS;
982 }
983 
985 {
986  int ret;
987  IsoImageWriter *writer;
988 
989  writer = malloc(sizeof(IsoImageWriter));
990  if (writer == NULL) {
991  return ISO_OUT_OF_MEM;
992  }
993 
998  writer->data = NULL;
999  writer->target = target;
1000 
1001  /* add this writer to image */
1002  target->writers[target->nwriters++] = writer;
1003 
1004  iso_msg_debug(target->image->id, "Creating low level ECMA-119 tree...");
1005  ret = ecma119_tree_create(target);
1006  if (ret < 0) {
1007  return ret;
1008  }
1009 
1010  if (target->image->sparc_core_node != NULL) {
1011  /* Obtain a duplicate of the IsoFile's Ecma119Node->file */
1012  ret = iso_file_src_create(target, target->image->sparc_core_node,
1013  &target->sparc_core_src);
1014  if (ret < 0)
1015  return ret;
1016  }
1017 
1018  if(target->opts->partition_offset > 0) {
1019  /* Create second tree */
1020  target->eff_partition_offset = target->opts->partition_offset;
1021  ret = ecma119_tree_create(target);
1022  target->eff_partition_offset = 0;
1023  if (ret < 0)
1024  return ret;
1025  }
1026 
1027  /* we need the volume descriptor */
1028  target->curblock++;
1029  return ISO_SUCCESS;
1030 }
1031 
1032 /** compute how many padding bytes are needed */
1033 static
1035 {
1036  Ecma119Image *target;
1037  uint32_t min_size;
1038 
1039  if (writer == NULL) {
1040  return ISO_ASSERT_FAILURE;
1041  }
1042  target = writer->target;
1043  min_size = 32 + target->opts->partition_offset;
1044  if (target->curblock < min_size) {
1045  target->mspad_blocks = min_size - target->curblock;
1046  target->curblock = min_size;
1047  }
1048  return ISO_SUCCESS;
1049 }
1050 
1051 static
1053 {
1054  /* nothing to do */
1055  return ISO_SUCCESS;
1056 }
1057 
1058 static
1060 {
1061  int ret;
1062  Ecma119Image *t;
1063  uint8_t *pad = NULL;
1064  size_t i;
1065 
1066  if (writer == NULL) {
1067  {ret = ISO_ASSERT_FAILURE; goto ex;}
1068  }
1069  t = writer->target;
1070 
1071  if (t->mspad_blocks == 0) {
1072  {ret = ISO_SUCCESS; goto ex;}
1073  }
1074 
1075  LIBISO_ALLOC_MEM(pad, uint8_t, BLOCK_SIZE);
1076  for (i = 0; i < t->mspad_blocks; ++i) {
1077  ret = iso_write(t, pad, BLOCK_SIZE);
1078  if (ret < 0) {
1079  goto ex;
1080  }
1081  }
1082 
1083  ret = ISO_SUCCESS;
1084 ex:;
1085  LIBISO_FREE_MEM(pad);
1086  return ret;
1087 }
1088 
1089 static
1091 {
1092  /* nothing to do */
1093  return ISO_SUCCESS;
1094 }
1095 
1096 static
1098 {
1099  IsoImageWriter *writer;
1100 
1101  writer = malloc(sizeof(IsoImageWriter));
1102  if (writer == NULL) {
1103  return ISO_OUT_OF_MEM;
1104  }
1105 
1110  writer->data = NULL;
1111  writer->target = target;
1112 
1113  /* add this writer to image */
1114  target->writers[target->nwriters++] = writer;
1115  return ISO_SUCCESS;
1116 }
1117 
1118 
1119 /** ----- Zero padding writer ----- */
1120 
1122  uint32_t num_blocks;
1123 };
1124 
1125 static
1127 {
1128  Ecma119Image *target;
1129  struct iso_zero_writer_data_struct *data;
1130 
1131  if (writer == NULL)
1132  return ISO_ASSERT_FAILURE;
1133  target = writer->target;
1134  data = (struct iso_zero_writer_data_struct *) writer->data;
1135  target->curblock += data->num_blocks;
1136  return ISO_SUCCESS;
1137 }
1138 
1139 static
1141 {
1142  /* nothing to do */
1143  return ISO_SUCCESS;
1144 }
1145 
1146 static
1148 {
1149  int ret;
1150  Ecma119Image *t;
1151  struct iso_zero_writer_data_struct *data;
1152  uint8_t *pad = NULL;
1153  size_t i;
1154 
1155  if (writer == NULL)
1156  {ret = ISO_ASSERT_FAILURE; goto ex;}
1157  t = writer->target;
1158  data = (struct iso_zero_writer_data_struct *) writer->data;
1159 
1160  if (data->num_blocks == 0)
1161  {ret = ISO_SUCCESS; goto ex;}
1162  LIBISO_ALLOC_MEM(pad, uint8_t, BLOCK_SIZE);
1163  for (i = 0; i < data->num_blocks; ++i) {
1164  ret = iso_write(t, pad, BLOCK_SIZE);
1165  if (ret < 0)
1166  goto ex;
1167  }
1168  ret = ISO_SUCCESS;
1169 ex:;
1170  LIBISO_FREE_MEM(pad);
1171  return ret;
1172 }
1173 
1174 static
1176 {
1177  if (writer == NULL)
1178  return ISO_SUCCESS;
1179  if (writer->data == NULL)
1180  return ISO_SUCCESS;
1181  free(writer->data);
1182  writer->data = NULL;
1183  return ISO_SUCCESS;
1184 }
1185 
1186 static
1188 {
1189  int ret;
1190  Ecma119Image *target;
1191 
1192 #ifdef Libisofs_part_align_writeR
1193 
1194  target = writer->target;
1195 
1196 #else
1197 
1198  struct iso_zero_writer_data_struct *data;
1199  char msg[80];
1200 
1201  target = writer->target;
1202  ret = iso_align_isohybrid(target, 0);
1203  if (ret < 0)
1204  return ret;
1205  data = (struct iso_zero_writer_data_struct *) writer->data;
1206  if (data->num_blocks != target->opts->tail_blocks) {
1207  sprintf(msg, "Aligned image size to cylinder size by %d blocks",
1208  target->opts->tail_blocks - data->num_blocks);
1209  iso_msgs_submit(0, msg, 0, "NOTE", 0);
1210  data->num_blocks = target->opts->tail_blocks;
1211  }
1212 
1213 #endif /* ! Libisofs_part_align_writeR */
1214 
1215  if (target->opts->tail_blocks <= 0)
1216  return ISO_SUCCESS;
1217  ret = zero_writer_compute_data_blocks(writer);
1218  return ret;
1219 }
1220 
1221 static
1223 {
1224  int ret;
1225  Ecma119Image *target;
1226  struct iso_zero_writer_data_struct *data;
1227  char msg[80];
1228 
1229  target = writer->target;
1230 
1231  /* Default setting in case no alignment is needed */
1232  target->alignment_end_block = target->curblock;
1233 
1234  ret = iso_align_isohybrid(target, 0);
1235  if (ret < 0)
1236  return ret;
1237  data = (struct iso_zero_writer_data_struct *) writer->data;
1238  if (target->part_align_blocks != 0) {
1239  sprintf(msg, "Aligned image size to cylinder size by %d blocks",
1240  target->part_align_blocks);
1241  iso_msgs_submit(0, msg, 0, "NOTE", 0);
1242  data->num_blocks = target->part_align_blocks;
1243  }
1244  if (target->part_align_blocks <= 0)
1245  return ISO_SUCCESS;
1246  ret = zero_writer_compute_data_blocks(writer);
1247  target->alignment_end_block = target->curblock;
1248  return ret;
1249 }
1250 
1251 /*
1252  @param flag bit0-3= compute_data_blocks mode:
1253  0= zero_writer_compute_data_blocks
1254  1= tail_writer_compute_data_blocks
1255  2= part_align_writer_compute_data_blocks
1256 */
1257 static
1258 int zero_writer_create(Ecma119Image *target, uint32_t num_blocks, int flag)
1259 {
1260  IsoImageWriter *writer;
1261  struct iso_zero_writer_data_struct *data;
1262  int mode;
1263 
1264  writer = malloc(sizeof(IsoImageWriter));
1265  if (writer == NULL) {
1266  return ISO_OUT_OF_MEM;
1267  }
1268  data = calloc(1, sizeof(struct iso_zero_writer_data_struct));
1269  if (data == NULL) {
1270  free(writer);
1271  return ISO_OUT_OF_MEM;
1272  }
1273  data->num_blocks = num_blocks;
1274 
1275  mode = (flag & 15);
1276  if (mode == 1) {
1278  } else if (mode == 2) {
1280  } else {
1282  }
1285  writer->free_data = zero_writer_free_data;
1286  writer->data = data;
1287  writer->target = target;
1288 
1289  /* add this writer to image */
1290  target->writers[target->nwriters++] = writer;
1291  return ISO_SUCCESS;
1292 }
1293 
1294 
1295 /* @param flag bit0= restore preserved cx (else dispose them)
1296 */
1297 static
1298 int process_preserved_cx(IsoDir *dir, int flag)
1299 {
1300  int ret, i;
1301  unsigned int cx_value;
1302  void *xipt;
1303  IsoNode *pos;
1304 
1305  pos = dir->children;
1306  for (pos = dir->children; pos != NULL; pos = pos->next) {
1307  if (pos->type == LIBISO_FILE) {
1308  if (flag & 1) {
1309  /* Restore preserved cx state of nodes */
1311  &xipt);
1312  if (ret == 1) {
1313  /* xipt is an int disguised as void pointer */
1314  cx_value = 0;
1315  for (i = 0; i < 4; i++)
1316  cx_value =
1317  (cx_value << 8) | ((unsigned char *) &xipt)[i];
1318  ret = iso_file_set_isofscx((IsoFile *) pos, cx_value, 0);
1319  if (ret < 0)
1320  return ret;
1321  } else if (ret == 0) {
1322  /* Node had no cx before the write run. Delete cx. */
1323  iso_file_set_isofscx((IsoFile *) pos, 0, 1);
1324  }
1325  }
1327  } else if (pos->type == LIBISO_DIR) {
1328  ret = process_preserved_cx((IsoDir *) pos, flag);
1329  if (ret != 0)
1330  return ret;
1331  }
1332  }
1333  return 0;
1334 }
1335 
1336 static
1338 {
1339  /* Transplant checksum buffer from Ecma119Image to IsoImage */
1341  target->checksum_range_start,
1342  target->checksum_array_pos,
1343  target->checksum_idx_counter + 2, 0);
1344  target->checksum_buffer = NULL;
1345  target->checksum_idx_counter = 0;
1346 
1347  /* Delete recorded cx xinfo */
1348  process_preserved_cx(target->image->root, 0);
1349 
1350  return 1;
1351 }
1352 
1353 static
1355 {
1356  int ret;
1357  uint8_t *buf = NULL;
1358  struct ecma119_vol_desc_terminator *vol;
1359 
1360  LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE);
1361 
1362  vol = (struct ecma119_vol_desc_terminator *) buf;
1363 
1364  vol->vol_desc_type[0] = 255;
1365  memcpy(vol->std_identifier, "CD001", 5);
1366  vol->vol_desc_version[0] = 1;
1367 
1368  ret = iso_write(target, buf, BLOCK_SIZE);
1369 ex:
1370  LIBISO_FREE_MEM(buf);
1371  return ret;
1372 }
1373 
1374 
1375 /* @param flag bit0= initialize system area by target->opts_overwrite
1376  bit1= fifo is not yet draining. Inquire write_count from fifo.
1377  bit2= target->opts->ms_block is not counted in
1378  target->total_size
1379 */
1380 static
1381 int write_head_part1(Ecma119Image *target, int *write_count, int flag)
1382 {
1383  int res, i, ret;
1384  uint8_t *sa, *sa_local = NULL;
1385  IsoImageWriter *writer;
1386  size_t buffer_size = 0, buffer_free = 0, buffer_start_free = 0;
1387 
1388  if (target->sys_area_already_written) {
1389  LIBISO_ALLOC_MEM(sa_local, uint8_t, 16 * BLOCK_SIZE);
1390  sa = sa_local;
1391  } else {
1392  sa = target->sys_area_as_written;
1393  target->sys_area_already_written = 1;
1394  }
1395  iso_ring_buffer_get_buf_status(target->buffer, &buffer_size,
1396  &buffer_start_free);
1397  *write_count = 0;
1398  /* Write System Area (ECMA-119, 6.2.1) */
1399  if ((flag & 1) && target->opts_overwrite != NULL)
1400  memcpy(sa, target->opts_overwrite, 16 * BLOCK_SIZE);
1401  res = iso_write_system_area(target, sa, (flag & 4) >> 2);
1402  if (res < 0)
1403  goto write_error;
1404  res = iso_write(target, sa, 16 * BLOCK_SIZE);
1405  if (res < 0)
1406  goto write_error;
1407  *write_count = 16;
1408 
1409  /* write volume descriptors, one per writer */
1410  iso_msg_debug(target->image->id, "Write volume descriptors");
1411  for (i = 0; i < (int) target->nwriters; ++i) {
1412  writer = target->writers[i];
1413  res = writer->write_vol_desc(writer);
1414  if (res < 0)
1415  goto write_error;
1416  }
1417 
1418  /* write Volume Descriptor Set Terminator (ECMA-119, 8.3) */
1419  res = write_vol_desc_terminator(target);
1420  if (res < 0)
1421  goto write_error;
1422 
1423  if(flag & 2) {
1424  iso_ring_buffer_get_buf_status(target->buffer, &buffer_size,
1425  &buffer_free);
1426  *write_count = ( buffer_start_free - buffer_free ) / BLOCK_SIZE;
1427  } else {
1428  *write_count = target->bytes_written / BLOCK_SIZE;
1429  }
1430 
1431  ret = ISO_SUCCESS;
1432  goto ex;
1433 
1434 write_error:;
1435  ret = res;
1436  goto ex;
1437 
1438 ex:
1439  LIBISO_FREE_MEM(sa_local);
1440  return ret;
1441 }
1442 
1443 static
1444 int write_head_part2(Ecma119Image *target, int *write_count, int flag)
1445 {
1446  int ret, i;
1447  uint8_t *buf = NULL;
1448  IsoImageWriter *writer;
1449 
1450  if (target->opts->partition_offset <= 0)
1451  {ret = ISO_SUCCESS; goto ex;}
1452 
1453  /* Write multi-session padding up to target->opts->partition_offset + 16 */
1454  LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE);
1455  for(; *write_count < (int) target->opts->partition_offset + 16;
1456  (*write_count)++) {
1457  ret = iso_write(target, buf, BLOCK_SIZE);
1458  if (ret < 0)
1459  goto ex;
1460  }
1461 
1462  /* Write volume descriptors subtracting
1463  target->partiton_offset from any LBA pointer.
1464  */
1465  target->eff_partition_offset = target->opts->partition_offset;
1466  target->pvd_size_is_total_size = 0;
1467  for (i = 0; i < (int) target->nwriters; ++i) {
1468  writer = target->writers[i];
1469  /* Not all writers have an entry in the partition volume descriptor set.
1470  It must be guaranteed that they write exactly one block.
1471  */
1472 
1473  /* >>> TWINTREE: Enhance ISO1999 writer and add it here */
1474 
1477  continue;
1478  ret = writer->write_vol_desc(writer);
1479  if (ret < 0)
1480  goto ex;
1481  (*write_count)++;
1482  }
1483  ret = write_vol_desc_terminator(target);
1484  if (ret < 0)
1485  goto ex;
1486  (*write_count)++;
1487  target->eff_partition_offset = 0;
1488 
1489  /* >>> TWINTREE: Postponed for now:
1490  Write second superblock checksum tag */;
1491 
1492  ret = ISO_SUCCESS;
1493 ex:;
1494  if (buf != NULL)
1495  free(buf);
1496  return ret;
1497 }
1498 
1499 static
1500 int write_head_part(Ecma119Image *target, int flag)
1501 {
1502  int res, write_count = 0;
1503 
1504  /* System area and volume descriptors */
1505  res = write_head_part1(target, &write_count, 4);
1506  if (res < 0)
1507  return res;
1508 
1509  /* Write superblock checksum tag */
1510  if (target->opts->md5_session_checksum && target->checksum_ctx != NULL) {
1511  res = iso_md5_write_tag(target, 2);
1512  if (res < 0)
1513  return res;
1514  write_count++;
1515  }
1516 
1517  /* Second set of system area and volume descriptors for partition_offset */
1518  res = write_head_part2(target, &write_count, 0);
1519  if (res < 0)
1520  return res;
1521  return ISO_SUCCESS;
1522 }
1523 
1524 
1525 /* Eventually end Jigdo Template Extraction */
1526 static int finish_libjte(Ecma119Image *target)
1527 {
1528 #ifdef Libisofs_with_libjtE
1529 
1530  int ret;
1531 
1532  if (target->opts->libjte_handle != NULL) {
1533  ret = libjte_write_footer(target->opts->libjte_handle);
1534  if (ret <= 0) {
1535  iso_libjte_forward_msgs(target->opts->libjte_handle,
1536  target->image->id, ISO_LIBJTE_END_FAILED, 0);
1537  return ISO_LIBJTE_END_FAILED;
1538  }
1539  }
1540 
1541 #endif /* Libisofs_with_libjtE */
1542 
1543  return 1;
1544 }
1545 
1546 
1547 
1549  int z_type; /* 0= $zero_start"-"$zero_end ,
1550  1= "zero_mbrpt" , 2= "zero_gpt" , 3= "zero_apm"
1551  */
1552  off_t zero_start;
1553  off_t zero_end;
1554 };
1555 
1557 
1558  /* Setup */
1559 
1561 
1562  char *path;
1563 
1564  int flags; /* bit0= imported_iso, else local_fs
1565  */
1566 
1567  off_t start_byte;
1568  off_t end_byte;
1569 
1572 
1573  char *source_pt; /* This is a parasite pointer of path. Do not free */
1574 
1575  /* State information */
1576 
1579  off_t cur_block;
1580  int fd;
1584  off_t read_count;
1585  int eof;
1586 
1588 
1589  uint32_t apm_block_size;
1590 
1591 };
1592 
1593 static
1594 int iso_ivr_next_comp(char *read_pt, char **next_pt, int flag)
1595 {
1596  *next_pt = NULL;
1597  if (read_pt == NULL)
1598  return 0;
1599  *next_pt = strchr(read_pt, ':');
1600  if (*next_pt != NULL)
1601  (*next_pt)++;
1602  return 1;
1603 }
1604 
1605 /* @param flag bit1= end number requested, forward to iso_scanf_io_size()
1606 */
1607 static
1608 int iso_ivr_read_number(char *start_pt, char *end_pt, off_t *result, int flag)
1609 {
1610  char txt[20];
1611  off_t num;
1612 
1613  if (end_pt - start_pt <= 0 || end_pt - start_pt > 16) {
1615  "Number text too short or too long in interval reader description string");
1616  return ISO_MALFORMED_READ_INTVL;
1617  }
1618  if (end_pt - start_pt > 0)
1619  strncpy(txt, start_pt, end_pt - start_pt);
1620  txt[end_pt - start_pt] = 0;
1621 
1622  num = iso_scanf_io_size(start_pt, 1 | (flag & 2));
1623  if (num < 0.0 || num > 281474976710655.0) {
1625  "Negative or overly large number in interval reader description string");
1626  return ISO_MALFORMED_READ_INTVL;
1627  }
1628  *result = num;
1629  return 1;
1630 }
1631 
1632 static
1633 int iso_ivr_parse_interval(char *start_pt, char *end_pt, off_t *start_byte,
1634  off_t *end_byte, int flag)
1635 {
1636  int ret;
1637  char *m_pt;
1638 
1639  m_pt = strchr(start_pt, '-');
1640  if (m_pt == NULL) {
1642  "Malformed byte interval in interval reader description string");
1643  return ISO_MALFORMED_READ_INTVL;
1644  }
1645  ret = iso_ivr_read_number(start_pt, m_pt, start_byte, 0);
1646  if (ret < 0)
1647  return ret;
1648  ret = iso_ivr_read_number(m_pt + 1, end_pt - 1, end_byte, 2);
1649  if (ret < 0)
1650  return ret;
1651  return ISO_SUCCESS;
1652 }
1653 
1654 static
1656  char *pathpt, char *end_pt, int flag)
1657 {
1658  int ret, num_zs = 1, idx, i;
1659  char *rpt, *cpt;
1660 
1661  ivr->num_zeroizers = 0;
1662  if (pathpt[0] == 0 || pathpt == end_pt)
1663  return ISO_SUCCESS;
1664  for(cpt = pathpt - 1; cpt != NULL && cpt < end_pt; num_zs++)
1665  cpt = strchr(cpt + 1, ',');
1666  LIBISO_ALLOC_MEM(ivr->zeroizers, struct iso_interval_zeroizer, num_zs);
1667  for (i = 0; i < num_zs; i++)
1668  ivr->zeroizers[i].zero_end = -1;
1669  idx = 0;
1670  for (rpt = pathpt; rpt != NULL && rpt < end_pt; idx++) {
1671  cpt = strchr(rpt, ',');
1672  if (cpt == NULL || cpt > end_pt)
1673  cpt = end_pt;
1674 
1675  if (cpt == rpt) {
1676  continue;
1677  } else if (strncmp(rpt, "zero_mbrpt", cpt - rpt) == 0) {
1678  ivr->zeroizers[idx].z_type = 1;
1679  } else if (strncmp(rpt, "zero_gpt", cpt - rpt) == 0) {
1680  ivr->zeroizers[idx].z_type = 2;
1681  } else if (strncmp(rpt, "zero_apm", cpt - rpt) == 0) {
1682  ivr->zeroizers[idx].z_type = 3;
1683  } else {
1684  ivr->zeroizers[idx].z_type = 0;
1685  ret = iso_ivr_parse_interval(rpt, cpt,
1686  &(ivr->zeroizers[idx].zero_start),
1687  &(ivr->zeroizers[idx].zero_end), 0);
1688  if (ret < 0)
1689  goto ex;
1690  }
1691  rpt = cpt + 1;
1692  ivr->num_zeroizers++;
1693  }
1694  ret = ISO_SUCCESS;
1695 ex:;
1696  return ret;
1697 }
1698 
1699 static
1700 int iso_ivr_parse(struct iso_interval_reader *ivr, char *path, int flag)
1701 {
1702  int ret;
1703  char *flags_pt, *interval_pt, *zeroize_pt;
1704 
1705  flags_pt = path;
1706  iso_ivr_next_comp(flags_pt, &interval_pt, 0);
1707  iso_ivr_next_comp(interval_pt, &zeroize_pt, 0);
1708  iso_ivr_next_comp(zeroize_pt, &(ivr->source_pt), 0);
1709  if (ivr->source_pt == NULL) {
1711  "Not enough components in interval reader description string");
1712  return ISO_MALFORMED_READ_INTVL;
1713  }
1714 
1715  ivr->flags = 0;
1716  if (strncmp(flags_pt, "imported_iso", 12) == 0) {
1717  ivr->flags |= 1;
1718  } else if (strncmp(flags_pt, "local_fs", 8) == 0) {
1719  ;
1720  } else {
1722  "Unknown flag name in first component of interval reader description string");
1723  return ISO_MALFORMED_READ_INTVL;
1724  }
1725  ret = iso_ivr_parse_interval(interval_pt, zeroize_pt, &(ivr->start_byte),
1726  &(ivr->end_byte), 0);
1727  if (ret < 0)
1728  goto ex;
1729  ret = iso_ivr_parse_zeroizers(ivr, zeroize_pt, ivr->source_pt - 1, 0);
1730  if (ret < 0)
1731  goto ex;
1732 
1733  ret = ISO_SUCCESS;
1734 ex:;
1735  return ret;
1736 }
1737 
1739 {
1740  struct iso_interval_reader *o;
1741 
1742  if (*ivr == NULL)
1743  return 0;
1744  o = *ivr;
1745 
1746  LIBISO_FREE_MEM(o->path);
1748 
1749  if (o->fd != -1)
1750  close(o->fd);
1751  if (o->src_is_open)
1752  (*o->image->import_src->close)(o->image->import_src);
1753 
1754  LIBISO_FREE_MEM(*ivr);
1755  return ISO_SUCCESS;
1756 }
1757 
1758 /* @param flag bit0= tolerate lack of import_src
1759 */
1761  struct iso_interval_reader **ivr,
1762  off_t *byte_count, int flag)
1763 {
1764  int ret, no_img = 0;
1765  struct iso_interval_reader *o = NULL;
1766 
1767  *ivr = NULL;
1768  *byte_count = 0;
1769  LIBISO_ALLOC_MEM(o, struct iso_interval_reader, 1);
1770  o->image = img;
1771  o->path = NULL;
1772  o->zeroizers = NULL;
1773  o->num_zeroizers = 0;
1774  o->source_pt = NULL;
1775  o->initialized = 0;
1776  o->is_block_aligned = 0;
1777  o->fd = -1;
1778  o->pending_read_pt = NULL;
1779  o->pending_read_bytes = 0;
1780  o->eof = 0;
1781  o->read_count = 0;
1782  o->src_is_open = 0;
1783 
1784  o->apm_block_size = 0;
1785 
1786  LIBISO_ALLOC_MEM(o->path, char, strlen(path) + 1);
1787  strcpy(o->path, path);
1788 
1789  ret = iso_ivr_parse(o, path, 0);
1790  if (ret < 0)
1791  goto ex;
1792 
1793  if (o->image == NULL)
1794  no_img = 1;
1795  else if (o->image->import_src == NULL)
1796  no_img = 1;
1797  if ((o->flags & 1) && no_img) {
1799  "Interval reader lacks of data source object of imported ISO");
1800  if (!(flag & 1)) {
1801  ret = ISO_BAD_PARTITION_FILE;
1802  goto ex;
1803  }
1804  o->eof = 1;
1805  }
1806  *byte_count = o->end_byte - o->start_byte + 1;
1807  *ivr = o;
1808  ret = ISO_SUCCESS;
1809 ex:;
1810  if (ret < 0)
1812  return ret;
1813 }
1814 
1815 static
1816 int iso_ivr_zeroize(struct iso_interval_reader *ivr, uint8_t *buf,
1817  int buf_fill, int flag)
1818 {
1819  int i;
1820  off_t low, high, part_start, entry_count, apm_offset = -1, map_entries;
1821  uint8_t *apm_buf;
1822  struct iso_interval_zeroizer *zr;
1823 
1824  for (i = 0; i < ivr->num_zeroizers; i++) {
1825  zr = ivr->zeroizers + i;
1826  if (zr->z_type == 1) { /* zero_mbrpt */
1827  if (ivr->read_count > 0 || buf_fill < 512)
1828  continue;
1829  if (buf[510] != 0x55 || buf[511] != 0xaa)
1830  continue;
1831  memset(buf + 446, 0, 64);
1832 
1833  } else if (zr->z_type == 2) { /* zero_gpt */
1834  if (zr->zero_start <= zr->zero_end)
1835  goto process_interval;
1836 
1837  if (ivr->read_count > 0 || buf_fill < 512 + 92)
1838  continue;
1839  if (strncmp((char *) buf + 512, "EFI PART", 8) != 0 ||
1840  buf[520] != 0 || buf[521] != 0 || buf[522] != 1 ||
1841  buf[523] != 0)
1842  continue;
1843  /* head_size , curr_lba , entry_size */
1844  if (iso_read_lsb(buf + 524, 4) != 92 ||
1845  iso_read_lsb(buf + 536, 4) != 1 ||
1846  iso_read_lsb(buf + 596, 4) != 128)
1847  continue;
1848  part_start = iso_read_lsb(buf + 584, 4);
1849  entry_count = iso_read_lsb(buf + 592, 4);
1850  if (part_start < 2 || part_start + (entry_count + 3) / 4 > 64)
1851  continue;
1852  zr->zero_start = part_start * 512;
1853  zr->zero_end = (part_start + (entry_count + 3) / 4) * 512 - 1;
1854  memset(buf + 512, 0, 92);
1855 
1856  } else if (zr->z_type == 3) { /* zero_apm */
1857  if (zr->zero_start <= zr->zero_end)
1858  goto process_interval;
1859 
1860  if (ivr->read_count == 0) {
1861  if (buf_fill < 512)
1862  continue;
1863  if (buf[0] != 'E' || buf[1] != 'R')
1864  continue;
1865  ivr->apm_block_size = iso_read_msb(buf + 2, 2);
1866  if ((ivr->apm_block_size != 512 &&
1867  ivr->apm_block_size != 1024 &&
1868  ivr->apm_block_size != 2048) ||
1869  ((uint32_t) buf_fill) < ivr->apm_block_size) {
1870  ivr->apm_block_size = 0;
1871  continue;
1872  }
1873  if (ivr->read_count + buf_fill >= 2 * ivr->apm_block_size)
1874  apm_offset = ivr->apm_block_size;
1875  } else if (ivr->read_count == 2048 &&
1876  ivr->apm_block_size == 2048 && buf_fill == 2048) {
1877  apm_offset = 0;
1878  }
1879  if (apm_offset < 0)
1880  continue;
1881 
1882  /* Check for first APM entry */
1883  apm_buf = buf + apm_offset;
1884  if(apm_buf[0] != 'P' || apm_buf[1] != 'M')
1885  continue;
1886  if (iso_read_msb(apm_buf + 8, 4) != 1)
1887  continue;
1888  map_entries = iso_read_msb(apm_buf + 4, 4);
1889  if ((1 + map_entries) * ivr->apm_block_size > 16 * 2048)
1890  continue;
1891  zr->zero_start = ivr->apm_block_size;
1892  zr->zero_end = (1 + map_entries) * ivr->apm_block_size;
1893  }
1894 process_interval:;
1895  /* If an interval is defined by now: zeroize its intersection with buf
1896  */
1897  if (zr->zero_start <= zr->zero_end) {
1898  low = ivr->read_count >= zr->zero_start ?
1899  ivr->read_count : zr->zero_start;
1900  high = ivr->read_count + buf_fill - 1 <= zr->zero_end ?
1901  ivr->read_count + buf_fill - 1 : zr->zero_end;
1902  if (low <= high)
1903  memset(buf + low - ivr->read_count, 0, high - low + 1);
1904  }
1905  }
1906 
1907  return ISO_SUCCESS;
1908 }
1909 
1910 int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf,
1911  int *buf_fill, int flag)
1912 {
1913  int ret, read_done, to_copy, initializing = 0;
1914  IsoDataSource *src;
1915  uint8_t *read_buf;
1916  off_t to_read;
1917 
1918  *buf_fill = 0;
1919  src = ivr->image->import_src;
1920 
1921  if (ivr->eof) {
1922 eof:;
1923  memset(buf, 0, BLOCK_SIZE);
1924  return 0;
1925  }
1926 
1927  if (ivr->initialized) {
1928  ivr->cur_block++;
1929  } else {
1930  initializing = 1;
1931  ivr->cur_block = ivr->start_byte / BLOCK_SIZE;
1932  ivr->is_block_aligned = !(ivr->start_byte % BLOCK_SIZE);
1933  if (ivr->flags & 1) {
1934  if (src == NULL)
1935  goto eof;
1936  ret = (*src->open)(src);
1937  if (ret < 0) {
1938  ivr->eof = 1;
1939  return ret;
1940  }
1941  ivr->src_is_open = 1;
1942  } else {
1943  ivr->fd = open(ivr->source_pt, O_RDONLY);
1944  if (ivr->fd == -1) {
1946  "Cannot open local file for interval reading");
1947  ivr->eof = 1;
1948  return ISO_BAD_PARTITION_FILE;
1949  }
1950  if (ivr->cur_block != 0) {
1951  if (lseek(ivr->fd, ivr->cur_block * BLOCK_SIZE, SEEK_SET) ==
1952  -1) {
1954  "Cannot address interval start in local file");
1955  ivr->eof = 1;
1956  goto eof;
1957  }
1958  }
1959  }
1960  ivr->initialized = 1;
1961  }
1962  if (ivr->is_block_aligned) {
1963  read_buf = buf;
1964  } else {
1965 process_pending:;
1966  read_buf = ivr->read_buf;
1967  /* Copy pending bytes from previous read */
1968  if (ivr->pending_read_bytes > 0) {
1969  memcpy(buf, ivr->pending_read_pt, ivr->pending_read_bytes);
1970  *buf_fill = ivr->pending_read_bytes;
1971  ivr->pending_read_bytes = 0;
1972  }
1973  }
1974 
1975  /* Read next block */
1976  read_done = 0;
1977  if (ivr->cur_block * BLOCK_SIZE <= ivr->end_byte) {
1978  if (ivr->flags & 1) {
1979  ret = (*src->read_block)(src, (uint32_t) ivr->cur_block, read_buf);
1980  if (ret < 0) {
1981  if (iso_error_get_severity(ret) > 0x68000000) /* > FAILURE */
1982  return ret;
1984  "Premature EOF while interval reading from imported ISO");
1985  ivr->eof = 1;
1986  }
1987  read_done = BLOCK_SIZE;
1988  } else {
1989  read_done = 0;
1990  to_read = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count;
1991  if (to_read > BLOCK_SIZE)
1992  to_read = BLOCK_SIZE;
1993  while (read_done < to_read) {
1994  ret = read(ivr->fd, read_buf, to_read - read_done);
1995  if (ret == -1) {
1997  "Read error while interval reading from local file");
1998  ivr->eof = 1;
1999  break;
2000  } else if (ret == 0) {
2002  "Premature EOF while interval reading from local file");
2003  ivr->eof = 1;
2004  break;
2005  } else
2006  read_done += ret;
2007  }
2008  }
2009  }
2010  if (ivr->is_block_aligned) {
2011  *buf_fill = read_done;
2012  } else if (initializing) {
2013  ivr->pending_read_pt = ivr->read_buf +
2014  (ivr->start_byte - ivr->cur_block * BLOCK_SIZE);
2015  ivr->pending_read_bytes = (((off_t) ivr->cur_block) + 1) * BLOCK_SIZE -
2016  ivr->start_byte;
2017  initializing = 0;
2018  goto process_pending;
2019 
2020  } else if (read_done > 0) {
2021  /* Copy bytes from new read */
2022  to_copy = read_done > BLOCK_SIZE - *buf_fill ?
2023  BLOCK_SIZE - *buf_fill : read_done;
2024  memcpy(buf + *buf_fill, ivr->read_buf, to_copy);
2025  *buf_fill += to_copy;
2026  ivr->pending_read_pt = ivr->read_buf + to_copy;
2027  ivr->pending_read_bytes = read_done - to_copy;
2028  }
2029  if (ivr->start_byte + ivr->read_count + *buf_fill - 1 > ivr->end_byte) {
2030  *buf_fill = ivr->end_byte - ivr->start_byte + 1 - ivr->read_count;
2031  ivr->eof = 1;
2032  }
2033 
2034  if (*buf_fill < BLOCK_SIZE)
2035  memset(buf + *buf_fill, 0, BLOCK_SIZE - *buf_fill);
2036 
2037  ret = iso_ivr_zeroize(ivr, buf, *buf_fill, 0);
2038  if (ret < 0)
2039  return ret;
2040 
2041  ivr->read_count += *buf_fill;
2042 
2043  return ISO_SUCCESS;
2044 }
2045 
2046 
2047 /* Tells whether ivr is a reader from imported_iso in a multi-session
2048  add-on situation, and thus to be kept in place.
2049 */
2051  struct iso_interval_reader *ivr,
2052  int flag)
2053 {
2054  /* Source must be "imported_iso" */
2055  if (!(ivr->flags & 1))
2056  return 0;
2057 
2058  /* It must not be a new ISO */
2059  if (!target->opts->appendable)
2060  return 0;
2061 
2062  /* --- From here on return either 1 or <0 --- */
2063 
2064  /* multi-session write offset must be larger than interval end */
2065  if (target->opts->ms_block <= ivr->end_byte / BLOCK_SIZE)
2066  return ISO_MULTI_OVER_IMPORTED;
2067 
2068  return 1;
2069 }
2070 
2071 
2073  off_t *start_byte, off_t *byte_count,
2074  int flag)
2075 {
2076  struct iso_interval_reader *ivr;
2077  int keep, ret;
2078 
2079  ret = iso_interval_reader_new(t->image, path, &ivr, byte_count, 0);
2080  if (ret < 0)
2081  return ret;
2082  *start_byte = ivr->start_byte;
2083  keep = iso_interval_reader_keep(t, ivr, 0);
2084  if (keep < 0)
2085  return(keep);
2086  iso_interval_reader_destroy(&ivr, 0);
2087  return ISO_SUCCESS + (keep > 0);
2088 }
2089 
2090 
2092  uint32_t prepad, uint32_t blocks, int flag)
2093 {
2094 
2095  struct iso_interval_reader *ivr = NULL;
2096  int buf_fill;
2097  off_t byte_count;
2098  FILE *fp = NULL;
2099 
2100  uint32_t i;
2101  uint8_t *buf = NULL;
2102  int ret;
2103 
2104  LIBISO_ALLOC_MEM(buf, uint8_t, BLOCK_SIZE);
2105  for (i = 0; i < prepad; i++) {
2106  ret = iso_write(target, buf, BLOCK_SIZE);
2107  if (ret < 0)
2108  goto ex;
2109  }
2110 
2111  if (flag & 1) {
2112  ret = iso_interval_reader_new(target->image, path,
2113  &ivr, &byte_count, 0);
2114  if (ret < 0)
2115  goto ex;
2116  ret = iso_interval_reader_keep(target, ivr, 0);
2117  if (ret < 0)
2118  goto ex;
2119  if (ret > 0) {
2120  /* From imported_iso and for add-on session. Leave it in place. */
2121  ret = ISO_SUCCESS;
2122  goto ex;
2123  }
2124  for (i = 0; i < blocks; i++) {
2125  ret = iso_interval_reader_read(ivr, buf, &buf_fill, 0);
2126  if (ret < 0)
2127  goto ex;
2128  ret = iso_write(target, buf, BLOCK_SIZE);
2129  if (ret < 0)
2130  goto ex;
2131  }
2132  } else {
2133  fp = fopen(path, "rb");
2134  if (fp == NULL)
2135  {ret = ISO_BAD_PARTITION_FILE; goto ex;}
2136 
2137  for (i = 0; i < blocks; i++) {
2138  memset(buf, 0, BLOCK_SIZE);
2139  if (fp != NULL) {
2140  ret = fread(buf, 1, BLOCK_SIZE, fp);
2141  if (ret != BLOCK_SIZE) {
2142  fclose(fp);
2143  fp = NULL;
2144  }
2145  }
2146  ret = iso_write(target, buf, BLOCK_SIZE);
2147  if (ret < 0) {
2148  if (fp != NULL)
2149  fclose(fp);
2150  goto ex;
2151  }
2152  }
2153  if (fp != NULL)
2154  fclose(fp);
2155  }
2156  ret = ISO_SUCCESS;
2157 ex:;
2158  iso_interval_reader_destroy(&ivr, 0);
2159  LIBISO_FREE_MEM(buf);
2160  return ret;
2161 }
2162 
2163 
2164 void issue_ucs2_warning_summary(size_t failures)
2165 {
2166  if (failures > ISO_JOLIET_UCS2_WARN_MAX) {
2168  "More filenames found which were not suitable for Joliet character set UCS-2");
2169  }
2170  if (failures > 0) {
2172  "Sum of filenames not suitable for Joliet character set UCS-2: %.f",
2173  (double) failures);
2174  }
2175 }
2176 
2177 
2178 static
2179 void *write_function(void *arg)
2180 {
2181  int res, i;
2182 #ifndef Libisofs_appended_partitions_inlinE
2183  int first_partition = 1, last_partition = 0;
2184 #endif
2185  IsoImageWriter *writer;
2186 
2187  Ecma119Image *target = (Ecma119Image*)arg;
2188  iso_msg_debug(target->image->id, "Starting image writing...");
2189 
2190  target->bytes_written = (off_t) 0;
2191  target->percent_written = 0;
2192 
2193  res = write_head_part(target, 0);
2194  if (res < 0)
2195  goto write_error;
2196 
2197  /* write data for each writer */
2198  for (i = 0; i < (int) target->nwriters; ++i) {
2199  writer = target->writers[i];
2200  if (target->gpt_backup_outside &&
2202  continue;
2203  res = writer->write_data(writer);
2204  if (res < 0) {
2205  goto write_error;
2206  }
2207  }
2208 
2209 #ifndef Libisofs_appended_partitions_inlinE
2210 
2211  /* Append partition data */
2212  iso_count_appended_partitions(target, &first_partition, &last_partition);
2213  for (i = first_partition - 1; i <= last_partition - 1; i++) {
2214  if (target->opts->appended_partitions[i] == NULL)
2215  continue;
2216  if (target->opts->appended_partitions[i][0] == 0)
2217  continue;
2218  res = iso_write_partition_file(target,
2219  target->opts->appended_partitions[i],
2220  target->appended_part_prepad[i],
2221  target->appended_part_size[i],
2222  target->opts->appended_part_flags[i] & 1);
2223  if (res < 0)
2224  goto write_error;
2225  }
2226 
2227 #endif /* ! Libisofs_appended_partitions_inlinE */
2228 
2229  if (target->gpt_backup_outside) {
2230  for (i = 0; i < (int) target->nwriters; ++i) {
2231  writer = target->writers[i];
2233  continue;
2234  res = writer->write_data(writer);
2235  if (res < 0)
2236  goto write_error;
2237  }
2238  }
2239 
2240  /* Transplant checksum buffer from Ecma119Image to IsoImage */
2241  transplant_checksum_buffer(target, 0);
2242 
2244 
2245  res = finish_libjte(target);
2246  if (res <= 0)
2247  goto write_error;
2248 
2250 
2251  target->image->generator_is_running = 0;
2252 
2253  /* Give up reference claim made in ecma119_image_new().
2254  Eventually free target */
2255  ecma119_image_free(target);
2256 
2257  if (target->tree_end_block == 1) {
2258  iso_msgs_submit(0,
2259  "Image is most likely damaged. Calculated/written tree end address mismatch.",
2260  0, "FATAL", 0);
2261  }
2262  if (target->bytes_written != target->total_size) {
2263  iso_msg_debug(target->image->id,
2264  "bytes_written = %.f <-> total_size = %.f",
2265  (double) target->bytes_written, (double) target->total_size);
2266  iso_msgs_submit(0,
2267 "Image is most likely damaged. Calculated/written image end address mismatch.",
2268  0, "FATAL", 0);
2269  }
2270 
2271 #ifdef Libisofs_with_pthread_exiT
2272  pthread_exit(NULL);
2273 #else
2274  return NULL;
2275 #endif
2276 
2277 write_error: ;
2278  if (res != (int) ISO_LIBJTE_END_FAILED)
2279  finish_libjte(target);
2280  target->eff_partition_offset = 0;
2281  if (res == (int) ISO_CANCELED) {
2282  /* canceled */
2283  if (!target->opts->will_cancel)
2285  0, NULL);
2286  } else {
2287  /* image write error */
2288  iso_msg_submit(target->image->id, ISO_WRITE_ERROR, res,
2289  "Image write error");
2290  }
2292 
2293  /* Re-activate recorded cx xinfo */
2294  process_preserved_cx(target->image->root, 1);
2295 
2296  target->image->generator_is_running = 0;
2297 
2298  /* Give up reference claim made in ecma119_image_new().
2299  Eventually free target */
2300  ecma119_image_free(target);
2301 
2302 #ifdef Libisofs_with_pthread_exiT
2303  pthread_exit(NULL);
2304 #else
2305  return NULL;
2306 #endif
2307 
2308 }
2309 
2310 
2311 static
2313 {
2314  int ret;
2315 
2316  /* Set provisory value of isofs.ca with
2317  4 byte LBA, 4 byte count, size 16, name MD5 */
2318  ret = iso_root_set_isofsca((IsoNode *) src->root, 0, 0, 0, 16, "MD5", 0);
2319  if (ret < 0)
2320  return ret;
2321  return ISO_SUCCESS;
2322 }
2323 
2324 
2325 /*
2326  @flag bit0= recursion
2327 */
2328 static
2329 int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
2330 {
2331  IsoNode *pos;
2332  IsoFile *file;
2333  IsoImage *img;
2334  int ret, i, no_md5 = 0, has_xinfo = 0, has_attr = 0;
2335  size_t old_cx_value_length = 0;
2336  unsigned int idx = 0;
2337  char *old_cx_value= NULL;
2338  void *xipt = NULL;
2339 
2340  img= target->image;
2341 
2342  if (node->type == LIBISO_FILE) {
2343  file = (IsoFile *) node;
2344  if (file->from_old_session) {
2345  /* Record attribute isofs.cx as xinfo before it can get overwritten
2346  for the emerging image.
2347  The recorded index will be used to retrieve the loaded MD5
2348  and it will be brought back into effect if cancellation of
2349  image production prevents that the old MD5 array gets replaced
2350  by the new one.
2351  */
2352  has_attr = iso_node_lookup_attr(node, "isofs.cx",
2353  &old_cx_value_length, &old_cx_value, 0);
2354  if (has_attr == 1 && old_cx_value_length == 4) {
2355  for (i = 0; i < 4; i++)
2356  idx = (idx << 8) | ((unsigned char *) old_cx_value)[i];
2357  if (idx > 0 && idx < 0x8000000) {
2358  /* xipt is an int disguised as void pointer */
2359  for (i = 0; i < 4; i++)
2360  ((char *) &xipt)[i] = old_cx_value[i];
2362  xipt);
2363  if (ret < 0)
2364  goto ex;
2365  } else
2366  no_md5 = 1;
2367  }
2368  }
2369  if (file->from_old_session && target->opts->appendable) {
2370  /* Save MD5 data of files from old image which will not
2371  be copied and have an MD5 recorded in the old image. */
2372  has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func,
2373  &xipt);
2374  if (has_xinfo > 0) {
2375  /* xinfo MD5 overrides everything else unless data get copied
2376  and checksummed during that copying
2377  */;
2378  } else if (has_attr == 1 && img->checksum_array == NULL) {
2379  /* No checksum array loaded. Delete "isofs.cx" */
2380  if (!target->opts->will_cancel)
2381  iso_file_set_isofscx((IsoFile *) node, 0, 1);
2382  no_md5 = 1;
2383  } else if (!(has_attr == 1 && old_cx_value_length == 4)) {
2384  no_md5 = 1;
2385  }
2386  }
2387 
2388  /* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0.
2389  Omit those from old image which will not be copied and have no MD5.
2390  Do not alter the nodes if this is only a will_cancel run.
2391  */
2392  if (!(target->opts->will_cancel || no_md5)) {
2393  /* Record provisory new index */
2394  ret = iso_file_set_isofscx(file, (unsigned int) 0, 0);
2395  if (ret < 0)
2396  goto ex;
2397  }
2398  } else if (node->type == LIBISO_DIR) {
2399  for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
2400  ret = checksum_prepare_nodes(target, pos, 1);
2401  if (ret < 0)
2402  goto ex;
2403  }
2404  }
2405  ret = ISO_SUCCESS;
2406 ex:;
2407  if (old_cx_value != NULL)
2408  free(old_cx_value);
2409  return ret;
2410 }
2411 
2412 /* Determine the alleged time of image production by predicting the volume
2413  creation and modification timestamps and taking the maximum of both.
2414 */
2415 static
2417 {
2418  IsoWriteOpts *o;
2419  time_t now = 0, t, t0;
2420  uint8_t time_text[18];
2421  int i;
2422 
2423  iso_nowtime(&t0, 0);
2424  o = target->opts;
2425  if (o->vol_uuid[0]) {
2426  for(i = 0; i < 16; i++)
2427  if(o->vol_uuid[i] < '0' || o->vol_uuid[i] > '9')
2428  break;
2429  else
2430  time_text[i] = o->vol_uuid[i];
2431  for(; i < 16; i++)
2432  time_text[i] = '1';
2433  time_text[16] = time_text[17] = 0;
2434  t = iso_datetime_read_17(time_text);
2435  if (t > now)
2436  now = t;
2437  } else {
2438  if (o->vol_creation_time > 0) {
2439  if (o->vol_creation_time > now)
2440  now = o->vol_creation_time;
2441  } else if (t0 > now) {
2442  now = t0;
2443  }
2444  if (o->vol_modification_time > 0) {
2445  if (o->vol_modification_time > now)
2446  now = o->vol_modification_time;
2447  } else if (t0 > now) {
2448  now = t0;
2449  }
2450  }
2451  target->now = now;
2452 }
2453 
2454 static
2456 {
2457  if (target->opts->gpt_disk_guid_mode == 0) {
2458  /* Random UUID production delayed until really needed */
2459  return ISO_SUCCESS;
2460  } else if (target->opts->gpt_disk_guid_mode == 1) {
2461  memcpy(target->gpt_uuid_base, target->opts->gpt_disk_guid, 16);
2462  } else if (target->opts->gpt_disk_guid_mode == 2) {
2463  if (target->opts->vol_uuid[0] == 0)
2464  return ISO_GPT_NO_VOL_UUID;
2465  /* Move centi-seconds part to byte 9 and 10 */
2466  memcpy(target->gpt_uuid_base, target->opts->vol_uuid, 9);
2467  memcpy(target->gpt_uuid_base + 9, target->opts->vol_uuid + 14, 2);
2468  memcpy(target->gpt_uuid_base + 11, target->opts->vol_uuid + 9, 5);
2470  } else {
2471  return ISO_BAD_GPT_GUID_MODE;
2472  }
2473  memcpy(target->gpt_disk_guid, target->gpt_uuid_base, 16);
2474  target->gpt_disk_guid_set = 1;
2475  target->gpt_uuid_counter = 1;
2476  return ISO_SUCCESS;
2477 }
2478 
2479 static
2481 {
2482  int ret, i, voldesc_size, nwriters, tag_pos;
2483  int sa_type;
2484  Ecma119Image *target;
2485  IsoWriteOpts *opts;
2486  IsoImageWriter *writer;
2487  int file_src_writer_index = -1;
2488  int system_area_options = 0;
2489  char *system_area = NULL;
2490  int write_count = 0, write_count_mem;
2491  uint32_t vol_space_size_mem;
2492  off_t total_size_mem;
2493 
2494 #ifdef Libisofs_appended_partitions_inlinE
2495  int fap, lap, app_part_count;
2496 #endif
2497 
2498  /* 1. Allocate target and attach a copy of in_opts there */
2499  target = calloc(1, sizeof(Ecma119Image));
2500  if (target == NULL) {
2501  return ISO_OUT_OF_MEM;
2502  }
2503  /* This reference will be transferred to the burn_source and released by
2504  bs_free_data.
2505  */
2506  target->refcount = 1;
2507  target->opts = NULL;
2508 
2509  /* Record a copy of in_opts.
2510  It is a copy because in_opts is prone to manipulations from the
2511  application thread while the image production thread is running.
2512  */
2513  ret = iso_write_opts_clone(in_opts, &(target->opts), 0);
2514  if (ret != ISO_SUCCESS)
2515  goto target_cleanup;
2516  opts = target->opts;
2517 
2518  /* create the tree for file caching */
2519  ret = iso_rbtree_new(iso_file_src_cmp, &(target->files));
2520  if (ret < 0) {
2521  goto target_cleanup;
2522  }
2523  target->ecma119_hidden_list = NULL;
2524 
2525  target->image = src;
2526  iso_image_ref(src);
2527 
2528  target->rr_reloc_node = NULL;
2529 
2530  target->replace_uid = opts->replace_uid ? 1 : 0;
2531  target->replace_gid = opts->replace_gid ? 1 : 0;
2532  target->replace_dir_mode = opts->replace_dir_mode ? 1 : 0;
2533  target->replace_file_mode = opts->replace_file_mode ? 1 : 0;
2534 
2535  target->uid = opts->replace_uid == 2 ? opts->uid : 0;
2536  target->gid = opts->replace_gid == 2 ? opts->gid : 0;
2537  target->dir_mode = opts->replace_dir_mode == 2 ? opts->dir_mode : 0555;
2538  target->file_mode = opts->replace_file_mode == 2 ? opts->file_mode : 0444;
2539 
2541 
2542  target->replace_timestamps = opts->replace_timestamps ? 1 : 0;
2543  target->timestamp = opts->replace_timestamps == 2 ?
2544  opts->timestamp : target->now;
2545 
2546  /* el-torito? */
2547  target->eltorito = (src->bootcat == NULL ? 0 : 1);
2548  target->catalog = src->bootcat;
2549  if (target->catalog != NULL) {
2550  target->num_bootsrc = target->catalog->num_bootimages;
2551  target->bootsrc = calloc(target->num_bootsrc + 1,
2552  sizeof(IsoFileSrc *));
2553  target->boot_appended_idx = calloc(target->num_bootsrc + 1,
2554  sizeof(int));
2555  target->boot_intvl_start = calloc(target->num_bootsrc + 1,
2556  sizeof(uint32_t));
2557  target->boot_intvl_size = calloc(target->num_bootsrc + 1,
2558  sizeof(uint32_t));
2559  if (target->bootsrc == NULL || target->boot_appended_idx == NULL ||
2560  target->boot_intvl_start == NULL ||
2561  target->boot_intvl_size == NULL) {
2562  ret = ISO_OUT_OF_MEM;
2563  goto target_cleanup;
2564  }
2565  for (i= 0; i < target->num_bootsrc; i++) {
2566  target->bootsrc[i] = NULL;
2567  target->boot_appended_idx[i] = -1;
2568  target->boot_intvl_start[i] = 0;
2569  target->boot_intvl_size[i] = 0;
2570  }
2571  /* It is not easy to predict when the node gets created and can be
2572  manipulated. So it is better for reproducibility to derive its
2573  timestamps from the well controllable now-time.
2574  */
2575  if (target->catalog->node != NULL) {
2576  iso_node_set_mtime((IsoNode *) target->catalog->node, target->now);
2577  iso_node_set_atime((IsoNode *) target->catalog->node, target->now);
2578  iso_node_set_ctime((IsoNode *) target->catalog->node, target->now);
2579  }
2580 
2581  } else {
2582  target->num_bootsrc = 0;
2583  target->bootsrc = NULL;
2584  }
2585 
2586  if (opts->system_area_data != NULL) {
2587  system_area = opts->system_area_data;
2588  system_area_options = opts->system_area_options;
2589  } else if (src->system_area_data != NULL) {
2590  system_area = src->system_area_data;
2591  system_area_options = src->system_area_options;
2592  } else {
2593  system_area_options = opts->system_area_options & 0xfffffffd;
2594  }
2595  sa_type = (system_area_options >> 2) & 0x3f;
2596  if (sa_type != 0 && sa_type != 3)
2597  for (i = 0; i < ISO_MAX_PARTITIONS; i++)
2598  if (opts->appended_partitions[i] != NULL) {
2599  ret = ISO_NON_MBR_SYS_AREA;
2600  goto target_cleanup;
2601  }
2602  if (sa_type != 0 && opts->prep_partition != NULL) {
2603  ret = ISO_NON_MBR_SYS_AREA;
2604  goto target_cleanup;
2605  }
2606 
2607  target->system_area_data = NULL;
2608  if (system_area != NULL) {
2609  target->system_area_data = calloc(32768, 1);
2610  if (target->system_area_data == NULL) {
2611  ret = ISO_OUT_OF_MEM;
2612  goto target_cleanup;
2613  }
2614  memcpy(target->system_area_data, system_area, 32768);
2615  }
2616  target->system_area_options = system_area_options;
2617 
2620  if (target->partition_secs_per_head == 0)
2621  target->partition_secs_per_head = 32;
2622  if (target->partition_heads_per_cyl == 0)
2623  target->partition_heads_per_cyl = 64;
2624  target->eff_partition_offset = 0;
2625  target->partition_root = NULL;
2626  target->partition_l_table_pos = 0;
2627  target->partition_m_table_pos = 0;
2628  target->j_part_root = NULL;
2629  target->j_part_l_path_table_pos = 0;
2630  target->j_part_m_path_table_pos = 0;
2631  target->input_charset = strdup(iso_get_local_charset(0));
2632  if (target->input_charset == NULL) {
2633  ret = ISO_OUT_OF_MEM;
2634  goto target_cleanup;
2635  }
2636 
2637  if (opts->output_charset != NULL) {
2638  target->output_charset = strdup(opts->output_charset);
2639  } else {
2640  target->output_charset = strdup(target->input_charset);
2641  }
2642  if (target->output_charset == NULL) {
2643  ret = ISO_OUT_OF_MEM;
2644  goto target_cleanup;
2645  }
2646 
2647  target->total_size = 0;
2648  target->vol_space_size = 0;
2649  target->pvd_size_is_total_size = 0;
2650 
2651  target->checksum_idx_counter = 0;
2652  target->checksum_ctx = NULL;
2653  target->checksum_counter = 0;
2654  target->checksum_rlsb_tag_pos = 0;
2655  target->checksum_sb_tag_pos = 0;
2656  target->checksum_tree_tag_pos = 0;
2657  target->checksum_tag_pos = 0;
2658  target->checksum_buffer = NULL;
2659  target->checksum_array_pos = 0;
2660  target->checksum_range_start = 0;
2661  target->checksum_range_size = 0;
2662  target->opts_overwrite = NULL;
2663 
2664 #ifdef Libisofs_with_libjtE
2665 
2666  /* Eventually start Jigdo Template Extraction */
2667  if (opts->libjte_handle != NULL) {
2668  ret = libjte_write_header(opts->libjte_handle);
2669  if (ret <= 0) {
2670  iso_libjte_forward_msgs(opts->libjte_handle,
2671  target->image->id, ISO_LIBJTE_START_FAILED, 0);
2673  goto target_cleanup;
2674  }
2675  }
2676 
2677 #endif /* Libisofs_with_libjtE */
2678 
2679  target->mipsel_e_entry = 0;
2680  target->mipsel_p_offset = 0;
2681  target->mipsel_p_vaddr = 0;
2682  target->mipsel_p_filesz = 0;
2683 
2684  target->sparc_core_src = NULL;
2685 
2686  target->empty_file_block = 0;
2687  target->tree_end_block = 0;
2688 
2689  target->wthread_is_running = 0;
2690 
2691  target->part_align_blocks = 0;
2692  target->alignment_end_block = 0;
2693  target->post_iso_part_pad = 0;
2694  target->prep_part_size = 0;
2695  target->efi_boot_part_size = 0;
2696  target->efi_boot_part_filesrc = NULL;
2697  for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
2698  target->appended_part_prepad[i] = 0;
2699  target->appended_part_start[i] = target->appended_part_size[i] = 0;
2700  }
2701  target->have_appended_partitions = 0;
2702  for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
2703  target->hfsplus_blessed[i] = src->hfsplus_blessed[i];
2704  if (target->hfsplus_blessed[i] != NULL)
2705  iso_node_ref(target->hfsplus_blessed[i]);
2706  }
2707  target->hfsp_cat_node_size = 0;
2708  target->hfsp_iso_block_fac = 0;
2709  target->hfsp_collision_count = 0;
2711  target->apm_req_count = 0;
2712  target->apm_req_flags = 0;
2713  for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
2714  target->apm_req[i] = NULL;
2715  for (i = 0; i < ISO_MBR_ENTRIES_MAX; i++)
2716  target->mbr_req[i] = NULL;
2717  target->mbr_req_count = 0;
2718  for (i = 0; i < ISO_GPT_ENTRIES_MAX; i++)
2719  target->gpt_req[i] = NULL;
2720  target->gpt_req_count = 0;
2721  target->gpt_req_flags = 0;
2722  target->gpt_backup_outside = 0;
2723  memset(target->gpt_uuid_base, 0, 16);
2724  target->gpt_uuid_counter = 0;
2725  target->gpt_disk_guid_set = 0;
2726  ret = gpt_disk_guid_setup(target);
2727  if (ret < 0)
2728  goto target_cleanup;
2729  target->gpt_part_start = 0;
2730  target->gpt_backup_end = 0;
2731  target->gpt_backup_size = 0;
2732  target->gpt_max_entries = 0;
2733  target->gpt_is_computed = 0;
2734 
2735  target->sys_area_already_written = 0;
2736 
2737  target->filesrc_start = 0;
2738  target->filesrc_blocks = 0;
2739 
2740  target->joliet_ucs2_failures = 0;
2741 
2742  /* If partitions get appended, then the backup GPT cannot be part of
2743  the ISO filesystem.
2744  */
2745  for (i = 0; i < ISO_MAX_PARTITIONS; i++)
2746  if (target->opts->appended_partitions[i] != NULL) {
2747  target->gpt_backup_outside = 1;
2748  target->have_appended_partitions = 1;
2749  break;
2750  }
2751 
2752  ret = iso_root_set_isofsnt((IsoNode *) (src->root),
2753  (uint32_t) src->truncate_mode,
2754  (uint32_t) src->truncate_length, 0);
2755  if (ret < 0)
2756  goto target_cleanup;
2757 
2758  /*
2759  * 2. Based on those options, create needed writers: iso, joliet...
2760  * Each writer inits its structures and stores needed info into
2761  * target.
2762  * If the writer needs an volume descriptor, it increments image
2763  * current block.
2764  * Finally, create Writer for files.
2765  */
2766  target->curblock = opts->ms_block + 16;
2767 
2768  if (opts->overwrite != NULL && opts->ms_block != 0 &&
2769  opts->ms_block < opts->partition_offset + 32) {
2770  /* Not enough room for superblock relocation */
2771  ret = ISO_OVWRT_MS_TOO_SMALL;
2772  goto target_cleanup;
2773  }
2774 
2775  /* the number of writers is dependent of the extensions */
2776  nwriters = 1 + 1 + 1; /* ECMA-119 + multi-session padding + files */
2777 
2778  if (target->eltorito) {
2779  nwriters++;
2780  }
2781  if (opts->joliet) {
2782  nwriters++;
2783  }
2784  if (opts->iso1999) {
2785  nwriters++;
2786  }
2787  nwriters++; /* Partition Prepend writer */
2788  if (opts->hfsplus || opts->fat) {
2789  nwriters+= 2;
2790  }
2791 
2792 #ifdef Libisofs_part_align_writeR
2793 
2794  nwriters++; /* part_align_blocks writer */
2795 
2796 #endif
2797 
2798 #ifdef Libisofs_appended_partitions_inlinE
2799 
2800  nwriters++; /* Inline Partition Append Writer */
2801 
2802 #endif
2803 
2804  nwriters++; /* GPT backup tail writer */
2805  nwriters++; /* Tail padding writer */
2806  if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) {
2807  nwriters++;
2808  ret = checksum_prepare_image(src, 0);
2809  if (ret < 0)
2810  goto target_cleanup;
2811  if (opts->appendable) {
2812  ret = checksum_prepare_nodes(target, (IsoNode *) src->root, 0);
2813  if (ret < 0)
2814  goto target_cleanup;
2815  }
2816  target->checksum_idx_counter = 0;
2817  }
2818 
2819  target->writers = malloc(nwriters * sizeof(void*));
2820  if (target->writers == NULL) {
2821  ret = ISO_OUT_OF_MEM;
2822  goto target_cleanup;
2823  }
2824 
2825  /* create writer for ECMA-119 structure */
2826  ret = ecma119_writer_create(target);
2827  if (ret < 0) {
2828  goto target_cleanup;
2829  }
2830 
2831  /* create writer for El-Torito */
2832  if (target->eltorito) {
2833  ret = eltorito_writer_create(target);
2834  if (ret < 0) {
2835  goto target_cleanup;
2836  }
2837  }
2838 
2839  /* create writer for Joliet structure */
2840  if (opts->joliet) {
2841  ret = joliet_writer_create(target);
2842  if (ret < 0) {
2843  goto target_cleanup;
2844  }
2845  }
2846 
2847  /* create writer for ISO 9660:1999 structure */
2848  if (opts->iso1999) {
2849  ret = iso1999_writer_create(target);
2850  if (ret < 0) {
2851  goto target_cleanup;
2852  }
2853  }
2854 
2855  voldesc_size = target->curblock - opts->ms_block - 16;
2856 
2857  /* Volume Descriptor Set Terminator */
2858  target->curblock++;
2859 
2860  /* All empty files point to the Volume Descriptor Set Terminator
2861  * rather than to addresses of non-empty files.
2862  */
2863  target->empty_file_block = target->curblock - 1;
2864 
2865  /*
2866  * Create the writer for possible padding to ensure that in case of image
2867  * growing we can safely overwrite the first 64 KiB of image.
2868  */
2869  ret = mspad_writer_create(target);
2870  if (ret < 0) {
2871  goto target_cleanup;
2872  }
2873 
2874  /* The writer for MBR and GPT partitions outside iso_file_src.
2875  * If PreP or FAT are desired, it creates MBR partition entries and
2876  * surrounding protecting partition entries.
2877  * If EFI boot partition is desired, it creates a GPT entry for it.
2878  */
2879  ret = partprepend_writer_create(target);
2880  if (ret < 0)
2881  goto target_cleanup;
2882 
2883  /* create writer for HFS+/FAT structure */
2884  /* Impotant: It must be created directly before iso_file_src_writer_create.
2885  */
2886  if (opts->hfsplus || opts->fat) {
2887  ret = hfsplus_writer_create(target);
2888  if (ret < 0) {
2889  goto target_cleanup;
2890  }
2891  }
2892 
2893  /* create writer for file contents */
2894  ret = iso_file_src_writer_create(target);
2895  if (ret < 0) {
2896  goto target_cleanup;
2897  }
2898  file_src_writer_index = target->nwriters - 1;
2899 
2900  /* create writer for HFS+ structure */
2901  if (opts->hfsplus || opts->fat) {
2902  ret = hfsplus_tail_writer_create(target);
2903  if (ret < 0) {
2904  goto target_cleanup;
2905  }
2906  }
2907 
2908 /* >>> Decide whether the GPT tail writer can be the last of all
2909 */
2910 #define Libisofs_gpt_writer_lasT yes
2911 
2912 #ifndef Libisofs_gpt_writer_lasT
2913  /* This writer has to be added to the list after any writer which might
2914  request production of APM or GPT partition entries by its
2915  compute_data_blocks() method. Its compute_data_blocks() fills the gaps
2916  in APM requests. It determines the position of primary GPT and
2917  backup GPT. Further it reserves blocks for the backup GPT.
2918  */
2919  ret = gpt_tail_writer_create(target);
2920  if (ret < 0)
2921  goto target_cleanup;
2922 #endif /* ! Libisofs_gpt_writer_lasT */
2923 
2924  if ((opts->md5_file_checksums & 1) || opts->md5_session_checksum) {
2925  ret = checksum_writer_create(target);
2926  if (ret < 0)
2927  goto target_cleanup;
2928  }
2929 
2930 #ifdef Libisofs_part_align_writeR
2931 
2932  /* Alignment padding before appended partitions */
2933  ret = zero_writer_create(target, 0, 2);
2934 
2935 #else
2936 
2937  ret = zero_writer_create(target, opts->tail_blocks, 1);
2938 
2939 #endif /* ! Libisofs_part_align_writeR */
2940 
2941  if (ret < 0)
2942  goto target_cleanup;
2943 
2944 #ifdef Libisofs_appended_partitions_inlinE
2945 
2946  ret = partappend_writer_create(target);
2947  if (ret < 0)
2948  goto target_cleanup;
2949 
2950 #endif /* Libisofs_appended_partitions_inlinE */
2951 
2952 #ifdef Libisofs_part_align_writeR
2953 
2954  ret = zero_writer_create(target, opts->tail_blocks, 0);
2955  if (ret < 0)
2956  goto target_cleanup;
2957 
2958 #endif /* Libisofs_part_align_writeR */
2959 
2960 #ifdef Libisofs_gpt_writer_lasT
2961  /* This writer shall be the last one in the list of writers of valuable
2962  data, because it protects the image on media which are seen as GPT
2963  partitioned.
2964  In any case it has to come after any writer which might request
2965  production of APM or GPT partition entries by its compute_data_blocks()
2966  method.
2967  gpt_tail_writer_compute_data_blocks() fills the gaps in APM requests.
2968  It determines the position of primary GPT and backup GPT.
2969  Further it reserves blocks for the backup GPT.
2970  */
2971  ret = gpt_tail_writer_create(target);
2972  if (ret < 0)
2973  goto target_cleanup;
2974 #endif /* Libisofs_gpt_writer_lasT */
2975 
2976  if (opts->partition_offset > 0) {
2977  /* After volume descriptors and superblock tag are accounted for:
2978  account for second volset
2979  */
2980  if (opts->ms_block + opts->partition_offset + 16 < target->curblock) {
2981  /* Overflow of partition system area */
2983  goto target_cleanup;
2984  }
2985  target->curblock = opts->ms_block + opts->partition_offset + 16;
2986 
2987  /* Account for partition tree volume descriptors */
2988  for (i = 0; i < (int) target->nwriters; ++i) {
2989  /* Not all writers have an entry in the partition
2990  volume descriptor set.
2991  */
2992  writer = target->writers[i];
2993 
2994  /* >>> TWINTREE: Enhance ISO1999 writer and add it here */
2995 
2998  continue;
2999  target->curblock++;
3000  }
3001  target->curblock++; /* + Terminator */
3002 
3003  /* >>> TWINTREE: eventually later : second superblock checksum tag */;
3004 
3005  }
3006 
3007 
3008  /* At least the FAT computation needs to know the size of filesrc data
3009  in advance. So this call produces target->filesrc_blocks and
3010  relative extent addresses, which get absolute in
3011  filesrc_writer_compute_data_blocks().
3012  */
3013  ret = filesrc_writer_pre_compute(target->writers[file_src_writer_index]);
3014  if (ret < 0)
3015  goto target_cleanup;
3016 
3017  /*
3018  * 3.
3019  * Call compute_data_blocks() in each Writer.
3020  * That function computes the size needed by its structures and
3021  * increments image current block properly.
3022  */
3023  for (i = 0; i < (int) target->nwriters; ++i) {
3024  IsoImageWriter *writer = target->writers[i];
3025 
3026  if (target->gpt_backup_outside &&
3028  continue;
3029 
3030  /* Exposing address of data start to IsoWriteOpts and memorizing
3031  this address for all files which have no block address:
3032  symbolic links, device files, empty data files.
3033  filesrc_writer_compute_data_blocks() and filesrc_writer_write_data()
3034  will account resp. write this single block.
3035  */
3036  if (i == file_src_writer_index) {
3037  if (! opts->old_empty)
3038  target->empty_file_block = target->curblock;
3039  in_opts->data_start_lba = opts->data_start_lba = target->curblock;
3040  }
3041 
3042  ret = writer->compute_data_blocks(writer);
3043  if (ret < 0) {
3044  goto target_cleanup;
3045  }
3046 
3047  }
3048 
3049  ret = iso_patch_eltoritos(target);
3050  if (ret < 0)
3051  goto target_cleanup;
3052  if (((target->system_area_options & 0xfc) >> 2) == 2) {
3053  ret = iso_read_mipsel_elf(target, 0);
3054  if (ret < 0)
3055  goto target_cleanup;
3056  }
3057 
3058  /*
3059  * The volume space size is just the size of the last session, in
3060  * case of ms images.
3061  */
3062 
3063 #ifdef Libisofs_appended_partitions_inlinE
3064 
3065  app_part_count = iso_count_appended_partitions(target, &fap, &lap);
3066  if (app_part_count == 0)
3067  target->vol_space_size = target->curblock - opts->ms_block;
3068  else
3069  target->vol_space_size = target->alignment_end_block - opts->ms_block;
3070 
3071  target->total_size = (off_t) (target->curblock - opts->ms_block) *
3072  BLOCK_SIZE;
3073 
3074 #else /* Libisofs_appended_partitions_inlinE */
3075 
3076  target->vol_space_size = target->curblock - opts->ms_block;
3077  target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
3078 
3079  /* Add sizes of eventually appended partitions */
3080  ret = iso_compute_append_partitions(target, 0);
3081  if (ret < 0)
3082  goto target_cleanup;
3083 
3084 #endif /* ! Libisofs_appended_partitions_inlinE */
3085 
3086  if (target->gpt_backup_outside) {
3087  for (i = 0; i < (int) target->nwriters; ++i) {
3088  IsoImageWriter *writer = target->writers[i];
3089 
3091  continue;
3092  ret = writer->compute_data_blocks(writer);
3093  if (ret < 0)
3094  goto target_cleanup;
3095  }
3096  }
3097 
3098  /* create the ring buffer */
3099  if (opts->overwrite != NULL &&
3100  opts->fifo_size < 32 + opts->partition_offset) {
3101  /* The ring buffer must be large enough to take opts->overwrite
3102  */
3104  goto target_cleanup;
3105  }
3106  ret = iso_ring_buffer_new(opts->fifo_size, &target->buffer);
3107  if (ret < 0) {
3108  goto target_cleanup;
3109  }
3110 
3111  /* check if we need to provide a copy of volume descriptors */
3112  vol_space_size_mem = target->vol_space_size;
3113  if (opts->overwrite != NULL) {
3114 
3115  /* opts->overwrite must be larger by partion_offset
3116  This storage is provided by the application.
3117  */
3118 
3119 
3120  /*
3121  * In the PVM to be written in the 16th sector of the disc, we
3122  * need to specify the full size.
3123  */
3124  target->vol_space_size += opts->ms_block;
3125 
3126  /* System area and volume descriptors */
3127  target->opts_overwrite = (char *) opts->overwrite;
3128  total_size_mem = target->total_size;
3129  target->total_size += target->opts->ms_block * BLOCK_SIZE;
3130  ret = write_head_part1(target, &write_count, 1 | 2);
3131  target->opts_overwrite = NULL;
3132  target->total_size = total_size_mem;
3133  if (ret < 0)
3134  goto target_cleanup;
3135 
3136  /* copy the volume descriptors to the overwrite buffer... */
3137  voldesc_size *= BLOCK_SIZE;
3138  ret = iso_ring_buffer_read(target->buffer, opts->overwrite,
3139  write_count * BLOCK_SIZE);
3140  if (ret < 0) {
3141  iso_msg_debug(target->image->id,
3142  "Error reading overwrite volume descriptors");
3143  goto target_cleanup;
3144  }
3145 
3146  /* Write relocated superblock checksum tag */
3147  tag_pos = voldesc_size / BLOCK_SIZE + 16 + 1;
3148  if (opts->md5_session_checksum) {
3149  target->checksum_rlsb_tag_pos = tag_pos;
3150  if (target->checksum_rlsb_tag_pos < 32) {
3151  ret = iso_md5_start(&(target->checksum_ctx));
3152  if (ret < 0)
3153  goto target_cleanup;
3154  target->opts_overwrite = (char *) opts->overwrite;
3155  iso_md5_compute(target->checksum_ctx, target->opts_overwrite,
3156  target->checksum_rlsb_tag_pos * 2048);
3157  ret = iso_md5_write_tag(target, 4);
3158  target->opts_overwrite = NULL; /* opts might not persist */
3159  if (ret < 0)
3160  goto target_cleanup;
3161  }
3162  tag_pos++;
3163  write_count++;
3164  }
3165 
3166  /* Clean out eventual obsolete checksum tags */
3167  for (i = tag_pos; i < 32; i++) {
3168  int tag_type;
3169  uint32_t pos, range_start, range_size, next_tag;
3170  char md5[16];
3171 
3172  ret = iso_util_decode_md5_tag((char *)(opts->overwrite + i * 2048),
3173  &tag_type, &pos, &range_start,
3174  &range_size, &next_tag, md5, 0);
3175  if (ret > 0)
3176  opts->overwrite[i * 2048] = 0;
3177  }
3178 
3179  /* Write second set of volume descriptors */
3180  write_count_mem= write_count;
3181  ret = write_head_part2(target, &write_count, 0);
3182  if (ret < 0)
3183  goto target_cleanup;
3184 
3185  /* Read written data into opts->overwrite */
3186  ret = iso_ring_buffer_read(target->buffer,
3187  opts->overwrite + write_count_mem * BLOCK_SIZE,
3188  (write_count - write_count_mem) * BLOCK_SIZE);
3189  if (ret < 0) {
3190  iso_msg_debug(target->image->id,
3191  "Error reading overwrite volume descriptors");
3192  goto target_cleanup;
3193  }
3194 
3195  /* Delete the filler partitions of GPT and APM so that write_function()
3196  can insert new ones for a possibly different total_size */;
3197  iso_delete_gpt_apm_fillers(target, 0);
3198  }
3199 
3200  /* This was possibly altered by above overwrite buffer production */
3201  target->vol_space_size = vol_space_size_mem;
3202 
3203 /*
3204 */
3205 #define Libisofs_print_size_no_forK 1
3206 
3207 #ifdef Libisofs_print_size_no_forK
3208  if (opts->will_cancel) {
3209  iso_msg_debug(target->image->id,
3210  "Will not start write thread because of iso_write_opts_set_will_cancel");
3211  *img = target;
3212  return ISO_SUCCESS;
3213  }
3214 #endif
3215 
3216 
3217  /* 4. Create and start writing thread */
3218  if (opts->md5_session_checksum) {
3219  /* After any fake writes are done: Initialize image checksum context */
3220  if (target->checksum_ctx != NULL)
3221  iso_md5_end(&(target->checksum_ctx), target->image_md5);
3222  ret = iso_md5_start(&(target->checksum_ctx));
3223  if (ret < 0)
3224  goto target_cleanup;
3225  }
3226 
3227  if (opts->apm_block_size == 0) {
3228  if (target->gpt_req_count)
3229  opts->apm_block_size = 2048; /* Combinable with GPT */
3230  else
3231  opts->apm_block_size = 512; /* Mountable on Linux */
3232  }
3233 
3234  /* ensure the thread is created joinable */
3235  pthread_attr_init(&(target->th_attr));
3236  pthread_attr_setdetachstate(&(target->th_attr), PTHREAD_CREATE_JOINABLE);
3237 
3238  /* To avoid race conditions with the caller, this mark must be set
3239  before the thread starts. So the caller can rely on a value of 0
3240  really meaning that the write has ended, and not that it might not have
3241  begun yet.
3242  In normal processing, the value will be changed to 0 at the end of
3243  write_function().
3244  */
3245  target->image->generator_is_running = 1;
3246 
3247 
3248  /* Claim that target may not get destroyed by bs_free_data() before
3249  write_function() is done with it */
3250  target->refcount++;
3251 
3252  ret = pthread_create(&(target->wthread), &(target->th_attr),
3253  write_function, (void *) target);
3254  if (ret != 0) {
3255  target->refcount--;
3256  iso_msg_submit(target->image->id, ISO_THREAD_ERROR, 0,
3257  "Cannot create writer thread");
3258  ret = ISO_THREAD_ERROR;
3259  goto target_cleanup;
3260  }
3261  target->wthread_is_running= 1;
3262 
3263  /*
3264  * Notice that once we reach this point, target belongs to the writer
3265  * thread and should not be modified until the writer thread finished.
3266  * There're however, specific fields in target that can be accessed, or
3267  * even modified by the read thread (look inside bs_* functions)
3268  */
3269 
3270  *img = target;
3271  return ISO_SUCCESS;
3272 
3273 target_cleanup: ;
3274  target->image->generator_is_running = 0;
3275  ecma119_image_free(target);
3276  return ret;
3277 }
3278 
3279 static int bs_read(struct burn_source *bs, unsigned char *buf, int size)
3280 {
3281  int ret;
3282  Ecma119Image *t = (Ecma119Image*)bs->data;
3283 
3284  ret = iso_ring_buffer_read(t->buffer, buf, size);
3285  if (ret == ISO_SUCCESS) {
3286  return size;
3287  } else if (ret < 0) {
3288  /* error */
3289  iso_msg_submit(t->image->id, ISO_BUF_READ_ERROR, ret, NULL);
3290  return -1;
3291  } else {
3292  /* EOF */
3293  return 0;
3294  }
3295 }
3296 
3297 static off_t bs_get_size(struct burn_source *bs)
3298 {
3299  Ecma119Image *target = (Ecma119Image*)bs->data;
3300  return target->total_size;
3301 }
3302 
3303 static void bs_free_data(struct burn_source *bs)
3304 {
3305  int st;
3306  Ecma119Image *target = (Ecma119Image*)bs->data;
3307 
3308  st = iso_ring_buffer_get_status(bs, NULL, NULL);
3309 
3310  /* was read already finished (i.e, canceled)? */
3311  if (st < 4) {
3312  /* forces writer to stop if it is still running */
3314 
3315  /* wait until writer thread finishes */
3316  if (target->wthread_is_running) {
3317  pthread_join(target->wthread, NULL);
3318  target->wthread_is_running = 0;
3319  iso_msg_debug(target->image->id, "Writer thread joined");
3320  }
3321  }
3322 
3323  iso_msg_debug(target->image->id,
3324  "Ring buffer was %d times full and %d times empty",
3327 
3328  /* The reference to target was inherited from ecma119_image_new() */
3329  ecma119_image_free(target);
3330 }
3331 
3332 static
3333 int bs_cancel(struct burn_source *bs)
3334 {
3335  int st;
3336  size_t cap, free;
3337  Ecma119Image *target = (Ecma119Image*)bs->data;
3338 
3339  st = iso_ring_buffer_get_status(bs, &cap, &free);
3340 
3341  if (free == cap && (st == 2 || st == 3)) {
3342  /* image was already consumed */
3344  } else {
3345  iso_msg_debug(target->image->id, "Reader thread being cancelled");
3346 
3347  /* forces writer to stop if it is still running */
3349  }
3350 
3351  /* wait until writer thread finishes */
3352  if (target->wthread_is_running) {
3353  pthread_join(target->wthread, NULL);
3354  target->wthread_is_running = 0;
3355  iso_msg_debug(target->image->id, "Writer thread joined");
3356  }
3357  return ISO_SUCCESS;
3358 }
3359 
3360 static
3361 int bs_set_size(struct burn_source *bs, off_t size)
3362 {
3363  Ecma119Image *target = (Ecma119Image*)bs->data;
3364 
3365  target->total_size = size;
3366  return 1;
3367 }
3368 
3369 static
3370 int dive_to_depth_8(IsoDir *dir, int depth)
3371 {
3372  int ret;
3373  IsoNode *pos;
3374 
3375  if (depth >= 8)
3376  return 1;
3377  pos = dir->children;
3378  for (pos = dir->children; pos != NULL; pos = pos->next) {
3379  if (pos->type != LIBISO_DIR)
3380  continue;
3381  ret = dive_to_depth_8((IsoDir *) pos, depth + 1);
3382  if (ret != 0)
3383  return ret;
3384  }
3385  return 0;
3386 }
3387 
3388 static
3390 {
3391  int ret;
3392  IsoDir *dir;
3393 
3394  /* Two forms to express the root directory */
3395  if (opts->rr_reloc_dir == NULL)
3396  return 1;
3397  if (opts->rr_reloc_dir[0] == 0)
3398  return 1;
3399 
3400  if (strchr(opts->rr_reloc_dir, '/') != NULL)
3401  return 0;
3402 
3403  /* Check existence of opts->rr_reloc_dir */
3404  ret = iso_dir_get_node(img->root, opts->rr_reloc_dir, NULL);
3405  if (ret > 0)
3406  return 1;
3407  if (ret < 0)
3408  return ret;
3409 
3410  /* Check whether there is a directory of depth 8 (root is depth 1) */
3411  ret = dive_to_depth_8(img->root, 1);
3412  if (ret < 0)
3413  return ret;
3414  if (ret == 0)
3415  return 1;
3416 
3417  /* Make IsoDir with same permissions as root directory */
3418  ret = iso_tree_add_new_dir(img->root, opts->rr_reloc_dir, &dir);
3419  if (ret < 0)
3420  return ret;
3421 
3422  opts->rr_reloc_flags |= 2; /* Auto-created relocation directory */
3423 
3424  return 1;
3425 }
3426 
3428  struct burn_source **burn_src)
3429 {
3430  int ret;
3431  struct burn_source *source;
3432  Ecma119Image *target= NULL;
3433 
3434  if (image == NULL || opts == NULL || burn_src == NULL) {
3435  return ISO_NULL_POINTER;
3436  }
3437 
3438  source = calloc(1, sizeof(struct burn_source));
3439  if (source == NULL) {
3440  return ISO_OUT_OF_MEM;
3441  }
3442 
3443  if (!opts->allow_deep_paths) {
3444  ret = make_reloc_dir_if_needed(image, opts, 0);
3445  if (ret < 0) {
3446  free(source);
3447  return ret;
3448  }
3449  }
3450 
3451  ret = ecma119_image_new(image, opts, &target);
3452  if (ret < 0) {
3453  free(source);
3454  return ret;
3455  }
3456 
3457  source->refcount = 1;
3458  source->version = 1;
3459  source->read = NULL;
3460  source->get_size = bs_get_size;
3461  source->set_size = bs_set_size;
3462  source->free_data = bs_free_data;
3463  source->read_xt = bs_read;
3464  source->cancel = bs_cancel;
3465  source->data = target;
3466 
3467  *burn_src = source;
3468  return ISO_SUCCESS;
3469 }
3470 
3471 int iso_write(Ecma119Image *target, void *buf, size_t count)
3472 {
3473  int ret;
3474 
3475  if (target->bytes_written + (off_t) count > target->total_size) {
3477  "ISO overwrite");
3478  return ISO_ASSERT_FAILURE;
3479  }
3480 
3481  ret = iso_ring_buffer_write(target->buffer, buf, count);
3482  if (ret == 0) {
3483  /* reader cancelled */
3484  return ISO_CANCELED;
3485  }
3486  if (ret < 0)
3487  return ret;
3488  if (target->checksum_ctx != NULL) {
3489  /* Add to image checksum */
3490  target->checksum_counter += count;
3491  iso_md5_compute(target->checksum_ctx, (char *) buf, (int) count);
3492  }
3493 
3494  ret = show_chunk_to_jte(target, buf, count);
3495  if (ret != ISO_SUCCESS)
3496  return ret;
3497 
3498  /* total size is 0 when writing the overwrite buffer */
3499  if (target->total_size != (off_t) 0){
3500  unsigned int kbw, kbt;
3501  int percent;
3502 
3503  target->bytes_written += (off_t) count;
3504  kbw = (unsigned int) (target->bytes_written >> 10);
3505  kbt = (unsigned int) (target->total_size >> 10);
3506  percent = (kbw * 100) / kbt;
3507 
3508  /* only report in 5% chunks */
3509  if (percent >= target->percent_written + 5) {
3510  iso_msg_debug(target->image->id, "Processed %u of %u KB (%d %%)",
3511  kbw, kbt, percent);
3512  target->percent_written = percent;
3513  }
3514  }
3515 
3516  return ISO_SUCCESS;
3517 }
3518 
3519 int iso_write_opts_new(IsoWriteOpts **opts, int profile)
3520 {
3521  int i;
3522  IsoWriteOpts *wopts;
3523 
3524  if (opts == NULL) {
3525  return ISO_NULL_POINTER;
3526  }
3527  if (profile < 0 || profile > 2) {
3528  return ISO_WRONG_ARG_VALUE;
3529  }
3530 
3531  wopts = calloc(1, sizeof(IsoWriteOpts));
3532  if (wopts == NULL) {
3533  return ISO_OUT_OF_MEM;
3534  }
3535  wopts->scdbackup_tag_written = NULL;
3536 
3537  switch (profile) {
3538  case 0:
3539  wopts->iso_level = 1;
3540  break;
3541  case 1:
3542  wopts->iso_level = 3;
3543  wopts->rockridge = 1;
3544  break;
3545  case 2:
3546  wopts->iso_level = 2;
3547  wopts->rockridge = 1;
3548  wopts->joliet = 1;
3549  wopts->replace_dir_mode = 1;
3550  wopts->replace_file_mode = 1;
3551  wopts->replace_uid = 1;
3552  wopts->replace_gid = 1;
3553  wopts->replace_timestamps = 1;
3554  wopts->always_gmt = 1;
3555  break;
3556  default:
3557  /* should never happen */
3558  free(wopts);
3559  return ISO_ASSERT_FAILURE;
3560  break;
3561  }
3562  wopts->hfsplus = 0;
3563  wopts->fat = 0;
3564  wopts->fifo_size = 1024; /* 2 MB buffer */
3565  wopts->sort_files = 1; /* file sorting is always good */
3566  wopts->joliet_utf16 = 0;
3567  wopts->rr_reloc_dir = NULL;
3568  wopts->rr_reloc_flags = 0;
3569  wopts->system_area_data = NULL;
3570  wopts->system_area_size = 0;
3571  wopts->system_area_options = 0;
3572  wopts->vol_creation_time = 0;
3573  wopts->vol_modification_time = 0;
3574  wopts->vol_expiration_time = 0;
3575  wopts->vol_effective_time = 0;
3576  memset(wopts->vol_uuid, 0, 17);
3577  wopts->partition_offset = 0;
3578  wopts->partition_secs_per_head = 0;
3579  wopts->partition_heads_per_cyl = 0;
3580 
3581 #ifdef Libisofs_with_libjtE
3582  wopts->libjte_handle = NULL;
3583 #endif /* Libisofs_with_libjtE */
3584 
3585  wopts->tail_blocks = 0;
3586  wopts->prep_partition = NULL;
3587  wopts->prep_part_flag = 0;
3588  wopts->efi_boot_partition = NULL;
3589  wopts->efi_boot_part_flag = 0;
3590  for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
3591  wopts->appended_partitions[i] = NULL;
3592  wopts->appended_part_types[i] = 0;
3593  wopts->appended_part_flags[i] = 0;
3594  memset(wopts->appended_part_type_guids[i], 0, 16);
3595  wopts->appended_part_gpt_flags[i] = 0;
3596  }
3597  wopts->appended_as_gpt = 0;
3598  wopts->appended_as_apm = 0;
3599  wopts->part_like_isohybrid = 0;
3600  wopts->iso_mbr_part_type = -1;
3601  memset(wopts->iso_gpt_type_guid, 0, 16);
3602  wopts->iso_gpt_flag= 0;
3603  wopts->ascii_disc_label[0] = 0;
3604  wopts->will_cancel = 0;
3605  wopts->allow_dir_id_ext = 0;
3606  wopts->old_empty = 0;
3607  wopts->untranslated_name_len = 0;
3608  for (i = 0; i < 8; i++)
3609  wopts->hfsp_serial_number[i] = 0;
3610  wopts->apm_block_size = 0;
3611  wopts->hfsp_block_size = 0;
3612  memset(wopts->gpt_disk_guid, 0, 16);
3613  wopts->gpt_disk_guid_mode = 0;
3614 
3615  *opts = wopts;
3616  return ISO_SUCCESS;
3617 }
3618 
3620 {
3621  int ret, i;
3622  IsoWriteOpts *o = NULL;
3623 
3624  ret = iso_write_opts_new(&o, 0);
3625  if (ret != 1)
3626  return ret;
3627  *out = o;
3628 
3629  /* Provisory copy of all values and un-managed pointers */
3630  memcpy(o, in, sizeof(IsoWriteOpts));
3631 
3632  /* Set managed pointers to NULL */
3633  o->output_charset = NULL;
3634  o->rr_reloc_dir = NULL;
3635  o->system_area_data = NULL;
3636  o->prep_partition = NULL;
3637  o->efi_boot_partition = NULL;
3638  for (i = 0; i < ISO_MAX_PARTITIONS; i++)
3639  o->appended_partitions[i] = NULL;
3640 
3641  /* Clone managed objects */
3642  if (iso_clone_mem(in->output_charset, &(o->output_charset), 0) != 1)
3643  goto out_of_mem;
3644  if (iso_clone_mem(in->rr_reloc_dir, &(o->rr_reloc_dir), 0) != 1)
3645  goto out_of_mem;
3647  in->system_area_size) != 1)
3648  goto out_of_mem;
3649  if (iso_clone_mem(in->prep_partition, &(o->prep_partition), 0) != 1)
3650  goto out_of_mem;
3652  != 1)
3653  goto out_of_mem;
3654  for (i = 0; i < ISO_MAX_PARTITIONS; i++)
3656  &(o->appended_partitions[i]), 0) != 1)
3657  goto out_of_mem;
3658 
3659  return ISO_SUCCESS;
3660 
3661 out_of_mem:;
3663  return ISO_OUT_OF_MEM;
3664 }
3665 
3667 {
3668  int i;
3669 
3670  if (opts == NULL) {
3671  return;
3672  }
3673  free(opts->output_charset);
3674  if (opts->rr_reloc_dir != NULL)
3675  free(opts->rr_reloc_dir);
3676  if (opts->system_area_data != NULL)
3677  free(opts->system_area_data);
3678  if (opts->prep_partition != NULL)
3679  free(opts->prep_partition);
3680  if (opts->efi_boot_partition != NULL)
3681  free(opts->efi_boot_partition);
3682  for (i = 0; i < ISO_MAX_PARTITIONS; i++)
3683  if (opts->appended_partitions[i] != NULL)
3684  free(opts->appended_partitions[i]);
3685 
3686  free(opts);
3687 }
3688 
3690 {
3691  if (opts == NULL) {
3692  return ISO_NULL_POINTER;
3693  }
3694  opts->will_cancel = !!will_cancel;
3695  return ISO_SUCCESS;
3696 }
3697 
3699 {
3700  if (opts == NULL) {
3701  return ISO_NULL_POINTER;
3702  }
3703  if (level != 1 && level != 2 && level != 3) {
3704  return ISO_WRONG_ARG_VALUE;
3705  }
3706  opts->iso_level = level;
3707  return ISO_SUCCESS;
3708 }
3709 
3711 {
3712  if (opts == NULL) {
3713  return ISO_NULL_POINTER;
3714  }
3715  opts->rockridge = enable ? 1 : 0;
3716  return ISO_SUCCESS;
3717 }
3718 
3720 {
3721  if (opts == NULL) {
3722  return ISO_NULL_POINTER;
3723  }
3724  opts->joliet = enable ? 1 : 0;
3725  return ISO_SUCCESS;
3726 }
3727 
3729 {
3730  if (opts == NULL) {
3731  return ISO_NULL_POINTER;
3732  }
3733  opts->hfsplus = enable ? 1 : 0;
3734  return ISO_SUCCESS;
3735 }
3736 
3737 int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable)
3738 {
3739  if (opts == NULL) {
3740  return ISO_NULL_POINTER;
3741  }
3742  opts->fat = enable ? 1 : 0;
3743  return ISO_SUCCESS;
3744 }
3745 
3747 {
3748  if (opts == NULL) {
3749  return ISO_NULL_POINTER;
3750  }
3751  opts->iso1999 = enable ? 1 : 0;
3752  return ISO_SUCCESS;
3753 }
3754 
3756 {
3757  if (opts == NULL) {
3758  return ISO_NULL_POINTER;
3759  }
3760  opts->hardlinks = enable ? 1 : 0;
3761  return ISO_SUCCESS;
3762 }
3763 
3765 {
3766  if (opts == NULL) {
3767  return ISO_NULL_POINTER;
3768  }
3769  opts->aaip = enable ? 1 : 0;
3770  return ISO_SUCCESS;
3771 }
3772 
3774 {
3775  if (opts == NULL) {
3776  return ISO_NULL_POINTER;
3777  }
3778  opts->old_empty = enable ? 1 : 0;
3779  return ISO_SUCCESS;
3780 }
3781 
3783 {
3784  if (opts == NULL) {
3785  return ISO_NULL_POINTER;
3786  }
3787  if (len == -1)
3789  else if(len == 0)
3790  opts->untranslated_name_len = 0;
3791  else if(len > ISO_UNTRANSLATED_NAMES_MAX || len < 0)
3792  return ISO_WRONG_ARG_VALUE;
3793  else
3794  opts->untranslated_name_len = len;
3795  return opts->untranslated_name_len;
3796 }
3797 
3799 {
3800  if (opts == NULL) {
3801  return ISO_NULL_POINTER;
3802  }
3803  opts->allow_dir_id_ext = allow ? 1 : 0;
3804  return ISO_SUCCESS;
3805 }
3806 
3808 {
3809  if (opts == NULL) {
3810  return ISO_NULL_POINTER;
3811  }
3812  opts->omit_version_numbers = omit & 3;
3813  return ISO_SUCCESS;
3814 }
3815 
3817 {
3818  if (opts == NULL) {
3819  return ISO_NULL_POINTER;
3820  }
3821  opts->allow_deep_paths = allow ? 1 : 0;
3822  return ISO_SUCCESS;
3823 }
3824 
3826 {
3827  if (opts == NULL) {
3828  return ISO_NULL_POINTER;
3829  }
3830  opts->allow_longer_paths = allow ? 1 : 0;
3831  return ISO_SUCCESS;
3832 }
3833 
3835 {
3836  if (opts == NULL) {
3837  return ISO_NULL_POINTER;
3838  }
3839  opts->max_37_char_filenames = allow ? 1 : 0;
3840  return ISO_SUCCESS;
3841 }
3842 
3844 {
3845  if (opts == NULL) {
3846  return ISO_NULL_POINTER;
3847  }
3848  opts->no_force_dots = no & 3;
3849  return ISO_SUCCESS;
3850 }
3851 
3853 {
3854  if (opts == NULL) {
3855  return ISO_NULL_POINTER;
3856  }
3857  opts->allow_lowercase = allow ? 1 : 0;
3858  return ISO_SUCCESS;
3859 }
3860 
3862 {
3863  if (opts == NULL) {
3864  return ISO_NULL_POINTER;
3865  }
3866  opts->allow_full_ascii = allow ? 1 : 0;
3867  return ISO_SUCCESS;
3868 }
3869 
3871 {
3872  if (opts == NULL) {
3873  return ISO_NULL_POINTER;
3874  }
3875  opts->allow_7bit_ascii = allow ? 1 : 0;
3876  return ISO_SUCCESS;
3877 }
3878 
3879 
3881 {
3882  if (opts == NULL) {
3883  return ISO_NULL_POINTER;
3884  }
3885  opts->relaxed_vol_atts = allow ? 1 : 0;
3886  return ISO_SUCCESS;
3887 }
3888 
3890 {
3891  if (opts == NULL) {
3892  return ISO_NULL_POINTER;
3893  }
3894  opts->joliet_longer_paths = allow ? 1 : 0;
3895  return ISO_SUCCESS;
3896 }
3897 
3899 {
3900  if (opts == NULL) {
3901  return ISO_NULL_POINTER;
3902  }
3903  opts->joliet_long_names = allow ? 1 : 0;
3904  return ISO_SUCCESS;
3905 }
3906 
3908 {
3909  if (opts == NULL) {
3910  return ISO_NULL_POINTER;
3911  }
3912  opts->joliet_utf16 = allow ? 1 : 0;
3913  return ISO_SUCCESS;
3914 }
3915 
3917 {
3918  if (opts == NULL) {
3919  return ISO_NULL_POINTER;
3920  }
3921  opts->rrip_version_1_10 = oldvers ? 1 : 0;
3922  return ISO_SUCCESS;
3923 }
3924 
3926 {
3927  if (opts == NULL) {
3928  return ISO_NULL_POINTER;
3929  }
3930  opts->rrip_1_10_px_ino = enable ? 1 : 0;
3931  return ISO_SUCCESS;
3932 }
3933 
3935 {
3936  if (opts == NULL) {
3937  return ISO_NULL_POINTER;
3938  }
3939  opts->aaip_susp_1_10 = oldvers ? 1 : 0;
3940  return ISO_SUCCESS;
3941 }
3942 
3944 {
3945  if (opts == NULL) {
3946  return ISO_NULL_POINTER;
3947  }
3948  if (allow < 0)
3949  allow = 1;
3950  else if (allow & (1 << 14))
3951  allow &= ~1;
3952  else if (allow & 6)
3953  allow |= 1;
3954  opts->dir_rec_mtime = allow & 7;
3955  return ISO_SUCCESS;
3956 }
3957 
3958 int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags)
3959 {
3960  if (opts->rr_reloc_dir != name) {
3961  if (opts->rr_reloc_dir != NULL)
3962  free(opts->rr_reloc_dir);
3963  opts->rr_reloc_dir = NULL;
3964  if (name != NULL) {
3965  opts->rr_reloc_dir = strdup(name);
3966  if (opts->rr_reloc_dir == NULL)
3967  return ISO_OUT_OF_MEM;
3968  }
3969  }
3970  opts->rr_reloc_flags = flags & 1;
3971  return ISO_SUCCESS;
3972 }
3973 
3975 {
3976  if (opts == NULL) {
3977  return ISO_NULL_POINTER;
3978  }
3979  opts->sort_files = sort ? 1 : 0;
3980  return ISO_SUCCESS;
3981 }
3982 
3983 int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
3984 {
3985  opts->md5_session_checksum = session & 1;
3986  opts->md5_file_checksums = files & 3;
3987  return ISO_SUCCESS;
3988 }
3989 
3991  char *name, char *timestamp,
3992  char *tag_written)
3993 {
3994  char eff_name[81], eff_time[19];
3995  int i;
3996 
3997  for (i = 0; name[i] != 0 && i < 80; i++)
3998  if (isspace((int) ((unsigned char *) name)[i]))
3999  eff_name[i] = '_';
4000  else
4001  eff_name[i] = name[i];
4002  if (i == 0)
4003  eff_name[i++] = '_';
4004  eff_name[i] = 0;
4005  for (i = 0; timestamp[i] != 0 && i < 18; i++)
4006  if (isspace((int) ((unsigned char *) timestamp)[i]))
4007  eff_time[i] = '_';
4008  else
4009  eff_time[i] = timestamp[i];
4010  if (i == 0)
4011  eff_time[i++] = '_';
4012  eff_time[i] = 0;
4013 
4014  sprintf(opts->scdbackup_tag_parm, "%s %s", eff_name, eff_time);
4015 
4016  opts->scdbackup_tag_written = tag_written;
4017  if (tag_written != NULL)
4018  tag_written[0] = 0;
4019  return ISO_SUCCESS;
4020 }
4021 
4023  int file_mode, int uid, int gid)
4024 {
4025  if (opts == NULL) {
4026  return ISO_NULL_POINTER;
4027  }
4028  if (dir_mode < 0 || dir_mode > 2) {
4029  return ISO_WRONG_ARG_VALUE;
4030  }
4031  if (file_mode < 0 || file_mode > 2) {
4032  return ISO_WRONG_ARG_VALUE;
4033  }
4034  if (uid < 0 || uid > 2) {
4035  return ISO_WRONG_ARG_VALUE;
4036  }
4037  if (gid < 0 || gid > 2) {
4038  return ISO_WRONG_ARG_VALUE;
4039  }
4040  opts->replace_dir_mode = dir_mode;
4041  opts->replace_file_mode = file_mode;
4042  opts->replace_uid = uid;
4043  opts->replace_gid = gid;
4044  return ISO_SUCCESS;
4045 }
4046 
4048 {
4049  if (opts == NULL) {
4050  return ISO_NULL_POINTER;
4051  }
4052  opts->dir_mode = dir_mode;
4053  return ISO_SUCCESS;
4054 }
4055 
4057 {
4058  if (opts == NULL) {
4059  return ISO_NULL_POINTER;
4060  }
4061  opts->file_mode = file_mode;
4062  return ISO_SUCCESS;
4063 }
4064 
4066 {
4067  if (opts == NULL) {
4068  return ISO_NULL_POINTER;
4069  }
4070  opts->uid = uid;
4071  return ISO_SUCCESS;
4072 }
4073 
4075 {
4076  if (opts == NULL) {
4077  return ISO_NULL_POINTER;
4078  }
4079  opts->gid = gid;
4080  return ISO_SUCCESS;
4081 }
4082 
4084 {
4085  if (opts == NULL) {
4086  return ISO_NULL_POINTER;
4087  }
4088  if (replace < 0 || replace > 2) {
4089  return ISO_WRONG_ARG_VALUE;
4090  }
4091  opts->replace_timestamps = replace;
4092  return ISO_SUCCESS;
4093 }
4094 
4096 {
4097  if (opts == NULL) {
4098  return ISO_NULL_POINTER;
4099  }
4100  opts->timestamp = timestamp;
4101  return ISO_SUCCESS;
4102 }
4103 
4105 {
4106  if (opts == NULL) {
4107  return ISO_NULL_POINTER;
4108  }
4109  opts->always_gmt = gmt ? 1 : 0;
4110  return ISO_SUCCESS;
4111 }
4112 
4113 int iso_write_opts_set_output_charset(IsoWriteOpts *opts, const char *charset)
4114 {
4115  if (opts == NULL) {
4116  return ISO_NULL_POINTER;
4117  }
4118  opts->output_charset = charset ? strdup(charset) : NULL;
4119  return ISO_SUCCESS;
4120 }
4121 
4123 {
4124  if (opts == NULL) {
4125  return ISO_NULL_POINTER;
4126  }
4127  opts->appendable = appendable ? 1 : 0;
4128  return ISO_SUCCESS;
4129 }
4130 
4131 int iso_write_opts_set_ms_block(IsoWriteOpts *opts, uint32_t ms_block)
4132 {
4133  if (opts == NULL) {
4134  return ISO_NULL_POINTER;
4135  }
4136  opts->ms_block = ms_block;
4137  return ISO_SUCCESS;
4138 }
4139 
4140 int iso_write_opts_set_overwrite_buf(IsoWriteOpts *opts, uint8_t *overwrite)
4141 {
4142  if (opts == NULL) {
4143  return ISO_NULL_POINTER;
4144  }
4145  opts->overwrite = overwrite;
4146  return ISO_SUCCESS;
4147 }
4148 
4149 int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size)
4150 {
4151  if (opts == NULL) {
4152  return ISO_NULL_POINTER;
4153  }
4154  if (fifo_size < 32) {
4155  return ISO_WRONG_ARG_VALUE;
4156  }
4157  opts->fifo_size = fifo_size;
4158  return ISO_SUCCESS;
4159 }
4160 
4161 int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start,
4162  int flag)
4163 {
4164  if (opts->data_start_lba == 0)
4165  return ISO_ERROR;
4166  *data_start = opts->data_start_lba;
4167  return ISO_SUCCESS;
4168 }
4169 
4170 /*
4171  * @param data Either NULL or 32 kB of data. Do not submit less bytes !
4172  * @param options
4173  * Can cause manipulations of submitted data before they get written:
4174  * bit0= apply a --protective-msdos-label as of grub-mkisofs.
4175  * This means to patch bytes 446 to 512 of the system area so
4176  * that one partition is defined which begins at the second
4177  * 512-byte block of the image and ends where the image ends.
4178  * This works with and without system_area_data.
4179  * bit1= apply isohybrid MBR patching to the system area.
4180  * This works only with system area data from SYSLINUX plus an
4181  * ISOLINUX boot image (see iso_image_set_boot_image()) and
4182  * only if not bit0 is set.
4183  * bit2-7= System area type
4184  * bit8-9= Only with System area type 0 = MBR
4185  * Cylinder alignment mode
4186  * bit10-13= System area sub type
4187  * @param flag bit0 = invalidate any attached system area data
4188  * same as data == NULL
4189  * bit1 = keep data unaltered
4190  * bit2 = keep options unaltered
4191  */
4193  int options, int flag)
4194 {
4195  if (data == NULL || (flag & 1)) { /* Disable */
4196  if (opts->system_area_data != NULL)
4197  free(opts->system_area_data);
4198  opts->system_area_data = NULL;
4199  opts->system_area_size = 0;
4200  } else if (!(flag & 2)) {
4201  if (opts->system_area_data == NULL) {
4202  opts->system_area_data = calloc(32768, 1);
4203  if (opts->system_area_data == NULL)
4204  return ISO_OUT_OF_MEM;
4205  }
4206  memcpy(opts->system_area_data, data, 32768);
4207  opts->system_area_size = 32768;
4208  }
4209  if (!(flag & 4))
4210  opts->system_area_options = options & 0xffff;
4211  return ISO_SUCCESS;
4212 }
4213 
4215  time_t vol_creation_time, time_t vol_modification_time,
4216  time_t vol_expiration_time, time_t vol_effective_time,
4217  char *vol_uuid)
4218 {
4219  opts->vol_creation_time = vol_creation_time;
4220  opts->vol_modification_time = vol_modification_time;
4221  opts->vol_expiration_time = vol_expiration_time;
4222  opts->vol_effective_time = vol_effective_time;
4223  strncpy(opts->vol_uuid, vol_uuid, 16);
4224  opts->vol_uuid[16] = 0;
4225  return ISO_SUCCESS;
4226 }
4227 
4229  uint32_t block_offset_2k,
4230  int secs_512_per_head, int heads_per_cyl)
4231 {
4232  if (block_offset_2k > 0 && block_offset_2k < 16)
4233  return ISO_PART_OFFST_TOO_SMALL;
4234  opts->partition_offset = block_offset_2k;
4235  opts->partition_secs_per_head = secs_512_per_head;
4236  opts->partition_heads_per_cyl = heads_per_cyl;
4237  return ISO_SUCCESS;
4238 }
4239 
4240 int iso_write_opts_attach_jte(IsoWriteOpts *opts, void *libjte_handle)
4241 {
4242 #ifdef Libisofs_with_libjtE
4243 
4244  opts->libjte_handle = libjte_handle;
4245  return ISO_SUCCESS;
4246 
4247 #else
4248 
4249  return ISO_LIBJTE_NOT_ENABLED;
4250 
4251 #endif /* Libisofs_with_libjtE */
4252 }
4253 
4254 int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle)
4255 {
4256 #ifdef Libisofs_with_libjtE
4257 
4258  if (*libjte_handle != NULL)
4259  *libjte_handle = opts->libjte_handle;
4260  opts->libjte_handle = NULL;
4261  return ISO_SUCCESS;
4262 
4263 #else
4264 
4265  return ISO_LIBJTE_NOT_ENABLED;
4266 
4267 #endif /* Libisofs_with_libjtE */
4268 }
4269 
4270 int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks)
4271 {
4272  opts->tail_blocks = num_blocks;
4273  return ISO_SUCCESS;
4274 }
4275 
4276 int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path, int flag)
4277 {
4278  if (opts->prep_partition != NULL)
4279  free(opts->prep_partition);
4280  if (image_path == NULL)
4281  return ISO_SUCCESS;
4282  opts->prep_partition = strdup(image_path);
4283  if (opts->prep_partition == NULL)
4284  return ISO_OUT_OF_MEM;
4285  opts->prep_part_flag = (flag & 1);
4286  return ISO_SUCCESS;
4287 }
4288 
4289 int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
4290  int flag)
4291 {
4292  if (opts->efi_boot_partition != NULL)
4293  free(opts->efi_boot_partition);
4294  if (image_path == NULL)
4295  return ISO_SUCCESS;
4296  opts->efi_boot_partition = strdup(image_path);
4297  if (opts->efi_boot_partition == NULL)
4298  return ISO_OUT_OF_MEM;
4299  opts->efi_boot_part_flag = (flag & 1);
4300  return ISO_SUCCESS;
4301 }
4302 
4303 int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number,
4304  uint8_t partition_type, char *image_path, int flag)
4305 {
4306  if (partition_number < 1 || partition_number > ISO_MAX_PARTITIONS)
4307  return ISO_BAD_PARTITION_NO;
4308  if (opts->appended_partitions[partition_number - 1] != NULL)
4309  free(opts->appended_partitions[partition_number - 1]);
4310  if (image_path == NULL)
4311  return ISO_SUCCESS;
4312  opts->appended_partitions[partition_number - 1] = strdup(image_path);
4313  if (opts->appended_partitions[partition_number - 1] == NULL)
4314  return ISO_OUT_OF_MEM;
4315  opts->appended_part_types[partition_number - 1] = partition_type;
4316  opts->appended_part_flags[partition_number - 1] = (flag & 1);
4317  return ISO_SUCCESS;
4318 }
4319 
4320 int iso_write_opts_set_part_type_guid(IsoWriteOpts *opts, int partition_number,
4321  uint8_t guid[16], int valid)
4322 {
4323  if (partition_number < 1 || partition_number > ISO_MAX_PARTITIONS)
4324  return ISO_BAD_PARTITION_NO;
4325  if (valid)
4326  memcpy(opts->appended_part_type_guids[partition_number - 1], guid, 16);
4327  if (valid)
4328  opts->appended_part_gpt_flags[partition_number - 1]|= 1;
4329  else
4330  opts->appended_part_gpt_flags[partition_number - 1]&= ~1;
4331  return ISO_SUCCESS;
4332 }
4333 
4335 {
4336  opts->appended_as_gpt = !!gpt;
4337  return ISO_SUCCESS;
4338 }
4339 
4341 {
4342  opts->appended_as_apm = !!apm;
4343  return ISO_SUCCESS;
4344 }
4345 
4347 {
4348  opts->part_like_isohybrid = !!alike;
4349  return ISO_SUCCESS;
4350 }
4351 
4353 {
4354  if (part_type < -1 || part_type > 255)
4355  part_type = -1;
4356  opts->iso_mbr_part_type = part_type;
4357  return ISO_SUCCESS;
4358 }
4359 
4361  int valid)
4362 {
4363  if (valid)
4364  memcpy(opts->iso_gpt_type_guid, guid, 16);
4365  opts->iso_gpt_flag = (opts->iso_gpt_flag & ~1) | !!valid;
4366  return ISO_SUCCESS;
4367 }
4368 
4370 {
4371  strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1);
4372  opts->ascii_disc_label[ISO_DISC_LABEL_SIZE - 1] = 0;
4373  return ISO_SUCCESS;
4374 }
4375 
4377  uint8_t serial_number[8])
4378 {
4379  memcpy(opts->hfsp_serial_number, serial_number, 8);
4380  return ISO_SUCCESS;
4381 }
4382 
4384  int hfsp_block_size, int apm_block_size)
4385 {
4386  if (hfsp_block_size != 0 && hfsp_block_size != 512 &&
4387  hfsp_block_size != 2048)
4388  return ISO_BOOT_HFSP_BAD_BSIZE;
4389  opts->hfsp_block_size = hfsp_block_size;
4390  if (apm_block_size != 0 && apm_block_size != 512 && apm_block_size != 2048)
4391  return ISO_BOOT_HFSP_BAD_BSIZE;
4392  opts->apm_block_size = apm_block_size;
4393  return ISO_SUCCESS;
4394 }
4395 
4396 int iso_write_opts_set_gpt_guid(IsoWriteOpts *opts, uint8_t guid[16], int mode)
4397 {
4398  if (mode < 0 || mode > 2)
4399  return ISO_BAD_GPT_GUID_MODE;
4400  opts->gpt_disk_guid_mode = mode;
4401  if (opts->gpt_disk_guid_mode == 1)
4402  memcpy(opts->gpt_disk_guid, guid, 16);
4403  return ISO_SUCCESS;
4404 }
4405 
4406 
4407 /*
4408  * @param flag
4409  * Bitfield for control purposes.
4410  * bit0-bit7= Name space
4411  * 0= generic (to_charset is valid, no reserved characters,
4412  * no length limits)
4413  * 1= Rock Ridge (to_charset is valid)
4414  * 2= Joliet (to_charset gets overridden by UCS-2 or UTF-16)
4415  * 3= ECMA-119 (dull ISO 9660 character set)
4416  * 4= HFS+ (to_charset gets overridden by UTF-16BE)
4417  * bit8= Treat input text as directory name
4418  * (matters for Joliet and ECMA-119)
4419  * bit9= Do not issue error messages
4420  * bit15= Reverse operation (best to be done only with results of
4421  * previous conversions)
4422  */
4423 int iso_conv_name_chars(IsoWriteOpts *opts, char *in_name, size_t name_len,
4424  char **result, size_t *result_len, int flag)
4425 {
4426  int name_space, ret, reverse;
4427  size_t i;
4428  size_t joliet_ucs2_failures = ISO_JOLIET_UCS2_WARN_MAX + 1;/* no warning */
4429  size_t conved_len;
4430  char *from_charset, *to_charset, *conved, *smashed = NULL, *name;
4431  char *tr, *with_version = NULL;
4432  uint16_t *ucs = NULL, *hfspcmp = NULL;
4433  uint32_t ucs_len;
4434  enum IsoNodeType node_type;
4435 
4436  *result = NULL;
4437  *result_len = 0;
4438 
4439  name = in_name;
4440  name_space = flag & 0xff;
4441  reverse = !!(flag & (1 << 15));
4442  node_type = (flag & 256) ? LIBISO_DIR : LIBISO_FILE;
4443  from_charset = iso_get_local_charset(0);
4444 
4445  /* Note: Joliet, ECMA-119, HFS+ actually use to_charset only for the
4446  reverse conversion case */
4447  if (opts->output_charset != NULL)
4448  to_charset = opts->output_charset;
4449  else
4450  to_charset = from_charset;
4451  if (name_space == 1) { /* Rock Ridge */
4452  if (!reverse) {
4453  LIBISO_ALLOC_MEM(smashed, char, name_len + 1);
4454  memcpy(smashed, name, name_len);
4455  smashed[name_len] = 0;
4456  for (i = 0; i < name_len; i++)
4457  if (smashed[i] == '/')
4458  smashed[i] = '_';
4459  name = smashed;
4460 
4461  /* >>> ??? truncate to 255 chars */
4462  }
4463  } else if (name_space == 2) { /* Joliet */
4464  if (opts->joliet_utf16)
4465  to_charset = "UTF-16BE";
4466  else
4467  to_charset = "UCS-2BE";
4468  } else if (name_space == 3) { /* ECMA-119 */
4469  to_charset = "ASCII";
4470  } else if (name_space == 4) { /* HFS+ */
4471  to_charset= "UTF-16BE";
4472  }
4473  if (reverse) {
4474  tr = from_charset;
4475  from_charset = to_charset;
4476  to_charset = tr;
4477  }
4478 
4479  if (name_space == 0 || reverse) {
4480  ret = strnconvl(name, from_charset, to_charset, name_len,
4481  &conved, &conved_len);
4482  if (ret != ISO_SUCCESS)
4483  goto ex;
4484 
4485  } else if (name_space == 1) { /* Rock Ridge */
4486  ret = iso_get_rr_name(opts, from_charset, to_charset, -1, name,
4487  &conved, !!(flag & 512));
4488  if (ret != ISO_SUCCESS)
4489  goto ex;
4490  conved_len = strlen(conved);
4491 
4492  } else if (name_space == 2) { /* Joliet */
4493  ret = iso_get_joliet_name(opts, from_charset, -1, name, node_type,
4494  &joliet_ucs2_failures, &ucs, !!(flag & 512));
4495  if (ret != ISO_SUCCESS)
4496  goto ex;
4497  conved_len = ucslen(ucs) * 2;
4498  conved = (char *) ucs; ucs = NULL;
4499  if (node_type != LIBISO_DIR && !(opts->omit_version_numbers & 3)) {
4500  LIBISO_ALLOC_MEM(with_version, char, conved_len + 6);
4501  memcpy(with_version, conved, conved_len);
4502  with_version[conved_len++] = 0;
4503  with_version[conved_len++] = ';';
4504  with_version[conved_len++] = 0;
4505  with_version[conved_len++] = '1';
4506  with_version[conved_len] = 0;
4507  with_version[conved_len + 1] = 0;
4508  free(conved);
4509  conved = with_version; with_version = NULL;
4510  }
4511 
4512  } else if (name_space == 3) { /* ECMA-119 */
4513  ret = iso_get_ecma119_name(opts, from_charset, -1, name, node_type,
4514  &conved, !!(flag & 512));
4515  if (ret != ISO_SUCCESS)
4516  goto ex;
4517  conved_len = strlen(conved);
4518  if (need_version_number(opts, node_type == LIBISO_DIR ?
4520  LIBISO_ALLOC_MEM(with_version, char, conved_len + 3);
4521  memcpy(with_version, conved, conved_len + 1);
4522  strcat(with_version, ";1");
4523  free(conved);
4524  conved = with_version; with_version = NULL;
4525  conved_len += 2;
4526  }
4527 
4528  } else if (name_space == 4) { /* HFS+ */
4529  ret = iso_get_hfsplus_name(from_charset, -1, name, &ucs, &ucs_len,
4530  &hfspcmp);
4531  if (ret != ISO_SUCCESS)
4532  goto ex;
4533  conved = (char *) ucs; ucs = NULL;
4534  conved_len = ucs_len * 2;
4535 
4536  } else {
4537  ret = ISO_WRONG_ARG_VALUE;
4538  goto ex;
4539  }
4540 
4541  *result = conved;
4542  *result_len = conved_len;
4543  ret = ISO_SUCCESS;
4544 ex:
4545  LIBISO_FREE_MEM(with_version);
4546  LIBISO_FREE_MEM(smashed);
4547  LIBISO_FREE_MEM(ucs);
4548  LIBISO_FREE_MEM(hfspcmp);
4549  return ret;
4550 }
4551 
4552 
4553 static
4555  int (*include_item)(void *),
4556  IsoFileSrc **filelist, size_t *size, int just_count)
4557 {
4558  size_t i;
4559  Ecma119Node *child;
4560 
4561  for (i = 0; i < dir->info.dir->nchildren; i++) {
4562  child = dir->info.dir->children[i];
4563  if (child->type == ECMA119_DIR) {
4564  ecma119_filesrc_array(child, include_item, filelist, size,
4565  just_count);
4566  } else if (child->type == ECMA119_FILE) {
4567  if (include_item != NULL)
4568  if (!include_item((void *) child->info.file))
4569  continue;
4570  if (just_count) {
4571  (*size)++;
4572  } else {
4573  if (!child->info.file->taken) {
4574  filelist[*size] = child->info.file;
4575  child->info.file->taken = 1;
4576  (*size)++;
4577  }
4578  }
4579  }
4580  }
4581 }
4582 
4583 
4584 static
4586  int (*include_item)(void *),
4587  IsoFileSrc **filelist, size_t *size, int just_count)
4588 {
4589  struct iso_filesrc_list_item *item;
4590 
4591  for (item = t->ecma119_hidden_list; item != NULL; item = item->next) {
4592  if (include_item != NULL)
4593  if (!include_item((void *) item->src))
4594  continue;
4595  if (just_count) {
4596  (*size)++;
4597  } else {
4598  if (!item->src->taken) {
4599  filelist[*size] = item->src;
4600  item->src->taken = 1;
4601  (*size)++;
4602  }
4603  }
4604  }
4605 }
4606 
4607 
4609  int (*include_item)(void *),
4610  size_t *size)
4611 {
4612  IsoFileSrc **filelist = NULL;
4613 
4614  /* Count nodes */
4615  *size = 0;
4616  ecma119_filesrc_array(t->root, include_item, filelist, size, 1);
4617  hidden_filesrc_array(t, include_item, filelist, size, 1);
4618 
4619  LIBISO_ALLOC_MEM_VOID(filelist, IsoFileSrc *, *size + 1);
4620 
4621  /* Fill array */
4622  *size = 0;
4623  ecma119_filesrc_array(t->root, include_item, filelist, size, 0);
4624  hidden_filesrc_array(t, include_item, filelist, size, 0);
4625  filelist[*size] = NULL;
4626  return filelist;
4627 
4628 ex: /* LIBISO_ALLOC_MEM failed */
4629  *size = 0;
4630  return NULL;
4631 }
4632 
4633 
4634 /* Determines the range of valid partition numbers depending on partition
4635  table type.
4636 */
4638  int *first_partition, int *last_partition,
4639  int flag)
4640 {
4641  int sa_type;
4642 
4643  sa_type = (opts->system_area_options >> 2) & 0x3f;
4644  if (sa_type == 3) { /* SUN Disk Label */
4645  *first_partition = 2;
4646  *last_partition = 8;
4647  } else {
4648  *first_partition = 1;
4649  *last_partition = 4;
4650  }
4651 }
4652 
4653 
4654 /* Obtains start and end number of appended partition range and returns
4655  the number of valid entries in the list of appended partitions.
4656 */
4658  int *first_partition, int *last_partition)
4659 {
4660  int i, count= 0;
4661 
4662  iso_tell_max_part_range(target->opts, first_partition, last_partition, 0);
4663  for (i = *first_partition - 1; i <= *last_partition - 1; i++) {
4664  if (target->opts->appended_partitions[i] == NULL)
4665  continue;
4666  if (target->opts->appended_partitions[i][0] == 0)
4667  continue;
4668  count++;
4669  }
4670  return(count);
4671 }
4672 
int iso_ring_buffer_get_buf_status(IsoRingBuffer *buf, size_t *size, size_t *free_bytes)
Definition: buffer.c:315
int iso_ring_buffer_read(IsoRingBuffer *buf, uint8_t *dest, size_t count)
Definition: buffer.c:206
void iso_ring_buffer_free(IsoRingBuffer *buf)
Definition: buffer.c:124
unsigned int iso_ring_buffer_get_times_full(IsoRingBuffer *buf)
Definition: buffer.c:282
int iso_ring_buffer_get_status(struct burn_source *b, size_t *size, size_t *free_bytes)
Definition: buffer.c:359
unsigned int iso_ring_buffer_get_times_empty(IsoRingBuffer *buf)
Definition: buffer.c:290
void iso_ring_buffer_reader_close(IsoRingBuffer *buf, int error)
Definition: buffer.c:262
int iso_ring_buffer_write(IsoRingBuffer *buf, uint8_t *data, size_t count)
Definition: buffer.c:150
void iso_ring_buffer_writer_close(IsoRingBuffer *buf, int error)
Definition: buffer.c:252
int iso_ring_buffer_new(size_t size, IsoRingBuffer **rbuf)
Definition: buffer.c:86
#define BLOCK_SIZE
Definition: buffer.h:23
int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path, int flag)
Definition: ecma119.c:4289
static int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
Definition: ecma119.c:2329
int iso_write_opts_set_hfsplus(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3728
IsoFileSrc ** iso_ecma119_to_filesrc_array(Ecma119Image *t, int(*include_item)(void *), size_t *size)
Definition: ecma119.c:4608
static int tail_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: ecma119.c:1187
int iso_write_opts_set_default_uid(IsoWriteOpts *opts, uid_t uid)
Definition: ecma119.c:4065
int iso_interval_reader_new(IsoImage *img, char *path, struct iso_interval_reader **ivr, off_t *byte_count, int flag)
Definition: ecma119.c:1760
int iso_write_opts_set_joliet_utf16(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3907
int iso_interval_reader_read(struct iso_interval_reader *ivr, uint8_t *buf, int *buf_fill, int flag)
Definition: ecma119.c:1910
static int write_head_part(Ecma119Image *target, int flag)
Definition: ecma119.c:1500
static int mspad_writer_write_vol_desc(IsoImageWriter *writer)
Definition: ecma119.c:1052
int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size)
Definition: ecma119.c:4149
static int ecma119_writer_write_data(IsoImageWriter *writer)
Definition: ecma119.c:936
int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label)
Definition: ecma119.c:4369
int iso_write_opts_set_no_force_dots(IsoWriteOpts *opts, int no)
Definition: ecma119.c:3843
static int part_align_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: ecma119.c:1222
int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3798
int iso_write_opts_set_part_offset(IsoWriteOpts *opts, uint32_t block_offset_2k, int secs_512_per_head, int heads_per_cyl)
Definition: ecma119.c:4228
int iso_write_opts_set_always_gmt(IsoWriteOpts *opts, int gmt)
Definition: ecma119.c:4104
int iso_write_opts_new(IsoWriteOpts **opts, int profile)
Definition: ecma119.c:3519
int iso_write_opts_set_appended_as_apm(IsoWriteOpts *opts, int apm)
Definition: ecma119.c:4340
static int bs_cancel(struct burn_source *bs)
Definition: ecma119.c:3333
int ecma119_writer_create(Ecma119Image *target)
Definition: ecma119.c:984
int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3719
static void calc_dir_pos(Ecma119Image *t, Ecma119Node *dir)
Definition: ecma119.c:258
static int transplant_checksum_buffer(Ecma119Image *target, int flag)
Definition: ecma119.c:1337
static int iso_ivr_read_number(char *start_pt, char *end_pt, off_t *result, int flag)
Definition: ecma119.c:1608
int iso_write_opts_set_default_file_mode(IsoWriteOpts *opts, mode_t file_mode)
Definition: ecma119.c:4056
static int write_head_part1(Ecma119Image *target, int *write_count, int flag)
Definition: ecma119.c:1381
int iso_write_opts_set_allow_deep_paths(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3816
static int gpt_disk_guid_setup(Ecma119Image *target)
Definition: ecma119.c:2455
int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode, int file_mode, int uid, int gid)
Definition: ecma119.c:4022
int iso_write_opts_set_output_charset(IsoWriteOpts *opts, const char *charset)
Definition: ecma119.c:4113
int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3943
int iso_write_opts_set_iso_level(IsoWriteOpts *opts, int level)
Definition: ecma119.c:3698
static size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
Definition: ecma119.c:208
static int zero_writer_write_vol_desc(IsoImageWriter *writer)
Definition: ecma119.c:1140
int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks)
Definition: ecma119.c:4270
static int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: ecma119.c:303
int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts, char *name, char *timestamp, char *tag_written)
Definition: ecma119.c:3990
int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers)
Definition: ecma119.c:3916
static int make_reloc_dir_if_needed(IsoImage *img, IsoWriteOpts *opts, int flag)
Definition: ecma119.c:3389
int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts, struct burn_source **burn_src)
Definition: ecma119.c:3427
int iso_write(Ecma119Image *target, void *buf, size_t count)
Definition: ecma119.c:3471
int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt)
Definition: ecma119.c:4334
static int ecma119_writer_write_dirs(IsoImageWriter *writer)
Definition: ecma119.c:865
int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts, int hfsp_block_size, int apm_block_size)
Definition: ecma119.c:4383
int iso_write_opts_set_relaxed_vol_atts(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3880
int iso_write_opts_set_prep_img(IsoWriteOpts *opts, char *image_path, int flag)
Definition: ecma119.c:4276
void iso_tell_max_part_range(IsoWriteOpts *opts, int *first_partition, int *last_partition, int flag)
Definition: ecma119.c:4637
int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3889
int iso_write_partition_file(Ecma119Image *target, char *path, uint32_t prepad, uint32_t blocks, int flag)
Definition: ecma119.c:2091
int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts, uint8_t serial_number[8])
Definition: ecma119.c:4376
static int mspad_writer_free_data(IsoImageWriter *writer)
Definition: ecma119.c:1090
static int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
Definition: ecma119.c:2480
static void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, uint8_t *buf, size_t len_fi, struct susp_info *info, int extent)
Definition: ecma119.c:378
int iso_write_opts_set_default_dir_mode(IsoWriteOpts *opts, mode_t dir_mode)
Definition: ecma119.c:4047
int iso_write_opts_set_default_gid(IsoWriteOpts *opts, gid_t gid)
Definition: ecma119.c:4074
int iso_write_opts_set_replace_timestamps(IsoWriteOpts *opts, int replace)
Definition: ecma119.c:4083
static int iso_ivr_next_comp(char *read_pt, char **next_pt, int flag)
Definition: ecma119.c:1594
void ecma119_set_voldescr_times(IsoImageWriter *writer, struct ecma119_pri_vol_desc *vol)
Definition: ecma119.c:475
int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit)
Definition: ecma119.c:3807
static void ecma119_determine_now_time(Ecma119Image *target)
Definition: ecma119.c:2416
int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3746
static int mspad_writer_create(Ecma119Image *target)
Definition: ecma119.c:1097
int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start, int flag)
Definition: ecma119.c:4161
static int ecma119_writer_write_vol_desc(IsoImageWriter *writer)
Definition: ecma119.c:536
static int iso_ivr_parse_interval(char *start_pt, char *end_pt, off_t *start_byte, off_t *end_byte, int flag)
Definition: ecma119.c:1633
int iso_write_opts_set_gpt_guid(IsoWriteOpts *opts, uint8_t guid[16], int mode)
Definition: ecma119.c:4396
int iso_write_opts_set_part_like_isohybrid(IsoWriteOpts *opts, int alike)
Definition: ecma119.c:4346
int iso_write_opts_set_iso_type_guid(IsoWriteOpts *opts, uint8_t guid[16], int valid)
Definition: ecma119.c:4360
void issue_ucs2_warning_summary(size_t failures)
Definition: ecma119.c:2164
int iso_interval_reader_keep(Ecma119Image *target, struct iso_interval_reader *ivr, int flag)
Definition: ecma119.c:2050
int iso_interval_reader_destroy(struct iso_interval_reader **ivr, int flag)
Definition: ecma119.c:1738
int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len)
Definition: ecma119.c:3782
static char * get_relaxed_vol_id(Ecma119Image *t, const char *name)
Definition: ecma119.c:452
int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3737
static int zero_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: ecma119.c:1126
static int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
Definition: ecma119.c:630
static void hidden_filesrc_array(Ecma119Image *t, int(*include_item)(void *), IsoFileSrc **filelist, size_t *size, int just_count)
Definition: ecma119.c:4585
static void ecma119_image_free(Ecma119Image *t)
Definition: ecma119.c:71
int iso_write_opts_set_pvd_times(IsoWriteOpts *opts, time_t vol_creation_time, time_t vol_modification_time, time_t vol_expiration_time, time_t vol_effective_time, char *vol_uuid)
Definition: ecma119.c:4214
static int bs_read(struct burn_source *bs, unsigned char *buf, int size)
Definition: ecma119.c:3279
int iso_write_opts_attach_jte(IsoWriteOpts *opts, void *libjte_handle)
Definition: ecma119.c:4240
static off_t bs_get_size(struct burn_source *bs)
Definition: ecma119.c:3297
int iso_write_opts_set_joliet_long_names(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3898
static int iso_ivr_parse_zeroizers(struct iso_interval_reader *ivr, char *pathpt, char *end_pt, int flag)
Definition: ecma119.c:1655
int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3764
static void ecma119_filesrc_array(Ecma119Node *dir, int(*include_item)(void *), IsoFileSrc **filelist, size_t *size, int just_count)
Definition: ecma119.c:4554
int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers)
Definition: ecma119.c:3934
static void bs_free_data(struct burn_source *bs)
Definition: ecma119.c:3303
int iso_count_appended_partitions(Ecma119Image *target, int *first_partition, int *last_partition)
Definition: ecma119.c:4657
static int write_vol_desc_terminator(Ecma119Image *target)
Definition: ecma119.c:1354
static int zero_writer_write_data(IsoImageWriter *writer)
Definition: ecma119.c:1147
static int dive_to_depth_8(IsoDir *dir, int depth)
Definition: ecma119.c:3370
static int show_chunk_to_jte(Ecma119Image *target, char *buf, int count)
Definition: ecma119.c:141
int iso_write_opts_set_hardlinks(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3755
static int need_version_number(IsoWriteOpts *opts, enum ecma119_node_type node_type)
Definition: ecma119.c:166
int iso_interval_reader_start_size(Ecma119Image *t, char *path, off_t *start_byte, off_t *byte_count, int flag)
Definition: ecma119.c:2072
static uint32_t calc_path_table_size(Ecma119Node *dir)
Definition: ecma119.c:282
int iso_write_opts_set_overwrite_buf(IsoWriteOpts *opts, uint8_t *overwrite)
Definition: ecma119.c:4140
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
Definition: ecma119.c:3983
static int checksum_prepare_image(IsoImage *src, int flag)
Definition: ecma119.c:2312
static int iso_ivr_parse(struct iso_interval_reader *ivr, char *path, int flag)
Definition: ecma119.c:1700
int iso_write_opts_set_max_37_char_filenames(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3834
int iso_write_opts_set_iso_mbr_part_type(IsoWriteOpts *opts, int part_type)
Definition: ecma119.c:4352
static int write_path_tables(Ecma119Image *t)
Definition: ecma119.c:814
int iso_write_opts_set_old_empty(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3773
static int mspad_writer_write_data(IsoImageWriter *writer)
Definition: ecma119.c:1059
int iso_write_opts_set_allow_longer_paths(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3825
int iso_write_opts_set_part_type_guid(IsoWriteOpts *opts, int partition_number, uint8_t guid[16], int valid)
Definition: ecma119.c:4320
int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768], int options, int flag)
Definition: ecma119.c:4192
int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag)
Definition: ecma119.c:3619
int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3925
static int bs_set_size(struct burn_source *bs, off_t size)
Definition: ecma119.c:3361
int iso_write_opts_set_allow_full_ascii(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3861
static int zero_writer_free_data(IsoImageWriter *writer)
Definition: ecma119.c:1175
int iso_write_opts_set_default_timestamp(IsoWriteOpts *opts, time_t timestamp)
Definition: ecma119.c:4095
static size_t calc_dirent_len(Ecma119Image *t, Ecma119Node *n)
Definition: ecma119.c:183
static int ecma119_writer_free_data(IsoImageWriter *writer)
Definition: ecma119.c:978
int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle)
Definition: ecma119.c:4254
int iso_write_opts_set_partition_img(IsoWriteOpts *opts, int partition_number, uint8_t partition_type, char *image_path, int flag)
Definition: ecma119.c:4303
int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags)
Definition: ecma119.c:3958
int iso_write_opts_set_allow_7bit_ascii(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3870
static int iso_ivr_zeroize(struct iso_interval_reader *ivr, uint8_t *buf, int buf_fill, int flag)
Definition: ecma119.c:1816
int iso_conv_name_chars(IsoWriteOpts *opts, char *in_name, size_t name_len, char **result, size_t *result_len, int flag)
Definition: ecma119.c:4423
static int finish_libjte(Ecma119Image *target)
Definition: ecma119.c:1526
static int write_head_part2(Ecma119Image *target, int *write_count, int flag)
Definition: ecma119.c:1444
void iso_write_opts_free(IsoWriteOpts *opts)
Definition: ecma119.c:3666
int iso_write_opts_set_allow_lowercase(IsoWriteOpts *opts, int allow)
Definition: ecma119.c:3852
static int write_dirs(Ecma119Image *t, Ecma119Node *root, Ecma119Node *parent)
Definition: ecma119.c:733
static int mspad_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: ecma119.c:1034
int iso_write_opts_set_will_cancel(IsoWriteOpts *opts, int will_cancel)
Definition: ecma119.c:3689
static int zero_writer_create(Ecma119Image *target, uint32_t num_blocks, int flag)
Definition: ecma119.c:1258
static void * write_function(void *arg)
Definition: ecma119.c:2179
static int write_path_table(Ecma119Image *t, Ecma119Node **pathlist, int l_type)
Definition: ecma119.c:758
int iso_write_opts_set_ms_block(IsoWriteOpts *opts, uint32_t ms_block)
Definition: ecma119.c:4131
int iso_write_opts_set_rockridge(IsoWriteOpts *opts, int enable)
Definition: ecma119.c:3710
int iso_write_opts_set_appendable(IsoWriteOpts *opts, int appendable)
Definition: ecma119.c:4122
int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort)
Definition: ecma119.c:3974
static int process_preserved_cx(IsoDir *dir, int flag)
Definition: ecma119.c:1298
#define ISO_JOLIET_UCS2_WARN_MAX
Definition: ecma119.h:93
#define ISO_DISC_LABEL_SIZE
Definition: ecma119.h:59
#define ISO_GPT_ENTRIES_MAX
Definition: ecma119.h:87
#define ISO_MBR_ENTRIES_MAX
Definition: ecma119.h:81
#define ISO_MAX_PARTITIONS
Definition: ecma119.h:47
#define ISO_UNTRANSLATED_NAMES_MAX
Definition: ecma119.h:69
#define ISO_APM_ENTRIES_MAX
Definition: ecma119.h:77
void ecma119_node_free(Ecma119Node *node)
Definition: ecma119_tree.c:349
int iso_filesrc_list_destroy(struct iso_filesrc_list_item **start_item)
Definition: ecma119_tree.c:385
int iso_get_ecma119_name(IsoWriteOpts *opts, char *input_charset, int imgid, char *node_name, enum IsoNodeType node_type, char **name, int flag)
Definition: ecma119_tree.c:34
int ecma119_tree_create(Ecma119Image *img)
ecma119_node_type
Definition: ecma119_tree.h:17
@ ECMA119_PLACEHOLDER
Definition: ecma119_tree.h:22
@ ECMA119_DIR
Definition: ecma119_tree.h:19
@ ECMA119_FILE
Definition: ecma119_tree.h:18
int eltorito_writer_create(Ecma119Image *target)
Definition: eltorito.c:1461
int iso_patch_eltoritos(Ecma119Image *t)
Definition: eltorito.c:1340
int iso_file_src_cmp(const void *n1, const void *n2)
Definition: filesrc.c:52
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
Definition: filesrc.c:69
int iso_file_src_writer_create(Ecma119Image *target)
Definition: filesrc.c:721
void iso_file_src_free(void *node)
Definition: filesrc.c:205
int filesrc_writer_pre_compute(IsoImageWriter *writer)
Definition: filesrc.c:239
void iso_setup_hfsplus_block_size(Ecma119Image *target)
Definition: hfsplus.c:1582
int hfsplus_writer_create(Ecma119Image *target)
Definition: hfsplus.c:1590
int hfsplus_tail_writer_create(Ecma119Image *target)
Definition: hfsplus.c:1817
int iso_get_hfsplus_name(char *input_charset, int imgid, char *name, uint16_t **result, uint32_t *result_len, uint16_t **cmp_name)
Definition: hfsplus.c:118
void iso_image_unref(IsoImage *image)
Definition: image.c:225
int iso_image_set_checksums(IsoImage *image, char *checksum_array, uint32_t start_lba, uint32_t end_lba, uint32_t idx_count, int flag)
Definition: image.c:843
void iso_image_ref(IsoImage *image)
Definition: image.c:215
int iso1999_writer_create(Ecma119Image *target)
Definition: iso1999.c:1042
static uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
Definition: isofs_wrap.c:78
int joliet_writer_create(Ecma119Image *target)
Definition: joliet.c:1267
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
int joliet_writer_write_vol_desc(IsoImageWriter *writer)
Definition: joliet.c:926
int iso_md5_write_tag(Ecma119Image *t, int flag)
Definition: md5.c:787
int checksum_writer_create(Ecma119Image *target)
Definition: md5.c:696
int checksum_cx_xinfo_func(void *data, int flag)
Definition: md5.c:421
int checksum_md5_xinfo_func(void *data, int flag)
Definition: md5.c:447
uint32_t iso_read_msb(const uint8_t *buf, int bytes)
Definition: util.c:1531
void iso_datetime_7(unsigned char *buf, time_t t, int always_gmt)
Definition: util.c:1574
int strnconvl(const char *str, const char *icharset, const char *ocharset, size_t len, char **output, size_t *out_len)
Definition: util.c:244
int str2d_char(const char *icharset, const char *input, char **output)
Definition: util.c:1410
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
void iso_datetime_17(unsigned char *buf, time_t t, int always_gmt)
Definition: util.c:1633
off_t iso_scanf_io_size(char *text, int flag)
Definition: util.c:2369
void strncpy_pad(char *dest, const char *src, size_t max)
Definition: util.c:1947
time_t iso_datetime_read_17(const uint8_t *buf)
Definition: util.c:1841
size_t ucslen(const uint16_t *str)
Definition: util.c:1331
int iso_clone_mem(char *in, char **out, size_t size)
Definition: util.c:2336
void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1478
int str2a_char(const char *icharset, const char *input, char **output)
Definition: util.c:1444
int strconv(const char *str, const char *icharset, const char *ocharset, char **output)
Definition: util.c:192
#define LIBISO_FREE_MEM(pt)
Definition: util.h:627
#define ROUND_UP(n, mul)
Definition: util.h:39
void iso_rbtree_destroy(IsoRBTree *tree, void(*free_data)(void *))
Definition: util_rbtree.c:84
int iso_rbtree_new(int(*compare)(const void *, const void *), IsoRBTree **tree)
Definition: util_rbtree.c:50
#define DIV_UP(n, div)
Definition: util.h:38
#define LIBISO_ALLOC_MEM_VOID(pt, typ, count)
Definition: util.h:621
#define LIBISO_ALLOC_MEM(pt, typ, count)
Definition: util.h:615
#define ISO_THREAD_ERROR
Definition: libisofs.h:8754
#define ISO_BUF_READ_ERROR
Definition: libisofs.h:8760
int iso_node_lookup_attr(IsoNode *node, char *name, size_t *value_length, char **value, int flag)
Definition: node.c:1757
#define ISO_BOOT_HFSP_BAD_BSIZE
Definition: libisofs.h:9144
#define ISO_OVWRT_FIFO_TOO_SMALL
Definition: libisofs.h:9049
#define ISO_BAD_PARTITION_NO
Definition: libisofs.h:9071
#define ISO_CANCELED
Definition: libisofs.h:8728
int iso_md5_end(void **md5_context, char result[16])
Definition: md5.c:391
#define ISO_OVWRT_MS_TOO_SMALL
Definition: libisofs.h:9036
void iso_node_unref(IsoNode *node)
Definition: node.c:56
#define ISO_SUCCESS
Definition: libisofs.h:8719
#define ISO_WRITE_ERROR
Definition: libisofs.h:8757
#define ISO_INTVL_READ_PROBLEM
Definition: libisofs.h:9196
int iso_error_get_severity(int e)
Definition: messages.c:767
IsoNodeType
Definition: libisofs.h:228
@ LIBISO_DIR
Definition: libisofs.h:229
@ LIBISO_FILE
Definition: libisofs.h:230
#define ISO_MALFORMED_READ_INTVL
Definition: libisofs.h:9192
#define ISO_NAME_NOT_UCS2
Definition: libisofs.h:9162
int iso_dir_get_node(IsoDir *dir, const char *name, IsoNode **node)
Definition: node.c:632
int iso_node_remove_xinfo(IsoNode *node, iso_node_xinfo_func proc)
Definition: node.c:172
int iso_nowtime(time_t *now, int flag)
Definition: util.c:2494
int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos, uint32_t *range_start, uint32_t *range_size, uint32_t *next_tag, char md5[16], int flag)
Definition: util.c:2150
#define ISO_OUT_OF_MEM
Definition: libisofs.h:8745
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
Definition: node.c:213
#define ISO_NO_KEPT_DATA_SRC
Definition: libisofs.h:9189
#define ISO_BAD_GPT_GUID_MODE
Definition: libisofs.h:9229
#define ISO_GPT_NO_VOL_UUID
Definition: libisofs.h:9225
int iso_tree_add_new_dir(IsoDir *parent, const char *name, IsoDir **dir)
Definition: tree.c:55
#define ISO_BAD_PARTITION_FILE
Definition: libisofs.h:9074
void iso_node_set_ctime(IsoNode *node, time_t time)
Definition: node.c:545
void iso_node_set_mtime(IsoNode *node, time_t time)
Definition: node.c:513
#define ISO_LIBJTE_END_FAILED
Definition: libisofs.h:9058
#define ISO_WRONG_ARG_VALUE
Definition: libisofs.h:8751
#define ISO_PART_OFFST_TOO_SMALL
Definition: libisofs.h:9043
void iso_node_ref(IsoNode *node)
Definition: node.c:46
int iso_node_add_xinfo(IsoNode *node, iso_node_xinfo_func proc, void *data)
Definition: node.c:136
int iso_msgs_submit(int error_code, char msg_text[], int os_errno, char severity[], int origin)
Definition: messages.c:707
#define ISO_NULL_POINTER
Definition: libisofs.h:8742
#define ISO_MULTI_OVER_IMPORTED
Definition: libisofs.h:9240
#define ISO_LIBJTE_NOT_ENABLED
Definition: libisofs.h:9052
#define ISO_ERROR
Definition: libisofs.h:8734
#define ISO_LIBJTE_START_FAILED
Definition: libisofs.h:9055
void iso_node_set_atime(IsoNode *node, time_t time)
Definition: node.c:529
char * iso_get_local_charset(int flag)
Definition: util.c:185
#define ISO_LIBJTE_FILE_FAILED
Definition: libisofs.h:9062
#define ISO_NON_MBR_SYS_AREA
Definition: libisofs.h:9078
int iso_md5_start(void **md5_context)
Definition: md5.c:353
#define ISO_FILENAME_WRONG_CHARSET
Definition: libisofs.h:8841
@ ISO_HFSPLUS_BLESS_MAX
Definition: libisofs.h:8598
int iso_md5_compute(void *md5_context, char *data, int datalen)
Definition: md5.c:365
#define ISO_IMAGE_WRITE_CANCELED
Definition: libisofs.h:8918
#define ISO_ASSERT_FAILURE
Definition: libisofs.h:8737
int libjte_write_header(struct libjte_env *o)
Definition: libjte.c:387
int libjte_write_footer(struct libjte_env *o)
Definition: libjte.c:422
int libjte_show_data_chunk(struct libjte_env *o, void *buffer, int sector_size, int count)
Definition: libjte.c:548
int iso_libjte_forward_msgs(void *libjte_handle, int imgid, int errcode, int flag)
Definition: messages.c:792
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
int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba, uint32_t count, uint32_t size, char *typetext, int flag)
Definition: node.c:2910
int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index, int flag)
Definition: node.c:2887
int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode, uint32_t truncate_length, int flag)
Definition: node.c:2982
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up, size_t *ce, size_t base_ce)
Definition: rockridge.c:1483
int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up, struct susp_info *info)
Definition: rockridge.c:1636
int iso_get_rr_name(IsoWriteOpts *opts, char *input_charset, char *output_charset, int imgid, char *str, char **name, int flag)
Definition: rockridge.c:367
int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
Definition: rockridge.c:2270
void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, uint8_t *buf)
Definition: rockridge.c:2235
Definition: node.h:140
IsoNode * children
Definition: node.h:144
struct iso_file_section * sections
Definition: filesrc.h:56
int nsections
Definition: filesrc.h:57
unsigned int taken
Definition: filesrc.h:37
Definition: node.h:149
unsigned int from_old_session
Definition: node.h:155
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 truncate_length
Definition: image.h:176
struct el_torito_boot_catalog * bootcat
Definition: image.h:62
int truncate_mode
Definition: image.h:175
IsoFile * sparc_core_node
Definition: image.h:81
int generator_is_running
Definition: image.h:235
char * system_area_data
Definition: image.h:65
IsoNode * hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]
Definition: image.h:242
char application_use[512]
Definition: image.h:59
char * checksum_array
Definition: image.h:229
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
int system_area_options
Definition: image.h:69
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
IsoDataSource * import_src
Definition: image.h:107
Definition: node.h:100
enum IsoNodeType type
Definition: node.h:111
IsoNode * next
Definition: node.h:131
time_t mtime
Definition: node.h:121
int(* set_size)(struct burn_source *source, off_t size)
Definition: libburn.h:526
void(* free_data)(struct burn_source *)
Definition: libburn.h:533
off_t(* get_size)(struct burn_source *)
Definition: libburn.h:509
int(* read)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:493
int(* cancel)(struct burn_source *source)
Definition: libburn.h:581
int refcount
Definition: libburn.h:469
void * data
Definition: libburn.h:557
int(* read_xt)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:575
int version
Definition: libburn.h:572
Ecma119Node ** children
Definition: ecma119_tree.h:34
char * opts_overwrite
Definition: ecma119.h:773
uint32_t partition_l_table_pos
Definition: ecma119.h:798
struct iso_filesrc_list_item * ecma119_hidden_list
Definition: ecma119.h:758
int partition_heads_per_cyl
Definition: ecma119.h:788
uint32_t hfsp_collision_count
Definition: ecma119.h:671
int post_iso_part_pad
Definition: ecma119.h:865
int apm_req_flags
Definition: ecma119.h:853
uint32_t vol_space_size
Definition: ecma119.h:602
struct iso_mbr_partition_request * mbr_req[4]
Definition: ecma119.h:858
uint32_t empty_file_block
Definition: ecma119.h:623
uint32_t tree_end_block
Definition: ecma119.h:629
char * system_area_data
Definition: ecma119.h:702
int mbr_req_count
Definition: ecma119.h:859
IsoImage * image
Definition: ecma119.h:560
struct el_torito_boot_catalog * catalog
Definition: ecma119.h:685
uint32_t checksum_tag_pos
Definition: ecma119.h:766
int partition_secs_per_head
Definition: ecma119.h:786
uint32_t appended_part_size[8]
Definition: ecma119.h:825
uint32_t appended_part_prepad[8]
Definition: ecma119.h:823
uint32_t gpt_backup_end
Definition: ecma119.h:898
IsoNode * hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]
Definition: ecma119.h:829
time_t now
Definition: ecma119.h:594
mode_t file_mode
Definition: ecma119.h:586
uint32_t mspad_blocks
Definition: ecma119.h:750
uint32_t partition_m_table_pos
Definition: ecma119.h:799
int refcount
Definition: ecma119.h:558
unsigned int eltorito
Definition: ecma119.h:566
int num_bootsrc
Definition: ecma119.h:688
uint32_t gpt_max_entries
Definition: ecma119.h:900
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t part_align_blocks
Definition: ecma119.h:819
mode_t dir_mode
Definition: ecma119.h:587
uint32_t m_path_table_pos
Definition: ecma119.h:638
IsoRingBuffer * buffer
Definition: ecma119.h:778
Ecma119Node * rr_reloc_node
Definition: ecma119.h:571
gid_t gid
Definition: ecma119.h:585
uint32_t j_part_l_path_table_pos
Definition: ecma119.h:803
unsigned int replace_timestamps
Definition: ecma119.h:581
char * output_charset
Definition: ecma119.h:592
char * input_charset
Definition: ecma119.h:591
uint32_t * boot_intvl_start
Definition: ecma119.h:693
uint32_t * boot_intvl_size
Definition: ecma119.h:694
uint32_t checksum_tree_tag_pos
Definition: ecma119.h:765
uint32_t mipsel_p_vaddr
Definition: ecma119.h:809
int wthread_is_running
Definition: ecma119.h:782
uint32_t checksum_rlsb_tag_pos
Definition: ecma119.h:763
int gpt_backup_outside
Definition: ecma119.h:880
uid_t uid
Definition: ecma119.h:584
int system_area_options
Definition: ecma119.h:735
unsigned int replace_dir_mode
Definition: ecma119.h:580
uint32_t gpt_part_start
Definition: ecma119.h:896
uint32_t checksum_range_start
Definition: ecma119.h:770
unsigned int replace_gid
Definition: ecma119.h:578
uint32_t prep_part_size
Definition: ecma119.h:867
int hfsp_cat_node_size
Definition: ecma119.h:839
int percent_written
Definition: ecma119.h:612
uint32_t checksum_sb_tag_pos
Definition: ecma119.h:764
uint8_t gpt_uuid_base[16]
Definition: ecma119.h:883
uint8_t sys_area_as_written[16 *2048]
Definition: ecma119.h:906
IsoImageWriter ** writers
Definition: ecma119.h:753
uint32_t mipsel_p_filesz
Definition: ecma119.h:810
int apm_req_count
Definition: ecma119.h:848
IsoFileSrc * efi_boot_part_filesrc
Definition: ecma119.h:888
JolietNode * j_part_root
Definition: ecma119.h:802
uint32_t mipsel_p_offset
Definition: ecma119.h:808
void * checksum_ctx
Definition: ecma119.h:761
unsigned int checksum_idx_counter
Definition: ecma119.h:760
int have_appended_partitions
Definition: ecma119.h:826
int sys_area_already_written
Definition: ecma119.h:907
uint32_t gpt_uuid_counter
Definition: ecma119.h:885
pthread_attr_t th_attr
Definition: ecma119.h:783
char * checksum_buffer
Definition: ecma119.h:768
uint32_t appended_part_start[8]
Definition: ecma119.h:824
size_t joliet_ucs2_failures
Definition: ecma119.h:648
uint32_t filesrc_blocks
Definition: ecma119.h:914
struct iso_apm_partition_request * apm_req[63]
Definition: ecma119.h:847
size_t nwriters
Definition: ecma119.h:752
uint32_t curblock
Definition: ecma119.h:618
Ecma119Node * partition_root
Definition: ecma119.h:797
uint32_t checksum_array_pos
Definition: ecma119.h:769
IsoFileSrc ** bootsrc
Definition: ecma119.h:689
int * boot_appended_idx
Definition: ecma119.h:691
uint32_t gpt_backup_size
Definition: ecma119.h:899
uint32_t filesrc_start
Definition: ecma119.h:913
off_t total_size
Definition: ecma119.h:599
IsoFileSrc * sparc_core_src
Definition: ecma119.h:815
uint32_t l_path_table_pos
Definition: ecma119.h:637
IsoRBTree * files
Definition: ecma119.h:756
Ecma119Node * root
Definition: ecma119.h:561
size_t ndirs
Definition: ecma119.h:635
time_t timestamp
Definition: ecma119.h:588
uint32_t mipsel_e_entry
Definition: ecma119.h:807
int gpt_is_computed
Definition: ecma119.h:901
uint32_t path_table_size
Definition: ecma119.h:636
int gpt_req_flags
Definition: ecma119.h:877
int hfsp_iso_block_fac
Definition: ecma119.h:840
int gpt_disk_guid_set
Definition: ecma119.h:894
unsigned int replace_uid
Definition: ecma119.h:577
uint8_t gpt_disk_guid[16]
Definition: ecma119.h:893
uint32_t eff_partition_offset
Definition: ecma119.h:794
unsigned int replace_file_mode
Definition: ecma119.h:579
struct iso_gpt_partition_request * gpt_req[248]
Definition: ecma119.h:874
int pvd_size_is_total_size
Definition: ecma119.h:607
uint32_t j_part_m_path_table_pos
Definition: ecma119.h:804
uint32_t checksum_range_size
Definition: ecma119.h:771
uint32_t alignment_end_block
Definition: ecma119.h:820
off_t bytes_written
Definition: ecma119.h:610
off_t checksum_counter
Definition: ecma119.h:762
uint32_t efi_boot_part_size
Definition: ecma119.h:887
int gpt_req_count
Definition: ecma119.h:875
pthread_t wthread
Definition: ecma119.h:781
char image_md5[16]
Definition: ecma119.h:767
union ecma119_node::@0 info
char * iso_name
Definition: ecma119_tree.h:61
IsoNode * node
Definition: ecma119_tree.h:65
Ecma119Node * parent
Definition: ecma119_tree.h:63
struct ecma119_dir_info * dir
Definition: ecma119_tree.h:76
enum ecma119_node_type type
Definition: ecma119_tree.h:72
IsoFileSrc * file
Definition: ecma119_tree.h:75
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 vol_desc_version[(7) -(7)+1]
Definition: isofs_wrap.c:44
uint8_t l_path_table_pos[(144) -(141)+1]
Definition: isofs_wrap.c:55
uint8_t app_use[(1395) -(884)+1]
Definition: isofs_wrap.c:73
uint8_t data_prep_id[(574) -(447)+1]
Definition: isofs_wrap.c:62
uint8_t vol_set_size[(124) -(121)+1]
Definition: isofs_wrap.c:51
uint8_t vol_seq_number[(128) -(125)+1]
Definition: isofs_wrap.c:52
uint8_t vol_modification_time[(847) -(831)+1]
Definition: isofs_wrap.c:68
uint8_t bibliographic_file_id[(813) -(777)+1]
Definition: isofs_wrap.c:66
uint8_t file_structure_version[(882) -(882)+1]
Definition: isofs_wrap.c:71
uint8_t m_path_table_pos[(152) -(149)+1]
Definition: isofs_wrap.c:57
uint8_t vol_expiration_time[(864) -(848)+1]
Definition: isofs_wrap.c:69
uint8_t vol_creation_time[(830) -(814)+1]
Definition: isofs_wrap.c:67
uint8_t vol_set_id[(318) -(191)+1]
Definition: isofs_wrap.c:60
uint8_t publisher_id[(446) -(319)+1]
Definition: isofs_wrap.c:61
uint8_t system_id[(40) -(9)+1]
Definition: isofs_wrap.c:46
uint8_t block_size[(132) -(129)+1]
Definition: isofs_wrap.c:53
uint8_t vol_space_size[(88) -(81)+1]
Definition: isofs_wrap.c:49
uint8_t root_dir_record[(190) -(157)+1]
Definition: isofs_wrap.c:59
uint8_t path_table_size[(140) -(133)+1]
Definition: isofs_wrap.c:54
uint8_t volume_id[(72) -(41)+1]
Definition: isofs_wrap.c:47
uint8_t vol_effective_time[(881) -(865)+1]
Definition: isofs_wrap.c:70
uint8_t copyright_file_id[(739) -(703)+1]
Definition: isofs_wrap.c:64
uint8_t vol_desc_type[(1) -(1)+1]
Definition: isofs_wrap.c:42
uint8_t abstract_file_id[(776) -(740)+1]
Definition: isofs_wrap.c:65
uint8_t std_identifier[(6) -(2)+1]
Definition: isofs_wrap.c:43
uint8_t application_id[(702) -(575)+1]
Definition: isofs_wrap.c:63
uint8_t vol_desc_type[(1) -(1)+1]
Definition: ecma119.h:1040
uint8_t vol_desc_version[(7) -(7)+1]
Definition: ecma119.h:1042
uint8_t std_identifier[(6) -(2)+1]
Definition: ecma119.h:1041
int(* close)(IsoDataSource *src)
Definition: libisofs.h:442
int(* open)(IsoDataSource *src)
Definition: libisofs.h:433