diff --git a/DiscImageChef.Devices/Device/Constructor.cs b/DiscImageChef.Devices/Device/Constructor.cs index 5d3b7f672..a9d074505 100644 --- a/DiscImageChef.Devices/Device/Constructor.cs +++ b/DiscImageChef.Devices/Device/Constructor.cs @@ -62,9 +62,9 @@ namespace DiscImageChef.Devices /// Device path public Device(string devicePath) { - PlatformId = DetectOS.GetRealPlatformID(); - Timeout = 15; - Error = false; + PlatformId = DetectOS.GetRealPlatformID(); + Timeout = 15; + Error = false; IsRemovable = false; switch(PlatformId) @@ -72,12 +72,13 @@ namespace DiscImageChef.Devices case PlatformID.Win32NT: { FileHandle = Extern.CreateFile(devicePath, FileAccess.GenericRead | FileAccess.GenericWrite, - FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.OpenExisting, + FileShare.Read | FileShare.Write, IntPtr.Zero, + FileMode.OpenExisting, FileAttributes.Normal, IntPtr.Zero); if(((SafeFileHandle)FileHandle).IsInvalid) { - Error = true; + Error = true; LastError = Marshal.GetLastWin32Error(); } @@ -85,11 +86,25 @@ namespace DiscImageChef.Devices } case PlatformID.Linux: { - FileHandle = Linux.Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking); + FileHandle = + Linux.Extern.open(devicePath, + FileFlags.ReadWrite | FileFlags.NonBlocking | FileFlags.CreateNew); if((int)FileHandle < 0) { - Error = true; + LastError = Marshal.GetLastWin32Error(); + + if(LastError == 13) // EACCES + { + FileHandle = Linux.Extern.open(devicePath, FileFlags.Readonly | FileFlags.NonBlocking); + if((int)FileHandle < 0) + { + Error = true; + LastError = Marshal.GetLastWin32Error(); + } + } + else Error = true; + LastError = Marshal.GetLastWin32Error(); } @@ -101,7 +116,7 @@ namespace DiscImageChef.Devices if(((IntPtr)FileHandle).ToInt64() == 0) { - Error = true; + Error = true; LastError = Marshal.GetLastWin32Error(); } @@ -118,7 +133,7 @@ namespace DiscImageChef.Devices if(Error) throw new SystemException($"Error {LastError} opening device."); - Type = DeviceType.Unknown; + Type = DeviceType.Unknown; ScsiType = PeripheralDeviceTypes.UnknownDevice; byte[] ataBuf; @@ -133,15 +148,15 @@ namespace DiscImageChef.Devices { case PlatformID.Win32NT: StoragePropertyQuery query = new StoragePropertyQuery(); - query.PropertyId = StoragePropertyId.Device; - query.QueryType = StorageQueryType.Standard; + query.PropertyId = StoragePropertyId.Device; + query.QueryType = StorageQueryType.Standard; query.AdditionalParameters = new byte[1]; IntPtr descriptorPtr = Marshal.AllocHGlobal(1000); - byte[] descriptorB = new byte[1000]; + byte[] descriptorB = new byte[1000]; uint returned = 0; - int error = 0; + int error = 0; bool hasError = !Extern.DeviceIoControlStorageQuery((SafeFileHandle)FileHandle, WindowsIoctl.IoctlStorageQueryProperty, @@ -156,18 +171,18 @@ namespace DiscImageChef.Devices { StorageDeviceDescriptor descriptor = new StorageDeviceDescriptor { - Version = BitConverter.ToUInt32(descriptorB, 0), - Size = BitConverter.ToUInt32(descriptorB, 4), - DeviceType = descriptorB[8], - DeviceTypeModifier = descriptorB[9], - RemovableMedia = descriptorB[10] > 0, - CommandQueueing = descriptorB[11] > 0, - VendorIdOffset = BitConverter.ToInt32(descriptorB, 12), - ProductIdOffset = BitConverter.ToInt32(descriptorB, 16), + Version = BitConverter.ToUInt32(descriptorB, 0), + Size = BitConverter.ToUInt32(descriptorB, 4), + DeviceType = descriptorB[8], + DeviceTypeModifier = descriptorB[9], + RemovableMedia = descriptorB[10] > 0, + CommandQueueing = descriptorB[11] > 0, + VendorIdOffset = BitConverter.ToInt32(descriptorB, 12), + ProductIdOffset = BitConverter.ToInt32(descriptorB, 16), ProductRevisionOffset = BitConverter.ToInt32(descriptorB, 20), - SerialNumberOffset = BitConverter.ToInt32(descriptorB, 24), - BusType = (StorageBusType)BitConverter.ToUInt32(descriptorB, 28), - RawPropertiesLength = BitConverter.ToUInt32(descriptorB, 32) + SerialNumberOffset = BitConverter.ToInt32(descriptorB, 24), + BusType = (StorageBusType)BitConverter.ToUInt32(descriptorB, 28), + RawPropertiesLength = BitConverter.ToUInt32(descriptorB, 32) }; descriptor.RawDeviceProperties = new byte[descriptor.RawPropertiesLength]; Array.Copy(descriptorB, 36, descriptor.RawDeviceProperties, 0, descriptor.RawPropertiesLength); @@ -183,11 +198,11 @@ namespace DiscImageChef.Devices break; case StorageBusType.FireWire: IsFireWire = true; - Type = DeviceType.SCSI; + Type = DeviceType.SCSI; break; case StorageBusType.USB: IsUsb = true; - Type = DeviceType.SCSI; + Type = DeviceType.SCSI; break; case StorageBusType.ATAPI: Type = DeviceType.ATAPI; @@ -224,6 +239,7 @@ namespace DiscImageChef.Devices if(ataid.HasValue) scsiSense = ScsiInquiry(out inqBuf, out _); } else Manufacturer = "ATA"; + break; } } @@ -283,7 +299,7 @@ namespace DiscImageChef.Devices LastError = Windows.Command.SendMmcCommand((SafeFileHandle)FileHandle, (MmcCommands)SecureDigitalCommands - .SendOperatingCondition, false, true, + .SendOperatingCondition, false, true, MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 | MmcFlags.CommandBcr, 0, 4, 1, ref sdBuffer, out _, out _, out sense); @@ -311,6 +327,7 @@ namespace DiscImageChef.Devices } } } + break; case PlatformID.Linux: if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) || @@ -323,25 +340,33 @@ namespace DiscImageChef.Devices string devPath = devicePath.Substring(5); if(File.Exists("/sys/block/" + devPath + "/device/csd")) { - int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/csd", out cachedCsd); + int len = + ConvertFromHexAscii("/sys/block/" + devPath + "/device/csd", out cachedCsd); if(len == 0) cachedCsd = null; } + if(File.Exists("/sys/block/" + devPath + "/device/cid")) { - int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/cid", out cachedCid); + int len = + ConvertFromHexAscii("/sys/block/" + devPath + "/device/cid", out cachedCid); if(len == 0) cachedCid = null; } + if(File.Exists("/sys/block/" + devPath + "/device/scr")) { - int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/scr", out cachedScr); + int len = + ConvertFromHexAscii("/sys/block/" + devPath + "/device/scr", out cachedScr); if(len == 0) cachedScr = null; } + if(File.Exists("/sys/block/" + devPath + "/device/ocr")) { - int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/ocr", out cachedOcr); + int len = + ConvertFromHexAscii("/sys/block/" + devPath + "/device/ocr", out cachedOcr); if(len == 0) cachedOcr = null; } } + break; default: scsiSense = ScsiInquiry(out inqBuf, out _); @@ -351,7 +376,7 @@ namespace DiscImageChef.Devices #region SecureDigital / MultiMediaCard if(cachedCid != null) { - ScsiType = PeripheralDeviceTypes.DirectAccess; + ScsiType = PeripheralDeviceTypes.DirectAccess; IsRemovable = false; if(cachedScr != null) @@ -359,18 +384,18 @@ namespace DiscImageChef.Devices Type = DeviceType.SecureDigital; CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(cachedCid); Manufacturer = VendorString.Prettify(decoded.Manufacturer); - Model = decoded.ProductName; - Revision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; - Serial = $"{decoded.ProductSerialNumber}"; + Model = decoded.ProductName; + Revision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; + Serial = $"{decoded.ProductSerialNumber}"; } else { Type = DeviceType.MMC; Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(cachedCid); Manufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer); - Model = decoded.ProductName; - Revision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; - Serial = $"{decoded.ProductSerialNumber}"; + Model = decoded.ProductName; + Revision = $"{(decoded.ProductRevision & 0xF0) >> 4:X2}.{decoded.ProductRevision & 0x0F:X2}"; + Serial = $"{decoded.ProductSerialNumber}"; } } #endregion SecureDigital / MultiMediaCard @@ -393,25 +418,25 @@ namespace DiscImageChef.Devices { resolvedLink = Path.GetDirectoryName(resolvedLink); if(!File.Exists(resolvedLink + "/descriptors") || - !File.Exists(resolvedLink + "/idProduct") || + !File.Exists(resolvedLink + "/idProduct") || !File.Exists(resolvedLink + "/idVendor")) continue; FileStream usbFs = new FileStream(resolvedLink + "/descriptors", System.IO.FileMode.Open, System.IO.FileAccess.Read); - byte[] usbBuf = new byte[65536]; - int usbCount = usbFs.Read(usbBuf, 0, 65536); + byte[] usbBuf = new byte[65536]; + int usbCount = usbFs.Read(usbBuf, 0, 65536); UsbDescriptors = new byte[usbCount]; Array.Copy(usbBuf, 0, UsbDescriptors, 0, usbCount); usbFs.Close(); - StreamReader usbSr = new StreamReader(resolvedLink + "/idProduct"); - string usbTemp = usbSr.ReadToEnd(); + StreamReader usbSr = new StreamReader(resolvedLink + "/idProduct"); + string usbTemp = usbSr.ReadToEnd(); ushort.TryParse(usbTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out usbProduct); usbSr.Close(); - usbSr = new StreamReader(resolvedLink + "/idVendor"); + usbSr = new StreamReader(resolvedLink + "/idVendor"); usbTemp = usbSr.ReadToEnd(); ushort.TryParse(usbTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out usbVendor); @@ -419,21 +444,21 @@ namespace DiscImageChef.Devices if(File.Exists(resolvedLink + "/manufacturer")) { - usbSr = new StreamReader(resolvedLink + "/manufacturer"); + usbSr = new StreamReader(resolvedLink + "/manufacturer"); UsbManufacturerString = usbSr.ReadToEnd().Trim(); usbSr.Close(); } if(File.Exists(resolvedLink + "/product")) { - usbSr = new StreamReader(resolvedLink + "/product"); + usbSr = new StreamReader(resolvedLink + "/product"); UsbProductString = usbSr.ReadToEnd().Trim(); usbSr.Close(); } if(File.Exists(resolvedLink + "/serial")) { - usbSr = new StreamReader(resolvedLink + "/serial"); + usbSr = new StreamReader(resolvedLink + "/serial"); UsbSerialString = usbSr.ReadToEnd().Trim(); usbSr.Close(); } @@ -458,14 +483,15 @@ namespace DiscImageChef.Devices if(usbDevice != null) { - UsbDescriptors = usbDevice.BinaryDescriptors; - usbVendor = (ushort)usbDevice.DeviceDescriptor.idVendor; - usbProduct = (ushort)usbDevice.DeviceDescriptor.idProduct; + UsbDescriptors = usbDevice.BinaryDescriptors; + usbVendor = (ushort)usbDevice.DeviceDescriptor.idVendor; + usbProduct = (ushort)usbDevice.DeviceDescriptor.idProduct; UsbManufacturerString = usbDevice.Manufacturer; - UsbProductString = usbDevice.Product; + UsbProductString = usbDevice.Product; UsbSerialString = usbDevice.SerialNumber; // This is incorrect filled by Windows with SCSI/ATA serial number } + break; default: IsUsb = false; @@ -492,19 +518,19 @@ namespace DiscImageChef.Devices if(!File.Exists(resolvedLink + "/model") || !File.Exists(resolvedLink + "/vendor") || !File.Exists(resolvedLink + "/guid")) continue; - StreamReader fwSr = new StreamReader(resolvedLink + "/model"); - string fwTemp = fwSr.ReadToEnd(); + StreamReader fwSr = new StreamReader(resolvedLink + "/model"); + string fwTemp = fwSr.ReadToEnd(); uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out firewireModel); fwSr.Close(); - fwSr = new StreamReader(resolvedLink + "/vendor"); + fwSr = new StreamReader(resolvedLink + "/vendor"); fwTemp = fwSr.ReadToEnd(); uint.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out firewireVendor); fwSr.Close(); - fwSr = new StreamReader(resolvedLink + "/guid"); + fwSr = new StreamReader(resolvedLink + "/guid"); fwTemp = fwSr.ReadToEnd(); ulong.TryParse(fwTemp, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out firewireGuid); @@ -512,14 +538,14 @@ namespace DiscImageChef.Devices if(File.Exists(resolvedLink + "/model_name")) { - fwSr = new StreamReader(resolvedLink + "/model_name"); + fwSr = new StreamReader(resolvedLink + "/model_name"); FireWireModelName = fwSr.ReadToEnd().Trim(); fwSr.Close(); } if(File.Exists(resolvedLink + "/vendor_name")) { - fwSr = new StreamReader(resolvedLink + "/vendor_name"); + fwSr = new StreamReader(resolvedLink + "/vendor_name"); FireWireVendorName = fwSr.ReadToEnd().Trim(); fwSr.Close(); } @@ -564,8 +590,8 @@ namespace DiscImageChef.Devices FileStream cisFs = new FileStream(possibleDir + "/cis", System.IO.FileMode.Open, System.IO.FileAccess.Read); - byte[] cisBuf = new byte[65536]; - int cisCount = cisFs.Read(cisBuf, 0, 65536); + byte[] cisBuf = new byte[65536]; + int cisCount = cisFs.Read(cisBuf, 0, 65536); Cis = new byte[cisCount]; Array.Copy(cisBuf, 0, Cis, 0, cisCount); cisFs.Close(); @@ -585,12 +611,12 @@ namespace DiscImageChef.Devices Inquiry.SCSIInquiry? inquiry = Inquiry.Decode(inqBuf); Type = DeviceType.SCSI; - bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80); + bool serialSense = ScsiInquiry(out inqBuf, out _, 0x80); if(!serialSense) Serial = EVPD.DecodePage80(inqBuf); if(inquiry.HasValue) { - string tmp = StringHandlers.CToString(inquiry.Value.ProductRevisionLevel); + string tmp = StringHandlers.CToString(inquiry.Value.ProductRevisionLevel); if(tmp != null) Revision = tmp.Trim(); tmp = StringHandlers.CToString(inquiry.Value.ProductIdentification); if(tmp != null) Model = tmp.Trim(); @@ -613,7 +639,7 @@ namespace DiscImageChef.Devices else { LastError = 0; - Error = false; + Error = false; } } @@ -633,11 +659,11 @@ namespace DiscImageChef.Devices else { Manufacturer = separated[0]; - Model = separated[separated.Length - 1]; + Model = separated[separated.Length - 1]; } Revision = ataid.Value.FirmwareRevision; - Serial = ataid.Value.SerialNumber; + Serial = ataid.Value.SerialNumber; ScsiType = PeripheralDeviceTypes.DirectAccess; @@ -653,31 +679,35 @@ namespace DiscImageChef.Devices if(Type == DeviceType.Unknown) { Manufacturer = null; - Model = null; - Revision = null; - Serial = null; + Model = null; + Revision = null; + Serial = null; } if(IsUsb) { if(string.IsNullOrEmpty(Manufacturer)) Manufacturer = UsbManufacturerString; - if(string.IsNullOrEmpty(Model)) Model = UsbProductString; + if(string.IsNullOrEmpty(Model)) Model = UsbProductString; if(string.IsNullOrEmpty(Serial)) Serial = UsbSerialString; - else foreach(char c in Serial.Where(char.IsControl)) Serial = UsbSerialString; + else + foreach(char c in Serial.Where(char.IsControl)) + Serial = UsbSerialString; } if(!IsFireWire) return; if(string.IsNullOrEmpty(Manufacturer)) Manufacturer = FireWireVendorName; - if(string.IsNullOrEmpty(Model)) Model = FireWireModelName; + if(string.IsNullOrEmpty(Model)) Model = FireWireModelName; if(string.IsNullOrEmpty(Serial)) Serial = $"{firewireGuid:X16}"; - else foreach(char c in Serial.Where(char.IsControl)) Serial = $"{firewireGuid:X16}"; + else + foreach(char c in Serial.Where(char.IsControl)) + Serial = $"{firewireGuid:X16}"; } static int ConvertFromHexAscii(string file, out byte[] outBuf) { - StreamReader sr = new StreamReader(file); - string ins = sr.ReadToEnd().Trim(); + StreamReader sr = new StreamReader(file); + string ins = sr.ReadToEnd().Trim(); outBuf = new byte[ins.Length / 2]; int count = 0;