/* -*- 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 #include #include /* for FILE */ #include #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 { struct iso_file_src *src; /* source for reading from the file */ int file; /* The index in filelist that we are * currently writing (or about to write). */ } state_files; /* temp buffer for read functions */ uint8_t buffer[2048]; int bytes_read; }; #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 */