Index: src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java	(revision 4793)
+++ src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java	(working copy)
@@ -19,7 +19,6 @@
 import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
-import java.nio.ByteBuffer;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
@@ -39,11 +38,11 @@
 import uk.me.parabola.imgfmt.mps.MpsFile;
 import uk.me.parabola.imgfmt.mps.MpsFileReader;
 import uk.me.parabola.imgfmt.mps.ProductBlock;
-import uk.me.parabola.imgfmt.sys.FileImgChannel;
 import uk.me.parabola.imgfmt.sys.FileLink;
 import uk.me.parabola.imgfmt.sys.ImgFS;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.CommandArgs;
+import uk.me.parabola.util.FileCopier;
 
 /**
  * Create the gmapsupp file.  There is nothing much special about this file
@@ -396,69 +395,3 @@
 		this.createIndex = create;
 	}
 }
-
-/**
- * Copies files from the source img to the gmapsupp.
- *
- * Each sub file has to be copied separately to a different 'file'.  This class makes sure
- * that the source file is only opened once.
- */
-class FileCopier {
-	private final String filename;
-	private FileSystem fs;
-	private int refCount;
-
-	public FileCopier(String filename) {
-		this.filename = filename;
-	}
-
-	Closeable add(String name, ImgChannel fout) {
-		refCount++;
-		return () -> sync(name, fout);
-	}
-
-	Closeable file(ImgChannel fout) {
-		return () -> sync(fout);
-	}
-
-	/**
-	 * This version of sync() is used for single files.
-	 */
-	public void sync(ImgChannel fout) throws IOException {
-		try (ImgChannel fin = new FileImgChannel(filename, "r")) {
-			copyFile(fin, fout);
-		}
-	}
-
-	/**
-	 * This version of sync is used for subfiles within a .img file.
-	 * @param name The sub file name.
-	 * @param fout Where to copy the file
-	 */
-	void sync(String name, ImgChannel fout) throws IOException {
-		if (fs == null)
-			fs = ImgFS.openFs(filename);
-
-		copyFile(name, fout);
-
-		refCount--;
-		if (refCount <= 0) {
-			fs.close();
-		}
-	}
-
-	private void copyFile(String name, ImgChannel fout) throws IOException {
-		try (ImgChannel fin = fs.open(name, "r")) {
-			copyFile(fin, fout);
-		}
-	}
-
-	private static void copyFile(ImgChannel fin, ImgChannel fout) throws IOException {
-		ByteBuffer buf = ByteBuffer.allocate(1024);
-		while (fin.read(buf) > 0) {
-			buf.flip();
-			fout.write(buf);
-			buf.compact();
-		}
-	}
-}
Index: src/uk/me/parabola/util/ExtractFile.java
===================================================================
--- src/uk/me/parabola/util/ExtractFile.java	(nonexistent)
+++ src/uk/me/parabola/util/ExtractFile.java	(working copy)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007 Steve Ratcliffe
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ * 
+ * Author: Steve Ratcliffe
+ * Create date: 20-Oct-2007
+ */
+package uk.me.parabola.util;
+ 
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import uk.me.parabola.imgfmt.fs.DirectoryEntry;
+import uk.me.parabola.imgfmt.fs.FileSystem;
+import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.imgfmt.sys.ImgFS;
+import uk.me.parabola.log.Logger;
+
+/**
+ * A quick program to copy all of the files out of a .img into separate
+ * file system files and to create a new .img file based on the files.
+ * This is a prototype of a program to create a gmapsupp for example.
+ *
+ * @author Steve Ratcliffe
+ */
+public class ExtractFile {
+	private static final Logger log = Logger.getLogger(ExtractFile.class);
+
+	public static void main(String[] args) throws IOException {
+		String file = "63240001.img";
+		if (args.length > 0)
+			file = args[0];
+
+		List<String> filterList = Collections.emptyList();
+		if (args.length > 1)
+			filterList = Arrays.asList(args).subList(1, args.length);
+		
+		(new ExtractFile()).mainprog(file, filterList);
+	}
+
+	private void mainprog(String file, List<String> filterList) throws IOException {
+		FileSystem fs = ImgFS.openFs(file);
+		lister(fs, filterList);
+	}
+
+	private void lister(FileSystem fs, List<String> filterList) throws IOException {
+		List<DirectoryEntry> entries = fs.list();
+		System.out.println("filter" + filterList);
+		for (DirectoryEntry ent : entries) {
+			String fullname = ent.getFullName();
+
+			ImgChannel f = fs.open(fullname, "r");
+			try {
+				String name = displayName(fullname);
+				if (filterList.isEmpty() || matches(filterList, name)) {
+					System.out.format("Copying %-15s %d%n", name, ent.getSize());
+					copyToFile(f, name);
+				}
+			} finally {
+				f.close();
+			}
+		}
+	}
+
+	private String displayName(String fullname) {
+		return fullname.trim().replace("\000", "");
+	}
+
+	private boolean matches(List<String> filterList, String fullname) {
+		String name = fullname.trim().replace("\000", "");
+		for (String s : filterList) {
+			if (s.equalsIgnoreCase(name))
+				return true;
+		}
+		return false;
+	}
+
+	private void copyToFile(ImgChannel f, String name) {
+		try (FileOutputStream fos = new FileOutputStream(name)) {
+			fos.getChannel().transferFrom(f, 0, Long.MAX_VALUE);
+		} catch (FileNotFoundException e) {
+			log.warn("Could not create file");
+		} catch (IOException e) {
+			log.warn("Failed during copy");
+		}
+	}
+}
Index: src/uk/me/parabola/util/FileCopier.java
===================================================================
--- src/uk/me/parabola/util/FileCopier.java	(nonexistent)
+++ src/uk/me/parabola/util/FileCopier.java	(working copy)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007 Steve Ratcliffe
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ * 
+ * Author: Steve Ratcliffe (for GmapsuppBuilder)
+ */
+package uk.me.parabola.util;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import uk.me.parabola.imgfmt.Sized;
+import uk.me.parabola.imgfmt.fs.FileSystem;
+import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.imgfmt.sys.FileImgChannel;
+import uk.me.parabola.imgfmt.sys.ImgFS;
+
+/**
+ * Copies files from the source img to the gmapsupp.
+ *
+ * Each sub file has to be copied separately to a different 'file'. This class
+ * makes sure that the source file is only opened once.
+ */
+public class FileCopier implements Sized {
+	private final String filename;
+	private FileSystem fs;
+	private int refCount;
+	private long fileSize;
+	
+	public FileCopier(String filename) {
+		this.filename = filename;
+		File f = new File(filename);
+		fileSize = f.length();
+	}
+
+	public Closeable add(String name, ImgChannel fout) {
+		refCount++;
+		return () -> sync(name, fout);
+	}
+
+	public Closeable file(ImgChannel fout) {
+		return () -> sync(fout);
+	}
+
+	/**
+	 * This version of sync() is used for single files.
+	 */
+	public void sync(ImgChannel fout) throws IOException {
+		try (ImgChannel fin = new FileImgChannel(filename, "r")) {
+			copyFile(fin, fout);
+		}
+	}
+
+	/**
+	 * This version of sync is used for subfiles within a .img file.
+	 * 
+	 * @param name The sub file name.
+	 * @param fout Where to copy the file
+	 */
+	public void sync(String name, ImgChannel fout) throws IOException {
+		if (fs == null)
+			fs = ImgFS.openFs(filename);
+
+		copyFile(name, fout);
+
+		refCount--;
+		if (refCount <= 0) {
+			fs.close();
+		}
+	}
+
+	private void copyFile(String name, ImgChannel fout) throws IOException {
+		try (ImgChannel fin = fs.open(name, "r")) {
+			copyFile(fin, fout);
+		}
+	}
+
+	private static void copyFile(ImgChannel fin, ImgChannel fout) throws IOException {
+		
+		ByteBuffer buf = ByteBuffer.allocateDirect(8 * 1024);
+		while (fin.read(buf) > 0) {
+			buf.flip();
+			fout.write(buf);
+			buf.compact();
+		}
+		
+	}
+
+	@Override
+	public long getSize() {
+		return fileSize;
+	}
+}
\ No newline at end of file
Index: src/uk/me/parabola/util/ZipFile.java
===================================================================
--- src/uk/me/parabola/util/ZipFile.java	(nonexistent)
+++ src/uk/me/parabola/util/ZipFile.java	(working copy)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 Steve Ratcliffe
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ * 
+ * Author: Steve Ratcliffe
+ * Create date: 20-Oct-2007
+ */
+package uk.me.parabola.util;
+ 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import uk.me.parabola.imgfmt.FileSystemParam;
+import uk.me.parabola.imgfmt.fs.FileSystem;
+import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.imgfmt.sys.FileLink;
+import uk.me.parabola.imgfmt.sys.ImgFS;
+
+/**
+ * Combines several files into one .img file.
+ * Kind of the opposite of ExtractFile.
+ *
+ * It can be used to reconstitute a tile .img file from the .LBL/.TRE/.RGN/.NET/.NOD etc files
+ * so that other display diagnostics can be run.
+ * eg, starting with just gmapsupp.img, extract all the components:
+ *  $ java -cp mkgmap.jar uk.me.parabola.util.ExtractFile gmapsupp.img
+ * or, from a --gmapi directory, the components are in $family-name.gmap/Product1/${tilename}
+ * then, for either:
+ *  $ java -cp mkgmap.jar uk.me.parabola.util.ZipFile ${tilename}.img ${tilename}.*
+ *
+ * @author Steve Ratcliffe
+ */
+public class ZipFile {
+	public static void main(String[] args) throws IOException {
+		FileSystemParam params = new FileSystemParam();
+
+		boolean first = true;
+		String outfile = "63240001.img";
+		List<String> inlist = new ArrayList<>();
+		for (String arg : args) {
+			if (arg.startsWith("--block-size")) {
+				int bsize = Integer.parseInt(arg.substring(13));
+				params.setBlockSize(bsize);
+			} else if (first) {
+				outfile = arg;
+				first = false;
+			} else {
+				inlist.add(arg);
+			}
+		}
+
+		try (FileSystem fs = ImgFS.createFs(outfile, params)) {
+			for (String name : inlist) {
+				System.out.println("file " + name);
+				File f = new File(name);
+				FileCopier fc = new FileCopier(name);
+				ImgChannel fout = fs.create(f.getName().toUpperCase());
+				((FileLink)fout).link(fc, fc.file(fout));
+			}
+		}
+	}
+}
