diff -ru genisovh-0.1/main.c gen-mips-cd/genisovh-dev/main.c
--- genisovh-0.1/main.c	2002-09-28 01:49:03.000000000 +1000
+++ gen-mips-cd/genisovh-dev/main.c	2003-02-18 15:27:59.000000000 +1100
@@ -9,6 +9,8 @@
 #include <assert.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
 
 #include "dvh.h"
 
@@ -20,6 +22,8 @@
 #define BYTES_PER_SECTOR	2048
 #endif
 
+#define CYL_BYTES (SECTORS_PER_TRACK * BYTES_PER_SECTOR)
+
 #define __u16	unsigned short
 #define __u32	unsigned int
 
@@ -53,6 +57,16 @@
 #define cpu_to_be16(x) ((__u16)(x))
 #endif
 
+void usage(void) {
+	printf("Usage:\n");
+	printf(
+"genisovh <isofile> <name|number>:<start>,<end>[,<source>] ... \n"
+"\n"
+"If a name is used, a bootfile is created.  If a number is used, a partition\n"
+"is created.\n"
+	);
+	exit(1);
+}
 
 __u32 vh_calc_checksum(struct volume_header *vh) {
 	__u32	oldchecksum,
@@ -71,20 +85,118 @@
 	return(newsum);
 }
 
-void usage(void ) {
-	printf("Usage:\ngenisovh <isofile> <name:sblock,size> ... \n");
-	exit(1);
+struct entry {
+	enum { ENTRY_FILE, ENTRY_PARTITION } type;
+	union {
+		int num;
+		char name[BFNAMESIZE + 1];
+	} u;
+	int start, len;
+	int has_source;
+	char source[300];		/* file to get image from */
+};
+
+void parse_entry(const char* cmd, struct entry* entry)
+{
+	int i;
+
+	memset(entry->u.name, 0, BFNAMESIZE);
+
+	if (isalpha(*cmd)) {
+		entry->type = ENTRY_FILE;
+
+		i = 0;
+		while (isalnum(*cmd)) {
+			char ch = *cmd++;
+			if (i <= BFNAMESIZE)
+				entry->u.name[i++] = ch;
+		}
+	} else {
+		entry->type = ENTRY_PARTITION;
+		entry->u.num = atoi(cmd);
+		while (isdigit(*cmd))
+			cmd++;
+	}
+
+	if (*cmd++ != ':')
+		usage();
+
+	entry->start = atoi(cmd);
+	while (isdigit(*cmd))
+		cmd++;
+
+	if (*cmd++ != ',')
+		usage();
+
+	entry->len = atoi(cmd);
+	while (isdigit(*cmd))
+		cmd++;
+
+	if (*cmd++ == ',') {
+		entry->has_source = 1;
+		i = 0;
+		while (*cmd && !isspace(*cmd)) {
+			char ch = *cmd++;
+			if (i < 299)
+				entry->source[i++] = ch;
+		}
+		entry->source[i] = 0;
+	} else {
+		entry->has_source = 0;
+	}
+}
+
+int round_up_to(int a, int b)
+{
+	return (a % b == 0)
+			? a
+		       	: a + b - (a % b);
+}
+
+void copy_file(FILE* target, const char *name, int start, int len) {
+	FILE* f;
+	struct stat st;
+	int size;
+	char buf[4096];
+	int pos;
+
+	f = fopen(name, "r");
+	if (!f) {
+		perror(name);
+		exit(1);
+	}
+
+	fstat(fileno(f), &st);
+	size = st.st_size;
+	if (size > len) {
+		printf("%s: too big to fit in %d+%d\n", name, start, len);
+		exit(1);
+	}
+
+	if (fseek(target, start, SEEK_SET)) {
+		perror("[iso image]");
+		exit(1);
+	}
+	assert(ftell(target) == start);
+
+	for (pos = 0; pos < len; pos += 4096) {
+		int r_status = fread(buf, 1, 4096, f);
+		if (r_status < 0) {
+			perror(name);
+			exit(1);
+		}
+		assert (r_status <= 4096);
+		fwrite(buf, 1, r_status, target);
+		if (r_status < 4096)
+			break;
+	}
+
+	fclose(f);
 }
 
 int main(int argc, char **argv) {
-	int			fd,
-				i,
-				v,
-				block,
-				size;
-	char			*isoname,
-				*cline,
-				*pos;
+	FILE*			iso_f;
+	int			i, file_count = 0;
 	struct stat		st;
 	struct volume_header	vh;
 
@@ -92,19 +204,12 @@
 	if (argc < 2)
 		usage();
 
-	isoname=argv[1];
-
-	if (!(fd=open(isoname, O_RDWR))) {
-		printf("File not found %s\n", isoname);
+	if (!(iso_f = fopen(argv[1], "r+"))
+	    || fstat(fileno(iso_f), &st)) {
+		perror(argv[1]);
 		exit(1);
 	}
 
-	if (fstat(fd, &st)) {
-		printf("Failed to stat file %s\n", isoname);
-		close(fd);
-		exit(1);
-	}
-	
 	memset(&vh, 0, sizeof(struct volume_header));
 
 	vh.vh_magic = cpu_to_be32(VHMAGIC);
@@ -118,38 +223,38 @@
 	vh.vh_dp.dp_cyls=cpu_to_be16((st.st_size + BYTES_PER_SECTOR - 1) /
 		(SECTORS_PER_TRACK*BYTES_PER_SECTOR));
 
-	for(i=2,v=0;i<argc;i++,v++) {
-
-		cline=argv[i];	
-
-		/* ip22:3838383,3333 */
-		if (!(pos=strchr(cline, ':'))) {
-			printf("Couldnt find : in parameter %s\n", cline);	
-			usage();
+	for(i=2; i<argc; i++) {
+		struct entry ent;
+		int start;
+		int len;
+
+		parse_entry(argv[i], &ent);
+
+		if (ent.type == ENTRY_PARTITION) {
+			start = round_up_to(ent.start, CYL_BYTES/512);
+			len = ent.len - (start - ent.start);
+
+			vh.vh_pt[ent.u.num].pt_type = cpu_to_be32(PTYPE_XFS);
+			vh.vh_pt[ent.u.num].pt_firstlbn
+				= cpu_to_be32(start / BYTES_PER_SECTOR);
+			vh.vh_pt[ent.u.num].pt_nblks
+			       	= cpu_to_be32(len / BYTES_PER_SECTOR);
+		} else /* ent.type == ENTRY_FILE */ {
+			if (file_count >= NVDIR)
+				printf("Too many boot files\n");
+
+			start = ent.start;
+			len = ent.len;
+
+			vh.vh_vd[file_count].vd_lbn = cpu_to_be32(start);
+			vh.vh_vd[file_count].vd_nbytes = cpu_to_be32(len);
+			strncpy(vh.vh_vd[file_count].vd_name, ent.u.name,
+				VDNAMESIZE);
+			file_count++;
 		}
 
-		*pos=0x0;
-
-		/* copy name */
-		strncpy(vh.vh_vd[v].vd_name, cline, VDNAMESIZE);
-
-		cline=pos+1;
-
-		if (!(pos=strchr(cline, ','))) {
-			printf("Could find , in parameter %s\n", cline);
-			usage();
-		}
-
-		*pos=0x0;
-
-		block=atoi(cline);	
-		vh.vh_vd[v].vd_lbn=cpu_to_be32(block);
-
-		cline=pos+1;
-
-		size=atoi(cline);	
-		vh.vh_vd[v].vd_nbytes=cpu_to_be32(size);
-
+		if (ent.has_source)
+			copy_file(iso_f, ent.source, start, len);
 	}
 
 	/* Create volume header partition on WHOLE cd iso */
@@ -159,11 +264,12 @@
 	/* Create checksum */
 	vh.vh_csum=cpu_to_be32(vh_calc_checksum(&vh));
 
-	if (write(fd, &vh, sizeof(struct volume_header)) != sizeof(struct volume_header)) {
+	rewind(iso_f);
+	if (fwrite(&vh, sizeof(struct volume_header), 1, iso_f) != 1) {
 		printf("Failed to write volume header to iso image");
-		close(fd);
 		exit(1);
 	}
 
-	close(fd);
+	fclose(iso_f);
+	return 0;
 }
