2018-08-27 18:29:55 +01:00
|
|
|
// /***************************************************************************
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : frmMain.xeto.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Main window.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Implements main GUI window.
|
|
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General public License as
|
|
|
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// 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.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General public License
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
|
|
|
|
// ****************************************************************************/
|
2018-08-28 23:29:06 +01:00
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
using System;
|
2018-10-08 00:49:30 +01:00
|
|
|
using System.Collections.Generic;
|
2018-08-27 18:25:11 +01:00
|
|
|
using System.ComponentModel;
|
2018-10-03 00:05:25 +01:00
|
|
|
using System.IO;
|
2018-08-27 15:07:51 +01:00
|
|
|
using System.Linq;
|
2018-10-03 00:05:25 +01:00
|
|
|
using DiscImageChef.CommonTypes;
|
|
|
|
|
using DiscImageChef.CommonTypes.Interfaces;
|
2018-10-24 23:16:45 +01:00
|
|
|
using DiscImageChef.CommonTypes.Structs;
|
2018-08-27 18:25:11 +01:00
|
|
|
using DiscImageChef.Console;
|
2018-10-03 00:05:25 +01:00
|
|
|
using DiscImageChef.Core;
|
2018-09-09 01:00:54 +01:00
|
|
|
using DiscImageChef.Core.Media.Info;
|
2018-10-08 00:14:03 +01:00
|
|
|
using DiscImageChef.Decoders.SCSI;
|
2018-08-27 15:07:51 +01:00
|
|
|
using DiscImageChef.Devices;
|
2018-09-09 01:07:46 +01:00
|
|
|
using DiscImageChef.Gui.Dialogs;
|
|
|
|
|
using DiscImageChef.Gui.Panels;
|
2018-11-16 00:31:12 +00:00
|
|
|
using DiscImageChef.Settings;
|
2018-10-07 23:29:28 +01:00
|
|
|
using Eto.Drawing;
|
2018-08-27 15:07:51 +01:00
|
|
|
using Eto.Forms;
|
|
|
|
|
using Eto.Serialization.Xaml;
|
2018-10-24 23:16:45 +01:00
|
|
|
using FileAttributes = DiscImageChef.CommonTypes.Structs.FileAttributes;
|
2018-10-07 23:29:28 +01:00
|
|
|
using ImageFormat = DiscImageChef.Core.ImageFormat;
|
2018-08-27 15:07:51 +01:00
|
|
|
|
2018-09-09 01:07:46 +01:00
|
|
|
namespace DiscImageChef.Gui.Forms
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
|
|
|
|
public class frmMain : Form
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
bool closing;
|
2018-10-08 00:14:03 +01:00
|
|
|
Bitmap devicesIcon;
|
|
|
|
|
Bitmap ejectIcon;
|
2018-10-07 23:29:28 +01:00
|
|
|
GridView grdFiles;
|
2018-10-08 00:14:03 +01:00
|
|
|
Bitmap hardDiskIcon;
|
|
|
|
|
Bitmap imagesIcon;
|
2018-10-07 23:29:28 +01:00
|
|
|
Label lblError;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This is to remember that column is an image to be set in future
|
|
|
|
|
/// </summary>
|
|
|
|
|
Image nullImage;
|
2018-10-08 00:14:03 +01:00
|
|
|
Bitmap opticalIcon;
|
2018-09-06 22:27:58 +01:00
|
|
|
TreeGridItem placeholderItem;
|
2018-10-08 00:14:03 +01:00
|
|
|
Bitmap removableIcon;
|
|
|
|
|
Bitmap sdIcon;
|
|
|
|
|
Bitmap tapeIcon;
|
2018-08-27 15:07:51 +01:00
|
|
|
TreeGridView treeImages;
|
|
|
|
|
TreeGridItemCollection treeImagesItems;
|
2018-11-17 00:06:50 +00:00
|
|
|
ContextMenu treeImagesMenu;
|
2018-10-08 00:14:03 +01:00
|
|
|
Bitmap usbIcon;
|
2018-08-27 15:07:51 +01:00
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
public frmMain(bool debug, bool verbose)
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
|
|
|
|
XamlReader.Load(this);
|
|
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
lblError = new Label();
|
|
|
|
|
grdFiles = new GridView();
|
|
|
|
|
nullImage = null;
|
2018-09-02 01:41:03 +01:00
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
ConsoleHandler.Init();
|
|
|
|
|
ConsoleHandler.Debug = debug;
|
|
|
|
|
ConsoleHandler.Verbose = verbose;
|
|
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
treeImagesItems = new TreeGridItemCollection();
|
|
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
treeImages.Columns.Add(new GridColumn {HeaderText = "Name", DataCell = new ImageTextCell(0, 1)});
|
2018-08-27 15:07:51 +01:00
|
|
|
|
|
|
|
|
treeImages.AllowMultipleSelection = false;
|
|
|
|
|
treeImages.ShowHeader = false;
|
|
|
|
|
treeImages.DataStore = treeImagesItems;
|
|
|
|
|
|
2018-10-08 00:14:03 +01:00
|
|
|
// TODO: SVG
|
|
|
|
|
imagesIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.inode-directory.png"));
|
|
|
|
|
devicesIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.computer.png"));
|
|
|
|
|
hardDiskIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.drive-harddisk.png"));
|
|
|
|
|
opticalIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.drive-optical.png"));
|
|
|
|
|
usbIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.drive-removable-media-usb.png"));
|
|
|
|
|
removableIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.drive-removable-media.png"));
|
|
|
|
|
sdIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.media-flash-sd-mmc.png"));
|
|
|
|
|
tapeIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.media-tape.png"));
|
|
|
|
|
ejectIcon =
|
|
|
|
|
new Bitmap(ResourceHandler
|
|
|
|
|
.GetResourceStream("DiscImageChef.Gui.Assets.Icons.oxygen._32x32.media-eject.png"));
|
|
|
|
|
|
|
|
|
|
imagesRoot = new TreeGridItem {Values = new object[] {imagesIcon, "Images"}};
|
|
|
|
|
devicesRoot = new TreeGridItem {Values = new object[] {devicesIcon, "Devices"}};
|
2018-08-27 15:07:51 +01:00
|
|
|
|
|
|
|
|
treeImagesItems.Add(imagesRoot);
|
|
|
|
|
treeImagesItems.Add(devicesRoot);
|
2018-08-27 18:25:11 +01:00
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
placeholderItem = new TreeGridItem {Values = new object[] {nullImage, "You should not be seeing this"}};
|
2018-09-06 22:27:58 +01:00
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
Closing += OnClosing;
|
2018-11-17 00:06:50 +00:00
|
|
|
|
|
|
|
|
treeImagesMenu = new ContextMenu();
|
|
|
|
|
treeImagesMenu.Opening += OnTreeImagesMenuOpening;
|
|
|
|
|
treeImages.ContextMenu = treeImagesMenu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnTreeImagesMenuOpening(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
OnTreeImagesSelectedItemChanged(treeImages, e);
|
|
|
|
|
|
|
|
|
|
treeImagesMenu.Items.Clear();
|
|
|
|
|
ButtonMenuItem menuItem = new ButtonMenuItem {Text = "Close all images"};
|
|
|
|
|
menuItem.Click += CloseAllImages;
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Refresh devices"};
|
|
|
|
|
menuItem.Click += OnDeviceRefresh;
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
|
|
|
|
|
if(!(treeImages.SelectedItem is TreeGridItem selectedItem)) return;
|
|
|
|
|
|
|
|
|
|
if(selectedItem.Values.Length < 4) return;
|
|
|
|
|
|
|
|
|
|
if(selectedItem.Values[3] is pnlImageInfo imageInfo)
|
|
|
|
|
{
|
|
|
|
|
IMediaImage image = selectedItem.Values[5] as IMediaImage;
|
|
|
|
|
|
|
|
|
|
// TODO: Global pool of forms
|
|
|
|
|
treeImagesMenu.Items.Add(new SeparatorMenuItem());
|
|
|
|
|
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Calculate entropy"};
|
|
|
|
|
menuItem.Click += (a, b) => { new frmImageEntropy(image).Show(); };
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Verify"};
|
|
|
|
|
menuItem.Click += (a, b) => { new frmImageVerify(image).Show(); };
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Checksum"};
|
|
|
|
|
menuItem.Click += (a, b) => { new frmImageChecksum(image).Show(); };
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Convert to..."};
|
|
|
|
|
menuItem.Click += (a, b) => { new frmImageConvert(image, selectedItem.Values[2] as string).Show(); };
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
|
|
|
|
menuItem = new ButtonMenuItem {Text = "Create CICM XML sidecar..."};
|
|
|
|
|
menuItem.Click += (a, b) =>
|
|
|
|
|
{
|
|
|
|
|
// TODO: Pass thru chosen default encoding
|
|
|
|
|
new frmImageSidecar(image, selectedItem.Values[2] as string, ((IFilter)selectedItem.Values[4]).Id,
|
|
|
|
|
null).Show();
|
|
|
|
|
};
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
2018-11-17 20:00:55 +00:00
|
|
|
menuItem = new ButtonMenuItem {Text = "View sectors"};
|
|
|
|
|
menuItem.Click += (a, b) => { new frmPrintHex(image).Show(); };
|
|
|
|
|
treeImagesMenu.Items.Add(menuItem);
|
2018-11-17 00:06:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CloseAllImages(object sender, EventArgs eventArgs)
|
|
|
|
|
{
|
2018-11-17 20:00:55 +00:00
|
|
|
// TODO
|
2018-11-17 00:06:50 +00:00
|
|
|
MessageBox.Show("Not yet implemented");
|
2018-08-27 18:25:11 +01:00
|
|
|
}
|
|
|
|
|
|
2018-11-16 00:31:12 +00:00
|
|
|
protected override void OnLoad(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLoad(e);
|
|
|
|
|
|
|
|
|
|
if(Settings.Settings.Current.GdprCompliance < DicSettings.GdprLevel) new dlgSettings(true).ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
void OnClosing(object sender, CancelEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// This prevents an infinite loop of crashes :p
|
|
|
|
|
if(closing) return;
|
|
|
|
|
|
|
|
|
|
closing = true;
|
|
|
|
|
Application.Instance.Quit();
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuOpen(object sender, EventArgs e)
|
|
|
|
|
{
|
2018-10-03 00:05:25 +01:00
|
|
|
// TODO: Extensions
|
|
|
|
|
OpenFileDialog dlgOpenImage = new OpenFileDialog {Title = "Choose image to open"};
|
|
|
|
|
|
|
|
|
|
DialogResult result = dlgOpenImage.ShowDialog(this);
|
|
|
|
|
if(result != DialogResult.Ok) return;
|
|
|
|
|
|
|
|
|
|
FiltersList filtersList = new FiltersList();
|
|
|
|
|
IFilter inputFilter = filtersList.GetFilter(dlgOpenImage.FileName);
|
|
|
|
|
|
|
|
|
|
if(inputFilter == null)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Cannot open specified file.", MessageBoxType.Error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
IMediaImage imageFormat = ImageFormat.Detect(inputFilter);
|
|
|
|
|
|
|
|
|
|
if(imageFormat == null)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Image format not identified.", MessageBoxType.Error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DicConsole.WriteLine("Image format identified by {0} ({1}).", imageFormat.Name, imageFormat.Id);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if(!imageFormat.Open(inputFilter))
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Unable to open image format", MessageBoxType.Error);
|
|
|
|
|
DicConsole.ErrorWriteLine("Unable to open image format");
|
|
|
|
|
DicConsole.ErrorWriteLine("No error given");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
// TODO: SVG
|
|
|
|
|
Stream logo =
|
|
|
|
|
ResourceHandler
|
|
|
|
|
.GetResourceStream($"DiscImageChef.Gui.Assets.Logos.Media.{imageFormat.Info.MediaType}.png");
|
|
|
|
|
|
2018-10-08 00:49:30 +01:00
|
|
|
TreeGridItem imageGridItem = new TreeGridItem
|
2018-10-03 00:05:25 +01:00
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
logo == null ? null : new Bitmap(logo),
|
2018-10-03 00:05:25 +01:00
|
|
|
$"{Path.GetFileName(dlgOpenImage.FileName)} ({imageFormat.Info.MediaType})",
|
|
|
|
|
dlgOpenImage.FileName,
|
2018-10-08 00:49:30 +01:00
|
|
|
new pnlImageInfo(dlgOpenImage.FileName, inputFilter, imageFormat), inputFilter,
|
|
|
|
|
imageFormat
|
2018-10-03 00:05:25 +01:00
|
|
|
}
|
2018-10-08 00:49:30 +01:00
|
|
|
};
|
2018-10-03 00:05:25 +01:00
|
|
|
|
2018-10-08 00:49:30 +01:00
|
|
|
List<Partition> partitions = Core.Partitions.GetAll(imageFormat);
|
|
|
|
|
Core.Partitions.AddSchemesToStats(partitions);
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
bool checkraw = false;
|
|
|
|
|
List<string> idPlugins;
|
|
|
|
|
IFilesystem plugin;
|
|
|
|
|
PluginBase plugins = GetPluginBase.Instance;
|
2018-10-08 00:49:30 +01:00
|
|
|
|
|
|
|
|
if(partitions.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
DicConsole.DebugWriteLine("Analyze command", "No partitions found");
|
|
|
|
|
|
|
|
|
|
checkraw = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DicConsole.WriteLine("{0} partitions found.", partitions.Count);
|
|
|
|
|
|
|
|
|
|
foreach(string scheme in partitions.Select(p => p.Scheme).Distinct().OrderBy(s => s))
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem schemeGridItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
nullImage, // TODO: Add icons to partition schemes
|
|
|
|
|
scheme
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foreach(Partition partition in partitions
|
|
|
|
|
.Where(p => p.Scheme == scheme).OrderBy(p => p.Start))
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem partitionGridItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
nullImage, // TODO: Add icons to partition schemes
|
|
|
|
|
$"{partition.Name} ({partition.Type})", null, new pnlPartition(partition)
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
DicConsole.WriteLine("Identifying filesystem on partition");
|
|
|
|
|
|
|
|
|
|
Core.Filesystems.Identify(imageFormat, out idPlugins, partition);
|
|
|
|
|
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
|
|
|
|
|
|
|
|
|
|
foreach(string pluginName in idPlugins)
|
|
|
|
|
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
|
|
|
|
{
|
2018-10-08 19:17:58 +01:00
|
|
|
plugin.GetInformation(imageFormat, partition, out string information, null);
|
2018-10-08 01:04:58 +01:00
|
|
|
|
2018-10-24 23:16:45 +01:00
|
|
|
IReadOnlyFilesystem fsPlugin = plugin as IReadOnlyFilesystem;
|
|
|
|
|
|
|
|
|
|
if(fsPlugin != null)
|
|
|
|
|
{
|
|
|
|
|
Errno error =
|
|
|
|
|
fsPlugin.Mount(imageFormat, partition, null,
|
|
|
|
|
new Dictionary<string, string>());
|
|
|
|
|
|
|
|
|
|
if(error != Errno.NoError) fsPlugin = null;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
TreeGridItem filesystemGridItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
nullImage, // TODO: Add icons to filesystems
|
|
|
|
|
plugin.XmlFsType.VolumeName is null
|
|
|
|
|
? $"{plugin.XmlFsType.Type}"
|
|
|
|
|
: $"{plugin.XmlFsType.VolumeName} ({plugin.XmlFsType.Type})",
|
2018-10-24 23:16:45 +01:00
|
|
|
fsPlugin, new pnlFilesystem(plugin.XmlFsType, information)
|
2018-10-08 01:04:58 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-10-24 23:16:45 +01:00
|
|
|
if(fsPlugin != null)
|
|
|
|
|
{
|
2018-11-16 00:31:12 +00:00
|
|
|
Statistics.AddCommand("ls");
|
2018-10-24 23:16:45 +01:00
|
|
|
filesystemGridItem.Children.Add(placeholderItem);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
|
|
|
|
partitionGridItem.Children.Add(filesystemGridItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 00:49:30 +01:00
|
|
|
schemeGridItem.Children.Add(partitionGridItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imageGridItem.Children.Add(schemeGridItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
if(checkraw)
|
|
|
|
|
{
|
|
|
|
|
Partition wholePart = new Partition
|
|
|
|
|
{
|
|
|
|
|
Name = "Whole device",
|
|
|
|
|
Length = imageFormat.Info.Sectors,
|
|
|
|
|
Size = imageFormat.Info.Sectors * imageFormat.Info.SectorSize
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Core.Filesystems.Identify(imageFormat, out idPlugins, wholePart);
|
|
|
|
|
if(idPlugins.Count == 0) DicConsole.WriteLine("Filesystem not identified");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DicConsole.WriteLine($"Identified by {idPlugins.Count} plugins");
|
|
|
|
|
|
|
|
|
|
foreach(string pluginName in idPlugins)
|
|
|
|
|
if(plugins.PluginsList.TryGetValue(pluginName, out plugin))
|
|
|
|
|
{
|
2018-10-08 19:17:58 +01:00
|
|
|
plugin.GetInformation(imageFormat, wholePart, out string information, null);
|
2018-10-08 01:04:58 +01:00
|
|
|
|
2018-10-24 23:16:45 +01:00
|
|
|
IReadOnlyFilesystem fsPlugin = plugin as IReadOnlyFilesystem;
|
|
|
|
|
|
|
|
|
|
if(fsPlugin != null)
|
|
|
|
|
{
|
|
|
|
|
Errno error =
|
|
|
|
|
fsPlugin.Mount(imageFormat, wholePart, null,
|
|
|
|
|
new Dictionary<string, string>());
|
|
|
|
|
|
|
|
|
|
if(error != Errno.NoError) fsPlugin = null;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
TreeGridItem filesystemGridItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
nullImage, // TODO: Add icons to filesystems
|
|
|
|
|
plugin.XmlFsType.VolumeName is null
|
|
|
|
|
? $"{plugin.XmlFsType.Type}"
|
|
|
|
|
: $"{plugin.XmlFsType.VolumeName} ({plugin.XmlFsType.Type})",
|
2018-10-24 23:16:45 +01:00
|
|
|
fsPlugin, new pnlFilesystem(plugin.XmlFsType, information)
|
2018-10-08 01:04:58 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-10-24 23:16:45 +01:00
|
|
|
if(fsPlugin != null)
|
|
|
|
|
{
|
2018-11-16 00:31:12 +00:00
|
|
|
Statistics.AddCommand("ls");
|
2018-10-24 23:16:45 +01:00
|
|
|
filesystemGridItem.Children.Add(placeholderItem);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 01:04:58 +01:00
|
|
|
Statistics.AddFilesystem(plugin.XmlFsType.Type);
|
|
|
|
|
imageGridItem.Children.Add(filesystemGridItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 00:49:30 +01:00
|
|
|
imagesRoot.Children.Add(imageGridItem);
|
2018-10-03 00:05:25 +01:00
|
|
|
treeImages.ReloadData();
|
|
|
|
|
|
|
|
|
|
Statistics.AddMediaFormat(imageFormat.Format);
|
|
|
|
|
Statistics.AddMedia(imageFormat.Info.MediaType, false);
|
|
|
|
|
Statistics.AddFilter(inputFilter.Name);
|
|
|
|
|
}
|
|
|
|
|
catch(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Unable to open image format", MessageBoxType.Error);
|
|
|
|
|
DicConsole.ErrorWriteLine("Unable to open image format");
|
|
|
|
|
DicConsole.ErrorWriteLine("Error: {0}", ex.Message);
|
|
|
|
|
DicConsole.DebugWriteLine("Image-info command", "Stack trace: {0}", ex.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Exception reading file", MessageBoxType.Error);
|
|
|
|
|
DicConsole.ErrorWriteLine($"Error reading file: {ex.Message}");
|
|
|
|
|
DicConsole.DebugWriteLine("Image-info command", ex.StackTrace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Statistics.AddCommand("image-info");
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuAbout(object sender, EventArgs e)
|
|
|
|
|
{
|
2018-08-27 18:43:18 +01:00
|
|
|
AboutDialog dlgAbout = new AboutDialog
|
|
|
|
|
{
|
|
|
|
|
Developers = new[] {"Natalia Portillo", "Michael Drüing"},
|
|
|
|
|
License = "This program is free software: you can redistribute it and/or modify\n" +
|
|
|
|
|
"it under the terms of the GNU General public License as\n" +
|
|
|
|
|
"published by the Free Software Foundation, either version 3 of the\n" +
|
|
|
|
|
"License, or (at your option) any later version.\n\n" +
|
|
|
|
|
"This program is distributed in the hope that it will be useful,\n" +
|
|
|
|
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
|
|
|
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
|
|
|
|
"GNU General public License for more details.\n\n" +
|
|
|
|
|
"You should have received a copy of the GNU General public License\n" +
|
|
|
|
|
"along with this program. If not, see <http://www.gnu.org/licenses/>.",
|
|
|
|
|
ProgramName = "The Disc Image Chef",
|
|
|
|
|
Website = new Uri("https://github.com/claunia"),
|
|
|
|
|
WebsiteLabel = "Source code on..."
|
|
|
|
|
};
|
|
|
|
|
dlgAbout.ShowDialog(this);
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuQuit(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Application.Instance.Quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnDeviceRefresh(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
RefreshDevices();
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 00:31:12 +00:00
|
|
|
protected void OnMenuSettings(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgSettings(false).ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
protected override void OnLoadComplete(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLoadComplete(e);
|
|
|
|
|
|
|
|
|
|
RefreshDevices();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RefreshDevices()
|
|
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
try
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
DicConsole.WriteLine("Refreshing devices");
|
|
|
|
|
devicesRoot.Children.Clear();
|
|
|
|
|
|
2018-08-28 23:29:06 +01:00
|
|
|
foreach(DeviceInfo device in Device.ListDevices().Where(d => d.Supported).OrderBy(d => d.Vendor)
|
|
|
|
|
.ThenBy(d => d.Model))
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
DicConsole.DebugWriteLine("Main window",
|
2018-08-28 23:29:06 +01:00
|
|
|
"Found supported device model {0} by manufacturer {1} on bus {2} and path {3}",
|
|
|
|
|
device.Model, device.Vendor, device.Bus, device.Path);
|
2018-09-06 22:27:58 +01:00
|
|
|
|
|
|
|
|
TreeGridItem devItem = new TreeGridItem
|
2018-08-27 22:03:20 +01:00
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
Values = new object[]
|
|
|
|
|
{
|
2018-10-08 00:14:03 +01:00
|
|
|
hardDiskIcon, $"{device.Vendor} {device.Model} ({device.Bus})", device.Path, null
|
2018-10-07 23:29:28 +01:00
|
|
|
}
|
2018-09-06 22:27:58 +01:00
|
|
|
};
|
2018-10-08 00:14:03 +01:00
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Device dev = new Device(device.Path);
|
|
|
|
|
|
|
|
|
|
switch(dev.Type)
|
|
|
|
|
{
|
|
|
|
|
case DeviceType.ATAPI:
|
|
|
|
|
case DeviceType.SCSI:
|
|
|
|
|
switch(dev.ScsiType)
|
|
|
|
|
{
|
|
|
|
|
case PeripheralDeviceTypes.DirectAccess:
|
|
|
|
|
case PeripheralDeviceTypes.SCSIZonedBlockDevice:
|
|
|
|
|
case PeripheralDeviceTypes.SimplifiedDevice:
|
|
|
|
|
devItem.Values[0] = dev.IsRemovable
|
|
|
|
|
? dev.IsUsb
|
|
|
|
|
? usbIcon
|
|
|
|
|
: removableIcon
|
|
|
|
|
: hardDiskIcon;
|
|
|
|
|
break;
|
|
|
|
|
case PeripheralDeviceTypes.SequentialAccess:
|
|
|
|
|
devItem.Values[0] = tapeIcon;
|
|
|
|
|
break;
|
|
|
|
|
case PeripheralDeviceTypes.OpticalDevice:
|
|
|
|
|
case PeripheralDeviceTypes.WriteOnceDevice:
|
|
|
|
|
case PeripheralDeviceTypes.OCRWDevice:
|
|
|
|
|
devItem.Values[0] = removableIcon;
|
|
|
|
|
break;
|
|
|
|
|
case PeripheralDeviceTypes.MultiMediaDevice:
|
|
|
|
|
devItem.Values[0] = opticalIcon;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case DeviceType.SecureDigital:
|
|
|
|
|
case DeviceType.MMC:
|
|
|
|
|
devItem.Values[0] = sdIcon;
|
|
|
|
|
break;
|
|
|
|
|
case DeviceType.NVMe:
|
|
|
|
|
devItem.Values[0] = nullImage;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev.Close();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
// ignored
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 22:27:58 +01:00
|
|
|
devItem.Children.Add(placeholderItem);
|
|
|
|
|
devicesRoot.Children.Add(devItem);
|
2018-08-27 22:03:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
}
|
2018-08-28 23:29:06 +01:00
|
|
|
catch(InvalidOperationException ex) { DicConsole.ErrorWriteLine(ex.Message); }
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
protected void OnMenuConsole(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new frmConsole().Show();
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-28 23:29:06 +01:00
|
|
|
protected void OnMenuPlugins(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgPlugins().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-30 22:51:29 +01:00
|
|
|
protected void OnMenuEncodings(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgEncodings().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 23:32:00 +01:00
|
|
|
protected void OnMenuBenchmark(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgBenchmark().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 13:16:04 +01:00
|
|
|
protected void OnMenuStatistics(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(Statistics.AllStats == null)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("There are no statistics.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new dlgStatistics().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-02 01:41:03 +01:00
|
|
|
protected void OnTreeImagesSelectedItemChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(!(sender is TreeGridView tree)) return;
|
|
|
|
|
|
|
|
|
|
if(!(tree.SelectedItem is TreeGridItem selectedItem)) return;
|
|
|
|
|
|
|
|
|
|
splMain.Panel2 = null;
|
|
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
if(selectedItem.Values.Length >= 4 && selectedItem.Values[3] is Panel infoPanel)
|
2018-09-09 01:00:54 +01:00
|
|
|
{
|
|
|
|
|
splMain.Panel2 = infoPanel;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-24 23:16:45 +01:00
|
|
|
if(selectedItem.Values.Length < 4) return;
|
2018-09-02 01:41:03 +01:00
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
switch(selectedItem.Values[3])
|
2018-09-02 01:41:03 +01:00
|
|
|
{
|
2018-10-24 23:16:45 +01:00
|
|
|
case null when selectedItem.Parent == devicesRoot:
|
2018-09-02 01:41:03 +01:00
|
|
|
try
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
Device dev = new Device((string)selectedItem.Values[2]);
|
2018-09-02 01:41:03 +01:00
|
|
|
if(dev.Error)
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
selectedItem.Values[3] = $"Error {dev.LastError} opening device";
|
2018-09-02 01:41:03 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core.Devices.Info.DeviceInfo devInfo = new Core.Devices.Info.DeviceInfo(dev);
|
|
|
|
|
|
2018-10-07 23:29:28 +01:00
|
|
|
selectedItem.Values[3] = new pnlDeviceInfo(devInfo);
|
|
|
|
|
splMain.Panel2 = (Panel)selectedItem.Values[3];
|
2018-09-02 01:41:03 +01:00
|
|
|
|
|
|
|
|
dev.Close();
|
|
|
|
|
}
|
|
|
|
|
catch(SystemException ex)
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
selectedItem.Values[3] = ex.Message;
|
2018-09-02 01:41:03 +01:00
|
|
|
lblError.Text = ex.Message;
|
|
|
|
|
splMain.Panel2 = lblError;
|
|
|
|
|
DicConsole.ErrorWriteLine(ex.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
2018-10-24 23:16:45 +01:00
|
|
|
case string devErrorMessage when selectedItem.Parent == devicesRoot:
|
2018-09-02 01:41:03 +01:00
|
|
|
lblError.Text = devErrorMessage;
|
|
|
|
|
splMain.Panel2 = lblError;
|
|
|
|
|
break;
|
2018-10-24 23:16:45 +01:00
|
|
|
case Dictionary<string, FileEntryInfo> files:
|
|
|
|
|
splMain.Panel2 = new pnlListFiles(selectedItem.Values[2] as IReadOnlyFilesystem, files,
|
|
|
|
|
selectedItem.Values[1] as string == "/"
|
|
|
|
|
? "/"
|
|
|
|
|
: selectedItem.Values[4] as string);
|
|
|
|
|
break;
|
2018-09-02 01:41:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 22:27:58 +01:00
|
|
|
protected void OnTreeImagesItemExpanding(object sender, TreeGridViewItemCancelEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// First expansion of a device
|
2018-10-24 23:16:45 +01:00
|
|
|
if((e.Item as TreeGridItem)?.Children?.Count != 1 ||
|
|
|
|
|
((TreeGridItem)e.Item).Children[0] != placeholderItem) return;
|
|
|
|
|
|
|
|
|
|
if(((TreeGridItem)e.Item).Parent == devicesRoot)
|
2018-09-06 22:27:58 +01:00
|
|
|
{
|
|
|
|
|
TreeGridItem deviceItem = (TreeGridItem)e.Item;
|
|
|
|
|
|
|
|
|
|
deviceItem.Children.Clear();
|
|
|
|
|
Device dev;
|
|
|
|
|
try
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
dev = new Device((string)deviceItem.Values[2]);
|
2018-09-06 22:27:58 +01:00
|
|
|
if(dev.Error)
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
deviceItem.Values[3] = $"Error {dev.LastError} opening device";
|
2018-09-06 22:27:58 +01:00
|
|
|
e.Cancel = true;
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
treeImages.SelectedItem = deviceItem;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(SystemException ex)
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
deviceItem.Values[3] = ex.Message;
|
2018-09-06 22:27:58 +01:00
|
|
|
e.Cancel = true;
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
DicConsole.ErrorWriteLine(ex.Message);
|
|
|
|
|
treeImages.SelectedItem = deviceItem;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!dev.IsRemovable)
|
|
|
|
|
deviceItem.Children.Add(new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
nullImage,
|
2018-09-06 22:27:58 +01:00
|
|
|
"Non-removable device commands not yet implemented"
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
else
|
2018-09-09 01:00:54 +01:00
|
|
|
{
|
|
|
|
|
// TODO: Removable non-SCSI?
|
|
|
|
|
ScsiInfo scsiInfo = new ScsiInfo(dev);
|
|
|
|
|
|
|
|
|
|
if(!scsiInfo.MediaInserted)
|
2018-10-07 23:29:28 +01:00
|
|
|
deviceItem.Children.Add(new TreeGridItem
|
|
|
|
|
{
|
2018-10-08 00:14:03 +01:00
|
|
|
Values = new object[] {ejectIcon, "No media inserted"}
|
2018-10-07 23:29:28 +01:00
|
|
|
});
|
2018-09-09 01:00:54 +01:00
|
|
|
else
|
2018-10-07 23:29:28 +01:00
|
|
|
{
|
|
|
|
|
// TODO: SVG
|
|
|
|
|
Stream logo =
|
|
|
|
|
ResourceHandler
|
|
|
|
|
.GetResourceStream($"DiscImageChef.Gui.Assets.Logos.Media.{scsiInfo.MediaType}.png");
|
|
|
|
|
|
2018-09-09 01:00:54 +01:00
|
|
|
deviceItem.Children.Add(new TreeGridItem
|
2018-09-06 22:27:58 +01:00
|
|
|
{
|
2018-09-09 01:00:54 +01:00
|
|
|
Values = new[]
|
|
|
|
|
{
|
2018-10-07 23:29:28 +01:00
|
|
|
logo == null ? null : new Bitmap(logo),
|
|
|
|
|
scsiInfo.MediaType, deviceItem.Values[2],
|
|
|
|
|
new pnlScsiInfo(scsiInfo, (string)deviceItem.Values[2])
|
2018-09-09 01:00:54 +01:00
|
|
|
}
|
|
|
|
|
});
|
2018-10-07 23:29:28 +01:00
|
|
|
}
|
2018-09-09 01:00:54 +01:00
|
|
|
}
|
2018-09-06 22:27:58 +01:00
|
|
|
|
|
|
|
|
dev.Close();
|
|
|
|
|
}
|
2018-10-24 23:16:45 +01:00
|
|
|
else if(((TreeGridItem)e.Item).Values[2] is IReadOnlyFilesystem fsPlugin)
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem fsItem = (TreeGridItem)e.Item;
|
|
|
|
|
|
|
|
|
|
fsItem.Children.Clear();
|
|
|
|
|
|
|
|
|
|
if(fsItem.Values.Length == 5 && fsItem.Values[4] is string dirPath)
|
|
|
|
|
{
|
|
|
|
|
Errno errno = fsPlugin.ReadDir(dirPath, out List<string> dirents);
|
|
|
|
|
|
|
|
|
|
if(errno != Errno.NoError)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show($"Error {errno} trying to read \"{dirPath}\" of chosen filesystem",
|
|
|
|
|
MessageBoxType.Error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dictionary<string, FileEntryInfo> files = new Dictionary<string, FileEntryInfo>();
|
|
|
|
|
List<string> directories = new List<string>();
|
|
|
|
|
|
|
|
|
|
foreach(string dirent in dirents)
|
|
|
|
|
{
|
|
|
|
|
errno = fsPlugin.Stat(dirPath + "/" + dirent, out FileEntryInfo stat);
|
|
|
|
|
|
|
|
|
|
if(errno != Errno.NoError)
|
|
|
|
|
{
|
|
|
|
|
DicConsole
|
|
|
|
|
.ErrorWriteLine($"Error {errno} trying to get information about filesystem entry named {dirent}");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(stat.Attributes.HasFlag(FileAttributes.Directory)) directories.Add(dirent);
|
|
|
|
|
else files.Add(dirent, stat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach(string directory in directories)
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem dirItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[] {imagesIcon, directory, fsPlugin, null, dirPath + "/" + directory}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dirItem.Children.Add(placeholderItem);
|
|
|
|
|
fsItem.Children.Add(dirItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Errno errno = fsPlugin.ReadDir("/", out List<string> dirents);
|
|
|
|
|
|
|
|
|
|
if(errno != Errno.NoError)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show($"Error {errno} trying to read root directory of chosen filesystem",
|
|
|
|
|
MessageBoxType.Error);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dictionary<string, FileEntryInfo> files = new Dictionary<string, FileEntryInfo>();
|
|
|
|
|
List<string> directories = new List<string>();
|
|
|
|
|
|
|
|
|
|
foreach(string dirent in dirents)
|
|
|
|
|
{
|
|
|
|
|
errno = fsPlugin.Stat("/" + dirent, out FileEntryInfo stat);
|
|
|
|
|
|
|
|
|
|
if(errno != Errno.NoError)
|
|
|
|
|
{
|
|
|
|
|
DicConsole
|
|
|
|
|
.ErrorWriteLine($"Error {errno} trying to get information about filesystem entry named {dirent}");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(stat.Attributes.HasFlag(FileAttributes.Directory)) directories.Add(dirent);
|
|
|
|
|
else files.Add(dirent, stat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TreeGridItem rootDirectoryItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
nullImage, // TODO: Get icon from volume
|
|
|
|
|
"/", fsPlugin, files
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foreach(string directory in directories)
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem dirItem = new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[] {imagesIcon, directory, fsPlugin, null, "/" + directory}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dirItem.Children.Add(placeholderItem);
|
|
|
|
|
rootDirectoryItem.Children.Add(dirItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fsItem.Children.Add(rootDirectoryItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-06 22:27:58 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
#region XAML IDs
|
|
|
|
|
TreeGridItem devicesRoot;
|
|
|
|
|
TreeGridItem imagesRoot;
|
2018-09-02 01:41:03 +01:00
|
|
|
Splitter splMain;
|
2018-08-27 15:07:51 +01:00
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|