323 lines
9.3 KiB
C
323 lines
9.3 KiB
C
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
|
/* vim: set noet ts=8 sts=8 sw=8 : */
|
|
|
|
/**
|
|
* \file ecma119.h
|
|
*
|
|
* Structures and definitions used for writing an emca119 (ISO9660) compatible
|
|
* volume.
|
|
*/
|
|
|
|
#ifndef LIBISO_ECMA119_H
|
|
#define LIBISO_ECMA119_H
|
|
|
|
#include <sys/time.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h> /* for FILE */
|
|
#include <sys/types.h>
|
|
#include "susp.h"
|
|
|
|
struct ecma119_tree_node;
|
|
struct joliet_tree_node;
|
|
|
|
/**
|
|
* The possible states that the ecma119 writer can be in.
|
|
*/
|
|
enum ecma119_write_state
|
|
{
|
|
ECMA119_WRITE_BEFORE,
|
|
|
|
ECMA119_WRITE_SYSTEM_AREA,
|
|
ECMA119_WRITE_PRI_VOL_DESC,
|
|
ECMA119_WRITE_ELTORITO_BOOT_VOL_DESC,
|
|
ECMA119_WRITE_SUP_VOL_DESC_JOLIET,
|
|
ECMA119_WRITE_VOL_DESC_TERMINATOR,
|
|
ECMA119_WRITE_L_PATH_TABLE,
|
|
ECMA119_WRITE_M_PATH_TABLE,
|
|
ECMA119_WRITE_L_PATH_TABLE_JOLIET,
|
|
ECMA119_WRITE_M_PATH_TABLE_JOLIET,
|
|
ECMA119_WRITE_DIR_RECORDS,
|
|
ECMA119_WRITE_DIR_RECORDS_JOLIET,
|
|
ECMA119_WRITE_ELTORITO_CATALOG,
|
|
ECMA119_WRITE_FILES,
|
|
|
|
ECMA119_WRITE_DONE
|
|
};
|
|
|
|
/**
|
|
* Data describing the state of the ecma119 writer. Everything here should be
|
|
* considered private!
|
|
*/
|
|
struct ecma119_write_target
|
|
{
|
|
struct ecma119_tree_node *root;
|
|
struct joliet_tree_node *joliet_root;
|
|
struct iso_volset *volset;
|
|
int volnum;
|
|
|
|
time_t now; /**< Time at which writing began. */
|
|
off_t total_size; /**< Total size of the output. This only
|
|
* includes the current volume. */
|
|
uint32_t vol_space_size;
|
|
|
|
unsigned int rockridge:1;
|
|
unsigned int joliet:1;
|
|
unsigned int iso_level:2;
|
|
unsigned int eltorito:1;
|
|
|
|
unsigned int write_eltorito:1;
|
|
/**<
|
|
* In multisession discs, select whether to copy el-torito catalog
|
|
* and boot image. Copy is needed for isolinux images, that need to
|
|
* be patched. However, it can lead to problems when the image is
|
|
* not present in the iso filesystem, because we can't figure out
|
|
* its size. In those cases, we only copy 1 block of data.
|
|
* When modifying images, we always need to copy data. Thus, this is
|
|
* always 1 for both new and modified images.
|
|
*/
|
|
|
|
struct el_torito_boot_catalog *catalog;
|
|
uint32_t catblock; /**< location of the boot catalog in the new image */
|
|
uint32_t imgblock; /**< location of the boot image in the new image */
|
|
|
|
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
|
|
|
int replace_mode; /**< Replace ownership and modes of files
|
|
*
|
|
* 0. filesystem values
|
|
* 1. useful values
|
|
* bits 1-4 bitmask:
|
|
* 2 - replace dir
|
|
* 3 - replace file
|
|
* 4 - replace gid
|
|
* 5 - replace uid
|
|
*/
|
|
mode_t dir_mode;
|
|
mode_t file_mode;
|
|
gid_t gid;
|
|
uid_t uid;
|
|
|
|
char *input_charset;
|
|
char *ouput_charset;
|
|
|
|
int cache_inodes;
|
|
|
|
int sort_files; /**< if sort files or not. Sorting is based of
|
|
* the weight of each file */
|
|
|
|
/**
|
|
* In the CD, each file must have an unique inode number. So each
|
|
* time we add a new file, this is incremented.
|
|
*/
|
|
ino_t ino;
|
|
|
|
uint32_t ms_block; /**< if != 0, nwa for multisession */
|
|
struct data_source* src;
|
|
|
|
int curblock;
|
|
uint16_t block_size;
|
|
uint32_t path_table_size;
|
|
uint32_t path_table_size_joliet;
|
|
uint32_t l_path_table_pos;
|
|
uint32_t m_path_table_pos;
|
|
uint32_t l_path_table_pos_joliet;
|
|
uint32_t m_path_table_pos_joliet;
|
|
uint32_t total_dir_size;
|
|
uint32_t total_dir_size_joliet;
|
|
|
|
struct ecma119_tree_node **dirlist;
|
|
/**< A pre-order list of directories
|
|
* (this is the order in which we write
|
|
* out directory records).
|
|
*/
|
|
struct ecma119_tree_node **pathlist;
|
|
/**< A breadth-first list of
|
|
* directories. This is used for
|
|
* writing out the path tables.
|
|
*/
|
|
size_t dirlist_len; /**< The length of the previous 2 lists.
|
|
*/
|
|
|
|
|
|
struct iso_file_table *file_table;
|
|
/**<
|
|
* A hash table with info about all files
|
|
*/
|
|
|
|
struct iso_file **filelist; /**< A pre-order list of files.*/
|
|
size_t filelist_len; /* Length of the previous list. */
|
|
|
|
int curfile; /**< Used as a helper field for writing
|
|
out filelist and dirlist */
|
|
|
|
/* Joliet versions of the above lists. Since Joliet doesn't require
|
|
* directory relocation, the order of these lists might be different
|
|
* from the lists above (but they will be the same length).
|
|
*/
|
|
struct joliet_tree_node **dirlist_joliet;
|
|
struct joliet_tree_node **pathlist_joliet;
|
|
|
|
size_t dirlist_len_joliet;
|
|
|
|
enum ecma119_write_state state; /* The current state of the writer. */
|
|
|
|
/* Most writers work by
|
|
* 1) making sure state_data is big enough for their data
|
|
* 2) writing _all_ their data into state_data
|
|
* 3) relying on write_data_chunk to write the data block
|
|
* by block.
|
|
*/
|
|
uint8_t *state_data;
|
|
off_t state_data_size;
|
|
off_t state_data_off;
|
|
int state_data_valid;
|
|
|
|
/* for writing out files */
|
|
struct state_files {
|
|
off_t pos; /* The number of bytes we have written
|
|
* so far in the current file.
|
|
*/
|
|
off_t data_len;/* The number of bytes in the currently
|
|
* open file.
|
|
*/
|
|
FILE *fd; /* The currently open file. */
|
|
int file; /* The index in filelist that we are
|
|
* currently writing (or about to write). */
|
|
} state_files;
|
|
};
|
|
|
|
#define BP(a,b) [(b) - (a) + 1]
|
|
|
|
struct ecma119_pri_vol_desc
|
|
{
|
|
uint8_t vol_desc_type BP(1, 1);
|
|
uint8_t std_identifier BP(2, 6);
|
|
uint8_t vol_desc_version BP(7, 7);
|
|
uint8_t unused1 BP(8, 8);
|
|
uint8_t system_id BP(9, 40);
|
|
uint8_t volume_id BP(41, 72);
|
|
uint8_t unused2 BP(73, 80);
|
|
uint8_t vol_space_size BP(81, 88);
|
|
uint8_t unused3 BP(89, 120);
|
|
uint8_t vol_set_size BP(121, 124);
|
|
uint8_t vol_seq_number BP(125, 128);
|
|
uint8_t block_size BP(129, 132);
|
|
uint8_t path_table_size BP(133, 140);
|
|
uint8_t l_path_table_pos BP(141, 144);
|
|
uint8_t opt_l_path_table_pos BP(145, 148);
|
|
uint8_t m_path_table_pos BP(149, 152);
|
|
uint8_t opt_m_path_table_pos BP(153, 156);
|
|
uint8_t root_dir_record BP(157, 190);
|
|
uint8_t vol_set_id BP(191, 318);
|
|
uint8_t publisher_id BP(319, 446);
|
|
uint8_t data_prep_id BP(447, 574);
|
|
uint8_t application_id BP(575, 702);
|
|
uint8_t copyright_file_id BP(703, 739);
|
|
uint8_t abstract_file_id BP(740, 776);
|
|
uint8_t bibliographic_file_id BP(777, 813);
|
|
uint8_t vol_creation_time BP(814, 830);
|
|
uint8_t vol_modification_time BP(831, 847);
|
|
uint8_t vol_expiration_time BP(848, 864);
|
|
uint8_t vol_effective_time BP(865, 881);
|
|
uint8_t file_structure_version BP(882, 882);
|
|
uint8_t reserved1 BP(883, 883);
|
|
uint8_t app_use BP(884, 1395);
|
|
uint8_t reserved2 BP(1396, 2048);
|
|
};
|
|
|
|
struct ecma119_sup_vol_desc
|
|
{
|
|
uint8_t vol_desc_type BP(1, 1);
|
|
uint8_t std_identifier BP(2, 6);
|
|
uint8_t vol_desc_version BP(7, 7);
|
|
uint8_t vol_flags BP(8, 8);
|
|
uint8_t system_id BP(9, 40);
|
|
uint8_t volume_id BP(41, 72);
|
|
uint8_t unused2 BP(73, 80);
|
|
uint8_t vol_space_size BP(81, 88);
|
|
uint8_t esc_sequences BP(89, 120);
|
|
uint8_t vol_set_size BP(121, 124);
|
|
uint8_t vol_seq_number BP(125, 128);
|
|
uint8_t block_size BP(129, 132);
|
|
uint8_t path_table_size BP(133, 140);
|
|
uint8_t l_path_table_pos BP(141, 144);
|
|
uint8_t opt_l_path_table_pos BP(145, 148);
|
|
uint8_t m_path_table_pos BP(149, 152);
|
|
uint8_t opt_m_path_table_pos BP(153, 156);
|
|
uint8_t root_dir_record BP(157, 190);
|
|
uint8_t vol_set_id BP(191, 318);
|
|
uint8_t publisher_id BP(319, 446);
|
|
uint8_t data_prep_id BP(447, 574);
|
|
uint8_t application_id BP(575, 702);
|
|
uint8_t copyright_file_id BP(703, 739);
|
|
uint8_t abstract_file_id BP(740, 776);
|
|
uint8_t bibliographic_file_id BP(777, 813);
|
|
uint8_t vol_creation_time BP(814, 830);
|
|
uint8_t vol_modification_time BP(831, 847);
|
|
uint8_t vol_expiration_time BP(848, 864);
|
|
uint8_t vol_effective_time BP(865, 881);
|
|
uint8_t file_structure_version BP(882, 882);
|
|
uint8_t reserved1 BP(883, 883);
|
|
uint8_t app_use BP(884, 1395);
|
|
uint8_t reserved2 BP(1396, 2048);
|
|
};
|
|
|
|
struct ecma119_boot_rec_vol_desc
|
|
{
|
|
uint8_t vol_desc_type BP(1, 1);
|
|
uint8_t std_identifier BP(2, 6);
|
|
uint8_t vol_desc_version BP(7, 7);
|
|
uint8_t boot_sys_id BP(8, 39);
|
|
uint8_t boot_id BP(40, 71);
|
|
uint8_t boot_catalog BP(72, 75);
|
|
uint8_t unused BP(76, 2048);
|
|
};
|
|
|
|
struct ecma119_vol_desc_terminator
|
|
{
|
|
uint8_t vol_desc_type BP(1, 1);
|
|
uint8_t std_identifier BP(2, 6);
|
|
uint8_t vol_desc_version BP(7, 7);
|
|
uint8_t reserved BP(8, 2048);
|
|
};
|
|
|
|
struct ecma119_dir_record
|
|
{
|
|
uint8_t len_dr BP(1, 1);
|
|
uint8_t len_xa BP(2, 2);
|
|
uint8_t block BP(3, 10);
|
|
uint8_t length BP(11, 18);
|
|
uint8_t recording_time BP(19, 25);
|
|
uint8_t flags BP(26, 26);
|
|
uint8_t file_unit_size BP(27, 27);
|
|
uint8_t interleave_gap_size BP(28, 28);
|
|
uint8_t vol_seq_number BP(29, 32);
|
|
uint8_t len_fi BP(33, 33);
|
|
uint8_t file_id BP(34, 34); /* 34 to 33+len_fi */
|
|
/* padding field (if len_fi is even) */
|
|
/* system use (len_dr - len_su + 1 to len_dr) */
|
|
};
|
|
|
|
struct ecma119_path_table_record
|
|
{
|
|
uint8_t len_di BP(1, 1);
|
|
uint8_t len_xa BP(2, 2);
|
|
uint8_t block BP(3, 6);
|
|
uint8_t parent BP(7, 8);
|
|
uint8_t dir_id BP(9, 9); /* 9 to 8+len_di */
|
|
/* padding field (if len_di is odd) */
|
|
};
|
|
|
|
/**
|
|
* A utility function for writers that want to write their data all at once
|
|
* rather than block-by-block. This creates a buffer of size \p size, passes
|
|
* it to the given writer, then hands out block-sized chunks.
|
|
*/
|
|
void
|
|
ecma119_start_chunking(struct ecma119_write_target *t,
|
|
void (*)(struct ecma119_write_target*, uint8_t*),
|
|
off_t size,
|
|
uint8_t *buf);
|
|
|
|
#endif /* LIBISO_ECMA119_H */
|