[Libburn] [PATCH] centralise reading/writing functions

Joe Neeman neeman at webone.com.au
Thu Jul 28 09:03:57 EST 2005


Hi all,

Attached is a patch that
- centralises the reading/writing of specific size/byteorder integers 
and presents an API that is useful for both reading and writing the same 
format.

- modifies the volume descriptor and directory record parts of ecma119.c 
to use the new functions.

- stores the Joliet volume/publisher/etc IDs instead of calculating them 
on the fly from the ISO IDs. This means that the Joliet volume IDs don't 
lose, for example, lower case characters.

Note that, since this contains a patch to libisofs/Makefile.am, it is 
necessary to have that file.

cheers,
Joe
-------------- next part --------------
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/ecma119.c libisofs/ecma119.c
--- libisofs/ecma119.c	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/ecma119.c	2005-07-24 11:16:54.000000000 +1000
@@ -4,6 +4,7 @@
 #include "ecma119.h"
 #include "volume.h"
 #include "util.h"
+#include "struct.h"
 #include "rockridge.h"
 #include "libisofs.h"
 #include "libburn/libburn.h"
@@ -17,6 +18,95 @@
 #include <errno.h>
 #include <wchar.h>
 
+const char* const ecma119_standard_id = "CD001";
+
+/* Format definitions */
+const char* const ecma119_vol_fmt = "B5bB"; /* common between all vol descs */
+
+const char* const ecma119_privol_fmt =
+	"B"	/* volume desc type */
+	"5b"	/* standard id */
+	"B"	/* volume desc version */
+	"x"
+	"32b"	/* system id */
+	"32b"	/* volume id */
+	"8x"
+	"=L"	/* volume space size */
+	"32x"
+	"=H"	/* volume set size */
+	"=H"	/* volume sequence number */
+	"=H"	/* block size */
+	"=L"	/* path table size */
+	"<L"	/* l path table 1 */
+	"<L"	/* l path table 2 */
+	">L"	/* m path table 1 */
+	">L"	/* m path table 2 */
+	"34B"	/* root directory record */
+	"128b"	/* volume id */
+	"128b"	/* publisher id */
+	"128b"	/* data preparer id */
+	"128b"	/* application id */
+	"37b"	/* copyright file id */
+	"37b"	/* abstract file id */
+	"37b"	/* bibliographic file id */
+	"T"	/* creation timestamp */
+	"T"	/* modification timestamp */
+	"T"	/* expiration timestamp */
+	"T"	/* effective timestamp */
+	"B"	/* file structure version */
+	"x"
+	"512x"	/* Application Use */
+	"653x";	/* reserved */
+
+const char* const ecma119_supvol_joliet_fmt =
+	"B"	/* volume desc type */
+	"5b"	/* standard id */
+	"B"	/* volume desc version */
+	"B"	/* volume flags */
+	"16h"	/* system id */
+	"16h"	/* volume id */
+	"8x"
+	"=L"	/* volume space size */
+	"32b"	/* escape sequences */
+	"=H"	/* volume set size */
+	"=H"	/* volume sequence number */
+	"=H"	/* block size */
+	"=L"	/* path table size */
+	"<L"	/* l path table 1 */
+	"<L"	/* l path table 2 */
+	">L"	/* m path table 1 */
+	">L"	/* m path table 2 */
+	"34B"	/* root directory record */
+	"64h"	/* volume id */
+	"64h"	/* publisher id */
+	"64h"	/* data preparer id */
+	"64h"	/* application id */
+	"18hx"	/* copyright file id */
+	"18hx"	/* abstract file id */
+	"18hx"	/* bibliographic file id */
+	"T"	/* creation timestamp */
+	"T"	/* modification timestamp */
+	"T"	/* expiration timestamp */
+	"T"	/* effective timestamp */
+	"B"	/* file structure version */
+	"x"
+	"512x"	/* Application Use */
+	"653x";	/* reserved */
+
+const char* const ecma119_dir_record_fmt =
+	"B"	/* dir record length */
+	"B"	/* extended attribute length */
+	"=L"	/* block */
+	"=L"	/* size */
+	"S"
+	"B"	/* file flags */
+	"B"	/* file unit size */
+	"B"	/* interleave gap size */
+	"=H"	/* volume sequence number */
+	"B";	/* name length */
+	/* file id ansa SU field have variable length, so they don't get defined
+	 * yet. */
+
 /* abstract string functions away from char* to make Joliet stuff easier */
 typedef void (*copy_string)(unsigned char *dest, void *str, int maxlen);
 typedef int (*node_namelen)(struct iso_tree_node *node);
@@ -28,8 +118,16 @@
 typedef int (*susp_len)(struct susp_info*);
 typedef int (*total_dirent_len)(struct iso_tree_node*);
 
-#define APPLICATION_ID "LIBBURN SUITE (C) 2002 D.FOREMAN/B.JANSENS"
-#define SYSTEM_ID "LINUX"
+const char application_id[] = "LIBBURN SUITE (C) 2002 D.FOREMAN/B.JANSENS";
+const char system_id[] = "LINUX";
+
+const uint16_t* application_id_joliet = (uint16_t*) "\0j\0a\0p\0p\0i\0d\0\0";
+const uint16_t* system_id_joliet = (uint16_t*) "\0j\0s\0y\0s\0i\0d\0\0";
+
+/* since we have to pass things by address to iso_struct_pack, this makes
+ * it easier. */
+const uint8_t zero = 0;
+const uint8_t one = 1;
 
 enum RecordType {
 	RECORD_TYPE_SELF,
@@ -53,9 +151,10 @@
 /* Writers for the different write_states. */
 static void ecma119_write_system_area(struct ecma119_write_target*,
 					unsigned char *buf);
-static void ecma119_write_vol_desc(struct ecma119_write_target*,
-				   unsigned char *buf,
-				   int flags);
+static void ecma119_write_privol_desc(struct ecma119_write_target*,
+				      unsigned char *buf);
+static void ecma119_write_supvol_desc_joliet(struct ecma119_write_target*,
+					     unsigned char *buf);
 static void ecma119_write_vol_desc_terminator(struct ecma119_write_target*,
 					unsigned char *buf);
 static void ecma119_write_path_table(struct ecma119_write_target*,
@@ -81,6 +180,21 @@
 					int flags,
 					struct iso_tree_node*,
 					enum RecordType);
+static void ecma119_write_dir_record_iso(struct ecma119_write_target *t,
+					 uint8_t *buf,
+					 struct iso_tree_node *node,
+					 enum RecordType type);
+static void ecma119_write_dir_record_joliet(struct ecma119_write_target *t,
+					    uint8_t *buf,
+					    struct iso_tree_node *node,
+					    enum RecordType type);
+static void ecma119_write_dir_record_noname(struct ecma119_write_target *t,
+					    uint8_t *buf,
+					    struct iso_tree_node *node,
+					    enum RecordType type,
+					    uint32_t block,
+					    uint32_t size,
+					    int joliet);
 
 /* string abstraction functions */
 static int node_namelen_iso(struct iso_tree_node *node)
@@ -106,39 +220,6 @@
 	return iso_tree_node_get_name(node, ISO_NAME_JOLIET);
 }
 
-static void copy_string_iso(unsigned char *dest, void *s, int len)
-{
-	char *src = (char*)s;
-	int slen = strlen(src);
-	memcpy((char*)dest, src, slen);
-
-	/* ISO specification requires padding with spaces. */
-	memset((char*)dest+slen, ' ', len-slen);
-}
-
-static void copy_string_joliet(unsigned char *dest, void *s, int len)
-{
-	uint16_t *src = (uint16_t*)s;
-	int slen = ucslen(src) * 2;
-	int i;
-
-	memcpy((char*)dest, (char*)src, MIN(slen, len));
-
-	/* set every alternate character to ' ' */
-	for (i=MIN(slen, len)+1; i<len; i += 2) {
-		dest[i] = ' ';
-	}
-}
-
-static void copy_string_joliet_conv(unsigned char *dest, void *s, int len)
-{
-	uint16_t *jstr = (uint16_t*)iso_j_str((char*)s);
-
-	len -= len%2;
-	copy_string_joliet(dest, jstr, len);
-	free(jstr);
-}
-
 static int susp_len_iso(struct susp_info *s)
 {
 	return s->non_CE_len;
@@ -535,6 +616,7 @@
 	t->curfile = 0;
 	ecma119_target_file_layout(t, TARGET_ROOT(t));
 	t->total_size = t->curblock * 2048;
+	t->vol_space_size = t->curblock;
 
 	if (t->rockridge) {
 		susp_finalize(t, TARGET_ROOT(t));
@@ -594,10 +676,10 @@
 		ecma119_write_system_area(t, data);
 		break;
 	case ECMA119_WRITE_PRI_VOL_DESC:
-		ecma119_write_vol_desc(t, data, 0);
+		ecma119_write_privol_desc(t, data);
 		break;
 	case ECMA119_WRITE_SUP_VOL_DESC_JOLIET:
-		ecma119_write_vol_desc(t, data, ECMA119_JOLIET);
+		ecma119_write_supvol_desc_joliet(t, data);
 		break;
 	case ECMA119_WRITE_VOL_DESC_TERMINATOR:
 		ecma119_write_vol_desc_terminator(t, data);
@@ -700,63 +782,94 @@
 	}
 }
 
-static void ecma119_write_vol_desc(struct ecma119_write_target *t,
-				   unsigned char *buf,
-				   int flags)
+static void ecma119_write_privol_desc(struct ecma119_write_target *t,
+				      unsigned char *buf)
 {
-	struct iso_tree_dir *root = TARGET_ROOT(t);
-	struct iso_volume *vol = root->volume;
-
-	copy_string scpy;
-
-	if (flags & ECMA119_JOLIET) {
-		scpy = copy_string_joliet_conv;
-	} else {
-		scpy = copy_string_iso;
-	}
-
-	buf[0] = 1;
-	strcpy((char*)&buf[1], "CD001");
-	buf[6] = 1;	/* volume descriptor version */
-	scpy(&buf[8], SYSTEM_ID, 32);
-	scpy(&buf[40], vol->volume_id, 32);
-	iso_bb(&buf[80], t->total_size/2048, 4);
-	iso_bb(&buf[120], 1, 2);	/* volume set size */
-	iso_bb(&buf[124], 1, 2);	/* volume sequence number */
-	iso_bb(&buf[128], 2048, 2);	/* block size */
-	iso_bb(&buf[132], t->path_table_size, 4);
-	iso_lsb(&buf[140], t->l_path_table_pos, 4);
-	iso_msb(&buf[148], t->m_path_table_pos, 4);
-	ecma119_write_dir_record(t, &buf[156], flags, ISO_NODE(root),
-				 RECORD_TYPE_ROOT);
-	scpy(&buf[190], t->volset->volset_id, 128);
-	scpy(&buf[318], vol->publisher_id, 128);
-	scpy(&buf[446], vol->data_preparer_id, 128);
-	scpy(&buf[574], APPLICATION_ID, 128);
-	scpy(&buf[702], "", 37); /* copyright */
-	scpy(&buf[739], "", 37); /* abstract */
-	scpy(&buf[776], "", 37); /* bibliography */
-	iso_datetime_17(&buf[813], t->now);
-	iso_datetime_17(&buf[830], t->now);
-	memset(&buf[847], '0', 17);
-	iso_datetime_17(&buf[864], t->now);
-	buf[881] = 1;	/* file structure version */
-
-	if (flags) {
-		buf[0] = 2;	/* we are writing a supplementary voldesc */
-		if (flags & ECMA119_JOLIET) {
-			memcpy(&buf[88], "%/E", 3);
-			iso_bb(&buf[132], t->path_table_size_joliet, 4);
-			iso_lsb(&buf[140], t->l_path_table_pos_joliet, 4);
-			iso_msb(&buf[148], t->m_path_table_pos_joliet, 4);
-		}
-	}
+	struct iso_tree_node *root = ISO_NODE(TARGET_ROOT(t));
+	struct iso_volume *vol = t->volset->volume[t->volnum];
+	uint8_t one = 1;	/* so that we can take &one */
+	uint32_t zero = 0;
+	time_t never = -1;
+	uint8_t dir_record[34];
+
+	ecma119_write_dir_record(t, dir_record, 0, root, RECORD_TYPE_ROOT);
+	iso_struct_pack(ecma119_privol_fmt, buf,
+			&one,
+			"CD001",
+			&one,
+			system_id,
+			vol->volume_id.cstr,
+			&t->vol_space_size,
+			&t->volset->volset_size,
+			&t->volnum,
+			&t->block_size,
+			&t->path_table_size,
+			&t->l_path_table_pos,
+			&zero,
+			&t->m_path_table_pos,
+			&zero,
+			dir_record,
+			t->volset->volset_id.cstr,
+			vol->publisher_id.cstr,
+			vol->data_preparer_id.cstr,
+			application_id,
+			"",
+			"",
+			"",
+			&t->now,
+			&t->now,
+			&never,
+			&t->now,
+			&one);
+
+	t->state = (t->joliet) ? ECMA119_WRITE_SUP_VOL_DESC_JOLIET :
+				 ECMA119_WRITE_VOL_DESC_TERMINATOR;
+}
+
+static void ecma119_write_supvol_desc_joliet(struct ecma119_write_target *t,
+					     unsigned char *buf)
+{	struct iso_tree_node *root = ISO_NODE(TARGET_ROOT(t));
+	struct iso_volume *vol = t->volset->volume[t->volnum];
+	uint8_t one = 1;	/* so that we can take &one */
+	uint8_t two = 2;
+	uint32_t zero = 0;
+	time_t never = -1;
+	uint8_t dir_record[34];
+
+	ecma119_write_dir_record(t, dir_record, ECMA119_JOLIET,
+				 root, RECORD_TYPE_ROOT);
+	iso_struct_pack(ecma119_supvol_joliet_fmt, buf,
+			&two,
+			"CD001",
+			&one,
+			&zero,
+			system_id_joliet,
+			vol->volume_id.jstr,
+			&t->vol_space_size,
+			"%/E",
+			&t->volset->volset_size,
+			&t->volnum,
+			&t->block_size,
+			&t->path_table_size_joliet,
+			&t->l_path_table_pos_joliet,
+			&zero,
+			&t->m_path_table_pos_joliet,
+			&zero,
+			dir_record,
+			t->volset->volset_id.jstr,
+			vol->publisher_id.jstr,
+			vol->data_preparer_id.jstr,
+			application_id_joliet,
+			&zero,
+			&zero,
+			&zero,
+			&t->now,
+			&t->now,
+			&never,
+			&t->now,
+			&one);
 
-	if (t->joliet && !flags) {
-		t->state = ECMA119_WRITE_SUP_VOL_DESC_JOLIET;
-	} else {
-		t->state = ECMA119_WRITE_VOL_DESC_TERMINATOR;
-	}
+	t->state = ECMA119_WRITE_VOL_DESC_TERMINATOR;
 }
 
 static void ecma119_write_vol_desc_terminator(struct ecma119_write_target *t,
@@ -778,7 +891,7 @@
 					  int flags,
 					  int m_type)
 {
-	void (*write_int)(unsigned char*, int, int);
+	void (*write_int)(uint8_t*, uint32_t, int);
 	struct iso_tree_dir *dir;
 	const char *name;
 	int len, parent, i;
@@ -786,16 +899,19 @@
 
 	node_namelen namelen;
 	node_getname getname;
+	off_t root_block;
 	struct iso_tree_dir **pathlist;
 
 	if (flags & ECMA119_JOLIET) {
 		namelen = node_namelen_joliet;
 		getname = node_getname_joliet;
 		pathlist = t->pathlist_joliet;
+		root_block = GET_DIR_INF(pathlist[0])->joliet_block;
 	} else {
 		namelen = node_namelen_iso;
 		getname = node_getname_iso;
 		pathlist = t->pathlist;
+		root_block = pathlist[0]->block;
 	}
 
 	write_int = m_type ? iso_msb : iso_lsb;
@@ -803,21 +919,24 @@
 	/* write the root directory */
 	buf[0] = 1;
 	buf[1] = 0;
-	write_int(&buf[2], pathlist[0]->block, 4);
+	write_int(&buf[2], root_block, 4);
 	write_int(&buf[6], 1, 2);
 
 	/* write the rest */
 	off = 10;
 	for (i=1; i<t->dirlist_len; i++) {
 		struct iso_tree_dir *dirparent;
+		off_t block;
 
 		dir = pathlist[i];
 		name = getname(ISO_NODE(dir));
 		len = namelen(ISO_NODE(dir));
 		if (flags & ECMA119_JOLIET) {
 			dirparent = GET_DIR_INF(dir)->real_parent;
+			block = GET_DIR_INF(dir)->joliet_block;
 		} else {
 			dirparent = dir->parent;
+			block = dir->block;
 		}
 
 		for (parent=0; parent<i; parent++) {
@@ -829,7 +948,7 @@
 
 		buf[off + 0] = len;
 		buf[off + 1] = 0;	/* extended attribute length */
-		write_int(&buf[off + 2], dir->block, 4);
+		write_int(&buf[off + 2], block, 4);
 		write_int(&buf[off + 6], parent + 1, 2);
 		memcpy(&buf[off + 8], name, len);
 		off += 8 + len + len % 2;
@@ -842,15 +961,23 @@
 				     int flags,
 				     int m_type)
 {
+	int path_table_size;
+
+	if (flags & ECMA119_JOLIET) {
+		path_table_size = t->path_table_size_joliet;
+	} else {
+		path_table_size = t->path_table_size;
+	}
+
 	if (!SDATA.data) {
-		SDATA.data = calloc(1, ROUND_UP(t->path_table_size, 2048));
+		SDATA.data = calloc(1, ROUND_UP(path_table_size, 2048));
 		ecma119_write_path_table_full(t, SDATA.data, flags, m_type);
 	}
 
-	memcpy(buf, SDATA.data, 2048);
+	memcpy(buf, SDATA.data + SDATA.blocks*2048, 2048);
 	SDATA.blocks++;
 
-	if (SDATA.blocks*2048 >= t->path_table_size) {
+	if (SDATA.blocks*2048 >= path_table_size) {
 		free(SDATA.data);
 		SDATA.data = NULL;
 		SDATA.blocks = 0;
@@ -1038,6 +1165,12 @@
 				     struct iso_tree_node *node,
 				     enum RecordType type)
 {
+	if (flags & ECMA119_JOLIET) {
+		ecma119_write_dir_record_joliet(t, buf, node, type);
+	} else {
+		ecma119_write_dir_record_iso(t, buf, node, type);
+	}
+#if 0
 	struct node_write_info *inf = GET_NODE_INF(node);
 	struct iso_tree_dir *parent;
 	const char *name;
@@ -1084,10 +1217,10 @@
 	buf[1] = 0; /* extended attribute length */
 	if (type == RECORD_TYPE_PARENT && parent) {
 		iso_bb(&buf[2], pblock, 4);
-		iso_bb(&buf[10], parent->attrib.st_size, 4);
+		iso_bb(&buf[10], psize, 4);
 	} else {
 		iso_bb(&buf[2], block, 4);
-		iso_bb(&buf[10], node->attrib.st_size, 4);
+		iso_bb(&buf[10], size, 4);
 	}
 	iso_datetime_7(&buf[18], t->now);
 	buf[25] = S_ISDIR(node->attrib.st_mode) ? 2 : 0; /* file flags */
@@ -1123,13 +1256,158 @@
 		if (!(flags & ECMA119_JOLIET))
 			susp_write(t, &inf->susp, &buf[node->dirent_len]);
 	}
+#endif
+}
+
+static void ecma119_write_dir_record_iso(struct ecma119_write_target *t,
+					 uint8_t *buf,
+					 struct iso_tree_node *node,
+					 enum RecordType type)
+{
+	struct node_write_info *inf = GET_NODE_INF(node);
+	uint8_t len_dr, len_fi, flags;
+	uint8_t vol_seq_num = t->volnum;
+
+	if (type == RECORD_TYPE_NORMAL) {
+		len_fi = node_namelen_iso(node);
+		len_dr = 33 + len_fi + 1 - len_fi%2 + inf->susp.non_CE_len;
+		flags = (S_ISDIR(node->attrib.st_mode)) ? 2 : 0;
+		iso_struct_pack(ecma119_dir_record_fmt, buf,
+				&len_dr,
+				&zero,
+				&node->block,
+				&node->attrib.st_size,
+				&t->now,
+				&flags,
+				&zero,
+				&zero,
+				&vol_seq_num,
+				&len_fi);
+		iso_struct_pack_long(&buf[33], len_fi, '<', 'B', 0, 0, 0,
+				     node_getname_iso(node));
+		susp_write(t, &inf->susp, &buf[len_dr - inf->susp.non_CE_len]);
+	} else if (type == RECORD_TYPE_PARENT && node->parent) {
+		ecma119_write_dir_record_noname(t, buf, node, type,
+					node->parent->block,
+					node->parent->attrib.st_size, 0);
+		susp_write(t, &GET_DIR_INF(node)->parent_susp, &buf[34]);
+	} else {
+		ecma119_write_dir_record_noname(t, buf, node, type,
+						node->block,
+						node->attrib.st_size, 0);
+		if (type != RECORD_TYPE_ROOT) {
+			susp_write(t, &GET_DIR_INF(node)->self_susp, &buf[34]);
+		}
+	}
+}
+
+static void ecma119_write_dir_record_joliet(struct ecma119_write_target *t,
+					    uint8_t *buf,
+					    struct iso_tree_node *node,
+					    enum RecordType type)
+{
+	uint8_t len_dr, len_fi, flags;
+	uint8_t vol_seq_num = t->volnum;
+	uint32_t block, size;
+
+	if (type == RECORD_TYPE_NORMAL) {
+		if (S_ISDIR(node->attrib.st_mode)) {
+			block = GET_DIR_INF(node)->joliet_block;
+			size = GET_DIR_INF(node)->joliet_len;
+			flags = 2;
+		} else {
+			block = node->block;
+			size = node->attrib.st_size;
+			flags = 0;
+		}
+		len_fi = node_namelen_joliet(node);
+		len_dr = 34 + len_fi;
+		iso_struct_pack(ecma119_dir_record_fmt, buf,
+				&len_dr,
+				&zero,
+				&block,
+				&size,
+				&t->now,
+				&flags,
+				&zero,
+				&zero,
+				&vol_seq_num,
+				&len_fi);
+		iso_struct_pack_long(&buf[33], len_fi, '<', 'B', 0, 0, 0,
+				     node->name.joliet);
+	} else if (type == RECORD_TYPE_PARENT && node->parent) {
+		struct iso_tree_dir *p = GET_DIR_INF(node)->real_parent;
+		struct dir_write_info *inf = GET_DIR_INF(p);
+		ecma119_write_dir_record_noname(t, buf, node, type,
+				inf->joliet_block,
+				inf->joliet_len,
+				1);
+	} else {
+		struct dir_write_info *inf = GET_DIR_INF(node);
+		ecma119_write_dir_record_noname(t, buf, node, type,
+						inf->joliet_block,
+						inf->joliet_len,
+						1);
+	}
+}
+
+/* this writes a directory record for a file whose RecordType is not
+ * RECORD_TYPE_NORMAL. Since this implies that we don't need to write a file
+ * id, the only difference between Joliet and non-Joliet records is whetheror
+ * not we write the SUSP fields. */
+static void ecma119_write_dir_record_noname(struct ecma119_write_target *t,
+					    uint8_t *buf,
+					    struct iso_tree_node *node,
+					    enum RecordType type,
+					    uint32_t block,
+					    uint32_t size,
+					    int joliet)
+{
+	int file_id;
+	uint8_t len_dr;
+	uint8_t flags = 2;
+	uint8_t len_fi = 1;
+	uint8_t zero = 0;
+	struct dir_write_info *inf = GET_DIR_INF(node);
+
+	assert( type != RECORD_TYPE_NORMAL );
+	switch(type) {
+	case RECORD_TYPE_ROOT:
+		file_id = 0;
+		len_dr = 34;
+		break;
+	case RECORD_TYPE_SELF:
+		file_id = 0;
+		len_dr = 34 + (joliet ? 0 : inf->self_susp.non_CE_len);
+		break;
+	case RECORD_TYPE_PARENT:
+		file_id = 1;
+		len_dr = 34 + (joliet ? 0 : inf->parent_susp.non_CE_len);
+		break;
+	case RECORD_TYPE_NORMAL: /* shut up warning */
+		assert(0);
+	}
+
+	assert(iso_struct_calcsize(ecma119_dir_record_fmt) == 33);
+	iso_struct_pack(ecma119_dir_record_fmt, buf,
+			&len_dr,
+			&zero,
+			&block,
+			&size,
+			&t->now,
+			&flags,		/* file flags */
+			&zero,
+			&zero,
+			&len_fi,	/* vol seq number */
+			&len_fi);	/* len_fi */
+	buf[33] = file_id;
 }
 
 static void ecma119_setup_path_tables(struct ecma119_write_target *t, int flags)
 {
 	int i, j, cur;
 	struct iso_tree_dir ***pathlist;
-	int *path_table_size;
+	uint32_t *path_table_size;
 	node_namelen namelen;
 	struct iso_tree_dir **children;
 	int nchildren;
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/ecma119.h libisofs/ecma119.h
--- libisofs/ecma119.h	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/ecma119.h	2005-07-24 11:16:54.000000000 +1000
@@ -104,20 +104,22 @@
 	int volnum;
 
 	time_t now;		/**< Time at which writing began. */
-	int total_size;		/**< Total size of the output. */
+	int 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;
 
 	int curblock;
-	int block_size;
-	int path_table_size;
-	int path_table_size_joliet;
-	int l_path_table_pos;
-	int m_path_table_pos;
-	int l_path_table_pos_joliet;
-	int m_path_table_pos_joliet;
+	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;
 
 	struct iso_tree_dir **dirlist;	/* A pre-order list of directories
 					 * (this is the order in which we write
@@ -214,4 +216,5 @@
 #define NODE_JOLLEN(n) ucslen(iso_tree_node_get_name(ISO_NODE(n), \
 						     ISO_NAME_JOLIET))
 
+
 #endif /* __ISO_ECMA119 */
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/struct.c libisofs/struct.c
--- libisofs/struct.c	1970-01-01 10:00:00.000000000 +1000
+++ libisofs/struct.c	2005-07-24 11:16:54.000000000 +1000
@@ -0,0 +1,340 @@
+/* vim: set noet ts=8 sts=8 sw=8 : */
+
+#include "struct.h"
+#include "util.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct struct_element {
+	uint8_t ch;
+
+	int bytes;	/* The number of bytes in the value to convert
+			 * from/to. */
+	uint8_t end;	/* The endianness specifier. */
+	int mul;	/* The number of values to convert. */
+
+	union {		/* Pointer to the value. */
+		uint8_t *val8;
+		uint16_t *val16;
+		uint32_t *val32;
+		time_t *time;
+	} val;
+};
+
+/* check if a character is a valid endian-ness specifier */
+#define isend(a) ((a) == '=' || (a) == '<' || (a) == '>')
+
+static int iso_struct_element_make(struct struct_element *elem,
+				   int mul,
+				   char end,
+				   char ch)
+{
+	if (!end) {
+#ifdef WORDS_BIGENDIAN
+		elem->end = '>';	/* default endianness is native */
+#else
+		elem->end = '<';
+#endif
+	} else {
+		elem->end = end;
+	}
+
+	elem->ch = ch;
+	elem->mul = mul;
+	elem->val.val8 = NULL;
+	switch(toupper(ch)) {
+		case 'X':
+		case 'B':
+			elem->bytes = 1;
+			break;
+		case 'H':
+			elem->bytes = 2;
+			break;
+		case 'L':
+			elem->bytes = 4;
+			break;
+		case 'S':
+			elem->bytes = 7;
+			elem->end = '<';
+			break;
+		case 'T':
+			elem->bytes = 17;
+			elem->end = '<';
+			break;
+		default:
+			elem->bytes = -1;
+			break;
+	}
+	return elem->bytes * elem->mul * ((elem->end == '=') ? 2 : 1);
+}
+
+static int iso_struct_element_make_v(struct struct_element *elem,
+				     va_list *ap)
+{
+	int mul = va_arg(*ap, int);
+	int end = va_arg(*ap, int);
+	int ch = va_arg(*ap, int);
+	return iso_struct_element_make(elem, mul, end, ch);
+}
+
+static int iso_struct_element_parse(const char **ffmt,
+				    struct struct_element *elem)
+{
+	off_t pos;
+	const char *fmt = *ffmt;
+	int mul;
+	char end = 0;
+
+	mul = 1;
+	for (pos=0; isdigit(fmt[pos]) || isend(fmt[pos]); pos++) {
+		if (isdigit(fmt[pos])) {
+			mul = atoi( fmt + pos );
+			while (isdigit(fmt[pos+1])) pos++;
+		} else {
+			end = fmt[pos];
+		}
+	}
+
+	(*ffmt) += pos + 1;
+
+	return iso_struct_element_make(elem, mul, end, fmt[pos]);
+}
+
+/* read a single integer from data[i] to elem[i], interpreting the endian-ness
+ * and offset appropriately. */
+static uint32_t iso_struct_element_read_int(struct struct_element *elem,
+					    const uint8_t *data,
+					    int i)
+{
+	uint32_t el;
+
+	switch(elem->end) {
+	case '>':
+		el = iso_read_msb(data + i*elem->bytes, elem->bytes);
+		break;
+	case '<':
+		el = iso_read_lsb(data + i*elem->bytes, elem->bytes);
+		break;
+	case '=':
+		el = iso_read_bb(data + i*elem->bytes*2, elem->bytes);
+	}
+
+	switch(elem->bytes) {
+	case 1:
+		elem->val.val8[i] = el;
+		break;
+	case 2:
+		elem->val.val16[i] = el;
+		break;
+	case 4:
+		elem->val.val32[i] = el;
+		break;
+	}
+
+	return el;
+}
+
+/* write a single integer from elem[i] to data[i]. */
+static uint32_t iso_struct_element_write1(struct struct_element *elem,
+					  uint8_t *data,
+					  int i)
+{
+	uint32_t el;
+
+	switch(elem->bytes) {
+	case 1:
+		el = elem->val.val8[i];
+		break;
+	case 2:
+		el = elem->val.val16[i];
+		break;
+	case 4:
+		el = elem->val.val32[i];
+		break;
+	}
+
+	switch(elem->end) {
+	case '>':
+		iso_msb(data + i*elem->bytes, el, elem->bytes);
+		break;
+	case '<':
+		iso_lsb(data + i*elem->bytes, el, elem->bytes);
+		break;
+	case '=':
+		iso_bb(data + i*elem->bytes*2, el, elem->bytes);
+	}
+
+	return el;
+}
+
+static int iso_struct_element_read(struct struct_element *elem,
+				   const uint8_t *data)
+{
+	int size = elem->bytes * ((elem->end == '=') ? 2 : 1);
+	int i;
+
+	if (elem->ch == 'x') {
+		return size * elem->mul;
+	}
+
+	for (i=0; i<elem->mul; i++) {
+		switch(toupper(elem->ch)) {
+		case 'S':
+			/*
+			elem->val.time[i] = iso_datetime_read_7(&data[i*7]);
+			*/
+			break;
+		case 'T':
+			/*
+			elem->val.time[i] = iso_datetime_read_17(&data[i*17]);
+			*/
+			break;
+		default:
+			iso_struct_element_read_int(elem, data, i);
+		}
+	}
+
+	return size * elem->mul;
+}
+
+static int iso_struct_element_write(struct struct_element *elem,
+				    uint8_t *data)
+{
+	int size = elem->bytes * ((elem->end == '=') ? 2 : 1);
+	int i;
+	uint32_t ret;
+
+	if (elem->ch == 'x') {
+		return size*elem->mul;
+	}
+
+	for (i=0; i<elem->mul; i++) {
+		switch(toupper(elem->ch)) {
+		case 'S':
+			iso_datetime_7(&data[i*7], elem->val.time[i]);
+			ret = elem->val.time[i];
+			break;
+		case 'T':
+			iso_datetime_17(&data[i*17], elem->val.time[i]);
+			ret = elem->val.time[i];
+			break;
+		default:
+			ret = iso_struct_element_write1(elem, data, i);
+			break;
+		}
+
+		if (islower(elem->ch) && ret == 0) {
+			memset(data + size*i, 0, size*(elem->mul-i));
+			break;
+		}
+	}
+
+	return size * elem->mul;
+}
+
+int iso_struct_unpack(const char *fmt, const uint8_t *data, ...)
+{
+	int num_conv;
+	int ret;
+	va_list ap;
+	struct struct_element elem;
+	off_t off;
+
+	va_start(ap, data);
+	num_conv = 0;
+	off = 0;
+	while(*fmt) {
+		ret = iso_struct_element_parse(&fmt, &elem);
+		if (ret < 0) {
+			va_end(ap);
+			return -1;
+		}
+		if (elem.ch != 'x') {
+			elem.val.val8 = va_arg(ap, void*);
+		}
+		off += iso_struct_element_read(&elem, data + off);
+		num_conv++;
+	}
+
+	va_end(ap);
+	return num_conv;
+}
+
+int iso_struct_pack(const char *fmt, uint8_t *data, ...)
+{
+	int num_conv;
+	int ret;
+	va_list ap;
+	struct struct_element elem;
+	off_t off;
+
+	va_start(ap, data);
+	num_conv = 0;
+	off = 0;
+	while(*fmt) {
+		ret = iso_struct_element_parse(&fmt, &elem);
+		if (ret < 0) {
+			va_end(ap);
+			return -1;
+		}
+		if (elem.ch != 'x') {
+			elem.val.val8 = va_arg(ap, void*);
+		}
+		off += iso_struct_element_write(&elem, data + off);
+		num_conv++;
+	}
+
+	va_end(ap);
+	return num_conv;
+}
+
+int iso_struct_pack_long(uint8_t *data, ...)
+{
+	int num_conv;
+	int ret;
+	int i, j;
+	va_list ap;
+	struct struct_element *elem = NULL;
+	off_t off;
+
+	va_start(ap, data);
+	num_conv = 0;
+	off = 0;
+
+	elem = calloc(1, sizeof(struct struct_element));
+	i=0;
+	while ((ret = iso_struct_element_make_v(&elem[i], &ap) > 0)) {
+		elem = realloc(elem, (++i + 1) * sizeof(struct struct_element));
+	}
+	for (j=0; j<i; j++) {
+		if (elem[j].ch != 'x') {
+			elem[j].val.val8 = va_arg(ap, void*);
+		}
+		off += iso_struct_element_write(&elem[j], data + off);
+	}
+
+	va_end(ap);
+	if (ret < 0) {
+		return -1;
+	}
+	return num_conv;
+}
+
+int iso_struct_calcsize(const char *fmt)
+{
+	int ret, total;
+	struct struct_element elem;
+
+	total = 0;
+	while (*fmt) {
+		ret = iso_struct_element_parse(&fmt, &elem);
+		if (ret < 0) {
+			return -1;
+		}
+		total += ret;
+	}
+	return total;
+}
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/struct.h libisofs/struct.h
--- libisofs/struct.h	1970-01-01 10:00:00.000000000 +1000
+++ libisofs/struct.h	2005-07-24 11:16:54.000000000 +1000
@@ -0,0 +1,77 @@
+/* vim: set noet ts=8 sts=8 sw=8 : */
+
+/**
+ * \file struct.h
+ * Add functionality similar to the python "struct" module to make it easier
+ * to read and write .iso structures.
+ *
+ * The following conversions are supported:
+ * B	uint8_t, the arg should be (uint8_t*)
+ * H	uint16_t, the arg should be (uint16_t*)
+ * L	uint32_t, the arg should be (uint32_t*)
+ * S	a 7-byte timestamp, the arg should be (time_t*)
+ * T	a 17-byte timestamp, the arg should be (time_t*)
+ * x	ignored field, no arg should be specified
+ *
+ * Any of the first 3 conversions may be preceded by a endian specifier:
+ * <	little-endian
+ * >	big-endian
+ * =	both-endian (ie. according to ecma119 7.2.3 or 7.3.3)
+ *
+ * Each conversion specifier may also be preceded by a length specifier. For
+ * example, "<5L" specifies an array of 5 little-endian 32-bit integers. Note
+ * that "=L" takes 8 bytes while "<L" and ">L" each take 4.
+ *
+ * You can use a lower-case conversion specifier instead of an upper-case one
+ * to signify that the (multi-element) conversion should stop when a zero is
+ * reached. This is useful for writing out NULL-terminated strings. Note that
+ * this has no effect when unpacking data from a struct.
+ */
+
+#ifndef __ISO_STRUCT
+#define __ISO_STRUCT
+
+#include <stdint.h>
+
+/**
+ * Unpack a struct into its components. The list of components is a list of
+ * pointers to the variables to write.
+ *
+ * For example:
+ * uint8_t byte1, byte2;
+ * uint16_t uint;
+ * iso_struct_unpack("BB=H", data, &byte1, &byte2, &uint);
+ *
+ * \return The number of conversions performed, or -1 on error.
+ */
+int iso_struct_unpack(const char *fmt, const uint8_t *data, ...);
+
+/**
+ * Write out a struct from its components. The list of components is a list of
+ * pointers to the variables to write and the buffer to which to write
+ * is assumed to be large
+ * enough to take the data.
+ *
+ * \return The number of conversions performed, or -1 on error.
+ */
+int iso_struct_pack(const char *fmt, uint8_t *data, ...);
+
+/**
+ * Achieves the same effect as iso_struct_pack(), but the format is passed as
+ * a sequence of (int, char, char) triples. This list is terminated by
+ * (0, 0, 0) and the list of parameters follows.
+ *
+ * Example: iso_struct_pack_long(data, 4, '=', 'H', 0, 0, 0, &val) is the same
+ * as iso_struct_pack("4=H", 0, 0, 0, &val)
+ */
+int iso_struct_pack_long(uint8_t *data, ...);
+
+/**
+ * Calculate the size of a given format string.
+ *
+ * \return The sum of the length of all formats in the string, in bytes. Return
+ *	  -1 on error.
+ */
+int iso_struct_calcsize(const char *fmt);
+
+#endif
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/tree.h libisofs/tree.h
--- libisofs/tree.h	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/tree.h	2005-07-24 11:16:54.000000000 +1000
@@ -41,7 +41,7 @@
 	struct iso_names name;		/**< \see iso_tree_node */
 	struct stat attrib;		/**< \see iso_tree_node */
 	off_t block;			/**< \see iso_tree_node */
-	size_t dirent_len;		/**< \see iso_tree_node */
+	uint8_t dirent_len;		/**< \see iso_tree_node */
 	void *writer_data;		/**< \see iso_tree_node */
 
 	int depth;			/**< The depth of this directory in the
@@ -66,7 +66,7 @@
 	struct iso_names name;		/**< \see iso_tree_node */
 	struct stat attrib;		/**< \see iso_tree_node */
 	off_t block;			/**< \see iso_tree_node */
-	size_t dirent_len;		/**< \see iso_tree_node */
+	uint8_t dirent_len;		/**< \see iso_tree_node */
 	void *writer_data;		/**< \see iso_tree_node */
 
 	char *path;			/**< Location of the file in the
@@ -114,7 +114,7 @@
 	off_t block;			/**< The block at which this node's
 					  *  data will be written.
 					  */
-	size_t dirent_len;		/**< The size of this node's
+	uint8_t dirent_len;		/**< The size of this node's
 					  *  Directory Record in its parent.
 					  *  This does not include System Use
 					  *  fields, if present.
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/util.c libisofs/util.c
--- libisofs/util.c	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/util.c	2005-07-24 11:16:54.000000000 +1000
@@ -1,4 +1,5 @@
 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
+/* vim: set ts=8 sts=8 sw=8 noet : */
 
 #include <ctype.h>
 #include <iconv.h>
@@ -77,11 +78,11 @@
 	return dest;
 }
 
-char *iso_j_str(char *src)
+uint16_t *iso_j_str(const char *src)
 {
 	int size = strlen(src) * 2;
-	char *dest = malloc(size + 2);
-	char *in, *out;
+	uint16_t *dest = malloc(size + 2);
+	char *cpy, *in, *out;
 	size_t inleft, outleft;
 	iconv_t cd;
 
@@ -95,9 +96,11 @@
 
 	/* In, out, inleft and outleft will be updated by iconv, that's why we 
 	   need separate variables. */
-	in = src;
-	out = dest;
-	inleft = strlen(src);
+	cpy = strdup(src); /* iconv doesn't take const * chars, so we need our
+			    * own copy. */
+	in = cpy;
+	out = (char*)dest;
+	inleft = strlen(cpy);
 	outleft = size;
 	iconv(cd, &in, &inleft, &out, &outleft);
 
@@ -109,6 +112,7 @@
 		outleft--;
 	}
 	iconv_close(cd);
+	free(cpy);
 
 	return dest;
 }
@@ -340,10 +344,8 @@
 		dest[pos++] = '.';
 		for (i = 0; i < lnext; i++)
 			dest[pos++] =
-				valid_p_char(src[lname + 1 + i]) ? src[lname +
-								       1 +
-								       i] :
-				'_';
+				valid_p_char(src[lname + 1 + i]) ?
+					     src[lname + 1 + i] : '_';
 	}
 	dest[pos] = '\0';
 	dest = (char *)realloc(dest, pos + 1);
@@ -476,36 +478,33 @@
 	return src ? strdup(src) : NULL;
 }
 
-void iso_lsb(unsigned char *buf, int num, int bytes)
+void iso_lsb(uint8_t *buf, uint32_t num, int bytes)
 {
 	int i;
 
-	assert(bytes <= sizeof(int));
+	assert(bytes <= 4);
 
 	for (i = 0; i < bytes; ++i)
 		buf[i] = (num >> (8 * i)) & 0xff;
 }
 
-void iso_msb(unsigned char *buf, int num, int bytes)
+void iso_msb(uint8_t *buf, uint32_t num, int bytes)
 {
 	int i;
 
-	assert(bytes <= sizeof(int));
+	assert(bytes <= 4);
 
 	for (i = 0; i < bytes; ++i)
 		buf[bytes - 1 - i] = (num >> (8 * i)) & 0xff;
 }
 
-void iso_bb(unsigned char *buf, int num, int bytes)
+void iso_bb(uint8_t *buf, uint32_t num, int bytes)
 {
-	int i;
-
-	assert(bytes <= sizeof(int));
-
-	for (i = 0; i < bytes; ++i)
-		buf[i] = buf[2 * bytes - 1 - i] = (num >> (8 * i)) & 0xff;
+	iso_lsb(buf, num, bytes);
+	iso_msb(buf+bytes, num, bytes);
 }
 
+
 void iso_datetime_7(unsigned char *buf, time_t t)
 {
 	static int tzsetup = 0;
@@ -533,6 +532,20 @@
 	buf[6] = tzoffset;
 }
 
+time_t iso_datetime_read_7(const uint8_t *buf)
+{
+	struct tm tm;
+
+	tm.tm_year = buf[0];
+	tm.tm_mon = buf[1] + 1;
+	tm.tm_mday = buf[2];
+	tm.tm_hour = buf[3];
+	tm.tm_min = buf[4];
+	tm.tm_sec = buf[5];
+
+	return mktime(&tm) - buf[6] * 60 * 60;
+}
+
 void iso_datetime_17(unsigned char *buf, time_t t)
 {
 	static int tzsetup = 0;
@@ -582,6 +595,22 @@
 	}
 }
 
+time_t iso_datetime_read_17(const uint8_t *buf)
+{
+	struct tm tm;
+
+	sscanf((char*)&buf[0], "%4d", &tm.tm_year);
+	sscanf((char*)&buf[4], "%2d", &tm.tm_mon);
+	sscanf((char*)&buf[6], "%2d", &tm.tm_mday);
+	sscanf((char*)&buf[8], "%2d", &tm.tm_hour);
+	sscanf((char*)&buf[10], "%2d", &tm.tm_min);
+	sscanf((char*)&buf[12], "%2d", &tm.tm_sec);
+	tm.tm_year -= 1900;
+	tm.tm_mon -= 1;
+
+	return mktime(&tm) - buf[16] * 60 * 60;
+}
+
 void iso_split_filename(char *name, char **ext)
 {
 	char *r;
@@ -625,9 +654,40 @@
 
 size_t ucslen(const uint16_t *str)
 {
-    int i;
+	int i;
+
+	for (i=0; str[i]; i++)
+		;
+	return i;
+}
+
+uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
+{
+	int i;
+	uint32_t ret = 0;
+
+	for (i=0; i<bytes; i++) {
+		ret += ((uint32_t) buf[i]) << (i*8);
+	}
+	return ret;
+}
+
+uint32_t iso_read_msb(const uint8_t *buf, int bytes)
+{
+	int i;
+	uint32_t ret = 0;
+
+	for (i=0; i<bytes; i++) {
+		ret += ((uint32_t) buf[bytes-i-1]) << (i*8);
+	}
+	return ret;
+}
+
+uint32_t iso_read_bb(const uint8_t *buf, int bytes)
+{
+	uint32_t v1 = iso_read_lsb(buf, bytes);
+	uint32_t v2 = iso_read_msb(buf+bytes, bytes);
 
-    for (i=0; str[i]; i++)
-        ;
-    return i;
+	assert(v1 == v2);
+	return v1;
 }
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/util.h libisofs/util.h
--- libisofs/util.h	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/util.h	2005-07-24 11:16:54.000000000 +1000
@@ -45,7 +45,7 @@
  * Requires the locale to be set correctly.
  * @return NULL if the conversion from the current codeset to UCS-2BE is not available.
  */
-char *iso_j_str(char *src);
+uint16_t *iso_j_str(const char *src);
 
 /**
  * Create a level 1 file identifier that consists of a name, extension and version number.
@@ -118,9 +118,13 @@
 
 char *iso_strdup(const char *src);
 
-void iso_lsb(unsigned char *buf, int num, int bytes);
-void iso_msb(unsigned char *buf, int num, int bytes);
-void iso_bb(unsigned char *buf, int num, int bytes);
+void iso_lsb(uint8_t *buf, uint32_t num, int bytes);
+void iso_msb(uint8_t *buf, uint32_t num, int bytes);
+void iso_bb(uint8_t *buf, uint32_t num, int bytes);
+
+uint32_t iso_read_lsb(const uint8_t *buf, int bytes);
+uint32_t iso_read_msb(const uint8_t *buf, int bytes);
+uint32_t iso_read_bb(const uint8_t *buf, int bytes);
 
 /** Records the date/time into a 7 byte buffer (9.1.5) */
 void iso_datetime_7(unsigned char *buf, time_t t);
@@ -128,6 +132,9 @@
 /** Records the date/time into a 17 byte buffer (8.4.26.1) */
 void iso_datetime_17(unsigned char *buf, time_t t);
 
+time_t iso_datetime_read_7(const uint8_t *buf);
+time_t iso_datetime_read_17(const uint8_t *buf);
+
 /** Removes the extension from the name, and returns the extension. The
     returned extension should _not_ be freed! */
 void iso_split_filename(char *name, char **ext);
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/volume.c libisofs/volume.c
--- libisofs/volume.c	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/volume.c	2005-07-24 11:16:54.000000000 +1000
@@ -1,4 +1,5 @@
 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
+/* vim: set ts=8 sts=8 sw=8 noet : */
 
 #include <stdlib.h>
 
@@ -15,7 +16,8 @@
 	volset->volset_size = 1;
 	volset->volume = malloc(sizeof(void *));
 	volset->volume[0] = vol;
-	volset->volset_id = strdup(id);
+	volset->volset_id.cstr = strdup(id);
+	volset->volset_id.jstr = iso_j_str(id);
 	return volset;
 }
 
@@ -32,13 +34,18 @@
 	volume->root = iso_tree_new_root(volume);
 
 	/* Set these fields, if given. */
-	if (volume_id != NULL)
-		volume->volume_id = strdup(volume_id);
-	if (publisher_id != NULL)
-		volume->publisher_id = strdup(publisher_id);
-	if (data_preparer_id != NULL)
-		volume->data_preparer_id = strdup(data_preparer_id);
-
+	if (volume_id != NULL) {
+		volume->volume_id.cstr = strdup(volume_id);
+		volume->volume_id.jstr = iso_j_str(volume_id);
+	}
+	if (publisher_id != NULL) {
+		volume->publisher_id.cstr = strdup(publisher_id);
+		volume->publisher_id.jstr = iso_j_str(publisher_id);
+	}
+	if (data_preparer_id != NULL) {
+		volume->data_preparer_id.cstr = strdup(data_preparer_id);
+		volume->data_preparer_id.jstr = iso_j_str(data_preparer_id);
+	}
 	return volume;
 }
 
@@ -48,9 +55,12 @@
 	if (--volume->refcount < 1) {
 		iso_tree_free(volume->root);
 
-		free(volume->volume_id);
-		free(volume->publisher_id);
-		free(volume->data_preparer_id);
+		free(volume->volume_id.cstr);
+		free(volume->volume_id.jstr);
+		free(volume->publisher_id.cstr);
+		free(volume->publisher_id.jstr);
+		free(volume->data_preparer_id.cstr);
+		free(volume->data_preparer_id.jstr);
 
 		free(volume);
 	}
diff -X ../exclude_from_diff -x structtest.c -x tests -x mntdir -x '*.iso' -N -u libisofs/volume.h libisofs/volume.h
--- libisofs/volume.h	2005-07-19 08:44:12.000000000 +1000
+++ libisofs/volume.h	2005-07-24 11:16:54.000000000 +1000
@@ -10,6 +10,12 @@
 
 #include "libisofs.h"
 
+struct iso_string
+{
+	char *cstr;
+	uint16_t *jstr;
+};
+
 /**
  * Data volume.
  */
@@ -25,9 +31,9 @@
 	unsigned joliet:1;
 	unsigned iso_level:2;
 
-	char *volume_id;		/**< Volume identifier. */
-	char *publisher_id;		/**< Volume publisher. */
-	char *data_preparer_id;		/**< Volume data preparer. */
+	struct iso_string volume_id;		/**< Volume identifier. */
+	struct iso_string publisher_id;		/**< Volume publisher. */
+	struct iso_string data_preparer_id;	/**< Volume data preparer. */
 };
 
 /**
@@ -42,7 +48,7 @@
 	int volset_size;		/**< The number of volumes in this
 					     volume set. */
 
-	char *volset_id;		/**< The id of this volume set, encoded
+	struct iso_string volset_id;	/**< The id of this volume set, encoded
 					     in the current locale. */
 };
 
--- libisofs/Makefile.am	2005-07-28 08:55:48.000000000 +1000
+++ libisofs/Makefile.am	2005-07-17 18:30:13.000000000 +1000
@@ -14,6 +14,8 @@
 	util.c \
 	ecma119.c \
 	ecma119.h \
+	struct.h \
+	struct.c \
 	susp.h \
 	susp.c \
 	rockridge.h \


More information about the libburn mailing list