Vladimir Serbinenko began to implement production of HFS+ metadata.

This revision introduces the writer class and a first attempt to integrate
it into image production. Not yet functional.
This commit is contained in:
Thomas Schmitt 2012-05-23 14:47:49 +02:00
parent 6982971796
commit 2c540b1f43
6 changed files with 1274 additions and 1 deletions

View File

@ -66,6 +66,8 @@ libisofs_libisofs_la_SOURCES = \
libisofs/rockridge_read.c \
libisofs/joliet.h \
libisofs/joliet.c \
libisofs/hfsplus.h \
libisofs/hfsplus.c \
libisofs/eltorito.h \
libisofs/eltorito.c \
libisofs/system_area.h \

View File

@ -21,6 +21,7 @@
#include "ecma119.h"
#include "joliet.h"
#include "hfsplus.h"
#include "iso1999.h"
#include "eltorito.h"
#include "ecma119_tree.h"
@ -451,6 +452,9 @@ char *get_relaxed_vol_id(Ecma119Image *t, const char *name)
return strdup(name);
}
/**
* Set the timestamps of Primary, Supplementary, or Enhanced Volume Descriptor.
*/
void ecma119_set_voldescr_times(IsoImageWriter *writer,
struct ecma119_pri_vol_desc *vol)
{
@ -1260,6 +1264,8 @@ int write_head_part1(Ecma119Image *target, int *write_count, int flag)
iso_msg_debug(target->image->id, "Write volume descriptors");
for (i = 0; i < (int) target->nwriters; ++i) {
writer = target->writers[i];
if (writer->write_vol_desc == hfsplus_writer_write_vol_desc)
continue;
res = writer->write_vol_desc(writer);
if (res < 0)
goto write_error;
@ -1270,6 +1276,16 @@ int write_head_part1(Ecma119Image *target, int *write_count, int flag)
if (res < 0)
goto write_error;
/* Special treatment for HFS */
for (i = 0; i < (int) target->nwriters; ++i) {
writer = target->writers[i];
if (writer->write_vol_desc != hfsplus_writer_write_vol_desc)
continue;
res = writer->write_vol_desc(writer);
if (res < 0)
goto write_error;
}
if(flag & 2) {
iso_ring_buffer_get_buf_status(target->buffer, &buffer_size,
&buffer_free);
@ -1314,6 +1330,13 @@ int write_head_part2(Ecma119Image *target, int *write_count, int flag)
/* >>> TWINTREE: Enhance ISO1999 writer and add it here */
/* >>> HFS : ts B20523
Vladimir wanted to run hfsplus_writer_write_vol_desc
here. But this function is called after the terminator
for the first descriptor set.
So it would have to be called after this loop.
If it is prepared for duplicate metadata at all.
*/
if(writer->write_vol_desc != ecma119_writer_write_vol_desc &&
writer->write_vol_desc != joliet_writer_write_vol_desc)
continue;
@ -1325,6 +1348,11 @@ int write_head_part2(Ecma119Image *target, int *write_count, int flag)
ret = write_vol_desc_terminator(target);
if (ret < 0)
goto ex;
/* >>> HFS : ts B20523
If desired and capable, write HFS "volume descriptor" stuff here.
*/
(*write_count)++;
target->eff_partition_offset = 0;
@ -1630,6 +1658,13 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
return ISO_SUCCESS;
}
static
int is_ms_file(void *arg)
{
IsoFileSrc *f = (IsoFileSrc *)arg;
return f->prev_img ? 0 : 1;
}
static
int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
{
@ -1641,7 +1676,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
int system_area_options = 0;
char *system_area = NULL;
int write_count = 0, write_count_mem;
int hfsplus_writer_index = -1;
/* 1. Allocate target and copy opts there */
target = calloc(1, sizeof(Ecma119Image));
@ -1666,6 +1701,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->iso_level = opts->level;
target->rockridge = opts->rockridge;
target->joliet = opts->joliet;
target->hfsplus = opts->hfsplus;
target->iso1999 = opts->iso1999;
target->hardlinks = opts->hardlinks;
target->aaip = opts->aaip;
@ -1891,6 +1927,9 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->joliet) {
nwriters++;
}
if (target->hfsplus) {
nwriters++;
}
if (target->iso1999) {
nwriters++;
}
@ -1940,6 +1979,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
}
/* create writer for HFS+ structure */
if (target->hfsplus) {
hfsplus_writer_index = target->nwriters - 1;
ret = hfsplus_writer_create(target);
if (ret < 0) {
goto target_cleanup;
}
}
/* create writer for ISO 9660:1999 structure */
if (target->iso1999) {
ret = iso1999_writer_create(target);
@ -2007,6 +2055,13 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
/* >>> TWINTREE: Enhance ISO1999 writer and add it here */
/* >>> HFS : ts B20523
Vladimir wanted to run hfsplus_writer_write_vol_desc
for the second descriptor set. But that aspect needs
further clarification. So it is not yet implemented
and is not yet counted here.
*/
if(writer->write_vol_desc != ecma119_writer_write_vol_desc &&
writer->write_vol_desc != joliet_writer_write_vol_desc)
continue;
@ -2032,6 +2087,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (i == el_torito_writer_index)
continue;
/* >>> HFS : ts B20523
Vladimir wanted to skip hfsplus_writer here.
I do not understand all motivation for this yet, but the
writer must compute its data size in sequence with the other
writers. The el_torito_writer jump is a hack and allowed only
because eltorito_writer_compute_data_blocks() does not
increase the block count. It rather performs -boot-info-table.
*/
/* Exposing address of data start to IsoWriteOpts and memorizing
this address for all files which have no block address:
symbolic links, device files, empty data files.
@ -2039,6 +2103,17 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
will account resp. write this single block.
*/
if (i == file_src_writer_index) {
/* >>> HFS : ts B20523
Vladimir wanted to delay the setting of
target->empty_file_block here. But it might be important
that this is the start block of the file_src_writer realm.
I have to examine, whether it is ok to choose a different
block.
This is related anyway to the inappropriate skipping of
hfs_writer. See above.
*/
if (! target->old_empty)
target->empty_file_block = target->curblock;
opts->data_start_lba = target->curblock;
@ -2050,6 +2125,50 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
}
#ifdef NIX
/* >>> HFS : ts B20523
By Vladimir.
This should be integrated in above loop and probably go into
hfs_writer->compute_data_blocks()..
I have to examine what it does.
*/
if (hfsplus_writer_index >= 0) {
IsoImageWriter *writer = target->writers[hfsplus_writer_index];
uint32_t extra;
IsoFileSrc **filelist;
size_t size;
size_t j;
target->vol_space_size = target->curblock - target->ms_block;
target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
target->curblock = opts->data_start_lba;
ret = writer->compute_data_blocks(writer);
if (ret < 0) {
goto target_cleanup;
}
writer = target->writers[file_src_writer_index];
if (! target->old_empty)
target->empty_file_block = target->curblock;
extra = target->curblock - opts->data_start_lba;
opts->data_start_lba = target->curblock;
filelist = (IsoFileSrc**)iso_rbtree_to_array(target->files, target->appendable ? is_ms_file : NULL, &size);
/* fill block value */
for (j = 0; j < size; ++j) {
int extent = 0;
IsoFileSrc *file = filelist[j];
for (extent = 0; extent < file->nsections - 1; ++extent) {
file->sections[extent].block += extra;
}
}
}
#endif /* NIX */
/* Now perform delayed image patching and System Area preparations */
if (el_torito_writer_index >= 0) {
IsoImageWriter *writer = target->writers[el_torito_writer_index];
@ -2412,6 +2531,10 @@ int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts,
struct burn_source *source;
Ecma119Image *target= NULL;
/* <<< ts B20523 : Only as long as Vladimir develops HFS */
iso_msg_debug(image->id, "(c) opts->hfsplus = 0x%x", opts->hfsplus);
iso_msg_debug(image->id, "(c) opts->joliet = 0x%x", opts->joliet);
if (image == NULL || opts == NULL || burn_src == NULL) {
return ISO_NULL_POINTER;
}
@ -2640,6 +2763,15 @@ int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable)
return ISO_SUCCESS;
}
int iso_write_opts_set_hfsplus(IsoWriteOpts *opts, int enable)
{
if (opts == NULL) {
return ISO_NULL_POINTER;
}
opts->hfsplus = enable ? 1 : 0;
return ISO_SUCCESS;
}
int iso_write_opts_set_iso1999(IsoWriteOpts *opts, int enable)
{
if (opts == NULL) {

View File

@ -83,6 +83,7 @@ struct iso_write_opts {
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int iso1999 :1;
unsigned int hfsplus :1;
unsigned int aaip :1; /* whether to write eventual ACL and EAs */
@ -448,6 +449,7 @@ typedef struct ecma119_image Ecma119Image;
typedef struct ecma119_node Ecma119Node;
typedef struct joliet_node JolietNode;
typedef struct iso1999_node Iso1999Node;
typedef struct hfsplus_node HFSPlusNode;
typedef struct Iso_File_Src IsoFileSrc;
typedef struct Iso_Image_Writer IsoImageWriter;
@ -467,6 +469,7 @@ struct ecma119_image
unsigned int joliet :1;
unsigned int eltorito :1;
unsigned int iso1999 :1;
unsigned int hfsplus :1;
unsigned int hardlinks:1; /* see iso_write_opts_set_hardlinks() */
@ -592,6 +595,16 @@ struct ecma119_image
uint32_t joliet_l_path_table_pos;
uint32_t joliet_m_path_table_pos;
/*
* HFS+ related information
*/
HFSPlusNode *hfsplus_root;
uint32_t hfsp_part_start;
uint32_t hfsp_nfiles;
uint32_t hfsp_ndirs;
uint32_t hfsp_cat_id;
uint32_t hfsp_allocation_blocks;
/*
* ISO 9660:1999 related information
*/

1011
libisofs/hfsplus.c Normal file

File diff suppressed because it is too large Load Diff

96
libisofs/hfsplus.h Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2012 Thomas Schmitt
* Copyright (c) 2012 Vladimir Serbinenko
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* or later as published by the Free Software Foundation.
* See COPYING file for details.
*/
/**
* Declare HFS+ related structures.
*/
#ifndef LIBISO_HFSPLUS_H
#define LIBISO_HFSPLUS_H
#include "ecma119.h"
/* <<< dummies */
#define LIBISO_HFSPLUS_NAME_MAX 255
enum hfsplus_node_type {
HFSPLUS_FILE,
HFSPLUS_DIR
};
struct hfsplus_dir_info {
HFSPlusNode **children;
size_t nchildren;
size_t len;
size_t block;
};
struct hfsplus_node
{
uint16_t *name; /**< Name in UCS-2BE. */
HFSPlusNode *parent;
IsoNode *node; /*< reference to the iso node */
enum hfsplus_node_type type;
union {
IsoFileSrc *file;
struct hfsplus_dir_info *dir;
} info;
/* <<< dummies */
int cat_id;
};
struct hfsplus_volheader {
uint16_t magic;
uint16_t version;
uint32_t attributes;
uint32_t last_mounted_version;
uint32_t ctime;
uint32_t utime;
uint32_t backup_time;
uint32_t fsck_time;
uint32_t file_count;
uint32_t folder_count;
uint32_t blksize;
uint32_t catalog_node_id;
uint32_t rsrc_clumpsize;
uint32_t data_clumpsize;
uint32_t total_blocks;
};
/* >>> ts B20523 : what else is needed here ? */
/**
* Create a IsoWriter to deal with HFS+ structures, and add it to the given
* target.
*
* @return
* 1 on success, < 0 on error
*/
int hfsplus_writer_create(Ecma119Image *target);
/* Not to be called but only for comparison with target->writers[i]
*/
int hfsplus_writer_write_vol_desc(IsoImageWriter *writer);
#endif /* LIBISO_HFSPLUS_H */

View File

@ -295,6 +295,11 @@ enum IsoHideNodeFlag {
/** Hide the node in the ISO-9660:1999 tree, if that format is enabled */
LIBISO_HIDE_ON_1999 = 1 << 2,
/** Hide the node in the HFS+ tree, if that format is enabled.
@since 1.2.4
*/
LIBISO_HIDE_ON_HFSPLUS = 1 << 4,
/** With IsoNode and IsoBoot: Write data content even if the node is
* not visible in any tree.
* With directory nodes : Write data content of IsoNode and IsoBoot
@ -1391,6 +1396,20 @@ int iso_write_opts_set_rockridge(IsoWriteOpts *opts, int enable);
*/
int iso_write_opts_set_joliet(IsoWriteOpts *opts, int enable);
/**
* Whether to add the HFS+ to the image.
*
* @param opts
* The option set to be manipulated.
* @param enable
* 1 to enable HFS+ extension, 0 to not add them
* @return
* 1 success, < 0 error
*
* @since 1.2.4
*/
int iso_write_opts_set_hfsplus(IsoWriteOpts *opts, int enable);
/**
* Whether to use newer ISO-9660:1999 version.
*