First pinch of libisofs rewrite

trunk@386
Mario Danic 17 years ago
parent 176e1654ff
commit 48d76e844e
  1. 33
      Makefile.am
  2. 23
      libisofs/Makefile.am
  3. 1896
      libisofs/ecma119.c
  4. 297
      libisofs/ecma119.h
  5. 126
      libisofs/libisofs.h
  6. 163
      libisofs/rockridge.c
  7. 30
      libisofs/rockridge.h
  8. 218
      libisofs/susp.c
  9. 47
      libisofs/susp.h
  10. 472
      libisofs/tree.c
  11. 234
      libisofs/tree.h
  12. 606
      libisofs/util.c
  13. 153
      libisofs/util.h
  14. 76
      libisofs/volume.c
  15. 26
      libisofs/volume.h
  16. 51
      test/iso.c

@ -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
##noinst_PROGRAMS = test
##test_SOURCES = test.c
##test_LDADD = $(libisofs_la_OBJECTS)
INCLUDES = -I..
##INCLUDES = -I../burn/libburn
## ========================================================================= ##
indent_files = $(libisofs_la_SOURCES)

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 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) )
#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);
};
#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 )
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);
};
#define TARGET_ROOT(t) ( (t)->volset->volume[(t)->volnum]->root )
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) */
};
#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))
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 /* __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);
/**
* Get the name of a node.
*/
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);
struct iso_tree_node *iso_tree_add_new_dir(struct iso_tree_node *parent,
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.
* Set the name of a file (using the current locale).
*/
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));
}
void rrip_add_PX_dir(struct ecma119_write_target *t, struct iso_tree_dir *dir)
{
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)));
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_PN(struct ecma119_write_target *t, struct iso_tree_node *node)
void rrip_add_PN(struct ecma119_write_target *t, struct ecma119_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);
if (dir->parent != dir->dir.real_parent) {
uint8_t *PL = susp_find(&dir->dir.parent_susp, "PL");
iso_bb(&PL[4], inf->real_parent->block, 4);
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");
for (i = 0; i < dir->nchildren; i++) {
rrip_finalize(t, dir->children[i]);
assert(CL);
iso_bb(&CL[4], ch->file.real_me->block, 4);
} else if (ch->type == ECMA119_DIR) {
rrip_finalize(t, ch);
}
}
}

@ -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 */

@ -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 dir_write_info *inf = node->writer_data;
struct susp_info *susp = &inf->susp;
susp_insert_direct(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 susp_info *susp,
uint8_t *data)
{
struct dir_write_info *inf = dir->writer_data;
struct susp_info *susp = &inf->parent_susp;
susp_insert_direct(t, susp, data, pos);
susp_insert(t, susp, data, susp->n_susp_fields);
}
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;
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;
}
size_t CE_offset = dir->dir.len;
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;
}
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(dir->type == ECMA119_DIR);
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]