libisofs  1.5.4
About: libisofs is a library to create an ISO 9660 filesystem, supports extensions like RockRidge or Joliet, makes bootable ISO 9660, and records file attributes which are of interest for data backups.
  Fossies Dox: libisofs-1.5.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

hfsplus.c File Reference
#include "hfsplus.h"
#include "messages.h"
#include "writer.h"
#include "image.h"
#include "filesrc.h"
#include "eltorito.h"
#include "libisofs.h"
#include "util.h"
#include "ecma119.h"
#include "system_area.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Include dependency graph for hfsplus.c:

Go to the source code of this file.

Macros

#define Libisofs_ts_debuG   yes
 
#define HFSPLUS_DEFAULT_BLOCK_SIZE   2048
 
#define HFSPLUS_MAX_BLOCK_SIZE   2048
 

Functions

uint16_t iso_hfsplus_cichar (uint16_t x)
 
static int pad_up_block (Ecma119Image *t)
 
static int filesrc_block_and_size (Ecma119Image *t, IsoFileSrc *src, uint32_t *start_block, uint64_t *total_size)
 
static uint8_t get_class (uint16_t v)
 
int iso_get_hfsplus_name (char *input_charset, int imgid, char *name, uint16_t **result, uint32_t *result_len, uint16_t **cmp_name)
 
static int set_hfsplus_name (Ecma119Image *t, char *name, HFSPlusNode *node)
 
static int hfsplus_count_tree (Ecma119Image *t, IsoNode *iso)
 
static int create_tree (Ecma119Image *t, IsoNode *iso, uint32_t parent_id)
 Create the low level Hfsplus tree from the high level ISO tree. More...
 
static int cmp_node (const void *f1, const void *f2)
 
static int hfsplus_tail_writer_compute_data_blocks (IsoImageWriter *writer)
 
static int hfsplus_writer_compute_data_blocks (IsoImageWriter *writer)
 
static uint32_t mac_time_offset (uint32_t t)
 
int nop_writer_write_vol_desc (IsoImageWriter *writer)
 
static uid_t px_get_uid (Ecma119Image *t, IsoNode *n)
 
static uid_t px_get_gid (Ecma119Image *t, IsoNode *n)
 
static mode_t px_get_mode (Ecma119Image *t, IsoNode *n, int isdir)
 
int write_sb (Ecma119Image *t)
 
static int hfsplus_writer_write_data (IsoImageWriter *writer)
 
static int hfsplus_tail_writer_write_data (IsoImageWriter *writer)
 
static int hfsplus_writer_free_data (IsoImageWriter *writer)
 
static int nop_writer_free_data (IsoImageWriter *writer)
 
static int search_mangled_pos (Ecma119Image *target, uint32_t idx, uint32_t *new_idx, uint32_t search_start, uint32_t search_end, int flag)
 
static void rotate_hfs_list (Ecma119Image *target, uint32_t old_idx, uint32_t new_idx, int flag)
 
static int subst_symlink_dest_comp (Ecma119Image *target, uint32_t idx, char **dest, unsigned int *dest_len, char **comp_start, char **comp_end, char *new_name, int flag)
 
static int update_symlink (Ecma119Image *target, uint32_t changed_idx, char *new_name, uint32_t link_idx, int *depth, int flag)
 
static int update_name_followers (Ecma119Image *target, uint32_t idx, char *new_name, uint16_t *old_name, uint16_t *old_cmp_name, uint32_t old_strlen)
 
static int try_mangle (Ecma119Image *target, uint32_t idx, uint32_t prev_idx, uint32_t search_start, uint32_t search_end, uint32_t *new_idx, char *prefix, int flag)
 
static int mangle_leafs (Ecma119Image *target, int flag)
 
void iso_setup_hfsplus_block_size (Ecma119Image *target)
 
int hfsplus_writer_create (Ecma119Image *target)
 
int hfsplus_tail_writer_create (Ecma119Image *target)
 
int iso_hfsplus_xinfo_func (void *data, int flag)
 The function that is used to mark struct iso_hfsplus_xinfo_data at IsoNodes and finally disposes such structs when their IsoNodes get disposed. More...
 
struct iso_hfsplus_xinfo_dataiso_hfsplus_xinfo_new (int flag)
 Create an instance of struct iso_hfsplus_xinfo_new(). More...
 
int iso_hfsplus_xinfo_cloner (void *old_data, void **new_data, int flag)
 

Macro Definition Documentation

◆ HFSPLUS_DEFAULT_BLOCK_SIZE

#define HFSPLUS_DEFAULT_BLOCK_SIZE   2048

Definition at line 47 of file hfsplus.c.

◆ HFSPLUS_MAX_BLOCK_SIZE

#define HFSPLUS_MAX_BLOCK_SIZE   2048

Definition at line 51 of file hfsplus.c.

◆ Libisofs_ts_debuG

#define Libisofs_ts_debuG   yes

Definition at line 20 of file hfsplus.c.

Function Documentation

◆ cmp_node()

static int cmp_node ( const void *  f1,
const void *  f2 
)
static

Definition at line 416 of file hfsplus.c.

417 {
418  HFSPlusNode *f = (HFSPlusNode*) f1;
419  HFSPlusNode *g = (HFSPlusNode*) f2;
420  const uint16_t empty[1] = {0};
421  const uint16_t *a, *b;
422  if (f->parent_id > g->parent_id)
423  return +1;
424  if (f->parent_id < g->parent_id)
425  return -1;
426  a = f->cmp_name;
427  b = g->cmp_name;
428  if (!a)
429  a = empty;
430  if (!b)
431  b = empty;
432 
433  return ucscmp(a, b);
434 }
uint32_t parent_id
Definition: hfsplus.h:62
uint16_t * cmp_name
Definition: hfsplus.h:51
int ucscmp(const uint16_t *s1, const uint16_t *s2)
Although each character is 2 bytes, we actually compare byte-by-byte because the words are big-endian...
Definition: util.c:1371

References hfsplus_node::cmp_name, hfsplus_node::parent_id, and ucscmp().

Referenced by hfsplus_writer_create(), mangle_leafs(), and search_mangled_pos().

◆ create_tree()

static int create_tree ( Ecma119Image t,
IsoNode iso,
uint32_t  parent_id 
)
static

Create the low level Hfsplus tree from the high level ISO tree.

Returns
1 success, 0 file ignored, < 0 error

Definition at line 299 of file hfsplus.c.

300 {
301  int ret;
302  uint32_t cat_id, cleaf;
303  int i;
304 
305  if (t == NULL || iso == NULL) {
306  return ISO_NULL_POINTER;
307  }
308 
309  if (iso->hidden & LIBISO_HIDE_ON_HFSPLUS) {
310  /* file will be ignored */
311  return 0;
312  }
313 
314  if (iso->type != LIBISO_FILE && iso->type != LIBISO_DIR
315  && iso->type != LIBISO_SYMLINK && iso->type != LIBISO_SPECIAL)
316  return 0;
317 
318  cat_id = t->hfsp_cat_id++;
319 
320  for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
321  if (t->hfsplus_blessed[i] == iso) {
322 
323 #ifdef Libisofs_ts_debuG
324  iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')",
325  i, cat_id, iso->name);
326 #endif /* Libisofs_ts_debuG */
327 
328  t->hfsp_bless_id[i] = cat_id;
329  }
330 
331  t->hfsp_leafs[t->hfsp_curleaf].node = iso;
332  t->hfsp_leafs[t->hfsp_curleaf].parent_id = parent_id;
333  ret = set_hfsplus_name (t, iso->name, &t->hfsp_leafs[t->hfsp_curleaf]);
334  if (ret < 0)
335  return ret;
336  t->hfsp_leafs[t->hfsp_curleaf].cat_id = cat_id;
337  t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_NONE;
338  t->hfsp_leafs[t->hfsp_curleaf].symlink_dest = NULL;
339 
340  switch (iso->type)
341  {
342  case LIBISO_SYMLINK:
343  {
344  IsoSymlink *sym = (IsoSymlink*) iso;
346  t->hfsp_leafs[t->hfsp_curleaf].symlink_dest = strdup(sym->dest);
347  if (t->hfsp_leafs[t->hfsp_curleaf].symlink_dest == NULL)
348  return ISO_OUT_OF_MEM;
349  t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_SYMLINK;
350  t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata);
351  break;
352  }
353  case LIBISO_SPECIAL:
354  t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_SPECIAL;
356  t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata);
357  break;
358 
359  case LIBISO_FILE:
360  {
361  IsoFile *file = (IsoFile*) iso;
363  ret = iso_file_src_create(t, file, &t->hfsp_leafs[t->hfsp_curleaf].file);
364  if (ret < 0) {
365  return ret;
366  }
367  t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common) + 2 * sizeof (struct hfsplus_forkdata);
368  }
369  break;
370  case LIBISO_DIR:
371  {
373  t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common);
374  break;
375  }
376  default:
377  return ISO_ASSERT_FAILURE;
378  }
379  cleaf = t->hfsp_curleaf;
380  t->hfsp_leafs[t->hfsp_curleaf].nchildren = 0;
381  t->hfsp_curleaf++;
382 
384  t->hfsp_leafs[t->hfsp_curleaf].cmp_name = NULL;
386  t->hfsp_leafs[t->hfsp_curleaf].used_size = t->hfsp_leafs[t->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_thread);
387  t->hfsp_leafs[t->hfsp_curleaf].node = iso;
389  t->hfsp_leafs[t->hfsp_curleaf].file = 0;
390  t->hfsp_leafs[t->hfsp_curleaf].cat_id = parent_id;
391  t->hfsp_leafs[t->hfsp_curleaf].parent_id = cat_id;
392  t->hfsp_leafs[t->hfsp_curleaf].unix_type = UNIX_NONE;
393  t->hfsp_curleaf++;
394 
395  if (iso->type == LIBISO_DIR)
396  {
397  IsoNode *pos;
398  IsoDir *dir = (IsoDir*)iso;
399 
400  pos = dir->children;
401  while (pos)
402  {
403  int cret;
404  cret = create_tree(t, pos, cat_id);
405  if (cret < 0)
406  return cret;
407  pos = pos->next;
408  if (cret > 0)
409  t->hfsp_leafs[cleaf].nchildren++;
410  }
411  }
412  return ISO_SUCCESS;
413 }
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
Create a new IsoFileSrc to get data from a specific IsoFile.
Definition: filesrc.c:69
static int create_tree(Ecma119Image *t, IsoNode *iso, uint32_t parent_id)
Create the low level Hfsplus tree from the high level ISO tree.
Definition: hfsplus.c:299
static int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
Definition: hfsplus.c:235
@ HFSPLUS_FILE_THREAD
Definition: hfsplus.h:27
@ HFSPLUS_DIR_THREAD
Definition: hfsplus.h:26
@ HFSPLUS_DIR
Definition: hfsplus.h:24
@ HFSPLUS_FILE
Definition: hfsplus.h:25
#define ISO_SUCCESS
successfully execution
Definition: libisofs.h:8719
@ LIBISO_DIR
Definition: libisofs.h:229
@ LIBISO_FILE
Definition: libisofs.h:230
@ LIBISO_SYMLINK
Definition: libisofs.h:231
@ LIBISO_SPECIAL
Definition: libisofs.h:232
#define ISO_OUT_OF_MEM
Memory allocation error (FATAL,HIGH, -6)
Definition: libisofs.h:8745
#define ISO_NULL_POINTER
NULL pointer as value for an arg.
Definition: libisofs.h:8742
@ LIBISO_HIDE_ON_HFSPLUS
Hide the node in the HFS+ tree, if that format is enabled.
Definition: libisofs.h:311
@ ISO_HFSPLUS_BLESS_MAX
Definition: libisofs.h:8598
#define ISO_ASSERT_FAILURE
Internal programming error.
Definition: libisofs.h:8737
void iso_msg_debug(int imgid, const char *fmt,...)
Submit a debug message.
Definition: messages.c:253
Definition: node.h:140
IsoNode * children
list of children.
Definition: node.h:144
Definition: node.h:149
int id
Definition: image.h:97
Definition: node.h:100
char * name
Real name, in default charset.
Definition: node.h:113
enum IsoNodeType type
Type of the IsoNode, do not confuse with mode.
Definition: node.h:111
int hidden
whether the node will be hidden, see IsoHideNodeFlag
Definition: node.h:124
IsoNode * next
Definition: node.h:131
IsoImage * image
Definition: ecma119.h:560
uint32_t hfsp_curleaf
Definition: ecma119.h:668
IsoNode * hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX]
Definition: ecma119.h:829
uint32_t hfsp_bless_id[ISO_HFSPLUS_BLESS_MAX]
Definition: ecma119.h:670
HFSPlusNode * hfsp_leafs
Definition: ecma119.h:654
uint32_t hfsp_cat_id
Definition: ecma119.h:660
uint32_t nchildren
Definition: hfsplus.h:63
uint16_t * name
Definition: hfsplus.h:50
char * symlink_dest
Definition: hfsplus.h:57
enum hfsplus_node_type type
Definition: hfsplus.h:59
IsoFileSrc * file
Definition: hfsplus.h:60
enum hfsplus_node::@3 unix_type
IsoNode * node
Definition: hfsplus.h:53
uint32_t used_size
Definition: hfsplus.h:66
uint32_t strlen
Definition: hfsplus.h:65
uint32_t cat_id
Definition: hfsplus.h:61

References hfsplus_node::cat_id, Iso_Dir::children, hfsplus_node::cmp_name, Iso_Symlink::dest, hfsplus_node::file, ecma119_image::hfsp_bless_id, ecma119_image::hfsp_cat_id, ecma119_image::hfsp_curleaf, ecma119_image::hfsp_leafs, ecma119_image::hfsplus_blessed, HFSPLUS_DIR, HFSPLUS_DIR_THREAD, HFSPLUS_FILE, HFSPLUS_FILE_THREAD, Iso_Node::hidden, Iso_Image::id, ecma119_image::image, ISO_ASSERT_FAILURE, iso_file_src_create(), ISO_HFSPLUS_BLESS_MAX, iso_msg_debug(), ISO_NULL_POINTER, ISO_OUT_OF_MEM, ISO_SUCCESS, LIBISO_DIR, LIBISO_FILE, LIBISO_HIDE_ON_HFSPLUS, LIBISO_SPECIAL, LIBISO_SYMLINK, hfsplus_node::name, Iso_Node::name, hfsplus_node::nchildren, Iso_Node::next, hfsplus_node::node, hfsplus_node::parent_id, set_hfsplus_name(), hfsplus_node::strlen, hfsplus_node::symlink_dest, hfsplus_node::type, Iso_Node::type, hfsplus_node::unix_type, and hfsplus_node::used_size.

Referenced by hfsplus_writer_create().

◆ filesrc_block_and_size()

static int filesrc_block_and_size ( Ecma119Image t,
IsoFileSrc src,
uint32_t *  start_block,
uint64_t *  total_size 
)
static

Definition at line 79 of file hfsplus.c.

81 {
82  int i;
83  uint32_t pos;
84 
85  *start_block = 0;
86  *total_size = 0;
87  if (src->nsections <= 0)
88  return 0;
89  pos = *start_block = src->sections[0].block;
90  for (i = 0; i < src->nsections; i++) {
91  *total_size += src->sections[i].size;
92  if (pos != src->sections[i].block) {
94  "File sections do not form consecutive array of blocks");
95  return ISO_SECT_SCATTERED;
96  }
97  /* If .size is not aligned to blocks then there is a byte gap.
98  No need to trace the exact byte address.
99  */
100  pos = src->sections[i].block + src->sections[i].size / 2048;
101  }
102  return 1;
103 }
#define ISO_SECT_SCATTERED
File sections do not form consecutive array of blocks (FAILURE, HIGH, -382)
Definition: libisofs.h:9116
int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt,...)
Definition: messages.c:579
struct iso_file_section * sections
File Sections of the file in the image.
Definition: filesrc.h:56
int nsections
Definition: filesrc.h:57
uint32_t size
Definition: libisofs.h:259
uint32_t block
Definition: libisofs.h:258

References iso_file_section::block, Iso_Image::id, ecma119_image::image, iso_msg_submit(), ISO_SECT_SCATTERED, Iso_File_Src::nsections, Iso_File_Src::sections, and iso_file_section::size.

Referenced by hfsplus_writer_write_data().

◆ get_class()

static uint8_t get_class ( uint16_t  v)
static

Definition at line 106 of file hfsplus.c.

107 {
108  uint16_t s;
109  uint8_t high, low;
110  s = iso_ntohs (v);
111  high = s >> 8;
112  low = v & 0xff;
113  if (!hfsplus_class_pages[high])
114  return 0;
115  return hfsplus_class_pages[high][low];
116 }
uint16_t * hfsplus_class_pages[256]
uint16_t iso_ntohs(uint16_t v)
Definition: util.c:2308

References hfsplus_class_pages, and iso_ntohs().

Referenced by iso_get_hfsplus_name().

◆ hfsplus_count_tree()

static int hfsplus_count_tree ( Ecma119Image t,
IsoNode iso 
)
static

Definition at line 250 of file hfsplus.c.

251 {
252  if (t == NULL || iso == NULL) {
253  return ISO_NULL_POINTER;
254  }
255 
256  if (iso->hidden & LIBISO_HIDE_ON_HFSPLUS) {
257  /* file will be ignored */
258  return 0;
259  }
260 
261  switch (iso->type) {
262  case LIBISO_SYMLINK:
263  case LIBISO_SPECIAL:
264  case LIBISO_FILE:
265  t->hfsp_nfiles++;
266  return ISO_SUCCESS;
267  case LIBISO_DIR:
268  t->hfsp_ndirs++;
269  {
270  IsoNode *pos;
271  IsoDir *dir = (IsoDir*)iso;
272  pos = dir->children;
273  while (pos) {
274  int cret;
275  cret = hfsplus_count_tree(t, pos);
276  if (cret < 0) {
277  /* error */
278  return cret;
279  }
280  pos = pos->next;
281  }
282  }
283  return ISO_SUCCESS;
284  case LIBISO_BOOT:
285  return ISO_SUCCESS;
286  default:
287  /* should never happen */
288  return ISO_ASSERT_FAILURE;
289  }
290 }
static int hfsplus_count_tree(Ecma119Image *t, IsoNode *iso)
Definition: hfsplus.c:250
@ LIBISO_BOOT
Definition: libisofs.h:233
uint32_t hfsp_nfiles
Definition: ecma119.h:658
uint32_t hfsp_ndirs
Definition: ecma119.h:659

References Iso_Dir::children, ecma119_image::hfsp_ndirs, ecma119_image::hfsp_nfiles, Iso_Node::hidden, ISO_ASSERT_FAILURE, ISO_NULL_POINTER, ISO_SUCCESS, LIBISO_BOOT, LIBISO_DIR, LIBISO_FILE, LIBISO_HIDE_ON_HFSPLUS, LIBISO_SPECIAL, LIBISO_SYMLINK, Iso_Node::next, and Iso_Node::type.

Referenced by hfsplus_writer_create().

◆ hfsplus_tail_writer_compute_data_blocks()

static int hfsplus_tail_writer_compute_data_blocks ( IsoImageWriter writer)
static

Definition at line 438 of file hfsplus.c.

439 {
440  Ecma119Image *t;
441  uint32_t hfsp_size, hfsp_curblock, block_fac, block_size;
442 
443  if (writer == NULL) {
444  return ISO_OUT_OF_MEM;
445  }
446 
447  t = writer->target;
448  block_size = t->opts->hfsp_block_size;
449  block_fac = t->hfsp_iso_block_fac;
450 
451 #ifdef Libisofs_ts_debuG
452  iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f",
453  ((double) t->curblock) * 2048.0);
454 #endif
455 
456  hfsp_curblock = t->curblock * block_fac;
457  hfsp_size = hfsp_curblock - t->hfsp_part_start + 1;
458 
459  /* We need one bit for every block. */
460  /* So if we allocate x blocks we have to satisfy:
461  8 * block_size * x >= total_size + x
462  (8 * block_size - 1) * x >= total_size
463  */
464  t->hfsp_allocation_blocks = hfsp_size / (8 * block_size - 1) + 1;
465  t->hfsp_allocation_file_start = hfsp_curblock;
466  hfsp_curblock += t->hfsp_allocation_blocks;
467 
468  /* write_data() will need to pad up ISO block before superblock copy */
469  t->curblock = hfsp_curblock / block_fac;
470  if (hfsp_curblock % block_fac)
471  t->curblock++;
472  hfsp_curblock = t->curblock * block_fac;
473 
474  /* Superblock always occupies 2K */
475  hfsp_curblock += block_fac;
476  t->curblock++;
477 
478 #ifdef Libisofs_ts_debuG
479  iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f",
480  ((double) hfsp_curblock) * block_size);
481 #endif
482 
483  t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start;
484 
485  return iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
486  t->hfsp_part_start / block_fac,
487  t->hfsp_total_blocks / block_fac +
488  !!(t->hfsp_total_blocks % block_fac),
489  "HFSPLUS_Hybrid", "Apple_HFS");
490 }
Ecma119Image * target
Definition: writer.h:28
uint32_t hfsp_part_start
Definition: ecma119.h:657
IsoWriteOpts * opts
Definition: ecma119.h:563
uint32_t hfsp_total_blocks
Definition: ecma119.h:665
uint32_t hfsp_allocation_file_start
Definition: ecma119.h:662
int apm_req_count
Definition: ecma119.h:848
struct iso_apm_partition_request * apm_req[63]
Definition: ecma119.h:847
uint32_t curblock
Definition: ecma119.h:618
int hfsp_iso_block_fac
Definition: ecma119.h:840
uint32_t hfsp_allocation_blocks
Definition: ecma119.h:661
int hfsp_block_size
Definition: ecma119.h:533
int iso_quick_apm_entry(struct iso_apm_partition_request **req_array, int *apm_req_count, uint32_t start_block, uint32_t block_count, char *name, char *type)
Definition: system_area.c:1036

References ecma119_image::apm_req, ecma119_image::apm_req_count, ecma119_image::curblock, ecma119_image::hfsp_allocation_blocks, ecma119_image::hfsp_allocation_file_start, iso_write_opts::hfsp_block_size, ecma119_image::hfsp_iso_block_fac, ecma119_image::hfsp_part_start, ecma119_image::hfsp_total_blocks, Iso_Image::id, ecma119_image::image, iso_msg_debug(), ISO_OUT_OF_MEM, iso_quick_apm_entry(), ecma119_image::opts, and Iso_Image_Writer::target.

Referenced by hfsplus_tail_writer_create().

◆ hfsplus_tail_writer_create()

int hfsplus_tail_writer_create ( Ecma119Image target)

Definition at line 1817 of file hfsplus.c.

1818 {
1819  IsoImageWriter *writer;
1820 
1821  writer = calloc(1, sizeof(IsoImageWriter));
1822  if (writer == NULL) {
1823  return ISO_OUT_OF_MEM;
1824  }
1825 
1829  writer->free_data = nop_writer_free_data;
1830  writer->data = NULL;
1831  writer->target = target;
1832 
1833  /* add this writer to image */
1834  target->writers[target->nwriters++] = writer;
1835 
1836  return ISO_SUCCESS;
1837 }
int nop_writer_write_vol_desc(IsoImageWriter *writer)
Definition: hfsplus.c:554
static int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
Definition: hfsplus.c:1042
static int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: hfsplus.c:438
static int nop_writer_free_data(IsoImageWriter *writer)
Definition: hfsplus.c:1129
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
IsoImageWriter ** writers
Definition: ecma119.h:753
size_t nwriters
Definition: ecma119.h:752

References Iso_Image_Writer::compute_data_blocks, Iso_Image_Writer::data, Iso_Image_Writer::free_data, hfsplus_tail_writer_compute_data_blocks(), hfsplus_tail_writer_write_data(), ISO_OUT_OF_MEM, ISO_SUCCESS, nop_writer_free_data(), nop_writer_write_vol_desc(), ecma119_image::nwriters, Iso_Image_Writer::target, Iso_Image_Writer::write_data, Iso_Image_Writer::write_vol_desc, and ecma119_image::writers.

Referenced by ecma119_image_new().

◆ hfsplus_tail_writer_write_data()

static int hfsplus_tail_writer_write_data ( IsoImageWriter writer)
static

Definition at line 1042 of file hfsplus.c.

1043 {
1044  int ret;
1045  static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
1046  uint32_t complete_blocks, remaining_blocks, block_size;
1047  int over;
1048  Ecma119Image *t;
1049 
1050  if (writer == NULL) {
1051  return ISO_NULL_POINTER;
1052  }
1053 
1054  t = writer->target;
1055  block_size = t->opts->hfsp_block_size;
1056 
1057 #ifdef Libisofs_ts_debuG
1058  iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
1059  (double) t->bytes_written);
1060 #endif
1061 
1062  memset (buffer, -1, sizeof (buffer));
1063  complete_blocks = (t->hfsp_allocation_size - 1) / block_size;
1064  remaining_blocks = t->hfsp_allocation_blocks - complete_blocks;
1065 
1066  while (complete_blocks--)
1067  {
1068  ret = iso_write(t, buffer, block_size);
1069  if (ret < 0)
1070  return ret;
1071  }
1072  over = (t->hfsp_allocation_size - 1) % block_size;
1073  if (over)
1074  {
1075  memset (buffer + over, 0, sizeof (buffer) - over);
1076  buffer[over] = 0xff00 >> (t->hfsp_total_blocks % 8);
1077  ret = iso_write(t, buffer, block_size);
1078  if (ret < 0)
1079  return ret;
1080  remaining_blocks--;
1081  }
1082  memset (buffer, 0, sizeof (buffer));
1083  /* When we have both FAT and HFS+ we may to overestimate needed blocks a bit. */
1084  while (remaining_blocks--)
1085  {
1086  ret = iso_write(t, buffer, block_size);
1087  if (ret < 0)
1088  return ret;
1089  }
1090 
1091  ret = pad_up_block(t);
1092  if (ret < 0)
1093  return ret;
1094  iso_msg_debug(t->image->id, "%d written", (int) t->bytes_written);
1095 
1096  ret = write_sb (t);
1097 
1098 #ifdef Libisofs_ts_debuG
1099  iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f",
1100  (double) t->bytes_written);
1101 #endif
1102 
1103  return ret;
1104 }
int iso_write(Ecma119Image *target, void *buf, size_t count)
This is the function all Writers should call to write data to image.
Definition: ecma119.c:3471
int write_sb(Ecma119Image *t)
Definition: hfsplus.c:595
#define HFSPLUS_MAX_BLOCK_SIZE
Definition: hfsplus.c:51
static int pad_up_block(Ecma119Image *t)
Definition: hfsplus.c:60
uint32_t hfsp_allocation_size
Definition: ecma119.h:666
off_t bytes_written
Definition: ecma119.h:610

References ecma119_image::bytes_written, ecma119_image::hfsp_allocation_blocks, ecma119_image::hfsp_allocation_size, iso_write_opts::hfsp_block_size, ecma119_image::hfsp_total_blocks, HFSPLUS_MAX_BLOCK_SIZE, Iso_Image::id, ecma119_image::image, iso_msg_debug(), ISO_NULL_POINTER, iso_write(), ecma119_image::opts, pad_up_block(), Iso_Image_Writer::target, and write_sb().

Referenced by hfsplus_tail_writer_create().

◆ hfsplus_writer_compute_data_blocks()

static int hfsplus_writer_compute_data_blocks ( IsoImageWriter writer)
static

Definition at line 494 of file hfsplus.c.

495 {
496  Ecma119Image *t;
497  uint32_t i, hfsp_curblock;
498  uint32_t block_fac, block_size;
499 
500  if (writer == NULL) {
501  return ISO_OUT_OF_MEM;
502  }
503 
504  t = writer->target;
505  block_size = t->opts->hfsp_block_size;
506  block_fac = t->hfsp_iso_block_fac;
507 
508  iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
509  t->hfsp_part_start = t->curblock * block_fac;
510 
511  hfsp_curblock = t->curblock * block_fac;
512 
513  /* Superblock always occupies 2K */
514  hfsp_curblock += block_fac;
515 
516  t->hfsp_catalog_file_start = hfsp_curblock;
517 
518 /*
519  hfsp_curblock += (t->hfsp_nnodes * t->hfsp_cat_node_size + block_size - 1) / block_size;
520 */
521  hfsp_curblock += 2 * t->hfsp_nnodes;
522 
523  t->hfsp_extent_file_start = hfsp_curblock;
524  hfsp_curblock++;
525 
526  iso_msg_debug(t->image->id, "(d) hfsp_curblock=%d, nodes =%d", hfsp_curblock, t->hfsp_nnodes);
527 
528  for (i = 0; i < t->hfsp_nleafs; i++)
529  if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK)
530  {
531  t->hfsp_leafs[i].symlink_block = hfsp_curblock;
532  hfsp_curblock += (strlen(t->hfsp_leafs[i].symlink_dest) +
533  block_size - 1) / block_size;
534  }
535 
536  t->curblock = hfsp_curblock / block_fac;
537  if (hfsp_curblock % block_fac)
538  t->curblock++;
539 
540  iso_msg_debug(t->image->id, "(a) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
541 
542  return ISO_SUCCESS;
543 }
uint32_t hfsp_nleafs
Definition: ecma119.h:667
uint32_t hfsp_extent_file_start
Definition: ecma119.h:663
uint32_t hfsp_catalog_file_start
Definition: ecma119.h:664
uint32_t hfsp_nnodes
Definition: ecma119.h:669
uint32_t symlink_block
Definition: hfsplus.h:56

References ecma119_image::curblock, iso_write_opts::hfsp_block_size, ecma119_image::hfsp_catalog_file_start, ecma119_image::hfsp_extent_file_start, ecma119_image::hfsp_iso_block_fac, ecma119_image::hfsp_leafs, ecma119_image::hfsp_nleafs, ecma119_image::hfsp_nnodes, ecma119_image::hfsp_part_start, Iso_Image::id, ecma119_image::image, iso_msg_debug(), ISO_OUT_OF_MEM, ISO_SUCCESS, ecma119_image::opts, hfsplus_node::symlink_block, hfsplus_node::symlink_dest, Iso_Image_Writer::target, and hfsplus_node::unix_type.

Referenced by hfsplus_writer_create().

◆ hfsplus_writer_create()

int hfsplus_writer_create ( Ecma119Image target)

Definition at line 1590 of file hfsplus.c.

1591 {
1592  int ret;
1593  IsoImageWriter *writer = NULL;
1594  int max_levels;
1595  int level = 0;
1596  IsoNode *pos;
1597  IsoDir *dir;
1598  int i;
1599  uint32_t cat_node_size;
1600 
1601  writer = calloc(1, sizeof(IsoImageWriter));
1602  if (writer == NULL) {
1603  ret = ISO_OUT_OF_MEM;
1604  goto ex;
1605  }
1606 
1609 
1611  cat_node_size = target->hfsp_cat_node_size;
1612 
1617  writer->data = NULL;
1618  writer->target = target;
1619 
1620  iso_msg_debug(target->image->id, "Creating HFS+ tree...");
1621  target->hfsp_nfiles = 0;
1622  target->hfsp_ndirs = 0;
1623  target->hfsp_cat_id = 16;
1624  ret = hfsplus_count_tree(target, (IsoNode*)target->image->root);
1625  if (ret < 0)
1626  goto ex;
1627 
1628  for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
1629  target->hfsp_bless_id[i] = 0;
1630 
1631  target->hfsp_nleafs = 2 * (target->hfsp_nfiles + target->hfsp_ndirs);
1632  target->hfsp_curleaf = 0;
1633 
1634  target->hfsp_leafs = calloc (target->hfsp_nleafs, sizeof (target->hfsp_leafs[0]));
1635  if (target->hfsp_leafs == NULL) {
1636  ret = ISO_OUT_OF_MEM;
1637  goto ex;
1638  }
1639  ret = set_hfsplus_name (target, target->image->volume_id,
1640  &target->hfsp_leafs[target->hfsp_curleaf]);
1641  if (ret < 0)
1642  goto ex;
1643  target->hfsp_leafs[target->hfsp_curleaf].node = (IsoNode *) target->image->root;
1644  target->hfsp_leafs[target->hfsp_curleaf].used_size = target->hfsp_leafs[target->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_common);
1645 
1646  target->hfsp_leafs[target->hfsp_curleaf].type = HFSPLUS_DIR;
1647  target->hfsp_leafs[target->hfsp_curleaf].file = 0;
1648  target->hfsp_leafs[target->hfsp_curleaf].cat_id = 2;
1649  target->hfsp_leafs[target->hfsp_curleaf].parent_id = 1;
1650  target->hfsp_leafs[target->hfsp_curleaf].nchildren = 0;
1651  target->hfsp_leafs[target->hfsp_curleaf].unix_type = UNIX_NONE;
1652  target->hfsp_curleaf++;
1653 
1654  target->hfsp_leafs[target->hfsp_curleaf].name = target->hfsp_leafs[target->hfsp_curleaf - 1].name;
1655  target->hfsp_leafs[target->hfsp_curleaf].cmp_name = 0;
1656  target->hfsp_leafs[target->hfsp_curleaf].strlen = target->hfsp_leafs[target->hfsp_curleaf - 1].strlen;
1657  target->hfsp_leafs[target->hfsp_curleaf].used_size = target->hfsp_leafs[target->hfsp_curleaf].strlen * 2 + 8 + 2 + sizeof (struct hfsplus_catfile_thread);
1658  target->hfsp_leafs[target->hfsp_curleaf].node = (IsoNode *) target->image->root;
1659  target->hfsp_leafs[target->hfsp_curleaf].type = HFSPLUS_DIR_THREAD;
1660  target->hfsp_leafs[target->hfsp_curleaf].file = 0;
1661  target->hfsp_leafs[target->hfsp_curleaf].cat_id = 1;
1662  target->hfsp_leafs[target->hfsp_curleaf].parent_id = 2;
1663  target->hfsp_leafs[target->hfsp_curleaf].unix_type = UNIX_NONE;
1664  target->hfsp_curleaf++;
1665 
1666  dir = (IsoDir*)target->image->root;
1667 
1668  pos = dir->children;
1669  while (pos)
1670  {
1671  int cret;
1672  cret = create_tree(target, pos, 2);
1673  if (cret < 0) {
1674  ret = cret;
1675  goto ex;
1676  }
1677  pos = pos->next;
1678  if (cret > 0)
1679  target->hfsp_leafs[0].nchildren++;
1680  }
1681 
1682  qsort(target->hfsp_leafs, target->hfsp_nleafs,
1683  sizeof(*target->hfsp_leafs), cmp_node);
1684 
1685  ret = mangle_leafs(target, 0);
1686  if (ret < 0)
1687  goto ex;
1688 
1689  for (max_levels = 0; target->hfsp_nleafs >> max_levels; max_levels++);
1690  max_levels += 2;
1691  target->hfsp_levels = calloc (max_levels, sizeof (target->hfsp_levels[0]));
1692  if (target->hfsp_levels == NULL) {
1693  ret = ISO_OUT_OF_MEM;
1694  goto ex;
1695  }
1696 
1697  target->hfsp_nnodes = 1;
1698  {
1699  uint32_t last_start = 0;
1700  uint32_t i;
1701  unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
1702 
1703  target->hfsp_levels[level].nodes = calloc ((target->hfsp_nleafs + 1), sizeof (target->hfsp_levels[level].nodes[0]));
1704  if (!target->hfsp_levels[level].nodes) {
1705  ret = ISO_OUT_OF_MEM;
1706  goto ex;
1707  }
1708  target->hfsp_levels[level].level_size = 0;
1709  for (i = 0; i < target->hfsp_nleafs; i++)
1710  {
1711  if (bytes_rem < target->hfsp_leafs[i].used_size)
1712  {
1713  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start;
1714  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start;
1715  if (target->hfsp_leafs[last_start].cmp_name)
1716  {
1717  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_leafs[last_start].strlen;
1718  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_leafs[last_start].name;
1719  }
1720  else
1721  {
1722  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = 0;
1723  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = NULL;
1724  }
1725  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id;
1726  target->hfsp_levels[level].level_size++;
1727  last_start = i;
1728  bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
1729  }
1730  bytes_rem -= target->hfsp_leafs[i].used_size;
1731  }
1732 
1733  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start;
1734  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start;
1735  if (target->hfsp_leafs[last_start].cmp_name)
1736  {
1737  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_leafs[last_start].strlen;
1738  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_leafs[last_start].name;
1739  }
1740  else
1741  {
1742  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = 0;
1743  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = NULL;
1744  }
1745  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id;
1746  target->hfsp_levels[level].level_size++;
1747  target->hfsp_nnodes += target->hfsp_levels[level].level_size;
1748  }
1749 
1750  while (target->hfsp_levels[level].level_size > 1)
1751  {
1752  uint32_t last_start = 0;
1753  uint32_t i;
1754  uint32_t last_size;
1755  unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
1756 
1757  last_size = target->hfsp_levels[level].level_size;
1758 
1759  level++;
1760 
1761  target->hfsp_levels[level].nodes = calloc (((last_size + 1) / 2), sizeof (target->hfsp_levels[level].nodes[0]));
1762  if (!target->hfsp_levels[level].nodes) {
1763  ret = ISO_OUT_OF_MEM;
1764  goto ex;
1765  }
1766 
1767  target->hfsp_levels[level].level_size = 0;
1768 
1769  for (i = 0; i < last_size; i++)
1770  {
1771  uint32_t used_size;
1772  used_size = target->hfsp_levels[level - 1].nodes[i].strlen * 2 + 14;
1773  if (bytes_rem < used_size)
1774  {
1775  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start;
1776  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start;
1777  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_levels[level - 1].nodes[last_start].strlen;
1778  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_levels[level - 1].nodes[last_start].str;
1779  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id;
1780  target->hfsp_levels[level].level_size++;
1781  last_start = i;
1782  bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
1783  }
1784  bytes_rem -= used_size;
1785  }
1786 
1787  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].start = last_start;
1788  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].cnt = i - last_start;
1789  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].strlen = target->hfsp_levels[level - 1].nodes[last_start].strlen;
1790  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].str = target->hfsp_levels[level - 1].nodes[last_start].str;
1791  target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id;
1792  target->hfsp_levels[level].level_size++;
1793  target->hfsp_nnodes += target->hfsp_levels[level].level_size;
1794  }
1795 
1796  target->hfsp_nlevels = level + 1;
1797 
1798  if (target->hfsp_nnodes > (cat_node_size - 0x100) * 8)
1799  {
1801  "HFS+ map nodes aren't implemented");
1803  goto ex;
1804  }
1805 
1806  /* add this writer to image */
1807  target->writers[target->nwriters++] = writer;
1808  writer = NULL;
1809 
1810  ret = ISO_SUCCESS;
1811 ex:;
1812  if (writer != NULL)
1813  free(writer);
1814  return ret;
1815 }
void iso_setup_hfsplus_block_size(Ecma119Image *target)
Definition: hfsplus.c:1582
static int hfsplus_writer_free_data(IsoImageWriter *writer)
Definition: hfsplus.c:1107
static int hfsplus_writer_write_data(IsoImageWriter *writer)
Definition: hfsplus.c:673
static int cmp_node(const void *f1, const void *f2)
Definition: hfsplus.c:416
static int mangle_leafs(Ecma119Image *target, int flag)
Definition: hfsplus.c:1467
static int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
Definition: hfsplus.c:494
void make_hfsplus_class_pages()
void make_hfsplus_decompose_pages()
#define ISO_HFSPLUS_TOO_MANY_FILES
Too many files in HFS+ directory tree (FAILURE, HIGH, -422)
Definition: libisofs.h:9246
char * volume_id
Volume identifier.
Definition: image.h:47
IsoDir * root
Definition: image.h:43
uint32_t hfsp_nlevels
Definition: ecma119.h:656
struct hfsplus_btree_level * hfsp_levels
Definition: ecma119.h:655
int hfsp_cat_node_size
Definition: ecma119.h:839
struct hfsplus_btree_node * nodes
Definition: hfsplus.h:42
uint32_t level_size
Definition: hfsplus.h:41
uint32_t strlen
Definition: hfsplus.h:34
uint16_t * str
Definition: hfsplus.h:35
uint32_t cnt
Definition: hfsplus.h:33
uint32_t start
Definition: hfsplus.h:32
uint32_t parent_id
Definition: hfsplus.h:36

References hfsplus_node::cat_id, Iso_Dir::children, hfsplus_node::cmp_name, cmp_node(), hfsplus_btree_node::cnt, Iso_Image_Writer::compute_data_blocks, create_tree(), Iso_Image_Writer::data, hfsplus_node::file, Iso_Image_Writer::free_data, ecma119_image::hfsp_bless_id, ecma119_image::hfsp_cat_id, ecma119_image::hfsp_cat_node_size, ecma119_image::hfsp_curleaf, ecma119_image::hfsp_leafs, ecma119_image::hfsp_levels, ecma119_image::hfsp_ndirs, ecma119_image::hfsp_nfiles, ecma119_image::hfsp_nleafs, ecma119_image::hfsp_nlevels, ecma119_image::hfsp_nnodes, hfsplus_count_tree(), HFSPLUS_DIR, HFSPLUS_DIR_THREAD, hfsplus_writer_compute_data_blocks(), hfsplus_writer_free_data(), hfsplus_writer_write_data(), Iso_Image::id, ecma119_image::image, ISO_HFSPLUS_BLESS_MAX, ISO_HFSPLUS_TOO_MANY_FILES, iso_msg_debug(), iso_msg_submit(), ISO_OUT_OF_MEM, iso_setup_hfsplus_block_size(), ISO_SUCCESS, hfsplus_btree_level::level_size, make_hfsplus_class_pages(), make_hfsplus_decompose_pages(), mangle_leafs(), hfsplus_node::name, hfsplus_node::nchildren, Iso_Node::next, hfsplus_node::node, hfsplus_btree_level::nodes, nop_writer_write_vol_desc(), ecma119_image::nwriters, hfsplus_btree_node::parent_id, hfsplus_node::parent_id, Iso_Image::root, set_hfsplus_name(), hfsplus_btree_node::start, hfsplus_btree_node::str, hfsplus_btree_node::strlen, hfsplus_node::strlen, Iso_Image_Writer::target, hfsplus_node::type, hfsplus_node::unix_type, hfsplus_node::used_size, Iso_Image::volume_id, Iso_Image_Writer::write_data, Iso_Image_Writer::write_vol_desc, and ecma119_image::writers.

Referenced by ecma119_image_new().

◆ hfsplus_writer_free_data()

static int hfsplus_writer_free_data ( IsoImageWriter writer)
static

Definition at line 1107 of file hfsplus.c.

1108 {
1109  /* free the Hfsplus tree */
1110  Ecma119Image *t = writer->target;
1111  uint32_t i;
1112  for (i = 0; i < t->hfsp_curleaf; i++)
1113  if (t->hfsp_leafs[i].type != HFSPLUS_FILE_THREAD
1114  && t->hfsp_leafs[i].type != HFSPLUS_DIR_THREAD)
1115  {
1116  free (t->hfsp_leafs[i].name);
1117  free (t->hfsp_leafs[i].cmp_name);
1118  if (t->hfsp_leafs[i].symlink_dest != NULL)
1119  free (t->hfsp_leafs[i].symlink_dest);
1120  }
1121  free(t->hfsp_leafs);
1122  for (i = 0; i < t->hfsp_nlevels; i++)
1123  free (t->hfsp_levels[i].nodes);
1124  free(t->hfsp_levels);
1125  return ISO_SUCCESS;
1126 }

References hfsplus_node::cmp_name, ecma119_image::hfsp_curleaf, ecma119_image::hfsp_leafs, ecma119_image::hfsp_levels, ecma119_image::hfsp_nlevels, HFSPLUS_DIR_THREAD, HFSPLUS_FILE_THREAD, ISO_SUCCESS, hfsplus_node::name, hfsplus_btree_level::nodes, hfsplus_node::symlink_dest, Iso_Image_Writer::target, and hfsplus_node::type.

Referenced by hfsplus_writer_create().

◆ hfsplus_writer_write_data()

static int hfsplus_writer_write_data ( IsoImageWriter writer)
static

Definition at line 673 of file hfsplus.c.

674 {
675  int ret;
676  static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
677  Ecma119Image *t;
678  struct hfsplus_btnode *node_head;
679  struct hfsplus_btheader *tree_head;
680  int level;
681  uint32_t curpos = 1, i, block_fac, cat_node_size, block_size;
682 
683  if (writer == NULL) {
684  return ISO_NULL_POINTER;
685  }
686 
687  t = writer->target;
688  block_size = t->opts->hfsp_block_size;
689  block_fac = t->hfsp_iso_block_fac;
690  cat_node_size = t->hfsp_cat_node_size;
691 
692  iso_msg_debug(t->image->id, "(b) %d written", (int) t->bytes_written / 0x800);
693 
694  ret = write_sb (t);
695  if (ret < 0)
696  return ret;
697 
698  iso_msg_debug(t->image->id, "(c) %d written", (int) t->bytes_written / 0x800);
699 
700  iso_msg_debug(t->image->id, "real catalog_file_start = %d\n", (int)t->bytes_written / 2048);
701 
702  memset (buffer, 0, sizeof (buffer));
703  node_head = (struct hfsplus_btnode *) buffer;
704  node_head->type = 1;
705  iso_msb ((uint8_t *) &node_head->count, 3, 2);
706  tree_head = (struct hfsplus_btheader *) (node_head + 1);
707  iso_msb ((uint8_t *) &tree_head->depth, t->hfsp_nlevels, 2);
708  iso_msb ((uint8_t *) &tree_head->root, 1, 4);
709  iso_msb ((uint8_t *) &tree_head->leaf_records, t->hfsp_nleafs, 4);
710  iso_msb ((uint8_t *) &tree_head->first_leaf_node, t->hfsp_nnodes - t->hfsp_levels[0].level_size, 4);
711  iso_msb ((uint8_t *) &tree_head->last_leaf_node, t->hfsp_nnodes - 1, 4);
712  iso_msb ((uint8_t *) &tree_head->nodesize, cat_node_size, 2);
713  iso_msb ((uint8_t *) &tree_head->keysize, 6 + 2 * LIBISO_HFSPLUS_NAME_MAX, 2);
714  iso_msb ((uint8_t *) &tree_head->total_nodes, t->hfsp_nnodes, 4);
715  iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
716  iso_msb ((uint8_t *) &tree_head->clump_size, cat_node_size, 4);
717  tree_head->key_compare = 0xcf;
718  iso_msb ((uint8_t *) &tree_head->attributes, 2 | 4, 4);
719  memset (buffer + 0xf8, -1, t->hfsp_nnodes / 8);
720  buffer[0xf8 + (t->hfsp_nnodes / 8)] = 0xff00 >> (t->hfsp_nnodes % 8);
721 
722  buffer[cat_node_size - 1] = sizeof (*node_head);
723  buffer[cat_node_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
724  buffer[cat_node_size - 5] = (char) 0xf8;
725  buffer[cat_node_size - 7] = (char) ((cat_node_size - 8) & 0xff);
726  buffer[cat_node_size - 8] = (cat_node_size - 8) >> 8;
727 
728 #ifdef Libisofs_hfsplus_verbose_debuG
729  iso_msg_debug(t->image->id, "Write\n");
730 #endif
731 
732  ret = iso_write(t, buffer, cat_node_size);
733  if (ret < 0)
734  return ret;
735 
736  for (level = t->hfsp_nlevels - 1; level > 0; level--)
737  {
738  uint32_t i;
739  uint32_t next_lev = curpos + t->hfsp_levels[level].level_size;
740  for (i = 0; i < t->hfsp_levels[level].level_size; i++)
741  {
742  uint32_t curoff;
743  uint32_t j;
744  uint32_t curnode = t->hfsp_levels[level].nodes[i].start;
745  memset (buffer, 0, sizeof (buffer));
746  node_head = (struct hfsplus_btnode *) buffer;
747  if (i != t->hfsp_levels[level].level_size - 1)
748  iso_msb ((uint8_t *) &node_head->next, curpos + i + 1, 4);
749  if (i != 0)
750  iso_msb ((uint8_t *) &node_head->prev, curpos + i - 1, 4);
751  node_head->type = 0;
752  node_head->height = level + 1;
753  iso_msb ((uint8_t *) &node_head->count, t->hfsp_levels[level].nodes[i].cnt, 2);
754  curoff = sizeof (struct hfsplus_btnode);
755  for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
756  {
757  iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
758 
759  iso_msb ((uint8_t *) buffer + curoff, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen + 6, 2);
760  iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_levels[level - 1].nodes[curnode].parent_id, 4);
761  iso_msb ((uint8_t *) buffer + curoff + 6, t->hfsp_levels[level - 1].nodes[curnode].strlen, 2);
762  curoff += 8;
763  memcpy ((uint8_t *) buffer + curoff, t->hfsp_levels[level - 1].nodes[curnode].str, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen);
764  curoff += 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen;
765  iso_msb ((uint8_t *) buffer + curoff, next_lev + curnode, 4);
766  curoff += 4;
767  curnode++;
768  }
769  iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
770 
771 #ifdef Libisofs_hfsplus_verbose_debuG
772  iso_msg_debug(t->image->id, "Write\n");
773 #endif
774 
775  ret = iso_write(t, buffer, cat_node_size);
776 
777  if (ret < 0)
778  return ret;
779  }
780  curpos = next_lev;
781  }
782 
783  {
784  uint32_t i;
785  uint32_t next_lev = curpos + t->hfsp_levels[level].level_size;
786  for (i = 0; i < t->hfsp_levels[level].level_size; i++)
787  {
788  uint32_t curoff;
789  uint32_t j;
790  uint32_t curnode = t->hfsp_levels[level].nodes[i].start;
791  memset (buffer, 0, sizeof (buffer));
792  node_head = (struct hfsplus_btnode *) buffer;
793  if (i != t->hfsp_levels[level].level_size - 1)
794  iso_msb ((uint8_t *) &node_head->next, curpos + i + 1, 4);
795  if (i != 0)
796  iso_msb ((uint8_t *) &node_head->prev, curpos + i - 1, 4);
797  node_head->type = -1;
798  node_head->height = level + 1;
799  iso_msb ((uint8_t *) &node_head->count, t->hfsp_levels[level].nodes[i].cnt, 2);
800  curoff = sizeof (struct hfsplus_btnode);
801  for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
802  {
803  iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
804 
805 #ifdef Libisofs_hfsplus_verbose_debuG
806 
807  if (t->hfsp_leafs[curnode].node->name == NULL)
808  {
809  iso_msg_debug(t->image->id, "%d out of %d",
810  (int) curnode, t->hfsp_nleafs);
811  }
812  else
813  {
814  iso_msg_debug(t->image->id, "%d out of %d, %s",
815  (int) curnode, t->hfsp_nleafs,
816  t->hfsp_leafs[curnode].node->name);
817  }
818 
819 #endif /* Libisofs_hfsplus_verbose_debuG */
820 
821  switch (t->hfsp_leafs[curnode].type)
822  {
823  case HFSPLUS_FILE_THREAD:
824  case HFSPLUS_DIR_THREAD:
825  {
826  struct hfsplus_catfile_thread *thread;
827  iso_msb ((uint8_t *) buffer + curoff, 6, 2);
828  iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_leafs[curnode].parent_id, 4);
829  iso_msb ((uint8_t *) buffer + curoff + 6, 0, 2);
830  curoff += 8;
831  thread = (struct hfsplus_catfile_thread *) (buffer + curoff);
832  ((uint8_t *) &thread->type)[1] = t->hfsp_leafs[curnode].type;
833  iso_msb ((uint8_t *) &thread->parentid, t->hfsp_leafs[curnode].cat_id, 4);
834  iso_msb ((uint8_t *) &thread->namelen, t->hfsp_leafs[curnode].strlen, 2);
835  curoff += sizeof (*thread);
836  memcpy (buffer + curoff, t->hfsp_leafs[curnode].name, t->hfsp_leafs[curnode].strlen * 2);
837  curoff += t->hfsp_leafs[curnode].strlen * 2;
838  break;
839  }
840  case HFSPLUS_FILE:
841  case HFSPLUS_DIR:
842  {
843  struct hfsplus_catfile_common *common;
844  struct hfsplus_forkdata *data_fork;
845  iso_msb ((uint8_t *) buffer + curoff, 6 + 2 * t->hfsp_leafs[curnode].strlen, 2);
846  iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_leafs[curnode].parent_id, 4);
847  iso_msb ((uint8_t *) buffer + curoff + 6, t->hfsp_leafs[curnode].strlen, 2);
848  curoff += 8;
849  memcpy (buffer + curoff, t->hfsp_leafs[curnode].name, t->hfsp_leafs[curnode].strlen * 2);
850  curoff += t->hfsp_leafs[curnode].strlen * 2;
851 
852  common = (struct hfsplus_catfile_common *) (buffer + curoff);
853  ((uint8_t *) &common->type)[1] = t->hfsp_leafs[curnode].type;
854  iso_msb ((uint8_t *) &common->valence, t->hfsp_leafs[curnode].nchildren, 4);
855  iso_msb ((uint8_t *) &common->fileid, t->hfsp_leafs[curnode].cat_id, 4);
856  common->ctime = mac_time_offset(t->hfsp_leafs[curnode].node->ctime);
857  common->mtime = mac_time_offset(t->hfsp_leafs[curnode].node->mtime);
858  /* FIXME: distinguish attr_mtime and mtime. */
859  common->attr_mtime = mac_time_offset(t->hfsp_leafs[curnode].node->mtime);
860  common->atime = mac_time_offset(t->hfsp_leafs[curnode].node->atime);
861  iso_msb ((uint8_t *) &common->uid, px_get_uid (t, t->hfsp_leafs[curnode].node), 4);
862  iso_msb ((uint8_t *) &common->gid, px_get_gid (t, t->hfsp_leafs[curnode].node), 4);
863  iso_msb ((uint8_t *) &common->mode, px_get_mode (t, t->hfsp_leafs[curnode].node, (t->hfsp_leafs[curnode].type == HFSPLUS_DIR)), 2);
864 
865  /*
866  FIXME:
867  uint8_t user_flags;
868  uint8_t group_flags;
869 
870  finder info
871  */
872  if (t->hfsp_leafs[curnode].type == HFSPLUS_FILE)
873  {
874  if (t->hfsp_leafs[curnode].unix_type == UNIX_SYMLINK)
875  {
876  memcpy (common->file_type, "slnk", 4);
877  memcpy (common->file_creator, "rhap", 4);
878  }
879  else
880  {
881  struct iso_hfsplus_xinfo_data *xinfo;
882  ret = iso_node_get_xinfo(t->hfsp_leafs[curnode].node,
884  (void *) &xinfo);
885  if (ret > 0)
886  {
887  memcpy (common->file_type, xinfo->type_code,
888  4);
889  memcpy (common->file_creator,
890  xinfo->creator_code, 4);
891 
892 #ifdef Libisofs_ts_debuG
893 {
894 char crtp[14];
895 
896 crtp[0] = '\'';
897 memcpy(crtp+1, xinfo->creator_code, 4);
898 strcpy(crtp + 5, "','");
899 memcpy(crtp + 8, xinfo->type_code, 4);
900 crtp[12] = '\'';
901 crtp[13]= 0;
903  "hfsplus creator,type %s to '%s/%s'",
904  crtp, ((IsoNode *) t->hfsp_leafs[curnode].node->parent)->name,
905  t->hfsp_leafs[curnode].node->name);
906 }
907 #endif /* Libisofs_ts_debuG */
908 
909  }
910  else if (ret < 0)
911  return ret;
912  else
913  {
914  memcpy (common->file_type, "????", 4);
915  memcpy (common->file_creator, "????", 4);
916  }
917  }
918 
919  if (t->hfsp_leafs[curnode].unix_type == UNIX_SPECIAL
920  && (S_ISBLK(t->hfsp_leafs[curnode].node->mode)
921  || S_ISCHR(t->hfsp_leafs[curnode].node->mode)))
922  iso_msb ((uint8_t *) &common->special,
923  (((IsoSpecial*) t->hfsp_leafs[curnode].node)->dev & 0xffffffff),
924  4);
925 
926  iso_msb ((uint8_t *) &common->flags, 2, 2);
927  }
928  else if (t->hfsp_leafs[curnode].type == HFSPLUS_DIR)
929  {
930  iso_msb ((uint8_t *) &common->flags, 0, 2);
931  }
932  curoff += sizeof (*common);
933  if (t->hfsp_leafs[curnode].type == HFSPLUS_FILE)
934  {
935  uint64_t sz;
936  uint32_t blk;
937  data_fork = (struct hfsplus_forkdata *) (buffer + curoff);
938 
939  if (t->hfsp_leafs[curnode].unix_type == UNIX_SYMLINK)
940  {
941  blk = t->hfsp_leafs[curnode].symlink_block;
942  sz = strlen(t->hfsp_leafs[curnode].symlink_dest);
943  }
944  else if (t->hfsp_leafs[curnode].unix_type == UNIX_SPECIAL)
945  {
946  blk = 0;
947  sz = 0;
948  }
949  else
950  {
951  ret = filesrc_block_and_size(t,
952  t->hfsp_leafs[curnode].file,
953  &blk, &sz);
954  if (ret <= 0)
955  return ret;
956  blk *= block_fac;
957  }
958  if (sz == 0)
959  blk = t->hfsp_part_start;
960  iso_msb ((uint8_t *) &data_fork->size, sz >> 32, 4);
961  iso_msb ((uint8_t *) &data_fork->size + 4, sz, 4);
962  iso_msb ((uint8_t *) &data_fork->clumpsize, block_size, 4);
963  iso_msb ((uint8_t *) &data_fork->blocks, (sz + block_size - 1) / block_size, 4);
964  iso_msb ((uint8_t *) &data_fork->extents[0].start, blk - t->hfsp_part_start, 4);
965  iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + block_size - 1) / block_size, 4);
966 
967  curoff += sizeof (*data_fork) * 2;
968  /* FIXME: resource fork */
969  }
970  break;
971  }
972  }
973  curnode++;
974  }
975  iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
976 
977 #ifdef Libisofs_hfsplus_verbose_debuG
978  iso_msg_debug(t->image->id, "Write\n");
979 #endif
980 
981  ret = iso_write(t, buffer, cat_node_size);
982  if (ret < 0)
983  return ret;
984  }
985  curpos = next_lev;
986  }
987  memset (buffer, 0, sizeof (buffer));
988 
989  iso_msg_debug(t->image->id, "real extent_file_start = %d\n", (int)t->bytes_written / 2048);
990 
991  node_head = (struct hfsplus_btnode *) buffer;
992  node_head->type = 1;
993  iso_msb ((uint8_t *) &node_head->count, 3, 2);
994  tree_head = (struct hfsplus_btheader *) (node_head + 1);
995  iso_msb ((uint8_t *) &tree_head->nodesize, block_size, 2);
996  iso_msb ((uint8_t *) &tree_head->keysize, 10, 2);
997  iso_msb ((uint8_t *) &tree_head->total_nodes, 1, 4);
998  iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
999  iso_msb ((uint8_t *) &tree_head->clump_size, block_size, 4);
1000  iso_msb ((uint8_t *) &tree_head->attributes, 2, 4);
1001  buffer[0xf8] = (char) 0x80;
1002 
1003  buffer[block_size - 1] = sizeof (*node_head);
1004  buffer[block_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
1005  buffer[block_size - 5] = (char) 0xf8;
1006  buffer[block_size - 7] = (char) ((block_size - 8) & 0xff);
1007  buffer[block_size - 8] = (block_size - 8) >> 8;
1008 
1009  ret = iso_write(t, buffer, block_size);
1010  if (ret < 0)
1011  return ret;
1012 
1013  iso_msg_debug(t->image->id, "(d) %d written", (int) t->bytes_written / 0x800);
1014  memset (buffer, 0, sizeof (buffer));
1015  for (i = 0; i < t->hfsp_nleafs; i++)
1016  if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK)
1017  {
1018  int overhead;
1019 
1020  ret = iso_write(t, t->hfsp_leafs[i].symlink_dest,
1021  strlen(t->hfsp_leafs[i].symlink_dest));
1022  if (ret < 0)
1023  return ret;
1024  overhead = strlen(t->hfsp_leafs[i].symlink_dest) % block_size;
1025  if (overhead)
1026  overhead = block_size - overhead;
1027  ret = iso_write(t, buffer, overhead);
1028  if (ret < 0)
1029  return ret;
1030  }
1031 
1032  /* Need to align for start of next writer */
1033  ret = pad_up_block(t);
1034  if (ret < 0)
1035  return ret;
1036 
1037  iso_msg_debug(t->image->id, "(a) %d written", (int) t->bytes_written / 0x800);
1038  return ISO_SUCCESS;
1039 }
static uid_t px_get_uid(Ecma119Image *t, IsoNode *n)
Definition: hfsplus.c:560
static int filesrc_block_and_size(Ecma119Image *t, IsoFileSrc *src, uint32_t *start_block, uint64_t *total_size)
Definition: hfsplus.c:79
static uid_t px_get_gid(Ecma119Image *t, IsoNode *n)
Definition: hfsplus.c:570
static uint32_t mac_time_offset(uint32_t t)
Definition: hfsplus.c:546
int iso_hfsplus_xinfo_func(void *data, int flag)
The function that is used to mark struct iso_hfsplus_xinfo_data at IsoNodes and finally disposes such...
Definition: hfsplus.c:1841
static mode_t px_get_mode(Ecma119Image *t, IsoNode *n, int isdir)
Definition: hfsplus.c:580
#define LIBISO_HFSPLUS_NAME_MAX
Declare HFS+ related structures.
Definition: hfsplus.h:20
int iso_node_get_xinfo(IsoNode *node, iso_node_xinfo_func proc, void **data)
Get the given extended info (defined by the proc function) from the given node.
Definition: node.c:213
time_t ctime
time of last status change
Definition: node.h:122
time_t atime
time of last access
Definition: node.h:120
IsoDir * parent
parent node, NULL for root
Definition: node.h:126
mode_t mode
protection
Definition: node.h:115
time_t mtime
time of last modification
Definition: node.h:121
uint16_t nodesize
Definition: hfsplus.h:143
uint32_t root
Definition: hfsplus.h:139
uint32_t attributes
Definition: hfsplus.h:151
uint16_t depth
Definition: hfsplus.h:138
uint32_t leaf_records
Definition: hfsplus.h:140
uint32_t first_leaf_node
Definition: hfsplus.h:141
uint32_t total_nodes
Definition: hfsplus.h:145
uint32_t last_leaf_node
Definition: hfsplus.h:142
uint8_t key_compare
Definition: hfsplus.h:150
uint32_t free_nodes
Definition: hfsplus.h:146
uint16_t keysize
Definition: hfsplus.h:144
uint32_t clump_size
Definition: hfsplus.h:148
uint8_t height
Definition: hfsplus.h:130
uint32_t prev
Definition: hfsplus.h:128
int8_t type
Definition: hfsplus.h:129
uint16_t count
Definition: hfsplus.h:131
uint32_t next
Definition: hfsplus.h:127
uint8_t file_creator[4]
Definition: hfsplus.h:181
uint8_t file_type[4]
Definition: hfsplus.h:180
uint32_t count
Definition: hfsplus.h:77
uint32_t start
Definition: hfsplus.h:75
uint32_t blocks
Definition: hfsplus.h:84
struct hfsplus_extent extents[8]
Definition: hfsplus.h:85
uint32_t clumpsize
Definition: hfsplus.h:83
uint64_t size
Definition: hfsplus.h:82
HFS+ attributes which may be attached to IsoNode objects as data parameter of iso_node_add_xinfo().
Definition: libisofs.h:8539
uint8_t creator_code[4]
Definition: libisofs.h:8548
uint8_t type_code[4]
Definition: libisofs.h:8549
void iso_msb(uint8_t *buf, uint32_t num, int bytes)
Definition: util.c:1494

References hfsplus_catfile_common::atime, Iso_Node::atime, hfsplus_catfile_common::attr_mtime, hfsplus_btheader::attributes, hfsplus_forkdata::blocks, ecma119_image::bytes_written, hfsplus_node::cat_id, hfsplus_btheader::clump_size, hfsplus_forkdata::clumpsize, hfsplus_btree_node::cnt, hfsplus_extent::count, hfsplus_btnode::count, iso_hfsplus_xinfo_data::creator_code, hfsplus_catfile_common::ctime, Iso_Node::ctime, hfsplus_btheader::depth, hfsplus_forkdata::extents, hfsplus_node::file, hfsplus_catfile_common::file_creator, hfsplus_catfile_common::file_type, hfsplus_catfile_common::fileid, filesrc_block_and_size(), hfsplus_btheader::first_leaf_node, hfsplus_catfile_common::flags, hfsplus_btheader::free_nodes, hfsplus_catfile_common::gid, hfsplus_btnode::height, iso_write_opts::hfsp_block_size, ecma119_image::hfsp_cat_node_size, ecma119_image::hfsp_iso_block_fac, ecma119_image::hfsp_leafs, ecma119_image::hfsp_levels, ecma119_image::hfsp_nleafs, ecma119_image::hfsp_nlevels, ecma119_image::hfsp_nnodes, ecma119_image::hfsp_part_start, HFSPLUS_DIR, HFSPLUS_DIR_THREAD, HFSPLUS_FILE, HFSPLUS_FILE_THREAD, HFSPLUS_MAX_BLOCK_SIZE, Iso_Image::id, ecma119_image::image, iso_hfsplus_xinfo_func(), iso_msb(), iso_msg_debug(), iso_node_get_xinfo(), ISO_NULL_POINTER, ISO_SUCCESS, iso_write(), hfsplus_btheader::key_compare, hfsplus_btheader::keysize, hfsplus_btheader::last_leaf_node, hfsplus_btheader::leaf_records, hfsplus_btree_level::level_size, LIBISO_HFSPLUS_NAME_MAX, mac_time_offset(), hfsplus_catfile_common::mode, Iso_Node::mode, hfsplus_catfile_common::mtime, Iso_Node::mtime, hfsplus_node::name, Iso_Node::name, hfsplus_catfile_thread::namelen, hfsplus_node::nchildren, hfsplus_btnode::next, hfsplus_node::node, hfsplus_btree_level::nodes, hfsplus_btheader::nodesize, ecma119_image::opts, pad_up_block(), Iso_Node::parent, hfsplus_btree_node::parent_id, hfsplus_node::parent_id, hfsplus_catfile_thread::parentid, hfsplus_btnode::prev, px_get_gid(), px_get_mode(), px_get_uid(), hfsplus_btheader::root, hfsplus_forkdata::size, hfsplus_catfile_common::special, hfsplus_btree_node::start, hfsplus_extent::start, hfsplus_btree_node::str, hfsplus_btree_node::strlen, hfsplus_node::strlen, hfsplus_node::symlink_block, hfsplus_node::symlink_dest, Iso_Image_Writer::target, hfsplus_btheader::total_nodes, hfsplus_node::type, hfsplus_btnode::type, hfsplus_catfile_thread::type, hfsplus_catfile_common::type, iso_hfsplus_xinfo_data::type_code, hfsplus_catfile_common::uid, hfsplus_node::unix_type, hfsplus_catfile_common::valence, and write_sb().

Referenced by hfsplus_writer_create().

◆ iso_get_hfsplus_name()

int iso_get_hfsplus_name ( char *  input_charset,
int  imgid,
char *  name,
uint16_t **  result,
uint32_t *  result_len,
uint16_t **  cmp_name 
)

Definition at line 118 of file hfsplus.c.

120 {
121  int ret;
122  uint16_t *ucs_name, *iptr, *optr;
123  uint32_t curlen;
124  int done;
125 
126  if (name == NULL) {
127  /* it is not necessarily an error, it can be the root */
128  return ISO_SUCCESS;
129  }
130 
131  ret = str2utf16be(input_charset, name, &ucs_name);
132  if (ret < 0) {
133  iso_msg_debug(imgid, "Cannot convert '%s'", name);
134  return ret;
135  }
136 
137  curlen = ucslen (ucs_name);
138  *result = calloc ((curlen * HFSPLUS_MAX_DECOMPOSE_LEN + 1),
139  sizeof (uint16_t));
140  if (*result == NULL) {
141  free(ucs_name);
142  return ISO_OUT_OF_MEM;
143  }
144 
145  for (iptr = ucs_name, optr = *result; *iptr; iptr++)
146  {
147  const uint16_t *dptr;
148  uint16_t val = iso_ntohs (*iptr);
149  uint8_t high = val >> 8;
150  uint8_t low = val & 0xff;
151 
152  if (val == ':')
153  {
154  *optr++ = iso_htons ('/');
155  continue;
156  }
157 
158  if (val >= 0xac00 && val <= 0xd7a3)
159  {
160  uint16_t s, l, v, t;
161  s = val - 0xac00;
162  l = s / (21 * 28);
163  v = (s % (21 * 28)) / 28;
164  t = s % 28;
165  *optr++ = iso_htons (l + 0x1100);
166  *optr++ = iso_htons (v + 0x1161);
167  if (t)
168  *optr++ = iso_htons (t + 0x11a7);
169  continue;
170  }
171  if (!hfsplus_decompose_pages[high])
172  {
173  *optr++ = *iptr;
174  continue;
175  }
176  dptr = hfsplus_decompose_pages[high][low];
177  if (!dptr[0])
178  {
179  *optr++ = *iptr;
180  continue;
181  }
182  for (; *dptr; dptr++)
183  *optr++ = iso_htons (*dptr);
184  }
185  *optr = 0;
186 
187  do
188  {
189  uint8_t last_class;
190  done = 0;
191  if (!ucs_name[0])
192  break;
193  last_class = get_class (ucs_name[0]);
194  for (optr = *result + 1; *optr; optr++)
195  {
196  uint8_t new_class = get_class (*optr);
197 
198  if (last_class == 0 || new_class == 0
199  || last_class <= new_class)
200  last_class = new_class;
201  else
202  {
203  uint16_t t;
204  t = *(optr - 1);
205  *(optr - 1) = *optr;
206  *optr = t;
207  }
208  }
209  }
210  while (done);
211 
212  *cmp_name = calloc ((ucslen (*result) + 1), sizeof (uint16_t));
213  if (*cmp_name == NULL) {
214  free(ucs_name);
215  free(*result);
216  *result = NULL;
217  return ISO_OUT_OF_MEM;
218  }
219 
220  for (iptr = *result, optr = *cmp_name; *iptr; iptr++)
221  {
222  *optr = iso_hfsplus_cichar(*iptr);
223  if (*optr != 0)
224  optr++;
225  }
226  *optr = 0;
227 
228  free (ucs_name);
229 
230  *result_len = ucslen (*result);
231  return ISO_SUCCESS;
232 }
uint16_t iso_hfsplus_cichar(uint16_t x)
Definition: hfsplus_case.c:444
static uint8_t get_class(uint16_t v)
Definition: hfsplus.c:106
#define HFSPLUS_MAX_DECOMPOSE_LEN
Definition: hfsplus.h:187
uint16_t(*[256] hfsplus_decompose_pages)[4+1]
int str2utf16be(const char *icharset, const char *input, uint16_t **output)
Convert a given string from any input charset to UTF-16BE charset, used for HFS+ file identifiers.
Definition: util.c:687
uint16_t iso_htons(uint16_t v)
Definition: util.c:2313
size_t ucslen(const uint16_t *str)
Like strlen, but for Joliet strings.
Definition: util.c:1331

References get_class(), hfsplus_decompose_pages, HFSPLUS_MAX_DECOMPOSE_LEN, iso_hfsplus_cichar(), iso_htons(), iso_msg_debug(), iso_ntohs(), ISO_OUT_OF_MEM, ISO_SUCCESS, str2utf16be(), and ucslen().

Referenced by iso_conv_name_chars(), and set_hfsplus_name().

◆ iso_hfsplus_cichar()

uint16_t iso_hfsplus_cichar ( uint16_t  x)

Definition at line 444 of file hfsplus_case.c.

445 {
446  int page, i;
447  uint16_t ret;
448  uint8_t low, high;
449 
450  high = ((uint8_t *) &x)[0];
451  low = ((uint8_t *) &x)[1];
452 
453  page = what_page(x);
454  if (page < 0)
455  return x; /* No translation needed */
456  if (page == 0)
457  return cmp_name_page0(x); /* Accelerator for ASCII subset */
458 
459  for (i = utf16be_transl_starts[page] * 4; i < utf16be_transl_count * 4;
460  i += 4) {
461  if (utf16be_transl[i] != high)
462  break;
463  if (utf16be_transl[i + 1] == low) {
464  ((uint8_t *) &ret)[0] = utf16be_transl[i + 2];
465  ((uint8_t *) &ret)[1] = utf16be_transl[i + 3];
466  return ret;
467  }
468  }
469  return x;
470 }
static int what_page(uint16_t x)
Definition: hfsplus_case.c:380
static uint8_t utf16be_transl[]
Maps UTF-16BE double-byte characters to the representative of their equivalence class under the relat...
Definition: hfsplus_case.c:35
static int utf16be_transl_count
Definition: hfsplus_case.c:367
static uint16_t cmp_name_page0(uint16_t x)
Definition: hfsplus_case.c:412
static int utf16be_transl_starts[]
Definition: hfsplus_case.c:375

References cmp_name_page0(), utf16be_transl, utf16be_transl_count, utf16be_transl_starts, and what_page().

Referenced by iso_get_hfsplus_name().

◆ iso_hfsplus_xinfo_cloner()

int iso_hfsplus_xinfo_cloner ( void *  old_data,
void **  new_data,
int  flag 
)

Definition at line 1864 of file hfsplus.c.

1865 {
1866  *new_data = NULL;
1867  if (flag)
1868  return ISO_XINFO_NO_CLONE;
1869  if (old_data == NULL)
1870  return 0;
1871  *new_data = iso_hfsplus_xinfo_new(0);
1872  if(*new_data == NULL)
1873  return ISO_OUT_OF_MEM;
1874  memcpy(*new_data, old_data, sizeof(struct iso_hfsplus_xinfo_data));
1875  return ISO_SUCCESS;
1876 }
struct iso_hfsplus_xinfo_data * iso_hfsplus_xinfo_new(int flag)
Create an instance of struct iso_hfsplus_xinfo_new().
Definition: hfsplus.c:1849
#define ISO_XINFO_NO_CLONE
Extended information class offers no cloning method (FAILURE, HIGH, -375)
Definition: libisofs.h:9093

References iso_hfsplus_xinfo_new(), ISO_OUT_OF_MEM, ISO_SUCCESS, and ISO_XINFO_NO_CLONE.

Referenced by iso_init_with_flag().

◆ iso_hfsplus_xinfo_func()

int iso_hfsplus_xinfo_func ( void *  data,
int  flag 
)

The function that is used to mark struct iso_hfsplus_xinfo_data at IsoNodes and finally disposes such structs when their IsoNodes get disposed.

Usually an application does not call this function, but only uses it as parameter of xinfo calls like iso_node_add_xinfo() or iso_node_get_xinfo().

Since
1.2.4

Definition at line 1841 of file hfsplus.c.

1842 {
1843  if (flag == 1 && data != NULL)
1844  free(data);
1845  return 1;
1846 }

Referenced by hfsplus_writer_write_data(), and iso_init_with_flag().

◆ iso_hfsplus_xinfo_new()

struct iso_hfsplus_xinfo_data* iso_hfsplus_xinfo_new ( int  flag)

Create an instance of struct iso_hfsplus_xinfo_new().

Parameters
flagBitfield for control purposes. Unused yet. Submit 0.
Returns
A pointer to the new object NULL indicates failure to allocate memory
Since
1.2.4

Definition at line 1849 of file hfsplus.c.

1850 {
1851  struct iso_hfsplus_xinfo_data *o;
1852 
1853  o = calloc(1, sizeof(struct iso_hfsplus_xinfo_data));
1854  if (o == NULL)
1855  return NULL;
1856  o->version = 0;
1857  return o;
1858 }

References iso_hfsplus_xinfo_data::version.

Referenced by iso_hfsplus_xinfo_cloner().

◆ iso_setup_hfsplus_block_size()

void iso_setup_hfsplus_block_size ( Ecma119Image target)

Definition at line 1582 of file hfsplus.c.

1583 {
1584  if (target->opts->hfsp_block_size == 0)
1586  target->hfsp_cat_node_size = 2 * target->opts->hfsp_block_size;
1587  target->hfsp_iso_block_fac = 2048 / target->opts->hfsp_block_size;
1588 }
#define HFSPLUS_DEFAULT_BLOCK_SIZE
Definition: hfsplus.c:47

References iso_write_opts::hfsp_block_size, ecma119_image::hfsp_cat_node_size, ecma119_image::hfsp_iso_block_fac, HFSPLUS_DEFAULT_BLOCK_SIZE, and ecma119_image::opts.

Referenced by ecma119_image_new(), and hfsplus_writer_create().

◆ mac_time_offset()

static uint32_t mac_time_offset ( uint32_t  t)
inlinestatic

Definition at line 546 of file hfsplus.c.

547 {
548  uint32_t val;
549  iso_msb ((uint8_t *) &val, t + 2082844800, sizeof(val));
550  return val;
551 }

References iso_msb().

Referenced by hfsplus_writer_write_data(), and write_sb().

◆ mangle_leafs()

static int mangle_leafs ( Ecma119Image target,
int  flag 
)
static

Definition at line 1467 of file hfsplus.c.

1468 {
1469  int ret;
1470  uint32_t i, new_idx, prev, first_prev;
1471 
1472  iso_msg_debug(target->image->id, "%s", "HFS+ mangling started ...");
1473 
1474  /* Look for the first owner of a name */
1475  for (prev = 0; prev < target->hfsp_nleafs; prev++) {
1476  if (target->hfsp_leafs[prev].type == HFSPLUS_DIR_THREAD ||
1477  target->hfsp_leafs[prev].type == HFSPLUS_FILE_THREAD ||
1478  target->hfsp_leafs[prev].node == NULL ||
1479  target->hfsp_leafs[prev].name == NULL ||
1480  target->hfsp_leafs[prev].cmp_name == NULL)
1481  continue;
1482  if (target->hfsp_leafs[prev].node->name == NULL)
1483  continue;
1484  break;
1485  }
1486 
1487  first_prev = prev;
1488  for (i = prev + 1; i < target->hfsp_nleafs; i++) {
1489  if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD ||
1490  target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD ||
1491  target->hfsp_leafs[i].node == NULL ||
1492  target->hfsp_leafs[i].name == NULL ||
1493  target->hfsp_leafs[i].cmp_name == NULL)
1494  continue;
1495  if (target->hfsp_leafs[i].node->name == NULL)
1496  continue;
1497  if (cmp_node(&(target->hfsp_leafs[prev]), &(target->hfsp_leafs[i]))
1498  != 0) {
1499  prev = i;
1500  continue;
1501  }
1502  target->hfsp_collision_count++;
1503 
1504 
1505 #ifdef Libisofs_with_mangle_masK
1506 
1507  /* >>> Development sketch: */
1508 
1509  /* >>> define in libisofs.h : enum with LIBISO_NOMANGLE_xyz
1510  xinfo function for uint32_t
1511  */
1512 
1513  /* >>> inquire xinfo for mangle protection : uint32_t mangle_mask */
1514 
1515  if (mangle_mask & (1 << LIBISO_NOMANGLE_HFSPLUS)) {
1516 
1517  /* >>> Get full ISO-RR paths of colliding nodes and print
1518  error message */;
1519 
1520  return ISO_HFSP_NO_MANGLE;
1521  } else {
1522 
1523 #else /* Libisofs_with_mangle_masK */
1524 
1525  {
1526 
1527 #endif /* ! Libisofs_with_mangle_masK */
1528 
1529 
1530  ret= try_mangle(target, i, prev, i + 1, target->hfsp_nleafs,
1531  &new_idx, target->hfsp_leafs[i].node->name, 0);
1532  if (ret == 0)
1533  ret= try_mangle(target, i, prev, 0, target->hfsp_nleafs,
1534  &new_idx, "MANGLED", 0);
1535  if (ret < 0)
1536  return(ret);
1537  if (new_idx > i) {
1538  i--; /* an unprocessed candidate has been rotated to i */
1539  } else {
1540  prev = i; /* advance */
1541  }
1542  }
1543  }
1544 
1545  if (target->hfsp_collision_count > 0) {
1546  /* Mangling cannot be properly performed if the name owners do not
1547  stay in sorting order.
1548  */
1549  prev = first_prev;
1550  for (i = prev + 1; i < target->hfsp_nleafs; i++) {
1551  if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD ||
1552  target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD ||
1553  target->hfsp_leafs[i].node == NULL ||
1554  target->hfsp_leafs[i].name == NULL ||
1555  target->hfsp_leafs[i].cmp_name == NULL)
1556  continue;
1557  if (target->hfsp_leafs[i].node->name == NULL)
1558  continue;
1559  if (cmp_node(&(target->hfsp_leafs[prev]),
1560  &(target->hfsp_leafs[i])) > 0) {
1561 
1562  iso_msg_debug(target->image->id,
1563  "*********** Mangling messed up sorting *************\n");
1564 
1565  break;
1566  }
1567  prev = i;
1568  }
1569 
1570  /* Only the owners of names were considered during mangling.
1571  The HFSPLUS_*_THREAD types must get in line by sorting again.
1572  */
1573  qsort(target->hfsp_leafs, target->hfsp_nleafs,
1574  sizeof(*target->hfsp_leafs), cmp_node);
1575  }
1576  iso_msg_debug(target->image->id,
1577  "HFS+ mangling done. Resolved Collisions: %lu",
1578  (unsigned long) target->hfsp_collision_count);
1579  return ISO_SUCCESS;
1580 }
static int try_mangle(Ecma119Image *target, uint32_t idx, uint32_t prev_idx, uint32_t search_start, uint32_t search_end, uint32_t *new_idx, char *prefix, int flag)
Definition: hfsplus.c:1385
#define ISO_HFSP_NO_MANGLE
Name collision in HFS+, mangling not possible (FAILURE, HIGH, -393)
Definition: libisofs.h:9150
uint32_t hfsp_collision_count
Definition: ecma119.h:671

References hfsplus_node::cmp_name, cmp_node(), ecma119_image::hfsp_collision_count, ecma119_image::hfsp_leafs, ecma119_image::hfsp_nleafs, HFSPLUS_DIR_THREAD, HFSPLUS_FILE_THREAD, Iso_Image::id, ecma119_image::image, ISO_HFSP_NO_MANGLE, iso_msg_debug(), ISO_SUCCESS, hfsplus_node::name, Iso_Node::name, hfsplus_node::node, try_mangle(), and hfsplus_node::type.

Referenced by hfsplus_writer_create().

◆ nop_writer_free_data()

static int nop_writer_free_data ( IsoImageWriter writer)
static

Definition at line 1129 of file hfsplus.c.

1130 {
1131  return ISO_SUCCESS;
1132 }

References ISO_SUCCESS.

Referenced by hfsplus_tail_writer_create().

◆ nop_writer_write_vol_desc()

int nop_writer_write_vol_desc ( IsoImageWriter writer)

Definition at line 554 of file hfsplus.c.

555 {
556  return ISO_SUCCESS;
557 }

References ISO_SUCCESS.

Referenced by hfsplus_tail_writer_create(), and hfsplus_writer_create().

◆ pad_up_block()

static int pad_up_block ( Ecma119Image t)
static

Definition at line 60 of file hfsplus.c.

61 {
62  int ret;
63  static char buffer[2048], buf_zeroed = 0;
64 
65  if (!buf_zeroed) {
66  memset(buffer, 0, 2048);
67  buf_zeroed = 1;
68  }
69  if (t->bytes_written % 2048) {
70  ret = iso_write(t, buffer, 2048 - (t->bytes_written % 2048));
71  if (ret < 0)
72  return ret;
73  }
74  return 1;
75 }

References ecma119_image::bytes_written, and iso_write().

Referenced by hfsplus_tail_writer_write_data(), and hfsplus_writer_write_data().

◆ px_get_gid()

static uid_t px_get_gid ( Ecma119Image t,
IsoNode n 
)
static

Definition at line 570 of file hfsplus.c.

571 {
572  if (t->replace_gid) {
573  return t->gid;
574  } else {
575  return n->gid;
576  }
577 }
gid_t gid
group ID of owner
Definition: node.h:117
gid_t gid
Definition: ecma119.h:585
unsigned int replace_gid
Definition: ecma119.h:578

References ecma119_image::gid, Iso_Node::gid, and ecma119_image::replace_gid.

Referenced by hfsplus_writer_write_data().

◆ px_get_mode()

static mode_t px_get_mode ( Ecma119Image t,
IsoNode n,
int  isdir 
)
static

Definition at line 580 of file hfsplus.c.

581 {
582  if (isdir) {
583  if (t->replace_dir_mode) {
584  return (n->mode & S_IFMT) | t->dir_mode;
585  }
586  } else {
587  if (t->replace_file_mode) {
588  return (n->mode & S_IFMT) | t->file_mode;
589  }
590  }
591  return n->mode;
592 }
mode_t file_mode
Definition: ecma119.h:586
mode_t dir_mode
Definition: ecma119.h:587
unsigned int replace_dir_mode
Definition: ecma119.h:580
unsigned int replace_file_mode
Definition: ecma119.h:579

References ecma119_image::dir_mode, ecma119_image::file_mode, Iso_Node::mode, ecma119_image::replace_dir_mode, and ecma119_image::replace_file_mode.

Referenced by hfsplus_writer_write_data().

◆ px_get_uid()

static uid_t px_get_uid ( Ecma119Image t,
IsoNode n 
)
static

Definition at line 560 of file hfsplus.c.

561 {
562  if (t->replace_uid) {
563  return t->uid;
564  } else {
565  return n->uid;
566  }
567 }
uid_t uid
user ID of owner
Definition: node.h:116
uid_t uid
Definition: ecma119.h:584
unsigned int replace_uid
Definition: ecma119.h:577

References ecma119_image::replace_uid, ecma119_image::uid, and Iso_Node::uid.

Referenced by hfsplus_writer_write_data().

◆ rotate_hfs_list()

static void rotate_hfs_list ( Ecma119Image target,
uint32_t  old_idx,
uint32_t  new_idx,
int  flag 
)
static

Definition at line 1171 of file hfsplus.c.

1173 {
1174  uint32_t i, sz;
1175  HFSPlusNode tr;
1176 
1177  if (old_idx == new_idx)
1178  return;
1179  sz = sizeof(HFSPlusNode);
1180  memcpy(&tr, &target->hfsp_leafs[old_idx], sz);
1181  if (old_idx > new_idx) {
1182  for (i = old_idx; i > new_idx; i--)
1183  memcpy(&target->hfsp_leafs[i], &target->hfsp_leafs[i - 1], sz);
1184  } else {
1185  for (i = old_idx; i < new_idx; i++)
1186  memcpy(&target->hfsp_leafs[i], &target->hfsp_leafs[i + 1], sz);
1187  }
1188  memcpy(&target->hfsp_leafs[new_idx], &tr, sz);
1189 }
struct hfsplus_node HFSPlusNode
Definition: ecma119.h:552

References ecma119_image::hfsp_leafs.

Referenced by try_mangle().

◆ search_mangled_pos()

static int search_mangled_pos ( Ecma119Image target,
uint32_t  idx,
uint32_t *  new_idx,
uint32_t  search_start,
uint32_t  search_end,
int  flag 
)
static

Definition at line 1143 of file hfsplus.c.

1145 {
1146  uint32_t i;
1147  int rel;
1148 
1149  for (i = search_start; i < search_end; i++) {
1150  if (target->hfsp_leafs[i].type == HFSPLUS_DIR_THREAD ||
1151  target->hfsp_leafs[i].type == HFSPLUS_FILE_THREAD)
1152  continue;
1153  rel = cmp_node(&(target->hfsp_leafs[idx]), &(target->hfsp_leafs[i]));
1154  if (rel == 0 && idx != i) {
1155  *new_idx = i;
1156  return 0; /* Collision */
1157  }
1158  if (rel < 0 && !(flag & 1)) {
1159  if (i <= idx)
1160  *new_idx = i;
1161  else
1162  *new_idx = i - 1;
1163  return 1;
1164  }
1165  }
1166  *new_idx = search_end - 1;
1167  return 1;
1168 }

References cmp_node(), ecma119_image::hfsp_leafs, HFSPLUS_DIR_THREAD, HFSPLUS_FILE_THREAD, and hfsplus_node::type.

Referenced by try_mangle().

◆ set_hfsplus_name()

static int set_hfsplus_name ( Ecma119Image t,
char *  name,
HFSPlusNode node 
)
static

Definition at line 235 of file hfsplus.c.

236 {
237  int ret;
238 
239  ret = iso_get_hfsplus_name(t->input_charset, t->image->id, name,
240  &(node->name), &(node->strlen), &(node->cmp_name));
241  return ret;
242 }
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
char * input_charset
Definition: ecma119.h:591

References hfsplus_node::cmp_name, Iso_Image::id, ecma119_image::image, ecma119_image::input_charset, iso_get_hfsplus_name(), hfsplus_node::name, and hfsplus_node::strlen.

Referenced by create_tree(), hfsplus_writer_create(), and try_mangle().

◆ subst_symlink_dest_comp()

static int subst_symlink_dest_comp ( Ecma119Image target,
uint32_t  idx,
char **  dest,
unsigned int *  dest_len,
char **  comp_start,
char **  comp_end,
char *  new_name,
int  flag 
)
static

Definition at line 1192 of file hfsplus.c.

1196 {
1197  int new_len;
1198  unsigned int new_dest_len;
1199  char *new_dest, *wpt;
1200 
1201  new_len = strlen(new_name);
1202  new_dest_len =
1203  *comp_start - *dest + new_len + *dest_len - (*comp_end - *dest);
1204  new_dest = calloc(1, new_dest_len + 1);
1205  if (new_dest == NULL)
1206  return ISO_OUT_OF_MEM;
1207  wpt = new_dest;
1208  if (*comp_start - *dest > 0)
1209  memcpy(wpt, *dest, *comp_start - *dest);
1210  wpt += *comp_start - *dest;
1211  memcpy(wpt, new_name, new_len);
1212  wpt += new_len;
1213  if ((unsigned int) (*comp_end - *dest) < *dest_len)
1214  memcpy(wpt, *comp_end, *dest_len - (*comp_end - *dest));
1215  wpt += *dest_len - (*comp_end - *dest);
1216  *wpt = 0;
1217 
1218  *comp_start = new_dest + (*comp_start - *dest);
1219  *comp_end = *comp_start + new_len;
1220  target->hfsp_leafs[idx].symlink_dest = new_dest;
1221  *dest_len = new_dest_len;
1222  free(*dest);
1223  *dest = new_dest;
1224  return ISO_SUCCESS;
1225 }

References ecma119_image::hfsp_leafs, ISO_OUT_OF_MEM, ISO_SUCCESS, and hfsplus_node::symlink_dest.

Referenced by update_symlink().

◆ try_mangle()

static int try_mangle ( Ecma119Image target,
uint32_t  idx,
uint32_t  prev_idx,
uint32_t  search_start,
uint32_t  search_end,
uint32_t *  new_idx,
char *  prefix,
int  flag 
)
static

Definition at line 1385 of file hfsplus.c.

1388 {
1389  int i, ret = 0;
1390  char new_name[LIBISO_HFSPLUS_NAME_MAX + 1], number[9];
1391  uint16_t *old_name, *old_cmp_name;
1392  uint32_t old_strlen;
1393 
1394  old_name = target->hfsp_leafs[idx].name;
1395  old_cmp_name = target->hfsp_leafs[idx].cmp_name;
1396  old_strlen = target->hfsp_leafs[idx].strlen;
1397 
1398  for (i = -1; i < 0x7fffffff; i++) {
1399  if (i == -1)
1400  number[0] = 0;
1401  else
1402  sprintf(number, "%X", (unsigned int) i);
1403  if (strlen(prefix) + 1 + strlen(number) > LIBISO_HFSPLUS_NAME_MAX) {
1404  ret = 0;
1405  goto no_success;
1406  }
1407 
1408  /* "-" would sort lower than capital letters ,
1409  traditional "_" causes longer rotations
1410  */
1411  sprintf(new_name, "%s_%s", prefix, number);
1412 
1413  /* The original name is kept until the end of the try */
1414  if (target->hfsp_leafs[idx].name != old_name)
1415  free(target->hfsp_leafs[idx].name);
1416  if (target->hfsp_leafs[idx].cmp_name != old_cmp_name)
1417  free(target->hfsp_leafs[idx].cmp_name);
1418 
1419 
1420  ret = set_hfsplus_name(target, new_name, &(target->hfsp_leafs[idx]));
1421  if (ret < 0)
1422  goto no_success;
1423 
1424  ret = search_mangled_pos(target, idx, new_idx, search_start,
1425  search_end, (flag & 1));
1426  if (ret < 0)
1427  goto no_success;
1428  if (ret == 0)
1429  continue; /* collision */
1430  if (flag & 1)
1431  *new_idx = idx;
1432  else
1433  rotate_hfs_list(target, idx, *new_idx, 0);
1434 
1435  /* >>> Get full ISO-RR paths of colliding nodes */;
1436  /* >>> iso_tree_get_node_path(node); */
1437 
1438  iso_msg_debug(target->image->id,
1439  "HFS+ name collision with \"%s\" : \"%s\" renamed to \"%s\"",
1440  target->hfsp_leafs[prev_idx].node->name,
1441  target->hfsp_leafs[*new_idx].node->name, new_name);
1442 
1443  break;
1444  }
1445  target->hfsp_leafs[*new_idx].used_size +=
1446  (target->hfsp_leafs[*new_idx].strlen - old_strlen) * 2;
1447 
1448  if (!(flag & 1)) {
1449  ret = update_name_followers(target, *new_idx, new_name,
1450  old_name, old_cmp_name, old_strlen);
1451  if (ret < 0)
1452  goto no_success;
1453  }
1454 
1455  free(old_name);
1456  free(old_cmp_name);
1457  return 1;
1458 
1459 no_success:;
1460  target->hfsp_leafs[idx].name = old_name;
1461  target->hfsp_leafs[idx].cmp_name = old_cmp_name;
1462  target->hfsp_leafs[idx].strlen = old_strlen;
1463  return ret;
1464 }
static int update_name_followers(Ecma119Image *target, uint32_t idx, char *new_name, uint16_t *old_name, uint16_t *old_cmp_name, uint32_t old_strlen)
Definition: hfsplus.c:1351
static void rotate_hfs_list(Ecma119Image *target, uint32_t old_idx, uint32_t new_idx, int flag)
Definition: hfsplus.c:1171
static int search_mangled_pos(Ecma119Image *target, uint32_t idx, uint32_t *new_idx, uint32_t search_start, uint32_t search_end, int flag)
Definition: hfsplus.c:1143

References hfsplus_node::cmp_name, ecma119_image::hfsp_leafs, Iso_Image::id, ecma119_image::image, iso_msg_debug(), LIBISO_HFSPLUS_NAME_MAX, hfsplus_node::name, Iso_Node::name, hfsplus_node::node, rotate_hfs_list(), search_mangled_pos(), set_hfsplus_name(), hfsplus_node::strlen, update_name_followers(), and hfsplus_node::used_size.

Referenced by mangle_leafs().

◆ update_name_followers()

static int update_name_followers ( Ecma119Image target,
uint32_t  idx,
char *  new_name,
uint16_t *  old_name,
uint16_t *  old_cmp_name,
uint32_t  old_strlen 
)
static

Definition at line 1351 of file hfsplus.c.

1354 {
1355  uint32_t i;
1356  int ret, link_depth;
1357 
1358  for (i = 0; i < target->hfsp_nleafs; i++) {
1359  if (target->hfsp_leafs[i].unix_type == UNIX_SYMLINK) {
1360  link_depth = 0;
1361  ret = update_symlink(target, idx, new_name, i, &link_depth, 0);
1362  if (ret < 0)
1363  return ret;
1364  }
1365  if (target->hfsp_leafs[i].name != old_name)
1366  continue;
1367  target->hfsp_leafs[i].name = target->hfsp_leafs[idx].name;
1368  target->hfsp_leafs[i].strlen = target->hfsp_leafs[idx].strlen;
1369  if (target->hfsp_leafs[i].cmp_name == old_cmp_name)
1370  target->hfsp_leafs[i].cmp_name = target->hfsp_leafs[idx].cmp_name;
1371  if (target->hfsp_leafs[i].strlen > old_strlen)
1372  target->hfsp_leafs[i].used_size += (target->hfsp_leafs[i].strlen -
1373  old_strlen) * 2;
1374  else
1375  target->hfsp_leafs[i].used_size -= 2 * (old_strlen -
1376  target->hfsp_leafs[i].strlen);
1377  }
1378  return 1;
1379 }
static int update_symlink(Ecma119Image *target, uint32_t changed_idx, char *new_name, uint32_t link_idx, int *depth, int flag)
Definition: hfsplus.c:1238

References hfsplus_node::cmp_name, ecma119_image::hfsp_leafs, ecma119_image::hfsp_nleafs, hfsplus_node::name, hfsplus_node::strlen, hfsplus_node::unix_type, update_symlink(), and hfsplus_node::used_size.

Referenced by try_mangle().

◆ update_symlink()

static int update_symlink ( Ecma119Image target,
uint32_t  changed_idx,
char *  new_name,
uint32_t  link_idx,
int *  depth,
int  flag 
)
static

Definition at line 1238 of file hfsplus.c.

1240 {
1241  IsoSymlink *sym;
1242  IsoDir *cur_dir = NULL;
1243  IsoNode *n, *resolved_node;
1244  char *orig_dest, *orig_start, *orig_end;
1245  char *hfsp_dest, *hfsp_start, *hfsp_end;
1246  int ret = 0;
1247  unsigned int comp_len, orig_len, hfsp_len;
1248 
1249  if (target->hfsp_leafs[link_idx].node->type != LIBISO_SYMLINK)
1250  return ISO_SUCCESS;
1251  sym = (IsoSymlink *) target->hfsp_leafs[link_idx].node;
1252  orig_dest = sym->dest;
1253  orig_len = strlen(orig_dest);
1254  hfsp_dest = target->hfsp_leafs[link_idx].symlink_dest;
1255  hfsp_len = strlen(hfsp_dest);
1256 
1257  if (orig_dest[0] == '/') {
1258 
1259  /* >>> ??? How to salvage absolute links without knowing the
1260  path of the future mount point ?
1261  ??? Would it be better to leave them as is ?
1262  I can only assume that it gets mounted at / during some stage
1263  of booting.
1264  */;
1265 
1266  cur_dir = target->image->root;
1267  orig_end = orig_dest;
1268  } else {
1269  cur_dir = sym->node.parent;
1270  if (cur_dir == NULL)
1271  cur_dir = target->image->root;
1272  orig_end = orig_dest - 1;
1273  }
1274 
1275  if (hfsp_dest[0] == '/')
1276  hfsp_end = hfsp_dest;
1277  else
1278  hfsp_end = hfsp_dest - 1;
1279 
1280  while (orig_end < orig_dest + orig_len) {
1281  orig_start = orig_end + 1;
1282  hfsp_start = hfsp_end + 1;
1283 
1284  orig_end = strchr(orig_start, '/');
1285  if (orig_end == NULL)
1286  orig_end = orig_start + strlen(orig_start);
1287  comp_len = orig_end - orig_start;
1288  hfsp_end = strchr(hfsp_start, '/');
1289  if (hfsp_end == NULL)
1290  hfsp_end = hfsp_start + strlen(hfsp_start);
1291 
1292  if (comp_len == 0 || (comp_len == 1 && orig_start[0] == '.'))
1293  continue;
1294  if (comp_len == 2 && orig_start[0] == '.' && orig_start[1] == '.') {
1295  cur_dir = cur_dir->node.parent;
1296  if (cur_dir == NULL) /* link shoots over root */
1297  return ISO_SUCCESS;
1298  continue;
1299  }
1300 
1301  /* Search node in cur_dir */
1302  for (n = cur_dir->children; n != NULL; n = n->next)
1303  if (strncmp(orig_start, n->name, comp_len) == 0 &&
1304  strlen(n->name) == comp_len)
1305  break;
1306  if (n == NULL) /* dead link */
1307  return ISO_SUCCESS;
1308 
1309  if (n == target->hfsp_leafs[changed_idx].node) {
1310  iso_msg_debug(target->image->id,
1311  " link path '%s' touches RR '%s', HFS+ '%s'",
1312  orig_dest, (n->name != NULL ? n->name : ""),
1313  new_name);
1314 
1315  /* Exchange HFS+ component by new_name */
1316  ret = subst_symlink_dest_comp(target, link_idx,
1317  &hfsp_dest, &hfsp_len,
1318  &hfsp_start, &hfsp_end, new_name, 0);
1319  if (ret < 0)
1320  return ret;
1321  }
1322 
1323  if (n->type == LIBISO_DIR) {
1324  cur_dir = (IsoDir *) n;
1325  } else if (n->type == LIBISO_SYMLINK) {
1326  /* Resolve link and check whether it is a directory */
1327  if (*depth >= LIBISO_MAX_LINK_DEPTH)
1328  return ISO_SUCCESS;
1329  (*depth)++;
1330  ret = iso_tree_resolve_symlink(target->image, (IsoSymlink *) n,
1331  &resolved_node, depth, 0);
1332  if (ret == (int) ISO_DEAD_SYMLINK || ret == (int) ISO_DEEP_SYMLINK)
1333  return ISO_SUCCESS;
1334  if (ret < 0)
1335  return ret;
1336  if (resolved_node->type != LIBISO_DIR)
1337  return ISO_SUCCESS;
1338  cur_dir = (IsoDir *) resolved_node;
1339  } else {
1340  break;
1341  }
1342  }
1343  return ISO_SUCCESS;
1344 }
static int subst_symlink_dest_comp(Ecma119Image *target, uint32_t idx, char **dest, unsigned int *dest_len, char **comp_start, char **comp_end, char *new_name, int flag)
Definition: hfsplus.c:1192
#define ISO_DEEP_SYMLINK
Too many chained symbolic links (FAILURE, HIGH, -395)
Definition: libisofs.h:9156
#define ISO_DEAD_SYMLINK
Symbolic link cannot be resolved (FAILURE, HIGH, -394)
Definition: libisofs.h:9153
#define LIBISO_MAX_LINK_DEPTH
Definition: libisofs.h:6589
int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res, int *depth, int flag)
Get the destination node of a symbolic link within the IsoImage.
Definition: tree.c:1578
IsoNode node
Definition: node.h:141

References Iso_Dir::children, hfsplus_btheader::depth, Iso_Symlink::dest, ecma119_image::hfsp_leafs, Iso_Image::id, ecma119_image::image, ISO_DEAD_SYMLINK, ISO_DEEP_SYMLINK, iso_msg_debug(), ISO_SUCCESS, iso_tree_resolve_symlink(), LIBISO_DIR, LIBISO_MAX_LINK_DEPTH, LIBISO_SYMLINK, Iso_Node::name, Iso_Node::next, hfsplus_node::node, Iso_Dir::node, Iso_Symlink::node, Iso_Node::parent, Iso_Image::root, subst_symlink_dest_comp(), hfsplus_node::symlink_dest, and Iso_Node::type.

Referenced by update_name_followers().

◆ write_sb()

int write_sb ( Ecma119Image t)

Definition at line 595 of file hfsplus.c.

596 {
597  struct hfsplus_volheader sb;
598  static char buffer[1024];
599  int ret;
600  int i;
601  uint32_t block_size;
602 
603  iso_msg_debug(t->image->id, "Write HFS+ superblock");
604 
605  block_size = t->opts->hfsp_block_size;
606 
607  memset (buffer, 0, sizeof (buffer));
608  ret = iso_write(t, buffer, 1024);
609  if (ret < 0)
610  return ret;
611 
612  memset (&sb, 0, sizeof (sb));
613 
614  t->hfsp_allocation_size = (t->hfsp_total_blocks + 7) >> 3;
615 
616  iso_msb ((uint8_t *) &sb.magic, 0x482b, 2);
617  iso_msb ((uint8_t *) &sb.version, 4, 2);
618  /* Cleanly unmounted, software locked. */
619  iso_msb ((uint8_t *) &sb.attributes, (1 << 8) | (1 << 15), 4);
620  iso_msb ((uint8_t *) &sb.last_mounted_version, 0x6c69736f, 4);
621  sb.ctime = mac_time_offset(t->now);
622  sb.utime = mac_time_offset(t->now);
623  sb.fsck_time = mac_time_offset(t->now);
624  iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4);
625  iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4);
626  iso_msb ((uint8_t *) &sb.blksize, block_size, 4);
627  iso_msb ((uint8_t *) &sb.catalog_node_id, t->hfsp_cat_id, 4);
628  iso_msb ((uint8_t *) &sb.rsrc_clumpsize, block_size, 4);
629  iso_msb ((uint8_t *) &sb.data_clumpsize, block_size, 4);
630  iso_msb ((uint8_t *) &sb.total_blocks, t->hfsp_total_blocks, 4);
631  iso_msb ((uint8_t *) &sb.encodings_bitmap + 4, 1, 4);
632 
633  iso_msb ((uint8_t *) &sb.allocations_file.size + 4, t->hfsp_allocation_size, 4);
634  iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, block_size, 4);
635  iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
636  iso_msb ((uint8_t *) &sb.allocations_file.extents[0].start, t->hfsp_allocation_file_start - t->hfsp_part_start, 4);
637  iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
638 
639  iso_msb ((uint8_t *) &sb.extents_file.size + 4, block_size, 4);
640  iso_msb ((uint8_t *) &sb.extents_file.clumpsize, block_size, 4);
641  iso_msb ((uint8_t *) &sb.extents_file.blocks, 1, 4);
642  iso_msb ((uint8_t *) &sb.extents_file.extents[0].start, t->hfsp_extent_file_start - t->hfsp_part_start, 4);
643  iso_msb ((uint8_t *) &sb.extents_file.extents[0].count, 1, 4);
644  iso_msg_debug(t->image->id, "extent_file_start = %d\n", (int)t->hfsp_extent_file_start);
645 
646  iso_msb ((uint8_t *) &sb.catalog_file.size + 4, block_size * 2 * t->hfsp_nnodes, 4);
647  iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, block_size * 2, 4);
648  iso_msb ((uint8_t *) &sb.catalog_file.blocks, 2 * t->hfsp_nnodes, 4);
649  iso_msb ((uint8_t *) &sb.catalog_file.extents[0].start, t->hfsp_catalog_file_start - t->hfsp_part_start, 4);
650  iso_msb ((uint8_t *) &sb.catalog_file.extents[0].count, 2 * t->hfsp_nnodes, 4);
651  iso_msg_debug(t->image->id, "catalog_file_start = %d\n", (int)t->hfsp_catalog_file_start);
652 
653  for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++) {
654  iso_msb ((uint8_t *) (&sb.ppc_bootdir + i
656  t->hfsp_bless_id[i], 4);
657 
658 #ifdef Libisofs_ts_debuG
659  iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u",
660  i, t->hfsp_bless_id[i]);
661 #endif /* Libisofs_ts_debuG */
662 
663  }
664 
665  memcpy (&sb.num_serial, &t->opts->hfsp_serial_number, 8);
666  ret = iso_write(t, &sb, sizeof (sb));
667  if (ret < 0)
668  return ret;
669  return iso_write(t, buffer, 512);
670 }
@ ISO_HFSPLUS_BLESS_OSX_FOLDER
Definition: libisofs.h:8595
time_t now
Time at which writing began.
Definition: ecma119.h:594
uint8_t hfsp_serial_number[8]
Definition: ecma119.h:529

References hfsplus_volheader::allocations_file, hfsplus_volheader::attributes, hfsplus_volheader::blksize, hfsplus_forkdata::blocks, hfsplus_volheader::catalog_file, hfsplus_volheader::catalog_node_id, hfsplus_forkdata::clumpsize, hfsplus_extent::count, hfsplus_volheader::ctime, hfsplus_volheader::data_clumpsize, hfsplus_volheader::encodings_bitmap, hfsplus_forkdata::extents, hfsplus_volheader::extents_file, hfsplus_volheader::file_count, hfsplus_volheader::folder_count, hfsplus_volheader::fsck_time, ecma119_image::hfsp_allocation_file_start, ecma119_image::hfsp_allocation_size, ecma119_image::hfsp_bless_id, iso_write_opts::hfsp_block_size, ecma119_image::hfsp_cat_id, ecma119_image::hfsp_catalog_file_start, ecma119_image::hfsp_extent_file_start, ecma119_image::hfsp_ndirs, ecma119_image::hfsp_nfiles, ecma119_image::hfsp_nnodes, ecma119_image::hfsp_part_start, iso_write_opts::hfsp_serial_number, ecma119_image::hfsp_total_blocks, Iso_Image::id, ecma119_image::image, ISO_HFSPLUS_BLESS_MAX, ISO_HFSPLUS_BLESS_OSX_FOLDER, iso_msb(), iso_msg_debug(), iso_write(), hfsplus_volheader::last_mounted_version, mac_time_offset(), hfsplus_volheader::magic, ecma119_image::now, hfsplus_volheader::num_serial, ecma119_image::opts, hfsplus_volheader::ppc_bootdir, hfsplus_volheader::rsrc_clumpsize, hfsplus_forkdata::size, hfsplus_extent::start, hfsplus_volheader::total_blocks, hfsplus_volheader::utime, and hfsplus_volheader::version.

Referenced by hfsplus_tail_writer_write_data(), and hfsplus_writer_write_data().