Move to file scoped namespaces.

This commit is contained in:
2022-03-06 13:29:30 +00:00
parent df66f70140
commit f0129131e5
53 changed files with 15299 additions and 15352 deletions

View File

@@ -30,61 +30,60 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes
{
/// <summary>Initializes a progress indicator (e.g. makes a progress bar visible)</summary>
public delegate void InitProgressHandler();
namespace Aaru.CommonTypes;
/// <summary>Updates a progress indicator with text</summary>
public delegate void UpdateProgressHandler(string text, long current, long maximum);
/// <summary>Initializes a progress indicator (e.g. makes a progress bar visible)</summary>
public delegate void InitProgressHandler();
/// <summary>Pulses a progress indicator with indeterminate boundaries</summary>
public delegate void PulseProgressHandler(string text);
/// <summary>Updates a progress indicator with text</summary>
public delegate void UpdateProgressHandler(string text, long current, long maximum);
/// <summary>Uninitializes a progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndProgressHandler();
/// <summary>Pulses a progress indicator with indeterminate boundaries</summary>
public delegate void PulseProgressHandler(string text);
/// <summary>Initializes a secondary progress indicator (e.g. makes a progress bar visible)</summary>
public delegate void InitProgressHandler2();
/// <summary>Uninitializes a progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndProgressHandler();
/// <summary>Updates a secondary progress indicator with text</summary>
public delegate void UpdateProgressHandler2(string text, long current, long maximum);
/// <summary>Initializes a secondary progress indicator (e.g. makes a progress bar visible)</summary>
public delegate void InitProgressHandler2();
/// <summary>Pulses a secondary progress indicator with indeterminate boundaries</summary>
public delegate void PulseProgressHandler2(string text);
/// <summary>Updates a secondary progress indicator with text</summary>
public delegate void UpdateProgressHandler2(string text, long current, long maximum);
/// <summary>Uninitializes a secondary progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndProgressHandler2();
/// <summary>Pulses a secondary progress indicator with indeterminate boundaries</summary>
public delegate void PulseProgressHandler2(string text);
/// <summary>Initializes two progress indicators (e.g. makes a progress bar visible)</summary>
public delegate void InitTwoProgressHandler();
/// <summary>Uninitializes a secondary progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndProgressHandler2();
/// <summary>Updates two progress indicators with text</summary>
public delegate void UpdateTwoProgressHandler(string text, long current, long maximum, string text2, long current2,
long maximum2);
/// <summary>Initializes two progress indicators (e.g. makes a progress bar visible)</summary>
public delegate void InitTwoProgressHandler();
/// <summary>Pulses a progress indicator with indeterminate boundaries</summary>
public delegate void PulseTwoProgressHandler(string text, string text2);
/// <summary>Updates two progress indicators with text</summary>
public delegate void UpdateTwoProgressHandler(string text, long current, long maximum, string text2, long current2,
long maximum2);
/// <summary>Uninitializes a progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndTwoProgressHandler();
/// <summary>Pulses a progress indicator with indeterminate boundaries</summary>
public delegate void PulseTwoProgressHandler(string text, string text2);
/// <summary>Updates a status indicator</summary>
public delegate void UpdateStatusHandler(string text);
/// <summary>Uninitializes a progress indicator (e.g. adds a newline to the console)</summary>
public delegate void EndTwoProgressHandler();
/// <summary>Shows an error message</summary>
public delegate void ErrorMessageHandler(string text);
/// <summary>Updates a status indicator</summary>
public delegate void UpdateStatusHandler(string text);
/// <summary>Initializes a block map that's going to be filled with a media scan</summary>
public delegate void InitBlockMapHandler(ulong blocks, ulong blockSize, ulong blocksToRead, ushort currentProfile);
/// <summary>Shows an error message</summary>
public delegate void ErrorMessageHandler(string text);
/// <summary>Updates lists of time taken on scanning from the specified sector</summary>
/// <param name="duration">Time in milliseconds</param>
public delegate void ScanTimeHandler(ulong sector, double duration);
/// <summary>Initializes a block map that's going to be filled with a media scan</summary>
public delegate void InitBlockMapHandler(ulong blocks, ulong blockSize, ulong blocksToRead, ushort currentProfile);
/// <summary>Specified a number of blocks could not be read on scan</summary>
public delegate void ScanUnreadableHandler(ulong sector);
/// <summary>Updates lists of time taken on scanning from the specified sector</summary>
/// <param name="duration">Time in milliseconds</param>
public delegate void ScanTimeHandler(ulong sector, double duration);
/// <summary>Sends the speed of scanning a specific sector</summary>
public delegate void ScanSpeedHandler(ulong sector, double currentSpeed);
}
/// <summary>Specified a number of blocks could not be read on scan</summary>
public delegate void ScanUnreadableHandler(ulong sector);
/// <summary>Sends the speed of scanning a specific sector</summary>
public delegate void ScanSpeedHandler(ulong sector, double currentSpeed);

View File

@@ -36,24 +36,23 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes.Enums
namespace Aaru.CommonTypes.Enums;
/// <summary>Device types</summary>
public enum DeviceType
{
/// <summary>Device types</summary>
public enum DeviceType
{
/// <summary>Unknown device type</summary>
Unknown = -1,
/// <summary>ATA device</summary>
ATA = 1,
/// <summary>ATA Packet device (aka SCSI over ATA)</summary>
ATAPI = 2,
/// <summary>SCSI device (or USB-MSC, SBP2, FC, UAS, etc)</summary>
SCSI = 3,
/// <summary>SecureDigital memory card</summary>
SecureDigital = 4,
/// <summary>MultiMediaCard memory card</summary>
MMC = 5,
/// <summary>NVMe device</summary>
NVMe = 6
}
/// <summary>Unknown device type</summary>
Unknown = -1,
/// <summary>ATA device</summary>
ATA = 1,
/// <summary>ATA Packet device (aka SCSI over ATA)</summary>
ATAPI = 2,
/// <summary>SCSI device (or USB-MSC, SBP2, FC, UAS, etc)</summary>
SCSI = 3,
/// <summary>SecureDigital memory card</summary>
SecureDigital = 4,
/// <summary>MultiMediaCard memory card</summary>
MMC = 5,
/// <summary>NVMe device</summary>
NVMe = 6
}

View File

@@ -40,215 +40,214 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="byte" /></summary>
public class ExtentsByte
{
/// <summary>Implements extents for <see cref="byte" /></summary>
public class ExtentsByte
List<Tuple<byte, byte>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsByte() => _backend = new List<Tuple<byte, byte>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsByte(IEnumerable<Tuple<byte, byte>> list)
{
List<Tuple<byte, byte>> _backend;
_backend = new List<Tuple<byte, byte>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsByte() => _backend = new List<Tuple<byte, byte>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<byte, byte> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsByte(IEnumerable<Tuple<byte, byte>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(byte item)
{
Tuple<byte, byte> removeOne = null;
Tuple<byte, byte> removeTwo = null;
Tuple<byte, byte> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<byte, byte>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<byte, byte> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(byte item)
{
Tuple<byte, byte> removeOne = null;
Tuple<byte, byte> removeTwo = null;
Tuple<byte, byte> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<byte, byte>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<byte, byte>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<byte, byte>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<byte, byte>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<byte, byte>(_backend[i].Item1, item);
itemToAdd = new Tuple<byte, byte>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<byte, byte>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<byte, byte>(item, item));
itemToAdd = new Tuple<byte, byte>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(byte start, byte end, bool run = false)
if(itemToAdd != null)
{
byte realEnd;
if(run)
realEnd = (byte)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(byte t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<byte, byte>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(byte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(byte start, byte end, bool run = false)
{
byte realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(byte item)
if(run)
realEnd = (byte)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(byte t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(byte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(byte item)
{
Tuple<byte, byte> toRemove = null;
Tuple<byte, byte> toAddOne = null;
Tuple<byte, byte> toAddTwo = null;
foreach(Tuple<byte, byte> extent in _backend)
{
Tuple<byte, byte> toRemove = null;
Tuple<byte, byte> toAddOne = null;
Tuple<byte, byte> toAddTwo = null;
foreach(Tuple<byte, byte> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<byte, byte>(extent.Item1, (byte)(item - 1));
toAddTwo = new Tuple<byte, byte>((byte)(item + 1), extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<byte, byte>((byte)(item + 1), extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<byte, byte>(extent.Item1, (byte)(item - 1));
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<byte, byte>(extent.Item1, (byte)(item - 1));
toAddTwo = new Tuple<byte, byte>((byte)(item + 1), extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<byte, byte>((byte)(item + 1), extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<byte, byte>(extent.Item1, (byte)(item - 1));
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<byte, byte>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(byte item, out byte start)
{
start = 0;
foreach(Tuple<byte, byte> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<byte, byte>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(byte item, out byte start)
{
start = 0;
foreach(Tuple<byte, byte> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -41,44 +41,43 @@ using System.Collections.Generic;
using System.Linq;
using Schemas;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Converts extents</summary>
public static class ExtentsConverter
{
/// <summary>Converts extents</summary>
public static class ExtentsConverter
/// <summary>Converts unsigned long integer extents into XML based extents</summary>
/// <param name="extents">Extents</param>
/// <returns>XML based extents</returns>
public static ExtentType[] ToMetadata(ExtentsULong extents)
{
/// <summary>Converts unsigned long integer extents into XML based extents</summary>
/// <param name="extents">Extents</param>
/// <returns>XML based extents</returns>
public static ExtentType[] ToMetadata(ExtentsULong extents)
{
if(extents == null)
return null;
if(extents == null)
return null;
Tuple<ulong, ulong>[] tuples = extents.ToArray();
ExtentType[] array = new ExtentType[tuples.Length];
Tuple<ulong, ulong>[] tuples = extents.ToArray();
ExtentType[] array = new ExtentType[tuples.Length];
for(ulong i = 0; i < (ulong)array.LongLength; i++)
array[i] = new ExtentType
{
Start = tuples[i].Item1,
End = tuples[i].Item2
};
for(ulong i = 0; i < (ulong)array.LongLength; i++)
array[i] = new ExtentType
{
Start = tuples[i].Item1,
End = tuples[i].Item2
};
return array;
}
return array;
}
/// <summary>Converts XML based extents into unsigned long integer extents</summary>
/// <param name="extents">XML based extents</param>
/// <returns>Extents</returns>
public static ExtentsULong FromMetadata(ExtentType[] extents)
{
if(extents == null)
return null;
/// <summary>Converts XML based extents into unsigned long integer extents</summary>
/// <param name="extents">XML based extents</param>
/// <returns>Extents</returns>
public static ExtentsULong FromMetadata(ExtentType[] extents)
{
if(extents == null)
return null;
List<Tuple<ulong, ulong>> tuples =
extents.Select(extent => new Tuple<ulong, ulong>(extent.Start, extent.End)).ToList();
List<Tuple<ulong, ulong>> tuples =
extents.Select(extent => new Tuple<ulong, ulong>(extent.Start, extent.End)).ToList();
return new ExtentsULong(tuples);
}
return new ExtentsULong(tuples);
}
}

View File

@@ -40,215 +40,214 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="int" /></summary>
public class ExtentsInt
{
/// <summary>Implements extents for <see cref="int" /></summary>
public class ExtentsInt
List<Tuple<int, int>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsInt() => _backend = new List<Tuple<int, int>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsInt(IEnumerable<Tuple<int, int>> list)
{
List<Tuple<int, int>> _backend;
_backend = new List<Tuple<int, int>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsInt() => _backend = new List<Tuple<int, int>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<int, int> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsInt(IEnumerable<Tuple<int, int>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(int item)
{
Tuple<int, int> removeOne = null;
Tuple<int, int> removeTwo = null;
Tuple<int, int> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<int, int>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<int, int> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(int item)
{
Tuple<int, int> removeOne = null;
Tuple<int, int> removeTwo = null;
Tuple<int, int> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<int, int>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<int, int>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<int, int>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<int, int>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<int, int>(_backend[i].Item1, item);
itemToAdd = new Tuple<int, int>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<int, int>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<int, int>(item, item));
itemToAdd = new Tuple<int, int>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(int start, int end, bool run = false)
if(itemToAdd != null)
{
int realEnd;
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(int t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<int, int>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(int item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(int start, int end, bool run = false)
{
int realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(int item)
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(int t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(int item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(int item)
{
Tuple<int, int> toRemove = null;
Tuple<int, int> toAddOne = null;
Tuple<int, int> toAddTwo = null;
foreach(Tuple<int, int> extent in _backend)
{
Tuple<int, int> toRemove = null;
Tuple<int, int> toAddOne = null;
Tuple<int, int> toAddTwo = null;
foreach(Tuple<int, int> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<int, int>(extent.Item1, item - 1);
toAddTwo = new Tuple<int, int>(item + 1, extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<int, int>(item + 1, extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<int, int>(extent.Item1, item - 1);
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<int, int>(extent.Item1, item - 1);
toAddTwo = new Tuple<int, int>(item + 1, extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<int, int>(item + 1, extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<int, int>(extent.Item1, item - 1);
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<int, int>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(int item, out int start)
{
start = 0;
foreach(Tuple<int, int> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<int, int>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(int item, out int start)
{
start = 0;
foreach(Tuple<int, int> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,215 +40,214 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="long" /></summary>
public class ExtentsLong
{
/// <summary>Implements extents for <see cref="long" /></summary>
public class ExtentsLong
List<Tuple<long, long>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsLong() => _backend = new List<Tuple<long, long>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsLong(IEnumerable<Tuple<long, long>> list)
{
List<Tuple<long, long>> _backend;
_backend = new List<Tuple<long, long>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsLong() => _backend = new List<Tuple<long, long>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<long, long> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsLong(IEnumerable<Tuple<long, long>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(long item)
{
Tuple<long, long> removeOne = null;
Tuple<long, long> removeTwo = null;
Tuple<long, long> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<long, long>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<long, long> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(long item)
{
Tuple<long, long> removeOne = null;
Tuple<long, long> removeTwo = null;
Tuple<long, long> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<long, long>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<long, long>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<long, long>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<long, long>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<long, long>(_backend[i].Item1, item);
itemToAdd = new Tuple<long, long>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<long, long>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<long, long>(item, item));
itemToAdd = new Tuple<long, long>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(long start, long end, bool run = false)
if(itemToAdd != null)
{
long realEnd;
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(long t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<long, long>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(long item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(long start, long end, bool run = false)
{
long realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(long item)
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(long t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(long item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(long item)
{
Tuple<long, long> toRemove = null;
Tuple<long, long> toAddOne = null;
Tuple<long, long> toAddTwo = null;
foreach(Tuple<long, long> extent in _backend)
{
Tuple<long, long> toRemove = null;
Tuple<long, long> toAddOne = null;
Tuple<long, long> toAddTwo = null;
foreach(Tuple<long, long> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<long, long>(extent.Item1, item - 1);
toAddTwo = new Tuple<long, long>(item + 1, extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<long, long>(item + 1, extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<long, long>(extent.Item1, item - 1);
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<long, long>(extent.Item1, item - 1);
toAddTwo = new Tuple<long, long>(item + 1, extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<long, long>(item + 1, extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<long, long>(extent.Item1, item - 1);
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<long, long>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(long item, out long start)
{
start = 0;
foreach(Tuple<long, long> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<long, long>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(long item, out long start)
{
start = 0;
foreach(Tuple<long, long> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,216 +40,215 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="sbyte" /></summary>
public class ExtentsSByte
{
/// <summary>Implements extents for <see cref="sbyte" /></summary>
public class ExtentsSByte
List<Tuple<sbyte, sbyte>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsSByte() => _backend = new List<Tuple<sbyte, sbyte>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsSByte(IEnumerable<Tuple<sbyte, sbyte>> list)
{
List<Tuple<sbyte, sbyte>> _backend;
_backend = new List<Tuple<sbyte, sbyte>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsSByte() => _backend = new List<Tuple<sbyte, sbyte>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<sbyte, sbyte> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsSByte(IEnumerable<Tuple<sbyte, sbyte>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(sbyte item)
{
Tuple<sbyte, sbyte> removeOne = null;
Tuple<sbyte, sbyte> removeTwo = null;
Tuple<sbyte, sbyte> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<sbyte, sbyte>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<sbyte, sbyte> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(sbyte item)
{
Tuple<sbyte, sbyte> removeOne = null;
Tuple<sbyte, sbyte> removeTwo = null;
Tuple<sbyte, sbyte> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<sbyte, sbyte>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i].Item1, item);
itemToAdd = new Tuple<sbyte, sbyte>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<sbyte, sbyte>(item, item));
itemToAdd = new Tuple<sbyte, sbyte>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(sbyte start, sbyte end, bool run = false)
if(itemToAdd != null)
{
sbyte realEnd;
if(run)
realEnd = (sbyte)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(sbyte t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<sbyte, sbyte>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(sbyte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(sbyte start, sbyte end, bool run = false)
{
sbyte realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(sbyte item)
if(run)
realEnd = (sbyte)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(sbyte t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(sbyte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(sbyte item)
{
Tuple<sbyte, sbyte> toRemove = null;
Tuple<sbyte, sbyte> toAddOne = null;
Tuple<sbyte, sbyte> toAddTwo = null;
foreach(Tuple<sbyte, sbyte> extent in _backend)
{
Tuple<sbyte, sbyte> toRemove = null;
Tuple<sbyte, sbyte> toAddOne = null;
Tuple<sbyte, sbyte> toAddTwo = null;
foreach(Tuple<sbyte, sbyte> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>(extent.Item1, (sbyte)(item - 1));
toAddTwo = new Tuple<sbyte, sbyte>((sbyte)(item + 1), extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>((sbyte)(item + 1), extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>(extent.Item1, (sbyte)(item - 1));
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>(extent.Item1, (sbyte)(item - 1));
toAddTwo = new Tuple<sbyte, sbyte>((sbyte)(item + 1), extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>((sbyte)(item + 1), extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<sbyte, sbyte>(extent.Item1, (sbyte)(item - 1));
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<sbyte, sbyte>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(sbyte item, out sbyte start)
{
start = 0;
foreach(Tuple<sbyte, sbyte> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<sbyte, sbyte>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(sbyte item, out sbyte start)
{
start = 0;
foreach(Tuple<sbyte, sbyte> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,216 +40,215 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="short" /></summary>
public class ExtentsShort
{
/// <summary>Implements extents for <see cref="short" /></summary>
public class ExtentsShort
List<Tuple<short, short>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsShort() => _backend = new List<Tuple<short, short>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsShort(IEnumerable<Tuple<short, short>> list)
{
List<Tuple<short, short>> _backend;
_backend = new List<Tuple<short, short>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsShort() => _backend = new List<Tuple<short, short>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<short, short> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsShort(IEnumerable<Tuple<short, short>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(short item)
{
Tuple<short, short> removeOne = null;
Tuple<short, short> removeTwo = null;
Tuple<short, short> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<short, short>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<short, short> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(short item)
{
Tuple<short, short> removeOne = null;
Tuple<short, short> removeTwo = null;
Tuple<short, short> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<short, short>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<short, short>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<short, short>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<short, short>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<short, short>(_backend[i].Item1, item);
itemToAdd = new Tuple<short, short>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<short, short>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<short, short>(item, item));
itemToAdd = new Tuple<short, short>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(short start, short end, bool run = false)
if(itemToAdd != null)
{
short realEnd;
if(run)
realEnd = (short)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(short t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<short, short>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(short item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(short start, short end, bool run = false)
{
short realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(short item)
if(run)
realEnd = (short)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(short t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(short item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(short item)
{
Tuple<short, short> toRemove = null;
Tuple<short, short> toAddOne = null;
Tuple<short, short> toAddTwo = null;
foreach(Tuple<short, short> extent in _backend)
{
Tuple<short, short> toRemove = null;
Tuple<short, short> toAddOne = null;
Tuple<short, short> toAddTwo = null;
foreach(Tuple<short, short> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<short, short>(extent.Item1, (short)(item - 1));
toAddTwo = new Tuple<short, short>((short)(item + 1), extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<short, short>((short)(item + 1), extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<short, short>(extent.Item1, (short)(item - 1));
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<short, short>(extent.Item1, (short)(item - 1));
toAddTwo = new Tuple<short, short>((short)(item + 1), extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<short, short>((short)(item + 1), extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<short, short>(extent.Item1, (short)(item - 1));
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<short, short>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(short item, out short start)
{
start = 0;
foreach(Tuple<short, short> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<short, short>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(short item, out short start)
{
start = 0;
foreach(Tuple<short, short> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,215 +40,214 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="uint" /></summary>
public class ExtentsUInt
{
/// <summary>Implements extents for <see cref="uint" /></summary>
public class ExtentsUInt
List<Tuple<uint, uint>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsUInt() => _backend = new List<Tuple<uint, uint>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsUInt(IEnumerable<Tuple<uint, uint>> list)
{
List<Tuple<uint, uint>> _backend;
_backend = new List<Tuple<uint, uint>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsUInt() => _backend = new List<Tuple<uint, uint>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<uint, uint> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsUInt(IEnumerable<Tuple<uint, uint>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(uint item)
{
Tuple<uint, uint> removeOne = null;
Tuple<uint, uint> removeTwo = null;
Tuple<uint, uint> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<uint, uint>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<uint, uint> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(uint item)
{
Tuple<uint, uint> removeOne = null;
Tuple<uint, uint> removeTwo = null;
Tuple<uint, uint> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<uint, uint>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<uint, uint>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<uint, uint>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<uint, uint>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<uint, uint>(_backend[i].Item1, item);
itemToAdd = new Tuple<uint, uint>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<uint, uint>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<uint, uint>(item, item));
itemToAdd = new Tuple<uint, uint>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(uint start, uint end, bool run = false)
if(itemToAdd != null)
{
uint realEnd;
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(uint t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<uint, uint>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(uint item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(uint start, uint end, bool run = false)
{
uint realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(uint item)
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(uint t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(uint item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(uint item)
{
Tuple<uint, uint> toRemove = null;
Tuple<uint, uint> toAddOne = null;
Tuple<uint, uint> toAddTwo = null;
foreach(Tuple<uint, uint> extent in _backend)
{
Tuple<uint, uint> toRemove = null;
Tuple<uint, uint> toAddOne = null;
Tuple<uint, uint> toAddTwo = null;
foreach(Tuple<uint, uint> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<uint, uint>(extent.Item1, item - 1);
toAddTwo = new Tuple<uint, uint>(item + 1, extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<uint, uint>(item + 1, extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<uint, uint>(extent.Item1, item - 1);
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<uint, uint>(extent.Item1, item - 1);
toAddTwo = new Tuple<uint, uint>(item + 1, extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<uint, uint>(item + 1, extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<uint, uint>(extent.Item1, item - 1);
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<uint, uint>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(uint item, out uint start)
{
start = 0;
foreach(Tuple<uint, uint> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<uint, uint>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(uint item, out uint start)
{
start = 0;
foreach(Tuple<uint, uint> extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,216 +40,215 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="ulong" /></summary>
public class ExtentsULong
{
/// <summary>Implements extents for <see cref="ulong" /></summary>
public class ExtentsULong
List<Tuple<ulong, ulong>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsULong() => _backend = new List<Tuple<ulong, ulong>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsULong(IEnumerable<Tuple<ulong, ulong>> list)
{
List<Tuple<ulong, ulong>> _backend;
_backend = new List<Tuple<ulong, ulong>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsULong() => _backend = new List<Tuple<ulong, ulong>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<ulong, ulong> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsULong(IEnumerable<Tuple<ulong, ulong>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(ulong item)
{
Tuple<ulong, ulong> removeOne = null;
Tuple<ulong, ulong> removeTwo = null;
Tuple<ulong, ulong> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<ulong, ulong>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<ulong, ulong> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(ulong item)
{
Tuple<ulong, ulong> removeOne = null;
Tuple<ulong, ulong> removeTwo = null;
Tuple<ulong, ulong> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<ulong, ulong>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<ulong, ulong>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<ulong, ulong>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<ulong, ulong>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<ulong, ulong>(_backend[i].Item1, item);
itemToAdd = new Tuple<ulong, ulong>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<ulong, ulong>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<ulong, ulong>(item, item));
itemToAdd = new Tuple<ulong, ulong>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(ulong start, ulong end, bool run = false)
if(itemToAdd != null)
{
ulong realEnd;
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(ulong t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<ulong, ulong>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(ulong item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(ulong start, ulong end, bool run = false)
{
ulong realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(ulong item)
if(run)
realEnd = start + end - 1;
else
realEnd = end;
// TODO: Optimize this
for(ulong t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(ulong item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(ulong item)
{
Tuple<ulong, ulong> toRemove = null;
Tuple<ulong, ulong> toAddOne = null;
Tuple<ulong, ulong> toAddTwo = null;
foreach(Tuple<ulong, ulong> extent in _backend)
{
Tuple<ulong, ulong> toRemove = null;
Tuple<ulong, ulong> toAddOne = null;
Tuple<ulong, ulong> toAddTwo = null;
foreach(Tuple<ulong, ulong> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(extent.Item1, item - 1);
toAddTwo = new Tuple<ulong, ulong>(item + 1, extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(item + 1, extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(extent.Item1, item - 1);
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(extent.Item1, item - 1);
toAddTwo = new Tuple<ulong, ulong>(item + 1, extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(item + 1, extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ulong, ulong>(extent.Item1, item - 1);
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<ulong, ulong>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(ulong item, out ulong start)
{
start = 0;
foreach(Tuple<ulong, ulong> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<ulong, ulong>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(ulong item, out ulong start)
{
start = 0;
foreach(Tuple<ulong, ulong> extent in
_backend.Where(extent => item >= extent.Item1 && item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -40,216 +40,215 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace Aaru.CommonTypes.Extents
namespace Aaru.CommonTypes.Extents;
/// <summary>Implements extents for <see cref="ushort" /></summary>
public class ExtentsUShort
{
/// <summary>Implements extents for <see cref="ushort" /></summary>
public class ExtentsUShort
List<Tuple<ushort, ushort>> _backend;
/// <summary>Initialize an empty list of extents</summary>
public ExtentsUShort() => _backend = new List<Tuple<ushort, ushort>>();
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsUShort(IEnumerable<Tuple<ushort, ushort>> list)
{
List<Tuple<ushort, ushort>> _backend;
_backend = new List<Tuple<ushort, ushort>>();
/// <summary>Initialize an empty list of extents</summary>
public ExtentsUShort() => _backend = new List<Tuple<ushort, ushort>>();
// This ensure no overlapping extents are added on creation
foreach(Tuple<ushort, ushort> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Initializes extents with an specific list</summary>
/// <param name="list">List of extents as tuples "start, end"</param>
public ExtentsUShort(IEnumerable<Tuple<ushort, ushort>> list)
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(ushort item)
{
Tuple<ushort, ushort> removeOne = null;
Tuple<ushort, ushort> removeTwo = null;
Tuple<ushort, ushort> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
{
_backend = new List<Tuple<ushort, ushort>>();
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// This ensure no overlapping extents are added on creation
foreach(Tuple<ushort, ushort> t in list)
Add(t.Item1, t.Item2);
}
/// <summary>Gets a count of how many extents are stored</summary>
public int Count => _backend.Count;
/// <summary>Adds the specified number to the corresponding extent, or creates a new one</summary>
/// <param name="item"></param>
public void Add(ushort item)
{
Tuple<ushort, ushort> removeOne = null;
Tuple<ushort, ushort> removeTwo = null;
Tuple<ushort, ushort> itemToAdd = null;
for(int i = 0; i < _backend.Count; i++)
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
// Already contained in an extent
if(item >= _backend[i].Item1 &&
item <= _backend[i].Item2)
return;
// Expands existing extent start
if(item == _backend[i].Item1 - 1)
{
removeOne = _backend[i];
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<ushort, ushort>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<ushort, ushort>(item, _backend[i].Item2);
break;
}
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
if(i > 0 &&
item == _backend[i - 1].Item2 + 1)
{
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<ushort, ushort>(_backend[i].Item1, _backend[i + 1].Item2);
removeTwo = _backend[i - 1];
itemToAdd = new Tuple<ushort, ushort>(_backend[i - 1].Item1, _backend[i].Item2);
}
else
itemToAdd = new Tuple<ushort, ushort>(_backend[i].Item1, item);
itemToAdd = new Tuple<ushort, ushort>(item, _backend[i].Item2);
break;
}
if(itemToAdd != null)
// Expands existing extent end
if(item != _backend[i].Item2 + 1)
continue;
removeOne = _backend[i];
if(i < _backend.Count - 1 &&
item == _backend[i + 1].Item1 - 1)
{
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
removeTwo = _backend[i + 1];
itemToAdd = new Tuple<ushort, ushort>(_backend[i].Item1, _backend[i + 1].Item2);
}
else
_backend.Add(new Tuple<ushort, ushort>(item, item));
itemToAdd = new Tuple<ushort, ushort>(_backend[i].Item1, item);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
break;
}
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(ushort start, ushort end, bool run = false)
if(itemToAdd != null)
{
ushort realEnd;
if(run)
realEnd = (ushort)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(ushort t = start; t <= realEnd; t++)
Add(t);
_backend.Remove(removeOne);
_backend.Remove(removeTwo);
_backend.Add(itemToAdd);
}
else
_backend.Add(new Tuple<ushort, ushort>(item, item));
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(ushort item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
}
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Adds a new extent</summary>
/// <param name="start">First element of the extent</param>
/// <param name="end">
/// Last element of the extent or if <see cref="run" /> is <c>true</c> how many elements the extent runs
/// for
/// </param>
/// <param name="run">If set to <c>true</c>, <see cref="end" /> indicates how many elements the extent runs for</param>
public void Add(ushort start, ushort end, bool run = false)
{
ushort realEnd;
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(ushort item)
if(run)
realEnd = (ushort)(start + end - 1);
else
realEnd = end;
// TODO: Optimize this
for(ushort t = start; t <= realEnd; t++)
Add(t);
}
/// <summary>Checks if the specified item is contained by an extent on this instance</summary>
/// <param name="item">Item to search for</param>
/// <returns><c>true</c> if any of the extents on this instance contains the item</returns>
public bool Contains(ushort item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2);
/// <summary>Removes all extents from this instance</summary>
public void Clear() => _backend.Clear();
/// <summary>Removes an item from the extents in this instance</summary>
/// <param name="item">Item to remove</param>
/// <returns><c>true</c> if the item was contained in a known extent and removed, false otherwise</returns>
public bool Remove(ushort item)
{
Tuple<ushort, ushort> toRemove = null;
Tuple<ushort, ushort> toAddOne = null;
Tuple<ushort, ushort> toAddTwo = null;
foreach(Tuple<ushort, ushort> extent in _backend)
{
Tuple<ushort, ushort> toRemove = null;
Tuple<ushort, ushort> toAddOne = null;
Tuple<ushort, ushort> toAddTwo = null;
foreach(Tuple<ushort, ushort> extent in _backend)
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
// Extent is contained and not a border
if(item > extent.Item1 &&
item < extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>(extent.Item1, (ushort)(item - 1));
toAddTwo = new Tuple<ushort, ushort>((ushort)(item + 1), extent.Item2);
break;
}
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>((ushort)(item + 1), extent.Item2);
break;
}
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>(extent.Item1, (ushort)(item - 1));
break;
}
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>(extent.Item1, (ushort)(item - 1));
toAddTwo = new Tuple<ushort, ushort>((ushort)(item + 1), extent.Item2);
break;
}
// Item not found
if(toRemove == null)
return false;
// Extent is left border, but not only element
if(item == extent.Item1 &&
item != extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>((ushort)(item + 1), extent.Item2);
_backend.Remove(toRemove);
break;
}
if(toAddOne != null)
_backend.Add(toAddOne);
// Extent is right border, but not only element
if(item != extent.Item1 &&
item == extent.Item2)
{
toRemove = extent;
toAddOne = new Tuple<ushort, ushort>(extent.Item1, (ushort)(item - 1));
if(toAddTwo != null)
_backend.Add(toAddTwo);
break;
}
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
// Extent is only element
if(item != extent.Item1 ||
item != extent.Item2)
continue;
toRemove = extent;
break;
}
// Item not found
if(toRemove == null)
return false;
_backend.Remove(toRemove);
if(toAddOne != null)
_backend.Add(toAddOne);
if(toAddTwo != null)
_backend.Add(toAddTwo);
// Sort
_backend = _backend.OrderBy(t => t.Item1).ToList();
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<ushort, ushort>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(ushort item, out ushort start)
{
start = 0;
foreach(Tuple<ushort, ushort> extent in _backend.Where(extent => item >= extent.Item1 &&
item <= extent.Item2))
{
start = extent.Item1;
return true;
}
/// <summary>
/// Converts the list of extents to an array of <see cref="Tuple" /> where T1 is first element of the extent and
/// T2 is last element
/// </summary>
/// <returns>Array of <see cref="Tuple" /></returns>
public Tuple<ushort, ushort>[] ToArray() => _backend.ToArray();
/// <summary>Gets the first element of the extent that contains the specified item</summary>
/// <param name="item">Item</param>
/// <param name="start">First element of extent</param>
/// <returns><c>true</c> if item was found in an extent, false otherwise</returns>
public bool GetStart(ushort item, out ushort start)
{
start = 0;
foreach(Tuple<ushort, ushort> extent in _backend.Where(extent => item >= extent.Item1 &&
item <= extent.Item2))
{
start = extent.Item1;
return true;
}
return false;
}
return false;
}
}

View File

@@ -45,73 +45,72 @@ using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Console;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
/// <summary>Manages the known filters</summary>
public sealed class FiltersList
{
/// <summary>Manages the known filters</summary>
public sealed class FiltersList
/// <summary>List of known filters</summary>
public readonly SortedDictionary<string, IFilter> Filters;
/// <summary>Fills the list of all known filters</summary>
public FiltersList()
{
/// <summary>List of known filters</summary>
public readonly SortedDictionary<string, IFilter> Filters;
var assembly = Assembly.Load("Aaru.Filters");
Filters = new SortedDictionary<string, IFilter>();
/// <summary>Fills the list of all known filters</summary>
public FiltersList()
foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IFilter))))
try
{
var filter = (IFilter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{});
if(filter != null &&
!Filters.ContainsKey(filter.Name.ToLower()))
Filters.Add(filter.Name.ToLower(), filter);
}
catch(Exception exception)
{
AaruConsole.ErrorWriteLine("Exception {0}", exception);
}
}
/// <summary>Gets the filter that allows to read the specified path</summary>
/// <param name="path">Path</param>
/// <returns>The filter that allows reading the specified path</returns>
public IFilter GetFilter(string path)
{
IFilter noFilter = null;
foreach(IFilter filter in Filters.Values)
{
var assembly = Assembly.Load("Aaru.Filters");
Filters = new SortedDictionary<string, IFilter>();
foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IFilter))))
try
try
{
if(filter.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000"))
{
var filter = (IFilter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
if(!filter.Identify(path))
continue;
var foundFilter = (IFilter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{});
if(filter != null &&
!Filters.ContainsKey(filter.Name.ToLower()))
Filters.Add(filter.Name.ToLower(), filter);
}
catch(Exception exception)
{
AaruConsole.ErrorWriteLine("Exception {0}", exception);
}
}
/// <summary>Gets the filter that allows to read the specified path</summary>
/// <param name="path">Path</param>
/// <returns>The filter that allows reading the specified path</returns>
public IFilter GetFilter(string path)
{
IFilter noFilter = null;
foreach(IFilter filter in Filters.Values)
{
try
{
if(filter.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000"))
{
if(!filter.Identify(path))
continue;
var foundFilter = (IFilter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[]
{});
if(foundFilter?.Open(path) == ErrorNumber.NoError)
return foundFilter;
}
else
noFilter = filter;
}
catch(IOException)
{
// Ignore and continue
if(foundFilter?.Open(path) == ErrorNumber.NoError)
return foundFilter;
}
else
noFilter = filter;
}
catch(IOException)
{
// Ignore and continue
}
if(!noFilter?.Identify(path) == true)
return null;
noFilter?.Open(path);
return noFilter;
}
if(!noFilter?.Identify(path) == true)
return null;
noFilter?.Open(path);
return noFilter;
}
}

View File

@@ -38,108 +38,107 @@
using System.Linq;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
/// <summary>Handles CHS geometries</summary>
public static class Geometry
{
/// <summary>Handles CHS geometries</summary>
public static class Geometry
{
/// <summary>List of known disk geometries</summary>
public static readonly (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding
encoding, bool variableSectorsPerTrack, MediaType type)[] KnownGeometries =
{
(32, 1, 8, 319, MediaEncoding.FM, false, MediaType.IBM23FD),
(35, 1, 9, 256, MediaEncoding.FM, false, MediaType.ECMA_66),
(35, 1, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32SS),
(35, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_I),
(35, 1, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33SS),
(35, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540),
(35, 2, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32DS),
(35, 2, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33DS),
(35, 2, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1571),
(40, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_8),
(40, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_9),
(40, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_40),
(40, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_40),
(40, 1, 18, 128, MediaEncoding.FM, false, MediaType.ATARI_525_SD),
(40, 1, 18, 256, MediaEncoding.MFM, false, MediaType.ATARI_525_DD),
(40, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540_Ext),
(40, 1, 26, 128, MediaEncoding.MFM, false, MediaType.ATARI_525_ED),
(40, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_8),
(40, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_9),
(40, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_70),
(70, 2, 9, 512, MediaEncoding.MFM, false, MediaType.Apricot_35),
(74, 1, 8, 512, MediaEncoding.FM, false, MediaType.IBM33FD_512),
(74, 1, 15, 256, MediaEncoding.FM, false, MediaType.IBM33FD_256),
(74, 1, 26, 128, MediaEncoding.FM, false, MediaType.IBM33FD_128),
(74, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.IBM53FD_1024),
(74, 2, 15, 256, MediaEncoding.FM, false, MediaType.IBM43FD_256),
(74, 2, 15, 512, MediaEncoding.MFM, false, MediaType.IBM53FD_512),
(74, 2, 26, 128, MediaEncoding.FM, false, MediaType.IBM43FD_128),
(74, 2, 26, 256, MediaEncoding.MFM, false, MediaType.IBM53FD_256),
(77, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_II),
(77, 1, 26, 128, MediaEncoding.FM, false, MediaType.RX01),
(77, 1, 26, 256, MediaEncoding.MFM, false, MediaType.RX02),
(77, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.NEC_525_HD),
(77, 2, 15, 512, MediaEncoding.MFM, false, MediaType.ECMA_99_15),
(77, 2, 26, 128, MediaEncoding.FM, false, MediaType.NEC_8_SD),
(77, 2, 26, 256, MediaEncoding.MFM, false, MediaType.RX03),
(80, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_8),
(80, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_9),
(80, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_80),
(80, 1, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonySS),
(80, 1, 10, 512, MediaEncoding.MFM, false, MediaType.RX50),
(80, 1, 11, 512, MediaEncoding.MFM, false, MediaType.ATARI_35_SS_DD_11),
(80, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_80),
(80, 2, 5, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_DD),
(80, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_8),
(80, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_9),
(80, 2, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonyDS),
(80, 2, 10, 512, MediaEncoding.MFM, false, MediaType.CBM_35_DD),
(80, 2, 10, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_HD),
(80, 2, 11, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_DD),
(80, 2, 15, 512, MediaEncoding.MFM, false, MediaType.DOS_525_HD),
(80, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_78),
(80, 2, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_DS_DD),
(80, 2, 18, 512, MediaEncoding.MFM, false, MediaType.DOS_35_HD),
(80, 2, 19, 512, MediaEncoding.MFM, false, MediaType.XDF_525),
(80, 2, 21, 512, MediaEncoding.MFM, false, MediaType.DMF),
(80, 2, 22, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_HD),
(80, 2, 23, 512, MediaEncoding.MFM, false, MediaType.XDF_35),
(80, 2, 36, 512, MediaEncoding.MFM, false, MediaType.DOS_35_ED),
(82, 2, 10, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_DD),
(82, 2, 17, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_525_HD),
(82, 2, 21, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_HD),
(240, 2, 38, 512, MediaEncoding.MFM, false, MediaType.NEC_35_TD),
(753, 2, 27, 512, MediaEncoding.MFM, false, MediaType.Floptical),
/// <summary>List of known disk geometries</summary>
public static readonly (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding
encoding, bool variableSectorsPerTrack, MediaType type)[] KnownGeometries =
{
(32, 1, 8, 319, MediaEncoding.FM, false, MediaType.IBM23FD),
(35, 1, 9, 256, MediaEncoding.FM, false, MediaType.ECMA_66),
(35, 1, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32SS),
(35, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_I),
(35, 1, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33SS),
(35, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540),
(35, 2, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32DS),
(35, 2, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33DS),
(35, 2, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1571),
(40, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_8),
(40, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_9),
(40, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_40),
(40, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_40),
(40, 1, 18, 128, MediaEncoding.FM, false, MediaType.ATARI_525_SD),
(40, 1, 18, 256, MediaEncoding.MFM, false, MediaType.ATARI_525_DD),
(40, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540_Ext),
(40, 1, 26, 128, MediaEncoding.MFM, false, MediaType.ATARI_525_ED),
(40, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_8),
(40, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_9),
(40, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_70),
(70, 2, 9, 512, MediaEncoding.MFM, false, MediaType.Apricot_35),
(74, 1, 8, 512, MediaEncoding.FM, false, MediaType.IBM33FD_512),
(74, 1, 15, 256, MediaEncoding.FM, false, MediaType.IBM33FD_256),
(74, 1, 26, 128, MediaEncoding.FM, false, MediaType.IBM33FD_128),
(74, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.IBM53FD_1024),
(74, 2, 15, 256, MediaEncoding.FM, false, MediaType.IBM43FD_256),
(74, 2, 15, 512, MediaEncoding.MFM, false, MediaType.IBM53FD_512),
(74, 2, 26, 128, MediaEncoding.FM, false, MediaType.IBM43FD_128),
(74, 2, 26, 256, MediaEncoding.MFM, false, MediaType.IBM53FD_256),
(77, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_II),
(77, 1, 26, 128, MediaEncoding.FM, false, MediaType.RX01),
(77, 1, 26, 256, MediaEncoding.MFM, false, MediaType.RX02),
(77, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.NEC_525_HD),
(77, 2, 15, 512, MediaEncoding.MFM, false, MediaType.ECMA_99_15),
(77, 2, 26, 128, MediaEncoding.FM, false, MediaType.NEC_8_SD),
(77, 2, 26, 256, MediaEncoding.MFM, false, MediaType.RX03),
(80, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_8),
(80, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_9),
(80, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_80),
(80, 1, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonySS),
(80, 1, 10, 512, MediaEncoding.MFM, false, MediaType.RX50),
(80, 1, 11, 512, MediaEncoding.MFM, false, MediaType.ATARI_35_SS_DD_11),
(80, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_80),
(80, 2, 5, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_DD),
(80, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_8),
(80, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_9),
(80, 2, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonyDS),
(80, 2, 10, 512, MediaEncoding.MFM, false, MediaType.CBM_35_DD),
(80, 2, 10, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_HD),
(80, 2, 11, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_DD),
(80, 2, 15, 512, MediaEncoding.MFM, false, MediaType.DOS_525_HD),
(80, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_78),
(80, 2, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_DS_DD),
(80, 2, 18, 512, MediaEncoding.MFM, false, MediaType.DOS_35_HD),
(80, 2, 19, 512, MediaEncoding.MFM, false, MediaType.XDF_525),
(80, 2, 21, 512, MediaEncoding.MFM, false, MediaType.DMF),
(80, 2, 22, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_HD),
(80, 2, 23, 512, MediaEncoding.MFM, false, MediaType.XDF_35),
(80, 2, 36, 512, MediaEncoding.MFM, false, MediaType.DOS_35_ED),
(82, 2, 10, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_DD),
(82, 2, 17, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_525_HD),
(82, 2, 21, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_HD),
(240, 2, 38, 512, MediaEncoding.MFM, false, MediaType.NEC_35_TD),
(753, 2, 27, 512, MediaEncoding.MFM, false, MediaType.Floptical),
// Following ones are what the device itself report, not the physical geometry
(154, 16, 32, 512, MediaEncoding.MFM, false, MediaType.PocketZip),
(262, 32, 56, 512, MediaEncoding.MFM, false, MediaType.LS240),
(963, 8, 32, 512, MediaEncoding.MFM, false, MediaType.LS120),
(1021, 64, 32, 512, MediaEncoding.MFM, false, MediaType.Jaz),
(1024, 2, 32, 512, MediaEncoding.MFM, false, MediaType.FD32MB)
};
// Following ones are what the device itself report, not the physical geometry
(154, 16, 32, 512, MediaEncoding.MFM, false, MediaType.PocketZip),
(262, 32, 56, 512, MediaEncoding.MFM, false, MediaType.LS240),
(963, 8, 32, 512, MediaEncoding.MFM, false, MediaType.LS120),
(1021, 64, 32, 512, MediaEncoding.MFM, false, MediaType.Jaz),
(1024, 2, 32, 512, MediaEncoding.MFM, false, MediaType.FD32MB)
};
/// <summary>Gets the media type for a given geometry</summary>
/// <param name="geometry">Geometry</param>
/// <returns>Media type</returns>
public static MediaType GetMediaType(
(ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding, bool
variableSectorsPerTrack) geometry) => (from geom in KnownGeometries
where geom.cylinders == geometry.cylinders &&
geom.heads == geometry.heads &&
geom.sectorsPerTrack == geometry.sectorsPerTrack &&
geom.bytesPerSector == geometry.bytesPerSector &&
geom.encoding == geometry.encoding &&
geom.variableSectorsPerTrack ==
geometry.variableSectorsPerTrack select geom.type).
FirstOrDefault();
/// <summary>Gets the media type for a given geometry</summary>
/// <param name="geometry">Geometry</param>
/// <returns>Media type</returns>
public static MediaType GetMediaType(
(ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding, bool
variableSectorsPerTrack) geometry) => (from geom in KnownGeometries
where geom.cylinders == geometry.cylinders &&
geom.heads == geometry.heads &&
geom.sectorsPerTrack == geometry.sectorsPerTrack &&
geom.bytesPerSector == geometry.bytesPerSector &&
geom.encoding == geometry.encoding &&
geom.variableSectorsPerTrack ==
geometry.variableSectorsPerTrack select geom.type).
FirstOrDefault();
/// <summary>Gets the geometry for a given media type</summary>
/// <param name="mediaType">Media type</param>
/// <returns>Geometry</returns>
public static (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding
, bool variableSectorsPerTrack, MediaType type) GetGeometry(MediaType mediaType) =>
(from geom in KnownGeometries where geom.type == mediaType select geom).FirstOrDefault();
}
/// <summary>Gets the geometry for a given media type</summary>
/// <param name="mediaType">Media type</param>
/// <returns>Geometry</returns>
public static (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding
, bool variableSectorsPerTrack, MediaType type) GetGeometry(MediaType mediaType) =>
(from geom in KnownGeometries where geom.type == mediaType select geom).FirstOrDefault();
}

View File

@@ -38,166 +38,165 @@ using Aaru.CommonTypes.Enums;
// ReSharper disable UnusedMember.Global
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Supported archive features</summary>
[Flags]
public enum ArchiveSupportedFeature : uint
{
/// <summary>Supported archive features</summary>
[Flags]
public enum ArchiveSupportedFeature : uint
{
/// <summary>The archive supports filenames for its entries. If this flag is not set, files can only be accessed by number.</summary>
SupportsFilenames = 1 << 0,
/// <summary>
/// The archive supports compression. If this flag is not set, compressed and uncompressed lengths are always the
/// same.
/// </summary>
SupportsCompression = 1 << 1,
/// <summary>
/// The archive supports subdirectories. If this flag is not set, all filenames are guaranteed to not contain any
/// "/" character.
/// </summary>
SupportsSubdirectories = 1 << 2,
/// <summary>
/// The archive supports explicit entries for directories (like Zip, for example). If this flag is not set,
/// directories are implicit by the relative name of the files.
/// </summary>
HasExplicitDirectories = 1 << 3,
/// <summary>The archive stores a timestamp with each entry if this flag is set.</summary>
HasEntryTimestamp = 1 << 4,
/// <summary>If this flag is set, individual files or the whole archive might be encrypted or password-protected.</summary>
SupportsProtection = 1 << 5, // TODO: not implemented yet
/// <summary>The archive supports filenames for its entries. If this flag is not set, files can only be accessed by number.</summary>
SupportsFilenames = 1 << 0,
/// <summary>
/// The archive supports compression. If this flag is not set, compressed and uncompressed lengths are always the
/// same.
/// </summary>
SupportsCompression = 1 << 1,
/// <summary>
/// The archive supports subdirectories. If this flag is not set, all filenames are guaranteed to not contain any
/// "/" character.
/// </summary>
SupportsSubdirectories = 1 << 2,
/// <summary>
/// The archive supports explicit entries for directories (like Zip, for example). If this flag is not set,
/// directories are implicit by the relative name of the files.
/// </summary>
HasExplicitDirectories = 1 << 3,
/// <summary>The archive stores a timestamp with each entry if this flag is set.</summary>
HasEntryTimestamp = 1 << 4,
/// <summary>If this flag is set, individual files or the whole archive might be encrypted or password-protected.</summary>
SupportsProtection = 1 << 5, // TODO: not implemented yet
/// <summary>If this flag is set, the archive supports returning extended attributes (Xattrs) for each entry.</summary>
SupportsXAttrs = 1 << 6
}
/// <summary>If this flag is set, the archive supports returning extended attributes (Xattrs) for each entry.</summary>
SupportsXAttrs = 1 << 6
}
/// <summary>Defines the interface to handle an archive (e.g. ZIP, WAD, etc)</summary>
public interface IArchive
{
/// <summary>Descriptive name of the plugin</summary>
string Name { get; }
/// <summary>Defines the interface to handle an archive (e.g. ZIP, WAD, etc)</summary>
public interface IArchive
{
/// <summary>Descriptive name of the plugin</summary>
string Name { get; }
/// <summary>Unique UUID of the plugin</summary>
Guid Id { get; }
/// <summary>Unique UUID of the plugin</summary>
Guid Id { get; }
/// <summary>Identifies if the specified path contains data recognizable by this archive instance</summary>
/// <param name="path">Path.</param>
bool Identify(string path);
/// <summary>Identifies if the specified path contains data recognizable by this archive instance</summary>
/// <param name="path">Path.</param>
bool Identify(string path);
/// <summary>Identifies if the specified stream contains data recognizable by this archive instance</summary>
/// <param name="stream">Stream.</param>
bool Identify(Stream stream);
/// <summary>Identifies if the specified stream contains data recognizable by this archive instance</summary>
/// <param name="stream">Stream.</param>
bool Identify(Stream stream);
/// <summary>Identifies if the specified buffer contains data recognizable by this archive instance</summary>
/// <param name="buffer">Buffer.</param>
bool Identify(byte[] buffer);
/// <summary>Identifies if the specified buffer contains data recognizable by this archive instance</summary>
/// <param name="buffer">Buffer.</param>
bool Identify(byte[] buffer);
/// <summary>Opens the specified path with this archive instance</summary>
/// <param name="path">Path.</param>
ErrorNumber Open(string path);
/// <summary>Opens the specified path with this archive instance</summary>
/// <param name="path">Path.</param>
ErrorNumber Open(string path);
/// <summary>Opens the specified stream with this archive instance</summary>
/// <param name="stream">Stream.</param>
ErrorNumber Open(Stream stream);
/// <summary>Opens the specified stream with this archive instance</summary>
/// <param name="stream">Stream.</param>
ErrorNumber Open(Stream stream);
/// <summary>Opens the specified buffer with this archive instance</summary>
/// <param name="buffer">Buffer.</param>
ErrorNumber Open(byte[] buffer);
/// <summary>Opens the specified buffer with this archive instance</summary>
/// <param name="buffer">Buffer.</param>
ErrorNumber Open(byte[] buffer);
/// <summary>
/// Returns true if the archive has a file/stream/buffer currently opened and no
/// <see cref="M:Aaru.Filters.Filter.Close" /> has been issued.
/// </summary>
bool IsOpened();
/// <summary>
/// Returns true if the archive has a file/stream/buffer currently opened and no
/// <see cref="M:Aaru.Filters.Filter.Close" /> has been issued.
/// </summary>
bool IsOpened();
/// <summary>Closes all opened streams.</summary>
void Close();
/// <summary>Closes all opened streams.</summary>
void Close();
/// <summary>Return a bitfield indicating the features supported by this archive type.</summary>
/// <returns>The <c>ArchiveSupportedFeature</c> bitfield.</returns>
/// <remarks>
/// This should be a constant, tied to the archive type, not to the particular features used by the
/// currently-opened archive file.
/// </remarks>
ArchiveSupportedFeature GetArchiveFeatures();
/// <summary>Return a bitfield indicating the features supported by this archive type.</summary>
/// <returns>The <c>ArchiveSupportedFeature</c> bitfield.</returns>
/// <remarks>
/// This should be a constant, tied to the archive type, not to the particular features used by the
/// currently-opened archive file.
/// </remarks>
ArchiveSupportedFeature GetArchiveFeatures();
/// <summary>Gets the number of entries (i.e. files) that are contained in this archive.</summary>
/// <remarks>
/// Entries in this context can also mean directories or volume labels, for some types of archives that store
/// these explicitly. Do not rely on all entries being regular files!
/// </remarks>
/// <returns>The number of files.</returns>
int GetNumberOfEntries();
/// <summary>Gets the number of entries (i.e. files) that are contained in this archive.</summary>
/// <remarks>
/// Entries in this context can also mean directories or volume labels, for some types of archives that store
/// these explicitly. Do not rely on all entries being regular files!
/// </remarks>
/// <returns>The number of files.</returns>
int GetNumberOfEntries();
/// <summary>Gets the file name (and path) of the given entry in the archive.</summary>
/// <remarks>
/// The path components are separated by a forward slash "/". <br /> The path should not start with a leading
/// slash (i.e. it should be relative, not absolute).
/// </remarks>
/// <seealso cref="Stat(int)" />
/// <param name="entryNumber">The entry in the archive for which to return the file name.</param>
/// <returns>The file name, with (relative) path</returns>
string GetFilename(int entryNumber);
/// <summary>Gets the file name (and path) of the given entry in the archive.</summary>
/// <remarks>
/// The path components are separated by a forward slash "/". <br /> The path should not start with a leading
/// slash (i.e. it should be relative, not absolute).
/// </remarks>
/// <seealso cref="Stat(int)" />
/// <param name="entryNumber">The entry in the archive for which to return the file name.</param>
/// <returns>The file name, with (relative) path</returns>
string GetFilename(int entryNumber);
/// <summary>
/// Gets the entry number for a particular file path in the archive. <c>fileName</c> is the relative path of the
/// file in the archive. If the file cannot be found, -1 is returned.
/// </summary>
/// <remarks>
/// The path should be relative (no leading slash), using regular slashes as path separator, and be normalized,
/// i.e. no "foo//bar" or "foo/../bar" path components.
/// </remarks>
/// <param name="fileName">The relative path for which to get the entry number.</param>
/// <param name="caseInsensitiveMatch">If set, do a case insensitive matching and return the first file that matches.</param>
/// <returns>The number of the entry corresponding to the given path, or -1 if the path does not exist.</returns>
int GetEntryNumber(string fileName, bool caseInsensitiveMatch);
/// <summary>
/// Gets the entry number for a particular file path in the archive. <c>fileName</c> is the relative path of the
/// file in the archive. If the file cannot be found, -1 is returned.
/// </summary>
/// <remarks>
/// The path should be relative (no leading slash), using regular slashes as path separator, and be normalized,
/// i.e. no "foo//bar" or "foo/../bar" path components.
/// </remarks>
/// <param name="fileName">The relative path for which to get the entry number.</param>
/// <param name="caseInsensitiveMatch">If set, do a case insensitive matching and return the first file that matches.</param>
/// <returns>The number of the entry corresponding to the given path, or -1 if the path does not exist.</returns>
int GetEntryNumber(string fileName, bool caseInsensitiveMatch);
/// <summary>Gets the (compressed) size of the given entry.</summary>
/// <param name="entryNumber">The entry for which to get the compressed size.</param>
/// <returns>The compressed size of the entry, or 0 if the entry is not a regular file.</returns>
/// <remarks>The return value is equal to the return value of <c>GetUncompressedSize()</c> if the file is not compressed.</remarks>
/// <seealso cref="GetUncompressedSize(int)" />
long GetCompressedSize(int entryNumber);
/// <summary>Gets the (compressed) size of the given entry.</summary>
/// <param name="entryNumber">The entry for which to get the compressed size.</param>
/// <returns>The compressed size of the entry, or 0 if the entry is not a regular file.</returns>
/// <remarks>The return value is equal to the return value of <c>GetUncompressedSize()</c> if the file is not compressed.</remarks>
/// <seealso cref="GetUncompressedSize(int)" />
long GetCompressedSize(int entryNumber);
/// <summary>Gets the uncompressed size of the given entry.</summary>
/// <param name="entryNumber">The entry for which to get the uncompressed size.</param>
/// <returns>The uncompressed size of the entry, or 0 if the entry is not a regular file.</returns>
/// <remarks>The return value is equal to the return value of <c>GetCompressedSize()</c> if the file is not compressed.</remarks>
/// <seealso cref="GetCompressedSize(int)" />
long GetUncompressedSize(int entryNumber);
/// <summary>Gets the uncompressed size of the given entry.</summary>
/// <param name="entryNumber">The entry for which to get the uncompressed size.</param>
/// <returns>The uncompressed size of the entry, or 0 if the entry is not a regular file.</returns>
/// <remarks>The return value is equal to the return value of <c>GetCompressedSize()</c> if the file is not compressed.</remarks>
/// <seealso cref="GetCompressedSize(int)" />
long GetUncompressedSize(int entryNumber);
/// <summary>Gets the attributes of a file or directory.</summary>
/// <seealso cref="Stat(int)" />
/// <returns>Error number.</returns>
/// <param name="entryNumber">The entry in the archive for which to retrieve the attributes.</param>
/// <returns>File attributes, or zero if the archive does not support attributes.</returns>
FileAttributes GetAttributes(int entryNumber);
/// <summary>Gets the attributes of a file or directory.</summary>
/// <seealso cref="Stat(int)" />
/// <returns>Error number.</returns>
/// <param name="entryNumber">The entry in the archive for which to retrieve the attributes.</param>
/// <returns>File attributes, or zero if the archive does not support attributes.</returns>
FileAttributes GetAttributes(int entryNumber);
/// <summary>Lists all extended attributes, alternate data streams and forks of the given file.</summary>
/// <param name="entryNumber">The entry in the archive for which to retrieve the list of attributes.</param>
/// <returns>List of extended attributes, alternate data streams and forks.</returns>
List<string> GetXAttrs(int entryNumber);
/// <summary>Lists all extended attributes, alternate data streams and forks of the given file.</summary>
/// <param name="entryNumber">The entry in the archive for which to retrieve the list of attributes.</param>
/// <returns>List of extended attributes, alternate data streams and forks.</returns>
List<string> GetXAttrs(int entryNumber);
/// <summary>Reads an extended attribute, alternate data stream or fork from the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="entryNumber">The entry in the archive for which to retrieve the XAttr.</param>
/// <param name="xattr">Extended attribute, alternate data stream or fork name.</param>
/// <returns>Buffer with the XAttr data.</returns>
ErrorNumber GetXattr(int entryNumber, string xattr, out byte[] buffer);
/// <summary>Reads an extended attribute, alternate data stream or fork from the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="entryNumber">The entry in the archive for which to retrieve the XAttr.</param>
/// <param name="xattr">Extended attribute, alternate data stream or fork name.</param>
/// <returns>Buffer with the XAttr data.</returns>
ErrorNumber GetXattr(int entryNumber, string xattr, out byte[] buffer);
/// <summary>Gets information about an entry in the archive.</summary>
/// <remarks>Note that some of the data might be incomplete or not available at all, depending on the type of archive.</remarks>
/// <seealso cref="GetAttributes(int)" />
/// <seealso cref="GetFilename(int)" />
/// <param name="entryNumber">The entry int he archive for which to get the information</param>
/// <returns>The available information about the entry in the archive</returns>
FileSystemInfo Stat(int entryNumber);
/// <summary>Gets information about an entry in the archive.</summary>
/// <remarks>Note that some of the data might be incomplete or not available at all, depending on the type of archive.</remarks>
/// <seealso cref="GetAttributes(int)" />
/// <seealso cref="GetFilename(int)" />
/// <param name="entryNumber">The entry int he archive for which to get the information</param>
/// <returns>The available information about the entry in the archive</returns>
FileSystemInfo Stat(int entryNumber);
/// <summary>
/// Returns the Filter for the given entry. It will return <c>null</c> if the entry in question is not a regular
/// file (i.e. directory, volume label, etc.)
/// </summary>
/// <param name="entryNumber">The entry for which the Filter should be returned.</param>
/// <returns>The Filter for the given entry.</returns>
IFilter GetEntry(int entryNumber);
}
/// <summary>
/// Returns the Filter for the given entry. It will return <c>null</c> if the entry in question is not a regular
/// file (i.e. directory, volume label, etc.)
/// </summary>
/// <param name="entryNumber">The entry for which the Filter should be returned.</param>
/// <returns>The Filter for the given entry.</returns>
IFilter GetEntry(int entryNumber);
}

View File

@@ -36,24 +36,23 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Defines the interface to implement a checksum or hashing algorithm</summary>
public interface IChecksum
{
/// <summary>Defines the interface to implement a checksum or hashing algorithm</summary>
public interface IChecksum
{
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
void Update(byte[] data, uint len);
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
/// <param name="len">Length of buffer to hash.</param>
void Update(byte[] data, uint len);
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
void Update(byte[] data);
/// <summary>Updates the hash with data.</summary>
/// <param name="data">Data buffer.</param>
void Update(byte[] data);
/// <summary>Returns a byte array of the hash value.</summary>
byte[] Final();
/// <summary>Returns a byte array of the hash value.</summary>
byte[] Final();
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
string End();
}
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
string End();
}

View File

@@ -40,34 +40,33 @@ using System;
using System.Text;
using Schemas;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Interface to implement filesystem plugins.</summary>
public interface IFilesystem
{
/// <summary>Interface to implement filesystem plugins.</summary>
public interface IFilesystem
{
/// <summary>Defines the encoding used to interpret strings in the filesystem</summary>
Encoding Encoding { get; }
/// <summary>Plugin name.</summary>
string Name { get; }
/// <summary>Plugin UUID.</summary>
Guid Id { get; }
/// <summary>Information about the filesystem as expected by CICM Metadata XML</summary>
/// <value>Information about the filesystem as expected by CICM Metadata XML</value>
FileSystemType XmlFsType { get; }
/// <summary>Plugin author</summary>
string Author { get; }
/// <summary>Defines the encoding used to interpret strings in the filesystem</summary>
Encoding Encoding { get; }
/// <summary>Plugin name.</summary>
string Name { get; }
/// <summary>Plugin UUID.</summary>
Guid Id { get; }
/// <summary>Information about the filesystem as expected by CICM Metadata XML</summary>
/// <value>Information about the filesystem as expected by CICM Metadata XML</value>
FileSystemType XmlFsType { get; }
/// <summary>Plugin author</summary>
string Author { get; }
/// <summary>Identifies the filesystem in the specified LBA</summary>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partition">Partition.</param>
/// <returns><c>true</c>, if the filesystem is recognized, <c>false</c> otherwise.</returns>
bool Identify(IMediaImage imagePlugin, Partition partition);
/// <summary>Identifies the filesystem in the specified LBA</summary>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partition">Partition.</param>
/// <returns><c>true</c>, if the filesystem is recognized, <c>false</c> otherwise.</returns>
bool Identify(IMediaImage imagePlugin, Partition partition);
/// <summary>Gets information about the identified filesystem.</summary>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partition">Partition.</param>
/// <param name="information">Filesystem information.</param>
/// <param name="encoding">Which encoding to use for this filesystem.</param>
void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding);
}
/// <summary>Gets information about the identified filesystem.</summary>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partition">Partition.</param>
/// <param name="information">Filesystem information.</param>
/// <param name="encoding">Which encoding to use for this filesystem.</param>
void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding);
}

View File

@@ -40,108 +40,107 @@ using System;
using System.IO;
using Aaru.CommonTypes.Enums;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>
/// Defines a filter, that is, a transformation of the data from a file, like, for example, a compressor (e.g.
/// GZIP), or a container (e.g. AppleDouble)
/// </summary>
public interface IFilter
{
/// <summary>Descriptive name of the plugin</summary>
string Name { get; }
/// <summary>Unique UUID of the plugin</summary>
Guid Id { get; }
/// <summary>Plugin author</summary>
string Author { get; }
/// <summary>
/// Defines a filter, that is, a transformation of the data from a file, like, for example, a compressor (e.g.
/// GZIP), or a container (e.g. AppleDouble)
/// Gets the path used to open this filter.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =&gt;
/// /path/to/archive.zip/path/to/file.bin <br /> Windows: C:\path\to\archive.zip\path\to\file.bin =&gt;
/// C:\path\to\archive.zip\path\to\file.bin
/// </summary>
public interface IFilter
{
/// <summary>Descriptive name of the plugin</summary>
string Name { get; }
/// <summary>Unique UUID of the plugin</summary>
Guid Id { get; }
/// <summary>Plugin author</summary>
string Author { get; }
/// <returns>Path used to open this filter.</returns>
string BasePath { get; }
/// <summary>
/// Gets the path used to open this filter.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =&gt;
/// /path/to/archive.zip/path/to/file.bin <br /> Windows: C:\path\to\archive.zip\path\to\file.bin =&gt;
/// C:\path\to\archive.zip\path\to\file.bin
/// </summary>
/// <returns>Path used to open this filter.</returns>
string BasePath { get; }
/// <summary>Gets creation time of file referenced by this filter.</summary>
/// <returns>The creation time.</returns>
DateTime CreationTime { get; }
/// <summary>Gets creation time of file referenced by this filter.</summary>
/// <returns>The creation time.</returns>
DateTime CreationTime { get; }
/// <summary>Gets length of this filter's data fork.</summary>
/// <returns>The data fork length.</returns>
long DataForkLength { get; }
/// <summary>Gets length of this filter's data fork.</summary>
/// <returns>The data fork length.</returns>
long DataForkLength { get; }
/// <summary>
/// Gets the filename for the file referenced by this filter.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =
/// &gt; file.bin <br /> Windows: C:\path\to\archive.zip\path\to\file.bin =&gt; file.bin
/// </summary>
/// <returns>The filename.</returns>
string Filename { get; }
/// <summary>
/// Gets the filename for the file referenced by this filter.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =
/// &gt; file.bin <br /> Windows: C:\path\to\archive.zip\path\to\file.bin =&gt; file.bin
/// </summary>
/// <returns>The filename.</returns>
string Filename { get; }
/// <summary>Gets last write time of file referenced by this filter.</summary>
/// <returns>The last write time.</returns>
DateTime LastWriteTime { get; }
/// <summary>Gets last write time of file referenced by this filter.</summary>
/// <returns>The last write time.</returns>
DateTime LastWriteTime { get; }
/// <summary>Gets length of file referenced by ths filter.</summary>
/// <returns>The length.</returns>
long Length { get; }
/// <summary>Gets length of file referenced by ths filter.</summary>
/// <returns>The length.</returns>
long Length { get; }
/// <summary>
/// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin =&gt; /path/to/file.bin <br /> Windows:
/// C:\path\to\archive.zip\path\to\file.bin =&gt; \path\to\file.bin
/// </summary>
/// <returns>The path.</returns>
string Path { get; }
/// <summary>
/// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.<br />
/// UNIX: /path/to/archive.zip/path/to/file.bin =&gt; /path/to/file.bin <br /> Windows:
/// C:\path\to\archive.zip\path\to\file.bin =&gt; \path\to\file.bin
/// </summary>
/// <returns>The path.</returns>
string Path { get; }
/// <summary>
/// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to
/// the archive itself.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =&gt; /path/to/archive.zip <br /> Windows:
/// C:\path\to\archive.zip\path\to\file.bin =&gt; C:\path\to\archive.zip
/// </summary>
/// <returns>The parent folder.</returns>
string ParentFolder { get; }
/// <summary>
/// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to
/// the archive itself.<br /> UNIX: /path/to/archive.zip/path/to/file.bin =&gt; /path/to/archive.zip <br /> Windows:
/// C:\path\to\archive.zip\path\to\file.bin =&gt; C:\path\to\archive.zip
/// </summary>
/// <returns>The parent folder.</returns>
string ParentFolder { get; }
/// <summary>Gets length of this filter's resource fork.</summary>
/// <returns>The resource fork length.</returns>
long ResourceForkLength { get; }
/// <summary>Gets length of this filter's resource fork.</summary>
/// <returns>The resource fork length.</returns>
long ResourceForkLength { get; }
/// <summary>Returns true if the file referenced by this filter has a resource fork</summary>
bool HasResourceFork { get; }
/// <summary>Returns true if the file referenced by this filter has a resource fork</summary>
bool HasResourceFork { get; }
/// <summary>Closes all opened streams.</summary>
void Close();
/// <summary>Closes all opened streams.</summary>
void Close();
/// <summary>Gets a stream to access the data fork contents.</summary>
/// <returns>The data fork stream.</returns>
Stream GetDataForkStream();
/// <summary>Gets a stream to access the data fork contents.</summary>
/// <returns>The data fork stream.</returns>
Stream GetDataForkStream();
/// <summary>Gets a stream to access the resource fork contents.</summary>
/// <returns>The resource fork stream.</returns>
Stream GetResourceForkStream();
/// <summary>Gets a stream to access the resource fork contents.</summary>
/// <returns>The resource fork stream.</returns>
Stream GetResourceForkStream();
/// <summary>Identifies if the specified path contains data recognizable by this filter instance</summary>
/// <param name="path">Path.</param>
bool Identify(string path);
/// <summary>Identifies if the specified path contains data recognizable by this filter instance</summary>
/// <param name="path">Path.</param>
bool Identify(string path);
/// <summary>Identifies if the specified stream contains data recognizable by this filter instance</summary>
/// <param name="stream">Stream.</param>
bool Identify(Stream stream);
/// <summary>Identifies if the specified stream contains data recognizable by this filter instance</summary>
/// <param name="stream">Stream.</param>
bool Identify(Stream stream);
/// <summary>Identifies if the specified buffer contains data recognizable by this filter instance</summary>
/// <param name="buffer">Buffer.</param>
bool Identify(byte[] buffer);
/// <summary>Identifies if the specified buffer contains data recognizable by this filter instance</summary>
/// <param name="buffer">Buffer.</param>
bool Identify(byte[] buffer);
/// <summary>Opens the specified path with this filter instance</summary>
/// <param name="path">Path.</param>
ErrorNumber Open(string path);
/// <summary>Opens the specified path with this filter instance</summary>
/// <param name="path">Path.</param>
ErrorNumber Open(string path);
/// <summary>Opens the specified stream with this filter instance</summary>
/// <param name="stream">Stream.</param>
ErrorNumber Open(Stream stream);
/// <summary>Opens the specified stream with this filter instance</summary>
/// <param name="stream">Stream.</param>
ErrorNumber Open(Stream stream);
/// <summary>Opens the specified buffer with this filter instance</summary>
/// <param name="buffer">Buffer.</param>
ErrorNumber Open(byte[] buffer);
}
/// <summary>Opens the specified buffer with this filter instance</summary>
/// <param name="buffer">Buffer.</param>
ErrorNumber Open(byte[] buffer);
}

View File

@@ -39,86 +39,85 @@
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
{
/// <inheritdoc />
/// <summary>
/// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is
/// needed because floppy formatting characteristics are not necesarily compatible with the whole. LBA-oriented
/// interface is defined by <see cref="T:Aaru.CommonTypes.Interfaces.IMediaImage" />. All data returned by these
/// methods is already decoded from its corresponding bitstream.
/// </summary>
public interface IFloppyImage : IMediaImage
{
/// <summary>
/// Floppy info, contains information about physical characteristics of floppy, like size, bitrate, track density,
/// etc...
/// </summary>
FloppyInfo FloppyInfo { get; }
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Reads a sector's user data.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
ErrorNumber ReadSector(ushort track, byte head, ushort sector, out FloppySectorStatus status,
/// <inheritdoc />
/// <summary>
/// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is
/// needed because floppy formatting characteristics are not necesarily compatible with the whole. LBA-oriented
/// interface is defined by <see cref="T:Aaru.CommonTypes.Interfaces.IMediaImage" />. All data returned by these
/// methods is already decoded from its corresponding bitstream.
/// </summary>
public interface IFloppyImage : IMediaImage
{
/// <summary>
/// Floppy info, contains information about physical characteristics of floppy, like size, bitrate, track density,
/// etc...
/// </summary>
FloppyInfo FloppyInfo { get; }
/// <summary>Reads a sector's user data.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
ErrorNumber ReadSector(ushort track, byte head, ushort sector, out FloppySectorStatus status,
out byte[] buffer);
/// <summary>Reads a sector's tag.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever tag is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
/// <param name="tag">Sector tag</param>
ErrorNumber ReadSectorTag(ushort track, byte head, ushort sector, out FloppySectorStatus status,
SectorTagType tag, out byte[] buffer);
/// <summary>Reads a whole track. It includes all gaps, address marks, sectors data, etc.</summary>
/// <returns>The track data.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
ErrorNumber ReadTrack(ushort track, byte head, out byte[] buffer);
/// <summary>Reads a sector's data including all tags, address mark, and so, in a format dependent of represented media.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
ErrorNumber ReadSectorLong(ushort track, byte head, ushort sector, out FloppySectorStatus status,
out byte[] buffer);
/// <summary>Reads a sector's tag.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever tag is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
/// <param name="tag">Sector tag</param>
ErrorNumber ReadSectorTag(ushort track, byte head, ushort sector, out FloppySectorStatus status,
SectorTagType tag, out byte[] buffer);
/// <summary>Verifies a track.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
bool? VerifyTrack(ushort track, byte head);
/// <summary>Reads a whole track. It includes all gaps, address marks, sectors data, etc.</summary>
/// <returns>The track data.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
ErrorNumber ReadTrack(ushort track, byte head, out byte[] buffer);
/// <summary>Reads a sector's data including all tags, address mark, and so, in a format dependent of represented media.</summary>
/// <returns>
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates is returned
/// randomly. If <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" /> or
/// <see cref="FloppySectorStatus.Hole" /> random data is returned. If <see cref="status" /> is
/// <see cref="FloppySectorStatus.NotFound" /> <c>null</c> is returned. Otherwise, whatever is in the sector is
/// returned.
/// </returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
ErrorNumber ReadSectorLong(ushort track, byte head, ushort sector, out FloppySectorStatus status,
out byte[] buffer);
/// <summary>Verifies a track.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
bool? VerifyTrack(ushort track, byte head);
/// <summary>Verifies a sector, relative to track.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
bool? VerifySector(ushort track, byte head, ushort sector);
}
/// <summary>Verifies a sector, relative to track.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
bool? VerifySector(ushort track, byte head, ushort sector);
}

View File

@@ -40,84 +40,83 @@ using System.Collections.Generic;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <inheritdoc cref="IMediaImage" />
/// <summary>Abstract class to implement disk image reading plugins.</summary>
public interface IOpticalMediaImage : IMediaImage, IPartitionableMediaImage, IVerifiableSectorsImage
{
/// <inheritdoc cref="IMediaImage" />
/// <summary>Abstract class to implement disk image reading plugins.</summary>
public interface IOpticalMediaImage : IMediaImage, IPartitionableMediaImage, IVerifiableSectorsImage
{
/// <summary>Gets the disc track extents (start, length).</summary>
/// <value>The track extents.</value>
List<Track> Tracks { get; }
/// <summary>Gets the sessions (optical discs only).</summary>
/// <value>The sessions.</value>
List<Session> Sessions { get; }
/// <summary>Gets the disc track extents (start, length).</summary>
/// <value>The track extents.</value>
List<Track> Tracks { get; }
/// <summary>Gets the sessions (optical discs only).</summary>
/// <value>The sessions.</value>
List<Session> Sessions { get; }
/// <summary>Reads a sector's user data, relative to track.</summary>
/// <returns>The sector's user data.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer);
/// <summary>Reads a sector's user data, relative to track.</summary>
/// <returns>The sector's user data.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSector(ulong sectorAddress, uint track, out byte[] buffer);
/// <summary>Reads a sector's tag, relative to track.</summary>
/// <returns>The sector's tag.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="tag">Tag type.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer);
/// <summary>Reads a sector's tag, relative to track.</summary>
/// <returns>The sector's tag.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="tag">Tag type.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag, out byte[] buffer);
/// <summary>Reads user data from several sectors, relative to track.</summary>
/// <returns>The sectors user data.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer);
/// <summary>Reads user data from several sectors, relative to track.</summary>
/// <returns>The sectors user data.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectors(ulong sectorAddress, uint length, uint track, out byte[] buffer);
/// <summary>Reads tag from several sectors, relative to track.</summary>
/// <returns>The sectors tag.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="tag">Tag type.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag, out byte[] buffer);
/// <summary>Reads tag from several sectors, relative to track.</summary>
/// <returns>The sectors tag.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="tag">Tag type.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag, out byte[] buffer);
/// <summary>Reads a complete sector (user data + all tags), relative to track.</summary>
/// <returns>The complete sector. Format depends on disk type.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer);
/// <summary>Reads a complete sector (user data + all tags), relative to track.</summary>
/// <returns>The complete sector. Format depends on disk type.</returns>
/// <param name="sectorAddress">Sector address (relative LBA).</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorLong(ulong sectorAddress, uint track, out byte[] buffer);
/// <summary>Reads several complete sector (user data + all tags), relative to track.</summary>
/// <returns>The complete sectors. Format depends on disk type.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer);
/// <summary>Reads several complete sector (user data + all tags), relative to track.</summary>
/// <returns>The complete sectors. Format depends on disk type.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="buffer"></param>
ErrorNumber ReadSectorsLong(ulong sectorAddress, uint length, uint track, out byte[] buffer);
/// <summary>Gets the disc track extents for a specified session.</summary>
/// <returns>The track extents for that session.</returns>
/// <param name="session">Session.</param>
List<Track> GetSessionTracks(Session session);
/// <summary>Gets the disc track extents for a specified session.</summary>
/// <returns>The track extents for that session.</returns>
/// <param name="session">Session.</param>
List<Track> GetSessionTracks(Session session);
/// <summary>Gets the disc track extents for a specified session.</summary>
/// <returns>The track extents for that session.</returns>
/// <param name="session">Session.</param>
List<Track> GetSessionTracks(ushort session);
/// <summary>Gets the disc track extents for a specified session.</summary>
/// <returns>The track extents for that session.</returns>
/// <param name="session">Session.</param>
List<Track> GetSessionTracks(ushort session);
/// <summary>Verifies several sectors, relative to track.</summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="failingLbas">List of incorrect sectors</param>
/// <param name="unknownLbas">List of uncheckable sectors</param>
bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas);
}
/// <summary>Verifies several sectors, relative to track.</summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (relative LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="track">Track.</param>
/// <param name="failingLbas">List of incorrect sectors</param>
/// <param name="unknownLbas">List of uncheckable sectors</param>
bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List<ulong> failingLbas,
out List<ulong> unknownLbas);
}

View File

@@ -40,23 +40,22 @@
using System;
using System.Collections.Generic;
namespace Aaru.CommonTypes.Interfaces
{
/// <summary>Abstract class to implement partitioning schemes interpreting plugins.</summary>
public interface IPartition
{
/// <summary>Plugin name.</summary>
string Name { get; }
/// <summary>Plugin UUID.</summary>
Guid Id { get; }
/// <summary>Plugin author</summary>
string Author { get; }
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Interprets a partitioning scheme.</summary>
/// <returns><c>true</c>, if partitioning scheme is recognized, <c>false</c> otherwise.</returns>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partitions">Returns list of partitions.</param>
/// <param name="sectorOffset">At which sector to start searching for the partition scheme.</param>
bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset);
}
/// <summary>Abstract class to implement partitioning schemes interpreting plugins.</summary>
public interface IPartition
{
/// <summary>Plugin name.</summary>
string Name { get; }
/// <summary>Plugin UUID.</summary>
Guid Id { get; }
/// <summary>Plugin author</summary>
string Author { get; }
/// <summary>Interprets a partitioning scheme.</summary>
/// <returns><c>true</c>, if partitioning scheme is recognized, <c>false</c> otherwise.</returns>
/// <param name="imagePlugin">Disk image.</param>
/// <param name="partitions">Returns list of partitions.</param>
/// <param name="sectorOffset">At which sector to start searching for the partition scheme.</param>
bool GetInformation(IMediaImage imagePlugin, out List<Partition> partitions, ulong sectorOffset);
}

View File

@@ -39,16 +39,15 @@
using System.Collections.Generic;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Defines an image that can contain partitions</summary>
public interface IPartitionableMediaImage
{
/// <summary>Defines an image that can contain partitions</summary>
public interface IPartitionableMediaImage
{
/// <summary>
/// Gets an array partitions. Typically only useful for optical disc images where each track and index means a
/// different partition, as reads can be relative to them.
/// </summary>
/// <value>The partitions.</value>
List<Partition> Partitions { get; }
}
/// <summary>
/// Gets an array partitions. Typically only useful for optical disc images where each track and index means a
/// different partition, as reads can be relative to them.
/// </summary>
/// <value>The partitions.</value>
List<Partition> Partitions { get; }
}

View File

@@ -43,83 +43,82 @@ using System.Text;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <inheritdoc />
/// <summary>Defines the interface to implement reading the contents of a filesystem</summary>
public interface IReadOnlyFilesystem : IFilesystem
{
/// <inheritdoc />
/// <summary>Defines the interface to implement reading the contents of a filesystem</summary>
public interface IReadOnlyFilesystem : IFilesystem
{
/// <summary>Retrieves a list of options supported by the filesystem, with name, type and description</summary>
IEnumerable<(string name, Type type, string description)> SupportedOptions { get; }
/// <summary>Retrieves a list of options supported by the filesystem, with name, type and description</summary>
IEnumerable<(string name, Type type, string description)> SupportedOptions { get; }
/// <summary>Supported namespaces</summary>
Dictionary<string, string> Namespaces { get; }
/// <summary>Supported namespaces</summary>
Dictionary<string, string> Namespaces { get; }
/// <summary>
/// Initializes whatever internal structures the filesystem plugin needs to be able to read files and directories
/// from the filesystem.
/// </summary>
/// <param name="imagePlugin"></param>
/// <param name="partition"></param>
/// <param name="encoding">Which encoding to use for this filesystem.</param>
/// <param name="options">Dictionary of key=value pairs containing options to pass to the filesystem</param>
/// <param name="namespace">Filename namespace</param>
ErrorNumber Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
Dictionary<string, string> options, string @namespace);
/// <summary>
/// Initializes whatever internal structures the filesystem plugin needs to be able to read files and directories
/// from the filesystem.
/// </summary>
/// <param name="imagePlugin"></param>
/// <param name="partition"></param>
/// <param name="encoding">Which encoding to use for this filesystem.</param>
/// <param name="options">Dictionary of key=value pairs containing options to pass to the filesystem</param>
/// <param name="namespace">Filename namespace</param>
ErrorNumber Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding,
Dictionary<string, string> options, string @namespace);
/// <summary>Frees all internal structures created by <see cref="Mount" /></summary>
ErrorNumber Unmount();
/// <summary>Frees all internal structures created by <see cref="Mount" /></summary>
ErrorNumber Unmount();
/// <summary>Maps a filesystem block from a file to a block from the underlying device.</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="fileBlock">File block.</param>
/// <param name="deviceBlock">Device block.</param>
ErrorNumber MapBlock(string path, long fileBlock, out long deviceBlock);
/// <summary>Maps a filesystem block from a file to a block from the underlying device.</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="fileBlock">File block.</param>
/// <param name="deviceBlock">Device block.</param>
ErrorNumber MapBlock(string path, long fileBlock, out long deviceBlock);
/// <summary>Gets the attributes of a file or directory</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="attributes">File attributes.</param>
ErrorNumber GetAttributes(string path, out FileAttributes attributes);
/// <summary>Gets the attributes of a file or directory</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="attributes">File attributes.</param>
ErrorNumber GetAttributes(string path, out FileAttributes attributes);
/// <summary>Lists all extended attributes, alternate data streams and forks of the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="path">Path.</param>
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
ErrorNumber ListXAttr(string path, out List<string> xattrs);
/// <summary>Lists all extended attributes, alternate data streams and forks of the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="path">Path.</param>
/// <param name="xattrs">List of extended attributes, alternate data streams and forks.</param>
ErrorNumber ListXAttr(string path, out List<string> xattrs);
/// <summary>Reads an extended attribute, alternate data stream or fork from the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="xattr">Extended attribute, alternate data stream or fork name.</param>
/// <param name="buf">Buffer.</param>
ErrorNumber GetXattr(string path, string xattr, ref byte[] buf);
/// <summary>Reads an extended attribute, alternate data stream or fork from the given file.</summary>
/// <returns>Error number.</returns>
/// <param name="path">File path.</param>
/// <param name="xattr">Extended attribute, alternate data stream or fork name.</param>
/// <param name="buf">Buffer.</param>
ErrorNumber GetXattr(string path, string xattr, ref byte[] buf);
/// <summary>Reads data from a file (main/only data stream or data fork).</summary>
/// <param name="path">File path.</param>
/// <param name="offset">Offset.</param>
/// <param name="size">Bytes to read.</param>
/// <param name="buf">Buffer.</param>
ErrorNumber Read(string path, long offset, long size, ref byte[] buf);
/// <summary>Reads data from a file (main/only data stream or data fork).</summary>
/// <param name="path">File path.</param>
/// <param name="offset">Offset.</param>
/// <param name="size">Bytes to read.</param>
/// <param name="buf">Buffer.</param>
ErrorNumber Read(string path, long offset, long size, ref byte[] buf);
/// <summary>Lists contents from a directory.</summary>
/// <param name="path">Directory path.</param>
/// <param name="contents">Directory contents.</param>
ErrorNumber ReadDir(string path, out List<string> contents);
/// <summary>Lists contents from a directory.</summary>
/// <param name="path">Directory path.</param>
/// <param name="contents">Directory contents.</param>
ErrorNumber ReadDir(string path, out List<string> contents);
/// <summary>Gets information about the mounted volume.</summary>
/// <param name="stat">Information about the mounted volume.</param>
ErrorNumber StatFs(out FileSystemInfo stat);
/// <summary>Gets information about the mounted volume.</summary>
/// <param name="stat">Information about the mounted volume.</param>
ErrorNumber StatFs(out FileSystemInfo stat);
/// <summary>Gets information about a file or directory.</summary>
/// <param name="path">File path.</param>
/// <param name="stat">File information.</param>
ErrorNumber Stat(string path, out FileEntryInfo stat);
/// <summary>Gets information about a file or directory.</summary>
/// <param name="path">File path.</param>
/// <param name="stat">File information.</param>
ErrorNumber Stat(string path, out FileEntryInfo stat);
/// <summary>Solves a symbolic link.</summary>
/// <param name="path">Link path.</param>
/// <param name="dest">Link destination.</param>
ErrorNumber ReadLink(string path, out string dest);
}
/// <summary>Solves a symbolic link.</summary>
/// <param name="path">Link path.</param>
/// <param name="dest">Link destination.</param>
ErrorNumber ReadLink(string path, out string dest);
}

View File

@@ -40,17 +40,16 @@
using System.Collections.Generic;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <inheritdoc />
/// <summary>Defines an image that can store the information from streaming, digital, tapes</summary>
public interface ITapeImage : IMediaImage
{
/// <inheritdoc />
/// <summary>Defines an image that can store the information from streaming, digital, tapes</summary>
public interface ITapeImage : IMediaImage
{
/// <summary>Gets a list of all the files registered in the image</summary>
List<TapeFile> Files { get; }
/// <summary>Gets a list of all the partitions registered in the image</summary>
List<TapePartition> TapePartitions { get; }
/// <summary>If the media is a really a tape, as some formats can store non-tapes</summary>
bool IsTape { get; }
}
/// <summary>Gets a list of all the files registered in the image</summary>
List<TapeFile> Files { get; }
/// <summary>Gets a list of all the partitions registered in the image</summary>
List<TapePartition> TapePartitions { get; }
/// <summary>If the media is a really a tape, as some formats can store non-tapes</summary>
bool IsTape { get; }
}

View File

@@ -37,13 +37,12 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Defines an image that can verify the integrity of the image itself, but not its contents</summary>
public interface IVerifiableImage
{
/// <summary>Defines an image that can verify the integrity of the image itself, but not its contents</summary>
public interface IVerifiableImage
{
/// <summary>Verifies media image internal checksum.</summary>
/// <returns>True if correct, false if incorrect, null if there is no internal checksum available</returns>
bool? VerifyMediaImage();
}
/// <summary>Verifies media image internal checksum.</summary>
/// <returns>True if correct, false if incorrect, null if there is no internal checksum available</returns>
bool? VerifyMediaImage();
}

View File

@@ -39,22 +39,21 @@
using System.Collections.Generic;
namespace Aaru.CommonTypes.Interfaces
{
/// <summary>Defines an image that can verify the integrity of the sectors it contains</summary>
public interface IVerifiableSectorsImage
{
/// <summary>Verifies a sector.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="sectorAddress">Sector address (LBA).</param>
bool? VerifySector(ulong sectorAddress);
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Verifies several sectors.</summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="failingLbas">List of incorrect sectors</param>
/// <param name="unknownLbas">List of uncheckable sectors</param>
bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas, out List<ulong> unknownLbas);
}
/// <summary>Defines an image that can verify the integrity of the sectors it contains</summary>
public interface IVerifiableSectorsImage
{
/// <summary>Verifies a sector.</summary>
/// <returns>True if correct, false if incorrect, null if uncheckable.</returns>
/// <param name="sectorAddress">Sector address (LBA).</param>
bool? VerifySector(ulong sectorAddress);
/// <summary>Verifies several sectors.</summary>
/// <returns>True if all are correct, false if any is incorrect, null if any is uncheckable.</returns>
/// <param name="sectorAddress">Starting sector address (LBA).</param>
/// <param name="length">How many sectors to read.</param>
/// <param name="failingLbas">List of incorrect sectors</param>
/// <param name="unknownLbas">List of uncheckable sectors</param>
bool? VerifySectors(ulong sectorAddress, uint length, out List<ulong> failingLbas, out List<ulong> unknownLbas);
}

View File

@@ -39,59 +39,58 @@
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <inheritdoc cref="IWritableImage" />
/// <summary>
/// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is
/// needed because floppy formatting characteristics are not necessarily compatible with the whole LBA-oriented
/// interface defined by <see cref="T:Aaru.CommonTypes.Interfaces.IMediaImage" />. All data expected by these methods
/// is already decoded from its corresponding bitstream.
/// </summary>
public interface IWritableFloppyImage : IFloppyImage, IWritableImage
{
/// <inheritdoc cref="IWritableImage" />
/// <summary>
/// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is
/// needed because floppy formatting characteristics are not necessarily compatible with the whole LBA-oriented
/// interface defined by <see cref="T:Aaru.CommonTypes.Interfaces.IMediaImage" />. All data expected by these methods
/// is already decoded from its corresponding bitstream.
/// Indicates the image plugin the floppy physical characteristics and must be called before following methods are
/// called. Once this is called, LBA-based methods should not be used.
/// </summary>
public interface IWritableFloppyImage : IFloppyImage, IWritableImage
{
/// <summary>
/// Indicates the image plugin the floppy physical characteristics and must be called before following methods are
/// called. Once this is called, LBA-based methods should not be used.
/// </summary>
/// <param name="info">
/// Floppy info, contains information about physical characteristics of floppy, like size, bitrate,
/// track density, etc...
/// </param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetFloppyCharacteristics(FloppyInfo info);
/// <param name="info">
/// Floppy info, contains information about physical characteristics of floppy, like size, bitrate,
/// track density, etc...
/// </param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetFloppyCharacteristics(FloppyInfo info);
/// <summary>Writes a sector's user data.</summary>
/// <param name="data">
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates. If
/// <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" />, <see cref="FloppySectorStatus.Hole" />,
/// <see cref="FloppySectorStatus.NotFound" /> it will be ignored. Otherwise, whatever data should be in the sector.
/// </param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of sector.</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteSector(byte[] data, ushort track, byte head, ushort sector, FloppySectorStatus status);
/// <summary>Writes a sector's user data.</summary>
/// <param name="data">
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates. If
/// <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" />, <see cref="FloppySectorStatus.Hole" />,
/// <see cref="FloppySectorStatus.NotFound" /> it will be ignored. Otherwise, whatever data should be in the sector.
/// </param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of sector.</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteSector(byte[] data, ushort track, byte head, ushort sector, FloppySectorStatus status);
/// <summary>Writes a whole track, including all gaps, address marks, sectors data, etc.</summary>
/// <param name="data">The track data.</param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteTrack(byte[] data, ushort track, byte head);
/// <summary>Writes a whole track, including all gaps, address marks, sectors data, etc.</summary>
/// <param name="data">The track data.</param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteTrack(byte[] data, ushort track, byte head);
/// <summary>Writes a sector's data including all tags, address mark, and so, in a format dependent of represented media.</summary>
/// <param name="data">
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates. If
/// <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" />, <see cref="FloppySectorStatus.Hole" />,
/// <see cref="FloppySectorStatus.NotFound" /> it will be ignored. Otherwise, whatever data should be in the sector.
/// </param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteSectorLong(byte[] data, ushort track, byte head, ushort sector, out FloppySectorStatus status);
}
/// <summary>Writes a sector's data including all tags, address mark, and so, in a format dependent of represented media.</summary>
/// <param name="data">
/// If <see cref="status" /> is <see cref="FloppySectorStatus.Duplicated" /> one of the duplicates. If
/// <see cref="status" /> is <see cref="FloppySectorStatus.Demagnetized" />, <see cref="FloppySectorStatus.Hole" />,
/// <see cref="FloppySectorStatus.NotFound" /> it will be ignored. Otherwise, whatever data should be in the sector.
/// </param>
/// <param name="track">Physical track (position of the heads over the floppy media, 0-based).</param>
/// <param name="head">Physical head (0-based).</param>
/// <param name="sector">Logical sector ID.</param>
/// <param name="status">Status of request.</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool WriteSectorLong(byte[] data, ushort track, byte head, ushort sector, out FloppySectorStatus status);
}

View File

@@ -40,17 +40,16 @@ using System.Collections.Generic;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
{
/// <summary>Defines an image that is writable and can store an optical disc (CD, DVD, etc)</summary>
public interface IWritableOpticalImage : IWritableImage, IOpticalMediaImage
{
/// <summary>Image format capabilities</summary>
OpticalImageCapabilities OpticalCapabilities { get; }
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Sets tracks for optical media</summary>
/// <param name="tracks">List of tracks</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetTracks(List<Track> tracks);
}
/// <summary>Defines an image that is writable and can store an optical disc (CD, DVD, etc)</summary>
public interface IWritableOpticalImage : IWritableImage, IOpticalMediaImage
{
/// <summary>Image format capabilities</summary>
OpticalImageCapabilities OpticalCapabilities { get; }
/// <summary>Sets tracks for optical media</summary>
/// <param name="tracks">List of tracks</param>
/// <returns><c>true</c> if operating completed successfully, <c>false</c> otherwise</returns>
bool SetTracks(List<Track> tracks);
}

View File

@@ -39,26 +39,25 @@
using Aaru.CommonTypes.Structs;
namespace Aaru.CommonTypes.Interfaces
namespace Aaru.CommonTypes.Interfaces;
/// <summary>Defines an image that is writable and can store information about a streaming, digital, tape</summary>
public interface IWritableTapeImage : ITapeImage, IWritableImage
{
/// <summary>Defines an image that is writable and can store information about a streaming, digital, tape</summary>
public interface IWritableTapeImage : ITapeImage, IWritableImage
{
/// <summary>Registers a new file in the image</summary>
/// <param name="file">Tape file descriptor</param>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool AddFile(TapeFile file);
/// <summary>Registers a new file in the image</summary>
/// <param name="file">Tape file descriptor</param>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool AddFile(TapeFile file);
/// <summary>Registers a new partition</summary>
/// <param name="partition">Tape partition descriptor</param>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool AddPartition(TapePartition partition);
/// <summary>Registers a new partition</summary>
/// <param name="partition">Tape partition descriptor</param>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool AddPartition(TapePartition partition);
/// <summary>
/// Tells the image plugin to set the internal structures to expect a tape (e.g. unknown block count and size).
/// Must be called before <see cref="IWritableImage.Create" />
/// </summary>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool SetTape();
}
/// <summary>
/// Tells the image plugin to set the internal structures to expect a tape (e.g. unknown block count and size).
/// Must be called before <see cref="IWritableImage.Create" />
/// </summary>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
bool SetTape();
}

View File

@@ -42,349 +42,348 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Aaru.CommonTypes.Interop
namespace Aaru.CommonTypes.Interop;
/// <summary>Detects the underlying execution framework and operating system</summary>
public static class DetectOS
{
/// <summary>Detects the underlying execution framework and operating system</summary>
public static class DetectOS
/// <summary>Are we running under Mono?</summary>
public static readonly bool IsMono =
RuntimeInformation.FrameworkDescription.StartsWith("Mono", StringComparison.Ordinal);
/// <summary>Are we running under .NET Framework?</summary>
public static readonly bool IsNetFramework =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
/// <summary>Are we running under .NET Core?</summary>
public static readonly bool IsNetCore =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.Ordinal);
/// <summary>Are we running under .NET Native?</summary>
public static readonly bool IsNetNative =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.Ordinal);
/// <summary>Checks if the underlying runtime runs in 64-bit mode</summary>
public static readonly bool Is64Bit = IntPtr.Size == 8;
/// <summary>Checks if the underlying runtime runs in 32-bit mode</summary>
public static readonly bool Is32Bit = IntPtr.Size == 4;
/// <summary>Are we running under Windows?</summary>
public static bool IsWindows => GetRealPlatformID() == PlatformID.Win32NT ||
GetRealPlatformID() == PlatformID.Win32S ||
GetRealPlatformID() == PlatformID.Win32Windows ||
GetRealPlatformID() == PlatformID.WinCE ||
GetRealPlatformID() == PlatformID.WindowsPhone ||
GetRealPlatformID() == PlatformID.Xbox;
/// <summary>Are we running with administrative (root) privileges?</summary>
public static bool IsAdmin
{
/// <summary>Are we running under Mono?</summary>
public static readonly bool IsMono =
RuntimeInformation.FrameworkDescription.StartsWith("Mono", StringComparison.Ordinal);
/// <summary>Are we running under .NET Framework?</summary>
public static readonly bool IsNetFramework =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal);
/// <summary>Are we running under .NET Core?</summary>
public static readonly bool IsNetCore =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.Ordinal);
/// <summary>Are we running under .NET Native?</summary>
public static readonly bool IsNetNative =
RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.Ordinal);
/// <summary>Checks if the underlying runtime runs in 64-bit mode</summary>
public static readonly bool Is64Bit = IntPtr.Size == 8;
/// <summary>Checks if the underlying runtime runs in 32-bit mode</summary>
public static readonly bool Is32Bit = IntPtr.Size == 4;
/// <summary>Are we running under Windows?</summary>
public static bool IsWindows => GetRealPlatformID() == PlatformID.Win32NT ||
GetRealPlatformID() == PlatformID.Win32S ||
GetRealPlatformID() == PlatformID.Win32Windows ||
GetRealPlatformID() == PlatformID.WinCE ||
GetRealPlatformID() == PlatformID.WindowsPhone ||
GetRealPlatformID() == PlatformID.Xbox;
/// <summary>Are we running with administrative (root) privileges?</summary>
public static bool IsAdmin
get
{
get
if(!IsWindows)
return Environment.UserName == "root";
bool isAdmin;
WindowsIdentity user = null;
try
{
if(!IsWindows)
return Environment.UserName == "root";
bool isAdmin;
WindowsIdentity user = null;
try
{
user = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(user);
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch(UnauthorizedAccessException)
{
isAdmin = false;
}
catch(Exception)
{
isAdmin = false;
}
finally
{
user?.Dispose();
}
return isAdmin;
user = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(user);
isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
[DllImport("libc", SetLastError = true)]
static extern int uname(out utsname name);
[DllImport("libc", SetLastError = true, EntryPoint = "sysctlbyname", CharSet = CharSet.Ansi)]
static extern int OSX_sysctlbyname(string name, IntPtr oldp, IntPtr oldlenp, IntPtr newp, uint newlen);
/// <summary>Gets the real platform ID, not the incomplete .NET framework one</summary>
/// <returns>Platform ID</returns>
/// <exception cref="Exception">Unhandled exception</exception>
public static PlatformID GetRealPlatformID()
{
if((int)Environment.OSVersion.Platform < 4 ||
(int)Environment.OSVersion.Platform == 5)
return (PlatformID)(int)Environment.OSVersion.Platform;
int error = uname(out utsname unixname);
if(error != 0)
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
switch(unixname.sysname)
catch(UnauthorizedAccessException)
{
// TODO: Differentiate Linux, Android, Tizen
case "Linux":
{
#if __ANDROID__
isAdmin = false;
}
catch(Exception)
{
isAdmin = false;
}
finally
{
user?.Dispose();
}
return isAdmin;
}
}
[DllImport("libc", SetLastError = true)]
static extern int uname(out utsname name);
[DllImport("libc", SetLastError = true, EntryPoint = "sysctlbyname", CharSet = CharSet.Ansi)]
static extern int OSX_sysctlbyname(string name, IntPtr oldp, IntPtr oldlenp, IntPtr newp, uint newlen);
/// <summary>Gets the real platform ID, not the incomplete .NET framework one</summary>
/// <returns>Platform ID</returns>
/// <exception cref="Exception">Unhandled exception</exception>
public static PlatformID GetRealPlatformID()
{
if((int)Environment.OSVersion.Platform < 4 ||
(int)Environment.OSVersion.Platform == 5)
return (PlatformID)(int)Environment.OSVersion.Platform;
int error = uname(out utsname unixname);
if(error != 0)
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
switch(unixname.sysname)
{
// TODO: Differentiate Linux, Android, Tizen
case "Linux":
{
#if __ANDROID__
return PlatformID.Android;
#else
return PlatformID.Linux;
#endif
#else
return PlatformID.Linux;
#endif
}
case "Darwin":
{
IntPtr pLen = Marshal.AllocHGlobal(sizeof(int));
int osxError = OSX_sysctlbyname("hw.machine", IntPtr.Zero, pLen, IntPtr.Zero, 0);
if(osxError != 0)
{
Marshal.FreeHGlobal(pLen);
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
}
case "Darwin":
int length = Marshal.ReadInt32(pLen);
IntPtr pStr = Marshal.AllocHGlobal(length);
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
if(osxError != 0)
{
IntPtr pLen = Marshal.AllocHGlobal(sizeof(int));
int osxError = OSX_sysctlbyname("hw.machine", IntPtr.Zero, pLen, IntPtr.Zero, 0);
if(osxError != 0)
{
Marshal.FreeHGlobal(pLen);
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
}
int length = Marshal.ReadInt32(pLen);
IntPtr pStr = Marshal.AllocHGlobal(length);
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
if(osxError != 0)
{
Marshal.FreeHGlobal(pStr);
Marshal.FreeHGlobal(pLen);
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
}
string machine = Marshal.PtrToStringAnsi(pStr);
Marshal.FreeHGlobal(pStr);
Marshal.FreeHGlobal(pLen);
if(machine != null &&
(machine.StartsWith("iPad", StringComparison.Ordinal) ||
machine.StartsWith("iPod", StringComparison.Ordinal) ||
machine.StartsWith("iPhone", StringComparison.Ordinal)))
return PlatformID.iOS;
return PlatformID.MacOSX;
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
}
case "GNU": return PlatformID.Hurd;
case "FreeBSD":
case "GNU/kFreeBSD": return PlatformID.FreeBSD;
case "DragonFly": return PlatformID.DragonFly;
case "Haiku": return PlatformID.Haiku;
case "HP-UX": return PlatformID.HPUX;
case "AIX": return PlatformID.AIX;
case "OS400": return PlatformID.OS400;
case "IRIX":
case "IRIX64": return PlatformID.IRIX;
case "Minix": return PlatformID.Minix;
case "NetBSD": return PlatformID.NetBSD;
case "NONSTOP_KERNEL": return PlatformID.NonStop;
case "OpenBSD": return PlatformID.OpenBSD;
case "QNX": return PlatformID.QNX;
case "SINIX-Y": return PlatformID.SINIX;
case "SunOS": return PlatformID.Solaris;
case "OSF1": return PlatformID.Tru64;
case "ULTRIX": return PlatformID.Ultrix;
case "SCO_SV": return PlatformID.OpenServer;
case "UnixWare": return PlatformID.UnixWare;
case "Interix":
case "UWIN-W7": return PlatformID.Win32NT;
default:
{
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal))
return PlatformID.Win32NT;
string machine = Marshal.PtrToStringAnsi(pStr);
return PlatformID.Unknown;
}
Marshal.FreeHGlobal(pStr);
Marshal.FreeHGlobal(pLen);
if(machine != null &&
(machine.StartsWith("iPad", StringComparison.Ordinal) ||
machine.StartsWith("iPod", StringComparison.Ordinal) ||
machine.StartsWith("iPhone", StringComparison.Ordinal)))
return PlatformID.iOS;
return PlatformID.MacOSX;
}
}
/// <summary>Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)</summary>
/// <returns>Current operating system version</returns>
public static string GetVersion()
{
string environ = Environment.OSVersion.Version.ToString();
switch(GetRealPlatformID())
case "GNU": return PlatformID.Hurd;
case "FreeBSD":
case "GNU/kFreeBSD": return PlatformID.FreeBSD;
case "DragonFly": return PlatformID.DragonFly;
case "Haiku": return PlatformID.Haiku;
case "HP-UX": return PlatformID.HPUX;
case "AIX": return PlatformID.AIX;
case "OS400": return PlatformID.OS400;
case "IRIX":
case "IRIX64": return PlatformID.IRIX;
case "Minix": return PlatformID.Minix;
case "NetBSD": return PlatformID.NetBSD;
case "NONSTOP_KERNEL": return PlatformID.NonStop;
case "OpenBSD": return PlatformID.OpenBSD;
case "QNX": return PlatformID.QNX;
case "SINIX-Y": return PlatformID.SINIX;
case "SunOS": return PlatformID.Solaris;
case "OSF1": return PlatformID.Tru64;
case "ULTRIX": return PlatformID.Ultrix;
case "SCO_SV": return PlatformID.OpenServer;
case "UnixWare": return PlatformID.UnixWare;
case "Interix":
case "UWIN-W7": return PlatformID.Win32NT;
default:
{
case PlatformID.MacOSX:
if(Environment.OSVersion.Version.Major != 1)
return $"10.{Environment.OSVersion.Version.Major - 4}.{Environment.OSVersion.Version.Minor}";
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal))
return PlatformID.Win32NT;
switch(Environment.OSVersion.Version.Minor)
{
case 3: return "10.0";
case 4: return "10.1";
}
goto default;
case PlatformID.Win32NT:
// From Windows 8.1 the reported version is simply falsified...
if((Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2) ||
Environment.OSVersion.Version.Major > 6)
return FileVersionInfo.
GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
"KERNEL32.DLL")).ProductVersion;
return environ;
default: return environ;
return PlatformID.Unknown;
}
}
/// <summary>From a platform ID and version returns a human-readable version</summary>
/// <param name="id">Platform ID</param>
/// <param name="version">Version number</param>
/// <returns>Operating system name</returns>
public static string GetPlatformName(PlatformID id, string version = null)
{
switch(id)
{
case PlatformID.AIX: return "AIX";
case PlatformID.Android: return "Android";
case PlatformID.DragonFly: return "DragonFly BSD";
case PlatformID.FreeBSD: return "FreeBSD";
case PlatformID.Haiku: return "Haiku";
case PlatformID.HPUX: return "HP/UX";
case PlatformID.Hurd: return "Hurd";
case PlatformID.iOS: return "iOS";
case PlatformID.IRIX: return "IRIX";
case PlatformID.Linux:
if(!File.Exists("/proc/version"))
return "Linux";
string s = File.ReadAllText("/proc/version");
return s.Contains("Microsoft") || s.Contains("WSL") ? "Windows Subsystem for Linux" : "Linux";
case PlatformID.MacOSX:
if(string.IsNullOrEmpty(version))
return "macOS";
string[] pieces = version.Split('.');
if(pieces.Length < 2 ||
!int.TryParse(pieces[1], out int minor))
return "macOS";
if(minor >= 12)
return "macOS";
if(minor >= 8)
return "OS X";
return "Mac OS X";
case PlatformID.Minix: return "MINIX";
case PlatformID.NetBSD: return "NetBSD";
case PlatformID.NonStop: return "NonStop OS";
case PlatformID.OpenBSD: return "OpenBSD";
case PlatformID.OpenServer: return "SCO OpenServer";
case PlatformID.OS400: return "OS/400";
case PlatformID.PlayStation3: return "Sony CellOS";
case PlatformID.PlayStation4: return "Sony Orbis OS";
case PlatformID.QNX: return "QNX";
case PlatformID.SINIX: return "SINIX";
case PlatformID.Solaris: return "Sun Solaris";
case PlatformID.Tizen: return "Samsung Tizen";
case PlatformID.Tru64: return "Tru64 UNIX";
case PlatformID.Ultrix: return "Ultrix";
case PlatformID.Unix: return "UNIX";
case PlatformID.UnixWare: return "SCO UnixWare";
case PlatformID.Wii: return "Nintendo Wii";
case PlatformID.WiiU: return "Nintendo Wii U";
case PlatformID.Win32NT:
if(string.IsNullOrEmpty(version))
return "Windows NT/2000/XP/Vista/7/10";
if(version.StartsWith("3.", StringComparison.Ordinal) ||
version.StartsWith("4.", StringComparison.Ordinal))
return "Windows NT";
if(version.StartsWith("5.0", StringComparison.Ordinal))
return "Windows 2000";
if(version.StartsWith("5.1", StringComparison.Ordinal))
return "Windows XP";
if(version.StartsWith("5.2", StringComparison.Ordinal))
return "Windows 2003";
if(version.StartsWith("6.0", StringComparison.Ordinal))
return "Windows Vista";
if(version.StartsWith("6.1", StringComparison.Ordinal))
return "Windows 7";
if(version.StartsWith("6.2", StringComparison.Ordinal))
return "Windows 8";
if(version.StartsWith("6.3", StringComparison.Ordinal))
return "Windows 8.1";
if(version.StartsWith("10.0", StringComparison.Ordinal))
return "Windows 10";
return "Windows NT/2000/XP/Vista/7/10";
case PlatformID.Win32S: return "Windows 3.x with win32s";
case PlatformID.Win32Windows:
if(string.IsNullOrEmpty(version))
return "Windows 9x/Me";
if(version.StartsWith("4.0", StringComparison.Ordinal))
return "Windows 95";
if(version.StartsWith("4.10.2222", StringComparison.Ordinal))
return "Windows 98 SE";
if(version.StartsWith("4.1", StringComparison.Ordinal))
return "Windows 98";
if(version.StartsWith("4.9", StringComparison.Ordinal))
return "Windows Me";
return "Windows 9x/Me";
case PlatformID.WinCE: return "Windows CE/Mobile";
case PlatformID.WindowsPhone: return "Windows Phone";
case PlatformID.Xbox: return "Xbox OS";
case PlatformID.zOS: return "z/OS";
default: return id.ToString();
}
}
/// <summary>POSIX uname structure, size from OSX, big enough to handle extra fields</summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct utsname
{
/// <summary>System name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string sysname;
/// <summary>Node name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string nodename;
/// <summary>Release level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string release;
/// <summary>Version level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string version;
/// <summary>Hardware level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string machine;
}
}
/// <summary>Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)</summary>
/// <returns>Current operating system version</returns>
public static string GetVersion()
{
string environ = Environment.OSVersion.Version.ToString();
switch(GetRealPlatformID())
{
case PlatformID.MacOSX:
if(Environment.OSVersion.Version.Major != 1)
return $"10.{Environment.OSVersion.Version.Major - 4}.{Environment.OSVersion.Version.Minor}";
switch(Environment.OSVersion.Version.Minor)
{
case 3: return "10.0";
case 4: return "10.1";
}
goto default;
case PlatformID.Win32NT:
// From Windows 8.1 the reported version is simply falsified...
if((Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2) ||
Environment.OSVersion.Version.Major > 6)
return FileVersionInfo.
GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
"KERNEL32.DLL")).ProductVersion;
return environ;
default: return environ;
}
}
/// <summary>From a platform ID and version returns a human-readable version</summary>
/// <param name="id">Platform ID</param>
/// <param name="version">Version number</param>
/// <returns>Operating system name</returns>
public static string GetPlatformName(PlatformID id, string version = null)
{
switch(id)
{
case PlatformID.AIX: return "AIX";
case PlatformID.Android: return "Android";
case PlatformID.DragonFly: return "DragonFly BSD";
case PlatformID.FreeBSD: return "FreeBSD";
case PlatformID.Haiku: return "Haiku";
case PlatformID.HPUX: return "HP/UX";
case PlatformID.Hurd: return "Hurd";
case PlatformID.iOS: return "iOS";
case PlatformID.IRIX: return "IRIX";
case PlatformID.Linux:
if(!File.Exists("/proc/version"))
return "Linux";
string s = File.ReadAllText("/proc/version");
return s.Contains("Microsoft") || s.Contains("WSL") ? "Windows Subsystem for Linux" : "Linux";
case PlatformID.MacOSX:
if(string.IsNullOrEmpty(version))
return "macOS";
string[] pieces = version.Split('.');
if(pieces.Length < 2 ||
!int.TryParse(pieces[1], out int minor))
return "macOS";
if(minor >= 12)
return "macOS";
if(minor >= 8)
return "OS X";
return "Mac OS X";
case PlatformID.Minix: return "MINIX";
case PlatformID.NetBSD: return "NetBSD";
case PlatformID.NonStop: return "NonStop OS";
case PlatformID.OpenBSD: return "OpenBSD";
case PlatformID.OpenServer: return "SCO OpenServer";
case PlatformID.OS400: return "OS/400";
case PlatformID.PlayStation3: return "Sony CellOS";
case PlatformID.PlayStation4: return "Sony Orbis OS";
case PlatformID.QNX: return "QNX";
case PlatformID.SINIX: return "SINIX";
case PlatformID.Solaris: return "Sun Solaris";
case PlatformID.Tizen: return "Samsung Tizen";
case PlatformID.Tru64: return "Tru64 UNIX";
case PlatformID.Ultrix: return "Ultrix";
case PlatformID.Unix: return "UNIX";
case PlatformID.UnixWare: return "SCO UnixWare";
case PlatformID.Wii: return "Nintendo Wii";
case PlatformID.WiiU: return "Nintendo Wii U";
case PlatformID.Win32NT:
if(string.IsNullOrEmpty(version))
return "Windows NT/2000/XP/Vista/7/10";
if(version.StartsWith("3.", StringComparison.Ordinal) ||
version.StartsWith("4.", StringComparison.Ordinal))
return "Windows NT";
if(version.StartsWith("5.0", StringComparison.Ordinal))
return "Windows 2000";
if(version.StartsWith("5.1", StringComparison.Ordinal))
return "Windows XP";
if(version.StartsWith("5.2", StringComparison.Ordinal))
return "Windows 2003";
if(version.StartsWith("6.0", StringComparison.Ordinal))
return "Windows Vista";
if(version.StartsWith("6.1", StringComparison.Ordinal))
return "Windows 7";
if(version.StartsWith("6.2", StringComparison.Ordinal))
return "Windows 8";
if(version.StartsWith("6.3", StringComparison.Ordinal))
return "Windows 8.1";
if(version.StartsWith("10.0", StringComparison.Ordinal))
return "Windows 10";
return "Windows NT/2000/XP/Vista/7/10";
case PlatformID.Win32S: return "Windows 3.x with win32s";
case PlatformID.Win32Windows:
if(string.IsNullOrEmpty(version))
return "Windows 9x/Me";
if(version.StartsWith("4.0", StringComparison.Ordinal))
return "Windows 95";
if(version.StartsWith("4.10.2222", StringComparison.Ordinal))
return "Windows 98 SE";
if(version.StartsWith("4.1", StringComparison.Ordinal))
return "Windows 98";
if(version.StartsWith("4.9", StringComparison.Ordinal))
return "Windows Me";
return "Windows 9x/Me";
case PlatformID.WinCE: return "Windows CE/Mobile";
case PlatformID.WindowsPhone: return "Windows Phone";
case PlatformID.Xbox: return "Xbox OS";
case PlatformID.zOS: return "z/OS";
default: return id.ToString();
}
}
/// <summary>POSIX uname structure, size from OSX, big enough to handle extra fields</summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct utsname
{
/// <summary>System name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string sysname;
/// <summary>Node name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string nodename;
/// <summary>Release level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string release;
/// <summary>Version level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string version;
/// <summary>Hardware level</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public readonly string machine;
}
}

View File

@@ -38,85 +38,84 @@
using System.Diagnostics.CodeAnalysis;
namespace Aaru.CommonTypes.Interop
namespace Aaru.CommonTypes.Interop;
/// <summary>Contains an arbitrary list of OSes, even if .NET does not run on them</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PlatformID
{
/// <summary>Contains an arbitrary list of OSes, even if .NET does not run on them</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PlatformID
{
/// <summary>Win32s</summary>
Win32S = 0,
/// <summary>Win32 (Windows 9x)</summary>
Win32Windows = 1,
/// <summary>Windows NT</summary>
Win32NT = 2,
/// <summary>Windows Mobile</summary>
WinCE = 3,
/// <summary>UNIX (do not use, too generic)</summary>
Unix = 4,
/// <summary>Xbox 360</summary>
Xbox = 5,
/// <summary>OS X</summary>
MacOSX = 6,
/// <summary>iOS is not OS X</summary>
iOS = 7,
/// <summary>Linux</summary>
Linux = 8,
/// <summary>Sun Solaris</summary>
Solaris = 9,
/// <summary>NetBSD</summary>
NetBSD = 10,
/// <summary>OpenBSD</summary>
OpenBSD = 11,
/// <summary>FreeBSD</summary>
FreeBSD = 12,
/// <summary>DragonFly BSD</summary>
DragonFly = 13,
/// <summary>Nintendo Wii</summary>
Wii = 14,
/// <summary>Nintendo Wii U</summary>
WiiU = 15,
/// <summary>Sony PlayStation 3</summary>
PlayStation3 = 16,
/// <summary>Sony Playstation 4</summary>
PlayStation4 = 17,
/// <summary>Google Android</summary>
Android = 18,
/// <summary>Samsung Tizen</summary>
Tizen = 19,
/// <summary>Windows Phone</summary>
WindowsPhone = 20,
/// <summary>GNU/Hurd</summary>
Hurd = 21,
/// <summary>Haiku</summary>
Haiku = 22,
/// <summary>HP-UX</summary>
HPUX = 23,
/// <summary>AIX</summary>
AIX = 24,
/// <summary>OS/400</summary>
OS400 = 25,
/// <summary>IRIX</summary>
IRIX = 26,
/// <summary>Minix</summary>
Minix = 27,
/// <summary>NonStop</summary>
NonStop = 28,
/// <summary>QNX</summary>
QNX = 29,
/// <summary>SINIX</summary>
SINIX = 30,
/// <summary>Tru64 UNIX</summary>
Tru64 = 31,
/// <summary>Ultrix</summary>
Ultrix = 32,
/// <summary>SCO OpenServer / SCO UNIX</summary>
OpenServer = 33,
/// <summary>SCO UnixWare</summary>
UnixWare = 34,
/// <summary>IBM z/OS</summary>
zOS = 35,
/// <summary>Unknown</summary>
Unknown = -1
}
/// <summary>Win32s</summary>
Win32S = 0,
/// <summary>Win32 (Windows 9x)</summary>
Win32Windows = 1,
/// <summary>Windows NT</summary>
Win32NT = 2,
/// <summary>Windows Mobile</summary>
WinCE = 3,
/// <summary>UNIX (do not use, too generic)</summary>
Unix = 4,
/// <summary>Xbox 360</summary>
Xbox = 5,
/// <summary>OS X</summary>
MacOSX = 6,
/// <summary>iOS is not OS X</summary>
iOS = 7,
/// <summary>Linux</summary>
Linux = 8,
/// <summary>Sun Solaris</summary>
Solaris = 9,
/// <summary>NetBSD</summary>
NetBSD = 10,
/// <summary>OpenBSD</summary>
OpenBSD = 11,
/// <summary>FreeBSD</summary>
FreeBSD = 12,
/// <summary>DragonFly BSD</summary>
DragonFly = 13,
/// <summary>Nintendo Wii</summary>
Wii = 14,
/// <summary>Nintendo Wii U</summary>
WiiU = 15,
/// <summary>Sony PlayStation 3</summary>
PlayStation3 = 16,
/// <summary>Sony Playstation 4</summary>
PlayStation4 = 17,
/// <summary>Google Android</summary>
Android = 18,
/// <summary>Samsung Tizen</summary>
Tizen = 19,
/// <summary>Windows Phone</summary>
WindowsPhone = 20,
/// <summary>GNU/Hurd</summary>
Hurd = 21,
/// <summary>Haiku</summary>
Haiku = 22,
/// <summary>HP-UX</summary>
HPUX = 23,
/// <summary>AIX</summary>
AIX = 24,
/// <summary>OS/400</summary>
OS400 = 25,
/// <summary>IRIX</summary>
IRIX = 26,
/// <summary>Minix</summary>
Minix = 27,
/// <summary>NonStop</summary>
NonStop = 28,
/// <summary>QNX</summary>
QNX = 29,
/// <summary>SINIX</summary>
SINIX = 30,
/// <summary>Tru64 UNIX</summary>
Tru64 = 31,
/// <summary>Ultrix</summary>
Ultrix = 32,
/// <summary>SCO OpenServer / SCO UNIX</summary>
OpenServer = 33,
/// <summary>SCO UnixWare</summary>
UnixWare = 34,
/// <summary>IBM z/OS</summary>
zOS = 35,
/// <summary>Unknown</summary>
Unknown = -1
}

View File

@@ -40,52 +40,51 @@ using System;
using System.Reflection;
using System.Runtime;
namespace Aaru.CommonTypes.Interop
namespace Aaru.CommonTypes.Interop;
/// <summary>Gets our own, or the runtime's version</summary>
public static class Version
{
/// <summary>Gets our own, or the runtime's version</summary>
public static class Version
/// <summary>Gets version string</summary>
/// <returns>Version</returns>
public static string GetVersion() => typeof(Version).Assembly.GetName().Version?.ToString();
/// <summary>Gets .NET Core version</summary>
/// <returns>Version</returns>
public static string GetNetCoreVersion()
{
/// <summary>Gets version string</summary>
/// <returns>Version</returns>
public static string GetVersion() => typeof(Version).Assembly.GetName().Version?.ToString();
Assembly assembly = typeof(GCSettings).Assembly;
/// <summary>Gets .NET Core version</summary>
/// <returns>Version</returns>
public static string GetNetCoreVersion()
string[] assemblyPath = assembly.CodeBase?.Split(new[]
{
Assembly assembly = typeof(GCSettings).Assembly;
string[] assemblyPath = assembly.CodeBase?.Split(new[]
{
'/', '\\'
}, StringSplitOptions.RemoveEmptyEntries);
if(assemblyPath is null)
return null;
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if(netCoreAppIndex > 0 &&
netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];
'/', '\\'
}, StringSplitOptions.RemoveEmptyEntries);
if(assemblyPath is null)
return null;
}
/// <summary>Gets Mono version</summary>
/// <returns>Version</returns>
public static string GetMonoVersion()
{
if(!DetectOS.IsMono)
return null;
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")?.
GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if(netCoreAppIndex > 0 &&
netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];
if(monoDisplayName != null)
return (string)monoDisplayName.Invoke(null, null);
return null;
}
/// <summary>Gets Mono version</summary>
/// <returns>Version</returns>
public static string GetMonoVersion()
{
if(!DetectOS.IsMono)
return null;
}
MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")?.
GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if(monoDisplayName != null)
return (string)monoDisplayName.Invoke(null, null);
return null;
}
}

View File

@@ -34,40 +34,39 @@
using Aaru.Console;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
public static partial class MediaTypeFromDevice
{
public static partial class MediaTypeFromDevice
/// <summary>Gets the media type from an ATA (not ATAPI) device</summary>
/// <param name="manufacturer">Manufacturer string</param>
/// <param name="model">Model string</param>
/// <param name="removable">Is the device removable?</param>
/// <param name="compactFlash">Does the device self-identify as CompactFlash?</param>
/// <param name="pcmcia">Is the device attached thru PCMCIA or CardBus?</param>
/// <param name="blocks">Number of blocks in device</param>
/// <returns>The media type</returns>
public static MediaType GetFromAta(string manufacturer, string model, bool removable, bool compactFlash,
bool pcmcia, ulong blocks)
{
/// <summary>Gets the media type from an ATA (not ATAPI) device</summary>
/// <param name="manufacturer">Manufacturer string</param>
/// <param name="model">Model string</param>
/// <param name="removable">Is the device removable?</param>
/// <param name="compactFlash">Does the device self-identify as CompactFlash?</param>
/// <param name="pcmcia">Is the device attached thru PCMCIA or CardBus?</param>
/// <param name="blocks">Number of blocks in device</param>
/// <returns>The media type</returns>
public static MediaType GetFromAta(string manufacturer, string model, bool removable, bool compactFlash,
bool pcmcia, ulong blocks)
if(!removable)
{
if(!removable)
{
if(compactFlash)
return MediaType.CompactFlash;
if(compactFlash)
return MediaType.CompactFlash;
return pcmcia ? MediaType.PCCardTypeI : MediaType.GENERIC_HDD;
}
if(manufacturer.ToLowerInvariant() == "syquest" &&
model.ToLowerInvariant() == "sparq" &&
blocks == 1961069)
{
AaruConsole.DebugWriteLine("Media detection",
"Drive manufacturer is SyQuest, media has 1961069 blocks of 512 bytes, setting media type to SparQ.");
return MediaType.SparQ;
}
return MediaType.Unknown;
return pcmcia ? MediaType.PCCardTypeI : MediaType.GENERIC_HDD;
}
if(manufacturer.ToLowerInvariant() == "syquest" &&
model.ToLowerInvariant() == "sparq" &&
blocks == 1961069)
{
AaruConsole.DebugWriteLine("Media detection",
"Drive manufacturer is SyQuest, media has 1961069 blocks of 512 bytes, setting media type to SparQ.");
return MediaType.SparQ;
}
return MediaType.Unknown;
}
}

View File

@@ -35,145 +35,144 @@
using System;
using Aaru.Console;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
/// <summary>Gets the media type from a real device</summary>
public static partial class MediaTypeFromDevice
{
/// <summary>Gets the media type from a real device</summary>
public static partial class MediaTypeFromDevice
/// <summary>Gets the media type from an SCSI MultiMedia Commands compliant device</summary>
/// <param name="model">Model string</param>
/// <param name="mediumType">Medium type from MODE SENSE</param>
/// <param name="densityCode">Density code from MODE SENSE</param>
/// <param name="blocks">Number of blocks in media</param>
/// <param name="blockSize">Size of a block in bytes</param>
/// <param name="isUsb">Is the device USB attached</param>
/// <param name="opticalDisc">Is the media an optical disc</param>
/// <returns>Media type</returns>
static MediaType GetFromMmc(string model, byte mediumType, byte densityCode, ulong blocks, uint blockSize,
bool isUsb, bool opticalDisc)
{
/// <summary>Gets the media type from an SCSI MultiMedia Commands compliant device</summary>
/// <param name="model">Model string</param>
/// <param name="mediumType">Medium type from MODE SENSE</param>
/// <param name="densityCode">Density code from MODE SENSE</param>
/// <param name="blocks">Number of blocks in media</param>
/// <param name="blockSize">Size of a block in bytes</param>
/// <param name="isUsb">Is the device USB attached</param>
/// <param name="opticalDisc">Is the media an optical disc</param>
/// <returns>Media type</returns>
static MediaType GetFromMmc(string model, byte mediumType, byte densityCode, ulong blocks, uint blockSize,
bool isUsb, bool opticalDisc)
switch(mediumType)
{
switch(mediumType)
{
case 0x00:
if(blockSize == 512)
if(blocks == 1281856)
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.",
mediumType, blocks, blockSize);
case 0x00:
if(blockSize == 512)
if(blocks == 1281856)
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650_WORM;
}
else
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650;
}
return MediaType.PD650_WORM;
}
else
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to Compact Disc.",
mediumType);
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.",
mediumType, blocks, blockSize);
return MediaType.CD;
return MediaType.PD650;
}
case 0x01:
case 0x05:
else
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-ROM.",
"SCSI medium type is {0:X2}h, setting media type to Compact Disc.",
mediumType);
return MediaType.CDROM;
case 0x02:
case 0x06:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to Compact Disc Digital Audio.",
mediumType);
return MediaType.CD;
}
case 0x01:
case 0x05:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-ROM.",
mediumType);
return MediaType.CDDA;
case 0x03:
case 0x07:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD+.", mediumType);
return MediaType.CDROM;
case 0x02:
case 0x06:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to Compact Disc Digital Audio.",
mediumType);
return MediaType.CDPLUS;
case 0x04:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to Photo CD.",
mediumType);
return MediaType.CDDA;
case 0x03:
case 0x07:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD+.", mediumType);
return MediaType.PCD;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-R.", mediumType);
return MediaType.CDPLUS;
case 0x04:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to Photo CD.",
mediumType);
return MediaType.CDR;
case 0x20:
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-RW.", mediumType);
return MediaType.PCD;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-R.", mediumType);
return MediaType.CDRW;
case 0x40 when isUsb && !opticalDisc:
case 0x41 when isUsb && !opticalDisc:
case 0x42 when isUsb && !opticalDisc:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h and device is USB, setting media type to Flash Drive.",
mediumType);
return MediaType.CDR;
case 0x20:
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to CD-RW.", mediumType);
return MediaType.FlashDrive;
case 0x80:
if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal))
switch(densityCode)
{
case 0x42:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.CDRW;
case 0x40 when isUsb && !opticalDisc:
case 0x41 when isUsb && !opticalDisc:
case 0x42 when isUsb && !opticalDisc:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h and device is USB, setting media type to Flash Drive.",
mediumType);
return MediaType.LTO2;
case 0x44:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.FlashDrive;
case 0x80:
if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal))
switch(densityCode)
{
case 0x42:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.LTO3;
case 0x46:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.LTO2;
case 0x44:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.LTO4;
case 0x58:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.LTO3;
case 0x46:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
return MediaType.LTO5;
}
return MediaType.LTO4;
case 0x58:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.",
mediumType, densityCode);
break;
}
return MediaType.LTO5;
}
return MediaType.Unknown;
break;
}
return MediaType.Unknown;
}
}

View File

@@ -34,309 +34,308 @@
using Aaru.Console;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
public static partial class MediaTypeFromDevice
{
public static partial class MediaTypeFromDevice
/// <summary>Gets the device type from a SCSI Optical Device</summary>
/// <param name="mediumType">Medium type from MODE SENSE</param>
/// <param name="blocks">Number of blocks in device</param>
/// <param name="blockSize">Size in bytes of a block</param>
/// <returns>Media type</returns>
static MediaType GetFromOdc(byte mediumType, ulong blocks, uint blockSize)
{
/// <summary>Gets the device type from a SCSI Optical Device</summary>
/// <param name="mediumType">Medium type from MODE SENSE</param>
/// <param name="blocks">Number of blocks in device</param>
/// <param name="blockSize">Size in bytes of a block</param>
/// <returns>Media type</returns>
static MediaType GetFromOdc(byte mediumType, ulong blocks, uint blockSize)
if(mediumType != 0x01 &&
mediumType != 0x02 &&
mediumType != 0x03 &&
mediumType != 0x05 &&
mediumType != 0x07)
{
if(mediumType != 0x01 &&
mediumType != 0x02 &&
mediumType != 0x03 &&
mediumType != 0x05 &&
mediumType != 0x07)
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to unknown magneto-optical.",
mediumType);
return MediaType.UnknownMO;
}
switch(blockSize)
{
case 512:
{
switch(blocks)
{
case 248826:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-154 / ISO 10090 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_154;
case 429975:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" embossed magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_201_ROM;
case 446325:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_201;
case 694929:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_223_512;
case 904995:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-183 / ISO 13481 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_183_512;
case 1041500:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15041 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15041_512;
case 1128772:
case 1163337:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_184_512;
case 1281856:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650_WORM;
case 1298496:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650;
case 1644581:
case 1647371:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_195_512;
case 2244958:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_14517_512;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 1024:
{
switch(blocks)
{
case 314569:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 10089 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_10089;
case 371371:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_223;
case 498526:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_183;
case 603466:
case 637041:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_184;
case 936921:
case 948770:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_195;
case 1244621:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-238 / ISO 15486 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_238;
case 1273011:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_14517;
case 2319786:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15286_1024;
case 4383356:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322_1k;
case 14476734:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_260;
case 24445990:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_260_Double;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 2048:
{
switch(blocks)
{
case 310352: // Found in real media
case 318988:
case 320332:
case 321100:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-239 / ISO 15498 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_239;
case 605846:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.GigaMo;
case 1063146:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 2 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.GigaMo2;
case 1128134:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-280 / ISO 18093 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_280;
case 1263472:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15286;
case 2043664:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322_2k;
case 7355716:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-317 / ISO 20162 conforming 300mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_317;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 4096:
{
switch(blocks)
{
case 1095840:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 8192:
{
switch(blocks)
{
case 1834348:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO.",
mediumType, blocks, blockSize);
return MediaType.UDO;
case 3668759:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM UDO2.",
mediumType, blocks, blockSize);
return MediaType.UDO2_WORM;
case 3669724:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO2.",
mediumType, blocks, blockSize);
return MediaType.UDO2;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, setting media type to unknown magneto-optical.",
mediumType);
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
switch(blockSize)
{
case 512:
{
switch(blocks)
{
case 248826:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-154 / ISO 10090 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_154;
case 429975:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" embossed magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_201_ROM;
case 446325:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_201;
case 694929:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_223_512;
case 904995:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-183 / ISO 13481 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_183_512;
case 1041500:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15041 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15041_512;
case 1128772:
case 1163337:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_184_512;
case 1281856:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650_WORM;
case 1298496:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.",
mediumType, blocks, blockSize);
return MediaType.PD650;
case 1644581:
case 1647371:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_195_512;
case 2244958:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_14517_512;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 1024:
{
switch(blocks)
{
case 314569:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 10089 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_10089;
case 371371:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_223;
case 498526:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_183;
case 603466:
case 637041:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_184;
case 936921:
case 948770:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_195;
case 1244621:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-238 / ISO 15486 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_238;
case 1273011:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_14517;
case 2319786:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15286_1024;
case 4383356:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322_1k;
case 14476734:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_260;
case 24445990:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_260_Double;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 2048:
{
switch(blocks)
{
case 310352: // Found in real media
case 318988:
case 320332:
case 321100:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-239 / ISO 15498 conforming 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_239;
case 605846:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.GigaMo;
case 1063146:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 2 3½\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.GigaMo2;
case 1128134:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-280 / ISO 18093 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_280;
case 1263472:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ISO_15286;
case 2043664:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322_2k;
case 7355716:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-317 / ISO 20162 conforming 300mm magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_317;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 4096:
{
switch(blocks)
{
case 1095840:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.ECMA_322;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
case 8192:
{
switch(blocks)
{
case 1834348:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO.",
mediumType, blocks, blockSize);
return MediaType.UDO;
case 3668759:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM UDO2.",
mediumType, blocks, blockSize);
return MediaType.UDO2_WORM;
case 3669724:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO2.",
mediumType, blocks, blockSize);
return MediaType.UDO2;
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
default:
AaruConsole.DebugWriteLine("Media detection",
"SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.",
mediumType, blocks, blockSize);
return MediaType.UnknownMO;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,100 +35,99 @@
using System;
using Aaru.Console;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
public static partial class MediaTypeFromDevice
{
public static partial class MediaTypeFromDevice
/// <summary>Tries to guess, from SCSI information, the media type of a device and/or its inserted media</summary>
/// <param name="scsiPeripheralType">The SCSI Peripheral Type as indicated in the INQUIRY response</param>
/// <param name="vendor">The vendor string of the device</param>
/// <param name="model">The model string of the device</param>
/// <param name="mediumType">The medium type byte from MODE SENSE</param>
/// <param name="densityCode">The density type byte from MODE SENSE</param>
/// <param name="blocks">How many blocks are on the media</param>
/// <param name="blockSize">Size in bytes of each block</param>
/// <param name="isUsb">Device is USB</param>
/// <param name="opticalDisc">Is media an optical disc?</param>
/// <returns>The media type</returns>
public static MediaType GetFromScsi(byte scsiPeripheralType, string vendor, string model, byte mediumType,
byte densityCode, ulong blocks, uint blockSize, bool isUsb,
bool opticalDisc)
{
/// <summary>Tries to guess, from SCSI information, the media type of a device and/or its inserted media</summary>
/// <param name="scsiPeripheralType">The SCSI Peripheral Type as indicated in the INQUIRY response</param>
/// <param name="vendor">The vendor string of the device</param>
/// <param name="model">The model string of the device</param>
/// <param name="mediumType">The medium type byte from MODE SENSE</param>
/// <param name="densityCode">The density type byte from MODE SENSE</param>
/// <param name="blocks">How many blocks are on the media</param>
/// <param name="blockSize">Size in bytes of each block</param>
/// <param name="isUsb">Device is USB</param>
/// <param name="opticalDisc">Is media an optical disc?</param>
/// <returns>The media type</returns>
public static MediaType GetFromScsi(byte scsiPeripheralType, string vendor, string model, byte mediumType,
byte densityCode, ulong blocks, uint blockSize, bool isUsb,
bool opticalDisc)
switch(scsiPeripheralType)
{
switch(scsiPeripheralType)
{
// Direct access device
case 0x00:
// Simplified access device
case 0x0E:
if(mediumType == 0x03 ||
mediumType == 0x05 ||
mediumType == 0x07)
goto case 0x07;
// Direct access device
case 0x00:
// Simplified access device
case 0x0E:
if(mediumType == 0x03 ||
mediumType == 0x05 ||
mediumType == 0x07)
goto case 0x07;
return GetFromSbc(vendor, model, mediumType, blocks, blockSize);
return GetFromSbc(vendor, model, mediumType, blocks, blockSize);
// Sequential access device
case 0x01:
return GetFromSsc(scsiPeripheralType, vendor, model, mediumType, densityCode, blocks, blockSize);
// Sequential access device
case 0x01:
return GetFromSsc(scsiPeripheralType, vendor, model, mediumType, densityCode, blocks, blockSize);
// Write-once device
case 0x04:
// Optical device
case 0x07: return GetFromOdc(mediumType, blocks, blockSize);
// Write-once device
case 0x04:
// Optical device
case 0x07: return GetFromOdc(mediumType, blocks, blockSize);
// MultiMedia Device
case 0x05: return GetFromMmc(model, mediumType, densityCode, blocks, blockSize, isUsb, opticalDisc);
// MultiMedia Device
case 0x05: return GetFromMmc(model, mediumType, densityCode, blocks, blockSize, isUsb, opticalDisc);
// MD DATA drives
case 0x10 when model.StartsWith("MDM", StringComparison.Ordinal) ||
model.StartsWith("MDH", StringComparison.Ordinal):
if(blockSize == 2048)
{
// MD DATA drives
case 0x10 when model.StartsWith("MDM", StringComparison.Ordinal) ||
model.StartsWith("MDH", StringComparison.Ordinal):
if(blockSize == 2048)
{
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to MiniDisc for Data.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MDData;
}
switch(blocks)
{
case 57312:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to MiniDisc for Data.",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MDData;
}
return MediaType.MD60;
case 70464:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 74 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
switch(blocks)
{
case 57312:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MD74;
case 76096:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 80 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MD60;
case 70464:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 74 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MD80;
}
return MediaType.MD74;
case 76096:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 80 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MD80;
}
return MediaType.MD;
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.",
scsiPeripheralType, blocks, blockSize);
// Host managed zoned block device
case 0x14:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, setting media type to host managed zoned block device.",
scsiPeripheralType, blocks, blockSize);
return MediaType.MD;
// Host managed zoned block device
case 0x14:
AaruConsole.DebugWriteLine("Media detection",
"SCSI peripheral type is {0:X2}h, setting media type to host managed zoned block device.",
scsiPeripheralType, blocks, blockSize);
return MediaType.Zone_HDD;
}
return MediaType.Unknown;
return MediaType.Zone_HDD;
}
return MediaType.Unknown;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -38,21 +38,20 @@
using System.ComponentModel.DataAnnotations;
namespace Aaru.CommonTypes.Metadata
namespace Aaru.CommonTypes.Metadata;
/// <summary>Describes CD reading offset</summary>
public class CdOffset
{
/// <summary>Describes CD reading offset</summary>
public class CdOffset
{
/// <summary>Drive manufacturer</summary>
public string Manufacturer { get; set; }
/// <summary>Drive model</summary>
public string Model { get; set; }
/// <summary>Reading offset</summary>
public short Offset { get; set; }
/// <summary>Number of times this offset has been submitted</summary>
public int Submissions { get; set; }
/// <summary>Percentage of submissions in agreement with this offset</summary>
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:P0}")]
public float Agreement { get; set; }
}
/// <summary>Drive manufacturer</summary>
public string Manufacturer { get; set; }
/// <summary>Drive model</summary>
public string Model { get; set; }
/// <summary>Reading offset</summary>
public short Offset { get; set; }
/// <summary>Number of times this offset has been submitted</summary>
public int Submissions { get; set; }
/// <summary>Percentage of submissions in agreement with this offset</summary>
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:P0}")]
public float Agreement { get; set; }
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -41,40 +41,39 @@ using System.Collections.Generic;
using System.Xml.Serialization;
using Schemas;
namespace Aaru.CommonTypes.Metadata
namespace Aaru.CommonTypes.Metadata;
/// <summary>Information that allows to resume a dump</summary>
[Serializable, XmlRoot("DicResume", Namespace = "", IsNullable = false)]
public class Resume
{
/// <summary>Information that allows to resume a dump</summary>
[Serializable, XmlRoot("DicResume", Namespace = "", IsNullable = false)]
public class Resume
{
/// <summary>List of blocks that returned an error on reading</summary>
[XmlArrayItem("Block")]
public List<ulong> BadBlocks;
/// <summary>Date/time this resume file was created</summary>
[XmlElement(DataType = "dateTime")]
public DateTime CreationDate;
/// <summary>Last block on media</summary>
public ulong LastBlock;
/// <summary>Date/time this resume file was last written to</summary>
[XmlElement(DataType = "dateTime")]
public DateTime LastWriteDate;
/// <summary>Next block to read</summary>
public ulong NextBlock;
/// <summary>Is media removable?</summary>
public bool Removable;
/// <summary>Is media a tape?</summary>
public bool Tape;
/// <summary>List of CD subchannels that did not read correctly</summary>
[XmlArrayItem("Block")]
public List<int> BadSubchannels;
/// <summary>Extents of BLANK sectors for magneto-opticals</summary>
[XmlArrayItem("Extent")]
public ExtentType[] BlankExtents;
/// <summary>Title keys that has not been read</summary>
[XmlArrayItem("Block")]
public List<ulong> MissingTitleKeys;
/// <summary>List of dump tries</summary>
[XmlArrayItem("DumpTry")]
public List<DumpHardwareType> Tries;
}
/// <summary>List of blocks that returned an error on reading</summary>
[XmlArrayItem("Block")]
public List<ulong> BadBlocks;
/// <summary>Date/time this resume file was created</summary>
[XmlElement(DataType = "dateTime")]
public DateTime CreationDate;
/// <summary>Last block on media</summary>
public ulong LastBlock;
/// <summary>Date/time this resume file was last written to</summary>
[XmlElement(DataType = "dateTime")]
public DateTime LastWriteDate;
/// <summary>Next block to read</summary>
public ulong NextBlock;
/// <summary>Is media removable?</summary>
public bool Removable;
/// <summary>Is media a tape?</summary>
public bool Tape;
/// <summary>List of CD subchannels that did not read correctly</summary>
[XmlArrayItem("Block")]
public List<int> BadSubchannels;
/// <summary>Extents of BLANK sectors for magneto-opticals</summary>
[XmlArrayItem("Extent")]
public ExtentType[] BlankExtents;
/// <summary>Title keys that has not been read</summary>
[XmlArrayItem("Block")]
public List<ulong> MissingTitleKeys;
/// <summary>List of dump tries</summary>
[XmlArrayItem("DumpTry")]
public List<DumpHardwareType> Tries;
}

View File

@@ -43,267 +43,266 @@ using System.Xml.Serialization;
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable UnusedMember.Global
namespace Aaru.CommonTypes.Metadata
namespace Aaru.CommonTypes.Metadata;
/// <summary>Statistics</summary>
[XmlRoot("DicStats", Namespace = "", IsNullable = false)]
public class Stats
{
/// <summary>Statistics</summary>
[XmlRoot("DicStats", Namespace = "", IsNullable = false)]
public class Stats
{
/// <summary>Executed commands</summary>
public CommandsStats Commands;
/// <summary>Operating systems Aaru has run from</summary>
[XmlArrayItem("OperatingSystem")]
public List<OsStats> OperatingSystems { get; set; }
/// <summary>Aaru versions</summary>
[XmlArrayItem("Version")]
public List<NameValueStats> Versions { get; set; }
/// <summary>Detected filesystems</summary>
[XmlArrayItem("Filesystem")]
public List<NameValueStats> Filesystems { get; set; }
/// <summary>Detected partitioning schemes</summary>
[XmlArrayItem("Scheme")]
public List<NameValueStats> Partitions { get; set; }
/// <summary>Media image formats</summary>
[XmlArrayItem("Format")]
public List<NameValueStats> MediaImages { get; set; }
/// <summary>Used filters</summary>
[XmlArrayItem("Filter", IsNullable = true)]
public List<NameValueStats> Filters { get; set; }
/// <summary>Found devices</summary>
[XmlArrayItem("Device", IsNullable = true)]
public List<DeviceStats> Devices { get; set; }
/// <summary>Found media types, real, and in image</summary>
[XmlArrayItem("Media")]
public List<MediaStats> Medias { get; set; }
/// <summary>Benchmark statistics</summary>
public BenchmarkStats Benchmark { get; set; }
/// <summary>Media scanning statistics</summary>
public MediaScanStats MediaScan { get; set; }
/// <summary>Image verification statistics</summary>
public VerifyStats Verify { get; set; }
}
/// <summary>DTO for statistics</summary>
[SuppressMessage("ReSharper", "CollectionNeverQueried.Global")]
public class StatsDto
{
/// <summary>Executed commands</summary>
public List<NameValueStats> Commands { get; set; }
/// <summary>Operating systems Aaru has run from</summary>
public List<OsStats> OperatingSystems { get; set; }
/// <summary>Aaru versions</summary>
public List<NameValueStats> Versions { get; set; }
/// <summary>Detected filesystems</summary>
public List<NameValueStats> Filesystems { get; set; }
/// <summary>Detected partitioning schemes</summary>
public List<NameValueStats> Partitions { get; set; }
/// <summary>Media image formats</summary>
public List<NameValueStats> MediaFormats { get; set; }
/// <summary>Used filters</summary>
public List<NameValueStats> Filters { get; set; }
/// <summary>Found devices</summary>
public List<DeviceStats> Devices { get; set; }
/// <summary>Found media types, real, and in image</summary>
public List<MediaStats> Medias { get; set; }
/// <summary>Remote applications</summary>
public List<OsStats> RemoteApplications { get; set; }
/// <summary>Remote application architectures</summary>
public List<NameValueStats> RemoteArchitectures { get; set; }
/// <summary>Operating systems where a remote application has been running</summary>
public List<OsStats> RemoteOperatingSystems { get; set; }
}
/// <summary>Command execution statistics</summary>
[SuppressMessage("ReSharper", "UnassignedField.Global")]
public class CommandsStats
{
/// <summary>Number of times the filesystem info command has been used</summary>
public long Analyze;
/// <summary>Number of times the benchmark command has been used</summary>
public long Benchmark;
/// <summary>Number of times the image checksum command has been used</summary>
public long Checksum;
/// <summary>Number of times the image compare command has been used</summary>
public long Compare;
/// <summary>Number of times the image convert command has been used</summary>
public long ConvertImage;
/// <summary>Number of times the image create-sidecar command has been used</summary>
public long CreateSidecar;
/// <summary>Number of times the image decode command has been used</summary>
public long Decode;
/// <summary>Number of times the device info command has been used</summary>
public long DeviceInfo;
/// <summary>Number of times the device report command has been used</summary>
public long DeviceReport;
/// <summary>Number of times the media dump command has been used</summary>
public long DumpMedia;
/// <summary>Number of times the image entropy command has been used</summary>
public long Entropy;
/// <summary>Number of times the filesystem extract command has been used</summary>
public long ExtractFiles;
/// <summary>Number of times the list formats command has been used</summary>
public long Formats;
/// <summary>Number of times the image info command has been used</summary>
public long ImageInfo;
/// <summary>Number of times the device list command has been used</summary>
public long ListDevices;
/// <summary>Number of times the list encodings command has been used</summary>
public long ListEncodings;
/// <summary>Number of times the filesystem ls command has been used</summary>
public long Ls;
/// <summary>Number of times the media info command has been used</summary>
public long MediaInfo;
/// <summary>Number of times the media scan command has been used</summary>
public long MediaScan;
/// <summary>Number of times the image printhex command has been used</summary>
public long PrintHex;
/// <summary>Number of times the image verify command has been used</summary>
public long Verify;
}
/// <summary>Statistics of verified media</summary>
public class VerifiedItems
{
/// <summary>Number of correct images</summary>
public long Correct;
/// <summary>Number of failed images</summary>
public long Failed;
}
/// <summary>Verification statistics</summary>
public class VerifyStats
{
/// <summary>Image verification statistics</summary>
public VerifiedItems MediaImages;
/// <summary>Image contents verification statistics</summary>
public ScannedSectors Sectors;
}
/// <summary>Image contents verification statistics</summary>
public class ScannedSectors
{
/// <summary>Sectors found to be correct</summary>
public long Correct;
/// <summary>Sectors found to be incorrect</summary>
public long Error;
/// <summary>Total number of verified sectors</summary>
public long Total;
/// <summary>Total number of sectors that could not be verified</summary>
public long Unverifiable;
}
/// <summary>Media scanning time statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class TimeStats
{
/// <summary>Number of sectors that took more than 3ms but less than 100ms to read</summary>
public long LessThan10ms;
/// <summary>Number of sectors that took more than 50ms but less than 150ms to read</summary>
public long LessThan150ms;
/// <summary>Number of sectors that took less than 3ms to read</summary>
public long LessThan3ms;
/// <summary>Number of sectors that took more than 150ms but less than 500ms to read</summary>
public long LessThan500ms;
/// <summary>Number of sectors that took more than 10ms but less than 50ms to read</summary>
public long LessThan50ms;
/// <summary>Number of sectors that took more than 500ms to read</summary>
public long MoreThan500ms;
}
/// <summary>Media scanning statistics</summary>
public class MediaScanStats
{
/// <summary>Statistics of scanned sectors</summary>
public ScannedSectors Sectors;
/// <summary>Scan time statistics</summary>
public TimeStats Times;
}
/// <summary>Checksum type statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class ChecksumStats
{
/// <summary>Checksum algorithm</summary>
[XmlAttribute]
public string algorithm;
/// <summary>Time taken to execute algorithm</summary>
[XmlText]
public double Value;
}
/// <summary>Executed commands</summary>
public CommandsStats Commands;
/// <summary>Operating systems Aaru has run from</summary>
[XmlArrayItem("OperatingSystem")]
public List<OsStats> OperatingSystems { get; set; }
/// <summary>Aaru versions</summary>
[XmlArrayItem("Version")]
public List<NameValueStats> Versions { get; set; }
/// <summary>Detected filesystems</summary>
[XmlArrayItem("Filesystem")]
public List<NameValueStats> Filesystems { get; set; }
/// <summary>Detected partitioning schemes</summary>
[XmlArrayItem("Scheme")]
public List<NameValueStats> Partitions { get; set; }
/// <summary>Media image formats</summary>
[XmlArrayItem("Format")]
public List<NameValueStats> MediaImages { get; set; }
/// <summary>Used filters</summary>
[XmlArrayItem("Filter", IsNullable = true)]
public List<NameValueStats> Filters { get; set; }
/// <summary>Found devices</summary>
[XmlArrayItem("Device", IsNullable = true)]
public List<DeviceStats> Devices { get; set; }
/// <summary>Found media types, real, and in image</summary>
[XmlArrayItem("Media")]
public List<MediaStats> Medias { get; set; }
/// <summary>Benchmark statistics</summary>
public class BenchmarkStats
{
/// <summary>Total time taken to run the checksum algorithms in parallel</summary>
public double All;
/// <summary>List of time taken by each checksum algorithm</summary>
[XmlElement("Checksum")]
public List<ChecksumStats> Checksum;
/// <summary>Time taken to benchmark entropy calculation</summary>
public double Entropy;
/// <summary>Maximum amount of memory used while running the benchmark</summary>
public long MaxMemory;
/// <summary>Minimum amount of memory used while running the benchmark</summary>
public long MinMemory;
/// <summary>Total time taken to run the checksum algorithms sequentially</summary>
public double Sequential;
}
public BenchmarkStats Benchmark { get; set; }
/// <summary>Media scanning statistics</summary>
public MediaScanStats MediaScan { get; set; }
/// <summary>Image verification statistics</summary>
public VerifyStats Verify { get; set; }
}
/// <summary>Media statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class MediaStats
{
/// <summary>Found in a real device?</summary>
[XmlAttribute]
public bool real;
/// <summary>Media type</summary>
[XmlAttribute]
public string type;
/// <summary>Number of times it has been found</summary>
[XmlText]
public long Value;
}
/// <summary>DTO for statistics</summary>
[SuppressMessage("ReSharper", "CollectionNeverQueried.Global")]
public class StatsDto
{
/// <summary>Executed commands</summary>
public List<NameValueStats> Commands { get; set; }
/// <summary>Operating systems Aaru has run from</summary>
public List<OsStats> OperatingSystems { get; set; }
/// <summary>Aaru versions</summary>
public List<NameValueStats> Versions { get; set; }
/// <summary>Detected filesystems</summary>
public List<NameValueStats> Filesystems { get; set; }
/// <summary>Detected partitioning schemes</summary>
public List<NameValueStats> Partitions { get; set; }
/// <summary>Media image formats</summary>
public List<NameValueStats> MediaFormats { get; set; }
/// <summary>Used filters</summary>
public List<NameValueStats> Filters { get; set; }
/// <summary>Found devices</summary>
public List<DeviceStats> Devices { get; set; }
/// <summary>Found media types, real, and in image</summary>
public List<MediaStats> Medias { get; set; }
/// <summary>Remote applications</summary>
public List<OsStats> RemoteApplications { get; set; }
/// <summary>Remote application architectures</summary>
public List<NameValueStats> RemoteArchitectures { get; set; }
/// <summary>Operating systems where a remote application has been running</summary>
public List<OsStats> RemoteOperatingSystems { get; set; }
}
/// <summary>Device statistics</summary>
public class DeviceStats
{
/// <summary>Is manufacturer null?</summary>
[XmlIgnore]
public bool ManufacturerSpecified;
/// <summary>Manufacturer string</summary>
public string Manufacturer { get; set; }
/// <summary>Model string</summary>
public string Model { get; set; }
/// <summary>Revision or firmware version</summary>
public string Revision { get; set; }
/// <summary>Bus the device was attached to</summary>
public string Bus { get; set; }
}
/// <summary>Command execution statistics</summary>
[SuppressMessage("ReSharper", "UnassignedField.Global")]
public class CommandsStats
{
/// <summary>Number of times the filesystem info command has been used</summary>
public long Analyze;
/// <summary>Number of times the benchmark command has been used</summary>
public long Benchmark;
/// <summary>Number of times the image checksum command has been used</summary>
public long Checksum;
/// <summary>Number of times the image compare command has been used</summary>
public long Compare;
/// <summary>Number of times the image convert command has been used</summary>
public long ConvertImage;
/// <summary>Number of times the image create-sidecar command has been used</summary>
public long CreateSidecar;
/// <summary>Number of times the image decode command has been used</summary>
public long Decode;
/// <summary>Number of times the device info command has been used</summary>
public long DeviceInfo;
/// <summary>Number of times the device report command has been used</summary>
public long DeviceReport;
/// <summary>Number of times the media dump command has been used</summary>
public long DumpMedia;
/// <summary>Number of times the image entropy command has been used</summary>
public long Entropy;
/// <summary>Number of times the filesystem extract command has been used</summary>
public long ExtractFiles;
/// <summary>Number of times the list formats command has been used</summary>
public long Formats;
/// <summary>Number of times the image info command has been used</summary>
public long ImageInfo;
/// <summary>Number of times the device list command has been used</summary>
public long ListDevices;
/// <summary>Number of times the list encodings command has been used</summary>
public long ListEncodings;
/// <summary>Number of times the filesystem ls command has been used</summary>
public long Ls;
/// <summary>Number of times the media info command has been used</summary>
public long MediaInfo;
/// <summary>Number of times the media scan command has been used</summary>
public long MediaScan;
/// <summary>Number of times the image printhex command has been used</summary>
public long PrintHex;
/// <summary>Number of times the image verify command has been used</summary>
public long Verify;
}
/// <summary>Name=value pair statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class NameValueStats
{
/// <summary>Name</summary>
[XmlAttribute]
public string name { get; set; }
/// <summary>Number of times it has been used/found</summary>
[XmlText]
public long Value { get; set; }
}
/// <summary>Statistics of verified media</summary>
public class VerifiedItems
{
/// <summary>Number of correct images</summary>
public long Correct;
/// <summary>Number of failed images</summary>
public long Failed;
}
/// <summary>Operating system statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class OsStats
{
/// <summary>Operating system name</summary>
[XmlAttribute]
public string name { get; set; }
/// <summary>Operating system version</summary>
[XmlAttribute]
public string version { get; set; }
/// <summary>Number of times Aaru run on it</summary>
[XmlText]
public long Value { get; set; }
}
/// <summary>Verification statistics</summary>
public class VerifyStats
{
/// <summary>Image verification statistics</summary>
public VerifiedItems MediaImages;
/// <summary>Image contents verification statistics</summary>
public ScannedSectors Sectors;
}
/// <summary>Image contents verification statistics</summary>
public class ScannedSectors
{
/// <summary>Sectors found to be correct</summary>
public long Correct;
/// <summary>Sectors found to be incorrect</summary>
public long Error;
/// <summary>Total number of verified sectors</summary>
public long Total;
/// <summary>Total number of sectors that could not be verified</summary>
public long Unverifiable;
}
/// <summary>Media scanning time statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class TimeStats
{
/// <summary>Number of sectors that took more than 3ms but less than 100ms to read</summary>
public long LessThan10ms;
/// <summary>Number of sectors that took more than 50ms but less than 150ms to read</summary>
public long LessThan150ms;
/// <summary>Number of sectors that took less than 3ms to read</summary>
public long LessThan3ms;
/// <summary>Number of sectors that took more than 150ms but less than 500ms to read</summary>
public long LessThan500ms;
/// <summary>Number of sectors that took more than 10ms but less than 50ms to read</summary>
public long LessThan50ms;
/// <summary>Number of sectors that took more than 500ms to read</summary>
public long MoreThan500ms;
}
/// <summary>Media scanning statistics</summary>
public class MediaScanStats
{
/// <summary>Statistics of scanned sectors</summary>
public ScannedSectors Sectors;
/// <summary>Scan time statistics</summary>
public TimeStats Times;
}
/// <summary>Checksum type statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class ChecksumStats
{
/// <summary>Checksum algorithm</summary>
[XmlAttribute]
public string algorithm;
/// <summary>Time taken to execute algorithm</summary>
[XmlText]
public double Value;
}
/// <summary>Benchmark statistics</summary>
public class BenchmarkStats
{
/// <summary>Total time taken to run the checksum algorithms in parallel</summary>
public double All;
/// <summary>List of time taken by each checksum algorithm</summary>
[XmlElement("Checksum")]
public List<ChecksumStats> Checksum;
/// <summary>Time taken to benchmark entropy calculation</summary>
public double Entropy;
/// <summary>Maximum amount of memory used while running the benchmark</summary>
public long MaxMemory;
/// <summary>Minimum amount of memory used while running the benchmark</summary>
public long MinMemory;
/// <summary>Total time taken to run the checksum algorithms sequentially</summary>
public double Sequential;
}
/// <summary>Media statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class MediaStats
{
/// <summary>Found in a real device?</summary>
[XmlAttribute]
public bool real;
/// <summary>Media type</summary>
[XmlAttribute]
public string type;
/// <summary>Number of times it has been found</summary>
[XmlText]
public long Value;
}
/// <summary>Device statistics</summary>
public class DeviceStats
{
/// <summary>Is manufacturer null?</summary>
[XmlIgnore]
public bool ManufacturerSpecified;
/// <summary>Manufacturer string</summary>
public string Manufacturer { get; set; }
/// <summary>Model string</summary>
public string Model { get; set; }
/// <summary>Revision or firmware version</summary>
public string Revision { get; set; }
/// <summary>Bus the device was attached to</summary>
public string Bus { get; set; }
}
/// <summary>Name=value pair statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class NameValueStats
{
/// <summary>Name</summary>
[XmlAttribute]
public string name { get; set; }
/// <summary>Number of times it has been used/found</summary>
[XmlText]
public long Value { get; set; }
}
/// <summary>Operating system statistics</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class OsStats
{
/// <summary>Operating system name</summary>
[XmlAttribute]
public string name { get; set; }
/// <summary>Operating system version</summary>
[XmlAttribute]
public string version { get; set; }
/// <summary>Number of times Aaru run on it</summary>
[XmlText]
public long Value { get; set; }
}

View File

@@ -39,18 +39,17 @@
using Aaru.CommonTypes.Interop;
using Schemas;
namespace Aaru.CommonTypes.Metadata
namespace Aaru.CommonTypes.Metadata;
/// <summary>Manages Aaru's version for metadata</summary>
public static class Version
{
/// <summary>Manages Aaru's version for metadata</summary>
public static class Version
/// <summary>Gets XML software type for the running version</summary>
/// <returns>XML software type</returns>
public static SoftwareType GetSoftwareType() => new SoftwareType
{
/// <summary>Gets XML software type for the running version</summary>
/// <returns>XML software type</returns>
public static SoftwareType GetSoftwareType() => new SoftwareType
{
Name = "Aaru",
OperatingSystem = DetectOS.GetRealPlatformID().ToString(),
Version = typeof(Version).Assembly.GetName().Version?.ToString()
};
}
Name = "Aaru",
OperatingSystem = DetectOS.GetRealPlatformID().ToString(),
Version = typeof(Version).Assembly.GetName().Version?.ToString()
};
}

View File

@@ -38,82 +38,81 @@
using System;
namespace Aaru.CommonTypes
namespace Aaru.CommonTypes;
/// <summary>Partition structure.</summary>
public struct Partition : IEquatable<Partition>, IComparable<Partition>
{
/// <summary>Partition structure.</summary>
public struct Partition : IEquatable<Partition>, IComparable<Partition>
/// <summary>Partition number, 0-started</summary>
public ulong Sequence;
/// <summary>Partition type</summary>
public string Type;
/// <summary>Partition name (if the scheme supports it)</summary>
public string Name;
/// <summary>Start of the partition, in bytes</summary>
public ulong Offset;
/// <summary>LBA of partition start</summary>
public ulong Start;
/// <summary>Length in bytes of the partition</summary>
public ulong Size;
/// <summary>Length in sectors of the partition</summary>
public ulong Length;
/// <summary>Information that does not find space in this struct</summary>
public string Description;
/// <summary>LBA of last partition sector</summary>
public readonly ulong End => Start + Length - 1;
/// <summary>Name of partition scheme that contains this partition</summary>
public string Scheme;
/// <inheritdoc />
/// <summary>Compares two partitions</summary>
/// <param name="other">Partition to compare with</param>
/// <returns>0 if both partitions start and end at the same sector</returns>
public bool Equals(Partition other) => Start == other.Start && Length == other.Length;
/// <inheritdoc />
public override bool Equals(object obj) => obj is Partition partition && Equals(partition);
/// <inheritdoc />
// ReSharper disable once NonReadonlyMemberInGetHashCode
public override int GetHashCode() => Start.GetHashCode() + End.GetHashCode();
/// <summary>
/// Compares this partition with another and returns an integer that indicates whether the current partition
/// precedes, follows, or is in the same place as the other partition.
/// </summary>
/// <param name="other">Partition to compare with</param>
/// <returns>A value that indicates the relative equality of the partitions being compared.</returns>
/// <inheritdoc />
public int CompareTo(Partition other)
{
/// <summary>Partition number, 0-started</summary>
public ulong Sequence;
/// <summary>Partition type</summary>
public string Type;
/// <summary>Partition name (if the scheme supports it)</summary>
public string Name;
/// <summary>Start of the partition, in bytes</summary>
public ulong Offset;
/// <summary>LBA of partition start</summary>
public ulong Start;
/// <summary>Length in bytes of the partition</summary>
public ulong Size;
/// <summary>Length in sectors of the partition</summary>
public ulong Length;
/// <summary>Information that does not find space in this struct</summary>
public string Description;
/// <summary>LBA of last partition sector</summary>
public readonly ulong End => Start + Length - 1;
/// <summary>Name of partition scheme that contains this partition</summary>
public string Scheme;
if(Start == other.Start &&
End == other.End)
return 0;
/// <inheritdoc />
/// <summary>Compares two partitions</summary>
/// <param name="other">Partition to compare with</param>
/// <returns>0 if both partitions start and end at the same sector</returns>
public bool Equals(Partition other) => Start == other.Start && Length == other.Length;
if(Start > other.Start ||
End > other.End)
return 1;
/// <inheritdoc />
public override bool Equals(object obj) => obj is Partition partition && Equals(partition);
/// <inheritdoc />
// ReSharper disable once NonReadonlyMemberInGetHashCode
public override int GetHashCode() => Start.GetHashCode() + End.GetHashCode();
/// <summary>
/// Compares this partition with another and returns an integer that indicates whether the current partition
/// precedes, follows, or is in the same place as the other partition.
/// </summary>
/// <param name="other">Partition to compare with</param>
/// <returns>A value that indicates the relative equality of the partitions being compared.</returns>
/// <inheritdoc />
public int CompareTo(Partition other)
{
if(Start == other.Start &&
End == other.End)
return 0;
if(Start > other.Start ||
End > other.End)
return 1;
return -1;
}
// Define the equality operator.
public static bool operator ==(Partition operand1, Partition operand2) => operand1.Equals(operand2);
// Define the inequality operator.
public static bool operator !=(Partition operand1, Partition operand2) => !operand1.Equals(operand2);
// Define the is greater than operator.
public static bool operator >(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == 1;
// Define the is less than operator.
public static bool operator <(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == -1;
// Define the is greater than or equal to operator.
public static bool operator >=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) >= 0;
// Define the is less than or equal to operator.
public static bool operator <=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) <= 0;
return -1;
}
// Define the equality operator.
public static bool operator ==(Partition operand1, Partition operand2) => operand1.Equals(operand2);
// Define the inequality operator.
public static bool operator !=(Partition operand1, Partition operand2) => !operand1.Equals(operand2);
// Define the is greater than operator.
public static bool operator >(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == 1;
// Define the is less than operator.
public static bool operator <(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == -1;
// Define the is greater than or equal to operator.
public static bool operator >=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) >= 0;
// Define the is less than or equal to operator.
public static bool operator <=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) <= 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -32,214 +32,213 @@
using System.Diagnostics.CodeAnalysis;
namespace Aaru.CommonTypes.Structs.Devices.SCSI
namespace Aaru.CommonTypes.Structs.Devices.SCSI;
/// <summary>List of known SCSI peripheral qualifiers</summary>
public enum PeripheralQualifiers : byte
{
/// <summary>List of known SCSI peripheral qualifiers</summary>
public enum PeripheralQualifiers : byte
{
/// <summary>Peripheral qualifier: Device is connected and supported</summary>
Supported = 0x00,
/// <summary>Peripheral qualifier: Device is supported but not connected</summary>
Unconnected = 0x01,
/// <summary>Peripheral qualifier: Reserved value</summary>
Reserved = 0x02,
/// <summary>Peripheral qualifier: Device is connected but unsupported</summary>
Unsupported = 0x03,
/// <summary>Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07</summary>
VendorMask = 0x04
}
/// <summary>Peripheral qualifier: Device is connected and supported</summary>
Supported = 0x00,
/// <summary>Peripheral qualifier: Device is supported but not connected</summary>
Unconnected = 0x01,
/// <summary>Peripheral qualifier: Reserved value</summary>
Reserved = 0x02,
/// <summary>Peripheral qualifier: Device is connected but unsupported</summary>
Unsupported = 0x03,
/// <summary>Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07</summary>
VendorMask = 0x04
}
/// <summary>List of known peripheral device types</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PeripheralDeviceTypes : byte
{
/// <summary>Direct-access device</summary>
DirectAccess = 0x00,
/// <summary>Sequential-access device</summary>
SequentialAccess = 0x01,
/// <summary>Printer device</summary>
PrinterDevice = 0x02,
/// <summary>Processor device</summary>
ProcessorDevice = 0x03,
/// <summary>Write-once device</summary>
WriteOnceDevice = 0x04,
/// <summary>CD-ROM/DVD/etc device</summary>
MultiMediaDevice = 0x05,
/// <summary>Scanner device</summary>
ScannerDevice = 0x06,
/// <summary>Optical memory device</summary>
OpticalDevice = 0x07,
/// <summary>Medium change device</summary>
MediumChangerDevice = 0x08,
/// <summary>Communications device</summary>
CommsDevice = 0x09,
/// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
PrePressDevice1 = 0x0A,
/// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
PrePressDevice2 = 0x0B,
/// <summary>Array controller device</summary>
ArrayControllerDevice = 0x0C,
/// <summary>Enclosure services device</summary>
EnclosureServiceDevice = 0x0D,
/// <summary>Simplified direct-access device</summary>
SimplifiedDevice = 0x0E,
/// <summary>Optical card reader/writer device</summary>
OCRWDevice = 0x0F,
/// <summary>Bridging Expanders</summary>
BridgingExpander = 0x10,
/// <summary>Object-based Storage Device</summary>
ObjectDevice = 0x11,
/// <summary>Automation/Drive Interface</summary>
ADCDevice = 0x12,
/// <summary>Security Manager Device</summary>
SCSISecurityManagerDevice = 0x13,
/// <summary>Host managed zoned block device</summary>
SCSIZonedBlockDevice = 0x14,
/// <summary>Well known logical unit</summary>
WellKnownDevice = 0x1E,
/// <summary>Unknown or no device type</summary>
UnknownDevice = 0x1F
}
/// <summary>List of known peripheral device types</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PeripheralDeviceTypes : byte
{
/// <summary>Direct-access device</summary>
DirectAccess = 0x00,
/// <summary>Sequential-access device</summary>
SequentialAccess = 0x01,
/// <summary>Printer device</summary>
PrinterDevice = 0x02,
/// <summary>Processor device</summary>
ProcessorDevice = 0x03,
/// <summary>Write-once device</summary>
WriteOnceDevice = 0x04,
/// <summary>CD-ROM/DVD/etc device</summary>
MultiMediaDevice = 0x05,
/// <summary>Scanner device</summary>
ScannerDevice = 0x06,
/// <summary>Optical memory device</summary>
OpticalDevice = 0x07,
/// <summary>Medium change device</summary>
MediumChangerDevice = 0x08,
/// <summary>Communications device</summary>
CommsDevice = 0x09,
/// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
PrePressDevice1 = 0x0A,
/// <summary>Graphics arts pre-press device (defined in ASC IT8)</summary>
PrePressDevice2 = 0x0B,
/// <summary>Array controller device</summary>
ArrayControllerDevice = 0x0C,
/// <summary>Enclosure services device</summary>
EnclosureServiceDevice = 0x0D,
/// <summary>Simplified direct-access device</summary>
SimplifiedDevice = 0x0E,
/// <summary>Optical card reader/writer device</summary>
OCRWDevice = 0x0F,
/// <summary>Bridging Expanders</summary>
BridgingExpander = 0x10,
/// <summary>Object-based Storage Device</summary>
ObjectDevice = 0x11,
/// <summary>Automation/Drive Interface</summary>
ADCDevice = 0x12,
/// <summary>Security Manager Device</summary>
SCSISecurityManagerDevice = 0x13,
/// <summary>Host managed zoned block device</summary>
SCSIZonedBlockDevice = 0x14,
/// <summary>Well known logical unit</summary>
WellKnownDevice = 0x1E,
/// <summary>Unknown or no device type</summary>
UnknownDevice = 0x1F
}
/// <summary>List of known ANSI SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ANSIVersions : byte
{
/// <summary>Device does not claim conformance to any ANSI version</summary>
ANSINoVersion = 0x00,
/// <summary>Device complies with ANSI X3.131:1986</summary>
ANSI1986Version = 0x01,
/// <summary>Device complies with ANSI X3.131:1994</summary>
ANSI1994Version = 0x02,
/// <summary>Device complies with ANSI X3.301:1997</summary>
ANSI1997Version = 0x03,
/// <summary>Device complies with ANSI X3.351:2001</summary>
ANSI2001Version = 0x04,
/// <summary>Device complies with ANSI X3.408:2005.</summary>
ANSI2005Version = 0x05,
/// <summary>Device complies with SPC-4</summary>
ANSI2008Version = 0x06
}
/// <summary>List of known ANSI SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ANSIVersions : byte
{
/// <summary>Device does not claim conformance to any ANSI version</summary>
ANSINoVersion = 0x00,
/// <summary>Device complies with ANSI X3.131:1986</summary>
ANSI1986Version = 0x01,
/// <summary>Device complies with ANSI X3.131:1994</summary>
ANSI1994Version = 0x02,
/// <summary>Device complies with ANSI X3.301:1997</summary>
ANSI1997Version = 0x03,
/// <summary>Device complies with ANSI X3.351:2001</summary>
ANSI2001Version = 0x04,
/// <summary>Device complies with ANSI X3.408:2005.</summary>
ANSI2005Version = 0x05,
/// <summary>Device complies with SPC-4</summary>
ANSI2008Version = 0x06
}
/// <summary>List of known ECMA SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ECMAVersions : byte
{
/// <summary>Device does not claim conformance to any ECMA version</summary>
ECMANoVersion = 0x00,
/// <summary>Device complies with a ECMA-111 standard</summary>
ECMA111 = 0x01
}
/// <summary>List of known ECMA SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ECMAVersions : byte
{
/// <summary>Device does not claim conformance to any ECMA version</summary>
ECMANoVersion = 0x00,
/// <summary>Device complies with a ECMA-111 standard</summary>
ECMA111 = 0x01
}
/// <summary>List of known ISO SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ISOVersions : byte
{
/// <summary>Device does not claim conformance to any ISO/IEC version</summary>
ISONoVersion = 0x00,
/// <summary>Device complies with ISO/IEC 9316:1995</summary>
ISO1995Version = 0x02
}
/// <summary>List of known ISO SCSI standards</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ISOVersions : byte
{
/// <summary>Device does not claim conformance to any ISO/IEC version</summary>
ISONoVersion = 0x00,
/// <summary>Device complies with ISO/IEC 9316:1995</summary>
ISO1995Version = 0x02
}
/// <summary>List of known SCSI Parallel Interface clocking types</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum SPIClocking : byte
{
/// <summary>Supports only ST</summary>
ST = 0x00,
/// <summary>Supports only DT</summary>
DT = 0x01,
/// <summary>Reserved value</summary>
Reserved = 0x02,
/// <summary>Supports ST and DT</summary>
STandDT = 0x03
}
/// <summary>List of known SCSI Parallel Interface clocking types</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum SPIClocking : byte
{
/// <summary>Supports only ST</summary>
ST = 0x00,
/// <summary>Supports only DT</summary>
DT = 0x01,
/// <summary>Reserved value</summary>
Reserved = 0x02,
/// <summary>Supports ST and DT</summary>
STandDT = 0x03
}
/// <summary>List of known TGPS values</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum TGPSValues : byte
{
/// <summary>Asymmetrical access not supported</summary>
NotSupported = 0x00,
/// <summary>Only implicit asymmetrical access is supported</summary>
OnlyImplicit = 0x01,
/// <summary>Only explicit asymmetrical access is supported</summary>
OnlyExplicit = 0x02,
/// <summary>Both implicit and explicit asymmetrical access are supported</summary>
Both = 0x03
}
/// <summary>List of known TGPS values</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum TGPSValues : byte
{
/// <summary>Asymmetrical access not supported</summary>
NotSupported = 0x00,
/// <summary>Only implicit asymmetrical access is supported</summary>
OnlyImplicit = 0x01,
/// <summary>Only explicit asymmetrical access is supported</summary>
OnlyExplicit = 0x02,
/// <summary>Both implicit and explicit asymmetrical access are supported</summary>
Both = 0x03
}
/// <summary>List of known SCSI protocols</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ProtocolIdentifiers : byte
{
/// <summary>Fibre Channel</summary>
FibreChannel = 0,
/// <summary>Parallel SCSI</summary>
SCSI = 1,
/// <summary>SSA</summary>
SSA = 2,
/// <summary>IEEE-1394</summary>
Firewire = 3,
/// <summary>SCSI Remote Direct Memory Access Protocol</summary>
RDMAP = 4,
/// <summary>Internet SCSI</summary>
iSCSI = 5,
/// <summary>Serial SCSI</summary>
SAS = 6,
/// <summary>Automation/Drive Interface Transport Protocol</summary>
ADT = 7,
/// <summary>AT Attachment Interface (ATA/ATAPI)</summary>
ATA = 8,
/// <summary>USB Attached SCSI</summary>
UAS = 9,
/// <summary>SCSI over PCI Express</summary>
SCSIe = 10,
/// <summary>PCI Express</summary>
PCIe = 11,
/// <summary>No specific protocol</summary>
NoProtocol = 15
}
/// <summary>List of known SCSI protocols</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ProtocolIdentifiers : byte
{
/// <summary>Fibre Channel</summary>
FibreChannel = 0,
/// <summary>Parallel SCSI</summary>
SCSI = 1,
/// <summary>SSA</summary>
SSA = 2,
/// <summary>IEEE-1394</summary>
Firewire = 3,
/// <summary>SCSI Remote Direct Memory Access Protocol</summary>
RDMAP = 4,
/// <summary>Internet SCSI</summary>
iSCSI = 5,
/// <summary>Serial SCSI</summary>
SAS = 6,
/// <summary>Automation/Drive Interface Transport Protocol</summary>
ADT = 7,
/// <summary>AT Attachment Interface (ATA/ATAPI)</summary>
ATA = 8,
/// <summary>USB Attached SCSI</summary>
UAS = 9,
/// <summary>SCSI over PCI Express</summary>
SCSIe = 10,
/// <summary>PCI Express</summary>
PCIe = 11,
/// <summary>No specific protocol</summary>
NoProtocol = 15
}
/// <summary>List of known SCSI definitions</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ScsiDefinitions : byte
{
/// <summary>Unknown</summary>
Current = 0,
/// <summary>SCSI-1</summary>
SCSI1 = 1,
/// <summary>Unknown</summary>
CCS = 2,
/// <summary>SCSI-2</summary>
SCSI2 = 3,
/// <summary>SCSI-3</summary>
SCSI3 = 4
}
/// <summary>List of known SCSI definitions</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum ScsiDefinitions : byte
{
/// <summary>Unknown</summary>
Current = 0,
/// <summary>SCSI-1</summary>
SCSI1 = 1,
/// <summary>Unknown</summary>
CCS = 2,
/// <summary>SCSI-2</summary>
SCSI2 = 3,
/// <summary>SCSI-3</summary>
SCSI3 = 4
}
/// <summary>List of known SCSI physical interfaces</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PhysicalInterfaces : uint
{
/// <summary>Unspecified physical interface</summary>
Unspecified = 0,
/// <summary>SCSI</summary>
SCSI = 1,
/// <summary>ATAPI</summary>
ATAPI = 2,
/// <summary>IEEE-1394/1995</summary>
IEEE1394 = 3,
/// <summary>IEEE-1394A</summary>
IEEE1394A = 4,
/// <summary>Fibre Channel</summary>
FC = 5,
/// <summary>IEEE-1394B</summary>
IEEE1394B = 6,
/// <summary>Serial ATAPI</summary>
SerialATAPI = 7,
/// <summary>USB</summary>
USB = 8,
/// <summary>Vendor unique</summary>
Vendor = 0xFFFF
}
/// <summary>List of known SCSI physical interfaces</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public enum PhysicalInterfaces : uint
{
/// <summary>Unspecified physical interface</summary>
Unspecified = 0,
/// <summary>SCSI</summary>
SCSI = 1,
/// <summary>ATAPI</summary>
ATAPI = 2,
/// <summary>IEEE-1394/1995</summary>
IEEE1394 = 3,
/// <summary>IEEE-1394A</summary>
IEEE1394A = 4,
/// <summary>Fibre Channel</summary>
FC = 5,
/// <summary>IEEE-1394B</summary>
IEEE1394B = 6,
/// <summary>Serial ATAPI</summary>
SerialATAPI = 7,
/// <summary>USB</summary>
USB = 8,
/// <summary>Vendor unique</summary>
Vendor = 0xFFFF
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,480 +35,479 @@ using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
namespace Aaru.CommonTypes.Structs.Devices.SCSI.Modes
namespace Aaru.CommonTypes.Structs.Devices.SCSI.Modes;
#region Mode Page 0x2A: CD-ROM capabilities page
/// <summary>
/// CD-ROM capabilities page Page code 0x2A 16 bytes in OB-U0077C 20 bytes in SFF-8020i 22 bytes in MMC-1 26 bytes
/// in MMC-2 Variable bytes in MMC-3
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
public class ModePage_2A
{
#region Mode Page 0x2A: CD-ROM capabilities page
/// <summary>Write speed performance descriptors</summary>
public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors;
/// <summary>Parameters can be saved</summary>
public bool PS { get; set; }
/// <summary>Drive supports multi-session and/or Photo-CD</summary>
public bool MultiSession { get; set; }
/// <summary>Drive is capable of reading sectors in Mode 2 Form 2 format</summary>
public bool Mode2Form2 { get; set; }
/// <summary>Drive is capable of reading sectors in Mode 2 Form 1 format</summary>
public bool Mode2Form1 { get; set; }
/// <summary>Drive is capable of playing audio</summary>
public bool AudioPlay { get; set; }
/// <summary>Drive can return the ISRC</summary>
public bool ISRC { get; set; }
/// <summary>Drive can return the media catalogue number</summary>
public bool UPC { get; set; }
/// <summary>Drive can return C2 pointers</summary>
public bool C2Pointer { get; set; }
/// <summary>Drive can read, deinterlave and correct R-W subchannels</summary>
public bool DeinterlaveSubchannel { get; set; }
/// <summary>Drive can read interleaved and uncorrected R-W subchannels</summary>
public bool Subchannel { get; set; }
/// <summary>Drive can continue from a loss of streaming on audio reading</summary>
public bool AccurateCDDA { get; set; }
/// <summary>Audio can be read as digital data</summary>
public bool CDDACommand { get; set; }
/// <summary>Loading Mechanism Type</summary>
public byte LoadingMechanism { get; set; }
/// <summary>Drive can eject discs</summary>
public bool Eject { get; set; }
/// <summary>Drive's optional prevent jumper status</summary>
public bool PreventJumper { get; set; }
/// <summary>Current lock status</summary>
public bool LockState { get; set; }
/// <summary>Drive can lock media</summary>
public bool Lock { get; set; }
/// <summary>Each channel can be muted independently</summary>
public bool SeparateChannelMute { get; set; }
/// <summary>Each channel's volume can be controlled independently</summary>
public bool SeparateChannelVolume { get; set; }
/// <summary>Maximum drive speed in Kbytes/second</summary>
public ushort MaximumSpeed { get; set; }
/// <summary>Supported volume levels</summary>
public ushort SupportedVolumeLevels { get; set; }
/// <summary>Buffer size in Kbytes</summary>
public ushort BufferSize { get; set; }
/// <summary>Current drive speed in Kbytes/second</summary>
public ushort CurrentSpeed { get; set; }
/// <summary>Can read packet media</summary>
public bool Method2 { get; set; }
/// <summary>Can read CD-RW</summary>
public bool ReadCDRW { get; set; }
/// <summary>Can read CD-R</summary>
public bool ReadCDR { get; set; }
/// <summary>Can write CD-RW</summary>
public bool WriteCDRW { get; set; }
/// <summary>Can write CD-R</summary>
public bool WriteCDR { get; set; }
/// <summary>Supports IEC-958 digital output on port 2</summary>
public bool DigitalPort2 { get; set; }
/// <summary>Supports IEC-958 digital output on port 1</summary>
public bool DigitalPort1 { get; set; }
/// <summary>Can deliver a composite audio and video data stream</summary>
public bool Composite { get; set; }
/// <summary>This bit controls the behavior of the LOAD/UNLOAD command when trying to load a Slot with no Disc present</summary>
public bool SSS { get; set; }
/// <summary>Contains a changer that can report the exact contents of the slots</summary>
public bool SDP { get; set; }
/// <summary>Page length</summary>
public byte Length { get; set; }
/// <summary>Set if LSB comes first</summary>
public bool LSBF { get; set; }
/// <summary>Set if HIGH on LRCK indicates left channel. Clear if HIGH on LRCK indicates right channel.</summary>
public bool RCK { get; set; }
/// <summary>
/// CD-ROM capabilities page Page code 0x2A 16 bytes in OB-U0077C 20 bytes in SFF-8020i 22 bytes in MMC-1 26 bytes
/// in MMC-2 Variable bytes in MMC-3
/// Set if data valid on the falling edge of the BCK signal. Clear if data valid on the rising edge of the BCK
/// signal
/// </summary>
[SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"),
SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")]
public class ModePage_2A
public bool BCK { get; set; }
/// <summary>Can do a test write</summary>
public bool TestWrite { get; set; }
/// <summary>Maximum write speed</summary>
public ushort MaxWriteSpeed { get; set; }
/// <summary>Current write speed</summary>
public ushort CurrentWriteSpeed { get; set; }
/// <summary>Can read disc's barcode</summary>
public bool ReadBarcode { get; set; }
/// <summary>Can read DVD-RAM</summary>
public bool ReadDVDRAM { get; set; }
/// <summary>Can read DVD-R</summary>
public bool ReadDVDR { get; set; }
/// <summary>Can read DVD-ROM</summary>
public bool ReadDVDROM { get; set; }
/// <summary>Can write DVD-RAM</summary>
public bool WriteDVDRAM { get; set; }
/// <summary>Can write DVD-R</summary>
public bool WriteDVDR { get; set; }
/// <summary>Can read raw R-W subchannel from the Lead-In</summary>
public bool LeadInPW { get; set; }
/// <summary>Can read both sides of a disc</summary>
public bool SCC { get; set; }
/// <summary>Support copyright management</summary>
public ushort CMRSupported { get; set; }
/// <summary>Supports buffer under-run free recording</summary>
public bool BUF { get; set; }
/// <summary>Selected rotational control</summary>
public byte RotationControlSelected { get; set; }
/// <summary>Current write speed selected</summary>
public ushort CurrentWriteSpeedSelected { get; set; }
/// <summary>Database ID</summary>
[JsonIgnore, Key]
public int Id { get; set; }
/// <summary>Decodes the page 2Ah of a MODE SENSE response</summary>
/// <param name="pageResponse">Raw page 2Ah</param>
/// <returns>Decoded page 2Ah</returns>
public static ModePage_2A Decode(byte[] pageResponse)
{
/// <summary>Write speed performance descriptors</summary>
public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors;
/// <summary>Parameters can be saved</summary>
public bool PS { get; set; }
/// <summary>Drive supports multi-session and/or Photo-CD</summary>
public bool MultiSession { get; set; }
/// <summary>Drive is capable of reading sectors in Mode 2 Form 2 format</summary>
public bool Mode2Form2 { get; set; }
/// <summary>Drive is capable of reading sectors in Mode 2 Form 1 format</summary>
public bool Mode2Form1 { get; set; }
/// <summary>Drive is capable of playing audio</summary>
public bool AudioPlay { get; set; }
/// <summary>Drive can return the ISRC</summary>
public bool ISRC { get; set; }
/// <summary>Drive can return the media catalogue number</summary>
public bool UPC { get; set; }
/// <summary>Drive can return C2 pointers</summary>
public bool C2Pointer { get; set; }
/// <summary>Drive can read, deinterlave and correct R-W subchannels</summary>
public bool DeinterlaveSubchannel { get; set; }
/// <summary>Drive can read interleaved and uncorrected R-W subchannels</summary>
public bool Subchannel { get; set; }
/// <summary>Drive can continue from a loss of streaming on audio reading</summary>
public bool AccurateCDDA { get; set; }
/// <summary>Audio can be read as digital data</summary>
public bool CDDACommand { get; set; }
/// <summary>Loading Mechanism Type</summary>
public byte LoadingMechanism { get; set; }
/// <summary>Drive can eject discs</summary>
public bool Eject { get; set; }
/// <summary>Drive's optional prevent jumper status</summary>
public bool PreventJumper { get; set; }
/// <summary>Current lock status</summary>
public bool LockState { get; set; }
/// <summary>Drive can lock media</summary>
public bool Lock { get; set; }
/// <summary>Each channel can be muted independently</summary>
public bool SeparateChannelMute { get; set; }
/// <summary>Each channel's volume can be controlled independently</summary>
public bool SeparateChannelVolume { get; set; }
/// <summary>Maximum drive speed in Kbytes/second</summary>
public ushort MaximumSpeed { get; set; }
/// <summary>Supported volume levels</summary>
public ushort SupportedVolumeLevels { get; set; }
/// <summary>Buffer size in Kbytes</summary>
public ushort BufferSize { get; set; }
/// <summary>Current drive speed in Kbytes/second</summary>
public ushort CurrentSpeed { get; set; }
if((pageResponse?[0] & 0x40) == 0x40)
return null;
/// <summary>Can read packet media</summary>
public bool Method2 { get; set; }
/// <summary>Can read CD-RW</summary>
public bool ReadCDRW { get; set; }
/// <summary>Can read CD-R</summary>
public bool ReadCDR { get; set; }
/// <summary>Can write CD-RW</summary>
public bool WriteCDRW { get; set; }
/// <summary>Can write CD-R</summary>
public bool WriteCDR { get; set; }
/// <summary>Supports IEC-958 digital output on port 2</summary>
public bool DigitalPort2 { get; set; }
/// <summary>Supports IEC-958 digital output on port 1</summary>
public bool DigitalPort1 { get; set; }
/// <summary>Can deliver a composite audio and video data stream</summary>
public bool Composite { get; set; }
/// <summary>This bit controls the behavior of the LOAD/UNLOAD command when trying to load a Slot with no Disc present</summary>
public bool SSS { get; set; }
/// <summary>Contains a changer that can report the exact contents of the slots</summary>
public bool SDP { get; set; }
/// <summary>Page length</summary>
public byte Length { get; set; }
/// <summary>Set if LSB comes first</summary>
public bool LSBF { get; set; }
/// <summary>Set if HIGH on LRCK indicates left channel. Clear if HIGH on LRCK indicates right channel.</summary>
public bool RCK { get; set; }
/// <summary>
/// Set if data valid on the falling edge of the BCK signal. Clear if data valid on the rising edge of the BCK
/// signal
/// </summary>
public bool BCK { get; set; }
if((pageResponse?[0] & 0x3F) != 0x2A)
return null;
/// <summary>Can do a test write</summary>
public bool TestWrite { get; set; }
/// <summary>Maximum write speed</summary>
public ushort MaxWriteSpeed { get; set; }
/// <summary>Current write speed</summary>
public ushort CurrentWriteSpeed { get; set; }
/// <summary>Can read disc's barcode</summary>
public bool ReadBarcode { get; set; }
/// <summary>Can read DVD-RAM</summary>
public bool ReadDVDRAM { get; set; }
/// <summary>Can read DVD-R</summary>
public bool ReadDVDR { get; set; }
/// <summary>Can read DVD-ROM</summary>
public bool ReadDVDROM { get; set; }
/// <summary>Can write DVD-RAM</summary>
public bool WriteDVDRAM { get; set; }
/// <summary>Can write DVD-R</summary>
public bool WriteDVDR { get; set; }
/// <summary>Can read raw R-W subchannel from the Lead-In</summary>
public bool LeadInPW { get; set; }
/// <summary>Can read both sides of a disc</summary>
public bool SCC { get; set; }
/// <summary>Support copyright management</summary>
public ushort CMRSupported { get; set; }
/// <summary>Supports buffer under-run free recording</summary>
public bool BUF { get; set; }
/// <summary>Selected rotational control</summary>
public byte RotationControlSelected { get; set; }
/// <summary>Current write speed selected</summary>
public ushort CurrentWriteSpeedSelected { get; set; }
if(pageResponse[1] + 2 != pageResponse.Length)
return null;
/// <summary>Database ID</summary>
[JsonIgnore, Key]
public int Id { get; set; }
if(pageResponse.Length < 16)
return null;
/// <summary>Decodes the page 2Ah of a MODE SENSE response</summary>
/// <param name="pageResponse">Raw page 2Ah</param>
/// <returns>Decoded page 2Ah</returns>
public static ModePage_2A Decode(byte[] pageResponse)
{
if((pageResponse?[0] & 0x40) == 0x40)
return null;
var decoded = new ModePage_2A();
if((pageResponse?[0] & 0x3F) != 0x2A)
return null;
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
if(pageResponse[1] + 2 != pageResponse.Length)
return null;
decoded.AudioPlay |= (pageResponse[4] & 0x01) == 0x01;
decoded.Mode2Form1 |= (pageResponse[4] & 0x10) == 0x10;
decoded.Mode2Form2 |= (pageResponse[4] & 0x20) == 0x20;
decoded.MultiSession |= (pageResponse[4] & 0x40) == 0x40;
if(pageResponse.Length < 16)
return null;
decoded.CDDACommand |= (pageResponse[5] & 0x01) == 0x01;
decoded.AccurateCDDA |= (pageResponse[5] & 0x02) == 0x02;
decoded.Subchannel |= (pageResponse[5] & 0x04) == 0x04;
decoded.DeinterlaveSubchannel |= (pageResponse[5] & 0x08) == 0x08;
decoded.C2Pointer |= (pageResponse[5] & 0x10) == 0x10;
decoded.UPC |= (pageResponse[5] & 0x20) == 0x20;
decoded.ISRC |= (pageResponse[5] & 0x40) == 0x40;
var decoded = new ModePage_2A();
decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5);
decoded.Lock |= (pageResponse[6] & 0x01) == 0x01;
decoded.LockState |= (pageResponse[6] & 0x02) == 0x02;
decoded.PreventJumper |= (pageResponse[6] & 0x04) == 0x04;
decoded.Eject |= (pageResponse[6] & 0x08) == 0x08;
decoded.PS |= (pageResponse[0] & 0x80) == 0x80;
decoded.SeparateChannelVolume |= (pageResponse[7] & 0x01) == 0x01;
decoded.SeparateChannelMute |= (pageResponse[7] & 0x02) == 0x02;
decoded.AudioPlay |= (pageResponse[4] & 0x01) == 0x01;
decoded.Mode2Form1 |= (pageResponse[4] & 0x10) == 0x10;
decoded.Mode2Form2 |= (pageResponse[4] & 0x20) == 0x20;
decoded.MultiSession |= (pageResponse[4] & 0x40) == 0x40;
decoded.CDDACommand |= (pageResponse[5] & 0x01) == 0x01;
decoded.AccurateCDDA |= (pageResponse[5] & 0x02) == 0x02;
decoded.Subchannel |= (pageResponse[5] & 0x04) == 0x04;
decoded.DeinterlaveSubchannel |= (pageResponse[5] & 0x08) == 0x08;
decoded.C2Pointer |= (pageResponse[5] & 0x10) == 0x10;
decoded.UPC |= (pageResponse[5] & 0x20) == 0x20;
decoded.ISRC |= (pageResponse[5] & 0x40) == 0x40;
decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5);
decoded.Lock |= (pageResponse[6] & 0x01) == 0x01;
decoded.LockState |= (pageResponse[6] & 0x02) == 0x02;
decoded.PreventJumper |= (pageResponse[6] & 0x04) == 0x04;
decoded.Eject |= (pageResponse[6] & 0x08) == 0x08;
decoded.SeparateChannelVolume |= (pageResponse[7] & 0x01) == 0x01;
decoded.SeparateChannelMute |= (pageResponse[7] & 0x02) == 0x02;
decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
if(pageResponse.Length < 20)
return decoded;
decoded.Method2 |= (pageResponse[2] & 0x04) == 0x04;
decoded.ReadCDRW |= (pageResponse[2] & 0x02) == 0x02;
decoded.ReadCDR |= (pageResponse[2] & 0x01) == 0x01;
decoded.WriteCDRW |= (pageResponse[3] & 0x02) == 0x02;
decoded.WriteCDR |= (pageResponse[3] & 0x01) == 0x01;
decoded.Composite |= (pageResponse[4] & 0x02) == 0x02;
decoded.DigitalPort1 |= (pageResponse[4] & 0x04) == 0x04;
decoded.DigitalPort2 |= (pageResponse[4] & 0x08) == 0x08;
decoded.SDP |= (pageResponse[7] & 0x04) == 0x04;
decoded.SSS |= (pageResponse[7] & 0x08) == 0x08;
decoded.Length = (byte)((pageResponse[17] & 0x30) >> 4);
decoded.LSBF |= (pageResponse[17] & 0x08) == 0x08;
decoded.RCK |= (pageResponse[17] & 0x04) == 0x04;
decoded.BCK |= (pageResponse[17] & 0x02) == 0x02;
if(pageResponse.Length < 22)
return decoded;
decoded.TestWrite |= (pageResponse[3] & 0x04) == 0x04;
decoded.MaxWriteSpeed = (ushort)((pageResponse[18] << 8) + pageResponse[19]);
decoded.CurrentWriteSpeed = (ushort)((pageResponse[20] << 8) + pageResponse[21]);
decoded.ReadBarcode |= (pageResponse[5] & 0x80) == 0x80;
if(pageResponse.Length < 26)
return decoded;
decoded.ReadDVDRAM |= (pageResponse[2] & 0x20) == 0x20;
decoded.ReadDVDR |= (pageResponse[2] & 0x10) == 0x10;
decoded.ReadDVDROM |= (pageResponse[2] & 0x08) == 0x08;
decoded.WriteDVDRAM |= (pageResponse[3] & 0x20) == 0x20;
decoded.WriteDVDR |= (pageResponse[3] & 0x10) == 0x10;
decoded.LeadInPW |= (pageResponse[3] & 0x20) == 0x20;
decoded.SCC |= (pageResponse[3] & 0x10) == 0x10;
decoded.CMRSupported = (ushort)((pageResponse[22] << 8) + pageResponse[23]);
if(pageResponse.Length < 32)
return decoded;
decoded.BUF |= (pageResponse[4] & 0x80) == 0x80;
decoded.RotationControlSelected = (byte)(pageResponse[27] & 0x03);
decoded.CurrentWriteSpeedSelected = (ushort)((pageResponse[28] << 8) + pageResponse[29]);
ushort descriptors = (ushort)((pageResponse.Length - 32) / 4);
decoded.WriteSpeedPerformanceDescriptors = new ModePage_2A_WriteDescriptor[descriptors];
for(int i = 0; i < descriptors; i++)
decoded.WriteSpeedPerformanceDescriptors[i] = new ModePage_2A_WriteDescriptor
{
RotationControl = (byte)(pageResponse[1 + 32 + (i * 4)] & 0x07),
WriteSpeed = (ushort)((pageResponse[2 + 32 + (i * 4)] << 8) + pageResponse[3 + 32 + (i * 4)])
};
decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
if(pageResponse.Length < 20)
return decoded;
}
/// <summary>Encodes a page 2Ah of a MODE SENSE response</summary>
/// <param name="decoded">Decoded page 2Ah</param>
/// <returns>Raw page 2Ah</returns>
public static byte[] Encode(ModePage_2A decoded)
{
byte[] pageResponse = new byte[512];
byte length = 16;
decoded.Method2 |= (pageResponse[2] & 0x04) == 0x04;
decoded.ReadCDRW |= (pageResponse[2] & 0x02) == 0x02;
decoded.ReadCDR |= (pageResponse[2] & 0x01) == 0x01;
pageResponse[0] = 0x2A;
decoded.WriteCDRW |= (pageResponse[3] & 0x02) == 0x02;
decoded.WriteCDR |= (pageResponse[3] & 0x01) == 0x01;
if(decoded.PS)
pageResponse[0] += 0x80;
decoded.Composite |= (pageResponse[4] & 0x02) == 0x02;
decoded.DigitalPort1 |= (pageResponse[4] & 0x04) == 0x04;
decoded.DigitalPort2 |= (pageResponse[4] & 0x08) == 0x08;
if(decoded.AudioPlay)
pageResponse[4] += 0x01;
decoded.SDP |= (pageResponse[7] & 0x04) == 0x04;
decoded.SSS |= (pageResponse[7] & 0x08) == 0x08;
if(decoded.Mode2Form1)
pageResponse[4] += 0x10;
decoded.Length = (byte)((pageResponse[17] & 0x30) >> 4);
decoded.LSBF |= (pageResponse[17] & 0x08) == 0x08;
decoded.RCK |= (pageResponse[17] & 0x04) == 0x04;
decoded.BCK |= (pageResponse[17] & 0x02) == 0x02;
if(decoded.Mode2Form2)
pageResponse[4] += 0x20;
if(pageResponse.Length < 22)
return decoded;
if(decoded.MultiSession)
pageResponse[4] += 0x40;
decoded.TestWrite |= (pageResponse[3] & 0x04) == 0x04;
decoded.MaxWriteSpeed = (ushort)((pageResponse[18] << 8) + pageResponse[19]);
decoded.CurrentWriteSpeed = (ushort)((pageResponse[20] << 8) + pageResponse[21]);
if(decoded.CDDACommand)
pageResponse[5] += 0x01;
decoded.ReadBarcode |= (pageResponse[5] & 0x80) == 0x80;
if(decoded.AccurateCDDA)
pageResponse[5] += 0x02;
if(pageResponse.Length < 26)
return decoded;
if(decoded.Subchannel)
pageResponse[5] += 0x04;
decoded.ReadDVDRAM |= (pageResponse[2] & 0x20) == 0x20;
decoded.ReadDVDR |= (pageResponse[2] & 0x10) == 0x10;
decoded.ReadDVDROM |= (pageResponse[2] & 0x08) == 0x08;
if(decoded.DeinterlaveSubchannel)
pageResponse[5] += 0x08;
decoded.WriteDVDRAM |= (pageResponse[3] & 0x20) == 0x20;
decoded.WriteDVDR |= (pageResponse[3] & 0x10) == 0x10;
if(decoded.C2Pointer)
pageResponse[5] += 0x10;
decoded.LeadInPW |= (pageResponse[3] & 0x20) == 0x20;
decoded.SCC |= (pageResponse[3] & 0x10) == 0x10;
if(decoded.UPC)
pageResponse[5] += 0x20;
decoded.CMRSupported = (ushort)((pageResponse[22] << 8) + pageResponse[23]);
if(decoded.ISRC)
pageResponse[5] += 0x40;
if(pageResponse.Length < 32)
return decoded;
decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5);
decoded.BUF |= (pageResponse[4] & 0x80) == 0x80;
decoded.RotationControlSelected = (byte)(pageResponse[27] & 0x03);
decoded.CurrentWriteSpeedSelected = (ushort)((pageResponse[28] << 8) + pageResponse[29]);
if(decoded.Lock)
pageResponse[6] += 0x01;
ushort descriptors = (ushort)((pageResponse.Length - 32) / 4);
decoded.WriteSpeedPerformanceDescriptors = new ModePage_2A_WriteDescriptor[descriptors];
if(decoded.LockState)
pageResponse[6] += 0x02;
if(decoded.PreventJumper)
pageResponse[6] += 0x04;
if(decoded.Eject)
pageResponse[6] += 0x08;
if(decoded.SeparateChannelVolume)
pageResponse[7] += 0x01;
if(decoded.SeparateChannelMute)
pageResponse[7] += 0x02;
decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
if(decoded.Method2 ||
decoded.ReadCDRW ||
decoded.ReadCDR ||
decoded.WriteCDRW ||
decoded.WriteCDR ||
decoded.Composite ||
decoded.DigitalPort1 ||
decoded.DigitalPort2 ||
decoded.SDP ||
decoded.SSS ||
decoded.Length > 0 ||
decoded.LSBF ||
decoded.RCK ||
decoded.BCK)
for(int i = 0; i < descriptors; i++)
decoded.WriteSpeedPerformanceDescriptors[i] = new ModePage_2A_WriteDescriptor
{
length = 20;
RotationControl = (byte)(pageResponse[1 + 32 + (i * 4)] & 0x07),
WriteSpeed = (ushort)((pageResponse[2 + 32 + (i * 4)] << 8) + pageResponse[3 + 32 + (i * 4)])
};
if(decoded.Method2)
pageResponse[2] += 0x04;
if(decoded.ReadCDRW)
pageResponse[2] += 0x02;
if(decoded.ReadCDR)
pageResponse[2] += 0x01;
if(decoded.WriteCDRW)
pageResponse[3] += 0x02;
if(decoded.WriteCDR)
pageResponse[3] += 0x01;
if(decoded.Composite)
pageResponse[4] += 0x02;
if(decoded.DigitalPort1)
pageResponse[4] += 0x04;
if(decoded.DigitalPort2)
pageResponse[4] += 0x08;
if(decoded.SDP)
pageResponse[7] += 0x04;
if(decoded.SSS)
pageResponse[7] += 0x08;
pageResponse[17] = (byte)(decoded.Length << 4);
if(decoded.LSBF)
pageResponse[17] += 0x08;
if(decoded.RCK)
pageResponse[17] += 0x04;
if(decoded.BCK)
pageResponse[17] += 0x02;
}
if(decoded.TestWrite ||
decoded.MaxWriteSpeed > 0 ||
decoded.CurrentWriteSpeed > 0 ||
decoded.ReadBarcode)
{
length = 22;
if(decoded.TestWrite)
pageResponse[3] += 0x04;
pageResponse[18] = (byte)((decoded.MaxWriteSpeed & 0xFF00) >> 8);
pageResponse[19] = (byte)(decoded.MaxWriteSpeed & 0xFF);
pageResponse[20] = (byte)((decoded.CurrentWriteSpeed & 0xFF00) >> 8);
pageResponse[21] = (byte)(decoded.CurrentWriteSpeed & 0xFF);
if(decoded.ReadBarcode)
pageResponse[5] += 0x80;
}
if(decoded.ReadDVDRAM ||
decoded.ReadDVDR ||
decoded.ReadDVDROM ||
decoded.WriteDVDRAM ||
decoded.WriteDVDR ||
decoded.LeadInPW ||
decoded.SCC ||
decoded.CMRSupported > 0)
{
length = 26;
if(decoded.ReadDVDRAM)
pageResponse[2] += 0x20;
if(decoded.ReadDVDR)
pageResponse[2] += 0x10;
if(decoded.ReadDVDROM)
pageResponse[2] += 0x08;
if(decoded.WriteDVDRAM)
pageResponse[3] += 0x20;
if(decoded.WriteDVDR)
pageResponse[3] += 0x10;
if(decoded.LeadInPW)
pageResponse[3] += 0x20;
if(decoded.SCC)
pageResponse[3] += 0x10;
pageResponse[22] = (byte)((decoded.CMRSupported & 0xFF00) >> 8);
pageResponse[23] = (byte)(decoded.CMRSupported & 0xFF);
}
if(decoded.BUF ||
decoded.RotationControlSelected > 0 ||
decoded.CurrentWriteSpeedSelected > 0)
{
length = 32;
if(decoded.BUF)
pageResponse[4] += 0x80;
pageResponse[27] += decoded.RotationControlSelected;
pageResponse[28] = (byte)((decoded.CurrentWriteSpeedSelected & 0xFF00) >> 8);
pageResponse[29] = (byte)(decoded.CurrentWriteSpeedSelected & 0xFF);
}
if(decoded.WriteSpeedPerformanceDescriptors != null)
{
length = 32;
for(int i = 0; i < decoded.WriteSpeedPerformanceDescriptors.Length; i++)
{
length += 4;
pageResponse[1 + 32 + (i * 4)] = decoded.WriteSpeedPerformanceDescriptors[i].RotationControl;
pageResponse[2 + 32 + (i * 4)] =
(byte)((decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF00) >> 8);
pageResponse[3 + 32 + (i * 4)] =
(byte)(decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF);
}
}
pageResponse[1] = (byte)(length - 2);
byte[] buf = new byte[length];
Array.Copy(pageResponse, 0, buf, 0, length);
return buf;
}
return decoded;
}
/// <summary>Page 2Ah write descriptor</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public struct ModePage_2A_WriteDescriptor
/// <summary>Encodes a page 2Ah of a MODE SENSE response</summary>
/// <param name="decoded">Decoded page 2Ah</param>
/// <returns>Raw page 2Ah</returns>
public static byte[] Encode(ModePage_2A decoded)
{
/// <summary>Rotational control</summary>
public byte RotationControl;
/// <summary>Write speed</summary>
public ushort WriteSpeed;
byte[] pageResponse = new byte[512];
byte length = 16;
pageResponse[0] = 0x2A;
if(decoded.PS)
pageResponse[0] += 0x80;
if(decoded.AudioPlay)
pageResponse[4] += 0x01;
if(decoded.Mode2Form1)
pageResponse[4] += 0x10;
if(decoded.Mode2Form2)
pageResponse[4] += 0x20;
if(decoded.MultiSession)
pageResponse[4] += 0x40;
if(decoded.CDDACommand)
pageResponse[5] += 0x01;
if(decoded.AccurateCDDA)
pageResponse[5] += 0x02;
if(decoded.Subchannel)
pageResponse[5] += 0x04;
if(decoded.DeinterlaveSubchannel)
pageResponse[5] += 0x08;
if(decoded.C2Pointer)
pageResponse[5] += 0x10;
if(decoded.UPC)
pageResponse[5] += 0x20;
if(decoded.ISRC)
pageResponse[5] += 0x40;
decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5);
if(decoded.Lock)
pageResponse[6] += 0x01;
if(decoded.LockState)
pageResponse[6] += 0x02;
if(decoded.PreventJumper)
pageResponse[6] += 0x04;
if(decoded.Eject)
pageResponse[6] += 0x08;
if(decoded.SeparateChannelVolume)
pageResponse[7] += 0x01;
if(decoded.SeparateChannelMute)
pageResponse[7] += 0x02;
decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]);
decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]);
decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]);
decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]);
if(decoded.Method2 ||
decoded.ReadCDRW ||
decoded.ReadCDR ||
decoded.WriteCDRW ||
decoded.WriteCDR ||
decoded.Composite ||
decoded.DigitalPort1 ||
decoded.DigitalPort2 ||
decoded.SDP ||
decoded.SSS ||
decoded.Length > 0 ||
decoded.LSBF ||
decoded.RCK ||
decoded.BCK)
{
length = 20;
if(decoded.Method2)
pageResponse[2] += 0x04;
if(decoded.ReadCDRW)
pageResponse[2] += 0x02;
if(decoded.ReadCDR)
pageResponse[2] += 0x01;
if(decoded.WriteCDRW)
pageResponse[3] += 0x02;
if(decoded.WriteCDR)
pageResponse[3] += 0x01;
if(decoded.Composite)
pageResponse[4] += 0x02;
if(decoded.DigitalPort1)
pageResponse[4] += 0x04;
if(decoded.DigitalPort2)
pageResponse[4] += 0x08;
if(decoded.SDP)
pageResponse[7] += 0x04;
if(decoded.SSS)
pageResponse[7] += 0x08;
pageResponse[17] = (byte)(decoded.Length << 4);
if(decoded.LSBF)
pageResponse[17] += 0x08;
if(decoded.RCK)
pageResponse[17] += 0x04;
if(decoded.BCK)
pageResponse[17] += 0x02;
}
if(decoded.TestWrite ||
decoded.MaxWriteSpeed > 0 ||
decoded.CurrentWriteSpeed > 0 ||
decoded.ReadBarcode)
{
length = 22;
if(decoded.TestWrite)
pageResponse[3] += 0x04;
pageResponse[18] = (byte)((decoded.MaxWriteSpeed & 0xFF00) >> 8);
pageResponse[19] = (byte)(decoded.MaxWriteSpeed & 0xFF);
pageResponse[20] = (byte)((decoded.CurrentWriteSpeed & 0xFF00) >> 8);
pageResponse[21] = (byte)(decoded.CurrentWriteSpeed & 0xFF);
if(decoded.ReadBarcode)
pageResponse[5] += 0x80;
}
if(decoded.ReadDVDRAM ||
decoded.ReadDVDR ||
decoded.ReadDVDROM ||
decoded.WriteDVDRAM ||
decoded.WriteDVDR ||
decoded.LeadInPW ||
decoded.SCC ||
decoded.CMRSupported > 0)
{
length = 26;
if(decoded.ReadDVDRAM)
pageResponse[2] += 0x20;
if(decoded.ReadDVDR)
pageResponse[2] += 0x10;
if(decoded.ReadDVDROM)
pageResponse[2] += 0x08;
if(decoded.WriteDVDRAM)
pageResponse[3] += 0x20;
if(decoded.WriteDVDR)
pageResponse[3] += 0x10;
if(decoded.LeadInPW)
pageResponse[3] += 0x20;
if(decoded.SCC)
pageResponse[3] += 0x10;
pageResponse[22] = (byte)((decoded.CMRSupported & 0xFF00) >> 8);
pageResponse[23] = (byte)(decoded.CMRSupported & 0xFF);
}
if(decoded.BUF ||
decoded.RotationControlSelected > 0 ||
decoded.CurrentWriteSpeedSelected > 0)
{
length = 32;
if(decoded.BUF)
pageResponse[4] += 0x80;
pageResponse[27] += decoded.RotationControlSelected;
pageResponse[28] = (byte)((decoded.CurrentWriteSpeedSelected & 0xFF00) >> 8);
pageResponse[29] = (byte)(decoded.CurrentWriteSpeedSelected & 0xFF);
}
if(decoded.WriteSpeedPerformanceDescriptors != null)
{
length = 32;
for(int i = 0; i < decoded.WriteSpeedPerformanceDescriptors.Length; i++)
{
length += 4;
pageResponse[1 + 32 + (i * 4)] = decoded.WriteSpeedPerformanceDescriptors[i].RotationControl;
pageResponse[2 + 32 + (i * 4)] =
(byte)((decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF00) >> 8);
pageResponse[3 + 32 + (i * 4)] =
(byte)(decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF);
}
}
pageResponse[1] = (byte)(length - 2);
byte[] buf = new byte[length];
Array.Copy(pageResponse, 0, buf, 0, length);
return buf;
}
#endregion Mode Page 0x2A: CD-ROM capabilities page
}
}
/// <summary>Page 2Ah write descriptor</summary>
[SuppressMessage("ReSharper", "InconsistentNaming")]
public struct ModePage_2A_WriteDescriptor
{
/// <summary>Rotational control</summary>
public byte RotationControl;
/// <summary>Write speed</summary>
public ushort WriteSpeed;
}
#endregion Mode Page 0x2A: CD-ROM capabilities page

View File

@@ -41,241 +41,240 @@ using System;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
namespace Aaru.CommonTypes.Structs
namespace Aaru.CommonTypes.Structs;
/// <summary>File attributes.</summary>
[Flags]
public enum FileAttributes : ulong
{
/// <summary>File attributes.</summary>
[Flags]
public enum FileAttributes : ulong
/// <summary>File has no attributes</summary>
None = 0,
/// <summary>File is an alias (Mac OS)</summary>
Alias = 0x01,
/// <summary>Indicates that the file can only be writable appended</summary>
AppendOnly = 0x02,
/// <summary>File is candidate for archival/backup</summary>
Archive = 0x04,
/// <summary>File is a block device</summary>
BlockDevice = 0x08,
/// <summary>File is stored on filesystem block units instead of device sectors</summary>
BlockUnits = 0x10,
/// <summary>Directory is a bundle or file contains a BNDL resource</summary>
Bundle = 0x20,
/// <summary>File is a char device</summary>
CharDevice = 0x40,
/// <summary>File is compressed</summary>
Compressed = 0x80,
/// <summary>File is compressed and should not be uncompressed on read</summary>
CompressedRaw = 0x100,
/// <summary>File has compression errors</summary>
CompressionError = 0x200,
/// <summary>Compressed file is dirty</summary>
CompressionDirty = 0x400,
/// <summary>File is a device</summary>
Device = 0x800,
/// <summary>File is a directory</summary>
Directory = 0x1000,
/// <summary>File is encrypted</summary>
Encrypted = 0x2000,
/// <summary>File is stored on disk using extents</summary>
Extents = 0x4000,
/// <summary>File is a FIFO</summary>
FIFO = 0x8000,
/// <summary>File is a normal file</summary>
File = 0x10000,
/// <summary>File is a Mac OS file containing desktop databases that has already been added to the desktop database</summary>
HasBeenInited = 0x20000,
/// <summary>File contains an icon resource / EA</summary>
HasCustomIcon = 0x40000,
/// <summary>File is a Mac OS extension or control panel lacking INIT resources</summary>
HasNoINITs = 0x80000,
/// <summary>File is hidden/invisible</summary>
Hidden = 0x100000,
/// <summary>File cannot be written, deleted, modified or linked to</summary>
Immutable = 0x200000,
/// <summary>Directory is indexed using hashed trees</summary>
IndexedDirectory = 0x400000,
/// <summary>File contents are stored alongside its inode (or equivalent)</summary>
Inline = 0x800000,
/// <summary>File contains integrity checks</summary>
IntegrityStream = 0x1000000,
/// <summary>File is on desktop</summary>
IsOnDesk = 0x2000000,
/// <summary>File changes are written to filesystem journal before being written to file itself</summary>
Journaled = 0x4000000,
/// <summary>Access time will not be modified</summary>
NoAccessTime = 0x8000000,
/// <summary>File will not be subject to copy-on-write</summary>
NoCopyOnWrite = 0x10000000,
/// <summary>File will not be backed up</summary>
NoDump = 0x20000000,
/// <summary>File contents should not be scrubbed</summary>
NoScrub = 0x40000000,
/// <summary>File contents should not be indexed</summary>
NotIndexed = 0x80000000,
/// <summary>File is offline</summary>
Offline = 0x100000000,
/// <summary>File is password protected, but contents are not encrypted on disk</summary>
Password = 0x200000000,
/// <summary>File is read-only</summary>
ReadOnly = 0x400000000,
/// <summary>File is a reparse point</summary>
ReparsePoint = 0x800000000,
/// <summary>When file is removed its content will be overwritten with zeroes</summary>
Secured = 0x1000000000,
/// <summary>File contents are sparse</summary>
Sparse = 0x2000000000,
/// <summary>File is a shadow (OS/2)</summary>
Shadow = 0x4000000000,
/// <summary>File is shared</summary>
Shared = 0x8000000000,
/// <summary>File is a stationery</summary>
Stationery = 0x10000000000,
/// <summary>File is a symbolic link</summary>
Symlink = 0x20000000000,
/// <summary>File writes are synchronously written to disk</summary>
Sync = 0x40000000000,
/// <summary>File belongs to the operating system</summary>
System = 0x80000000000,
/// <summary>If file end is a partial block its content will be merged with other files</summary>
TailMerged = 0x100000000000,
/// <summary>File is temporary</summary>
Temporary = 0x200000000000,
/// <summary>Subdirectories inside of this directory are not related and should be allocated elsewhere</summary>
TopDirectory = 0x400000000000,
/// <summary>If file is deleted, contents should be stored, for a possible future undeletion</summary>
Undeletable = 0x800000000000,
/// <summary>File is a pipe</summary>
Pipe = 0x1000000000000,
/// <summary>File is a socket</summary>
Socket = 0x2000000000000
}
/// <summary>Information about a file entry</summary>
public class FileEntryInfo
{
/// <summary>File attributes</summary>
public FileAttributes Attributes { get; set; }
/// <summary>File length in blocks</summary>
public long Blocks { get; set; }
/// <summary>File block size in bytes</summary>
public long BlockSize { get; set; }
/// <summary>If file points to a device, device number. Null if the underlying filesystem does not support them.</summary>
public ulong? DeviceNo { get; set; }
/// <summary>POSIX group ID. Null if the underlying filesystem does not support them.</summary>
public ulong? GID { get; set; }
/// <summary>inode number for this file (or other unique identifier for the volume)</summary>
public ulong Inode { get; set; }
/// <summary>File length in bytes</summary>
public long Length { get; set; }
/// <summary>Number of hard links pointing to this file (. and .. entries count as hard links)</summary>
public ulong Links { get; set; }
/// <summary>POSIX permissions/mode for this file. Null if the underlying filesystem does not support them.</summary>
public uint? Mode { get; set; }
/// <summary>POSIX owner ID. Null if the underlying filesystem does not support them.</summary>
public ulong? UID { get; set; }
/// <summary>File creation date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? CreationTimeUtc { get; set; }
/// <summary>File last access date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? AccessTimeUtc { get; set; }
/// <summary>File attributes change date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? StatusChangeTimeUtc { get; set; }
/// <summary>File last backup date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? BackupTimeUtc { get; set; }
/// <summary>File last modification date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? LastWriteTimeUtc { get; set; }
/// <summary>File creation date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? CreationTime
{
/// <summary>File has no attributes</summary>
None = 0,
/// <summary>File is an alias (Mac OS)</summary>
Alias = 0x01,
/// <summary>Indicates that the file can only be writable appended</summary>
AppendOnly = 0x02,
/// <summary>File is candidate for archival/backup</summary>
Archive = 0x04,
/// <summary>File is a block device</summary>
BlockDevice = 0x08,
/// <summary>File is stored on filesystem block units instead of device sectors</summary>
BlockUnits = 0x10,
/// <summary>Directory is a bundle or file contains a BNDL resource</summary>
Bundle = 0x20,
/// <summary>File is a char device</summary>
CharDevice = 0x40,
/// <summary>File is compressed</summary>
Compressed = 0x80,
/// <summary>File is compressed and should not be uncompressed on read</summary>
CompressedRaw = 0x100,
/// <summary>File has compression errors</summary>
CompressionError = 0x200,
/// <summary>Compressed file is dirty</summary>
CompressionDirty = 0x400,
/// <summary>File is a device</summary>
Device = 0x800,
/// <summary>File is a directory</summary>
Directory = 0x1000,
/// <summary>File is encrypted</summary>
Encrypted = 0x2000,
/// <summary>File is stored on disk using extents</summary>
Extents = 0x4000,
/// <summary>File is a FIFO</summary>
FIFO = 0x8000,
/// <summary>File is a normal file</summary>
File = 0x10000,
/// <summary>File is a Mac OS file containing desktop databases that has already been added to the desktop database</summary>
HasBeenInited = 0x20000,
/// <summary>File contains an icon resource / EA</summary>
HasCustomIcon = 0x40000,
/// <summary>File is a Mac OS extension or control panel lacking INIT resources</summary>
HasNoINITs = 0x80000,
/// <summary>File is hidden/invisible</summary>
Hidden = 0x100000,
/// <summary>File cannot be written, deleted, modified or linked to</summary>
Immutable = 0x200000,
/// <summary>Directory is indexed using hashed trees</summary>
IndexedDirectory = 0x400000,
/// <summary>File contents are stored alongside its inode (or equivalent)</summary>
Inline = 0x800000,
/// <summary>File contains integrity checks</summary>
IntegrityStream = 0x1000000,
/// <summary>File is on desktop</summary>
IsOnDesk = 0x2000000,
/// <summary>File changes are written to filesystem journal before being written to file itself</summary>
Journaled = 0x4000000,
/// <summary>Access time will not be modified</summary>
NoAccessTime = 0x8000000,
/// <summary>File will not be subject to copy-on-write</summary>
NoCopyOnWrite = 0x10000000,
/// <summary>File will not be backed up</summary>
NoDump = 0x20000000,
/// <summary>File contents should not be scrubbed</summary>
NoScrub = 0x40000000,
/// <summary>File contents should not be indexed</summary>
NotIndexed = 0x80000000,
/// <summary>File is offline</summary>
Offline = 0x100000000,
/// <summary>File is password protected, but contents are not encrypted on disk</summary>
Password = 0x200000000,
/// <summary>File is read-only</summary>
ReadOnly = 0x400000000,
/// <summary>File is a reparse point</summary>
ReparsePoint = 0x800000000,
/// <summary>When file is removed its content will be overwritten with zeroes</summary>
Secured = 0x1000000000,
/// <summary>File contents are sparse</summary>
Sparse = 0x2000000000,
/// <summary>File is a shadow (OS/2)</summary>
Shadow = 0x4000000000,
/// <summary>File is shared</summary>
Shared = 0x8000000000,
/// <summary>File is a stationery</summary>
Stationery = 0x10000000000,
/// <summary>File is a symbolic link</summary>
Symlink = 0x20000000000,
/// <summary>File writes are synchronously written to disk</summary>
Sync = 0x40000000000,
/// <summary>File belongs to the operating system</summary>
System = 0x80000000000,
/// <summary>If file end is a partial block its content will be merged with other files</summary>
TailMerged = 0x100000000000,
/// <summary>File is temporary</summary>
Temporary = 0x200000000000,
/// <summary>Subdirectories inside of this directory are not related and should be allocated elsewhere</summary>
TopDirectory = 0x400000000000,
/// <summary>If file is deleted, contents should be stored, for a possible future undeletion</summary>
Undeletable = 0x800000000000,
/// <summary>File is a pipe</summary>
Pipe = 0x1000000000000,
/// <summary>File is a socket</summary>
Socket = 0x2000000000000
get => CreationTimeUtc?.ToLocalTime();
set => CreationTimeUtc = value?.ToUniversalTime();
}
/// <summary>Information about a file entry</summary>
public class FileEntryInfo
/// <summary>File last access date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? AccessTime
{
/// <summary>File attributes</summary>
public FileAttributes Attributes { get; set; }
/// <summary>File length in blocks</summary>
public long Blocks { get; set; }
/// <summary>File block size in bytes</summary>
public long BlockSize { get; set; }
/// <summary>If file points to a device, device number. Null if the underlying filesystem does not support them.</summary>
public ulong? DeviceNo { get; set; }
/// <summary>POSIX group ID. Null if the underlying filesystem does not support them.</summary>
public ulong? GID { get; set; }
/// <summary>inode number for this file (or other unique identifier for the volume)</summary>
public ulong Inode { get; set; }
/// <summary>File length in bytes</summary>
public long Length { get; set; }
/// <summary>Number of hard links pointing to this file (. and .. entries count as hard links)</summary>
public ulong Links { get; set; }
/// <summary>POSIX permissions/mode for this file. Null if the underlying filesystem does not support them.</summary>
public uint? Mode { get; set; }
/// <summary>POSIX owner ID. Null if the underlying filesystem does not support them.</summary>
public ulong? UID { get; set; }
/// <summary>File creation date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? CreationTimeUtc { get; set; }
/// <summary>File last access date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? AccessTimeUtc { get; set; }
/// <summary>File attributes change date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? StatusChangeTimeUtc { get; set; }
/// <summary>File last backup date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? BackupTimeUtc { get; set; }
/// <summary>File last modification date in UTC. Null if the underlying filesystem does not support them.</summary>
public DateTime? LastWriteTimeUtc { get; set; }
/// <summary>File creation date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? CreationTime
{
get => CreationTimeUtc?.ToLocalTime();
set => CreationTimeUtc = value?.ToUniversalTime();
}
/// <summary>File last access date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? AccessTime
{
get => AccessTimeUtc?.ToLocalTime();
set => AccessTimeUtc = value?.ToUniversalTime();
}
/// <summary>File attributes change date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? StatusChangeTime
{
get => StatusChangeTimeUtc?.ToLocalTime();
set => StatusChangeTimeUtc = value?.ToUniversalTime();
}
/// <summary>File last backup date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? BackupTime
{
get => BackupTimeUtc?.ToLocalTime();
set => BackupTimeUtc = value?.ToUniversalTime();
}
/// <summary>File last modification date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? LastWriteTime
{
get => LastWriteTimeUtc?.ToLocalTime();
set => LastWriteTimeUtc = value?.ToUniversalTime();
}
get => AccessTimeUtc?.ToLocalTime();
set => AccessTimeUtc = value?.ToUniversalTime();
}
/// <summary>Information about a volume</summary>
public class FileSystemInfo
/// <summary>File attributes change date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? StatusChangeTime
{
/// <summary>Blocks for this filesystem</summary>
public ulong Blocks;
/// <summary>Maximum length of filenames on this filesystem</summary>
public ushort FilenameLength;
/// <summary>Files on this filesystem</summary>
public ulong Files;
/// <summary>Blocks free on this filesystem</summary>
public ulong FreeBlocks;
/// <summary>Free inodes on this filesystem</summary>
public ulong FreeFiles;
/// <summary>Filesystem ID</summary>
public FileSystemId Id;
/// <summary>ID of plugin for this file</summary>
public Guid PluginId;
/// <summary>Filesystem type</summary>
public string Type;
/// <summary>Initializes an empty instance of this structure</summary>
public FileSystemInfo() => Id = new FileSystemId();
/// <summary>Gets a clone of this structure</summary>
/// <returns>Clone of this structure</returns>
public FileSystemInfo ShallowCopy() => (FileSystemInfo)MemberwiseClone();
get => StatusChangeTimeUtc?.ToLocalTime();
set => StatusChangeTimeUtc = value?.ToUniversalTime();
}
/// <summary>Stores a filesystem volume unique identifier or serial number</summary>
[StructLayout(LayoutKind.Explicit)]
public struct FileSystemId
/// <summary>File last backup date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? BackupTime
{
/// <summary>Set to <c>true</c> if the identifier is a 32-bit integer</summary>
[FieldOffset(0)]
public bool IsInt;
/// <summary>Set to <c>true</c> if the identifier is a 64-bit integer</summary>
[FieldOffset(1)]
public bool IsLong;
/// <summary>Set to <c>true</c> if the identifier is a GUID</summary>
[FieldOffset(2)]
public bool IsGuid;
/// <summary>Identifier as a 32-bit integer</summary>
[FieldOffset(3)]
public uint Serial32;
/// <summary>Identifier as a 64-bit integer</summary>
[FieldOffset(3)]
public ulong Serial64;
/// <summary>Identifier as a GUID</summary>
[FieldOffset(3)]
public Guid uuid;
get => BackupTimeUtc?.ToLocalTime();
set => BackupTimeUtc = value?.ToUniversalTime();
}
/// <summary>File last modification date. Null if the underlying filesystem does not support them.</summary>
[JsonIgnore]
public DateTime? LastWriteTime
{
get => LastWriteTimeUtc?.ToLocalTime();
set => LastWriteTimeUtc = value?.ToUniversalTime();
}
}
/// <summary>Information about a volume</summary>
public class FileSystemInfo
{
/// <summary>Blocks for this filesystem</summary>
public ulong Blocks;
/// <summary>Maximum length of filenames on this filesystem</summary>
public ushort FilenameLength;
/// <summary>Files on this filesystem</summary>
public ulong Files;
/// <summary>Blocks free on this filesystem</summary>
public ulong FreeBlocks;
/// <summary>Free inodes on this filesystem</summary>
public ulong FreeFiles;
/// <summary>Filesystem ID</summary>
public FileSystemId Id;
/// <summary>ID of plugin for this file</summary>
public Guid PluginId;
/// <summary>Filesystem type</summary>
public string Type;
/// <summary>Initializes an empty instance of this structure</summary>
public FileSystemInfo() => Id = new FileSystemId();
/// <summary>Gets a clone of this structure</summary>
/// <returns>Clone of this structure</returns>
public FileSystemInfo ShallowCopy() => (FileSystemInfo)MemberwiseClone();
}
/// <summary>Stores a filesystem volume unique identifier or serial number</summary>
[StructLayout(LayoutKind.Explicit)]
public struct FileSystemId
{
/// <summary>Set to <c>true</c> if the identifier is a 32-bit integer</summary>
[FieldOffset(0)]
public bool IsInt;
/// <summary>Set to <c>true</c> if the identifier is a 64-bit integer</summary>
[FieldOffset(1)]
public bool IsLong;
/// <summary>Set to <c>true</c> if the identifier is a GUID</summary>
[FieldOffset(2)]
public bool IsGuid;
/// <summary>Identifier as a 32-bit integer</summary>
[FieldOffset(3)]
public uint Serial32;
/// <summary>Identifier as a 64-bit integer</summary>
[FieldOffset(3)]
public ulong Serial64;
/// <summary>Identifier as a GUID</summary>
[FieldOffset(3)]
public Guid uuid;
}

View File

@@ -36,18 +36,17 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes.Structs
namespace Aaru.CommonTypes.Structs;
/// <summary>Describes a tape file</summary>
public struct TapeFile
{
/// <summary>Describes a tape file</summary>
public struct TapeFile
{
/// <summary>File number</summary>
public uint File;
/// <summary>Partition number</summary>
public byte Partition;
/// <summary>First block, inclusive, of the file</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the file</summary>
public ulong LastBlock;
}
/// <summary>File number</summary>
public uint File;
/// <summary>Partition number</summary>
public byte Partition;
/// <summary>First block, inclusive, of the file</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the file</summary>
public ulong LastBlock;
}

View File

@@ -36,16 +36,15 @@
// Copyright © 2011-2022 Natalia Portillo
// ****************************************************************************/
namespace Aaru.CommonTypes.Structs
namespace Aaru.CommonTypes.Structs;
/// <summary>Describes a tape partition</summary>
public struct TapePartition
{
/// <summary>Describes a tape partition</summary>
public struct TapePartition
{
/// <summary>Partition number</summary>
public byte Number;
/// <summary>First block, inclusive, of the partition</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the partition</summary>
public ulong LastBlock;
}
/// <summary>Partition number</summary>
public byte Number;
/// <summary>First block, inclusive, of the partition</summary>
public ulong FirstBlock;
/// <summary>Last block, inclusive, of the partition</summary>
public ulong LastBlock;
}