mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
General refactor and cleanup.
This commit is contained in:
@@ -49,12 +49,13 @@ public sealed partial class CPM
|
||||
try
|
||||
{
|
||||
_definitions =
|
||||
JsonSerializer.
|
||||
Deserialize(Assembly.GetExecutingAssembly().GetManifestResourceStream("Aaru.Filesystems.CPM.cpmdefs.json") ?? new MemoryStream(),
|
||||
typeof(CpmDefinitions), CpmDefinitionsContext.Default) as CpmDefinitions;
|
||||
JsonSerializer.Deserialize(Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream("Aaru.Filesystems.CPM.cpmdefs.json") ??
|
||||
new MemoryStream(),
|
||||
typeof(CpmDefinitions),
|
||||
CpmDefinitionsContext.Default) as CpmDefinitions;
|
||||
|
||||
if(_definitions is null)
|
||||
return false;
|
||||
if(_definitions is null) return false;
|
||||
|
||||
// Patch definitions
|
||||
foreach(CpmDefinition def in _definitions.definitions)
|
||||
@@ -67,12 +68,10 @@ public sealed partial class CPM
|
||||
sectorIds = new int[def.sectorsPerTrack]
|
||||
};
|
||||
|
||||
for(var i = 0; i < def.sectorsPerTrack; i++)
|
||||
def.side1.sectorIds[i] = i + 1;
|
||||
for(var i = 0; i < def.sectorsPerTrack; i++) def.side1.sectorIds[i] = i + 1;
|
||||
}
|
||||
|
||||
if(def.sides != 2 || def.side2 != null)
|
||||
continue;
|
||||
if(def.sides != 2 || def.side2 != null) continue;
|
||||
|
||||
{
|
||||
def.side2 = new Side
|
||||
@@ -81,8 +80,7 @@ public sealed partial class CPM
|
||||
sectorIds = new int[def.sectorsPerTrack]
|
||||
};
|
||||
|
||||
for(var i = 0; i < def.sectorsPerTrack; i++)
|
||||
def.side2.sectorIds[i] = i + 1;
|
||||
for(var i = 0; i < def.sectorsPerTrack; i++) def.side2.sectorIds[i] = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,9 +93,11 @@ public sealed partial class CPM
|
||||
}
|
||||
}
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
[JsonSourceGenerationOptions(WriteIndented = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
IncludeFields = true)]
|
||||
[JsonSerializable(typeof(CpmDefinitions))]
|
||||
|
||||
// ReSharper disable once PartialTypeWithSinglePart
|
||||
public partial class CpmDefinitionsContext : JsonSerializerContext;
|
||||
|
||||
|
||||
@@ -47,8 +47,7 @@ public sealed partial class CPM
|
||||
{
|
||||
node = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0)
|
||||
return ErrorNumber.NotSupported;
|
||||
@@ -68,17 +67,13 @@ public sealed partial class CPM
|
||||
{
|
||||
filename = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
if(node is not CpmDirNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(node is not CpmDirNode mynode) return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(mynode.Position < 0)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(mynode.Position < 0) return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(mynode.Position >= mynode.Contents.Length)
|
||||
return ErrorNumber.NoError;
|
||||
if(mynode.Position >= mynode.Contents.Length) return ErrorNumber.NoError;
|
||||
|
||||
filename = mynode.Contents[mynode.Position++];
|
||||
|
||||
@@ -88,8 +83,7 @@ public sealed partial class CPM
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber CloseDir(IDirNode node)
|
||||
{
|
||||
if(node is not CpmDirNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(node is not CpmDirNode mynode) return ErrorNumber.InvalidArgument;
|
||||
|
||||
mynode.Position = -1;
|
||||
mynode.Contents = null;
|
||||
@@ -110,8 +104,7 @@ public sealed partial class CPM
|
||||
{
|
||||
try
|
||||
{
|
||||
if(directory == null)
|
||||
return false;
|
||||
if(directory == null) return false;
|
||||
|
||||
var fileCount = 0;
|
||||
|
||||
@@ -123,18 +116,15 @@ public sealed partial class CPM
|
||||
{
|
||||
for(var f = 0; f < 8; f++)
|
||||
{
|
||||
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00)
|
||||
return false;
|
||||
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false;
|
||||
}
|
||||
|
||||
for(var e = 0; e < 3; e++)
|
||||
{
|
||||
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00)
|
||||
return false;
|
||||
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false;
|
||||
}
|
||||
|
||||
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename))
|
||||
fileCount++;
|
||||
if(!ArrayHelpers.ArrayIsNullOrWhiteSpace(entry.filename)) fileCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -144,14 +134,12 @@ public sealed partial class CPM
|
||||
{
|
||||
for(var f = 0; f < 8; f++)
|
||||
{
|
||||
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00)
|
||||
return false;
|
||||
if(entry.filename[f] < 0x20 && entry.filename[f] != 0x00) return false;
|
||||
}
|
||||
|
||||
for(var e = 0; e < 3; e++)
|
||||
{
|
||||
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00)
|
||||
return false;
|
||||
if(entry.extension[e] < 0x20 && entry.extension[e] != 0x00) return false;
|
||||
}
|
||||
|
||||
_label = Encoding.ASCII.GetString(directory, off + 1, 11).Trim();
|
||||
|
||||
@@ -43,16 +43,15 @@ public sealed partial class CPM
|
||||
{
|
||||
attributes = new FileAttributes();
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
{
|
||||
'/'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(pathElements.Length != 1) return ErrorNumber.NotSupported;
|
||||
|
||||
if(string.IsNullOrEmpty(pathElements[0]) ||
|
||||
string.Compare(pathElements[0], "/", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
@@ -76,19 +75,17 @@ public sealed partial class CPM
|
||||
{
|
||||
node = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
{
|
||||
'/'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(pathElements.Length != 1) return ErrorNumber.NotSupported;
|
||||
|
||||
if(!_fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file))
|
||||
return ErrorNumber.NoSuchFile;
|
||||
if(!_fileCache.TryGetValue(pathElements[0].ToUpperInvariant(), out byte[] file)) return ErrorNumber.NoSuchFile;
|
||||
|
||||
node = new CpmFileNode
|
||||
{
|
||||
@@ -104,11 +101,9 @@ public sealed partial class CPM
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber CloseFile(IFileNode node)
|
||||
{
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
if(node is not CpmFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(node is not CpmFileNode mynode) return ErrorNumber.InvalidArgument;
|
||||
|
||||
mynode.Cache = null;
|
||||
|
||||
@@ -120,19 +115,15 @@ public sealed partial class CPM
|
||||
{
|
||||
read = 0;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
if(buffer is null || buffer.Length < length)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(buffer is null || buffer.Length < length) return ErrorNumber.InvalidArgument;
|
||||
|
||||
if(node is not CpmFileNode mynode)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(node is not CpmFileNode mynode) return ErrorNumber.InvalidArgument;
|
||||
|
||||
read = length;
|
||||
|
||||
if(length + mynode.Offset >= mynode.Length)
|
||||
read = mynode.Length - mynode.Offset;
|
||||
if(length + mynode.Offset >= mynode.Length) read = mynode.Length - mynode.Offset;
|
||||
|
||||
Array.Copy(mynode.Cache, mynode.Offset, buffer, 0, read);
|
||||
|
||||
@@ -154,16 +145,15 @@ public sealed partial class CPM
|
||||
{
|
||||
stat = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
{
|
||||
'/'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(pathElements.Length != 1) return ErrorNumber.NotSupported;
|
||||
|
||||
if(!string.IsNullOrEmpty(path) && string.Compare(path, "/", StringComparison.OrdinalIgnoreCase) != 0)
|
||||
{
|
||||
@@ -178,11 +168,9 @@ public sealed partial class CPM
|
||||
BlockSize = Metadata.ClusterSize
|
||||
};
|
||||
|
||||
if(_labelCreationDate != null)
|
||||
stat.CreationTime = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
if(_labelCreationDate != null) stat.CreationTime = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
|
||||
if(_labelUpdateDate != null)
|
||||
stat.StatusChangeTime = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
if(_labelUpdateDate != null) stat.StatusChangeTime = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
|
||||
return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
@@ -191,8 +191,7 @@ public sealed partial class CPM
|
||||
var sig3 = BitConverter.ToUInt32(sector, 0x7C);
|
||||
|
||||
// PCW16 extended boot record
|
||||
if(sig1 == 0x4D2F5043 && sig2 == 0x004B5344 && sig3 == sig1)
|
||||
amsSbOffset = 0x80;
|
||||
if(sig1 == 0x4D2F5043 && sig2 == 0x004B5344 && sig3 == sig1) amsSbOffset = 0x80;
|
||||
|
||||
// Read the superblock
|
||||
AmstradSuperBlock amsSb =
|
||||
@@ -222,8 +221,7 @@ public sealed partial class CPM
|
||||
bsh = amsSb.bsh
|
||||
};
|
||||
|
||||
for(var i = 0; i < _dpb.bsh; i++)
|
||||
_dpb.blm += (byte)Math.Pow(2, i);
|
||||
for(var i = 0; i < _dpb.bsh; i++) _dpb.blm += (byte)Math.Pow(2, i);
|
||||
|
||||
if(sectorCount >= 1440)
|
||||
{
|
||||
@@ -241,13 +239,13 @@ public sealed partial class CPM
|
||||
_dpb.off = amsSb.off;
|
||||
_dpb.psh = amsSb.psh;
|
||||
|
||||
for(var i = 0; i < _dpb.psh; i++)
|
||||
_dpb.phm += (byte)Math.Pow(2, i);
|
||||
for(var i = 0; i < _dpb.psh; i++) _dpb.phm += (byte)Math.Pow(2, i);
|
||||
|
||||
_dpb.spt = (ushort)(amsSb.spt * (sectorSize / 128));
|
||||
var directoryLength = (uint)(((ulong)_dpb.drm + 1) * 32 / sectorSize);
|
||||
|
||||
imagePlugin.ReadSectors(firstDirectorySector + partition.Start, directoryLength,
|
||||
imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
|
||||
directoryLength,
|
||||
out directory);
|
||||
|
||||
// Build a CP/M disk definition
|
||||
@@ -276,8 +274,7 @@ public sealed partial class CPM
|
||||
}
|
||||
};
|
||||
|
||||
for(var si = 0; si < amsSb.spt; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < amsSb.spt; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
if(amsSb.format == 2)
|
||||
{
|
||||
@@ -294,8 +291,7 @@ public sealed partial class CPM
|
||||
sectorIds = new int[amsSb.spt]
|
||||
};
|
||||
|
||||
for(var si = 0; si < amsSb.spt; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < amsSb.spt; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
else
|
||||
_workingDefinition.order = null;
|
||||
@@ -320,8 +316,7 @@ public sealed partial class CPM
|
||||
ushort sum = 0;
|
||||
|
||||
// Sum of all 16-bit words that make this sector must be 0
|
||||
for(var i = 0; i < sector.Length; i += 2)
|
||||
sum += BitConverter.ToUInt16(sector, i);
|
||||
for(var i = 0; i < sector.Length; i += 2) sum += BitConverter.ToUInt16(sector, i);
|
||||
|
||||
// It may happen that there is a corrupted superblock
|
||||
// Better to ignore corrupted than to false positive the rest
|
||||
@@ -368,7 +363,8 @@ public sealed partial class CPM
|
||||
|
||||
var directoryLength = (uint)(((ulong)_dpb.drm + 1) * 32 / sectorSize);
|
||||
|
||||
imagePlugin.ReadSectors(firstDirectorySector + partition.Start, directoryLength,
|
||||
imagePlugin.ReadSectors(firstDirectorySector + partition.Start,
|
||||
directoryLength,
|
||||
out directory);
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Found_CPM_86_hard_disk_superblock);
|
||||
@@ -410,8 +406,7 @@ public sealed partial class CPM
|
||||
for(var si = 0; si < hddSb.sectorsPerTrack; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < hddSb.spt; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < hddSb.spt; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -496,8 +491,7 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 8; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 8; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -556,11 +550,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 8; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 8; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 8; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 8; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -621,11 +613,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -685,11 +675,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -748,11 +736,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 9; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 9; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -811,11 +797,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 15; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 15; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 15; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 15; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -874,11 +858,9 @@ public sealed partial class CPM
|
||||
sofs = 0
|
||||
};
|
||||
|
||||
for(var si = 0; si < 18; si++)
|
||||
_workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 18; si++) _workingDefinition.side1.sectorIds[si] = si + 1;
|
||||
|
||||
for(var si = 0; si < 18; si++)
|
||||
_workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
for(var si = 0; si < 18; si++) _workingDefinition.side2.sectorIds[si] = si + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -888,7 +870,8 @@ public sealed partial class CPM
|
||||
{
|
||||
var directoryLength = (uint)(((ulong)_dpb.drm + 1) * 32 / imagePlugin.Info.SectorSize);
|
||||
|
||||
imagePlugin.ReadSectors(firstDirectorySector86 + partition.Start, directoryLength,
|
||||
imagePlugin.ReadSectors(firstDirectorySector86 + partition.Start,
|
||||
directoryLength,
|
||||
out directory);
|
||||
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Found_CPM_86_floppy_identifier);
|
||||
@@ -962,7 +945,8 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
// Head changes after whole side
|
||||
else if(string.Compare(def.order, "CYLINDERS",
|
||||
else if(string.Compare(def.order,
|
||||
"CYLINDERS",
|
||||
StringComparison.InvariantCultureIgnoreCase) ==
|
||||
0)
|
||||
{
|
||||
@@ -981,13 +965,14 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
// TODO: Implement COLUMBIA ordering
|
||||
else if(string.Compare(def.order, "COLUMBIA",
|
||||
else if(string.Compare(def.order,
|
||||
"COLUMBIA",
|
||||
StringComparison.InvariantCultureIgnoreCase) ==
|
||||
0)
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Dont_know_how_to_handle_COLUMBIA_ordering_not_proceeding_with_this_definition);
|
||||
Localization
|
||||
.Dont_know_how_to_handle_COLUMBIA_ordering_not_proceeding_with_this_definition);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -997,16 +982,16 @@ public sealed partial class CPM
|
||||
0)
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Don_know_how_to_handle_EAGLE_ordering_not_proceeding_with_this_definition);
|
||||
Localization
|
||||
.Don_know_how_to_handle_EAGLE_ordering_not_proceeding_with_this_definition);
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Unknown_order_type_0_not_proceeding_with_this_definition,
|
||||
Localization
|
||||
.Unknown_order_type_0_not_proceeding_with_this_definition,
|
||||
def.order);
|
||||
|
||||
continue;
|
||||
@@ -1018,13 +1003,13 @@ public sealed partial class CPM
|
||||
|
||||
for(var p = 0; p < dirLen; p++)
|
||||
{
|
||||
errno =
|
||||
imagePlugin.
|
||||
ReadSector((ulong)((int)offset + (int)partition.Start + p / _sectorMask.Length * _sectorMask.Length + _sectorMask[p % _sectorMask.Length]),
|
||||
out byte[] dirSector);
|
||||
errno = imagePlugin.ReadSector((ulong)((int)offset +
|
||||
(int)partition.Start +
|
||||
p / _sectorMask.Length * _sectorMask.Length +
|
||||
_sectorMask[p % _sectorMask.Length]),
|
||||
out byte[] dirSector);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
break;
|
||||
if(errno != ErrorNumber.NoError) break;
|
||||
|
||||
ms.Write(dirSector, 0, dirSector.Length);
|
||||
}
|
||||
@@ -1034,21 +1019,21 @@ public sealed partial class CPM
|
||||
if(def.evenOdd)
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Definition_contains_EVEN_ODD_field_with_unknown_meaning_detection_may_be_wrong);
|
||||
Localization
|
||||
.Definition_contains_EVEN_ODD_field_with_unknown_meaning_detection_may_be_wrong);
|
||||
}
|
||||
|
||||
// Complement of the directory bytes if needed
|
||||
if(def.complement)
|
||||
{
|
||||
for(var b = 0; b < directory.Length; b++)
|
||||
directory[b] = (byte)(~directory[b] & 0xFF);
|
||||
for(var b = 0; b < directory.Length; b++) directory[b] = (byte)(~directory[b] & 0xFF);
|
||||
}
|
||||
|
||||
// Check the directory
|
||||
if(CheckDir(directory))
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME, Localization.Definition_0_has_a_correct_directory,
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.Definition_0_has_a_correct_directory,
|
||||
def.comment);
|
||||
|
||||
// Build a Disc Parameter Block
|
||||
@@ -1157,8 +1142,7 @@ public sealed partial class CPM
|
||||
metadata = new FileSystem();
|
||||
|
||||
// As the identification is so complex, just call Identify() and relay on its findings
|
||||
if(!Identify(imagePlugin, partition) || !_cpmFound || _workingDefinition == null || _dpb == null)
|
||||
return;
|
||||
if(!Identify(imagePlugin, partition) || !_cpmFound || _workingDefinition == null || _dpb == null) return;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(Localization.CPM_filesystem);
|
||||
@@ -1170,8 +1154,8 @@ public sealed partial class CPM
|
||||
|
||||
if(_dpb.dsm > 0)
|
||||
{
|
||||
sb.AppendFormat(Localization.Volume_contains_0_blocks_1_bytes, _dpb.dsm, _dpb.dsm * (128 << _dpb.bsh)).
|
||||
AppendLine();
|
||||
sb.AppendFormat(Localization.Volume_contains_0_blocks_1_bytes, _dpb.dsm, _dpb.dsm * (128 << _dpb.bsh))
|
||||
.AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendFormat(Localization.Volume_contains_0_directory_entries, _dpb.drm + 1).AppendLine();
|
||||
@@ -1181,8 +1165,9 @@ public sealed partial class CPM
|
||||
else
|
||||
{
|
||||
sb.AppendFormat(Localization.Volume_reserves_1_tracks_0_sectors_for_system,
|
||||
_workingDefinition.ofs * _workingDefinition.sectorsPerTrack, _workingDefinition.ofs).
|
||||
AppendLine();
|
||||
_workingDefinition.ofs * _workingDefinition.sectorsPerTrack,
|
||||
_workingDefinition.ofs)
|
||||
.AppendLine();
|
||||
}
|
||||
|
||||
if(_workingDefinition.side1.sectorIds.Length >= 2)
|
||||
@@ -1201,8 +1186,8 @@ public sealed partial class CPM
|
||||
|
||||
if(interleaveSide2 > 1)
|
||||
{
|
||||
sb.AppendFormat(Localization.Side_one_uses_0_one_software_interleaving, interleaveSide2).
|
||||
AppendLine();
|
||||
sb.AppendFormat(Localization.Side_one_uses_0_one_software_interleaving, interleaveSide2)
|
||||
.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1217,8 +1202,8 @@ public sealed partial class CPM
|
||||
|
||||
break;
|
||||
default:
|
||||
sb.AppendFormat(Localization.Unknown_how_0_side_ordering_works, _workingDefinition.order).
|
||||
AppendLine();
|
||||
sb.AppendFormat(Localization.Unknown_how_0_side_ordering_works, _workingDefinition.order)
|
||||
.AppendLine();
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1238,25 +1223,22 @@ public sealed partial class CPM
|
||||
:X2}H AL1 {_dpb.al1:X2}H OFS {_workingDefinition.ofs}");
|
||||
}
|
||||
|
||||
if(_label != null)
|
||||
sb.AppendFormat(Localization.Volume_label_0, _label).AppendLine();
|
||||
if(_label != null) sb.AppendFormat(Localization.Volume_label_0, _label).AppendLine();
|
||||
|
||||
if(_standardTimestamps)
|
||||
sb.AppendLine(Localization.Volume_uses_standard_CPM_timestamps);
|
||||
if(_standardTimestamps) sb.AppendLine(Localization.Volume_uses_standard_CPM_timestamps);
|
||||
|
||||
if(_thirdPartyTimestamps)
|
||||
sb.AppendLine(Localization.Volume_uses_third_party_timestamps);
|
||||
if(_thirdPartyTimestamps) sb.AppendLine(Localization.Volume_uses_third_party_timestamps);
|
||||
|
||||
if(_labelCreationDate != null)
|
||||
{
|
||||
sb.AppendFormat(Localization.Volume_created_on_0, DateHandlers.CpmToDateTime(_labelCreationDate)).
|
||||
AppendLine();
|
||||
sb.AppendFormat(Localization.Volume_created_on_0, DateHandlers.CpmToDateTime(_labelCreationDate))
|
||||
.AppendLine();
|
||||
}
|
||||
|
||||
if(_labelUpdateDate != null)
|
||||
{
|
||||
sb.AppendFormat(Localization.Volume_updated_on_0, DateHandlers.CpmToDateTime(_labelUpdateDate)).
|
||||
AppendLine();
|
||||
sb.AppendFormat(Localization.Volume_updated_on_0, DateHandlers.CpmToDateTime(_labelUpdateDate))
|
||||
.AppendLine();
|
||||
}
|
||||
|
||||
metadata = new FileSystem();
|
||||
@@ -1268,11 +1250,9 @@ public sealed partial class CPM
|
||||
else
|
||||
metadata.Clusters = partition.End - partition.Start;
|
||||
|
||||
if(_labelCreationDate != null)
|
||||
metadata.CreationDate = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
if(_labelCreationDate != null) metadata.CreationDate = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
|
||||
if(_labelUpdateDate != null)
|
||||
metadata.ModificationDate = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
if(_labelUpdateDate != null) metadata.ModificationDate = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
|
||||
metadata.Type = FS_TYPE;
|
||||
metadata.VolumeName = _label;
|
||||
|
||||
@@ -89,12 +89,12 @@ public sealed partial class CPM
|
||||
internal string[] Contents;
|
||||
internal int Position;
|
||||
|
||||
#region IDirNode Members
|
||||
#region IDirNode Members
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -105,7 +105,7 @@ public sealed partial class CPM
|
||||
{
|
||||
internal byte[] Cache;
|
||||
|
||||
#region IFileNode Members
|
||||
#region IFileNode Members
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Path { get; init; }
|
||||
@@ -116,7 +116,7 @@ public sealed partial class CPM
|
||||
/// <inheritdoc />
|
||||
public long Offset { get; set; }
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -94,7 +94,8 @@ public sealed partial class CPM
|
||||
}
|
||||
|
||||
// Head changes after whole side
|
||||
else if(string.Compare(_workingDefinition.order, "CYLINDERS",
|
||||
else if(string.Compare(_workingDefinition.order,
|
||||
"CYLINDERS",
|
||||
StringComparison.InvariantCultureIgnoreCase) ==
|
||||
0)
|
||||
{
|
||||
@@ -122,8 +123,8 @@ public sealed partial class CPM
|
||||
0)
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Dont_know_how_to_handle_COLUMBIA_ordering_not_proceeding_with_this_definition);
|
||||
Localization
|
||||
.Dont_know_how_to_handle_COLUMBIA_ordering_not_proceeding_with_this_definition);
|
||||
|
||||
return ErrorNumber.NotImplemented;
|
||||
}
|
||||
@@ -132,8 +133,8 @@ public sealed partial class CPM
|
||||
else if(string.Compare(_workingDefinition.order, "EAGLE", StringComparison.InvariantCultureIgnoreCase) == 0)
|
||||
{
|
||||
AaruConsole.DebugWriteLine(MODULE_NAME,
|
||||
Localization.
|
||||
Don_know_how_to_handle_EAGLE_ordering_not_proceeding_with_this_definition);
|
||||
Localization
|
||||
.Don_know_how_to_handle_EAGLE_ordering_not_proceeding_with_this_definition);
|
||||
|
||||
return ErrorNumber.NotImplemented;
|
||||
}
|
||||
@@ -158,16 +159,16 @@ public sealed partial class CPM
|
||||
for(var p = 0; p <= (int)(partition.End - partition.Start); p++)
|
||||
{
|
||||
ErrorNumber errno =
|
||||
_device.ReadSector((ulong)((int)partition.Start + p / _sectorMask.Length * _sectorMask.Length + _sectorMask[p % _sectorMask.Length]),
|
||||
_device.ReadSector((ulong)((int)partition.Start +
|
||||
p / _sectorMask.Length * _sectorMask.Length +
|
||||
_sectorMask[p % _sectorMask.Length]),
|
||||
out byte[] readSector);
|
||||
|
||||
if(errno != ErrorNumber.NoError)
|
||||
return errno;
|
||||
if(errno != ErrorNumber.NoError) return errno;
|
||||
|
||||
if(_workingDefinition.complement)
|
||||
{
|
||||
for(var b = 0; b < readSector.Length; b++)
|
||||
readSector[b] = (byte)(~readSector[b] & 0xFF);
|
||||
for(var b = 0; b < readSector.Length; b++) readSector[b] = (byte)(~readSector[b] & 0xFF);
|
||||
}
|
||||
|
||||
deinterleavedSectors.Add((ulong)p, readSector);
|
||||
@@ -204,8 +205,7 @@ public sealed partial class CPM
|
||||
blockMs.Write(sector, 0, sector.Length);
|
||||
sectorsPerBlock++;
|
||||
|
||||
if(sectorsPerBlock != blockSize / sector.Length)
|
||||
continue;
|
||||
if(sectorsPerBlock != blockSize / sector.Length) continue;
|
||||
|
||||
allocationBlocks.Add(blockNo++, blockMs.ToArray());
|
||||
sectorsPerBlock = 0;
|
||||
@@ -238,8 +238,7 @@ public sealed partial class CPM
|
||||
|
||||
byte[] directory = dirMs.ToArray();
|
||||
|
||||
if(directory == null)
|
||||
return ErrorNumber.InvalidArgument;
|
||||
if(directory == null) return ErrorNumber.InvalidArgument;
|
||||
|
||||
var dirCnt = 0;
|
||||
string file1 = null;
|
||||
@@ -291,18 +290,15 @@ public sealed partial class CPM
|
||||
validEntry &= entry.extension[i] >= 0x20;
|
||||
}
|
||||
|
||||
if(!validEntry)
|
||||
continue;
|
||||
if(!validEntry) continue;
|
||||
|
||||
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
|
||||
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
|
||||
|
||||
// If user is != 0, append user to name to have identical filenames
|
||||
if(user > 0)
|
||||
filename = $"{user:X1}:{filename}";
|
||||
if(user > 0) filename = $"{user:X1}:{filename}";
|
||||
|
||||
if(!string.IsNullOrEmpty(extension))
|
||||
filename = filename + "." + extension;
|
||||
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
|
||||
|
||||
filename = filename.Replace('/', '\u2215');
|
||||
|
||||
@@ -332,14 +328,11 @@ public sealed partial class CPM
|
||||
blocks = new List<ushort>();
|
||||
|
||||
// Attributes
|
||||
if(hidden)
|
||||
fInfo.Attributes |= FileAttributes.Hidden;
|
||||
if(hidden) fInfo.Attributes |= FileAttributes.Hidden;
|
||||
|
||||
if(rdOnly)
|
||||
fInfo.Attributes |= FileAttributes.ReadOnly;
|
||||
if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly;
|
||||
|
||||
if(system)
|
||||
fInfo.Attributes |= FileAttributes.System;
|
||||
if(system) fInfo.Attributes |= FileAttributes.System;
|
||||
|
||||
// Supposedly there is a value in the directory entry telling how many blocks are designated in
|
||||
// this entry. However some implementations tend to do whatever they wish, but none will ever
|
||||
@@ -356,8 +349,7 @@ public sealed partial class CPM
|
||||
_statCache.Add(filename, fInfo);
|
||||
|
||||
// Add the file to the directory listing
|
||||
if(!_dirList.Contains(filename))
|
||||
_dirList.Add(filename);
|
||||
if(!_dirList.Contains(filename)) _dirList.Add(filename);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
@@ -406,18 +398,15 @@ public sealed partial class CPM
|
||||
validEntry &= entry.extension[i] >= 0x20;
|
||||
}
|
||||
|
||||
if(!validEntry)
|
||||
continue;
|
||||
if(!validEntry) continue;
|
||||
|
||||
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
|
||||
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
|
||||
|
||||
// If user is != 0, append user to name to have identical filenames
|
||||
if(user > 0)
|
||||
filename = $"{user:X1}:{filename}";
|
||||
if(user > 0) filename = $"{user:X1}:{filename}";
|
||||
|
||||
if(!string.IsNullOrEmpty(extension))
|
||||
filename = filename + "." + extension;
|
||||
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
|
||||
|
||||
filename = filename.Replace('/', '\u2215');
|
||||
|
||||
@@ -447,14 +436,11 @@ public sealed partial class CPM
|
||||
blocks = new List<ushort>();
|
||||
|
||||
// Attributes
|
||||
if(hidden)
|
||||
fInfo.Attributes |= FileAttributes.Hidden;
|
||||
if(hidden) fInfo.Attributes |= FileAttributes.Hidden;
|
||||
|
||||
if(rdOnly)
|
||||
fInfo.Attributes |= FileAttributes.ReadOnly;
|
||||
if(rdOnly) fInfo.Attributes |= FileAttributes.ReadOnly;
|
||||
|
||||
if(system)
|
||||
fInfo.Attributes |= FileAttributes.System;
|
||||
if(system) fInfo.Attributes |= FileAttributes.System;
|
||||
|
||||
// Supposedly there is a value in the directory entry telling how many blocks are designated in
|
||||
// this entry. However some implementations tend to do whatever they wish, but none will ever
|
||||
@@ -471,8 +457,7 @@ public sealed partial class CPM
|
||||
_statCache.Add(filename, fInfo);
|
||||
|
||||
// Add the file to the directory listing
|
||||
if(!_dirList.Contains(filename))
|
||||
_dirList.Add(filename);
|
||||
if(!_dirList.Contains(filename)) _dirList.Add(filename);
|
||||
|
||||
// Count entries 3 by 3 for timestamps
|
||||
switch(dirCnt % 3)
|
||||
@@ -503,27 +488,22 @@ public sealed partial class CPM
|
||||
|
||||
int user = entry.userNumber & 0x0F;
|
||||
|
||||
for(var i = 0; i < 8; i++)
|
||||
entry.filename[i] &= 0x7F;
|
||||
for(var i = 0; i < 8; i++) entry.filename[i] &= 0x7F;
|
||||
|
||||
for(var i = 0; i < 3; i++)
|
||||
entry.extension[i] &= 0x7F;
|
||||
for(var i = 0; i < 3; i++) entry.extension[i] &= 0x7F;
|
||||
|
||||
string filename = Encoding.ASCII.GetString(entry.filename).Trim();
|
||||
string extension = Encoding.ASCII.GetString(entry.extension).Trim();
|
||||
|
||||
// If user is != 0, append user to name to have identical filenames
|
||||
if(user > 0)
|
||||
filename = $"{user:X1}:{filename}";
|
||||
if(user > 0) filename = $"{user:X1}:{filename}";
|
||||
|
||||
if(!string.IsNullOrEmpty(extension))
|
||||
filename = filename + "." + extension;
|
||||
if(!string.IsNullOrEmpty(extension)) filename = filename + "." + extension;
|
||||
|
||||
filename = filename.Replace('/', '\u2215');
|
||||
|
||||
// Do not repeat passwords
|
||||
if(_passwordCache.ContainsKey(filename))
|
||||
_passwordCache.Remove(filename);
|
||||
if(_passwordCache.ContainsKey(filename)) _passwordCache.Remove(filename);
|
||||
|
||||
// Copy whole password entry
|
||||
var tmp = new byte[32];
|
||||
@@ -745,8 +725,7 @@ public sealed partial class CPM
|
||||
{
|
||||
var fileMs = new MemoryStream();
|
||||
|
||||
if(_statCache.TryGetValue(filename, out FileEntryInfo fInfo))
|
||||
_statCache.Remove(filename);
|
||||
if(_statCache.TryGetValue(filename, out FileEntryInfo fInfo)) _statCache.Remove(filename);
|
||||
|
||||
fInfo.Blocks = 0;
|
||||
|
||||
@@ -754,8 +733,7 @@ public sealed partial class CPM
|
||||
{
|
||||
for(var ex = 0; ex < extents.Count; ex++)
|
||||
{
|
||||
if(!extents.TryGetValue(ex, out List<ushort> alBlks))
|
||||
continue;
|
||||
if(!extents.TryGetValue(ex, out List<ushort> alBlks)) continue;
|
||||
|
||||
foreach(ushort alBlk in alBlks)
|
||||
{
|
||||
@@ -787,8 +765,7 @@ public sealed partial class CPM
|
||||
var tmp = new byte[8];
|
||||
Array.Copy(kvp.Value, 16, tmp, 0, 8);
|
||||
|
||||
for(var t = 0; t < 8; t++)
|
||||
tmp[t] ^= kvp.Value[13];
|
||||
for(var t = 0; t < 8; t++) tmp[t] ^= kvp.Value[13];
|
||||
|
||||
_decodedPasswordCache.Add(kvp.Key, tmp);
|
||||
}
|
||||
@@ -812,14 +789,11 @@ public sealed partial class CPM
|
||||
Type = FS_TYPE
|
||||
};
|
||||
|
||||
if(_labelCreationDate != null)
|
||||
Metadata.CreationDate = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
if(_labelCreationDate != null) Metadata.CreationDate = DateHandlers.CpmToDateTime(_labelCreationDate);
|
||||
|
||||
if(_labelUpdateDate != null)
|
||||
Metadata.ModificationDate = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
if(_labelUpdateDate != null) Metadata.ModificationDate = DateHandlers.CpmToDateTime(_labelUpdateDate);
|
||||
|
||||
if(!string.IsNullOrEmpty(_label))
|
||||
Metadata.VolumeName = _label;
|
||||
if(!string.IsNullOrEmpty(_label)) Metadata.VolumeName = _label;
|
||||
|
||||
_mounted = true;
|
||||
|
||||
@@ -831,8 +805,7 @@ public sealed partial class CPM
|
||||
{
|
||||
stat = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
stat = _cpmStat;
|
||||
|
||||
|
||||
@@ -43,24 +43,21 @@ public sealed partial class CPM
|
||||
/// <inheritdoc />
|
||||
public ErrorNumber GetXattr(string path, string xattr, ref byte[] buf)
|
||||
{
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
{
|
||||
'/'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(pathElements.Length != 1) return ErrorNumber.NotSupported;
|
||||
|
||||
if(!_fileCache.ContainsKey(pathElements[0].ToUpperInvariant()))
|
||||
return ErrorNumber.NoSuchFile;
|
||||
if(!_fileCache.ContainsKey(pathElements[0].ToUpperInvariant())) return ErrorNumber.NoSuchFile;
|
||||
|
||||
if(string.Compare(xattr, "com.caldera.cpm.password", StringComparison.InvariantCulture) == 0)
|
||||
{
|
||||
if(!_passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf))
|
||||
return ErrorNumber.NoError;
|
||||
if(!_passwordCache.TryGetValue(pathElements[0].ToUpperInvariant(), out buf)) return ErrorNumber.NoError;
|
||||
}
|
||||
|
||||
if(string.Compare(xattr, "com.caldera.cpm.password.text", StringComparison.InvariantCulture) != 0)
|
||||
@@ -76,24 +73,21 @@ public sealed partial class CPM
|
||||
{
|
||||
xattrs = null;
|
||||
|
||||
if(!_mounted)
|
||||
return ErrorNumber.AccessDenied;
|
||||
if(!_mounted) return ErrorNumber.AccessDenied;
|
||||
|
||||
string[] pathElements = path.Split(new[]
|
||||
{
|
||||
'/'
|
||||
}, StringSplitOptions.RemoveEmptyEntries);
|
||||
{
|
||||
'/'
|
||||
},
|
||||
StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(pathElements.Length != 1)
|
||||
return ErrorNumber.NotSupported;
|
||||
if(pathElements.Length != 1) return ErrorNumber.NotSupported;
|
||||
|
||||
if(!_fileCache.ContainsKey(pathElements[0].ToUpperInvariant()))
|
||||
return ErrorNumber.NoSuchFile;
|
||||
if(!_fileCache.ContainsKey(pathElements[0].ToUpperInvariant())) return ErrorNumber.NoSuchFile;
|
||||
|
||||
xattrs = new List<string>();
|
||||
|
||||
if(_passwordCache.ContainsKey(pathElements[0].ToUpperInvariant()))
|
||||
xattrs.Add("com.caldera.cpm.password");
|
||||
if(_passwordCache.ContainsKey(pathElements[0].ToUpperInvariant())) xattrs.Add("com.caldera.cpm.password");
|
||||
|
||||
if(_decodedPasswordCache.ContainsKey(pathElements[0].ToUpperInvariant()))
|
||||
xattrs.Add("com.caldera.cpm.password.text");
|
||||
|
||||
Reference in New Issue
Block a user