From 8789300d31e3c9b4310254c2416473bfdfa4739a Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sat, 5 Jan 2013 00:04:46 +0100 Subject: Populate File table, create cabinet for media "1" --- src/builder.vala | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/msi.vala | 65 ++++++++++++++++++++++++++++++++++++++++++++---- src/wix.vala | 24 ++++++++++++++++++ 3 files changed, 157 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/builder.vala b/src/builder.vala index 780cb65..699be29 100644 --- a/src/builder.vala +++ b/src/builder.vala @@ -1,13 +1,16 @@ namespace Wixl { class WixBuilder: WixElementVisitor { - WixRoot root; - MsiDatabase db; public WixBuilder (WixRoot root) { this.root = root; } + WixRoot root; + MsiDatabase db; + List files; + List medias; + delegate void AddSequence (string action, int sequence) throws GLib.Error; void sequence_actions () throws GLib.Error { @@ -59,6 +62,8 @@ namespace Wixl { } if (db.table_remove_file.records.length () > 0) add ("RemoveFiles", 3500); + if (db.table_file.records.length () > 0) + add ("InstallFiles", 4000); add ("RegisterUser", 6000); add ("RegisterProduct", 6100); add ("PublishFeatures", 6300); @@ -75,10 +80,41 @@ namespace Wixl { add ("ExecuteAction", 1300); } + public void build_cabinet () throws GLib.Error { + var sequence = 0; + + foreach (var m in medias) { + var folder = new GCab.Folder (GCab.Compression.MSZIP); + + foreach (var f in files) { + if (f.DiskId != m.Id) + continue; + + folder.add_file (new GCab.File.with_file (f.Id, File.new_for_path (f.Name)), false); + var rec = f.record; + sequence += 1; + MsiTableFile.set_sequence (rec, sequence); + } + + var cab = new GCab.Cabinet (); + cab.add_folder (folder); + var output = new MemoryOutputStream (null, realloc, free); + cab.write (output, null, null, null); + var input = new MemoryInputStream.from_data (output.get_data ()[0:output.data_size], null); + if (parse_yesno (m.EmbedCab)) + db.table_streams.add (m.Cabinet, input, output.data_size); + + db.table_media.set_last_sequence (m.record, sequence); + } + } + public MsiDatabase build () throws GLib.Error { db = new MsiDatabase (); + root.accept (this); sequence_actions (); + build_cabinet (); + return db; } @@ -109,7 +145,14 @@ namespace Wixl { } public override void visit_media (WixMedia media) throws GLib.Error { - db.table_media.add (media.Id, media.EmbedCab, media.DiskPrompt, "#" + media.Cabinet); + var cabinet = media.Cabinet; + + medias.append (media); + if (parse_yesno (media.EmbedCab)) + cabinet = "#" + cabinet; + + var rec = db.table_media.add (media.Id, media.DiskPrompt, cabinet); + media.record = rec; } public override void visit_directory (WixDirectory dir) throws GLib.Error { @@ -229,6 +272,33 @@ namespace Wixl { visit_key_element (reg); } + + [Flags] + enum FileAttribute { + READ_ONLY = 1 << 0, + HIDDEN = 1 << 1, + SYSTEM = 1 << 2, + VITAL = 1 << 9, + CHECKSUM = 1 << 10, + PATCH_ADDED = 1 << 11, + NON_COMPRESSED = 1 << 12, + COMPRESSED = 1 << 13 + } + + public override void visit_file (WixFile file) throws GLib.Error { + return_if_fail (file.DiskId == "1"); + files.append (file); + + var comp = file.parent as WixComponent; + var gfile = File.new_for_path (file.Name); + var info = gfile.query_info ("standard::*", 0, null); + var attr = FileAttribute.VITAL; + + var rec = db.table_file.add (file.Id, comp.Id, file.Name, (int)info.get_size (), attr); + file.record = rec; + + visit_key_element (file); + } } } // Wixl diff --git a/src/msi.vala b/src/msi.vala index 4f21bef..027f44f 100644 --- a/src/msi.vala +++ b/src/msi.vala @@ -122,9 +122,33 @@ namespace Wixl { name = "File"; } + public Libmsi.Record add (string File, string Component, string FileName, int FileSize, int Attributes, int Sequence = 0) throws GLib.Error { + var rec = new Libmsi.Record (6); + + if (!rec.set_string (1, File) || + !rec.set_string (2, Component) || + !rec.set_string (3, FileName) || + !rec.set_int (4, FileSize) || + !rec.set_int (5, Attributes) || + !rec.set_int (6, Sequence)) + throw new Wixl.Error.FAILED ("failed to add record"); + + records.append (rec); + + return rec; + } + + public static bool set_sequence (Libmsi.Record rec, int Sequence) { + return rec.set_int (6, Sequence); + } + public override void create (Libmsi.Database db) throws GLib.Error { var query = new Libmsi.Query (db, "CREATE TABLE `File` (`File` CHAR(72) NOT NULL, `Component_` CHAR(72) NOT NULL, `FileName` CHAR(255) NOT NULL LOCALIZABLE, `FileSize` LONG NOT NULL, `Version` CHAR(72), `Language` CHAR(20), `Attributes` INT, `Sequence` LONG NOT NULL PRIMARY KEY `File`)"); query.execute (null); + + query = new Libmsi.Query (db, "INSERT INTO `File` (`File`, `Component_`, `FileName`, `FileSize`, `Attributes`, `Sequence`) VALUES (?, ?, ?, ?, ?, ?)"); + foreach (var r in records) + query.execute (r); } } @@ -184,17 +208,21 @@ namespace Wixl { name = "Media"; } - public void add (string DiskId, string LastSequence, string DiskPrompt, string Cabinet) throws GLib.Error { + public bool set_last_sequence (Libmsi.Record rec, int last_sequence) { + return rec.set_int (2, last_sequence); + } + + public Libmsi.Record add (string DiskId, string DiskPrompt, string Cabinet) throws GLib.Error { var rec = new Libmsi.Record (4); if (!rec.set_int (1, int.parse (DiskId)) || - !rec.set_int (2, int.parse (LastSequence)) || + !rec.set_int (2, 0) || !rec.set_string (3, DiskPrompt) || !rec.set_string (4, Cabinet)) throw new Wixl.Error.FAILED ("failed to add record"); records.append (rec); - + return rec; } public override void create (Libmsi.Database db) throws GLib.Error { @@ -386,7 +414,7 @@ namespace Wixl { } } - class MsiTable_Validation: MsiTable { + class MsiTableValidation: MsiTable { construct { name = "_Validation"; } @@ -395,6 +423,27 @@ namespace Wixl { } } + class MsiTableStreams: MsiTable { + construct { + name = "_Streams"; + } + + public void add (string name, GLib.InputStream input, size_t count) throws GLib.Error { + var rec = new Libmsi.Record (2); + if (!rec.set_string (1, name) || + !rec.set_stream (2, input, count)) + throw new Wixl.Error.FAILED ("failed to add record"); + + records.append (rec); + } + + public override void create (Libmsi.Database db) throws GLib.Error { + var query = new Libmsi.Query (db, "INSERT INTO `_Streams` (`Name`, `Data`) VALUES (?, ?)"); + foreach (var r in records) + query.execute (r); + } + } + class MsiSummaryInfo: Object { public Libmsi.SummaryInfo properties; @@ -457,11 +506,13 @@ namespace Wixl { public MsiTableFeatureComponents table_feature_components; public MsiTableRemoveFile table_remove_file; public MsiTableRegistry table_registry; + public MsiTableFile table_file; public MsiTableAdminExecuteSequence table_admin_execute_sequence; public MsiTableAdminUISequence table_admin_ui_sequence; public MsiTableAdvtExecuteSequence table_advt_execute_sequence; public MsiTableInstallExecuteSequence table_install_execute_sequence; public MsiTableInstallUISequence table_install_ui_sequence; + public MsiTableStreams table_streams; HashTable tables; @@ -493,11 +544,13 @@ namespace Wixl { table_feature_components = new MsiTableFeatureComponents (); table_remove_file = new MsiTableRemoveFile (); table_registry = new MsiTableRegistry (); + table_file = new MsiTableFile (); table_admin_execute_sequence = new MsiTableAdminExecuteSequence (); table_admin_ui_sequence = new MsiTableAdminUISequence (); table_advt_execute_sequence = new MsiTableAdvtExecuteSequence (); table_install_execute_sequence = new MsiTableInstallExecuteSequence (); table_install_ui_sequence = new MsiTableInstallUISequence (); + table_streams = new MsiTableStreams (); foreach (var t in new MsiTable[] { table_admin_execute_sequence, @@ -514,8 +567,10 @@ namespace Wixl { table_feature_components, table_remove_file, table_registry, + table_file, + table_streams, new MsiTableError (), - new MsiTable_Validation () + new MsiTableValidation () }) { tables.insert (t.name, t); } diff --git a/src/wix.vala b/src/wix.vala index aa6f0d4..f4dfeb2 100644 --- a/src/wix.vala +++ b/src/wix.vala @@ -12,6 +12,7 @@ namespace Wixl { public abstract void visit_component_ref (WixComponentRef ref) throws GLib.Error; public abstract void visit_remove_folder (WixRemoveFolder rm) throws GLib.Error; public abstract void visit_registry_value (WixRegistryValue reg) throws GLib.Error; + public abstract void visit_file (WixFile reg) throws GLib.Error; } public abstract class WixElement: Object { @@ -135,6 +136,22 @@ namespace Wixl { public string KeyPath { get; set; } } + public class WixFile: WixKeyElement { + static construct { + name = "File"; + } + + public string DiskId { get; set; } + public string Source { get; set; } + public string Name { get; set; } + + public Libmsi.Record record; + + public override void accept (WixElementVisitor visitor) throws GLib.Error { + visitor.visit_file (this); + } + } + public class WixRegistryValue: WixKeyElement { static construct { name = "RegistryValue"; @@ -285,6 +302,8 @@ namespace Wixl { public string EmbedCab { get; set; } public string DiskPrompt { get; set; } + public Libmsi.Record record; + public override void accept (WixElementVisitor visitor) throws GLib.Error { visitor.visit_media (this); } @@ -318,6 +337,11 @@ namespace Wixl { reg.load (child); add_child (reg); continue; + case "File": + var file = new WixFile (); + file.load (child); + add_child (file); + continue; } break; } -- cgit