Author: abock
Date: 2006-06-09 17:10:21 -0400 (Fri, 09 Jun 2006)
New Revision: 61609

Added:
   trunk/ipod-sharp/ipod-sharp.mdp
   trunk/ipod-sharp/ipod-sharp.mds
   trunk/ipod-sharp/src/DmgImage.cs
   trunk/ipod-sharp/src/DmgPartition.cs
   trunk/ipod-sharp/tools/DmgIsoExtract.cs
Modified:
   trunk/ipod-sharp/ChangeLog
   trunk/ipod-sharp/src/Makefile.am
   trunk/ipod-sharp/tools/Makefile.am
Log:
2006-06-09  Aaron Bockover  <[EMAIL PROTECTED]>

    * src/DmgImage.cs: Parse DMG partitions from a DMG image file; writes
    HFS+ ISO from DMG image

    * src/DmgPartition.cs: Read DMG partition information from plist XML
    node and extract HFS+ ISO image partition

    * tools/DmgIsoExtract.cs: Command line tool to convert DMG images to
    HFS+ ISO images

    * src/Makefile.am: Added DmgImage.cs and DmgPartition.cs to build

    * tools/Makefile.am: Build dmg-iso-extract.exe tool

    * ipod-sharp.mds:
    * ipod-sharp.mdp: Added MonoDevelop project



Modified: trunk/ipod-sharp/ChangeLog
===================================================================
--- trunk/ipod-sharp/ChangeLog  2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/ChangeLog  2006-06-09 21:10:21 UTC (rev 61609)
@@ -1,3 +1,21 @@
+2006-06-09  Aaron Bockover  <[EMAIL PROTECTED]>
+
+       * src/DmgImage.cs: Parse DMG partitions from a DMG image file; writes
+       HFS+ ISO from DMG image
+       
+       * src/DmgPartition.cs: Read DMG partition information from plist XML
+       node and extract HFS+ ISO image partition 
+       
+       * tools/DmgIsoExtract.cs: Command line tool to convert DMG images to
+       HFS+ ISO images
+
+       * src/Makefile.am: Added DmgImage.cs and DmgPartition.cs to build
+
+       * tools/Makefile.am: Build dmg-iso-extract.exe tool
+
+       * ipod-sharp.mds:
+       * ipod-sharp.mdp: Added MonoDevelop project
+
 2006-06-02  James Willcox  <[EMAIL PROTECTED]>
 
        * Track.cs: add Type property

Added: trunk/ipod-sharp/ipod-sharp.mdp
===================================================================
--- trunk/ipod-sharp/ipod-sharp.mdp     2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/ipod-sharp.mdp     2006-06-09 21:10:21 UTC (rev 61609)
@@ -0,0 +1,47 @@
+<Project name="ipod-sharp" fileversion="2.0" language="C#" 
clr-version="Net_1_1" ctype="DotNetProject">
+  <Configurations active="Debug">
+    <Configuration name="Debug" ctype="DotNetProjectConfiguration">
+      <Output directory="./src" assembly="ipod-sharp" />
+      <Build debugmode="True" target="Library" />
+      <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" 
clr-version="Net_1_1" />
+      <CodeGeneration compiler="Csc" warninglevel="4" optimize="True" 
unsafecodeallowed="True" generateoverflowchecks="True" mainclass="" 
generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+    </Configuration>
+    <Configuration name="Release" ctype="DotNetProjectConfiguration">
+      <Output directory="./src" assembly="ipod-sharp" />
+      <Build debugmode="False" target="Library" />
+      <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" 
clr-version="Net_1_1" />
+      <CodeGeneration compiler="Csc" warninglevel="4" optimize="True" 
unsafecodeallowed="True" generateoverflowchecks="True" mainclass="" 
generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
+    </Configuration>
+  </Configurations>
+  <DeploymentInformation strategy="File">
+    <excludeFiles />
+  </DeploymentInformation>
+  <Contents>
+    <File name="./src/DatabaseReadException.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/DatabaseWriteException.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/Device.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/DeviceAddedHandler.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/DeviceBusyException.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/DeviceEventListener.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/DeviceException.cs" subtype="Code" buildaction="Compile" 
/>
+    <File name="./src/DeviceGeneration.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/DeviceModel.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/DeviceRemovedHandler.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/EndianBinaryWriter.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/Equalizer.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/Initializer.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/Playlist.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/ShuffleTrackDatabase.cs" subtype="Code" 
buildaction="Compile" />
+    <File name="./src/Track.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/TrackDatabase.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/Utility.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/DmgImage.cs" subtype="Code" buildaction="Compile" />
+    <File name="./src/DmgPartition.cs" subtype="Code" buildaction="Compile" />
+    <File name="./tools/DmgIsoExtract.cs" subtype="Code" buildaction="Compile" 
/>
+    <File name="./tools/PodTool.cs" subtype="Code" buildaction="Compile" />
+  </Contents>
+  <References>
+    <ProjectReference type="Gac" localcopy="True" refto="glib-sharp, 
Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, 
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
+  </References>
+</Project>
\ No newline at end of file

Added: trunk/ipod-sharp/ipod-sharp.mds
===================================================================
--- trunk/ipod-sharp/ipod-sharp.mds     2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/ipod-sharp.mds     2006-06-09 21:10:21 UTC (rev 61609)
@@ -0,0 +1,16 @@
+<Combine name="ipod-sharp" fileversion="2.0">
+  <Configurations active="Debug">
+    <Configuration name="Debug" ctype="CombineConfiguration">
+      <Entry build="True" name="ipod-sharp" configuration="Debug" />
+    </Configuration>
+    <Configuration name="Release" ctype="CombineConfiguration">
+      <Entry build="True" name="ipod-sharp" configuration="Debug" />
+    </Configuration>
+  </Configurations>
+  <StartMode startupentry="ipod-sharp" single="True">
+    <Execute type="None" entry="ipod-sharp" />
+  </StartMode>
+  <Entries>
+    <Entry filename="./ipod-sharp.mdp" />
+  </Entries>
+</Combine>
\ No newline at end of file

Added: trunk/ipod-sharp/src/DmgImage.cs
===================================================================
--- trunk/ipod-sharp/src/DmgImage.cs    2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/src/DmgImage.cs    2006-06-09 21:10:21 UTC (rev 61609)
@@ -0,0 +1,113 @@
+//
+// DmgImage.cs: Parses DMG partitions from a DMG image
+//   to build an HFS+ ISO image suitable for mounting
+//
+// Authors:
+//   Aaron Bockover ([EMAIL PROTECTED])
+//
+// (C) 2006 Aaron Bockover
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Collections;
+
+namespace Dmg
+{
+    public class Image : IEnumerable
+    {
+        private static readonly long PLIST_START = 0x1e0;
+        private static readonly long PLIST_END = 0x128;
+
+        private Stream dmg_stream;
+        private BinaryReader dmg_reader;
+        private XmlDocument plist_doc;
+
+        private ArrayList partitions = new ArrayList();
+
+        public Image(Stream dmgStream)
+        {
+            dmg_stream = dmgStream;
+            dmg_reader = new BinaryReader(dmg_stream);
+
+            ReadImage();
+        }
+
+        public void SavePartitionsXml(Stream stream)
+        {
+            plist_doc.Save(stream);
+        }
+
+        public void Extract(Stream isoStream)
+        {
+            long out_offset = 0;
+            foreach(Partition partition in partitions) {
+                partition.Extract(dmg_stream, isoStream, ref out_offset);
+            }
+        }
+
+        public IEnumerator GetEnumerator()
+        {
+            return partitions.GetEnumerator();
+        }
+
+        private void ReadImage()
+        {
+            long plist_address = LocateVerifyPlist();
+            ExtractPlistXmlDocument(plist_address);
+            XmlNode partitions_node = LocatePartitionsNode(plist_doc);
+
+            foreach(XmlNode partition_node in partitions_node) {
+                partitions.Add(new Partition(partition_node));
+            }
+        }
+
+        private long LocateVerifyPlist()
+        {
+            dmg_stream.Seek(-PLIST_START, SeekOrigin.End);
+            long address = dmg_reader.ReadInt64();
+            dmg_stream.Seek(-PLIST_END, SeekOrigin.End);
+            if(dmg_reader.ReadInt64() != address) {
+                throw new IOException("Could not verify plist addresses");
+            }
+
+            return IPAddress.HostToNetworkOrder(address);
+        }
+
+        private void ExtractPlistXmlDocument(long address)
+        {
+            dmg_stream.Seek(address, SeekOrigin.Begin);
+            byte [] tail_bytes = dmg_reader.ReadBytes((int)(dmg_stream.Length 
- address));
+            
+            string raw_xml = Encoding.UTF8.GetString(tail_bytes);
+            raw_xml = raw_xml.Substring(0, raw_xml.LastIndexOf("</plist>") + 
8);
+            
+            plist_doc = new XmlDocument();
+            plist_doc.LoadXml(raw_xml);    
+        }
+
+        private XmlNode LocatePartitionsNode(XmlDocument plistDoc)
+        {
+            foreach(XmlNode key_node in 
plistDoc.SelectNodes("/plist/dict/key")) {
+                if(key_node.InnerText != "resource-fork") {
+                    continue;
+                }
+
+                XmlNode dict_node = key_node.NextSibling;
+            
+                foreach(XmlNode node in dict_node.ChildNodes) {
+                    if(node.Name == "key" && node.InnerText == "blkx") {
+                        return node.NextSibling;
+                    }
+                }
+        
+                break;
+            }
+            
+            throw new ApplicationException("Could not read partition table 
from plist");
+        }
+    }
+}

Added: trunk/ipod-sharp/src/DmgPartition.cs
===================================================================
--- trunk/ipod-sharp/src/DmgPartition.cs        2006-06-09 21:07:29 UTC (rev 
61608)
+++ trunk/ipod-sharp/src/DmgPartition.cs        2006-06-09 21:10:21 UTC (rev 
61609)
@@ -0,0 +1,201 @@
+//
+// DmgPartition.cs: Parses a DMG partition from the image 
+//   plist XML and can perform data extraction for generating
+//   an HFS+ ISO image partition
+//
+// Authors:
+//   Aaron Bockover ([EMAIL PROTECTED])
+//
+// (C) 2006 Aaron Bockover
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Xml;
+using System.Collections;
+using ICSharpCode.SharpZipLib.Zip.Compression;
+
+namespace Dmg
+{
+    public class Partition
+    {
+        private enum BlockType : uint
+        {
+            Copy = 0x00000001,
+            Zero = 0x00000002,
+            End = 0xffffffff,
+            Zlib = 0x80000005,
+            Unknown = 0x7ffffffe
+        }
+
+        private Hashtable table = new Hashtable();
+
+        private Partition()
+        {
+        }
+
+        internal Partition(XmlNode node)
+        {
+            ParsePartition(node);
+        }
+
+        private void ParsePartition(XmlNode node)
+        {
+            foreach(XmlNode key_node in node.SelectNodes("key")) {
+                XmlNode value_node = key_node.NextSibling;
+                if(value_node == null) {
+                    continue;
+                }
+                
+                object value = ParseValue(value_node);
+                if(value != null) {
+                    table.Add(key_node.InnerText.ToLower(), value);
+                }
+            }
+        }
+
+        private object ParseValue(XmlNode node)
+        {
+            if(node.Name == "string") {
+                return node.InnerText.Trim();
+            } else if(node.Name == "data") {
+                return Convert.FromBase64String(node.InnerText);
+            }
+
+            return null;
+        }
+
+        internal void Extract(Stream dmgStream, Stream isoStream, ref long 
lastOutOffset)
+        {
+            MemoryStream stream = new MemoryStream(Data);
+            BinaryReader reader = new BinaryReader(stream);
+            
+            byte [] temp = new byte[0x40000];
+            byte [] otemp = new byte[0x40000];
+            byte [] zeroblock = new byte[4096];
+            
+            int offset = 0xcc;
+            long total_size = 0;
+            long block_count = 0;
+            
+            BlockType block_type = BlockType.Zero;
+        
+            while(block_type != BlockType.End) {
+                stream.Seek(offset, SeekOrigin.Begin);
+                block_type = (BlockType)EndianSwap(reader.ReadInt32());
+                
+                stream.Seek(offset + 12, SeekOrigin.Begin);
+                long out_offset = EndianSwap(reader.ReadInt32()) * 0x200;
+                
+                stream.Seek(offset + 20, SeekOrigin.Begin);
+                long out_size = EndianSwap(reader.ReadInt32()) * 0x200;
+
+                stream.Seek(offset + 28, SeekOrigin.Begin);
+                long in_offset = EndianSwap(reader.ReadInt32());
+
+                stream.Seek(offset + 36, SeekOrigin.Begin);
+                long in_size = EndianSwap(reader.ReadInt32());
+
+                out_offset += lastOutOffset;
+
+                if(block_type == BlockType.Zlib) {
+                    dmgStream.Seek(in_offset, SeekOrigin.Begin);
+                    if(temp.Length < in_size) {
+                        temp = new byte[in_size];
+                    }
+
+                    long total_bytes_read = 0;
+                    while(total_bytes_read < in_size) {
+                        total_bytes_read += dmgStream.Read(temp, 0, 
+                            Math.Min((int)(in_size - total_bytes_read), 
temp.Length));
+                    }
+
+                    Inflater inflater = new Inflater();
+                    inflater.SetInput(temp, 0, (int)total_bytes_read);
+
+                    if(otemp.Length < out_size + 4) {
+                        otemp = new byte[out_size + 4];
+                    }
+
+                    inflater.Inflate(otemp);
+                    if(inflater.RemainingInput > 0) {
+                        throw new ApplicationException("Could not inflate 
entire block");
+                    }
+
+                    isoStream.Write(otemp, 0, (int)out_size);
+                } else if(block_type == BlockType.Copy) {
+                    dmgStream.Seek(in_offset, SeekOrigin.Begin);
+                    
+                    int bytes_read = dmgStream.Read(temp, 0, 
Math.Min((int)in_size, temp.Length));
+                    long total_bytes_read = bytes_read;
+                    
+                    while(bytes_read != -1) {
+                        isoStream.Write(temp, 0, bytes_read);
+                        if(total_bytes_read >= in_size) {
+                            break;
+                        }
+                        
+                        bytes_read = dmgStream.Read(temp, 0, 
+                            Math.Min((int)(in_size - total_bytes_read), 
temp.Length));
+
+                        if(bytes_read > 0) {
+                            total_bytes_read += bytes_read;
+                        }
+                    }
+                } else if(block_type == BlockType.Zero) {    
+                    long zero_block_count = out_size / zeroblock.Length;
+                    
+                    for(int i = 0; i < zero_block_count; ++i) {
+                        isoStream.Write(zeroblock, 0, zeroblock.Length);
+                    }
+                    
+                    isoStream.Write(zeroblock, 0, (int)(out_size % 
zeroblock.Length));
+                } else if(block_type == BlockType.End) {
+                    lastOutOffset = out_offset;
+                }
+
+                offset += 0x28;
+                block_count++;
+                total_size += out_size;
+            }
+        }
+
+        private static int EndianSwap(int input)
+        {
+            return IPAddress.HostToNetworkOrder(input);
+        }
+
+        public object this[string key] {
+            get { return table[key]; }
+        }
+
+        public string ID {
+            get { return table["id"] as string; }
+        }
+        
+        public string Name {
+            get { return table["name"] as string; }
+        }
+
+        public string Attributes {
+            get { return table["attributes"] as string; }
+        }
+
+        public int AttributesNumeric {
+            get { 
+                if(Attributes.StartsWith("0x")) {
+                    return Int32.Parse(Attributes.Substring(2),
+                        System.Globalization.NumberStyles.AllowHexSpecifier);
+                }
+
+                return 0;
+            }
+        }
+
+        public byte [] Data {
+            get { return table["data"] as byte []; }
+        }
+    }
+}

Modified: trunk/ipod-sharp/src/Makefile.am
===================================================================
--- trunk/ipod-sharp/src/Makefile.am    2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/src/Makefile.am    2006-06-09 21:10:21 UTC (rev 61609)
@@ -28,7 +28,9 @@
        $(srcdir)/Track.cs              \
        $(srcdir)/TrackDatabase.cs \
        $(srcdir)/Utility.cs \
-       $(srcdir)/ShuffleTrackDatabase.cs
+       $(srcdir)/ShuffleTrackDatabase.cs \
+       $(srcdir)/DmgImage.cs \
+       $(srcdir)/DmgPartition.cs
 
 ASSEMBLY_RESOURCES =
 
@@ -43,7 +45,7 @@
 all: $(ASSEMBLY) 
 
 $(ASSEMBLY): $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES)
-       $(MCS) $(MCS_FLAGS) -unsafe -keyfile:$(top_srcdir)/ipod-sharp.snk 
-target:library -out:$@ $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES:%=-resource:%) 
-r:Mono.Posix -pkg:gtk-sharp-2.0
+       $(MCS) $(MCS_FLAGS) -unsafe -keyfile:$(top_srcdir)/ipod-sharp.snk 
-target:library -out:$@ $(ASSEMBLY_SOURCES) $(ASSEMBLY_RESOURCES:%=-resource:%) 
-r:Mono.Posix -pkg:gtk-sharp-2.0 -r:ICSharpCode.SharpZipLib
 
 update-docs: $(ASSEMBLY)
        $(DOC_UPDATER) -assembly:$(ASSEMBLY) -path:en

Added: trunk/ipod-sharp/tools/DmgIsoExtract.cs
===================================================================
--- trunk/ipod-sharp/tools/DmgIsoExtract.cs     2006-06-09 21:07:29 UTC (rev 
61608)
+++ trunk/ipod-sharp/tools/DmgIsoExtract.cs     2006-06-09 21:10:21 UTC (rev 
61609)
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using Dmg;
+
+public static class DmgIsoExtract
+{
+    public static int Main(string [] args)
+    {
+        string dmg_file = null;
+        string iso_file = null;
+        string plist_file = null;
+        bool list_partitions = false;
+    
+        if(args.Length < 1) {
+            ShowHelp();
+            return 1;
+        }
+        
+        for(int i = 0; i < args.Length; i++) {
+            switch(args[i]) {
+                case "--list-partitions":
+                    list_partitions = true;
+                    break;
+                case "--dump-plist":
+                    plist_file = args[++i];
+                    break;
+                case "--help":
+                    ShowHelp();
+                    return 1;
+                default:
+                    if(dmg_file == null) {
+                        dmg_file = args[i];
+                    } else if(iso_file == null) {
+                        iso_file = args[i];
+                    } else {
+                        Console.Error.WriteLine("Invalid argument: `{0}'", 
args[0]);
+                        return 1;
+                    }
+                    break;
+            }
+        }
+        
+        if(!File.Exists(dmg_file)) {
+            Console.Error.WriteLine("DMG file `{0}' does not exist", dmg_file);
+            return 1;
+        }
+        
+        FileStream dmg_stream = new FileStream(dmg_file, FileMode.Open);
+        Image image = new Image(dmg_stream);
+        
+        if(list_partitions) {
+            foreach(Partition partition in image) {
+                Console.WriteLine("ID = {0}, Name = {1}, Attributes = 
0x{2:x2}", 
+                    partition.ID, partition.Name, partition.AttributesNumeric);
+            }
+        }
+        
+        if(plist_file != null) {
+            image.SavePartitionsXml(new FileStream(plist_file, 
FileMode.Create));
+        }
+        
+        if(iso_file != null) {
+            image.Extract(new FileStream(iso_file, FileMode.Create));
+        }
+    
+        return 0;
+    }
+    
+    private static void ShowHelp()
+    {
+        Console.Error.WriteLine("Usage: dmg-iso-extract <dmg-file> 
[<iso-file>] [--list-partitions]");
+        Console.Error.WriteLine("         [--dump-plist <plist-file>]\n");
+        Console.Error.WriteLine("   <dmg-file>                 DMG input file 
to read (required)");
+        Console.Error.WriteLine("   <iso-file>                 HFS+ ISO file 
to output (optional)");
+        Console.Error.WriteLine("   --list-partitions          Show the 
partitions in the DMG image");
+        Console.Error.WriteLine("   --dump-plist <plist-file>  Dump the raw 
plist XML to file\n");
+        Console.Error.WriteLine("   --help                     Show this 
help\n");
+    }
+}

Modified: trunk/ipod-sharp/tools/Makefile.am
===================================================================
--- trunk/ipod-sharp/tools/Makefile.am  2006-06-09 21:07:29 UTC (rev 61608)
+++ trunk/ipod-sharp/tools/Makefile.am  2006-06-09 21:10:21 UTC (rev 61609)
@@ -1,14 +1,20 @@
-
 MCS_FLAGS = -debug
 
-TOOLS = ipod-tool.exe
+TOOLS = ipod-tool.exe dmg-iso-extract.exe
 
 IPOD_TOOL_SOURCES = $(srcdir)/PodTool.cs
+DMG_ISO_EXTRACT_SRC = \
+       $(srcdir)/DmgIsoExtract.cs \
+       $(top_builddir)/src/Dmg*.cs
 
 all: $(TOOLS)
 
 ipod-tool.exe: $(IPOD_TOOL_SOURCES)
        $(MCS) $(MCS_FLAGS) -r:$(top_builddir)/src/ipod-sharp.dll -target:exe 
-out:$@ $(IPOD_TOOL_SOURCES)
 
-EXTRA_DIST = $(IPOD_TOOL_SOURCES)
+dmg-iso-extract.exe: $(DMG_ISO_EXTRACT_SRC)
+       $(MCS) $(MCS_FLAGS) -r:ICSharpCode.SharpZipLib -target:exe -out:$@ 
$(DMG_ISO_EXTRACT_SRC)
+
+EXTRA_DIST = $(IPOD_TOOL_SOURCES) $(DMG_ISO_EXTRACT_SRC)
 CLEANFILES = $(TOOLS)
+

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to