diff --git a/DiscImageChef.Core/Statistics.cs b/DiscImageChef.Core/Statistics.cs index 9620abd3..03c7ca81 100644 --- a/DiscImageChef.Core/Statistics.cs +++ b/DiscImageChef.Core/Statistics.cs @@ -291,16 +291,16 @@ namespace DiscImageChef.Core CurrentStats.Commands.Entropy++; break; case "extract-files": - AllStats.Commands.Entropy++; - CurrentStats.Commands.Entropy++; + AllStats.Commands.ExtractFiles++; + CurrentStats.Commands.ExtractFiles++; break; case "formats": AllStats.Commands.Formats++; CurrentStats.Commands.Formats++; break; case "ls": - AllStats.Commands.Formats++; - CurrentStats.Commands.Formats++; + AllStats.Commands.Ls++; + CurrentStats.Commands.Ls++; break; case "media-info": AllStats.Commands.MediaInfo++; @@ -318,6 +318,10 @@ namespace DiscImageChef.Core AllStats.Commands.Verify++; CurrentStats.Commands.Verify++; break; + case "list-devices": + AllStats.Commands.ListDevices++; + CurrentStats.Commands.ListDevices++; + break; } } } diff --git a/DiscImageChef.Devices/Device/List.cs b/DiscImageChef.Devices/Device/List.cs new file mode 100644 index 00000000..4c033217 --- /dev/null +++ b/DiscImageChef.Devices/Device/List.cs @@ -0,0 +1,62 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : List.cs +// Author(s) : Natalia Portillo +// +// Component : Component +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2017 Natalia Portillo +// ****************************************************************************/ +using System; + +namespace DiscImageChef.Devices +{ + public struct DeviceInfo + { + public string path; + public string vendor; + public string model; + public string serial; + public string bus; + public bool supported; + } + + public partial class Device + { + public static DeviceInfo[] ListDevices() + { + switch(Interop.DetectOS.GetRealPlatformID()) + { + case Interop.PlatformID.Win32NT: + throw new NotImplementedException(); + case Interop.PlatformID.Linux: + return Linux.ListDevices.GetList(); + default: + throw new InvalidOperationException(string.Format("Platform {0} not yet supported.", Interop.DetectOS.GetRealPlatformID())); + } + + } + } +} diff --git a/DiscImageChef.Devices/DiscImageChef.Devices.csproj b/DiscImageChef.Devices/DiscImageChef.Devices.csproj index f04fae7b..a8b49d8c 100644 --- a/DiscImageChef.Devices/DiscImageChef.Devices.csproj +++ b/DiscImageChef.Devices/DiscImageChef.Devices.csproj @@ -80,6 +80,8 @@ + + @@ -95,22 +97,10 @@ - - - - - - - - - - - - - - - - + + + + diff --git a/DiscImageChef.Devices/Linux/Extern.cs b/DiscImageChef.Devices/Linux/Extern.cs index 25ac296a..13d364aa 100644 --- a/DiscImageChef.Devices/Linux/Extern.cs +++ b/DiscImageChef.Devices/Linux/Extern.cs @@ -31,6 +31,7 @@ // Copyright © 2011-2017 Natalia Portillo // ****************************************************************************/ +using System; using System.Runtime.InteropServices; namespace DiscImageChef.Devices.Linux @@ -60,6 +61,15 @@ namespace DiscImageChef.Devices.Linux [DllImport("libc", CharSet = CharSet.Ansi, EntryPoint = "readlink", SetLastError = true)] internal static extern long readlink64(string path, System.IntPtr buf, long bufsize); + + [DllImport("libudev", CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern IntPtr udev_new(); + + [DllImport("libudev", CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern IntPtr udev_device_new_from_subsystem_sysname(IntPtr udev, string subsystem, string sysname); + + [DllImport("libudev", CharSet = CharSet.Ansi, SetLastError = true)] + internal static extern string udev_device_get_property_value(IntPtr udev_device, string key); } } diff --git a/DiscImageChef.Devices/Linux/ListDevices.cs b/DiscImageChef.Devices/Linux/ListDevices.cs new file mode 100644 index 00000000..f59f30a0 --- /dev/null +++ b/DiscImageChef.Devices/Linux/ListDevices.cs @@ -0,0 +1,142 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : ListDevices.cs +// Author(s) : Natalia Portillo +// +// Component : Component +// +// --[ Description ] ---------------------------------------------------------- +// +// Description +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2017 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Text; + +namespace DiscImageChef.Devices.Linux +{ + public static class ListDevices + { + const string PATH_SYS_DEVBLOCK = "/sys/block/"; + + public static DeviceInfo[] GetList() + { + string[] sysdevs = Directory.GetFileSystemEntries(PATH_SYS_DEVBLOCK, "*", SearchOption.TopDirectoryOnly); + DeviceInfo[] devices = new DeviceInfo[sysdevs.Length]; + bool hasUdev; + + StreamReader sr; + IntPtr udev = IntPtr.Zero; + IntPtr udevDev = IntPtr.Zero; + + try + { + udev = Extern.udev_new(); + hasUdev = udev != IntPtr.Zero; + } + catch + { + hasUdev = false; + } + + for(int i = 0; i < sysdevs.Length; i++) + { + devices[i] = new DeviceInfo(); + devices[i].path = "/dev/" + Path.GetFileName(sysdevs[i]); + + if(hasUdev) + { + udevDev = Extern.udev_device_new_from_subsystem_sysname(udev, "block", Path.GetFileName(sysdevs[i])); + devices[i].vendor = Extern.udev_device_get_property_value(udevDev, "ID_VENDOR"); + devices[i].model = Extern.udev_device_get_property_value(udevDev, "ID_MODEL"); + if(!string.IsNullOrEmpty(devices[i].model)) + devices[i].model = devices[i].model.Replace('_', ' '); + devices[i].serial = Extern.udev_device_get_property_value(udevDev, "ID_SCSI_SERIAL"); + if(string.IsNullOrEmpty(devices[i].serial)) + devices[i].serial = Extern.udev_device_get_property_value(udevDev, "ID_SERIAL_SHORT"); + devices[i].bus = Extern.udev_device_get_property_value(udevDev, "ID_BUS"); + } + + if(File.Exists(Path.Combine(sysdevs[i], "device/vendor")) && string.IsNullOrEmpty(devices[i].vendor)) + { + sr = new StreamReader(Path.Combine(sysdevs[i], "device/vendor"), Encoding.ASCII); + devices[i].vendor = sr.ReadLine().Trim(); + } + else if(devices[i].path.StartsWith("/dev/loop", StringComparison.CurrentCulture)) + devices[i].vendor = "Linux"; + + if(File.Exists(Path.Combine(sysdevs[i], "device/model")) && (string.IsNullOrEmpty(devices[i].model) || devices[i].bus == "ata")) + { + sr = new StreamReader(Path.Combine(sysdevs[i], "device/model"), Encoding.ASCII); + devices[i].model = sr.ReadLine().Trim(); + } + else if(devices[i].path.StartsWith("/dev/loop", StringComparison.CurrentCulture)) + devices[i].model = "Linux"; + + if(File.Exists(Path.Combine(sysdevs[i], "device/serial")) && string.IsNullOrEmpty(devices[i].serial)) + { + sr = new StreamReader(Path.Combine(sysdevs[i], "device/serial"), Encoding.ASCII); + devices[i].serial = sr.ReadLine().Trim(); + } + + if(string.IsNullOrEmpty(devices[i].vendor) || devices[i].vendor == "ATA") + { + string[] pieces = devices[i].model.Split(' '); + if(pieces.Length > 1) + { + devices[i].vendor = pieces[0]; + devices[i].model = devices[i].model.Substring(pieces[0].Length + 1); + } + } + + // TODO: Get better device type from sysfs paths + if(string.IsNullOrEmpty(devices[i].bus)) + { + if(devices[i].path.StartsWith("/dev/loop", StringComparison.CurrentCulture)) + devices[i].bus = "loop"; + else if(devices[i].path.StartsWith("/dev/nvme", StringComparison.CurrentCulture)) + devices[i].bus = "NVMe"; + else if(devices[i].path.StartsWith("/dev/mmc", StringComparison.CurrentCulture)) + devices[i].bus = "MMC/SD"; + } + else + devices[i].bus = devices[i].bus.ToUpper(); + + switch(devices[i].bus) + { + case "ATA": + case "ATAPI": + case "SCSI": + case "USB": + case "PCMCIA": + case "FireWire": + devices[i].supported = true; + break; + } + } + + return devices; + } + } +} diff --git a/DiscImageChef.Metadata/Statistics.cs b/DiscImageChef.Metadata/Statistics.cs index 0763afab..c2a6096a 100644 --- a/DiscImageChef.Metadata/Statistics.cs +++ b/DiscImageChef.Metadata/Statistics.cs @@ -79,6 +79,7 @@ namespace DiscImageChef.Metadata public long MediaScan; public long PrintHex; public long Verify; + public long ListDevices; } public class VerifiedItems diff --git a/DiscImageChef.Server/Controllers/UploadStatsController.cs b/DiscImageChef.Server/Controllers/UploadStatsController.cs index 7cfb1d8c..393f037b 100644 --- a/DiscImageChef.Server/Controllers/UploadStatsController.cs +++ b/DiscImageChef.Server/Controllers/UploadStatsController.cs @@ -110,6 +110,7 @@ namespace DiscImageChef.Server.Controllers oldStats.Commands.Verify += newStats.Commands.Verify; oldStats.Commands.Ls += newStats.Commands.Ls; oldStats.Commands.ExtractFiles += newStats.Commands.ExtractFiles; + oldStats.Commands.ListDevices += newStats.Commands.ListDevices; } } diff --git a/DiscImageChef.Server/Default.aspx b/DiscImageChef.Server/Default.aspx index a7ebf686..a1926bfc 100644 --- a/DiscImageChef.Server/Default.aspx +++ b/DiscImageChef.Server/Default.aspx @@ -37,23 +37,24 @@

Commands run:

- analyze command has been run times
- benchmark command has been run times
- checksum command has been run times
- compare command has been run times
- create-sidecar command has been run times
- decode command has been run times
- device-info command has been run times
- device-report command has been run times
- dump-media command has been run times
- entropy command has been run times
+ analyze command has been run times
+ benchmark command has been run times
+ checksum command has been run times
+ compare command has been run times
+ create-sidecar command has been run times
+ decode command has been run times
+ device-info command has been run times
+ device-report command has been run times
+ dump-media command has been run times
+ entropy command has been run times
extract-files command has been run times
- formats command has been run times
+ formats command has been run times
+ list-devices command has been run times
ls command has been run times
- media-info command has been run times
- media-scan command has been run times
- printhex command has been run times
- verify command has been run times + media-info command has been run times
+ media-scan command has been run times
+ printhex command has been run times
+ verify command has been run times

diff --git a/DiscImageChef.Server/Default.aspx.cs b/DiscImageChef.Server/Default.aspx.cs index 02c0d218..7bb11dcc 100644 --- a/DiscImageChef.Server/Default.aspx.cs +++ b/DiscImageChef.Server/Default.aspx.cs @@ -105,6 +105,7 @@ namespace DiscImageChef.Server lblDeviceReport.Text = statistics.Commands.DeviceReport.ToString(); lblLs.Text = statistics.Commands.Ls.ToString(); lblExtractFiles.Text = statistics.Commands.ExtractFiles.ToString(); + lblListDevices.Text = statistics.Commands.ListDevices.ToString(); } else divCommands.Visible = false; diff --git a/DiscImageChef.Server/Default.aspx.designer.cs b/DiscImageChef.Server/Default.aspx.designer.cs index fdbd4523..ed737446 100644 --- a/DiscImageChef.Server/Default.aspx.designer.cs +++ b/DiscImageChef.Server/Default.aspx.designer.cs @@ -1,12 +1,12 @@ -// ------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Mono Runtime Version: 4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -// ------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ namespace DiscImageChef.Server { @@ -53,6 +53,8 @@ namespace DiscImageChef.Server { protected System.Web.UI.WebControls.Label lblFormats; + protected System.Web.UI.WebControls.Label lblListDevices; + protected System.Web.UI.WebControls.Label lblLs; protected System.Web.UI.WebControls.Label lblMediaInfo; diff --git a/DiscImageChef/Commands/ListDevices.cs b/DiscImageChef/Commands/ListDevices.cs new file mode 100644 index 00000000..a739883a --- /dev/null +++ b/DiscImageChef/Commands/ListDevices.cs @@ -0,0 +1,67 @@ +// /*************************************************************************** +// The Disc Image Chef +// ---------------------------------------------------------------------------- +// +// Filename : ListDevices.cs +// Author(s) : Natalia Portillo +// +// Component : Verbs. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements the 'media-info' verb. +// +// --[ 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 . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2017 Natalia Portillo +// ****************************************************************************/ + +using System.Linq; +using DiscImageChef.Console; +using DiscImageChef.Devices; + +namespace DiscImageChef.Commands +{ + public static class ListDevices + { + public static void doListDevices(ListDevicesOptions options) + { + DicConsole.DebugWriteLine("Media-Info command", "--debug={0}", options.Debug); + DicConsole.DebugWriteLine("Media-Info command", "--verbose={0}", options.Verbose); + + Devices.DeviceInfo[] devices = Device.ListDevices(); + + if(devices == null || devices.Length == 0) + DicConsole.WriteLine("No known devices attached."); + else + { + devices = devices.OrderBy(d => d.path).ToArray(); + + DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", + "Path", "Vendor", "Model", "Serial", "Bus", "Supported?"); + DicConsole.WriteLine("{0,-22}+{1,-16}+{2,-24}+{3,-24}+{4,-10}+{5,-10}", + "----------------------", "----------------", "------------------------", + "------------------------", "----------", "----------"); + foreach(Devices.DeviceInfo dev in devices) + DicConsole.WriteLine("{0,-22}|{1,-16}|{2,-24}|{3,-24}|{4,-10}|{5,-10}", dev.path, dev.vendor, dev.model, dev.serial, dev.bus, dev.supported); + } + + Core.Statistics.AddCommand("list-devices"); + } + } +} + diff --git a/DiscImageChef/DiscImageChef.csproj b/DiscImageChef/DiscImageChef.csproj index 88ce8ef0..44fda6ac 100644 --- a/DiscImageChef/DiscImageChef.csproj +++ b/DiscImageChef/DiscImageChef.csproj @@ -68,6 +68,7 @@ + @@ -79,22 +80,14 @@ - - - - - - - - - - + + @@ -148,18 +141,9 @@ - - - - - - - - - - - - + + + diff --git a/DiscImageChef/Main.cs b/DiscImageChef/Main.cs index 7854f0c5..104e0a33 100644 --- a/DiscImageChef/Main.cs +++ b/DiscImageChef/Main.cs @@ -57,7 +57,7 @@ namespace DiscImageChef typeof(CreateSidecarOptions), typeof(DumpMediaOptions), typeof(DeviceReportOptions), typeof(ConfigureOptions), typeof(StatsOptions), typeof(LsOptions), - typeof(ExtractFilesOptions)}) + typeof(ExtractFilesOptions), typeof(ListDevicesOptions)}) .WithParsed(opts => { if(opts.Debug) @@ -226,6 +226,15 @@ namespace DiscImageChef Commands.ExtractFiles.doExtractFiles(opts); }) + .WithParsed(opts => + { + if(opts.Debug) + DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine; + if(opts.Verbose) + DicConsole.VerboseWriteLineEvent += System.Console.WriteLine; + PrintCopyright(); + Commands.ListDevices.doListDevices(opts); + }) .WithParsed(opts => { PrintCopyright(); Commands.Configure.doConfigure(); }) .WithParsed(opts => { PrintCopyright(); Commands.Statistics.showStats(); }) diff --git a/DiscImageChef/Options.cs b/DiscImageChef/Options.cs index 98377e17..2e3560e4 100644 --- a/DiscImageChef/Options.cs +++ b/DiscImageChef/Options.cs @@ -352,5 +352,9 @@ namespace DiscImageChef public bool Xattrs { get; set; } } + [Verb("list-devices", HelpText = "Lists all connected devices.")] + public class ListDevicesOptions : CommonOptions + { + } }