First pinch of libisofs rewrite
This commit is contained in:
parent
176e1654ff
commit
48d76e844e
33
Makefile.am
33
Makefile.am
@ -59,23 +59,22 @@ libburn_libburn_la_SOURCES = \
|
||||
libisofs_libisofs_la_LDFLAGS = \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/errors.h \
|
||||
libisofs/errors.c \
|
||||
libisofs/tree.h \
|
||||
libisofs/tree.c \
|
||||
libisofs/volume.h \
|
||||
libisofs/volume.c \
|
||||
libisofs/util.h \
|
||||
libisofs/util.c \
|
||||
libisofs/ecma119.c \
|
||||
libisofs/ecma119.h \
|
||||
libisofs/struct.h \
|
||||
libisofs/struct.c \
|
||||
libisofs/susp.h \
|
||||
libisofs/susp.c \
|
||||
libisofs/rockridge.h \
|
||||
libisofs/rockridge.c \
|
||||
libisofs/libisofs.h
|
||||
libisofs/tree.h \
|
||||
libisofs/tree.c \
|
||||
libisofs/volume.h \
|
||||
libisofs/volume.c \
|
||||
libisofs/util.h \
|
||||
libisofs/util.c \
|
||||
libisofs/ecma119.c \
|
||||
libisofs/ecma119.h \
|
||||
libisofs/ecma119_tree.c \
|
||||
libisofs/ecma119_tree.h \
|
||||
libisofs/susp.h \
|
||||
libisofs/susp.c \
|
||||
libisofs/rockridge.h \
|
||||
libisofs/rockridge.c \
|
||||
libisofs/joliet.c \
|
||||
libisofs/joliet.h
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libburn/libburn.h \
|
||||
|
@ -1,11 +1,11 @@
|
||||
pkgconfigdir=$(libdir)/pkgconfig
|
||||
libincludedir=$(includedir)/libburn
|
||||
|
||||
##bin_PROGRAMS = test
|
||||
|
||||
lib_LTLIBRARIES = libisofs.la
|
||||
|
||||
libisofs_la_SOURCES = \
|
||||
errors.h \
|
||||
errors.c \
|
||||
tree.h \
|
||||
tree.c \
|
||||
volume.h \
|
||||
@ -14,20 +14,25 @@ libisofs_la_SOURCES = \
|
||||
util.c \
|
||||
ecma119.c \
|
||||
ecma119.h \
|
||||
struct.h \
|
||||
struct.c \
|
||||
ecma119_tree.c \
|
||||
ecma119_tree.h \
|
||||
susp.h \
|
||||
susp.c \
|
||||
rockridge.h \
|
||||
rockridge.c
|
||||
rockridge.c \
|
||||
joliet.c \
|
||||
joliet.h
|
||||
|
||||
libinclude_HEADERS = libisofs.h
|
||||
|
||||
noinst_PROGRAMS = test
|
||||
test_SOURCES = test.c
|
||||
test_LDADD = $(libisofs_la_OBJECTS)
|
||||
##test_SOURCES = test.c
|
||||
##test_LDADD = libisofs.la
|
||||
|
||||
INCLUDES = -I..
|
||||
##noinst_PROGRAMS = test
|
||||
##test_SOURCES = test.c
|
||||
##test_LDADD = $(libisofs_la_OBJECTS)
|
||||
|
||||
##INCLUDES = -I../burn/libburn
|
||||
|
||||
## ========================================================================= ##
|
||||
indent_files = $(libisofs_la_SOURCES)
|
||||
|
2042
libisofs/ecma119.c
2042
libisofs/ecma119.c
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,4 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
/**
|
||||
@ -7,70 +8,17 @@
|
||||
* volume.
|
||||
*/
|
||||
|
||||
#ifndef __ISO_ECMA119
|
||||
#define __ISO_ECMA119
|
||||
#ifndef LIBISO_ECMA119_H
|
||||
#define LIBISO_ECMA119_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include <sys/types.h>
|
||||
#include "susp.h"
|
||||
|
||||
/**
|
||||
* Persistent data for writing directories according to the ecma119 standard.
|
||||
*/
|
||||
struct dir_write_info
|
||||
{
|
||||
struct susp_info susp; /**< \see node_write_info */
|
||||
struct susp_info self_susp; /**< SUSP data for this directory's
|
||||
* "." entry.
|
||||
*/
|
||||
struct susp_info parent_susp; /**< SUSP data for this directory's
|
||||
* ".." entry.
|
||||
*/
|
||||
|
||||
int len; /**< The combined length of all children's
|
||||
* Directory Record lengths. This includes
|
||||
* the System Use areas.
|
||||
*/
|
||||
int susp_len; /**< The combined length of all children's
|
||||
* SUSP Continuation Areas.
|
||||
*/
|
||||
|
||||
/* the parent/child information prior to relocation */
|
||||
struct iso_tree_dir *real_parent;
|
||||
int real_nchildren;
|
||||
struct iso_tree_dir **real_children;
|
||||
int real_depth;
|
||||
|
||||
/* joliet information */
|
||||
int joliet_block; /**< The block at which the Joliet version of
|
||||
* this directory will be written.
|
||||
*/
|
||||
int joliet_len; /**< The combined length of all children's
|
||||
* Joliet Directory Record lengths.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Persistent data for writing files according to the ecma119 standard.
|
||||
*/
|
||||
struct file_write_info
|
||||
{
|
||||
struct susp_info susp; /**< \see node_write_info */
|
||||
|
||||
struct iso_tree_dir *real_me; /**< If this is non-NULL, the file is
|
||||
* a placeholder for a relocated
|
||||
* directory and this field points to
|
||||
* that relocated directory.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* The fields in common between file_write_info and dir_write_info.
|
||||
*/
|
||||
struct node_write_info
|
||||
{
|
||||
struct susp_info susp; /**< The SUSP data for this file. */
|
||||
};
|
||||
struct ecma119_tree_node;
|
||||
struct joliet_tree_node;
|
||||
|
||||
/**
|
||||
* The possible states that the ecma119 writer can be in.
|
||||
@ -100,11 +48,13 @@ enum ecma119_write_state
|
||||
*/
|
||||
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. */
|
||||
int total_size; /**< Total size of the output. This only
|
||||
off_t total_size; /**< Total size of the output. This only
|
||||
* includes the current volume. */
|
||||
uint32_t vol_space_size;
|
||||
|
||||
@ -120,73 +70,63 @@ struct ecma119_write_target
|
||||
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 iso_tree_dir **dirlist; /* A pre-order list of directories
|
||||
struct ecma119_tree_node **dirlist;
|
||||
/**< A pre-order list of directories
|
||||
* (this is the order in which we write
|
||||
* out directory records).
|
||||
*/
|
||||
struct iso_tree_dir **pathlist; /* A breadth-first list of directories.
|
||||
* This is used for writing out the path
|
||||
* tables.
|
||||
struct ecma119_tree_node **pathlist;
|
||||
/**< A breadth-first list of
|
||||
* directories. This is used for
|
||||
* writing out the path tables.
|
||||
*/
|
||||
int dirlist_len; /* The length of the previous 2 lists.
|
||||
size_t dirlist_len; /**< The length of the previous 2 lists.
|
||||
*/
|
||||
|
||||
struct iso_tree_file **filelist;/* A pre-order list of files with
|
||||
struct ecma119_tree_node **filelist;
|
||||
/**< A pre-order list of files with
|
||||
* non-NULL paths and non-zero sizes.
|
||||
*/
|
||||
int filelist_len; /* Length of the previous list. */
|
||||
size_t filelist_len; /* Length of the previous list. */
|
||||
|
||||
int curfile; /* Used as a helper field for writing
|
||||
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 list might be different from
|
||||
* the lists above. */
|
||||
struct iso_tree_dir **dirlist_joliet;
|
||||
struct iso_tree_dir **pathlist_joliet;
|
||||
* 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;
|
||||
|
||||
enum ecma119_write_state state; /* The current state of the writer. */
|
||||
|
||||
/* persistent data for the various states. Each struct should not be
|
||||
* touched except for the writer of the relevant stage. When the writer
|
||||
* of the relevant stage is finished, it should set all fields to 0.
|
||||
/* 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.
|
||||
*/
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int blocks;
|
||||
unsigned char *data;
|
||||
} path_table;
|
||||
struct
|
||||
{
|
||||
size_t pos; /* The number of bytes we have written
|
||||
* so far in the current directory.
|
||||
*/
|
||||
size_t data_len;/* The number of bytes in the current
|
||||
* directory.
|
||||
*/
|
||||
unsigned char *data; /* The data (combined Directory
|
||||
* Records and susp_CE areas) of the
|
||||
* current directory.
|
||||
*/
|
||||
int dir; /* The index in dirlist that we are
|
||||
* currently writing. */
|
||||
} dir_records;
|
||||
struct
|
||||
{
|
||||
size_t pos; /* The number of bytes we have written
|
||||
* so far in the current file.
|
||||
*/
|
||||
size_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. */
|
||||
} files;
|
||||
} state_data;
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -198,23 +138,130 @@ struct ecma119_write_target
|
||||
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
|
||||
*/
|
||||
struct ecma119_write_target *ecma119_target_new(struct iso_volset *volset,
|
||||
int volnum);
|
||||
int volnum,
|
||||
int level,
|
||||
int flags);
|
||||
|
||||
/** Macros to help with casting between node_write_info and dir/file_write_info.
|
||||
#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_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.
|
||||
*/
|
||||
#define DIR_INF(a) ( (struct dir_write_info*) (a) )
|
||||
#define FILE_INF(a) ( (struct file_write_info*) (a) )
|
||||
#define NODE_INF(a) ( (struct node_write_info*) (a) )
|
||||
void
|
||||
ecma119_start_chunking(struct ecma119_write_target *t,
|
||||
void (*)(struct ecma119_write_target*, uint8_t*),
|
||||
off_t size,
|
||||
uint8_t *buf);
|
||||
|
||||
#define GET_DIR_INF(a) ( (struct dir_write_info*) (a)->writer_data )
|
||||
#define GET_FILE_INF(a) ( (struct file_write_info*) (a)->writer_data )
|
||||
#define GET_NODE_INF(a) ( (struct node_write_info*) (a)->writer_data )
|
||||
|
||||
#define TARGET_ROOT(t) ( (t)->volset->volume[(t)->volnum]->root )
|
||||
|
||||
#define NODE_NAMELEN(n,i) strlen(iso_tree_node_get_name(ISO_NODE(n), i))
|
||||
#define NODE_JOLLEN(n) ucslen(iso_tree_node_get_name(ISO_NODE(n), \
|
||||
ISO_NAME_JOLIET))
|
||||
|
||||
|
||||
#endif /* __ISO_ECMA119 */
|
||||
#endif /* LIBISO_ECMA119_H */
|
||||
|
@ -9,10 +9,11 @@
|
||||
* - Write the volume to a file or create a burn source for use with Libburn.
|
||||
*/
|
||||
|
||||
#ifndef __LIBISOFS
|
||||
#define __LIBISOFS
|
||||
#ifndef LIBISO_LIBISOFS_H
|
||||
#define LIBISO_LIBISOFS_H
|
||||
|
||||
#include "libburn/libburn.h"
|
||||
/* #include <libburn.h> */
|
||||
struct burn_source;
|
||||
|
||||
/**
|
||||
* Data volume.
|
||||
@ -27,35 +28,11 @@ struct iso_volume;
|
||||
struct iso_volset;
|
||||
|
||||
/**
|
||||
* Directory on a volume.
|
||||
* @see tree.h for details.
|
||||
*/
|
||||
struct iso_tree_dir;
|
||||
|
||||
/**
|
||||
* File on a volume.
|
||||
* @see tree.h for details.
|
||||
*/
|
||||
struct iso_tree_file;
|
||||
|
||||
/**
|
||||
* Either a file or a directory.
|
||||
* A node in the filesystem tree.
|
||||
* \see tree.h
|
||||
*/
|
||||
struct iso_tree_node;
|
||||
|
||||
/**
|
||||
* Possible versions of a file or directory name or identifier.
|
||||
*/
|
||||
enum iso_name_version {
|
||||
ISO_NAME_FULL, /**< In the current locale. */
|
||||
ISO_NAME_ISO, /**< Current ISO level identifier. */
|
||||
ISO_NAME_ISO_L1, /**< ISO level 1 identifier. */
|
||||
ISO_NAME_ISO_L2, /**< ISO level 2 identifier. */
|
||||
ISO_NAME_ROCKRIDGE, /**< Rock Ridge file or directory name. */
|
||||
ISO_NAME_JOLIET /**< Joliet identifier. */
|
||||
};
|
||||
|
||||
enum ecma119_extension_flag {
|
||||
ECMA119_ROCKRIDGE = (1<<0),
|
||||
ECMA119_JOLIET = (1<<1)
|
||||
@ -69,6 +46,11 @@ struct iso_volume *iso_volume_new(const char *volume_id,
|
||||
const char *publisher_id,
|
||||
const char *data_preparer_id);
|
||||
|
||||
struct iso_volume *iso_volume_new_with_root(const char *volume_id,
|
||||
const char *publisher_id,
|
||||
const char *data_preparer_id,
|
||||
struct iso_tree_node *root);
|
||||
|
||||
/**
|
||||
* Free a volume.
|
||||
*/
|
||||
@ -77,7 +59,7 @@ void iso_volume_free(struct iso_volume *volume);
|
||||
/**
|
||||
* Get the root directory for a volume.
|
||||
*/
|
||||
struct iso_tree_dir *iso_volume_get_root(const struct iso_volume *volume);
|
||||
struct iso_tree_node *iso_volume_get_root(const struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Fill in the volume identifier for a volume.
|
||||
@ -97,37 +79,6 @@ void iso_volume_set_publisher_id(struct iso_volume *volume,
|
||||
void iso_volume_set_data_preparer_id(struct iso_volume *volume,
|
||||
const char *data_preparer_id);
|
||||
|
||||
/**
|
||||
* Get the current ISO level for a volume.
|
||||
*/
|
||||
int iso_volume_get_iso_level(const struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Set the current ISO level for a volume.
|
||||
* ISO level must be 1 or 2.
|
||||
*/
|
||||
void iso_volume_set_iso_level(struct iso_volume *volume, int level);
|
||||
|
||||
/**
|
||||
* See if Rock Ridge (POSIX) is enabled for a volume.
|
||||
*/
|
||||
int iso_volume_get_rockridge(const struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Enable or disable Rock Ridge (POSIX) for a volume.
|
||||
*/
|
||||
void iso_volume_set_rockridge(struct iso_volume *volume, int rockridge);
|
||||
|
||||
/**
|
||||
* See if Joliet (Unicode) is enabled for a volume.
|
||||
*/
|
||||
int iso_volume_get_joliet(const struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Enable or disable Joliet (Unicode) for a volume.
|
||||
*/
|
||||
void iso_volume_set_joliet(struct iso_volume *volume, int joliet);
|
||||
|
||||
/**
|
||||
* Create a new Volume Set consisting of only one volume.
|
||||
* @param volume The first and only volume for the volset to contain.
|
||||
@ -142,28 +93,14 @@ struct iso_volset *iso_volset_new(struct iso_volume *volume,
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the file.
|
||||
*
|
||||
* \pre \p parent is non-NULL
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p path is non-NULL and is a valid path to a non-directory on the local
|
||||
* filesystem.
|
||||
* \return An iso_tree_file whose path is \p path and whose parent is \p parent.
|
||||
* \return An iso_tree_node whose path is \p path and whose parent is \p parent.
|
||||
*/
|
||||
struct iso_tree_file *iso_tree_add_file(struct iso_tree_dir *parent,
|
||||
struct iso_tree_node *iso_tree_add_node(struct iso_tree_node *parent,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Add a directory from the local filesystem to the tree.
|
||||
* Warning: this only adds the directory itself, no files or subdirectories.
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the directory.
|
||||
*
|
||||
* \pre \p parent is non-NULL
|
||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||
* filesystem.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_dir *iso_tree_add_dir(struct iso_tree_dir *parent,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Recursively add an existing directory to the tree.
|
||||
* Warning: when using this, you'll lose pointers to files or subdirectories.
|
||||
@ -172,18 +109,18 @@ struct iso_tree_dir *iso_tree_add_dir(struct iso_tree_dir *parent,
|
||||
*
|
||||
* \param path The path, on the local filesystem, of the directory to add.
|
||||
*
|
||||
* \pre \p parent is non-NULL
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p path is non-NULL and is a valid path to a directory on the local
|
||||
* filesystem.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_dir *iso_tree_radd_dir(struct iso_tree_dir *parent,
|
||||
const char *path);
|
||||
struct iso_tree_node *iso_tree_radd_dir(struct iso_tree_node *parent,
|
||||
const char *path);
|
||||
|
||||
/**
|
||||
* Creates a new, empty directory on the volume.
|
||||
*
|
||||
* \pre \p parent is non-NULL
|
||||
* \pre \p parent is NULL or is a directory.
|
||||
* \pre \p name is unique among the children and files belonging to \p parent.
|
||||
* Also, it doesn't contain '/' characters.
|
||||
*
|
||||
@ -191,35 +128,20 @@ struct iso_tree_dir *iso_tree_radd_dir(struct iso_tree_dir *parent,
|
||||
* POSIX attributes are the same as \p parent's.
|
||||
* \return a pointer to the newly created directory.
|
||||
*/
|
||||
struct iso_tree_dir *iso_tree_add_new_dir(struct iso_tree_dir *parent,
|
||||
const char *name);
|
||||
struct iso_tree_node *iso_tree_add_new_dir(struct iso_tree_node *parent,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Get the name of a node.
|
||||
* Set the name of a file (using the current locale).
|
||||
*/
|
||||
const char *iso_tree_node_get_name(const struct iso_tree_node *node,
|
||||
enum iso_name_version ver);
|
||||
|
||||
/**
|
||||
* Set the name of a file.
|
||||
* The name you input here will be the full name and will be used to derive the
|
||||
* ISO, RockRidge and Joliet names.
|
||||
*/
|
||||
void iso_tree_file_set_name(struct iso_tree_file *file, const char *name);
|
||||
|
||||
/**
|
||||
* Set the name of a directory.
|
||||
* The name you input here will be the full name and will be used to derive the
|
||||
* ISO, RockRidge and Joliet names.
|
||||
*/
|
||||
void iso_tree_dir_set_name(struct iso_tree_dir *dir, const char *name);
|
||||
void iso_tree_node_set_name(struct iso_tree_node *file, const char *name);
|
||||
|
||||
/**
|
||||
* Recursively print a directory to stdout.
|
||||
* \param spaces The initial number of spaces on the left. Set to 0 if you
|
||||
* supply a root directory.
|
||||
*/
|
||||
void iso_tree_print(const struct iso_tree_dir *root, int spaces);
|
||||
void iso_tree_print(const struct iso_tree_node *root, int spaces);
|
||||
|
||||
/** Create a burn_source which can be used as a data source for a track
|
||||
*
|
||||
@ -240,4 +162,4 @@ struct burn_source* iso_source_new_ecma119 (struct iso_volset *volumeset,
|
||||
int level,
|
||||
int flags);
|
||||
|
||||
#endif /* __LIBISOFS */
|
||||
#endif /* LIBISO_LIBISOFS_H */
|
||||
|
@ -1,10 +1,10 @@
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
#include "rockridge.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "ecma119.h"
|
||||
#include "ecma119_tree.h"
|
||||
#include "tree.h"
|
||||
#include "susp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -15,53 +15,50 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* create a PX field from the permissions on the current node. */
|
||||
unsigned char *rrip_make_PX(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *node)
|
||||
uint8_t *rrip_make_PX(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *node)
|
||||
{
|
||||
unsigned char *PX = malloc(44);
|
||||
uint8_t *PX = malloc(44);
|
||||
|
||||
PX[0] = 'P';
|
||||
PX[1] = 'X';
|
||||
PX[2] = 44;
|
||||
PX[3] = 1;
|
||||
iso_bb(&PX[4], node->attrib.st_mode, 4);
|
||||
iso_bb(&PX[12], node->attrib.st_nlink, 4);
|
||||
iso_bb(&PX[20], node->attrib.st_uid, 4);
|
||||
iso_bb(&PX[28], node->attrib.st_gid, 4);
|
||||
iso_bb(&PX[36], node->attrib.st_ino, 4);
|
||||
iso_bb(&PX[4], node->iso_self->attrib.st_mode, 4);
|
||||
iso_bb(&PX[12], node->iso_self->attrib.st_nlink, 4);
|
||||
iso_bb(&PX[20], node->iso_self->attrib.st_uid, 4);
|
||||
iso_bb(&PX[28], node->iso_self->attrib.st_gid, 4);
|
||||
iso_bb(&PX[36], node->iso_self->attrib.st_ino, 4);
|
||||
return PX;
|
||||
}
|
||||
|
||||
/** See IEEE 1282 4.1.1 */
|
||||
void rrip_add_PX(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void rrip_add_PX(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
susp_append(t, node, rrip_make_PX(t, node));
|
||||
susp_append(t, &node->susp, rrip_make_PX(t, node));
|
||||
if (node->type == ECMA119_DIR) {
|
||||
susp_append(t, &node->dir.self_susp, rrip_make_PX(t, node));
|
||||
susp_append(t, &node->dir.parent_susp, rrip_make_PX(t, node));
|
||||
}
|
||||
}
|
||||
|
||||
void rrip_add_PX_dir(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
void rrip_add_PN(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
susp_append(t, ISO_NODE(dir), rrip_make_PX(t, ISO_NODE(dir)));
|
||||
susp_append_self(t, dir, rrip_make_PX(t, ISO_NODE(dir)));
|
||||
susp_append_parent(t, dir, rrip_make_PX(t, ISO_NODE(dir)));
|
||||
}
|
||||
|
||||
void rrip_add_PN(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
{
|
||||
unsigned char *PN = malloc(20);
|
||||
uint8_t *PN = malloc(20);
|
||||
|
||||
PN[0] = 'P';
|
||||
PN[1] = 'N';
|
||||
PN[2] = 20;
|
||||
PN[3] = 1;
|
||||
iso_bb(&PN[4], node->attrib.st_dev >> 32, 4);
|
||||
iso_bb(&PN[12], node->attrib.st_dev & 0xffffffff, 4);
|
||||
susp_append(t, node, PN);
|
||||
iso_bb(&PN[4], node->iso_self->attrib.st_dev >> 32, 4);
|
||||
iso_bb(&PN[12], node->iso_self->attrib.st_dev & 0xffffffff, 4);
|
||||
susp_append(t, &node->susp, PN);
|
||||
}
|
||||
|
||||
static void rrip_SL_append_comp(int *n, unsigned char ***comps,
|
||||
static void rrip_SL_append_comp(int *n, uint8_t ***comps,
|
||||
char *s, int size, char fl)
|
||||
{
|
||||
unsigned char *comp = malloc(size + 2);
|
||||
uint8_t *comp = malloc(size + 2);
|
||||
|
||||
(*n)++;
|
||||
comp[0] = fl;
|
||||
@ -75,7 +72,7 @@ static void rrip_SL_append_comp(int *n, unsigned char ***comps,
|
||||
}
|
||||
|
||||
static void rrip_SL_add_component(char *prev, char *cur, int *n_comp,
|
||||
unsigned char ***comps)
|
||||
uint8_t ***comps)
|
||||
{
|
||||
int size = cur - prev;
|
||||
|
||||
@ -103,24 +100,24 @@ static void rrip_SL_add_component(char *prev, char *cur, int *n_comp,
|
||||
rrip_SL_append_comp(n_comp, comps, prev, size, 0);
|
||||
}
|
||||
|
||||
void rrip_add_SL(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void rrip_add_SL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
int ret, pathsize = 0;
|
||||
char *path = NULL, *cur, *prev;
|
||||
struct iso_tree_file *file = (struct iso_tree_file *)node;
|
||||
int i, j;
|
||||
|
||||
unsigned char **comp = NULL;
|
||||
uint8_t **comp = NULL;
|
||||
int n_comp = 0;
|
||||
int total_comp_len = 0;
|
||||
int written = 0, pos;
|
||||
|
||||
unsigned char *SL;
|
||||
uint8_t *SL;
|
||||
|
||||
do {
|
||||
pathsize += 128;
|
||||
path = realloc(path, pathsize);
|
||||
ret = readlink(file->path, path, pathsize);
|
||||
/* FIXME: what if the file is not on the local fs? */
|
||||
ret = readlink(node->iso_self->loc.path, path, pathsize);
|
||||
} while (ret == pathsize);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Error: couldn't read symlink: %s\n",
|
||||
@ -156,7 +153,7 @@ void rrip_add_SL(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
memcpy(&SL[pos], comp[j], comp[j][2]);
|
||||
pos += comp[j][2];
|
||||
}
|
||||
susp_append(t, node, SL);
|
||||
susp_append(t, &node->susp, SL);
|
||||
written = i - 1;
|
||||
total_comp_len = comp[i][1];
|
||||
}
|
||||
@ -173,7 +170,7 @@ void rrip_add_SL(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
memcpy(&SL[pos], comp[j], comp[j][1] + 2);
|
||||
pos += comp[j][1] + 2;
|
||||
}
|
||||
susp_append(t, node, SL);
|
||||
susp_append(t, &node->susp, SL);
|
||||
|
||||
free(path);
|
||||
/* free the components */
|
||||
@ -184,10 +181,10 @@ void rrip_add_SL(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
}
|
||||
|
||||
static void rrip_add_NM_single(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *node,
|
||||
struct susp_info *susp,
|
||||
char *name, int size, int flags)
|
||||
{
|
||||
unsigned char *NM = malloc(size + 5);
|
||||
uint8_t *NM = malloc(size + 5);
|
||||
|
||||
NM[0] = 'N';
|
||||
NM[1] = 'M';
|
||||
@ -197,103 +194,107 @@ static void rrip_add_NM_single(struct ecma119_write_target *t,
|
||||
if (size) {
|
||||
memcpy(&NM[5], name, size);
|
||||
}
|
||||
susp_append(t, node, NM);
|
||||
susp_append(t, susp, NM);
|
||||
}
|
||||
|
||||
void rrip_add_NM(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void
|
||||
rrip_add_NM(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
struct iso_tree_file *file = (struct iso_tree_file *)node;
|
||||
int len = strlen(file->name.rockridge);
|
||||
char *pos = file->name.rockridge;
|
||||
char *name = iso_p_fileid(node->iso_self->name);
|
||||
int len = name ? strlen(name) : 0;
|
||||
char *pos = name;
|
||||
|
||||
if (len == 1 && pos[0] == '.') {
|
||||
rrip_add_NM_single(t, node, pos, 0, 1 << 1);
|
||||
return;
|
||||
}
|
||||
if (len == 2 && !strncmp(pos, "..", 2)) {
|
||||
rrip_add_NM_single(t, node, pos, 0, 1 << 2);
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
if (node->type == ECMA119_DIR) {
|
||||
rrip_add_NM_single(t, &node->dir.self_susp, pos, 0, 1 << 1);
|
||||
rrip_add_NM_single(t, &node->dir.parent_susp, pos, 0, 1 << 2);
|
||||
}
|
||||
|
||||
while (len > 250) {
|
||||
rrip_add_NM_single(t, node, pos, 250, 1);
|
||||
rrip_add_NM_single(t, &node->susp, pos, 250, 1);
|
||||
len -= 250;
|
||||
pos += 250;
|
||||
}
|
||||
rrip_add_NM_single(t, node, pos, len, 0);
|
||||
rrip_add_NM_single(t, &node->susp, pos, len, 0);
|
||||
}
|
||||
|
||||
void rrip_add_CL(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void rrip_add_CL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
unsigned char *CL = calloc(1, 12);
|
||||
uint8_t *CL = calloc(1, 12);
|
||||
|
||||
CL[0] = 'C';
|
||||
CL[1] = 'L';
|
||||
CL[2] = 12;
|
||||
CL[3] = 1;
|
||||
susp_append(t, node, CL);
|
||||
susp_append(t, &node->susp, CL);
|
||||
}
|
||||
|
||||
void rrip_add_PL(struct ecma119_write_target *t, struct iso_tree_dir *node)
|
||||
void
|
||||
rrip_add_PL(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
unsigned char *PL = calloc(1, 12);
|
||||
uint8_t *PL = calloc(1, 12);
|
||||
|
||||
PL[0] = 'P';
|
||||
PL[1] = 'L';
|
||||
PL[2] = 12;
|
||||
PL[3] = 1;
|
||||
susp_append_parent(t, node, PL);
|
||||
susp_append(t, &node->dir.parent_susp, PL);
|
||||
}
|
||||
|
||||
void rrip_add_RE(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void
|
||||
rrip_add_RE(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
unsigned char *RE = malloc(4);
|
||||
uint8_t *RE = malloc(4);
|
||||
|
||||
RE[0] = 'R';
|
||||
RE[1] = 'E';
|
||||
RE[2] = 4;
|
||||
RE[3] = 1;
|
||||
susp_append(t, node, RE);
|
||||
susp_append(t, &node->susp, RE);
|
||||
}
|
||||
|
||||
void rrip_add_TF(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void
|
||||
rrip_add_TF(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
unsigned char *TF = malloc(5 + 3 * 17);
|
||||
uint8_t *TF = malloc(5 + 3 * 7);
|
||||
|
||||
TF[0] = 'T';
|
||||
TF[1] = 'F';
|
||||
TF[2] = 5 + 3 * 17;
|
||||
TF[2] = 5 + 3 * 7;
|
||||
TF[3] = 1;
|
||||
TF[4] = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7);
|
||||
iso_datetime_17(&TF[5], node->attrib.st_mtime);
|
||||
iso_datetime_17(&TF[22], node->attrib.st_atime);
|
||||
iso_datetime_17(&TF[39], node->attrib.st_ctime);
|
||||
susp_append(t, node, TF);
|
||||
iso_datetime_7(&TF[5], node->iso_self->attrib.st_mtime);
|
||||
iso_datetime_7(&TF[12], node->iso_self->attrib.st_atime);
|
||||
iso_datetime_7(&TF[19], node->iso_self->attrib.st_ctime);
|
||||
susp_append(t, &node->susp, TF);
|
||||
}
|
||||
|
||||
void rrip_finalize(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
void
|
||||
rrip_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
struct dir_write_info *inf;
|
||||
struct file_write_info *finf;
|
||||
int i;
|
||||
|
||||
inf = dir->writer_data;
|
||||
if (dir->parent != inf->real_parent) {
|
||||
unsigned char *PL = susp_find(&inf->parent_susp, "PL");
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
iso_bb(&PL[4], inf->real_parent->block, 4);
|
||||
if (dir->parent != dir->dir.real_parent) {
|
||||
uint8_t *PL = susp_find(&dir->dir.parent_susp, "PL");
|
||||
|
||||
assert(PL);
|
||||
iso_bb(&PL[4], dir->dir.real_parent->block, 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->nfiles; i++) {
|
||||
finf = dir->files[i]->writer_data;
|
||||
if (finf->real_me) {
|
||||
unsigned char *CL = susp_find(&finf->susp, "CL");
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
|
||||
iso_bb(&CL[4], finf->real_me->block, 4);
|
||||
if (ch->type == ECMA119_FILE && ch->file.real_me) {
|
||||
uint8_t *CL = susp_find(&ch->susp, "CL");
|
||||
|
||||
assert(CL);
|
||||
iso_bb(&CL[4], ch->file.real_me->block, 4);
|
||||
} else if (ch->type == ECMA119_DIR) {
|
||||
rrip_finalize(t, ch);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
rrip_finalize(t, dir->children[i]);
|
||||
}
|
||||
}
|
||||
|
@ -2,29 +2,25 @@
|
||||
|
||||
/** Functions and structures used for Rock Ridge support. */
|
||||
|
||||
#ifndef __ISO_ROCKRIDGE
|
||||
#define __ISO_ROCKRIDGE
|
||||
#ifndef ISO_ROCKRIDGE_H
|
||||
#define ISO_ROCKRIDGE_H
|
||||
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
struct iso_tree_dir;
|
||||
struct ecma119_tree_node;
|
||||
|
||||
void rrip_add_PX(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_PN(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_SL(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_NM(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_CL(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_RE(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_TF(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void rrip_add_PX(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_PN(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_SL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_NM(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_CL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_RE(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
void rrip_add_TF(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/* This is special because it doesn't modify the susp fields of the directory
|
||||
* that gets passed to it; it modifies the susp fields of the ".." entry in
|
||||
* that directory. */
|
||||
void rrip_add_PL(struct ecma119_write_target *, struct iso_tree_dir *);
|
||||
void rrip_add_PL(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/* Add a PX field to the susp, self_susp and parent_susp entries */
|
||||
void rrip_add_PX_dir(struct ecma119_write_target *, struct iso_tree_dir *);
|
||||
void rrip_finalize(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
void rrip_finalize(struct ecma119_write_target *, struct iso_tree_dir *);
|
||||
|
||||
#endif /* __ISO_ROCKRIDGE */
|
||||
#endif /* ISO_ROCKRIDGE_H */
|
||||
|
216
libisofs/susp.c
216
libisofs/susp.c
@ -1,20 +1,25 @@
|
||||
/* vim: set noet ts=8 sts=8 sw=8 : */
|
||||
|
||||
#include "susp.h"
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "ecma119.h"
|
||||
#include "ecma119_tree.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static void susp_insert_direct(struct ecma119_write_target *t,
|
||||
struct susp_info *susp, unsigned char *data,
|
||||
int pos)
|
||||
void susp_insert(struct ecma119_write_target *t,
|
||||
struct susp_info *susp,
|
||||
uint8_t *data,
|
||||
int pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pos < 0) {
|
||||
pos = susp->n_susp_fields;
|
||||
}
|
||||
|
||||
assert(pos <= susp->n_susp_fields);
|
||||
susp->n_susp_fields++;
|
||||
susp->susp_fields = realloc(susp->susp_fields,
|
||||
@ -27,60 +32,13 @@ static void susp_insert_direct(struct ecma119_write_target *t,
|
||||
}
|
||||
|
||||
void susp_append(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *node, unsigned char *data)
|
||||
struct susp_info *susp,
|
||||
uint8_t *data)
|
||||
{
|
||||
struct dir_write_info *inf = node->writer_data;
|
||||
struct susp_info *susp = &inf->susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, susp->n_susp_fields);
|
||||
susp_insert(t, susp, data, susp->n_susp_fields);
|
||||
}
|
||||
|
||||
void susp_append_self(struct ecma119_write_target *t,
|
||||
struct iso_tree_dir *dir, unsigned char *data)
|
||||
{
|
||||
struct dir_write_info *inf = dir->writer_data;
|
||||
struct susp_info *susp = &inf->self_susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, susp->n_susp_fields);
|
||||
}
|
||||
|
||||
void susp_append_parent(struct ecma119_write_target *t,
|
||||
struct iso_tree_dir *dir, unsigned char *data)
|
||||
{
|
||||
struct dir_write_info *inf = dir->writer_data;
|
||||
struct susp_info *susp = &inf->parent_susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, susp->n_susp_fields);
|
||||
}
|
||||
|
||||
void susp_insert(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *node, unsigned char *data, int pos)
|
||||
{
|
||||
struct dir_write_info *inf = node->writer_data;
|
||||
struct susp_info *susp = &inf->susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, pos);
|
||||
}
|
||||
|
||||
void susp_insert_self(struct ecma119_write_target *t,
|
||||
struct iso_tree_dir *dir, unsigned char *data, int pos)
|
||||
{
|
||||
struct dir_write_info *inf = dir->writer_data;
|
||||
struct susp_info *susp = &inf->self_susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, pos);
|
||||
}
|
||||
|
||||
void susp_insert_parent(struct ecma119_write_target *t,
|
||||
struct iso_tree_dir *dir, unsigned char *data, int pos)
|
||||
{
|
||||
struct dir_write_info *inf = dir->writer_data;
|
||||
struct susp_info *susp = &inf->parent_susp;
|
||||
|
||||
susp_insert_direct(t, susp, data, pos);
|
||||
}
|
||||
|
||||
unsigned char *susp_find(struct susp_info *susp, const char *name)
|
||||
uint8_t *susp_find(struct susp_info *susp, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -92,11 +50,15 @@ unsigned char *susp_find(struct susp_info *susp, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* utility function for susp_add_CE because susp_add_CE needs to act 3 times
|
||||
* on directories (for the "." and ".." entries. */
|
||||
/** Utility function for susp_add_CE because susp_add_CE needs to act 3 times
|
||||
* on directories (for the "." and ".." entries.
|
||||
*
|
||||
* \param len The amount of space available for the System Use area.
|
||||
*/
|
||||
#define CE_LEN 28
|
||||
static unsigned char *susp_add_single_CE(struct ecma119_write_target *t,
|
||||
struct susp_info *susp, int len)
|
||||
struct susp_info *susp,
|
||||
int len)
|
||||
{
|
||||
int susp_length = 0, tmp_len;
|
||||
int i;
|
||||
@ -138,33 +100,36 @@ static unsigned char *susp_add_single_CE(struct ecma119_write_target *t,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
try_add_CE(struct ecma119_write_target *t,
|
||||
struct susp_info *susp,
|
||||
size_t dirent_len)
|
||||
{
|
||||
uint8_t *CE = susp_add_single_CE(t, susp, 255 - dirent_len);
|
||||
if (CE)
|
||||
susp_insert(t, susp, CE, susp->n_fields_fit - 1);
|
||||
}
|
||||
|
||||
/** See IEEE P1281 Draft Version 1.12/5.2. Because this function depends on the
|
||||
* length of the other SUSP fields, it should always be calculated last. */
|
||||
void susp_add_CE(struct ecma119_write_target *t, struct iso_tree_node *node)
|
||||
void
|
||||
susp_add_CE(struct ecma119_write_target *t, struct ecma119_tree_node *node)
|
||||
{
|
||||
struct dir_write_info *inf = node->writer_data;
|
||||
unsigned char *CE;
|
||||
|
||||
CE = susp_add_single_CE(t, &inf->susp, 255 - node->dirent_len);
|
||||
if (CE)
|
||||
susp_insert(t, node, CE, inf->susp.n_fields_fit - 1);
|
||||
if (S_ISDIR(node->attrib.st_mode)) {
|
||||
CE = susp_add_single_CE(t, &inf->self_susp, 255 - 34);
|
||||
if (CE)
|
||||
susp_insert_self(t, (struct iso_tree_dir *)node, CE,
|
||||
inf->self_susp.n_fields_fit - 1);
|
||||
CE = susp_add_single_CE(t, &inf->parent_susp, 255 - 34);
|
||||
if (CE)
|
||||
susp_insert_parent(t, (struct iso_tree_dir *)node, CE,
|
||||
inf->parent_susp.n_fields_fit - 1);
|
||||
try_add_CE(t, &node->susp, node->dirent_len);
|
||||
if (node->type == ECMA119_DIR) {
|
||||
try_add_CE(t, &node->dir.self_susp, 34);
|
||||
try_add_CE(t, &node->dir.parent_susp, 34);
|
||||
}
|
||||
}
|
||||
|
||||
/** See IEEE P1281 Draft Version 1.12/5.3 */
|
||||
void susp_add_SP(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
void
|
||||
susp_add_SP(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
unsigned char *SP = malloc(7);
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
SP[0] = 'S';
|
||||
SP[1] = 'P';
|
||||
SP[2] = (char)7;
|
||||
@ -172,7 +137,7 @@ void susp_add_SP(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
SP[4] = 0xbe;
|
||||
SP[5] = 0xef;
|
||||
SP[6] = 0;
|
||||
susp_append_self(t, dir, SP);
|
||||
susp_append(t, &dir->dir.self_susp, SP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -190,11 +155,14 @@ static void susp_add_ST(struct ecma119_write_target *t,
|
||||
}
|
||||
#endif
|
||||
|
||||
/** See IEEE P1281 Draft Version 1.12/5.5 */
|
||||
void susp_add_ER(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
/** See IEEE P1281 Draft Version 1.12/5.5 FIXME: this is rockridge */
|
||||
void
|
||||
rrip_add_ER(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
unsigned char *ER = malloc(182);
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
ER[0] = 'E';
|
||||
ER[1] = 'R';
|
||||
ER[2] = 182;
|
||||
@ -208,71 +176,71 @@ void susp_add_ER(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
"FILE SYSTEM SEMANTICS.", 72);
|
||||
memcpy(&ER[89], "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, "
|
||||
"PISCATAWAY, NJ, USA FOR THE 1282 SPECIFICATION.", 93);
|
||||
susp_append_self(t, dir, ER);
|
||||
susp_append(t, &dir->dir.self_susp, ER);
|
||||
}
|
||||
|
||||
/* calculate the location of the CE areas. Since CE areas don't need to be
|
||||
* aligned to a block boundary, we contatenate all CE areas from a single
|
||||
* directory and dump them immediately after all the directory records.
|
||||
*
|
||||
* Requires that the following be known:
|
||||
* - position of the current directory (dir->block)
|
||||
* - length of the current directory (dir->dir.len)
|
||||
* - sum of the children's CE lengths (dir->dir.CE_len)
|
||||
*/
|
||||
static void
|
||||
susp_fin_1_CE(struct ecma119_write_target *t,
|
||||
struct susp_info *susp,
|
||||
size_t block,
|
||||
size_t *offset)
|
||||
{
|
||||
uint8_t *CE = susp->susp_fields[susp->n_fields_fit - 1];
|
||||
|
||||
if (!susp->CE_len) {
|
||||
return;
|
||||
}
|
||||
iso_bb(&CE[4], block + (*offset) / t->block_size, 4);
|
||||
iso_bb(&CE[12], (*offset) % t->block_size, 4);
|
||||
*offset += susp->CE_len;
|
||||
}
|
||||
|
||||
static void susp_fin_CE(struct ecma119_write_target *t,
|
||||
struct iso_tree_dir *dir)
|
||||
struct ecma119_tree_node *dir)
|
||||
{
|
||||
struct dir_write_info *inf = (struct dir_write_info *)
|
||||
dir->writer_data;
|
||||
struct node_write_info *cinf;
|
||||
unsigned char *CE;
|
||||
int i;
|
||||
int CE_offset = inf->len;
|
||||
size_t CE_offset = dir->dir.len;
|
||||
|
||||
if (inf->self_susp.CE_len) {
|
||||
CE = inf->self_susp.susp_fields[inf->self_susp.n_fields_fit -
|
||||
1];
|
||||
iso_bb(&CE[4], dir->block + CE_offset / 2048, 4);
|
||||
iso_bb(&CE[12], CE_offset % 2048, 4);
|
||||
CE_offset += inf->self_susp.CE_len;
|
||||
}
|
||||
if (inf->parent_susp.CE_len) {
|
||||
CE = inf->parent_susp.susp_fields[inf->parent_susp.
|
||||
n_fields_fit - 1];
|
||||
iso_bb(&CE[4], dir->block + CE_offset / 2048, 4);
|
||||
iso_bb(&CE[12], CE_offset % 2048, 4);
|
||||
CE_offset += inf->parent_susp.CE_len;
|
||||
}
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
cinf = dir->children[i]->writer_data;
|
||||
if (!cinf->susp.CE_len) {
|
||||
continue;
|
||||
}
|
||||
CE = cinf->susp.susp_fields[cinf->susp.n_fields_fit - 1];
|
||||
iso_bb(&CE[4], dir->block + CE_offset / 2048, 4);
|
||||
iso_bb(&CE[12], CE_offset % 2048, 4);
|
||||
CE_offset += cinf->susp.CE_len;
|
||||
susp_fin_1_CE(t, &dir->dir.self_susp, dir->block, &CE_offset);
|
||||
susp_fin_1_CE(t, &dir->dir.parent_susp, dir->block, &CE_offset);
|
||||
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->dir.children[i];
|
||||
susp_fin_1_CE(t, &ch->susp, dir->block, &CE_offset);
|
||||
}
|
||||
for (i = 0; i < dir->nfiles; i++) {
|
||||
cinf = dir->files[i]->writer_data;
|
||||
if (!cinf->susp.CE_len) {
|
||||
continue;
|
||||
}
|
||||
CE = cinf->susp.susp_fields[cinf->susp.n_fields_fit - 1];
|
||||
iso_bb(&CE[4], dir->block + CE_offset / 2048, 4);
|
||||
iso_bb(&CE[12], CE_offset % 2048, 4);
|
||||
CE_offset += cinf->susp.CE_len;
|
||||
}
|
||||
assert(CE_offset == inf->len + inf->susp_len);
|
||||
assert(CE_offset == dir->dir.len + dir->dir.CE_len);
|
||||
}
|
||||
|
||||
void susp_finalize(struct ecma119_write_target *t, struct iso_tree_dir *dir)
|
||||
void
|
||||
susp_finalize(struct ecma119_write_target *t, struct ecma119_tree_node *dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dir->depth != 1) {
|
||||
assert(dir->type = ECMA119_DIR);
|
||||
|
||||
if (dir->dir.depth != 1) {
|
||||
susp_fin_CE(t, dir);
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->nchildren; i++) {
|
||||
susp_finalize(t, dir->children[i]);
|
||||
for (i = 0; i < dir->dir.nchildren; i++) {
|
||||
if (dir->dir.children[i]->type == ECMA119_DIR)
|
||||
susp_finalize(t, dir->dir.children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void susp_write(struct ecma119_write_target *t, struct susp_info *susp,
|
||||
void susp_write(struct ecma119_write_target *t,
|
||||
struct susp_info *susp,
|
||||
unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
|
@ -6,17 +6,18 @@
|
||||
#ifndef __ISO_SUSP
|
||||
#define __ISO_SUSP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* SUSP is only present in standard ecma119 */
|
||||
struct ecma119_write_target;
|
||||
struct iso_tree_node;
|
||||
struct iso_tree_dir;
|
||||
struct ecma119_tree_node;
|
||||
|
||||
/** This contains the information that needs to go in the SUSP area of a file.
|
||||
*/
|
||||
struct susp_info
|
||||
{
|
||||
int n_susp_fields; /**< Number of SUSP fields */
|
||||
unsigned char **susp_fields; /**< Data for each SUSP field */
|
||||
uint8_t **susp_fields; /**< Data for each SUSP field */
|
||||
|
||||
/* the next 3 relate to CE and are filled out by susp_add_CE. */
|
||||
int n_fields_fit; /**< How many of the above SUSP fields fit
|
||||
@ -27,48 +28,34 @@ struct susp_info
|
||||
* will go in a CE area. */
|
||||
};
|
||||
|
||||
void susp_add_CE(struct ecma119_write_target *, struct iso_tree_node *);
|
||||
void susp_add_CE(struct ecma119_write_target *, struct ecma119_tree_node *);
|
||||
|
||||
/* these next 2 are special because they don't modify the susp fields of the
|
||||
* directory that gets passed to them; they modify the susp fields of the |