mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-08-10 01:51:15 +10:00
Compare commits
92
Commits
2.8
...
3.0-preview2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a982c119fb | ||
|
|
c6dee3fe33 | ||
|
|
91961b0e7b | ||
|
|
29c6ab06d4 | ||
|
|
b03b561724 | ||
|
|
91f534a7c3 | ||
|
|
f0f3268924 | ||
|
|
c269cfe839 | ||
|
|
7d8aad0e88 | ||
|
|
310d0b97c5 | ||
|
|
8e50c46357 | ||
|
|
e6555741b0 | ||
|
|
c21692491d | ||
|
|
350b6e8f1e | ||
|
|
0101477830 | ||
|
|
a6c017986b | ||
|
|
0174fc8b30 | ||
|
|
c6f6ef4429 | ||
|
|
ab0c35e879 | ||
|
|
676a95dd97 | ||
|
|
8981fd02e9 | ||
|
|
16d3f95971 | ||
|
|
293c649edb | ||
|
|
88efc77887 | ||
|
|
dc6085f185 | ||
|
|
e2cbb9c6fc | ||
|
|
4b7b9621b4 | ||
|
|
96c42a29b5 | ||
|
|
742c89b9bf | ||
|
|
dbd303fd07 | ||
|
|
8d35be447a | ||
|
|
83c09bdc81 | ||
|
|
93a5064751 | ||
|
|
ef6a962a01 | ||
|
|
d32788198d | ||
|
|
7798dd1c34 | ||
|
|
57cd052d61 | ||
|
|
5eb523530c | ||
|
|
8a17b05398 | ||
|
|
dc5ac1e7d4 | ||
|
|
1d14d79fab | ||
|
|
846ea41883 | ||
|
|
452393aaa7 | ||
|
|
17bc763761 | ||
|
|
668a9b7fe2 | ||
|
|
8293c18406 | ||
|
|
48fbfa77df | ||
|
|
709c91cec5 | ||
|
|
611ad122f9 | ||
|
|
d8fd0aa516 | ||
|
|
7f3c8b1777 | ||
|
|
087457fa0d | ||
|
|
bb9f614e82 | ||
|
|
f4a5e63d25 | ||
|
|
c5fcb1ec8d | ||
|
|
9f4c92f437 | ||
|
|
62fa3844f9 | ||
|
|
efc81332f9 | ||
|
|
847ce0506d | ||
|
|
9865ef7f79 | ||
|
|
9ba1333edf | ||
|
|
49b87d6f24 | ||
|
|
ad96465e16 | ||
|
|
f7ab5fa6f2 | ||
|
|
759cb53f64 | ||
|
|
0ea33ff35c | ||
|
|
8630a89553 | ||
|
|
a24998c6ee | ||
|
|
f438d0dd71 | ||
|
|
019c47ad40 | ||
|
|
1d6af81253 | ||
|
|
9734077bb1 | ||
|
|
3e6529119f | ||
|
|
db81853e07 | ||
|
|
f6ad0c98b7 | ||
|
|
774ff9956f | ||
|
|
a3f323259a | ||
|
|
81145ed0e9 | ||
|
|
fa896b7c39 | ||
|
|
b8d63d1a11 | ||
|
|
a57896c429 | ||
|
|
17e2dc2984 | ||
|
|
2371274ac9 | ||
|
|
8d3a010bd4 | ||
|
|
a34904a4d4 | ||
|
|
c6459c694a | ||
|
|
a2a1c2302b | ||
|
|
0e6f905809 | ||
|
|
126429227e | ||
|
|
bf7b09d551 | ||
|
|
b56595ac27 | ||
|
|
5dae1da560 |
@@ -0,0 +1,60 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Create a bug report to help improve WPinternals
|
||||||
|
labels: [bug]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps To Reproduce
|
||||||
|
description: Steps to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to '....'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See the error
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: A clear and concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: wpi-version
|
||||||
|
attributes:
|
||||||
|
label: WPinternals Version
|
||||||
|
description: What version of WPinternals are you using?
|
||||||
|
placeholder: v2.9.2
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Windows Version
|
||||||
|
description: What version of Windows are you using? Press <kbd>Win</kbd> + <kbd>Pause/Break</kbd> and copy.
|
||||||
|
placeholder: e.g. Windows 11 21H2 22000.132
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Phone model
|
||||||
|
description: What phone model did you reproduce the bug on (if applicable)
|
||||||
|
placeholder: e.g. Lumia 950 XL (RM-1085)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Relevant Assets
|
||||||
|
description: |
|
||||||
|
A list of assets (logs, screenshots) relevant to this bug.
|
||||||
|
|
||||||
|
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||||
|
placeholder: |
|
||||||
|
To upload the log
|
||||||
|
- Copy the `WPinternals.log` files from `%ALLUSERSPROFILE%\WPinternals`
|
||||||
|
- Drag and drop them into this text area.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
architecture: [x86, x64, arm64]
|
||||||
|
platform: [win]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install .NET SDK
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: "8.0.x"
|
||||||
|
|
||||||
|
- name: Add MSBuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
|
|
||||||
|
- name: Build utilities
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
msbuild /m /t:restore,wpinternals:publish /p:Platform=${{ matrix.architecture }} /p:RuntimeIdentifier=${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishDir=${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }} /p:PublishSingleFile=true /p:PublishTrimmed=false WPinternals.sln
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.platform }}-${{ matrix.architecture }}
|
||||||
|
path: ${{ github.workspace }}/artifacts/${{ matrix.platform }}-${{ matrix.architecture }}
|
||||||
+334
@@ -0,0 +1,334 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
# *.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// Common/CRC.cs
|
|
||||||
|
|
||||||
namespace SevenZip
|
|
||||||
{
|
|
||||||
class CRC
|
|
||||||
{
|
|
||||||
public static readonly uint[] Table;
|
|
||||||
|
|
||||||
static CRC()
|
|
||||||
{
|
|
||||||
Table = new uint[256];
|
|
||||||
const uint kPoly = 0xEDB88320;
|
|
||||||
for (uint i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
uint r = i;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
if ((r & 1) != 0)
|
|
||||||
r = (r >> 1) ^ kPoly;
|
|
||||||
else
|
|
||||||
r >>= 1;
|
|
||||||
Table[i] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint _value = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
public void Init() { _value = 0xFFFFFFFF; }
|
|
||||||
|
|
||||||
public void UpdateByte(byte b)
|
|
||||||
{
|
|
||||||
_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
for (uint i = 0; i < size; i++)
|
|
||||||
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
|
|
||||||
|
|
||||||
static uint CalculateDigest(byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
CRC crc = new CRC();
|
|
||||||
// crc.Init();
|
|
||||||
crc.Update(data, offset, size);
|
|
||||||
return crc.GetDigest();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
|
|
||||||
{
|
|
||||||
return (CalculateDigest(data, offset, size) == digest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
// CommandLineParser.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace SevenZip.CommandLineParser
|
|
||||||
{
|
|
||||||
public enum SwitchType
|
|
||||||
{
|
|
||||||
Simple,
|
|
||||||
PostMinus,
|
|
||||||
LimitedPostString,
|
|
||||||
UnLimitedPostString,
|
|
||||||
PostChar
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SwitchForm
|
|
||||||
{
|
|
||||||
public string IDString;
|
|
||||||
public SwitchType Type;
|
|
||||||
public bool Multi;
|
|
||||||
public int MinLen;
|
|
||||||
public int MaxLen;
|
|
||||||
public string PostCharSet;
|
|
||||||
|
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi,
|
|
||||||
int minLen, int maxLen, string postCharSet)
|
|
||||||
{
|
|
||||||
IDString = idString;
|
|
||||||
Type = type;
|
|
||||||
Multi = multi;
|
|
||||||
MinLen = minLen;
|
|
||||||
MaxLen = maxLen;
|
|
||||||
PostCharSet = postCharSet;
|
|
||||||
}
|
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi, int minLen):
|
|
||||||
this(idString, type, multi, minLen, 0, "")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public SwitchForm(string idString, SwitchType type, bool multi):
|
|
||||||
this(idString, type, multi, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SwitchResult
|
|
||||||
{
|
|
||||||
public bool ThereIs;
|
|
||||||
public bool WithMinus;
|
|
||||||
public ArrayList PostStrings = new ArrayList();
|
|
||||||
public int PostCharIndex;
|
|
||||||
public SwitchResult()
|
|
||||||
{
|
|
||||||
ThereIs = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Parser
|
|
||||||
{
|
|
||||||
public ArrayList NonSwitchStrings = new ArrayList();
|
|
||||||
SwitchResult[] _switches;
|
|
||||||
|
|
||||||
public Parser(int numSwitches)
|
|
||||||
{
|
|
||||||
_switches = new SwitchResult[numSwitches];
|
|
||||||
for (int i = 0; i < numSwitches; i++)
|
|
||||||
_switches[i] = new SwitchResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ParseString(string srcString, SwitchForm[] switchForms)
|
|
||||||
{
|
|
||||||
int len = srcString.Length;
|
|
||||||
if (len == 0)
|
|
||||||
return false;
|
|
||||||
int pos = 0;
|
|
||||||
if (!IsItSwitchChar(srcString[pos]))
|
|
||||||
return false;
|
|
||||||
while (pos < len)
|
|
||||||
{
|
|
||||||
if (IsItSwitchChar(srcString[pos]))
|
|
||||||
pos++;
|
|
||||||
const int kNoLen = -1;
|
|
||||||
int matchedSwitchIndex = 0;
|
|
||||||
int maxLen = kNoLen;
|
|
||||||
for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
|
|
||||||
{
|
|
||||||
int switchLen = switchForms[switchIndex].IDString.Length;
|
|
||||||
if (switchLen <= maxLen || pos + switchLen > len)
|
|
||||||
continue;
|
|
||||||
if (String.Compare(switchForms[switchIndex].IDString, 0,
|
|
||||||
srcString, pos, switchLen, true) == 0)
|
|
||||||
{
|
|
||||||
matchedSwitchIndex = switchIndex;
|
|
||||||
maxLen = switchLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxLen == kNoLen)
|
|
||||||
throw new Exception("maxLen == kNoLen");
|
|
||||||
SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
|
|
||||||
SwitchForm switchForm = switchForms[matchedSwitchIndex];
|
|
||||||
if ((!switchForm.Multi) && matchedSwitch.ThereIs)
|
|
||||||
throw new Exception("switch must be single");
|
|
||||||
matchedSwitch.ThereIs = true;
|
|
||||||
pos += maxLen;
|
|
||||||
int tailSize = len - pos;
|
|
||||||
SwitchType type = switchForm.Type;
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case SwitchType.PostMinus:
|
|
||||||
{
|
|
||||||
if (tailSize == 0)
|
|
||||||
matchedSwitch.WithMinus = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);
|
|
||||||
if (matchedSwitch.WithMinus)
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SwitchType.PostChar:
|
|
||||||
{
|
|
||||||
if (tailSize < switchForm.MinLen)
|
|
||||||
throw new Exception("switch is not full");
|
|
||||||
string charSet = switchForm.PostCharSet;
|
|
||||||
const int kEmptyCharValue = -1;
|
|
||||||
if (tailSize == 0)
|
|
||||||
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int index = charSet.IndexOf(srcString[pos]);
|
|
||||||
if (index < 0)
|
|
||||||
matchedSwitch.PostCharIndex = kEmptyCharValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matchedSwitch.PostCharIndex = index;
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SwitchType.LimitedPostString:
|
|
||||||
case SwitchType.UnLimitedPostString:
|
|
||||||
{
|
|
||||||
int minLen = switchForm.MinLen;
|
|
||||||
if (tailSize < minLen)
|
|
||||||
throw new Exception("switch is not full");
|
|
||||||
if (type == SwitchType.UnLimitedPostString)
|
|
||||||
{
|
|
||||||
matchedSwitch.PostStrings.Add(srcString.Substring(pos));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
String stringSwitch = srcString.Substring(pos, minLen);
|
|
||||||
pos += minLen;
|
|
||||||
for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
|
|
||||||
{
|
|
||||||
char c = srcString[pos];
|
|
||||||
if (IsItSwitchChar(c))
|
|
||||||
break;
|
|
||||||
stringSwitch += c;
|
|
||||||
}
|
|
||||||
matchedSwitch.PostStrings.Add(stringSwitch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
|
|
||||||
{
|
|
||||||
int numCommandStrings = commandStrings.Length;
|
|
||||||
bool stopSwitch = false;
|
|
||||||
for (int i = 0; i < numCommandStrings; i++)
|
|
||||||
{
|
|
||||||
string s = commandStrings[i];
|
|
||||||
if (stopSwitch)
|
|
||||||
NonSwitchStrings.Add(s);
|
|
||||||
else
|
|
||||||
if (s == kStopSwitchParsing)
|
|
||||||
stopSwitch = true;
|
|
||||||
else
|
|
||||||
if (!ParseString(s, switchForms))
|
|
||||||
NonSwitchStrings.Add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SwitchResult this[int index] { get { return _switches[index]; } }
|
|
||||||
|
|
||||||
public static int ParseCommand(CommandForm[] commandForms, string commandString,
|
|
||||||
out string postString)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < commandForms.Length; i++)
|
|
||||||
{
|
|
||||||
string id = commandForms[i].IDString;
|
|
||||||
if (commandForms[i].PostStringMode)
|
|
||||||
{
|
|
||||||
if (commandString.IndexOf(id) == 0)
|
|
||||||
{
|
|
||||||
postString = commandString.Substring(id.Length);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (commandString == id)
|
|
||||||
{
|
|
||||||
postString = "";
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
postString = "";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
|
|
||||||
string commandString, ArrayList indices)
|
|
||||||
{
|
|
||||||
indices.Clear();
|
|
||||||
int numUsedChars = 0;
|
|
||||||
for (int i = 0; i < numForms; i++)
|
|
||||||
{
|
|
||||||
CommandSubCharsSet charsSet = forms[i];
|
|
||||||
int currentIndex = -1;
|
|
||||||
int len = charsSet.Chars.Length;
|
|
||||||
for (int j = 0; j < len; j++)
|
|
||||||
{
|
|
||||||
char c = charsSet.Chars[j];
|
|
||||||
int newIndex = commandString.IndexOf(c);
|
|
||||||
if (newIndex >= 0)
|
|
||||||
{
|
|
||||||
if (currentIndex >= 0)
|
|
||||||
return false;
|
|
||||||
if (commandString.IndexOf(c, newIndex + 1) >= 0)
|
|
||||||
return false;
|
|
||||||
currentIndex = j;
|
|
||||||
numUsedChars++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentIndex == -1 && !charsSet.EmptyAllowed)
|
|
||||||
return false;
|
|
||||||
indices.Add(currentIndex);
|
|
||||||
}
|
|
||||||
return (numUsedChars == commandString.Length);
|
|
||||||
}
|
|
||||||
const char kSwitchID1 = '-';
|
|
||||||
const char kSwitchID2 = '/';
|
|
||||||
|
|
||||||
const char kSwitchMinus = '-';
|
|
||||||
const string kStopSwitchParsing = "--";
|
|
||||||
|
|
||||||
static bool IsItSwitchChar(char c)
|
|
||||||
{
|
|
||||||
return (c == kSwitchID1 || c == kSwitchID2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CommandForm
|
|
||||||
{
|
|
||||||
public string IDString = "";
|
|
||||||
public bool PostStringMode = false;
|
|
||||||
public CommandForm(string idString, bool postStringMode)
|
|
||||||
{
|
|
||||||
IDString = idString;
|
|
||||||
PostStringMode = postStringMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CommandSubCharsSet
|
|
||||||
{
|
|
||||||
public string Chars = "";
|
|
||||||
public bool EmptyAllowed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// InBuffer.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
|
||||||
{
|
|
||||||
public class InBuffer
|
|
||||||
{
|
|
||||||
byte[] m_Buffer;
|
|
||||||
uint m_Pos;
|
|
||||||
uint m_Limit;
|
|
||||||
uint m_BufferSize;
|
|
||||||
System.IO.Stream m_Stream;
|
|
||||||
bool m_StreamWasExhausted;
|
|
||||||
ulong m_ProcessedSize;
|
|
||||||
|
|
||||||
public InBuffer(uint bufferSize)
|
|
||||||
{
|
|
||||||
m_Buffer = new byte[bufferSize];
|
|
||||||
m_BufferSize = bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
m_Stream = stream;
|
|
||||||
m_ProcessedSize = 0;
|
|
||||||
m_Limit = 0;
|
|
||||||
m_Pos = 0;
|
|
||||||
m_StreamWasExhausted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ReadBlock()
|
|
||||||
{
|
|
||||||
if (m_StreamWasExhausted)
|
|
||||||
return false;
|
|
||||||
m_ProcessedSize += m_Pos;
|
|
||||||
int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
|
|
||||||
m_Pos = 0;
|
|
||||||
m_Limit = (uint)aNumProcessedBytes;
|
|
||||||
m_StreamWasExhausted = (aNumProcessedBytes == 0);
|
|
||||||
return (!m_StreamWasExhausted);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
// m_Stream.Close();
|
|
||||||
m_Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ReadByte(byte b) // check it
|
|
||||||
{
|
|
||||||
if (m_Pos >= m_Limit)
|
|
||||||
if (!ReadBlock())
|
|
||||||
return false;
|
|
||||||
b = m_Buffer[m_Pos++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte ReadByte()
|
|
||||||
{
|
|
||||||
// return (byte)m_Stream.ReadByte();
|
|
||||||
if (m_Pos >= m_Limit)
|
|
||||||
if (!ReadBlock())
|
|
||||||
return 0xFF;
|
|
||||||
return m_Buffer[m_Pos++];
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetProcessedSize()
|
|
||||||
{
|
|
||||||
return m_ProcessedSize + m_Pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// OutBuffer.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Buffer
|
|
||||||
{
|
|
||||||
public class OutBuffer
|
|
||||||
{
|
|
||||||
byte[] m_Buffer;
|
|
||||||
uint m_Pos;
|
|
||||||
uint m_BufferSize;
|
|
||||||
System.IO.Stream m_Stream;
|
|
||||||
ulong m_ProcessedSize;
|
|
||||||
|
|
||||||
public OutBuffer(uint bufferSize)
|
|
||||||
{
|
|
||||||
m_Buffer = new byte[bufferSize];
|
|
||||||
m_BufferSize = bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
|
|
||||||
public void FlushStream() { m_Stream.Flush(); }
|
|
||||||
public void CloseStream() { m_Stream.Close(); }
|
|
||||||
public void ReleaseStream() { m_Stream = null; }
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
m_ProcessedSize = 0;
|
|
||||||
m_Pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteByte(byte b)
|
|
||||||
{
|
|
||||||
m_Buffer[m_Pos++] = b;
|
|
||||||
if (m_Pos >= m_BufferSize)
|
|
||||||
FlushData();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushData()
|
|
||||||
{
|
|
||||||
if (m_Pos == 0)
|
|
||||||
return;
|
|
||||||
m_Stream.Write(m_Buffer, 0, (int)m_Pos);
|
|
||||||
m_Pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// IMatchFinder.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
interface IInWindowStream
|
|
||||||
{
|
|
||||||
void SetStream(System.IO.Stream inStream);
|
|
||||||
void Init();
|
|
||||||
void ReleaseStream();
|
|
||||||
Byte GetIndexByte(Int32 index);
|
|
||||||
UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
|
|
||||||
UInt32 GetNumAvailableBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMatchFinder : IInWindowStream
|
|
||||||
{
|
|
||||||
void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
|
|
||||||
UInt32 GetMatches(UInt32[] distances);
|
|
||||||
void Skip(UInt32 num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,367 +0,0 @@
|
|||||||
// LzBinTree.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class BinTree : InWindow, IMatchFinder
|
|
||||||
{
|
|
||||||
UInt32 _cyclicBufferPos;
|
|
||||||
UInt32 _cyclicBufferSize = 0;
|
|
||||||
UInt32 _matchMaxLen;
|
|
||||||
|
|
||||||
UInt32[] _son;
|
|
||||||
UInt32[] _hash;
|
|
||||||
|
|
||||||
UInt32 _cutValue = 0xFF;
|
|
||||||
UInt32 _hashMask;
|
|
||||||
UInt32 _hashSizeSum = 0;
|
|
||||||
|
|
||||||
bool HASH_ARRAY = true;
|
|
||||||
|
|
||||||
const UInt32 kHash2Size = 1 << 10;
|
|
||||||
const UInt32 kHash3Size = 1 << 16;
|
|
||||||
const UInt32 kBT2HashSize = 1 << 16;
|
|
||||||
const UInt32 kStartMaxLen = 1;
|
|
||||||
const UInt32 kHash3Offset = kHash2Size;
|
|
||||||
const UInt32 kEmptyHashValue = 0;
|
|
||||||
const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
|
|
||||||
|
|
||||||
UInt32 kNumHashDirectBytes = 0;
|
|
||||||
UInt32 kMinMatchCheck = 4;
|
|
||||||
UInt32 kFixHashSize = kHash2Size + kHash3Size;
|
|
||||||
|
|
||||||
public void SetType(int numHashBytes)
|
|
||||||
{
|
|
||||||
HASH_ARRAY = (numHashBytes > 2);
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
kNumHashDirectBytes = 0;
|
|
||||||
kMinMatchCheck = 4;
|
|
||||||
kFixHashSize = kHash2Size + kHash3Size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kNumHashDirectBytes = 2;
|
|
||||||
kMinMatchCheck = 2 + 1;
|
|
||||||
kFixHashSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
|
|
||||||
public new void ReleaseStream() { base.ReleaseStream(); }
|
|
||||||
|
|
||||||
public new void Init()
|
|
||||||
{
|
|
||||||
base.Init();
|
|
||||||
for (UInt32 i = 0; i < _hashSizeSum; i++)
|
|
||||||
_hash[i] = kEmptyHashValue;
|
|
||||||
_cyclicBufferPos = 0;
|
|
||||||
ReduceOffsets(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public new void MovePos()
|
|
||||||
{
|
|
||||||
if (++_cyclicBufferPos >= _cyclicBufferSize)
|
|
||||||
_cyclicBufferPos = 0;
|
|
||||||
base.MovePos();
|
|
||||||
if (_pos == kMaxValForNormalize)
|
|
||||||
Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
|
|
||||||
|
|
||||||
public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
|
||||||
{ return base.GetMatchLen(index, distance, limit); }
|
|
||||||
|
|
||||||
public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
|
|
||||||
|
|
||||||
public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
|
|
||||||
{
|
|
||||||
if (historySize > kMaxValForNormalize - 256)
|
|
||||||
throw new Exception();
|
|
||||||
_cutValue = 16 + (matchMaxLen >> 1);
|
|
||||||
|
|
||||||
UInt32 windowReservSize = (historySize + keepAddBufferBefore +
|
|
||||||
matchMaxLen + keepAddBufferAfter) / 2 + 256;
|
|
||||||
|
|
||||||
base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
|
|
||||||
|
|
||||||
_matchMaxLen = matchMaxLen;
|
|
||||||
|
|
||||||
UInt32 cyclicBufferSize = historySize + 1;
|
|
||||||
if (_cyclicBufferSize != cyclicBufferSize)
|
|
||||||
_son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
|
|
||||||
|
|
||||||
UInt32 hs = kBT2HashSize;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
hs = historySize - 1;
|
|
||||||
hs |= (hs >> 1);
|
|
||||||
hs |= (hs >> 2);
|
|
||||||
hs |= (hs >> 4);
|
|
||||||
hs |= (hs >> 8);
|
|
||||||
hs >>= 1;
|
|
||||||
hs |= 0xFFFF;
|
|
||||||
if (hs > (1 << 24))
|
|
||||||
hs >>= 1;
|
|
||||||
_hashMask = hs;
|
|
||||||
hs++;
|
|
||||||
hs += kFixHashSize;
|
|
||||||
}
|
|
||||||
if (hs != _hashSizeSum)
|
|
||||||
_hash = new UInt32[_hashSizeSum = hs];
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetMatches(UInt32[] distances)
|
|
||||||
{
|
|
||||||
UInt32 lenLimit;
|
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
|
||||||
lenLimit = _matchMaxLen;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lenLimit = _streamPos - _pos;
|
|
||||||
if (lenLimit < kMinMatchCheck)
|
|
||||||
{
|
|
||||||
MovePos();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 offset = 0;
|
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
|
||||||
UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
|
|
||||||
UInt32 hashValue, hash2Value = 0, hash3Value = 0;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
|
||||||
hash2Value = temp & (kHash2Size - 1);
|
|
||||||
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
|
|
||||||
hash3Value = temp & (kHash3Size - 1);
|
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
|
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 curMatch2 = _hash[hash2Value];
|
|
||||||
UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
|
|
||||||
_hash[hash2Value] = _pos;
|
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
|
||||||
if (curMatch2 > matchMinPos)
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = 2;
|
|
||||||
distances[offset++] = _pos - curMatch2 - 1;
|
|
||||||
}
|
|
||||||
if (curMatch3 > matchMinPos)
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
|
|
||||||
{
|
|
||||||
if (curMatch3 == curMatch2)
|
|
||||||
offset -= 2;
|
|
||||||
distances[offset++] = maxLen = 3;
|
|
||||||
distances[offset++] = _pos - curMatch3 - 1;
|
|
||||||
curMatch2 = curMatch3;
|
|
||||||
}
|
|
||||||
if (offset != 0 && curMatch2 == curMatch)
|
|
||||||
{
|
|
||||||
offset -= 2;
|
|
||||||
maxLen = kStartMaxLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
|
||||||
UInt32 ptr1 = (_cyclicBufferPos << 1);
|
|
||||||
|
|
||||||
UInt32 len0, len1;
|
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
|
||||||
|
|
||||||
if (kNumHashDirectBytes != 0)
|
|
||||||
{
|
|
||||||
if (curMatch > matchMinPos)
|
|
||||||
{
|
|
||||||
if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
|
|
||||||
_bufferBase[cur + kNumHashDirectBytes])
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = kNumHashDirectBytes;
|
|
||||||
distances[offset++] = _pos - curMatch - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
|
||||||
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
if(curMatch <= matchMinPos || count-- == 0)
|
|
||||||
{
|
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UInt32 delta = _pos - curMatch;
|
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
|
||||||
(_cyclicBufferPos - delta) :
|
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
|
||||||
UInt32 len = Math.Min(len0, len1);
|
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
|
||||||
break;
|
|
||||||
if (maxLen < len)
|
|
||||||
{
|
|
||||||
distances[offset++] = maxLen = len;
|
|
||||||
distances[offset++] = delta - 1;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
_son[ptr1] = _son[cyclicPos];
|
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
_son[ptr1] = curMatch;
|
|
||||||
ptr1 = cyclicPos + 1;
|
|
||||||
curMatch = _son[ptr1];
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_son[ptr0] = curMatch;
|
|
||||||
ptr0 = cyclicPos;
|
|
||||||
curMatch = _son[ptr0];
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MovePos();
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Skip(UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 lenLimit;
|
|
||||||
if (_pos + _matchMaxLen <= _streamPos)
|
|
||||||
lenLimit = _matchMaxLen;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lenLimit = _streamPos - _pos;
|
|
||||||
if (lenLimit < kMinMatchCheck)
|
|
||||||
{
|
|
||||||
MovePos();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
|
|
||||||
UInt32 cur = _bufferOffset + _pos;
|
|
||||||
|
|
||||||
UInt32 hashValue;
|
|
||||||
|
|
||||||
if (HASH_ARRAY)
|
|
||||||
{
|
|
||||||
UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
|
|
||||||
UInt32 hash2Value = temp & (kHash2Size - 1);
|
|
||||||
_hash[hash2Value] = _pos;
|
|
||||||
temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
|
|
||||||
UInt32 hash3Value = temp & (kHash3Size - 1);
|
|
||||||
_hash[kHash3Offset + hash3Value] = _pos;
|
|
||||||
hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
|
|
||||||
|
|
||||||
UInt32 curMatch = _hash[kFixHashSize + hashValue];
|
|
||||||
_hash[kFixHashSize + hashValue] = _pos;
|
|
||||||
|
|
||||||
UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
|
|
||||||
UInt32 ptr1 = (_cyclicBufferPos << 1);
|
|
||||||
|
|
||||||
UInt32 len0, len1;
|
|
||||||
len0 = len1 = kNumHashDirectBytes;
|
|
||||||
|
|
||||||
UInt32 count = _cutValue;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (curMatch <= matchMinPos || count-- == 0)
|
|
||||||
{
|
|
||||||
_son[ptr0] = _son[ptr1] = kEmptyHashValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 delta = _pos - curMatch;
|
|
||||||
UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
|
|
||||||
(_cyclicBufferPos - delta) :
|
|
||||||
(_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
|
|
||||||
|
|
||||||
UInt32 pby1 = _bufferOffset + curMatch;
|
|
||||||
UInt32 len = Math.Min(len0, len1);
|
|
||||||
if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
while (++len != lenLimit)
|
|
||||||
if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
|
|
||||||
break;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
_son[ptr1] = _son[cyclicPos];
|
|
||||||
_son[ptr0] = _son[cyclicPos + 1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
|
|
||||||
{
|
|
||||||
_son[ptr1] = curMatch;
|
|
||||||
ptr1 = cyclicPos + 1;
|
|
||||||
curMatch = _son[ptr1];
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_son[ptr0] = curMatch;
|
|
||||||
ptr0 = cyclicPos;
|
|
||||||
curMatch = _son[ptr0];
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MovePos();
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
|
|
||||||
{
|
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
|
||||||
{
|
|
||||||
UInt32 value = items[i];
|
|
||||||
if (value <= subValue)
|
|
||||||
value = kEmptyHashValue;
|
|
||||||
else
|
|
||||||
value -= subValue;
|
|
||||||
items[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Normalize()
|
|
||||||
{
|
|
||||||
UInt32 subValue = _pos - _cyclicBufferSize;
|
|
||||||
NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
|
|
||||||
NormalizeLinks(_hash, _hashSizeSum, subValue);
|
|
||||||
ReduceOffsets((Int32)subValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
// LzInWindow.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class InWindow
|
|
||||||
{
|
|
||||||
public Byte[] _bufferBase = null; // pointer to buffer with data
|
|
||||||
System.IO.Stream _stream;
|
|
||||||
UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
|
|
||||||
bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
|
|
||||||
|
|
||||||
UInt32 _pointerToLastSafePosition;
|
|
||||||
|
|
||||||
public UInt32 _bufferOffset;
|
|
||||||
|
|
||||||
public UInt32 _blockSize; // Size of Allocated memory block
|
|
||||||
public UInt32 _pos; // offset (from _buffer) of curent byte
|
|
||||||
UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
|
|
||||||
UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
|
|
||||||
public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
|
|
||||||
|
|
||||||
public void MoveBlock()
|
|
||||||
{
|
|
||||||
UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
|
|
||||||
// we need one additional byte, since MovePos moves on 1 byte.
|
|
||||||
if (offset > 0)
|
|
||||||
offset--;
|
|
||||||
|
|
||||||
UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
|
|
||||||
|
|
||||||
// check negative offset ????
|
|
||||||
for (UInt32 i = 0; i < numBytes; i++)
|
|
||||||
_bufferBase[i] = _bufferBase[offset + i];
|
|
||||||
_bufferOffset -= offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ReadBlock()
|
|
||||||
{
|
|
||||||
if (_streamEndWasReached)
|
|
||||||
return;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
|
|
||||||
if (numReadBytes == 0)
|
|
||||||
{
|
|
||||||
_posLimit = _streamPos;
|
|
||||||
UInt32 pointerToPostion = _bufferOffset + _posLimit;
|
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
|
||||||
_posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
|
|
||||||
|
|
||||||
_streamEndWasReached = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_streamPos += (UInt32)numReadBytes;
|
|
||||||
if (_streamPos >= _pos + _keepSizeAfter)
|
|
||||||
_posLimit = _streamPos - _keepSizeAfter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Free() { _bufferBase = null; }
|
|
||||||
|
|
||||||
public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
|
|
||||||
{
|
|
||||||
_keepSizeBefore = keepSizeBefore;
|
|
||||||
_keepSizeAfter = keepSizeAfter;
|
|
||||||
UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
|
|
||||||
if (_bufferBase == null || _blockSize != blockSize)
|
|
||||||
{
|
|
||||||
Free();
|
|
||||||
_blockSize = blockSize;
|
|
||||||
_bufferBase = new Byte[_blockSize];
|
|
||||||
}
|
|
||||||
_pointerToLastSafePosition = _blockSize - keepSizeAfter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream) { _stream = stream; }
|
|
||||||
public void ReleaseStream() { _stream = null; }
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
_bufferOffset = 0;
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = 0;
|
|
||||||
_streamEndWasReached = false;
|
|
||||||
ReadBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MovePos()
|
|
||||||
{
|
|
||||||
_pos++;
|
|
||||||
if (_pos > _posLimit)
|
|
||||||
{
|
|
||||||
UInt32 pointerToPostion = _bufferOffset + _pos;
|
|
||||||
if (pointerToPostion > _pointerToLastSafePosition)
|
|
||||||
MoveBlock();
|
|
||||||
ReadBlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
|
|
||||||
|
|
||||||
// index + limit have not to exceed _keepSizeAfter;
|
|
||||||
public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
|
|
||||||
{
|
|
||||||
if (_streamEndWasReached)
|
|
||||||
if ((_pos + index) + limit > _streamPos)
|
|
||||||
limit = _streamPos - (UInt32)(_pos + index);
|
|
||||||
distance++;
|
|
||||||
// Byte *pby = _buffer + (size_t)_pos + index;
|
|
||||||
UInt32 pby = _bufferOffset + _pos + (UInt32)index;
|
|
||||||
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
|
|
||||||
|
|
||||||
public void ReduceOffsets(Int32 subValue)
|
|
||||||
{
|
|
||||||
_bufferOffset += (UInt32)subValue;
|
|
||||||
_posLimit -= (UInt32)subValue;
|
|
||||||
_pos -= (UInt32)subValue;
|
|
||||||
_streamPos -= (UInt32)subValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
// LzOutWindow.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZ
|
|
||||||
{
|
|
||||||
public class OutWindow
|
|
||||||
{
|
|
||||||
byte[] _buffer = null;
|
|
||||||
uint _pos;
|
|
||||||
uint _windowSize = 0;
|
|
||||||
uint _streamPos;
|
|
||||||
System.IO.Stream _stream;
|
|
||||||
|
|
||||||
public uint TrainSize = 0;
|
|
||||||
|
|
||||||
public void Create(uint windowSize)
|
|
||||||
{
|
|
||||||
if (_windowSize != windowSize)
|
|
||||||
{
|
|
||||||
// System.GC.Collect();
|
|
||||||
_buffer = new byte[windowSize];
|
|
||||||
}
|
|
||||||
_windowSize = windowSize;
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream, bool solid)
|
|
||||||
{
|
|
||||||
ReleaseStream();
|
|
||||||
_stream = stream;
|
|
||||||
if (!solid)
|
|
||||||
{
|
|
||||||
_streamPos = 0;
|
|
||||||
_pos = 0;
|
|
||||||
TrainSize = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
long len = stream.Length;
|
|
||||||
uint size = (len < _windowSize) ? (uint)len : _windowSize;
|
|
||||||
TrainSize = size;
|
|
||||||
stream.Position = len - size;
|
|
||||||
_streamPos = _pos = 0;
|
|
||||||
while (size > 0)
|
|
||||||
{
|
|
||||||
uint curSize = _windowSize - _pos;
|
|
||||||
if (size < curSize)
|
|
||||||
curSize = size;
|
|
||||||
int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
|
|
||||||
if (numReadBytes == 0)
|
|
||||||
return false;
|
|
||||||
size -= (uint)numReadBytes;
|
|
||||||
_pos += (uint)numReadBytes;
|
|
||||||
_streamPos += (uint)numReadBytes;
|
|
||||||
if (_pos == _windowSize)
|
|
||||||
_streamPos = _pos = 0;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
_stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Flush()
|
|
||||||
{
|
|
||||||
uint size = _pos - _streamPos;
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
_stream.Write(_buffer, (int)_streamPos, (int)size);
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
_pos = 0;
|
|
||||||
_streamPos = _pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CopyBlock(uint distance, uint len)
|
|
||||||
{
|
|
||||||
uint pos = _pos - distance - 1;
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos += _windowSize;
|
|
||||||
for (; len > 0; len--)
|
|
||||||
{
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos = 0;
|
|
||||||
_buffer[_pos++] = _buffer[pos++];
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PutByte(byte b)
|
|
||||||
{
|
|
||||||
_buffer[_pos++] = b;
|
|
||||||
if (_pos >= _windowSize)
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte GetByte(uint distance)
|
|
||||||
{
|
|
||||||
uint pos = _pos - distance - 1;
|
|
||||||
if (pos >= _windowSize)
|
|
||||||
pos += _windowSize;
|
|
||||||
return _buffer[pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
// LzmaBase.cs
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
|
||||||
{
|
|
||||||
internal abstract class Base
|
|
||||||
{
|
|
||||||
public const uint kNumRepDistances = 4;
|
|
||||||
public const uint kNumStates = 12;
|
|
||||||
|
|
||||||
// static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
|
|
||||||
// static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
|
|
||||||
// static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
|
|
||||||
// static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
|
|
||||||
|
|
||||||
public struct State
|
|
||||||
{
|
|
||||||
public uint Index;
|
|
||||||
public void Init() { Index = 0; }
|
|
||||||
public void UpdateChar()
|
|
||||||
{
|
|
||||||
if (Index < 4) Index = 0;
|
|
||||||
else if (Index < 10) Index -= 3;
|
|
||||||
else Index -= 6;
|
|
||||||
}
|
|
||||||
public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
|
|
||||||
public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
|
|
||||||
public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
|
|
||||||
public bool IsCharState() { return Index < 7; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int kNumPosSlotBits = 6;
|
|
||||||
public const int kDicLogSizeMin = 0;
|
|
||||||
// public const int kDicLogSizeMax = 30;
|
|
||||||
// public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
|
|
||||||
|
|
||||||
public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
|
|
||||||
public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
|
|
||||||
|
|
||||||
public const uint kMatchMinLen = 2;
|
|
||||||
|
|
||||||
public static uint GetLenToPosState(uint len)
|
|
||||||
{
|
|
||||||
len -= kMatchMinLen;
|
|
||||||
if (len < kNumLenToPosStates)
|
|
||||||
return len;
|
|
||||||
return (uint)(kNumLenToPosStates - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public const int kNumAlignBits = 4;
|
|
||||||
public const uint kAlignTableSize = 1 << kNumAlignBits;
|
|
||||||
public const uint kAlignMask = (kAlignTableSize - 1);
|
|
||||||
|
|
||||||
public const uint kStartPosModelIndex = 4;
|
|
||||||
public const uint kEndPosModelIndex = 14;
|
|
||||||
public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
|
|
||||||
|
|
||||||
public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
|
|
||||||
|
|
||||||
public const uint kNumLitPosStatesBitsEncodingMax = 4;
|
|
||||||
public const uint kNumLitContextBitsMax = 8;
|
|
||||||
|
|
||||||
public const int kNumPosStatesBitsMax = 4;
|
|
||||||
public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
|
|
||||||
public const int kNumPosStatesBitsEncodingMax = 4;
|
|
||||||
public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
|
|
||||||
|
|
||||||
public const int kNumLowLenBits = 3;
|
|
||||||
public const int kNumMidLenBits = 3;
|
|
||||||
public const int kNumHighLenBits = 8;
|
|
||||||
public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
|
|
||||||
public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
|
|
||||||
public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
|
|
||||||
(1 << kNumHighLenBits);
|
|
||||||
public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,398 +0,0 @@
|
|||||||
// LzmaDecoder.cs
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.LZMA
|
|
||||||
{
|
|
||||||
using RangeCoder;
|
|
||||||
|
|
||||||
public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
|
|
||||||
{
|
|
||||||
class LenDecoder
|
|
||||||
{
|
|
||||||
BitDecoder m_Choice = new BitDecoder();
|
|
||||||
BitDecoder m_Choice2 = new BitDecoder();
|
|
||||||
BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
|
||||||
BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
|
|
||||||
BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
|
|
||||||
uint m_NumPosStates = 0;
|
|
||||||
|
|
||||||
public void Create(uint numPosStates)
|
|
||||||
{
|
|
||||||
for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
|
|
||||||
{
|
|
||||||
m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
|
|
||||||
m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
|
|
||||||
}
|
|
||||||
m_NumPosStates = numPosStates;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
m_Choice.Init();
|
|
||||||
for (uint posState = 0; posState < m_NumPosStates; posState++)
|
|
||||||
{
|
|
||||||
m_LowCoder[posState].Init();
|
|
||||||
m_MidCoder[posState].Init();
|
|
||||||
}
|
|
||||||
m_Choice2.Init();
|
|
||||||
m_HighCoder.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
|
|
||||||
{
|
|
||||||
if (m_Choice.Decode(rangeDecoder) == 0)
|
|
||||||
return m_LowCoder[posState].Decode(rangeDecoder);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint symbol = Base.kNumLowLenSymbols;
|
|
||||||
if (m_Choice2.Decode(rangeDecoder) == 0)
|
|
||||||
symbol += m_MidCoder[posState].Decode(rangeDecoder);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
symbol += Base.kNumMidLenSymbols;
|
|
||||||
symbol += m_HighCoder.Decode(rangeDecoder);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LiteralDecoder
|
|
||||||
{
|
|
||||||
struct Decoder2
|
|
||||||
{
|
|
||||||
BitDecoder[] m_Decoders;
|
|
||||||
public void Create() { m_Decoders = new BitDecoder[0x300]; }
|
|
||||||
public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
|
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint symbol = 1;
|
|
||||||
do
|
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
|
||||||
while (symbol < 0x100);
|
|
||||||
return (byte)symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
|
|
||||||
{
|
|
||||||
uint symbol = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
uint matchBit = (uint)(matchByte >> 7) & 1;
|
|
||||||
matchByte <<= 1;
|
|
||||||
uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
|
|
||||||
symbol = (symbol << 1) | bit;
|
|
||||||
if (matchBit != bit)
|
|
||||||
{
|
|
||||||
while (symbol < 0x100)
|
|
||||||
symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
return (byte)symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Decoder2[] m_Coders;
|
|
||||||
int m_NumPrevBits;
|
|
||||||
int m_NumPosBits;
|
|
||||||
uint m_PosMask;
|
|
||||||
|
|
||||||
public void Create(int numPosBits, int numPrevBits)
|
|
||||||
{
|
|
||||||
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
|
|
||||||
m_NumPosBits == numPosBits)
|
|
||||||
return;
|
|
||||||
m_NumPosBits = numPosBits;
|
|
||||||
m_PosMask = ((uint)1 << numPosBits) - 1;
|
|
||||||
m_NumPrevBits = numPrevBits;
|
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
|
||||||
m_Coders = new Decoder2[numStates];
|
|
||||||
for (uint i = 0; i < numStates; i++)
|
|
||||||
m_Coders[i].Create();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
|
|
||||||
for (uint i = 0; i < numStates; i++)
|
|
||||||
m_Coders[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint GetState(uint pos, byte prevByte)
|
|
||||||
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
|
|
||||||
|
|
||||||
public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
|
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
|
|
||||||
|
|
||||||
public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
|
|
||||||
{ return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
|
|
||||||
};
|
|
||||||
|
|
||||||
LZ.OutWindow m_OutWindow = new LZ.OutWindow();
|
|
||||||
RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
|
|
||||||
|
|
||||||
BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
|
||||||
BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
|
|
||||||
BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
|
|
||||||
|
|
||||||
BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
|
|
||||||
BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
|
|
||||||
|
|
||||||
BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
|
|
||||||
|
|
||||||
LenDecoder m_LenDecoder = new LenDecoder();
|
|
||||||
LenDecoder m_RepLenDecoder = new LenDecoder();
|
|
||||||
|
|
||||||
LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
|
|
||||||
|
|
||||||
uint m_DictionarySize;
|
|
||||||
uint m_DictionarySizeCheck;
|
|
||||||
|
|
||||||
uint m_PosStateMask;
|
|
||||||
|
|
||||||
public Decoder()
|
|
||||||
{
|
|
||||||
m_DictionarySize = 0xFFFFFFFF;
|
|
||||||
for (int i = 0; i < Base.kNumLenToPosStates; i++)
|
|
||||||
m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDictionarySize(uint dictionarySize)
|
|
||||||
{
|
|
||||||
if (m_DictionarySize != dictionarySize)
|
|
||||||
{
|
|
||||||
m_DictionarySize = dictionarySize;
|
|
||||||
m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
|
|
||||||
uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
|
|
||||||
m_OutWindow.Create(blockSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLiteralProperties(int lp, int lc)
|
|
||||||
{
|
|
||||||
if (lp > 8)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
if (lc > 8)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
m_LiteralDecoder.Create(lp, lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPosBitsProperties(int pb)
|
|
||||||
{
|
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
uint numPosStates = (uint)1 << pb;
|
|
||||||
m_LenDecoder.Create(numPosStates);
|
|
||||||
m_RepLenDecoder.Create(numPosStates);
|
|
||||||
m_PosStateMask = numPosStates - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _solid = false;
|
|
||||||
void Init(System.IO.Stream inStream, System.IO.Stream outStream)
|
|
||||||
{
|
|
||||||
m_RangeDecoder.Init(inStream);
|
|
||||||
m_OutWindow.Init(outStream, _solid);
|
|
||||||
|
|
||||||
uint i;
|
|
||||||
for (i = 0; i < Base.kNumStates; i++)
|
|
||||||
{
|
|
||||||
for (uint j = 0; j <= m_PosStateMask; j++)
|
|
||||||
{
|
|
||||||
uint index = (i << Base.kNumPosStatesBitsMax) + j;
|
|
||||||
m_IsMatchDecoders[index].Init();
|
|
||||||
m_IsRep0LongDecoders[index].Init();
|
|
||||||
}
|
|
||||||
m_IsRepDecoders[i].Init();
|
|
||||||
m_IsRepG0Decoders[i].Init();
|
|
||||||
m_IsRepG1Decoders[i].Init();
|
|
||||||
m_IsRepG2Decoders[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_LiteralDecoder.Init();
|
|
||||||
for (i = 0; i < Base.kNumLenToPosStates; i++)
|
|
||||||
m_PosSlotDecoder[i].Init();
|
|
||||||
// m_PosSpecDecoder.Init();
|
|
||||||
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
|
|
||||||
m_PosDecoders[i].Init();
|
|
||||||
|
|
||||||
m_LenDecoder.Init();
|
|
||||||
m_RepLenDecoder.Init();
|
|
||||||
m_PosAlignDecoder.Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress)
|
|
||||||
{
|
|
||||||
Init(inStream, outStream);
|
|
||||||
|
|
||||||
Base.State state = new Base.State();
|
|
||||||
state.Init();
|
|
||||||
uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
|
|
||||||
|
|
||||||
UInt64 nowPos64 = 0;
|
|
||||||
UInt64 outSize64 = (UInt64)outSize;
|
|
||||||
if (nowPos64 < outSize64)
|
|
||||||
{
|
|
||||||
if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
|
|
||||||
throw new DataErrorException();
|
|
||||||
state.UpdateChar();
|
|
||||||
byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
|
|
||||||
m_OutWindow.PutByte(b);
|
|
||||||
nowPos64++;
|
|
||||||
}
|
|
||||||
while (nowPos64 < outSize64)
|
|
||||||
{
|
|
||||||
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
|
|
||||||
// while(nowPos64 < next)
|
|
||||||
{
|
|
||||||
uint posState = (uint)nowPos64 & m_PosStateMask;
|
|
||||||
if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
byte b;
|
|
||||||
byte prevByte = m_OutWindow.GetByte(0);
|
|
||||||
if (!state.IsCharState())
|
|
||||||
b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
|
|
||||||
(uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
|
|
||||||
else
|
|
||||||
b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
|
|
||||||
m_OutWindow.PutByte(b);
|
|
||||||
state.UpdateChar();
|
|
||||||
nowPos64++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint len;
|
|
||||||
if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
|
|
||||||
{
|
|
||||||
if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
state.UpdateShortRep();
|
|
||||||
m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
|
|
||||||
nowPos64++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
{
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
|
|
||||||
distance = rep2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
|
|
||||||
state.UpdateRep();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
|
|
||||||
state.UpdateMatch();
|
|
||||||
uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
|
|
||||||
if (posSlot >= Base.kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = (int)((posSlot >> 1) - 1);
|
|
||||||
rep0 = ((2 | (posSlot & 1)) << numDirectBits);
|
|
||||||
if (posSlot < Base.kEndPosModelIndex)
|
|
||||||
rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
|
|
||||||
rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep0 += (m_RangeDecoder.DecodeDirectBits(
|
|
||||||
numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
|
|
||||||
rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
}
|
|
||||||
if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
|
|
||||||
{
|
|
||||||
if (rep0 == 0xFFFFFFFF)
|
|
||||||
break;
|
|
||||||
throw new DataErrorException();
|
|
||||||
}
|
|
||||||
m_OutWindow.CopyBlock(rep0, len);
|
|
||||||
nowPos64 += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_OutWindow.Flush();
|
|
||||||
m_OutWindow.ReleaseStream();
|
|
||||||
m_RangeDecoder.ReleaseStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetDecoderProperties(byte[] properties)
|
|
||||||
{
|
|
||||||
if (properties.Length < 5)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
int lc = properties[0] % 9;
|
|
||||||
int remainder = properties[0] / 9;
|
|
||||||
int lp = remainder % 5;
|
|
||||||
int pb = remainder / 5;
|
|
||||||
if (pb > Base.kNumPosStatesBitsMax)
|
|
||||||
throw new InvalidParamException();
|
|
||||||
UInt32 dictionarySize = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
|
|
||||||
SetDictionarySize(dictionarySize);
|
|
||||||
SetLiteralProperties(lp, lc);
|
|
||||||
SetPosBitsProperties(pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Train(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
_solid = true;
|
|
||||||
return m_OutWindow.Train(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
public override bool CanRead { get { return true; }}
|
|
||||||
public override bool CanWrite { get { return true; }}
|
|
||||||
public override bool CanSeek { get { return true; }}
|
|
||||||
public override long Length { get { return 0; }}
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return 0; }
|
|
||||||
set { }
|
|
||||||
}
|
|
||||||
public override void Flush() { }
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
public override void SetLength(long value) {}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,234 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
class Encoder
|
|
||||||
{
|
|
||||||
public const uint kTopValue = (1 << 24);
|
|
||||||
|
|
||||||
System.IO.Stream Stream;
|
|
||||||
|
|
||||||
public UInt64 Low;
|
|
||||||
public uint Range;
|
|
||||||
uint _cacheSize;
|
|
||||||
byte _cache;
|
|
||||||
|
|
||||||
long StartPosition;
|
|
||||||
|
|
||||||
public void SetStream(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
Stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
StartPosition = Stream.Position;
|
|
||||||
|
|
||||||
Low = 0;
|
|
||||||
Range = 0xFFFFFFFF;
|
|
||||||
_cacheSize = 1;
|
|
||||||
_cache = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushData()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FlushStream()
|
|
||||||
{
|
|
||||||
Stream.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseStream()
|
|
||||||
{
|
|
||||||
Stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(uint start, uint size, uint total)
|
|
||||||
{
|
|
||||||
Low += start * (Range /= total);
|
|
||||||
Range *= size;
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShiftLow()
|
|
||||||
{
|
|
||||||
if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
|
|
||||||
{
|
|
||||||
byte temp = _cache;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Stream.WriteByte((byte)(temp + (Low >> 32)));
|
|
||||||
temp = 0xFF;
|
|
||||||
}
|
|
||||||
while (--_cacheSize != 0);
|
|
||||||
_cache = (byte)(((uint)Low) >> 24);
|
|
||||||
}
|
|
||||||
_cacheSize++;
|
|
||||||
Low = ((uint)Low) << 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EncodeDirectBits(uint v, int numTotalBits)
|
|
||||||
{
|
|
||||||
for (int i = numTotalBits - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
Range >>= 1;
|
|
||||||
if (((v >> i) & 1) == 1)
|
|
||||||
Low += Range;
|
|
||||||
if (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EncodeBit(uint size0, int numTotalBits, uint symbol)
|
|
||||||
{
|
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
|
||||||
if (symbol == 0)
|
|
||||||
Range = newBound;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Low += newBound;
|
|
||||||
Range -= newBound;
|
|
||||||
}
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Range <<= 8;
|
|
||||||
ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long GetProcessedSizeAdd()
|
|
||||||
{
|
|
||||||
return _cacheSize +
|
|
||||||
Stream.Position - StartPosition + 4;
|
|
||||||
// (long)Stream.GetProcessedSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Decoder
|
|
||||||
{
|
|
||||||
public const uint kTopValue = (1 << 24);
|
|
||||||
public uint Range;
|
|
||||||
public uint Code;
|
|
||||||
// public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
|
|
||||||
public System.IO.Stream Stream;
|
|
||||||
|
|
||||||
public void Init(System.IO.Stream stream)
|
|
||||||
{
|
|
||||||
// Stream.Init(stream);
|
|
||||||
Stream = stream;
|
|
||||||
|
|
||||||
Code = 0;
|
|
||||||
Range = 0xFFFFFFFF;
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseStream()
|
|
||||||
{
|
|
||||||
// Stream.ReleaseStream();
|
|
||||||
Stream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CloseStream()
|
|
||||||
{
|
|
||||||
Stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Normalize()
|
|
||||||
{
|
|
||||||
while (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
Range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Normalize2()
|
|
||||||
{
|
|
||||||
if (Range < kTopValue)
|
|
||||||
{
|
|
||||||
Code = (Code << 8) | (byte)Stream.ReadByte();
|
|
||||||
Range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetThreshold(uint total)
|
|
||||||
{
|
|
||||||
return Code / (Range /= total);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Decode(uint start, uint size, uint total)
|
|
||||||
{
|
|
||||||
Code -= start * Range;
|
|
||||||
Range *= size;
|
|
||||||
Normalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint DecodeDirectBits(int numTotalBits)
|
|
||||||
{
|
|
||||||
uint range = Range;
|
|
||||||
uint code = Code;
|
|
||||||
uint result = 0;
|
|
||||||
for (int i = numTotalBits; i > 0; i--)
|
|
||||||
{
|
|
||||||
range >>= 1;
|
|
||||||
/*
|
|
||||||
result <<= 1;
|
|
||||||
if (code >= range)
|
|
||||||
{
|
|
||||||
code -= range;
|
|
||||||
result |= 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
uint t = (code - range) >> 31;
|
|
||||||
code -= range & (t - 1);
|
|
||||||
result = (result << 1) | (1 - t);
|
|
||||||
|
|
||||||
if (range < kTopValue)
|
|
||||||
{
|
|
||||||
code = (code << 8) | (byte)Stream.ReadByte();
|
|
||||||
range <<= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Range = range;
|
|
||||||
Code = code;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint DecodeBit(uint size0, int numTotalBits)
|
|
||||||
{
|
|
||||||
uint newBound = (Range >> numTotalBits) * size0;
|
|
||||||
uint symbol;
|
|
||||||
if (Code < newBound)
|
|
||||||
{
|
|
||||||
symbol = 0;
|
|
||||||
Range = newBound;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
symbol = 1;
|
|
||||||
Code -= newBound;
|
|
||||||
Range -= newBound;
|
|
||||||
}
|
|
||||||
Normalize();
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
struct BitEncoder
|
|
||||||
{
|
|
||||||
public const int kNumBitModelTotalBits = 11;
|
|
||||||
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
|
|
||||||
const int kNumMoveBits = 5;
|
|
||||||
const int kNumMoveReducingBits = 2;
|
|
||||||
public const int kNumBitPriceShiftBits = 6;
|
|
||||||
|
|
||||||
uint Prob;
|
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
|
||||||
|
|
||||||
public void UpdateModel(uint symbol)
|
|
||||||
{
|
|
||||||
if (symbol == 0)
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
else
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(Encoder encoder, uint symbol)
|
|
||||||
{
|
|
||||||
// encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
|
|
||||||
// UpdateModel(symbol);
|
|
||||||
uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
|
|
||||||
if (symbol == 0)
|
|
||||||
{
|
|
||||||
encoder.Range = newBound;
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
encoder.Low += newBound;
|
|
||||||
encoder.Range -= newBound;
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
}
|
|
||||||
if (encoder.Range < Encoder.kTopValue)
|
|
||||||
{
|
|
||||||
encoder.Range <<= 8;
|
|
||||||
encoder.ShiftLow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
|
|
||||||
|
|
||||||
static BitEncoder()
|
|
||||||
{
|
|
||||||
const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
|
|
||||||
for (int i = kNumBits - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 start = (UInt32)1 << (kNumBits - i - 1);
|
|
||||||
UInt32 end = (UInt32)1 << (kNumBits - i);
|
|
||||||
for (UInt32 j = start; j < end; j++)
|
|
||||||
ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
|
|
||||||
(((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetPrice(uint symbol)
|
|
||||||
{
|
|
||||||
return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
|
|
||||||
}
|
|
||||||
public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
|
|
||||||
public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BitDecoder
|
|
||||||
{
|
|
||||||
public const int kNumBitModelTotalBits = 11;
|
|
||||||
public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
|
|
||||||
const int kNumMoveBits = 5;
|
|
||||||
|
|
||||||
uint Prob;
|
|
||||||
|
|
||||||
public void UpdateModel(int numMoveBits, uint symbol)
|
|
||||||
{
|
|
||||||
if (symbol == 0)
|
|
||||||
Prob += (kBitModelTotal - Prob) >> numMoveBits;
|
|
||||||
else
|
|
||||||
Prob -= (Prob) >> numMoveBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init() { Prob = kBitModelTotal >> 1; }
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
|
|
||||||
if (rangeDecoder.Code < newBound)
|
|
||||||
{
|
|
||||||
rangeDecoder.Range = newBound;
|
|
||||||
Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
|
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
|
||||||
{
|
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
|
||||||
rangeDecoder.Range <<= 8;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rangeDecoder.Range -= newBound;
|
|
||||||
rangeDecoder.Code -= newBound;
|
|
||||||
Prob -= (Prob) >> kNumMoveBits;
|
|
||||||
if (rangeDecoder.Range < Decoder.kTopValue)
|
|
||||||
{
|
|
||||||
rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
|
|
||||||
rangeDecoder.Range <<= 8;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip.Compression.RangeCoder
|
|
||||||
{
|
|
||||||
struct BitTreeEncoder
|
|
||||||
{
|
|
||||||
BitEncoder[] Models;
|
|
||||||
int NumBitLevels;
|
|
||||||
|
|
||||||
public BitTreeEncoder(int numBitLevels)
|
|
||||||
{
|
|
||||||
NumBitLevels = numBitLevels;
|
|
||||||
Models = new BitEncoder[1 << numBitLevels];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
|
||||||
Models[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encode(Encoder rangeEncoder, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; )
|
|
||||||
{
|
|
||||||
bitIndex--;
|
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (UInt32 i = 0; i < NumBitLevels; i++)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
Models[m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
symbol >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 GetPrice(UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; )
|
|
||||||
{
|
|
||||||
bitIndex--;
|
|
||||||
UInt32 bit = (symbol >> bitIndex) & 1;
|
|
||||||
price += Models[m].GetPrice(bit);
|
|
||||||
m = (m << 1) + bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UInt32 ReverseGetPrice(UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
symbol >>= 1;
|
|
||||||
price += Models[m].GetPrice(bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
|
|
||||||
int NumBitLevels, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 price = 0;
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = NumBitLevels; i > 0; i--)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
symbol >>= 1;
|
|
||||||
price += Models[startIndex + m].GetPrice(bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
}
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
|
|
||||||
Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
|
|
||||||
{
|
|
||||||
UInt32 m = 1;
|
|
||||||
for (int i = 0; i < NumBitLevels; i++)
|
|
||||||
{
|
|
||||||
UInt32 bit = symbol & 1;
|
|
||||||
Models[startIndex + m].Encode(rangeEncoder, bit);
|
|
||||||
m = (m << 1) | bit;
|
|
||||||
symbol >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BitTreeDecoder
|
|
||||||
{
|
|
||||||
BitDecoder[] Models;
|
|
||||||
int NumBitLevels;
|
|
||||||
|
|
||||||
public BitTreeDecoder(int numBitLevels)
|
|
||||||
{
|
|
||||||
NumBitLevels = numBitLevels;
|
|
||||||
Models = new BitDecoder[1 << numBitLevels];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
for (uint i = 1; i < (1 << NumBitLevels); i++)
|
|
||||||
Models[i].Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Decode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
|
|
||||||
m = (m << 1) + Models[m].Decode(rangeDecoder);
|
|
||||||
return m - ((uint)1 << NumBitLevels);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
uint symbol = 0;
|
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
|
||||||
{
|
|
||||||
uint bit = Models[m].Decode(rangeDecoder);
|
|
||||||
m <<= 1;
|
|
||||||
m += bit;
|
|
||||||
symbol |= (bit << bitIndex);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
|
|
||||||
RangeCoder.Decoder rangeDecoder, int NumBitLevels)
|
|
||||||
{
|
|
||||||
uint m = 1;
|
|
||||||
uint symbol = 0;
|
|
||||||
for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
|
|
||||||
{
|
|
||||||
uint bit = Models[startIndex + m].Decode(rangeDecoder);
|
|
||||||
m <<= 1;
|
|
||||||
m += bit;
|
|
||||||
symbol |= (bit << bitIndex);
|
|
||||||
}
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-157
@@ -1,157 +0,0 @@
|
|||||||
// ICoder.h
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace SevenZip
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The exception that is thrown when an error in input stream occurs during decoding.
|
|
||||||
/// </summary>
|
|
||||||
class DataErrorException : ApplicationException
|
|
||||||
{
|
|
||||||
public DataErrorException(): base("Data Error") { }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The exception that is thrown when the value of an argument is outside the allowable range.
|
|
||||||
/// </summary>
|
|
||||||
class InvalidParamException : ApplicationException
|
|
||||||
{
|
|
||||||
public InvalidParamException(): base("Invalid Parameter") { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ICodeProgress
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Callback progress.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inSize">
|
|
||||||
/// input size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outSize">
|
|
||||||
/// output size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
void SetProgress(Int64 inSize, Int64 outSize);
|
|
||||||
};
|
|
||||||
|
|
||||||
public interface ICoder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Codes streams.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inStream">
|
|
||||||
/// input Stream.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outStream">
|
|
||||||
/// output Stream.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="inSize">
|
|
||||||
/// input Size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="outSize">
|
|
||||||
/// output Size. -1 if unknown.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="progress">
|
|
||||||
/// callback progress reference.
|
|
||||||
/// </param>
|
|
||||||
/// <exception cref="SevenZip.DataErrorException">
|
|
||||||
/// if input stream is not valid
|
|
||||||
/// </exception>
|
|
||||||
void Code(System.IO.Stream inStream, System.IO.Stream outStream,
|
|
||||||
Int64 inSize, Int64 outSize, ICodeProgress progress);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
public interface ICoder2
|
|
||||||
{
|
|
||||||
void Code(ISequentialInStream []inStreams,
|
|
||||||
const UInt64 []inSizes,
|
|
||||||
ISequentialOutStream []outStreams,
|
|
||||||
UInt64 []outSizes,
|
|
||||||
ICodeProgress progress);
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides the fields that represent properties idenitifiers for compressing.
|
|
||||||
/// </summary>
|
|
||||||
public enum CoderPropID
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies default property.
|
|
||||||
/// </summary>
|
|
||||||
DefaultProp = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies size of dictionary.
|
|
||||||
/// </summary>
|
|
||||||
DictionarySize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies size of memory for PPM*.
|
|
||||||
/// </summary>
|
|
||||||
UsedMemorySize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies order for PPM methods.
|
|
||||||
/// </summary>
|
|
||||||
Order,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies Block Size.
|
|
||||||
/// </summary>
|
|
||||||
BlockSize,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of postion state bits for LZMA (0 <= x <= 4).
|
|
||||||
/// </summary>
|
|
||||||
PosStateBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of literal context bits for LZMA (0 <= x <= 8).
|
|
||||||
/// </summary>
|
|
||||||
LitContextBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of literal position bits for LZMA (0 <= x <= 4).
|
|
||||||
/// </summary>
|
|
||||||
LitPosBits,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of fast bytes for LZ*.
|
|
||||||
/// </summary>
|
|
||||||
NumFastBytes,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
|
|
||||||
/// </summary>
|
|
||||||
MatchFinder,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the number of match finder cyckes.
|
|
||||||
/// </summary>
|
|
||||||
MatchFinderCycles,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of passes.
|
|
||||||
/// </summary>
|
|
||||||
NumPasses,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies number of algorithm.
|
|
||||||
/// </summary>
|
|
||||||
Algorithm,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies the number of threads.
|
|
||||||
/// </summary>
|
|
||||||
NumThreads,
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies mode with end marker.
|
|
||||||
/// </summary>
|
|
||||||
EndMarker
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public interface ISetCoderProperties
|
|
||||||
{
|
|
||||||
void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
|
|
||||||
};
|
|
||||||
|
|
||||||
public interface IWriteCoderProperties
|
|
||||||
{
|
|
||||||
void WriteCoderProperties(System.IO.Stream outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ISetDecoderProperties
|
|
||||||
{
|
|
||||||
void SetDecoderProperties(byte[] properties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
internal class Block
|
|
||||||
{
|
|
||||||
public Block()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Position { get; set; }
|
|
||||||
|
|
||||||
public byte[] Data { get; set; }
|
|
||||||
|
|
||||||
public int Available { get; set; }
|
|
||||||
|
|
||||||
public bool Equals(Block other)
|
|
||||||
{
|
|
||||||
return Position == other.Position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
internal class BlockCache<T>
|
|
||||||
where T : Block, new()
|
|
||||||
{
|
|
||||||
private int _blockSize;
|
|
||||||
private Dictionary<long, T> _blocks;
|
|
||||||
private LinkedList<T> _lru;
|
|
||||||
private List<T> _freeBlocks;
|
|
||||||
private int _blocksCreated;
|
|
||||||
private int _totalBlocks;
|
|
||||||
|
|
||||||
private int _freeBlockCount;
|
|
||||||
|
|
||||||
public BlockCache(int blockSize, int blockCount)
|
|
||||||
{
|
|
||||||
_blockSize = blockSize;
|
|
||||||
_totalBlocks = blockCount;
|
|
||||||
|
|
||||||
_blocks = new Dictionary<long, T>();
|
|
||||||
_lru = new LinkedList<T>();
|
|
||||||
_freeBlocks = new List<T>(_totalBlocks);
|
|
||||||
|
|
||||||
_freeBlockCount = _totalBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int FreeBlockCount
|
|
||||||
{
|
|
||||||
get { return _freeBlockCount; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsBlock(long position)
|
|
||||||
{
|
|
||||||
return _blocks.ContainsKey(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetBlock(long position, out T block)
|
|
||||||
{
|
|
||||||
if (_blocks.TryGetValue(position, out block))
|
|
||||||
{
|
|
||||||
_lru.Remove(block);
|
|
||||||
_lru.AddFirst(block);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetBlock(long position)
|
|
||||||
{
|
|
||||||
T result;
|
|
||||||
|
|
||||||
if (TryGetBlock(position, out result))
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = GetFreeBlock();
|
|
||||||
result.Position = position;
|
|
||||||
result.Available = -1;
|
|
||||||
StoreBlock(result);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseBlock(long position)
|
|
||||||
{
|
|
||||||
T block;
|
|
||||||
if (_blocks.TryGetValue(position, out block))
|
|
||||||
{
|
|
||||||
_blocks.Remove(position);
|
|
||||||
_lru.Remove(block);
|
|
||||||
_freeBlocks.Add(block);
|
|
||||||
_freeBlockCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StoreBlock(T block)
|
|
||||||
{
|
|
||||||
_blocks[block.Position] = block;
|
|
||||||
_lru.AddFirst(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
private T GetFreeBlock()
|
|
||||||
{
|
|
||||||
T block;
|
|
||||||
|
|
||||||
if (_freeBlocks.Count > 0)
|
|
||||||
{
|
|
||||||
int idx = _freeBlocks.Count - 1;
|
|
||||||
block = _freeBlocks[idx];
|
|
||||||
_freeBlocks.RemoveAt(idx);
|
|
||||||
_freeBlockCount--;
|
|
||||||
}
|
|
||||||
else if (_blocksCreated < _totalBlocks)
|
|
||||||
{
|
|
||||||
block = new T();
|
|
||||||
block.Data = new byte[_blockSize];
|
|
||||||
_blocksCreated++;
|
|
||||||
_freeBlockCount--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
block = _lru.Last.Value;
|
|
||||||
_lru.RemoveLast();
|
|
||||||
_blocks.Remove(block.Position);
|
|
||||||
}
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Settings controlling BlockCache instances.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BlockCacheSettings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BlockCacheSettings class.
|
|
||||||
/// </summary>
|
|
||||||
public BlockCacheSettings()
|
|
||||||
{
|
|
||||||
this.BlockSize = (int)(4 * Sizes.OneKiB);
|
|
||||||
this.ReadCacheSize = 4 * Sizes.OneMiB;
|
|
||||||
this.LargeReadSize = 64 * Sizes.OneKiB;
|
|
||||||
this.OptimumReadSize = (int)(64 * Sizes.OneKiB);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BlockCacheSettings class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="settings">The cache settings.</param>
|
|
||||||
internal BlockCacheSettings(BlockCacheSettings settings)
|
|
||||||
{
|
|
||||||
this.BlockSize = settings.BlockSize;
|
|
||||||
this.ReadCacheSize = settings.ReadCacheSize;
|
|
||||||
this.LargeReadSize = settings.LargeReadSize;
|
|
||||||
this.OptimumReadSize = settings.OptimumReadSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the size (in bytes) of each cached block.
|
|
||||||
/// </summary>
|
|
||||||
public int BlockSize { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the size (in bytes) of the read cache.
|
|
||||||
/// </summary>
|
|
||||||
public long ReadCacheSize { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the maximum read size that will be cached.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Large reads are not cached, on the assumption they will not
|
|
||||||
/// be repeated. This setting controls what is considered 'large'.
|
|
||||||
/// Any read that is more than this many bytes will not be cached.</remarks>
|
|
||||||
public long LargeReadSize { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the optimum size of a read to the wrapped stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This value must be a multiple of BlockSize.</remarks>
|
|
||||||
public int OptimumReadSize { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Statistical information about the effectiveness of a BlockCache instance.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BlockCacheStatistics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of requested 'large' reads, as defined by the LargeReadSize setting.
|
|
||||||
/// </summary>
|
|
||||||
public long LargeReadsIn { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of requested unaligned reads.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Unaligned reads are reads where the read doesn't start on a multiple of
|
|
||||||
/// the block size.</remarks>
|
|
||||||
public long UnalignedReadsIn { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total number of requested reads.
|
|
||||||
/// </summary>
|
|
||||||
public long TotalReadsIn { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total number of reads passed on by the cache.
|
|
||||||
/// </summary>
|
|
||||||
public long TotalReadsOut { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of times a read request was serviced (in part or whole) from the cache.
|
|
||||||
/// </summary>
|
|
||||||
public long ReadCacheHits { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of time a read request was serviced (in part or whole) from the wrapped stream.
|
|
||||||
/// </summary>
|
|
||||||
public long ReadCacheMisses { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of requested unaligned writes.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Unaligned writes are writes where the write doesn't start on a multiple of
|
|
||||||
/// the block size.</remarks>
|
|
||||||
public long UnalignedWritesIn { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total number of requested writes.
|
|
||||||
/// </summary>
|
|
||||||
public long TotalWritesIn { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of free blocks in the read cache.
|
|
||||||
/// </summary>
|
|
||||||
public int FreeReadBlocks { get; internal set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,472 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A stream implementing a block-oriented read cache.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BlockCacheStream : SparseStream
|
|
||||||
{
|
|
||||||
private SparseStream _wrappedStream;
|
|
||||||
private Ownership _ownWrapped;
|
|
||||||
private BlockCacheSettings _settings;
|
|
||||||
private BlockCacheStatistics _stats;
|
|
||||||
|
|
||||||
private long _position;
|
|
||||||
private bool _atEof;
|
|
||||||
|
|
||||||
private BlockCache<Block> _cache;
|
|
||||||
private byte[] _readBuffer;
|
|
||||||
private int _blocksInReadBuffer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BlockCacheStream class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="toWrap">The stream to wrap.</param>
|
|
||||||
/// <param name="ownership">Whether to assume ownership of <c>toWrap</c>.</param>
|
|
||||||
public BlockCacheStream(SparseStream toWrap, Ownership ownership)
|
|
||||||
: this(toWrap, ownership, new BlockCacheSettings())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BlockCacheStream class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="toWrap">The stream to wrap.</param>
|
|
||||||
/// <param name="ownership">Whether to assume ownership of <c>toWrap</c>.</param>
|
|
||||||
/// <param name="settings">The cache settings.</param>
|
|
||||||
public BlockCacheStream(SparseStream toWrap, Ownership ownership, BlockCacheSettings settings)
|
|
||||||
{
|
|
||||||
if (!toWrap.CanRead)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The wrapped stream does not support reading", "toWrap");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!toWrap.CanSeek)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The wrapped stream does not support seeking", "toWrap");
|
|
||||||
}
|
|
||||||
|
|
||||||
_wrappedStream = toWrap;
|
|
||||||
_ownWrapped = ownership;
|
|
||||||
_settings = new BlockCacheSettings(settings);
|
|
||||||
|
|
||||||
if (_settings.OptimumReadSize % _settings.BlockSize != 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid settings, OptimumReadSize must be a multiple of BlockSize", "settings");
|
|
||||||
}
|
|
||||||
|
|
||||||
_readBuffer = new byte[_settings.OptimumReadSize];
|
|
||||||
_blocksInReadBuffer = _settings.OptimumReadSize / _settings.BlockSize;
|
|
||||||
|
|
||||||
int totalBlocks = (int)(_settings.ReadCacheSize / _settings.BlockSize);
|
|
||||||
|
|
||||||
_cache = new BlockCache<Block>(_settings.BlockSize, totalBlocks);
|
|
||||||
_stats = new BlockCacheStatistics();
|
|
||||||
_stats.FreeReadBlocks = totalBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of the stream that are stored.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This may be an empty enumeration if all bytes are zero.</remarks>
|
|
||||||
public override IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _wrappedStream.Extents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication as to whether the stream can be read.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication as to whether the stream position can be changed.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication as to whether the stream can be written to.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return _wrappedStream.CanWrite; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _wrappedStream.Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets and sets the current stream position.
|
|
||||||
/// </summary>
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
_position = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the performance statistics for this instance.
|
|
||||||
/// </summary>
|
|
||||||
public BlockCacheStatistics Statistics
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
_stats.FreeReadBlocks = _cache.FreeBlockCount;
|
|
||||||
return _stats;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of a stream that are stored, within a specified range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="start">The offset of the first byte of interest.</param>
|
|
||||||
/// <param name="count">The number of bytes of interest.</param>
|
|
||||||
/// <returns>An enumeration of stream extents, indicating stored bytes.</returns>
|
|
||||||
public override IEnumerable<StreamExtent> GetExtentsInRange(long start, long count)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _wrappedStream.GetExtentsInRange(start, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads data from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to fill.</param>
|
|
||||||
/// <param name="offset">The buffer offset to start from.</param>
|
|
||||||
/// <param name="count">The number of bytes to read.</param>
|
|
||||||
/// <returns>The number of bytes read.</returns>
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
if (_position >= Length)
|
|
||||||
{
|
|
||||||
if (_atEof)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to read beyond end of stream");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_atEof = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_stats.TotalReadsIn++;
|
|
||||||
|
|
||||||
if (count > _settings.LargeReadSize)
|
|
||||||
{
|
|
||||||
_stats.LargeReadsIn++;
|
|
||||||
_stats.TotalReadsOut++;
|
|
||||||
_wrappedStream.Position = _position;
|
|
||||||
int numRead = _wrappedStream.Read(buffer, offset, count);
|
|
||||||
_position = _wrappedStream.Position;
|
|
||||||
|
|
||||||
if (_position >= Length)
|
|
||||||
{
|
|
||||||
_atEof = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalBytesRead = 0;
|
|
||||||
bool servicedFromCache = false;
|
|
||||||
bool servicedOutsideCache = false;
|
|
||||||
int blockSize = _settings.BlockSize;
|
|
||||||
|
|
||||||
long firstBlock = _position / blockSize;
|
|
||||||
int offsetInNextBlock = (int)(_position % blockSize);
|
|
||||||
long endBlock = Utilities.Ceil(Math.Min(_position + count, Length), blockSize);
|
|
||||||
int numBlocks = (int)(endBlock - firstBlock);
|
|
||||||
|
|
||||||
if (offsetInNextBlock != 0)
|
|
||||||
{
|
|
||||||
_stats.UnalignedReadsIn++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int blocksRead = 0;
|
|
||||||
while (blocksRead < numBlocks)
|
|
||||||
{
|
|
||||||
Block block;
|
|
||||||
|
|
||||||
// Read from the cache as much as possible
|
|
||||||
while (blocksRead < numBlocks && _cache.TryGetBlock(firstBlock + blocksRead, out block))
|
|
||||||
{
|
|
||||||
int bytesToRead = Math.Min(count - totalBytesRead, block.Available - offsetInNextBlock);
|
|
||||||
|
|
||||||
Array.Copy(block.Data, offsetInNextBlock, buffer, offset + totalBytesRead, bytesToRead);
|
|
||||||
offsetInNextBlock = 0;
|
|
||||||
totalBytesRead += bytesToRead;
|
|
||||||
_position += bytesToRead;
|
|
||||||
blocksRead++;
|
|
||||||
|
|
||||||
servicedFromCache = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now handle a sequence of (one or more) blocks that are not cached
|
|
||||||
if (blocksRead < numBlocks && !_cache.ContainsBlock(firstBlock + blocksRead))
|
|
||||||
{
|
|
||||||
servicedOutsideCache = true;
|
|
||||||
|
|
||||||
// Figure out how many blocks to read from the wrapped stream
|
|
||||||
int blocksToRead = 0;
|
|
||||||
while (blocksRead + blocksToRead < numBlocks
|
|
||||||
&& blocksToRead < _blocksInReadBuffer
|
|
||||||
&& !_cache.ContainsBlock(firstBlock + blocksRead + blocksToRead))
|
|
||||||
{
|
|
||||||
++blocksToRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow for the end of the stream not being block-aligned
|
|
||||||
long readPosition = (firstBlock + blocksRead) * (long)blockSize;
|
|
||||||
int bytesToRead = (int)Math.Min(blocksToRead * (long)blockSize, Length - readPosition);
|
|
||||||
|
|
||||||
// Do the read
|
|
||||||
_stats.TotalReadsOut++;
|
|
||||||
_wrappedStream.Position = readPosition;
|
|
||||||
int bytesRead = Utilities.ReadFully(_wrappedStream, _readBuffer, 0, bytesToRead);
|
|
||||||
if (bytesRead != bytesToRead)
|
|
||||||
{
|
|
||||||
throw new IOException("Short read before end of stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the read blocks
|
|
||||||
for (int i = 0; i < blocksToRead; ++i)
|
|
||||||
{
|
|
||||||
int copyBytes = Math.Min(blockSize, bytesToRead - (i * blockSize));
|
|
||||||
block = _cache.GetBlock(firstBlock + blocksRead + i);
|
|
||||||
Array.Copy(_readBuffer, i * blockSize, block.Data, 0, copyBytes);
|
|
||||||
block.Available = copyBytes;
|
|
||||||
|
|
||||||
if (copyBytes < blockSize)
|
|
||||||
{
|
|
||||||
Array.Clear(_readBuffer, (i * blockSize) + copyBytes, blockSize - copyBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blocksRead += blocksToRead;
|
|
||||||
|
|
||||||
// Propogate the data onto the caller
|
|
||||||
int bytesToCopy = Math.Min(count - totalBytesRead, bytesRead - offsetInNextBlock);
|
|
||||||
Array.Copy(_readBuffer, offsetInNextBlock, buffer, offset + totalBytesRead, bytesToCopy);
|
|
||||||
totalBytesRead += bytesToCopy;
|
|
||||||
_position += bytesToCopy;
|
|
||||||
offsetInNextBlock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_position >= Length && totalBytesRead == 0)
|
|
||||||
{
|
|
||||||
_atEof = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (servicedFromCache)
|
|
||||||
{
|
|
||||||
_stats.ReadCacheHits++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (servicedOutsideCache)
|
|
||||||
{
|
|
||||||
_stats.ReadCacheMisses++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalBytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
_wrappedStream.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves the stream position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">The origin-relative location.</param>
|
|
||||||
/// <param name="origin">The base location.</param>
|
|
||||||
/// <returns>The new absolute stream position.</returns>
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
long effectiveOffset = offset;
|
|
||||||
if (origin == SeekOrigin.Current)
|
|
||||||
{
|
|
||||||
effectiveOffset += _position;
|
|
||||||
}
|
|
||||||
else if (origin == SeekOrigin.End)
|
|
||||||
{
|
|
||||||
effectiveOffset += Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
_atEof = false;
|
|
||||||
|
|
||||||
if (effectiveOffset < 0)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to move before beginning of disk");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_position = effectiveOffset;
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the length of the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The new length.</param>
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
_wrappedStream.SetLength(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes data to the stream at the current location.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The data to write.</param>
|
|
||||||
/// <param name="offset">The first byte to write from buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to write.</param>
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
_stats.TotalWritesIn++;
|
|
||||||
|
|
||||||
int blockSize = _settings.BlockSize;
|
|
||||||
long firstBlock = _position / blockSize;
|
|
||||||
long endBlock = Utilities.Ceil(Math.Min(_position + count, Length), blockSize);
|
|
||||||
int numBlocks = (int)(endBlock - firstBlock);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_wrappedStream.Position = _position;
|
|
||||||
_wrappedStream.Write(buffer, offset, count);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
InvalidateBlocks(firstBlock, numBlocks);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
int offsetInNextBlock = (int)(_position % blockSize);
|
|
||||||
if (offsetInNextBlock != 0)
|
|
||||||
{
|
|
||||||
_stats.UnalignedWritesIn++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each block touched, if it's cached, update it
|
|
||||||
int bytesProcessed = 0;
|
|
||||||
for (int i = 0; i < numBlocks; ++i)
|
|
||||||
{
|
|
||||||
int bufferPos = offset + bytesProcessed;
|
|
||||||
int bytesThisBlock = Math.Min(count - bytesProcessed, blockSize - offsetInNextBlock);
|
|
||||||
|
|
||||||
Block block;
|
|
||||||
if (_cache.TryGetBlock(firstBlock + i, out block))
|
|
||||||
{
|
|
||||||
Array.Copy(buffer, bufferPos, block.Data, offsetInNextBlock, bytesThisBlock);
|
|
||||||
block.Available = Math.Max(block.Available, offsetInNextBlock + bytesThisBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetInNextBlock = 0;
|
|
||||||
bytesProcessed += bytesThisBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
_position += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of this instance, freeing up associated resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing"><c>true</c> if invoked from <c>Dispose</c>, else <c>false</c>.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
if (_wrappedStream != null && _ownWrapped == Ownership.Dispose)
|
|
||||||
{
|
|
||||||
_wrappedStream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_wrappedStream = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckDisposed()
|
|
||||||
{
|
|
||||||
if (_wrappedStream == null)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException("BlockCacheStream");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InvalidateBlocks(long firstBlock, int numBlocks)
|
|
||||||
{
|
|
||||||
for (long i = firstBlock; i < (firstBlock + numBlocks); ++i)
|
|
||||||
{
|
|
||||||
_cache.ReleaseBlock(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of known application image types.
|
|
||||||
/// </summary>
|
|
||||||
public enum ApplicationImageType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown type.
|
|
||||||
/// </summary>
|
|
||||||
None = 0x0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Firmware application.
|
|
||||||
/// </summary>
|
|
||||||
Firmware = 0x1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Windows boot loader.
|
|
||||||
/// </summary>
|
|
||||||
WindowsBoot = 0x2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Legacy boot loader.
|
|
||||||
/// </summary>
|
|
||||||
LegacyLoader = 0x3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Real mode boot loader.
|
|
||||||
/// </summary>
|
|
||||||
RealMode = 0x4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of known application types.
|
|
||||||
/// </summary>
|
|
||||||
public enum ApplicationType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown type.
|
|
||||||
/// </summary>
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Firmware boot manager (e.g. UEFI).
|
|
||||||
/// </summary>
|
|
||||||
FirmwareBootManager = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Windows boot manager.
|
|
||||||
/// </summary>
|
|
||||||
BootManager = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Operating System Loader.
|
|
||||||
/// </summary>
|
|
||||||
OsLoader = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resume loader.
|
|
||||||
/// </summary>
|
|
||||||
Resume = 4,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Memory diagnostic application.
|
|
||||||
/// </summary>
|
|
||||||
MemoryDiagnostics = 5,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Legacy NT loader application.
|
|
||||||
/// </summary>
|
|
||||||
NtLoader = 6,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Windows setup application.
|
|
||||||
/// </summary>
|
|
||||||
SetupLoader = 7,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Boot sector application.
|
|
||||||
/// </summary>
|
|
||||||
BootSector = 8,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Startup application.
|
|
||||||
/// </summary>
|
|
||||||
Startup = 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for BCD storage repositories.
|
|
||||||
/// </summary>
|
|
||||||
internal abstract class BaseStorage
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Tests if an element is present (i.e. has a value) on an object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to inspect.</param>
|
|
||||||
/// <param name="element">The element to inspect.</param>
|
|
||||||
/// <returns><c>true</c> if present, else <c>false</c>.</returns>
|
|
||||||
public abstract bool HasValue(Guid obj, int element);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the value of a string element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to inspect.</param>
|
|
||||||
/// <param name="element">The element to retrieve.</param>
|
|
||||||
/// <returns>The value as a string.</returns>
|
|
||||||
public abstract string GetString(Guid obj, int element);
|
|
||||||
|
|
||||||
public abstract byte[] GetBinary(Guid obj, int element);
|
|
||||||
|
|
||||||
public abstract void SetString(Guid obj, int element, string value);
|
|
||||||
|
|
||||||
public abstract void SetBinary(Guid obj, int element, byte[] value);
|
|
||||||
|
|
||||||
public abstract string[] GetMultiString(Guid obj, int element);
|
|
||||||
|
|
||||||
public abstract void SetMultiString(Guid obj, int element, string[] values);
|
|
||||||
|
|
||||||
public abstract IEnumerable<Guid> EnumerateObjects();
|
|
||||||
|
|
||||||
public abstract IEnumerable<int> EnumerateElements(Guid obj);
|
|
||||||
|
|
||||||
public abstract int GetObjectType(Guid obj);
|
|
||||||
|
|
||||||
public abstract bool ObjectExists(Guid obj);
|
|
||||||
|
|
||||||
public abstract Guid CreateObject(Guid obj, int type);
|
|
||||||
|
|
||||||
public abstract void CreateElement(Guid obj, int element);
|
|
||||||
|
|
||||||
public abstract void DeleteObject(Guid obj);
|
|
||||||
|
|
||||||
public abstract void DeleteElement(Guid obj, int element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,365 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbolic names of BCD Objects taken from Geoff Chappell's website:
|
|
||||||
// http://www.geoffchappell.com/viewer.htm?doc=notes/windows/boot/bcd/objects.htm
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a Boot Configuration Database object (application, device or inherited settings).
|
|
||||||
/// </summary>
|
|
||||||
public class BcdObject
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Emergency Management Services settings.
|
|
||||||
/// </summary>
|
|
||||||
public const string EmsSettingsGroupId = "{0CE4991B-E6B3-4B16-B23C-5E0D9250E5D9}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for the Resume boot loader.
|
|
||||||
/// </summary>
|
|
||||||
public const string ResumeLoaderSettingsGroupId = "{1AFA9C49-16AB-4A5C-4A90-212802DA9460}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Alias for the Default boot entry.
|
|
||||||
/// </summary>
|
|
||||||
public const string DefaultBootEntryId = "{1CAE1EB7-A0DF-4D4D-9851-4860E34EF535}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Emergency Management Services settings.
|
|
||||||
/// </summary>
|
|
||||||
public const string DebuggerSettingsGroupId = "{4636856E-540F-4170-A130-A84776F4C654}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for NTLDR application.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsLegacyNtldrId = "{466F5A88-0AF2-4F76-9038-095B170DC21C}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for bad memory settings.
|
|
||||||
/// </summary>
|
|
||||||
public const string BadMemoryGroupId = "{5189B25C-5558-4BF2-BCA4-289B11BD29E2}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Boot Loader settings.
|
|
||||||
/// </summary>
|
|
||||||
public const string BootLoaderSettingsGroupId = "{6EFB52BF-1766-41DB-A6B3-0EE5EFF72BD7}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for EFI setup.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsSetupEfiId = "{7254A080-1510-4E85-AC0F-E7FB3D444736}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Global settings.
|
|
||||||
/// </summary>
|
|
||||||
public const string GlobalSettingsGroupId = "{7EA2E1AC-2E61-4728-AAA3-896D9D0A9F0E}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Windows Boot Manager.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsBootManagerId = "{9DEA862C-5CDD-4E70-ACC1-F32B344D4795}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for PCAT Template.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsOsTargetTemplatePcatId = "{A1943BBC-EA85-487C-97C7-C9EDE908A38A}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Firmware Boot Manager.
|
|
||||||
/// </summary>
|
|
||||||
public const string FirmwareBootManagerId = "{A5A30FA2-3D06-4E9F-B5F4-A01DF9D1FCBA}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Windows Setup RAMDISK options.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsSetupRamdiskOptionsId = "{AE5534E0-A924-466C-B836-758539A3EE3A}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for EFI template.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsOsTargetTemplateEfiId = "{B012B84D-C47C-4ED5-B722-C0C42163E569}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Windows memory tester application.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsMemoryTesterId = "{B2721D73-1DB4-4C62-BF78-C548A880142D}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Well-known object for Windows PCAT setup.
|
|
||||||
/// </summary>
|
|
||||||
public const string WindowsSetupPcatId = "{CBD971BF-B7B8-4885-951A-FA03044F5D71}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Alias for the current boot entry.
|
|
||||||
/// </summary>
|
|
||||||
public const string CurrentBootEntryId = "{FA926493-6F1C-4193-A414-58F0B2456D1E}";
|
|
||||||
|
|
||||||
private static Dictionary<string, Guid> s_nameToGuid;
|
|
||||||
private static Dictionary<Guid, string> s_guidToName;
|
|
||||||
|
|
||||||
private BaseStorage _storage;
|
|
||||||
private Guid _id;
|
|
||||||
private int _type;
|
|
||||||
|
|
||||||
static BcdObject()
|
|
||||||
{
|
|
||||||
s_nameToGuid = new Dictionary<string, Guid>();
|
|
||||||
s_guidToName = new Dictionary<Guid, string>();
|
|
||||||
|
|
||||||
AddMapping("{emssettings}", EmsSettingsGroupId);
|
|
||||||
AddMapping("{resumeloadersettings}", ResumeLoaderSettingsGroupId);
|
|
||||||
AddMapping("{default}", DefaultBootEntryId);
|
|
||||||
AddMapping("{dbgsettings}", DebuggerSettingsGroupId);
|
|
||||||
AddMapping("{legacy}", WindowsLegacyNtldrId);
|
|
||||||
AddMapping("{ntldr}", WindowsLegacyNtldrId);
|
|
||||||
AddMapping("{badmemory}", BadMemoryGroupId);
|
|
||||||
AddMapping("{bootloadersettings}", BootLoaderSettingsGroupId);
|
|
||||||
AddMapping("{globalsettings}", GlobalSettingsGroupId);
|
|
||||||
AddMapping("{bootmgr}", WindowsBootManagerId);
|
|
||||||
AddMapping("{fwbootmgr}", FirmwareBootManagerId);
|
|
||||||
AddMapping("{ramdiskoptions}", WindowsSetupRamdiskOptionsId);
|
|
||||||
AddMapping("{memdiag}", WindowsMemoryTesterId);
|
|
||||||
AddMapping("{current}", CurrentBootEntryId);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal BcdObject(BaseStorage store, Guid id)
|
|
||||||
{
|
|
||||||
_storage = store;
|
|
||||||
_id = id;
|
|
||||||
_type = _storage.GetObjectType(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the identity of this object.
|
|
||||||
/// </summary>
|
|
||||||
public Guid Identity
|
|
||||||
{
|
|
||||||
get { return _id; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the friendly name for this object, if known.
|
|
||||||
/// </summary>
|
|
||||||
public string FriendlyName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string name;
|
|
||||||
if (s_guidToName.TryGetValue(_id, out name))
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _id.ToString("B");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the object type for this object.
|
|
||||||
/// </summary>
|
|
||||||
public ObjectType ObjectType
|
|
||||||
{
|
|
||||||
get { return (ObjectType)((_type >> 28) & 0xF); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the image type for this application.
|
|
||||||
/// </summary>
|
|
||||||
public ApplicationImageType ApplicationImageType
|
|
||||||
{
|
|
||||||
get { return IsApplication ? (ApplicationImageType)((_type & 0x00F00000) >> 20) : 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the application type for this application.
|
|
||||||
/// </summary>
|
|
||||||
public ApplicationType ApplicationType
|
|
||||||
{
|
|
||||||
get { return IsApplication ? (ApplicationType)(_type & 0xFFFFF) : 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the elements in this object.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<Element> Elements
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
foreach (var el in _storage.EnumerateElements(_id))
|
|
||||||
{
|
|
||||||
yield return new Element(_storage, _id, ApplicationType, el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsApplication
|
|
||||||
{
|
|
||||||
get { return ObjectType == ObjectType.Application; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if the settings in this object are inheritable by another object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type of the object to test for inheritability.</param>
|
|
||||||
/// <returns><c>true</c> if the settings can be inherited, else <c>false</c>.</returns>
|
|
||||||
public bool IsInheritableBy(ObjectType type)
|
|
||||||
{
|
|
||||||
if (type == ObjectType.Inherit)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Can not test inheritability by inherit objects", "type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ObjectType != ObjectType.Inherit)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
InheritType setting = (InheritType)((_type & 0x00F00000) >> 20);
|
|
||||||
|
|
||||||
return setting == InheritType.AnyObject
|
|
||||||
|| (setting == InheritType.ApplicationObjects && type == ObjectType.Application)
|
|
||||||
|| (setting == InheritType.DeviceObjects && type == ObjectType.Device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if this object has a specific element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to look for.</param>
|
|
||||||
/// <returns><c>true</c> if present, else <c>false</c>.</returns>
|
|
||||||
public bool HasElement(int id)
|
|
||||||
{
|
|
||||||
return _storage.HasValue(_id, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if this object has a specific element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to look for.</param>
|
|
||||||
/// <returns><c>true</c> if present, else <c>false</c>.</returns>
|
|
||||||
public bool HasElement(WellKnownElement id)
|
|
||||||
{
|
|
||||||
return HasElement((int)id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a specific element in this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to look for.</param>
|
|
||||||
/// <returns>The element object.</returns>
|
|
||||||
public Element GetElement(int id)
|
|
||||||
{
|
|
||||||
if (HasElement(id))
|
|
||||||
{
|
|
||||||
return new Element(_storage, _id, ApplicationType, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a specific element in this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to look for.</param>
|
|
||||||
/// <returns>The element object.</returns>
|
|
||||||
public Element GetElement(WellKnownElement id)
|
|
||||||
{
|
|
||||||
return GetElement((int)id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an element in this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to add.</param>
|
|
||||||
/// <param name="initialValue">The initial value of the element.</param>
|
|
||||||
/// <returns>The element object.</returns>
|
|
||||||
public Element AddElement(int id, ElementValue initialValue)
|
|
||||||
{
|
|
||||||
_storage.CreateElement(_id, id);
|
|
||||||
Element el = new Element(_storage, _id, ApplicationType, id);
|
|
||||||
el.Value = initialValue;
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an element in this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the element to add.</param>
|
|
||||||
/// <param name="initialValue">The initial value of the element.</param>
|
|
||||||
/// <returns>The element object.</returns>
|
|
||||||
public Element AddElement(WellKnownElement id, ElementValue initialValue)
|
|
||||||
{
|
|
||||||
return AddElement((int)id, initialValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a specific element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The element to remove.</param>
|
|
||||||
public void RemoveElement(int id)
|
|
||||||
{
|
|
||||||
_storage.DeleteElement(_id, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a specific element.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The element to remove.</param>
|
|
||||||
public void RemoveElement(WellKnownElement id)
|
|
||||||
{
|
|
||||||
RemoveElement((int)id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the object identity as a GUID string.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A string representation, with surrounding curly braces.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _id.ToString("B");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int MakeApplicationType(ApplicationImageType imageType, ApplicationType appType)
|
|
||||||
{
|
|
||||||
return 0x10000000 | (((int)imageType << 20) & 0x00F00000) | ((int)appType & 0x0000FFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int MakeInheritType(InheritType inheritType)
|
|
||||||
{
|
|
||||||
return 0x20000000 | (((int)inheritType << 20) & 0x00F00000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddMapping(string name, string id)
|
|
||||||
{
|
|
||||||
Guid guid = new Guid(id);
|
|
||||||
s_nameToGuid[name] = guid;
|
|
||||||
s_guidToName[guid] = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
internal class BooleanElementValue : ElementValue
|
|
||||||
{
|
|
||||||
private bool _value;
|
|
||||||
|
|
||||||
public BooleanElementValue(byte[] value)
|
|
||||||
{
|
|
||||||
_value = value[0] != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BooleanElementValue(bool value)
|
|
||||||
{
|
|
||||||
_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ElementFormat Format
|
|
||||||
{
|
|
||||||
get { return ElementFormat.Boolean; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _value ? "True" : "False";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte[] GetBytes()
|
|
||||||
{
|
|
||||||
return new byte[] { (_value ? (byte)1 : (byte)0) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
internal class DeviceAndPathRecord : DeviceRecord
|
|
||||||
{
|
|
||||||
private DeviceRecord _container;
|
|
||||||
private string _path;
|
|
||||||
|
|
||||||
public override int Size
|
|
||||||
{
|
|
||||||
get { throw new NotImplementedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void GetBytes(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _container.ToString() + ":" + _path;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoParse(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
base.DoParse(data, offset);
|
|
||||||
|
|
||||||
_container = DeviceRecord.Parse(data, offset + 0x34);
|
|
||||||
|
|
||||||
int pathStart = 0x34 + _container.Size;
|
|
||||||
_path = Encoding.Unicode.GetString(data, offset + pathStart, Length - pathStart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
internal class DeviceElementValue : ElementValue
|
|
||||||
{
|
|
||||||
private Guid _parentObject;
|
|
||||||
private DeviceRecord _record;
|
|
||||||
|
|
||||||
public DeviceElementValue()
|
|
||||||
{
|
|
||||||
_parentObject = Guid.Empty;
|
|
||||||
|
|
||||||
PartitionRecord record = new PartitionRecord();
|
|
||||||
record.Type = 5;
|
|
||||||
_record = record;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceElementValue(Guid parentObject, PhysicalVolumeInfo pvi)
|
|
||||||
{
|
|
||||||
_parentObject = parentObject;
|
|
||||||
|
|
||||||
PartitionRecord record = new PartitionRecord();
|
|
||||||
record.Type = 6;
|
|
||||||
if (pvi.VolumeType == PhysicalVolumeType.BiosPartition)
|
|
||||||
{
|
|
||||||
record.PartitionType = 1;
|
|
||||||
record.DiskIdentity = new byte[4];
|
|
||||||
Utilities.WriteBytesLittleEndian(pvi.DiskSignature, record.DiskIdentity, 0);
|
|
||||||
record.PartitionIdentity = new byte[8];
|
|
||||||
Utilities.WriteBytesLittleEndian(pvi.PhysicalStartSector * 512, record.PartitionIdentity, 0);
|
|
||||||
}
|
|
||||||
else if (pvi.VolumeType == PhysicalVolumeType.GptPartition)
|
|
||||||
{
|
|
||||||
record.PartitionType = 0;
|
|
||||||
record.DiskIdentity = new byte[16];
|
|
||||||
Utilities.WriteBytesLittleEndian(pvi.DiskIdentity, record.DiskIdentity, 0);
|
|
||||||
record.PartitionIdentity = new byte[16];
|
|
||||||
Utilities.WriteBytesLittleEndian(pvi.PartitionIdentity, record.PartitionIdentity, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Unknown how to convert volume type {0} to a Device element", pvi.VolumeType));
|
|
||||||
}
|
|
||||||
|
|
||||||
_record = record;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceElementValue(byte[] value)
|
|
||||||
{
|
|
||||||
_parentObject = Utilities.ToGuidLittleEndian(value, 0x00);
|
|
||||||
_record = DeviceRecord.Parse(value, 0x10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Guid ParentObject
|
|
||||||
{
|
|
||||||
get { return _parentObject; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ElementFormat Format
|
|
||||||
{
|
|
||||||
get { return ElementFormat.Device; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (_parentObject != Guid.Empty)
|
|
||||||
{
|
|
||||||
return _parentObject.ToString() + ":" + _record.ToString();
|
|
||||||
}
|
|
||||||
else if (_record != null)
|
|
||||||
{
|
|
||||||
return _record.ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "<unknown>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte[] GetBytes()
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[_record.Size + 0x10];
|
|
||||||
|
|
||||||
Utilities.WriteBytesLittleEndian(_parentObject, buffer, 0);
|
|
||||||
_record.GetBytes(buffer, 0x10);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal abstract class DeviceRecord
|
|
||||||
{
|
|
||||||
public int Type { get; set; }
|
|
||||||
|
|
||||||
public int Length { get; set; }
|
|
||||||
|
|
||||||
public abstract int Size { get; }
|
|
||||||
|
|
||||||
public static DeviceRecord Parse(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
int type = Utilities.ToInt32LittleEndian(data, offset);
|
|
||||||
int length = Utilities.ToInt32LittleEndian(data, offset + 0x8);
|
|
||||||
if (offset + length > data.Length)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Device record is truncated");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceRecord newRecord = null;
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
newRecord = new DeviceAndPathRecord();
|
|
||||||
break;
|
|
||||||
case 5: // Logical 'boot' device
|
|
||||||
case 6: // Disk partition
|
|
||||||
newRecord = new PartitionRecord();
|
|
||||||
break;
|
|
||||||
case 8: // custom:nnnnnn
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("Unknown device type: " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newRecord != null)
|
|
||||||
{
|
|
||||||
newRecord.DoParse(data, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void GetBytes(byte[] data, int offset);
|
|
||||||
|
|
||||||
protected virtual void DoParse(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
Type = Utilities.ToInt32LittleEndian(data, offset);
|
|
||||||
Length = Utilities.ToInt32LittleEndian(data, offset + 0x8);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteHeader(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
Length = Size;
|
|
||||||
Utilities.WriteBytesLittleEndian(Type, data, offset);
|
|
||||||
Utilities.WriteBytesLittleEndian(Size, data, offset + 0x8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using DiscUtils.Registry;
|
|
||||||
|
|
||||||
internal class DiscUtilsRegistryStorage : BaseStorage
|
|
||||||
{
|
|
||||||
private const string ElementsPathTemplate = @"Objects\{0}\Elements";
|
|
||||||
private const string ElementPathTemplate = @"Objects\{0}\Elements\{1:X8}";
|
|
||||||
private const string ObjectTypePathTemplate = @"Objects\{0}\Description";
|
|
||||||
private const string ObjectsPath = @"Objects";
|
|
||||||
|
|
||||||
private RegistryKey _rootKey;
|
|
||||||
|
|
||||||
public DiscUtilsRegistryStorage(RegistryKey key)
|
|
||||||
{
|
|
||||||
_rootKey = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetString(Guid obj, int element)
|
|
||||||
{
|
|
||||||
return GetValue(obj, element) as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetString(Guid obj, int element, string value)
|
|
||||||
{
|
|
||||||
SetValue(obj, element, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override byte[] GetBinary(Guid obj, int element)
|
|
||||||
{
|
|
||||||
return GetValue(obj, element) as byte[];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetBinary(Guid obj, int element, byte[] value)
|
|
||||||
{
|
|
||||||
SetValue(obj, element, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string[] GetMultiString(Guid obj, int element)
|
|
||||||
{
|
|
||||||
return GetValue(obj, element) as string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetMultiString(Guid obj, int element, string[] values)
|
|
||||||
{
|
|
||||||
SetValue(obj, element, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Guid> EnumerateObjects()
|
|
||||||
{
|
|
||||||
RegistryKey parentKey = _rootKey.OpenSubKey("Objects");
|
|
||||||
foreach (var key in parentKey.GetSubKeyNames())
|
|
||||||
{
|
|
||||||
yield return new Guid(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<int> EnumerateElements(Guid obj)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementsPathTemplate, obj.ToString("B"));
|
|
||||||
RegistryKey parentKey = _rootKey.OpenSubKey(path);
|
|
||||||
foreach (var key in parentKey.GetSubKeyNames())
|
|
||||||
{
|
|
||||||
yield return int.Parse(key, NumberStyles.HexNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetObjectType(Guid obj)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ObjectTypePathTemplate, obj.ToString("B"));
|
|
||||||
|
|
||||||
RegistryKey descKey = _rootKey.OpenSubKey(path);
|
|
||||||
|
|
||||||
object val = descKey.GetValue("Type");
|
|
||||||
return (int)val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool HasValue(Guid obj, int element)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementPathTemplate, obj.ToString("B"), element);
|
|
||||||
return _rootKey.OpenSubKey(path) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ObjectExists(Guid obj)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ObjectTypePathTemplate, obj.ToString("B"));
|
|
||||||
|
|
||||||
return _rootKey.OpenSubKey(path) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Guid CreateObject(Guid obj, int type)
|
|
||||||
{
|
|
||||||
Guid realObj = (obj == Guid.Empty) ? Guid.NewGuid() : obj;
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ObjectTypePathTemplate, realObj.ToString("B"));
|
|
||||||
|
|
||||||
RegistryKey key = _rootKey.CreateSubKey(path);
|
|
||||||
key.SetValue("Type", type, RegistryValueType.Dword);
|
|
||||||
|
|
||||||
return realObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CreateElement(Guid obj, int element)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementPathTemplate, obj.ToString("B"), element);
|
|
||||||
|
|
||||||
_rootKey.CreateSubKey(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DeleteObject(Guid obj)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ObjectTypePathTemplate, obj.ToString("B"));
|
|
||||||
|
|
||||||
_rootKey.DeleteSubKeyTree(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DeleteElement(Guid obj, int element)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementPathTemplate, obj.ToString("B"), element);
|
|
||||||
|
|
||||||
_rootKey.DeleteSubKeyTree(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetValue(Guid obj, int element)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementPathTemplate, obj.ToString("B"), element);
|
|
||||||
RegistryKey key = _rootKey.OpenSubKey(path);
|
|
||||||
return key.GetValue("Element");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetValue(Guid obj, int element, object value)
|
|
||||||
{
|
|
||||||
string path = string.Format(CultureInfo.InvariantCulture, ElementPathTemplate, obj.ToString("B"), element);
|
|
||||||
RegistryKey key = _rootKey.OpenSubKey(path);
|
|
||||||
key.SetValue("Element", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,390 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbolic names of BCD Elements taken from Geoff Chappell's website:
|
|
||||||
// http://www.geoffchappell.com/viewer.htm?doc=notes/windows/boot/bcd/elements.htm
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an element in a Boot Configuration Database object.
|
|
||||||
/// </summary>
|
|
||||||
public class Element
|
|
||||||
{
|
|
||||||
private BaseStorage _storage;
|
|
||||||
private Guid _obj;
|
|
||||||
private ApplicationType _appType;
|
|
||||||
private int _identifier;
|
|
||||||
private ElementValue _value;
|
|
||||||
|
|
||||||
internal Element(BaseStorage storage, Guid obj, ApplicationType appType, int identifier)
|
|
||||||
{
|
|
||||||
_storage = storage;
|
|
||||||
_obj = obj;
|
|
||||||
_appType = appType;
|
|
||||||
_identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the friendly name of the element, if any.
|
|
||||||
/// </summary>
|
|
||||||
public string FriendlyName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "{" + IdentifierToName(_appType, _identifier) + "}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the class of the element.
|
|
||||||
/// </summary>
|
|
||||||
public ElementClass Class
|
|
||||||
{
|
|
||||||
get { return (ElementClass)((_identifier >> 28) & 0xF); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the element's format.
|
|
||||||
/// </summary>
|
|
||||||
public ElementFormat Format
|
|
||||||
{
|
|
||||||
get { return (ElementFormat)((_identifier >> 24) & 0xF); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the element's value.
|
|
||||||
/// </summary>
|
|
||||||
public ElementValue Value
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_value == null)
|
|
||||||
{
|
|
||||||
_value = LoadValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (Format != value.Format)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Attempt to assign {1} value to {0} format element", Format, value.Format));
|
|
||||||
}
|
|
||||||
|
|
||||||
_value = value;
|
|
||||||
WriteValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the element's id as a hex string.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A hex string.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _identifier.ToString("X8", CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string IdentifierToName(ApplicationType appType, int identifier)
|
|
||||||
{
|
|
||||||
ElementClass idClass = GetClass(identifier);
|
|
||||||
if (idClass == ElementClass.Library)
|
|
||||||
{
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x11000001: return "device";
|
|
||||||
case 0x12000002: return "path";
|
|
||||||
case 0x12000004: return "description";
|
|
||||||
case 0x12000005: return "locale";
|
|
||||||
case 0x14000006: return "inherit";
|
|
||||||
case 0x15000007: return "truncatememory";
|
|
||||||
case 0x14000008: return "recoverysequence";
|
|
||||||
case 0x16000009: return "recoveryenabled";
|
|
||||||
case 0x1700000A: return "badmemorylist";
|
|
||||||
case 0x1600000B: return "badmemoryaccess";
|
|
||||||
case 0x1500000C: return "firstmegabytepolicy";
|
|
||||||
|
|
||||||
case 0x16000010: return "bootdebug";
|
|
||||||
case 0x15000011: return "debugtype";
|
|
||||||
case 0x15000012: return "debugaddress";
|
|
||||||
case 0x15000013: return "debugport";
|
|
||||||
case 0x15000014: return "baudrate";
|
|
||||||
case 0x15000015: return "channel";
|
|
||||||
case 0x12000016: return "targetname";
|
|
||||||
case 0x16000017: return "noumex";
|
|
||||||
case 0x15000018: return "debugstart";
|
|
||||||
|
|
||||||
case 0x16000020: return "bootems";
|
|
||||||
case 0x15000022: return "emsport";
|
|
||||||
case 0x15000023: return "emsbaudrate";
|
|
||||||
|
|
||||||
case 0x12000030: return "loadoptions";
|
|
||||||
|
|
||||||
case 0x16000040: return "advancedoptions";
|
|
||||||
case 0x16000041: return "optionsedit";
|
|
||||||
case 0x15000042: return "keyringaddress";
|
|
||||||
case 0x16000046: return "graphicsmodedisabled";
|
|
||||||
case 0x15000047: return "configaccesspolicy";
|
|
||||||
case 0x16000048: return "nointegritychecks";
|
|
||||||
case 0x16000049: return "testsigning";
|
|
||||||
case 0x16000050: return "extendedinput";
|
|
||||||
case 0x15000051: return "initialconsoleinput";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (idClass == ElementClass.Application)
|
|
||||||
{
|
|
||||||
switch (appType)
|
|
||||||
{
|
|
||||||
case ApplicationType.FirmwareBootManager:
|
|
||||||
case ApplicationType.BootManager:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x24000001: return "displayorder";
|
|
||||||
case 0x24000002: return "bootsequence";
|
|
||||||
case 0x23000003: return "default";
|
|
||||||
case 0x25000004: return "timeout";
|
|
||||||
case 0x26000005: return "resume";
|
|
||||||
case 0x23000006: return "resumeobject";
|
|
||||||
|
|
||||||
case 0x24000010: return "toolsdisplayorder";
|
|
||||||
|
|
||||||
case 0x26000020: return "displaybootmenu";
|
|
||||||
case 0x26000021: return "noerrordisplay";
|
|
||||||
case 0x21000022: return "bcddevice";
|
|
||||||
case 0x22000023: return "bcdfilepath";
|
|
||||||
|
|
||||||
case 0x27000030: return "customactions";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ApplicationType.OsLoader:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x21000001: return "osdevice";
|
|
||||||
case 0x22000002: return "systemroot";
|
|
||||||
case 0x23000003: return "resumeobject";
|
|
||||||
|
|
||||||
case 0x26000010: return "detecthal";
|
|
||||||
case 0x22000011: return "kernel";
|
|
||||||
case 0x22000012: return "hal";
|
|
||||||
case 0x22000013: return "dbgtransport";
|
|
||||||
|
|
||||||
case 0x25000020: return "nx";
|
|
||||||
case 0x25000021: return "pae";
|
|
||||||
case 0x26000022: return "winpe";
|
|
||||||
case 0x26000024: return "nocrashautoreboot";
|
|
||||||
case 0x26000025: return "lastknowngood";
|
|
||||||
case 0x26000026: return "oslnointegritychecks";
|
|
||||||
case 0x26000027: return "osltestsigning";
|
|
||||||
|
|
||||||
case 0x26000030: return "nolowmem";
|
|
||||||
case 0x25000031: return "removememory";
|
|
||||||
case 0x25000032: return "increaseuserva";
|
|
||||||
case 0x25000033: return "perfmem";
|
|
||||||
|
|
||||||
case 0x26000040: return "vga";
|
|
||||||
case 0x26000041: return "quietboot";
|
|
||||||
case 0x26000042: return "novesa";
|
|
||||||
|
|
||||||
case 0x25000050: return "clustermodeaddressing";
|
|
||||||
case 0x26000051: return "usephysicaldestination";
|
|
||||||
case 0x25000052: return "restrictapiccluster";
|
|
||||||
|
|
||||||
case 0x26000060: return "onecpu";
|
|
||||||
case 0x25000061: return "numproc";
|
|
||||||
case 0x26000062: return "maxproc";
|
|
||||||
case 0x25000063: return "configflags";
|
|
||||||
|
|
||||||
case 0x26000070: return "usefirmwarepcisettings";
|
|
||||||
case 0x25000071: return "msi";
|
|
||||||
case 0x25000072: return "pciexpress";
|
|
||||||
|
|
||||||
case 0x25000080: return "safeboot";
|
|
||||||
case 0x26000081: return "safebootalternateshell";
|
|
||||||
|
|
||||||
case 0x26000090: return "bootlog";
|
|
||||||
case 0x26000091: return "sos";
|
|
||||||
|
|
||||||
case 0x260000A0: return "debug";
|
|
||||||
case 0x260000A1: return "halbreakpoint";
|
|
||||||
|
|
||||||
case 0x260000B0: return "ems";
|
|
||||||
|
|
||||||
case 0x250000C0: return "forcefailure";
|
|
||||||
case 0x250000C1: return "driverloadfailurepolicy";
|
|
||||||
|
|
||||||
case 0x250000E0: return "bootstatuspolicy";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ApplicationType.Resume:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x21000001: return "filedevice";
|
|
||||||
case 0x22000002: return "filepath";
|
|
||||||
case 0x26000003: return "customsettings";
|
|
||||||
case 0x26000004: return "pae";
|
|
||||||
case 0x21000005: return "associatedosdevice";
|
|
||||||
case 0x26000006: return "debugoptionenabled";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ApplicationType.MemoryDiagnostics:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x25000001: return "passcount";
|
|
||||||
case 0x25000002: return "testmix";
|
|
||||||
case 0x25000003: return "failurecount";
|
|
||||||
case 0x25000004: return "testtofail";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ApplicationType.NtLoader:
|
|
||||||
case ApplicationType.SetupLoader:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x22000001: return "bpbstring";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ApplicationType.Startup:
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x26000001: return "pxesoftreboot";
|
|
||||||
case 0x22000002: return "applicationname";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (idClass == ElementClass.Device)
|
|
||||||
{
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x35000001: return "ramdiskimageoffset";
|
|
||||||
case 0x35000002: return "ramdisktftpclientport";
|
|
||||||
case 0x31000003: return "ramdisksdidevice";
|
|
||||||
case 0x32000004: return "ramdisksdipath";
|
|
||||||
case 0x35000005: return "ramdiskimagelength";
|
|
||||||
case 0x36000006: return "exportascd";
|
|
||||||
case 0x35000007: return "ramdisktftpblocksize";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (idClass == ElementClass.Hidden)
|
|
||||||
{
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case 0x45000001: return "devicetype";
|
|
||||||
case 0x42000002: return "apprelativepath";
|
|
||||||
case 0x42000003: return "ramdiskdevicerelativepath";
|
|
||||||
case 0x46000004: return "omitosloaderelements";
|
|
||||||
case 0x46000010: return "recoveryos";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return identifier.ToString("X8", CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ElementClass GetClass(int identifier)
|
|
||||||
{
|
|
||||||
return (ElementClass)((identifier >> 28) & 0xF);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ElementValue LoadValue()
|
|
||||||
{
|
|
||||||
switch (Format)
|
|
||||||
{
|
|
||||||
case ElementFormat.Boolean:
|
|
||||||
return new BooleanElementValue(_storage.GetBinary(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.Device:
|
|
||||||
return new DeviceElementValue(_storage.GetBinary(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.Guid:
|
|
||||||
return new GuidElementValue(_storage.GetString(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.GuidList:
|
|
||||||
return new GuidListElementValue(_storage.GetMultiString(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.Integer:
|
|
||||||
return new IntegerElementValue(_storage.GetBinary(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.IntegerList:
|
|
||||||
return new IntegerListElementValue(_storage.GetBinary(_obj, _identifier));
|
|
||||||
|
|
||||||
case ElementFormat.String:
|
|
||||||
return new StringElementValue(_storage.GetString(_obj, _identifier));
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("Unknown element format: " + Format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteValue()
|
|
||||||
{
|
|
||||||
switch (_value.Format)
|
|
||||||
{
|
|
||||||
case ElementFormat.Boolean:
|
|
||||||
_storage.SetBinary(_obj, _identifier, ((BooleanElementValue)_value).GetBytes());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ElementFormat.Device:
|
|
||||||
_storage.SetBinary(_obj, _identifier, ((DeviceElementValue)_value).GetBytes());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ElementFormat.GuidList:
|
|
||||||
_storage.SetMultiString(_obj, _identifier, ((GuidListElementValue)_value).GetGuidStrings());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ElementFormat.Integer:
|
|
||||||
_storage.SetBinary(_obj, _identifier, ((IntegerElementValue)_value).GetBytes());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ElementFormat.IntegerList:
|
|
||||||
_storage.SetBinary(_obj, _identifier, ((IntegerListElementValue)_value).GetBytes());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ElementFormat.Guid:
|
|
||||||
case ElementFormat.String:
|
|
||||||
_storage.SetString(_obj, _identifier, _value.ToString());
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("Unknown element format: " + Format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The known classes of element.
|
|
||||||
/// </summary>
|
|
||||||
public enum ElementClass
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown class.
|
|
||||||
/// </summary>
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Common setting.
|
|
||||||
/// </summary>
|
|
||||||
Library = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An application setting.
|
|
||||||
/// </summary>
|
|
||||||
Application = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A device (or partition) setting.
|
|
||||||
/// </summary>
|
|
||||||
Device = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A hidden setting.
|
|
||||||
/// </summary>
|
|
||||||
Hidden = 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The known formats used to store BCD values.
|
|
||||||
/// </summary>
|
|
||||||
public enum ElementFormat
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown format.
|
|
||||||
/// </summary>
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A block device, or partition.
|
|
||||||
/// </summary>
|
|
||||||
Device = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A unicode string.
|
|
||||||
/// </summary>
|
|
||||||
String = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A Globally Unique Identifier (GUID).
|
|
||||||
/// </summary>
|
|
||||||
Guid = 3,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A GUID list.
|
|
||||||
/// </summary>
|
|
||||||
GuidList = 4,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An integer.
|
|
||||||
/// </summary>
|
|
||||||
Integer = 5,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A boolean.
|
|
||||||
/// </summary>
|
|
||||||
Boolean = 6,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An integer list.
|
|
||||||
/// </summary>
|
|
||||||
IntegerList = 7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The value of an element.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class ElementValue
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the format of the value.
|
|
||||||
/// </summary>
|
|
||||||
public abstract ElementFormat Format { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parent object (only for Device values).
|
|
||||||
/// </summary>
|
|
||||||
public virtual Guid ParentObject
|
|
||||||
{
|
|
||||||
get { return Guid.Empty; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing a device (aka partition).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="parentObject">Object containing detailed information about the device.</param>
|
|
||||||
/// <param name="physicalVolume">The volume to represent.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForDevice(Guid parentObject, PhysicalVolumeInfo physicalVolume)
|
|
||||||
{
|
|
||||||
return new DeviceElementValue(parentObject, physicalVolume);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing the logical boot device.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The boot pseudo-device as an object.</returns>
|
|
||||||
public static ElementValue ForBootDevice()
|
|
||||||
{
|
|
||||||
return new DeviceElementValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing a string value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForString(string value)
|
|
||||||
{
|
|
||||||
return new StringElementValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing an integer value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForInteger(long value)
|
|
||||||
{
|
|
||||||
return new IntegerElementValue((ulong)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing an integer list value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForIntegerList(long[] values)
|
|
||||||
{
|
|
||||||
ulong[] ulValues = new ulong[values.Length];
|
|
||||||
for (int i = 0; i < values.Length; ++i)
|
|
||||||
{
|
|
||||||
ulValues[i] = (ulong)values[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IntegerListElementValue(ulValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing a boolean value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForBoolean(bool value)
|
|
||||||
{
|
|
||||||
return new BooleanElementValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing a GUID value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForGuid(Guid value)
|
|
||||||
{
|
|
||||||
return new GuidElementValue(value.ToString("B"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value representing a GUID list value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="values">The value to convert.</param>
|
|
||||||
/// <returns>The value as an object.</returns>
|
|
||||||
public static ElementValue ForGuidList(Guid[] values)
|
|
||||||
{
|
|
||||||
string[] strValues = new string[values.Length];
|
|
||||||
for (int i = 0; i < values.Length; ++i)
|
|
||||||
{
|
|
||||||
strValues[i] = values[i].ToString("B");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GuidListElementValue(strValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the type of objects that can inherit from an object.
|
|
||||||
/// </summary>
|
|
||||||
public enum InheritType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Undefined value.
|
|
||||||
/// </summary>
|
|
||||||
None = 0x0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Any type of object may inherit from this object.
|
|
||||||
/// </summary>
|
|
||||||
AnyObject = 0x1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only Application objects may inherit from this object.
|
|
||||||
/// </summary>
|
|
||||||
ApplicationObjects = 0x2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only Device objects may inherit from this object.
|
|
||||||
/// </summary>
|
|
||||||
DeviceObjects = 0x3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
internal class IntegerElementValue : ElementValue
|
|
||||||
{
|
|
||||||
private ulong _value;
|
|
||||||
|
|
||||||
public IntegerElementValue(byte[] value)
|
|
||||||
{
|
|
||||||
// Actual bytes stored may be less than 8
|
|
||||||
byte[] buffer = new byte[8];
|
|
||||||
Array.Copy(value, buffer, value.Length);
|
|
||||||
|
|
||||||
_value = Utilities.ToUInt64LittleEndian(buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntegerElementValue(ulong value)
|
|
||||||
{
|
|
||||||
_value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ElementFormat Format
|
|
||||||
{
|
|
||||||
get { return ElementFormat.Integer; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "{0}", _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte[] GetBytes()
|
|
||||||
{
|
|
||||||
byte[] bytes = new byte[8];
|
|
||||||
Utilities.WriteBytesLittleEndian(_value, bytes, 0);
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
internal class IntegerListElementValue : ElementValue
|
|
||||||
{
|
|
||||||
private ulong[] _values;
|
|
||||||
|
|
||||||
public IntegerListElementValue(byte[] value)
|
|
||||||
{
|
|
||||||
_values = new ulong[value.Length / 8];
|
|
||||||
for (int i = 0; i < _values.Length; ++i)
|
|
||||||
{
|
|
||||||
_values[i] = Utilities.ToUInt64LittleEndian(value, i * 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntegerListElementValue(ulong[] values)
|
|
||||||
{
|
|
||||||
_values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ElementFormat Format
|
|
||||||
{
|
|
||||||
get { return ElementFormat.IntegerList; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (_values == null || _values.Length == 0)
|
|
||||||
{
|
|
||||||
return "<none>";
|
|
||||||
}
|
|
||||||
|
|
||||||
string result = string.Empty;
|
|
||||||
for (int i = 0; i < _values.Length; ++i)
|
|
||||||
{
|
|
||||||
if (i != 0)
|
|
||||||
{
|
|
||||||
result += " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += _values[i].ToString("X16", CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte[] GetBytes()
|
|
||||||
{
|
|
||||||
byte[] bytes = new byte[_values.Length * 8];
|
|
||||||
for (int i = 0; i < _values.Length; ++i)
|
|
||||||
{
|
|
||||||
Utilities.WriteBytesLittleEndian(_values[i], bytes, i * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of known object types.
|
|
||||||
/// </summary>
|
|
||||||
public enum ObjectType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An unknown type.
|
|
||||||
/// </summary>
|
|
||||||
None = 0x0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An application object.
|
|
||||||
/// </summary>
|
|
||||||
Application = 0x1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Inheritable common settings.
|
|
||||||
/// </summary>
|
|
||||||
Inherit = 0x2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Device (or partition) object.
|
|
||||||
/// </summary>
|
|
||||||
Device = 0x3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
internal class PartitionRecord : DeviceRecord
|
|
||||||
{
|
|
||||||
public int PartitionType { get; set; }
|
|
||||||
|
|
||||||
public byte[] DiskIdentity { get; set; }
|
|
||||||
|
|
||||||
public byte[] PartitionIdentity { get; set; }
|
|
||||||
|
|
||||||
public override int Size
|
|
||||||
{
|
|
||||||
get { return 0x48; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void GetBytes(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
WriteHeader(data, offset);
|
|
||||||
|
|
||||||
if (Type == 5)
|
|
||||||
{
|
|
||||||
Array.Clear(data, offset + 0x10, 0x38);
|
|
||||||
}
|
|
||||||
else if (Type == 6)
|
|
||||||
{
|
|
||||||
Utilities.WriteBytesLittleEndian(PartitionType, data, offset + 0x24);
|
|
||||||
|
|
||||||
if (PartitionType == 1)
|
|
||||||
{
|
|
||||||
Array.Copy(DiskIdentity, 0, data, offset + 0x28, 4);
|
|
||||||
Array.Copy(PartitionIdentity, 0, data, offset + 0x10, 8);
|
|
||||||
}
|
|
||||||
else if (PartitionType == 0)
|
|
||||||
{
|
|
||||||
Array.Copy(DiskIdentity, 0, data, offset + 0x28, 16);
|
|
||||||
Array.Copy(PartitionIdentity, 0, data, offset + 0x10, 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Unknown partition type: " + PartitionType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Unknown device type: " + Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (Type == 5)
|
|
||||||
{
|
|
||||||
return "<boot device>";
|
|
||||||
}
|
|
||||||
else if (Type == 6)
|
|
||||||
{
|
|
||||||
if (PartitionType == 1)
|
|
||||||
{
|
|
||||||
return string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"(disk:{0:X2}{1:X2}{2:X2}{3:X2} part-offset:{4})",
|
|
||||||
DiskIdentity[0],
|
|
||||||
DiskIdentity[1],
|
|
||||||
DiskIdentity[2],
|
|
||||||
DiskIdentity[3],
|
|
||||||
Utilities.ToUInt64LittleEndian(PartitionIdentity, 0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Guid diskGuid = Utilities.ToGuidLittleEndian(DiskIdentity, 0);
|
|
||||||
Guid partitionGuid = Utilities.ToGuidLittleEndian(PartitionIdentity, 0);
|
|
||||||
return string.Format(CultureInfo.InvariantCulture, "(disk:{0} partition:{1})", diskGuid, partitionGuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Type == 8)
|
|
||||||
{
|
|
||||||
return "custom:<unknown>";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "<unknown>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DoParse(byte[] data, int offset)
|
|
||||||
{
|
|
||||||
base.DoParse(data, offset);
|
|
||||||
|
|
||||||
if (Type == 5)
|
|
||||||
{
|
|
||||||
// Nothing to do - just empty...
|
|
||||||
}
|
|
||||||
else if (Type == 6)
|
|
||||||
{
|
|
||||||
PartitionType = Utilities.ToInt32LittleEndian(data, offset + 0x24);
|
|
||||||
|
|
||||||
if (PartitionType == 1)
|
|
||||||
{
|
|
||||||
// BIOS disk
|
|
||||||
DiskIdentity = new byte[4];
|
|
||||||
Array.Copy(data, offset + 0x28, DiskIdentity, 0, 4);
|
|
||||||
PartitionIdentity = new byte[8];
|
|
||||||
Array.Copy(data, offset + 0x10, PartitionIdentity, 0, 8);
|
|
||||||
}
|
|
||||||
else if (PartitionType == 0)
|
|
||||||
{
|
|
||||||
// GPT disk
|
|
||||||
DiskIdentity = new byte[16];
|
|
||||||
Array.Copy(data, offset + 0x28, DiskIdentity, 0, 16);
|
|
||||||
PartitionIdentity = new byte[16];
|
|
||||||
Array.Copy(data, offset + 0x10, PartitionIdentity, 0, 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Unknown partition type: " + PartitionType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Unknown device type: " + Type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using DiscUtils.Registry;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a Boot Configuration Database store (i.e. a BCD file).
|
|
||||||
/// </summary>
|
|
||||||
public class Store
|
|
||||||
{
|
|
||||||
private BaseStorage _store;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the Store class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key">The registry key that is the root of the configuration database.</param>
|
|
||||||
public Store(RegistryKey key)
|
|
||||||
{
|
|
||||||
_store = new DiscUtilsRegistryStorage(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the objects within the store.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<BcdObject> Objects
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
foreach (var obj in _store.EnumerateObjects())
|
|
||||||
{
|
|
||||||
yield return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new Boot Configuration Database.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="root">The registry key at the root of the database.</param>
|
|
||||||
/// <returns>The BCD store.</returns>
|
|
||||||
public static Store Initialize(RegistryKey root)
|
|
||||||
{
|
|
||||||
RegistryKey descKey = root.CreateSubKey("Description");
|
|
||||||
descKey.SetValue("KeyName", "BCD00000001");
|
|
||||||
root.CreateSubKey("Objects");
|
|
||||||
return new Store(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object from the store.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the object.</param>
|
|
||||||
/// <returns>The requested object, or <c>null</c>.</returns>
|
|
||||||
public BcdObject GetObject(Guid id)
|
|
||||||
{
|
|
||||||
if (_store.ObjectExists(id))
|
|
||||||
{
|
|
||||||
return new BcdObject(_store, id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a specific object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the object to create.</param>
|
|
||||||
/// <param name="type">The object's type.</param>
|
|
||||||
/// <returns>The object representing the new application.</returns>
|
|
||||||
public BcdObject CreateObject(Guid id, int type)
|
|
||||||
{
|
|
||||||
_store.CreateObject(id, type);
|
|
||||||
return new BcdObject(_store, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an application object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="imageType">The image type of the application.</param>
|
|
||||||
/// <param name="appType">The application's type.</param>
|
|
||||||
/// <returns>The object representing the new application.</returns>
|
|
||||||
public BcdObject CreateApplication(ApplicationImageType imageType, ApplicationType appType)
|
|
||||||
{
|
|
||||||
Guid obj = _store.CreateObject(Guid.NewGuid(), BcdObject.MakeApplicationType(imageType, appType));
|
|
||||||
return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an application object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the object to create.</param>
|
|
||||||
/// <param name="imageType">The image type of the application.</param>
|
|
||||||
/// <param name="appType">The application's type.</param>
|
|
||||||
/// <returns>The object representing the new application.</returns>
|
|
||||||
public BcdObject CreateApplication(Guid id, ApplicationImageType imageType, ApplicationType appType)
|
|
||||||
{
|
|
||||||
Guid obj = _store.CreateObject(id, BcdObject.MakeApplicationType(imageType, appType));
|
|
||||||
return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an 'inherit' object that contains common settings.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="inheritType">The type of object the settings apply to.</param>
|
|
||||||
/// <returns>The object representing the new settings.</returns>
|
|
||||||
public BcdObject CreateInherit(InheritType inheritType)
|
|
||||||
{
|
|
||||||
Guid obj = _store.CreateObject(Guid.NewGuid(), BcdObject.MakeInheritType(inheritType));
|
|
||||||
return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an 'inherit' object that contains common settings.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the object to create.</param>
|
|
||||||
/// <param name="inheritType">The type of object the settings apply to.</param>
|
|
||||||
/// <returns>The object representing the new settings.</returns>
|
|
||||||
public BcdObject CreateInherit(Guid id, InheritType inheritType)
|
|
||||||
{
|
|
||||||
Guid obj = _store.CreateObject(id, BcdObject.MakeInheritType(inheritType));
|
|
||||||
return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new device object, representing a partition.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The object representing the new device.</returns>
|
|
||||||
public BcdObject CreateDevice()
|
|
||||||
{
|
|
||||||
Guid obj = _store.CreateObject(Guid.NewGuid(), 0x30000000);
|
|
||||||
return new BcdObject(_store, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes an object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identity of the object to remove.</param>
|
|
||||||
public void RemoveObject(Guid id)
|
|
||||||
{
|
|
||||||
_store.DeleteObject(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,618 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbolic names of BCD Elements taken from Geoff Chappell's website:
|
|
||||||
// http://www.geoffchappell.com/viewer.htm?doc=notes/windows/boot/bcd/elements.htm
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.BootConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of known BCD elements.
|
|
||||||
/// </summary>
|
|
||||||
public enum WellKnownElement : int
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Not specified.
|
|
||||||
/// </summary>
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Device containing the application.
|
|
||||||
/// </summary>
|
|
||||||
LibraryApplicationDevice = 0x11000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path to the application.
|
|
||||||
/// </summary>
|
|
||||||
LibraryApplicationPath = 0x12000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Description of the object.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDescription = 0x12000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preferred locale of the object.
|
|
||||||
/// </summary>
|
|
||||||
LibraryPreferredLocale = 0x12000005,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Objects containing elements inherited by the object.
|
|
||||||
/// </summary>
|
|
||||||
LibraryInheritedObjects = 0x14000006,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Upper bound on physical addresses used by Windows.
|
|
||||||
/// </summary>
|
|
||||||
LibraryTruncatePhysicalMemory = 0x15000007,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of objects, indicating recovery sequence.
|
|
||||||
/// </summary>
|
|
||||||
LibraryRecoverySequence = 0x14000008,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables auto recovery.
|
|
||||||
/// </summary>
|
|
||||||
LibraryAutoRecoveryEnabled = 0x16000009,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List of bad memory regions.
|
|
||||||
/// </summary>
|
|
||||||
LibraryBadMemoryList = 0x1700000A,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allow use of bad memory regions.
|
|
||||||
/// </summary>
|
|
||||||
LibraryAllowBadMemoryAccess = 0x1600000B,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Policy on use of first mega-byte of physical RAM.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = UseNone, 1 = UseAll, 2 = UsePrivate.</remarks>
|
|
||||||
LibraryFirstMegaBytePolicy = 0x1500000C,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger enabled.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerEnabled = 0x16000010,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger type.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = Serial, 1 = 1394, 2 = USB.</remarks>
|
|
||||||
LibraryDebuggerType = 0x15000011,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger serial port address.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerSerialAddress = 0x15000012,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger serial port.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerSerialPort = 0x15000013,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger serial port baud rate.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerSerialBaudRate = 0x15000014,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger 1394 channel.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebugger1394Channel = 0x15000015,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger USB target name.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerUsbTargetName = 0x12000016,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger ignores user mode exceptions.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDebuggerIgnoreUserModeExceptions = 0x16000017,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Debugger start policy.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = Active, 1 = AutoEnable, 2 = Disable.</remarks>
|
|
||||||
LibraryDebuggerStartPolicy = 0x15000018,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Emergency Management System enabled.
|
|
||||||
/// </summary>
|
|
||||||
LibraryEmergencyManagementSystemEnabled = 0x16000020,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Emergency Management System serial port.
|
|
||||||
/// </summary>
|
|
||||||
LibraryEmergencyManagementSystemPort = 0x15000022,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Emergency Management System baud rate.
|
|
||||||
/// </summary>
|
|
||||||
LibraryEmergencyManagementSystemBaudRate = 0x15000023,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load options.
|
|
||||||
/// </summary>
|
|
||||||
LibraryLoadOptions = 0x12000030,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Displays advanced options.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDisplayAdvancedOptions = 0x16000040,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Displays UI to edit advanced options.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDisplayOptionsEdit = 0x16000041,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// FVE (Full Volume Encryption - aka BitLocker?) KeyRing address.
|
|
||||||
/// </summary>
|
|
||||||
LibraryFveKeyRingAddress = 0x16000042,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Device to contain Boot Status Log.
|
|
||||||
/// </summary>
|
|
||||||
LibraryBootStatusLogDevice = 0x11000043,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path to Boot Status Log.
|
|
||||||
/// </summary>
|
|
||||||
LibraryBootStatusLogFile = 0x12000044,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether to append to the existing Boot Status Log.
|
|
||||||
/// </summary>
|
|
||||||
LibraryBootStatusLogAppend = 0x12000045,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disables graphics mode.
|
|
||||||
/// </summary>
|
|
||||||
LibraryGraphicsModeDisabled = 0x16000046,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configure access policy.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = default, 1 = DisallowMmConfig.</remarks>
|
|
||||||
LibraryConfigAccessPolicy = 0x15000047,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disables integrity checks.
|
|
||||||
/// </summary>
|
|
||||||
LibraryDisableIntegrityChecks = 0x16000048,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows pre-release signatures (test signing).
|
|
||||||
/// </summary>
|
|
||||||
LibraryAllowPrereleaseSignatures = 0x16000049,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Console extended input.
|
|
||||||
/// </summary>
|
|
||||||
LibraryConsoleExtendedInput = 0x16000050,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initial console input.
|
|
||||||
/// </summary>
|
|
||||||
LibraryInitialConsoleInput = 0x15000051,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Application display order.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrDisplayOrder = 0x24000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Application boot sequence.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrBootSequence = 0x24000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default application.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrDefaultObject = 0x23000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// User input timeout.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrTimeout = 0x25000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempt to resume from hibernated state.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrAttemptResume = 0x26000005,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The resume application.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrResumeObject = 0x23000006,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The tools display order.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrToolsDisplayOrder = 0x24000010,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Displays the boot menu.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrDisplayBootMenu = 0x26000020,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// No error display.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrNoErrorDisplay = 0x26000021,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The BCD device.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrBcdDevice = 0x21000022,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The BCD file path.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrBcdFilePath = 0x22000023,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The custom actions list.
|
|
||||||
/// </summary>
|
|
||||||
BootMgrCustomActionsList = 0x27000030,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Device containing the Operating System.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderOsDevice = 0x21000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System root on the OS device.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderSystemRoot = 0x22000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The resume application associated with this OS.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderAssociatedResumeObject = 0x23000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Auto-detect the correct kernel & HAL.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDetectKernelAndHal = 0x26000010,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The filename of the kernel.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderKernelPath = 0x22000011,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The filename of the HAL.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderHalPath = 0x22000012,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The debug transport path.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDebugTransportPath = 0x22000013,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// NX (No-Execute) policy.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = OptIn, 1 = OptOut, 2 = AlwaysOff, 3 = AlwaysOn.</remarks>
|
|
||||||
OsLoaderNxPolicy = 0x25000020,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PAE policy.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = default, 1 = ForceEnable, 2 = ForceDisable.</remarks>
|
|
||||||
OsLoaderPaePolicy = 0x25000021,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// WinPE mode.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderWinPeMode = 0x26000022,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disable automatic reboot on OS crash.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDisableCrashAutoReboot = 0x26000024,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use the last known good settings.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderUseLastGoodSettings = 0x26000025,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disable integrity checks.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDisableIntegrityChecks = 0x26000026,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows pre-release signatures (test signing).
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderAllowPrereleaseSignatures = 0x26000027,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads all executables above 4GB boundary.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderNoLowMemory = 0x26000030,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Excludes a given amount of memory from use by Windows.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderRemoveMemory = 0x25000031,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increases the User Mode virtual address space.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderIncreaseUserVa = 0x25000032,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Size of buffer (in MB) for perfomance data logging.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderPerformanceDataMemory = 0x25000033,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the VGA display driver.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderUseVgaDriver = 0x26000040,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Quiet boot.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDisableBootDisplay = 0x26000041,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disables use of the VESA BIOS.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDisableVesaBios = 0x26000042,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum processors in a single APIC cluster.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderClusterModeAddressing = 0x25000050,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Forces the physical APIC to be used.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderUsePhysicalDestination = 0x26000051,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The largest APIC cluster number the system can use.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderRestrictApicCluster = 0x25000052,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Forces only the boot processor to be used.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderUseBootProcessorOnly = 0x26000060,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The number of processors to be used.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderNumberOfProcessors = 0x25000061,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use maximum number of processors.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderForceMaxProcessors = 0x26000062,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processor specific configuration flags.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderProcessorConfigurationFlags = 0x25000063,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses BIOS-configured PCI resources.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderUseFirmwarePciSettings = 0x26000070,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Message Signalled Interrupt setting.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderMsiPolicy = 0x25000071,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PCE Express Policy.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderPciExpressPolicy = 0x25000072,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The safe boot option.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>0 = Minimal, 1 = Network, 2 = DsRepair.</remarks>
|
|
||||||
OsLoaderSafeBoot = 0x25000080,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the configured alternate shell during a safe boot.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderSafeBootAlternateShell = 0x26000081,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables boot log.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderBootLogInitialization = 0x26000090,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Displays diagnostic information during boot.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderVerboseObjectLoadMode = 0x26000091,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables the kernel debugger.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderKernelDebuggerEnabled = 0x260000A0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Causes the kernal to halt early during boot.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDebuggerHalBreakpoint = 0x260000A1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables Windows Emergency Management System.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderEmsEnabled = 0x260000B0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Forces a failure on boot.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderForceFailure = 0x250000C0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The OS failure policy.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderDriverLoadFailurePolicy = 0x250000C1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The OS boot status policy.
|
|
||||||
/// </summary>
|
|
||||||
OsLoaderBootStatusPolicy = 0x250000E0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The device containing the hibernation file.
|
|
||||||
/// </summary>
|
|
||||||
ResumeHiberFileDevice = 0x21000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The path to the hibernation file.
|
|
||||||
/// </summary>
|
|
||||||
ResumeHiberFilePath = 0x22000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows resume loader to use custom settings.
|
|
||||||
/// </summary>
|
|
||||||
ResumeUseCustomSettings = 0x26000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PAE settings for resume application.
|
|
||||||
/// </summary>
|
|
||||||
ResumePaeMode = 0x26000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An MS-DOS device with containing resume application.
|
|
||||||
/// </summary>
|
|
||||||
ResumeAssociatedDosDevice = 0x21000005,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables debug option.
|
|
||||||
/// </summary>
|
|
||||||
ResumeDebugOptionEnabled = 0x26000006,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The number of iterations to run.
|
|
||||||
/// </summary>
|
|
||||||
MemDiagPassCount = 0x25000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The test mix.
|
|
||||||
/// </summary>
|
|
||||||
MemDiagTestMix = 0x25000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The failure count.
|
|
||||||
/// </summary>
|
|
||||||
MemDiagFailureCount = 0x25000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The tests to fail.
|
|
||||||
/// </summary>
|
|
||||||
MemDiagTestToFail = 0x25000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// BPB string.
|
|
||||||
/// </summary>
|
|
||||||
LoaderBpbString = 0x22000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Causes a soft PXE reboot.
|
|
||||||
/// </summary>
|
|
||||||
StartupPxeSoftReboot = 0x26000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PXE application name.
|
|
||||||
/// </summary>
|
|
||||||
StartupPxeApplicationName = 0x22000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Offset of the RAM disk image.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskImageOffset = 0x35000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Client port for TFTP.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskTftpClientPort = 0x35000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Device containing the SDI file.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskSdiDevice = 0x31000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Path to the SDI file.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskSdiPath = 0x32000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Length of the RAM disk image.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskRamDiskImageLength = 0x35000005,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Exports the image as a CD.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskExportAsCd = 0x36000006,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The TFTP transfer block size.
|
|
||||||
/// </summary>
|
|
||||||
DeviceRamDiskTftpBlockSize = 0x35000007,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The device type.
|
|
||||||
/// </summary>
|
|
||||||
SetupDeviceType = 0x45000001,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The application relative path.
|
|
||||||
/// </summary>
|
|
||||||
SetupAppRelativePath = 0x42000002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The device relative path.
|
|
||||||
/// </summary>
|
|
||||||
SetupRamDiskDeviceRelativePath = 0x42000003,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Omit OS loader elements.
|
|
||||||
/// </summary>
|
|
||||||
SetupOmitOsLoaderElements = 0x46000004,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recovery OS flag.
|
|
||||||
/// </summary>
|
|
||||||
SetupRecoveryOs = 0x46000010,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Abstract base class for implementations of IBuffer.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class Buffer : MarshalByRefObject, IBuffer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this buffer can be read.
|
|
||||||
/// </summary>
|
|
||||||
public abstract bool CanRead { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this buffer can be modified.
|
|
||||||
/// </summary>
|
|
||||||
public abstract bool CanWrite { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current capacity of the buffer, in bytes.
|
|
||||||
/// </summary>
|
|
||||||
public abstract long Capacity { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of the stream that are stored.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This may be an empty enumeration if all bytes are zero.</remarks>
|
|
||||||
public virtual IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetExtentsInRange(0, Capacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads from the buffer into a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The offset within the buffer to start reading.</param>
|
|
||||||
/// <param name="buffer">The destination byte array.</param>
|
|
||||||
/// <param name="offset">The start offset within the destination buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to read.</param>
|
|
||||||
/// <returns>The actual number of bytes read.</returns>
|
|
||||||
public abstract int Read(long pos, byte[] buffer, int offset, int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a byte array into the buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The start offset within the buffer.</param>
|
|
||||||
/// <param name="buffer">The source byte array.</param>
|
|
||||||
/// <param name="offset">The start offset within the source byte array.</param>
|
|
||||||
/// <param name="count">The number of bytes to write.</param>
|
|
||||||
public abstract void Write(long pos, byte[] buffer, int offset, int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clears bytes from the buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The start offset within the buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to clear.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Logically equivalent to writing <c>count</c> null/zero bytes to the buffer, some
|
|
||||||
/// implementations determine that some (or all) of the range indicated is not actually
|
|
||||||
/// stored. There is no direct, automatic, correspondence to clearing bytes and them
|
|
||||||
/// not being represented as an 'extent' - for example, the implementation of the underlying
|
|
||||||
/// stream may not permit fine-grained extent storage.</para>
|
|
||||||
/// <para>It is always safe to call this method to 'zero-out' a section of a buffer, regardless of
|
|
||||||
/// the underlying buffer implementation.</para>
|
|
||||||
/// </remarks>
|
|
||||||
public virtual void Clear(long pos, int count)
|
|
||||||
{
|
|
||||||
Write(pos, new byte[count], 0, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes all data to the underlying storage.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>The default behaviour, implemented by this class, is to take no action.</remarks>
|
|
||||||
public virtual void Flush()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the capacity of the buffer, truncating if appropriate.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The desired capacity of the buffer.</param>
|
|
||||||
public abstract void SetCapacity(long value);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of a buffer that are stored, within a specified range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="start">The offset of the first byte of interest.</param>
|
|
||||||
/// <param name="count">The number of bytes of interest.</param>
|
|
||||||
/// <returns>An enumeration of stream extents, indicating stored bytes.</returns>
|
|
||||||
public abstract IEnumerable<StreamExtent> GetExtentsInRange(long start, long count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,218 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a Buffer into a Stream.
|
|
||||||
/// </summary>
|
|
||||||
public class BufferStream : SparseStream
|
|
||||||
{
|
|
||||||
private IBuffer _buffer;
|
|
||||||
private FileAccess _access;
|
|
||||||
|
|
||||||
private long _position;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BufferStream class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to use.</param>
|
|
||||||
/// <param name="access">The access permitted to clients.</param>
|
|
||||||
public BufferStream(IBuffer buffer, FileAccess access)
|
|
||||||
{
|
|
||||||
_buffer = buffer;
|
|
||||||
_access = access;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether read access is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return _access != FileAccess.Write; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether seeking is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether write access is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return _access != FileAccess.Read; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the stream (the capacity of the underlying buffer).
|
|
||||||
/// </summary>
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get { return _buffer.Capacity; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets and sets the current position within the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return _position; }
|
|
||||||
set { _position = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the stored extents within the sparse stream.
|
|
||||||
/// </summary>
|
|
||||||
public override IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get { return _buffer.Extents; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes all data to the underlying storage.
|
|
||||||
/// </summary>
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads a number of bytes from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The destination buffer.</param>
|
|
||||||
/// <param name="offset">The start offset within the destination buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to read.</param>
|
|
||||||
/// <returns>The number of bytes read.</returns>
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (!CanRead)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to read from write-only stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
Utilities.AssertBufferParameters(buffer, offset, count);
|
|
||||||
|
|
||||||
int numRead = _buffer.Read(_position, buffer, offset, count);
|
|
||||||
_position += numRead;
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes the current stream position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">The origin-relative stream position.</param>
|
|
||||||
/// <param name="origin">The origin for the stream position.</param>
|
|
||||||
/// <returns>The new stream position.</returns>
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
long effectiveOffset = offset;
|
|
||||||
if (origin == SeekOrigin.Current)
|
|
||||||
{
|
|
||||||
effectiveOffset += _position;
|
|
||||||
}
|
|
||||||
else if (origin == SeekOrigin.End)
|
|
||||||
{
|
|
||||||
effectiveOffset += _buffer.Capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effectiveOffset < 0)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to move before beginning of disk");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_position = effectiveOffset;
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the length of the stream (the underlying buffer's capacity).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The new length of the stream.</param>
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
_buffer.SetCapacity(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a buffer to the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to write.</param>
|
|
||||||
/// <param name="offset">The starting offset within buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to write.</param>
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (!CanWrite)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to write to read-only stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
Utilities.AssertBufferParameters(buffer, offset, count);
|
|
||||||
|
|
||||||
_buffer.Write(_position, buffer, offset, count);
|
|
||||||
_position += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clears bytes from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="count">The number of bytes (from the current position) to clear.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Logically equivalent to writing <c>count</c> null/zero bytes to the stream, some
|
|
||||||
/// implementations determine that some (or all) of the range indicated is not actually
|
|
||||||
/// stored. There is no direct, automatic, correspondence to clearing bytes and them
|
|
||||||
/// not being represented as an 'extent' - for example, the implementation of the underlying
|
|
||||||
/// stream may not permit fine-grained extent storage.</para>
|
|
||||||
/// <para>It is always safe to call this method to 'zero-out' a section of a stream, regardless of
|
|
||||||
/// the underlying stream implementation.</para>
|
|
||||||
/// </remarks>
|
|
||||||
public override void Clear(int count)
|
|
||||||
{
|
|
||||||
if (!CanWrite)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to erase bytes in a read-only stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer.Clear(_position, count);
|
|
||||||
_position += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of a stream that are stored, within a specified range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="start">The offset of the first byte of interest.</param>
|
|
||||||
/// <param name="count">The number of bytes of interest.</param>
|
|
||||||
/// <returns>An enumeration of stream extents, indicating stored bytes.</returns>
|
|
||||||
public override IEnumerable<StreamExtent> GetExtentsInRange(long start, long count)
|
|
||||||
{
|
|
||||||
return _buffer.GetExtentsInRange(start, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal class BuilderBufferExtent : BuilderExtent
|
|
||||||
{
|
|
||||||
private bool _fixedBuffer;
|
|
||||||
private byte[] _buffer;
|
|
||||||
|
|
||||||
public BuilderBufferExtent(long start, long length)
|
|
||||||
: base(start, length)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public BuilderBufferExtent(long start, byte[] buffer)
|
|
||||||
: base(start, buffer.Length)
|
|
||||||
{
|
|
||||||
_fixedBuffer = true;
|
|
||||||
_buffer = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void PrepareForRead()
|
|
||||||
{
|
|
||||||
if (!_fixedBuffer)
|
|
||||||
{
|
|
||||||
_buffer = GetBuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override int Read(long diskOffset, byte[] block, int offset, int count)
|
|
||||||
{
|
|
||||||
int startOffset = (int)(diskOffset - Start);
|
|
||||||
int numBytes = (int)Math.Min(Length - startOffset, count);
|
|
||||||
Array.Copy(_buffer, startOffset, block, offset, numBytes);
|
|
||||||
return numBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void DisposeReadState()
|
|
||||||
{
|
|
||||||
if (!_fixedBuffer)
|
|
||||||
{
|
|
||||||
_buffer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual byte[] GetBuffer()
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Derived class should implement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
internal abstract class BuilderExtent : IDisposable
|
|
||||||
{
|
|
||||||
private long _start;
|
|
||||||
private long _length;
|
|
||||||
|
|
||||||
public BuilderExtent(long start, long length)
|
|
||||||
{
|
|
||||||
_start = start;
|
|
||||||
_length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of the stream that are stored.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This may be an empty enumeration if all bytes are zero.</remarks>
|
|
||||||
public virtual IEnumerable<StreamExtent> StreamExtents
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new StreamExtent[] { new StreamExtent(Start, Length) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal long Start
|
|
||||||
{
|
|
||||||
get { return _start; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal long Length
|
|
||||||
{
|
|
||||||
get { return _length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Dispose();
|
|
||||||
|
|
||||||
internal abstract void PrepareForRead();
|
|
||||||
|
|
||||||
internal abstract int Read(long diskOffset, byte[] block, int offset, int count);
|
|
||||||
|
|
||||||
internal abstract void DisposeReadState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
internal class BuilderSparseStreamExtent : BuilderExtent
|
|
||||||
{
|
|
||||||
private SparseStream _stream;
|
|
||||||
private Ownership _ownership;
|
|
||||||
|
|
||||||
public BuilderSparseStreamExtent(long start, SparseStream stream)
|
|
||||||
: this(start, stream, Ownership.None)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public BuilderSparseStreamExtent(long start, SparseStream stream, Ownership ownership)
|
|
||||||
: base(start, stream.Length)
|
|
||||||
{
|
|
||||||
_stream = stream;
|
|
||||||
_ownership = ownership;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<StreamExtent> StreamExtents
|
|
||||||
{
|
|
||||||
get { return StreamExtent.Offset(_stream.Extents, Start); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
if (_stream != null && _ownership == Ownership.Dispose)
|
|
||||||
{
|
|
||||||
_stream.Dispose();
|
|
||||||
_stream = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void PrepareForRead()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override int Read(long diskOffset, byte[] block, int offset, int count)
|
|
||||||
{
|
|
||||||
_stream.Position = diskOffset - Start;
|
|
||||||
return _stream.Read(block, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void DisposeReadState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal class BuiltStream : SparseStream
|
|
||||||
{
|
|
||||||
private Stream _baseStream;
|
|
||||||
private long _length;
|
|
||||||
private List<BuilderExtent> _extents;
|
|
||||||
|
|
||||||
private BuilderExtent _currentExtent;
|
|
||||||
private long _position;
|
|
||||||
|
|
||||||
public BuiltStream(long length, List<BuilderExtent> extents)
|
|
||||||
{
|
|
||||||
_baseStream = new ZeroStream(length);
|
|
||||||
_length = length;
|
|
||||||
_extents = extents;
|
|
||||||
|
|
||||||
// Make sure the extents are sorted, so binary searches will work.
|
|
||||||
_extents.Sort(new ExtentStartComparer());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get { return _length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return _position; }
|
|
||||||
set { _position = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
foreach (var extent in _extents)
|
|
||||||
{
|
|
||||||
foreach (var streamExtent in extent.StreamExtents)
|
|
||||||
{
|
|
||||||
yield return streamExtent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (_position >= _length)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalRead = 0;
|
|
||||||
while (totalRead < count && _position < _length)
|
|
||||||
{
|
|
||||||
// If current region is outside the area of interest, clean it up
|
|
||||||
if (_currentExtent != null && (_position < _currentExtent.Start || _position >= _currentExtent.Start + _currentExtent.Length))
|
|
||||||
{
|
|
||||||
_currentExtent.DisposeReadState();
|
|
||||||
_currentExtent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we need to find a new region, look for it
|
|
||||||
if (_currentExtent == null)
|
|
||||||
{
|
|
||||||
using (SearchExtent searchExtent = new SearchExtent(_position))
|
|
||||||
{
|
|
||||||
int idx = _extents.BinarySearch(searchExtent, new ExtentRangeComparer());
|
|
||||||
if (idx >= 0)
|
|
||||||
{
|
|
||||||
BuilderExtent extent = _extents[idx];
|
|
||||||
extent.PrepareForRead();
|
|
||||||
_currentExtent = extent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int numRead = 0;
|
|
||||||
|
|
||||||
// If the block is outside any known extent, defer to base stream.
|
|
||||||
if (_currentExtent == null)
|
|
||||||
{
|
|
||||||
_baseStream.Position = _position;
|
|
||||||
BuilderExtent nextExtent = FindNext(_position);
|
|
||||||
if (nextExtent != null)
|
|
||||||
{
|
|
||||||
numRead = _baseStream.Read(buffer, offset + totalRead, (int)Math.Min(count - totalRead, nextExtent.Start - _position));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numRead = _baseStream.Read(buffer, offset + totalRead, count - totalRead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numRead = _currentExtent.Read(_position, buffer, offset + totalRead, count - totalRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
_position += numRead;
|
|
||||||
totalRead += numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
long newPos = offset;
|
|
||||||
if (origin == SeekOrigin.Current)
|
|
||||||
{
|
|
||||||
newPos += _position;
|
|
||||||
}
|
|
||||||
else if (origin == SeekOrigin.End)
|
|
||||||
{
|
|
||||||
newPos += _length;
|
|
||||||
}
|
|
||||||
|
|
||||||
_position = newPos;
|
|
||||||
return newPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
if (_currentExtent != null)
|
|
||||||
{
|
|
||||||
_currentExtent.DisposeReadState();
|
|
||||||
_currentExtent = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_baseStream != null)
|
|
||||||
{
|
|
||||||
_baseStream.Dispose();
|
|
||||||
_baseStream = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private BuilderExtent FindNext(long pos)
|
|
||||||
{
|
|
||||||
int min = 0;
|
|
||||||
int max = _extents.Count - 1;
|
|
||||||
|
|
||||||
if (_extents.Count == 0 || (_extents[_extents.Count - 1].Start + _extents[_extents.Count - 1].Length) <= pos)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (min >= max)
|
|
||||||
{
|
|
||||||
return _extents[min];
|
|
||||||
}
|
|
||||||
|
|
||||||
int mid = (max + min) / 2;
|
|
||||||
if (_extents[mid].Start < pos)
|
|
||||||
{
|
|
||||||
min = mid + 1;
|
|
||||||
}
|
|
||||||
else if (_extents[mid].Start > pos)
|
|
||||||
{
|
|
||||||
max = mid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _extents[mid];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SearchExtent : BuilderExtent
|
|
||||||
{
|
|
||||||
public SearchExtent(long pos)
|
|
||||||
: base(pos, 1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void PrepareForRead()
|
|
||||||
{
|
|
||||||
// Not valid to use this 'dummy' extent for actual construction
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override int Read(long diskOffset, byte[] block, int offset, int count)
|
|
||||||
{
|
|
||||||
// Not valid to use this 'dummy' extent for actual construction
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void DisposeReadState()
|
|
||||||
{
|
|
||||||
// Not valid to use this 'dummy' extent for actual construction
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExtentRangeComparer : IComparer<BuilderExtent>
|
|
||||||
{
|
|
||||||
public int Compare(BuilderExtent x, BuilderExtent y)
|
|
||||||
{
|
|
||||||
if (x == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("x");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("y");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x.Start + x.Length <= y.Start)
|
|
||||||
{
|
|
||||||
// x < y, with no intersection
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (x.Start >= y.Start + y.Length)
|
|
||||||
{
|
|
||||||
// x > y, with no intersection
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// x intersects y
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ExtentStartComparer : IComparer<BuilderExtent>
|
|
||||||
{
|
|
||||||
public int Compare(BuilderExtent x, BuilderExtent y)
|
|
||||||
{
|
|
||||||
if (x == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("x");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("y");
|
|
||||||
}
|
|
||||||
|
|
||||||
long val = x.Start - y.Start;
|
|
||||||
if (val < 0)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (val > 0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class whose instances represent a CHS (Cylinder, Head, Sector) address on a disk.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Instances of this class are immutable.</remarks>
|
|
||||||
public sealed class ChsAddress
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The address of the first sector on any disk.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly ChsAddress First = new ChsAddress(0, 0, 1);
|
|
||||||
|
|
||||||
private int _cylinder;
|
|
||||||
private int _head;
|
|
||||||
private int _sector;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the ChsAddress class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cylinder">The number of cylinders of the disk.</param>
|
|
||||||
/// <param name="head">The number of heads (aka platters) of the disk.</param>
|
|
||||||
/// <param name="sector">The number of sectors per track/cylinder of the disk.</param>
|
|
||||||
public ChsAddress(int cylinder, int head, int sector)
|
|
||||||
{
|
|
||||||
_cylinder = cylinder;
|
|
||||||
_head = head;
|
|
||||||
_sector = sector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the cylinder number (zero-based).
|
|
||||||
/// </summary>
|
|
||||||
public int Cylinder
|
|
||||||
{
|
|
||||||
get { return _cylinder; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the head (zero-based).
|
|
||||||
/// </summary>
|
|
||||||
public int Head
|
|
||||||
{
|
|
||||||
get { return _head; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the sector number (one-based).
|
|
||||||
/// </summary>
|
|
||||||
public int Sector
|
|
||||||
{
|
|
||||||
get { return _sector; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if this object is equivalent to another.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to test against.</param>
|
|
||||||
/// <returns><c>true</c> if the <paramref name="obj"/> is equivalent, else <c>false</c>.</returns>
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj == null || obj.GetType() != GetType())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChsAddress other = (ChsAddress)obj;
|
|
||||||
|
|
||||||
return _cylinder == other._cylinder && _head == other._head && _sector == other._sector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the hash code for this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The hash code.</returns>
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _cylinder.GetHashCode() ^ _head.GetHashCode() ^ _sector.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a string representation of this object, in the form (C/H/S).
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The string representation.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "(" + _cylinder + "/" + _head + "/" + _sector + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of possible cluster roles.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>A cluster may be in more than one role.</remarks>
|
|
||||||
[Flags]
|
|
||||||
public enum ClusterRoles
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown, or unspecified role.
|
|
||||||
/// </summary>
|
|
||||||
None = 0x00,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster is free.
|
|
||||||
/// </summary>
|
|
||||||
Free = 0x01,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster is in use by a normal file.
|
|
||||||
/// </summary>
|
|
||||||
DataFile = 0x02,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster is in use by a system file.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This isn't a file marked with the 'system' attribute,
|
|
||||||
/// rather files that form part of the file system namespace but also
|
|
||||||
/// form part of the file system meta-data.</remarks>
|
|
||||||
SystemFile = 0x04,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster is in use for meta-data.
|
|
||||||
/// </summary>
|
|
||||||
Metadata = 0x08,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster contains the boot region.
|
|
||||||
/// </summary>
|
|
||||||
BootArea = 0x10,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cluster is marked bad.
|
|
||||||
/// </summary>
|
|
||||||
Bad = 0x20,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Class that identifies the role of each cluster in a file system.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class ClusterMap
|
|
||||||
{
|
|
||||||
private ClusterRoles[] _clusterToRole;
|
|
||||||
private object[] _clusterToFileId;
|
|
||||||
private Dictionary<object, string[]> _fileIdToPaths;
|
|
||||||
|
|
||||||
internal ClusterMap(ClusterRoles[] clusterToRole, object[] clusterToFileId, Dictionary<object, string[]> fileIdToPaths)
|
|
||||||
{
|
|
||||||
_clusterToRole = clusterToRole;
|
|
||||||
_clusterToFileId = clusterToFileId;
|
|
||||||
_fileIdToPaths = fileIdToPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the role of a cluster within the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cluster">The cluster to inspect.</param>
|
|
||||||
/// <returns>The clusters role (or roles).</returns>
|
|
||||||
public ClusterRoles GetRole(long cluster)
|
|
||||||
{
|
|
||||||
if (_clusterToRole == null || _clusterToRole.Length < cluster)
|
|
||||||
{
|
|
||||||
return ClusterRoles.None;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _clusterToRole[cluster];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a cluster to a list of file names.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cluster">The cluster to inspect.</param>
|
|
||||||
/// <returns>A list of paths that map to the cluster.</returns>
|
|
||||||
/// <remarks>A list is returned because on file systems with the notion of
|
|
||||||
/// hard links, a cluster may correspond to multiple directory entries.</remarks>
|
|
||||||
public string[] ClusterToPaths(long cluster)
|
|
||||||
{
|
|
||||||
if ((GetRole(cluster) & (ClusterRoles.DataFile | ClusterRoles.SystemFile)) != 0)
|
|
||||||
{
|
|
||||||
object fileId = _clusterToFileId[cluster];
|
|
||||||
return _fileIdToPaths[fileId];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new string[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of the Adler-32 checksum algorithm.
|
|
||||||
/// </summary>
|
|
||||||
public class Adler32
|
|
||||||
{
|
|
||||||
private uint _a;
|
|
||||||
private uint _b;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the Adler32 class.
|
|
||||||
/// </summary>
|
|
||||||
public Adler32()
|
|
||||||
{
|
|
||||||
_a = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the checksum of all data processed so far.
|
|
||||||
/// </summary>
|
|
||||||
public int Value
|
|
||||||
{
|
|
||||||
get { return (int)(_b << 16 | _a); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides data that should be checksummed.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">Buffer containing the data to checksum.</param>
|
|
||||||
/// <param name="offset">Offset of the first byte to checksum.</param>
|
|
||||||
/// <param name="count">The number of bytes to checksum.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// Call this method repeatedly until all checksummed
|
|
||||||
/// data has been processed.
|
|
||||||
/// </remarks>
|
|
||||||
public void Process(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (buffer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 0 || offset > buffer.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Offset outside of array bounds", "offset");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0 || offset + count > buffer.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Array index out of bounds", "count");
|
|
||||||
}
|
|
||||||
|
|
||||||
int processed = 0;
|
|
||||||
while (processed < count)
|
|
||||||
{
|
|
||||||
int innerEnd = Math.Min(count, processed + 2000);
|
|
||||||
while (processed < innerEnd)
|
|
||||||
{
|
|
||||||
_a += buffer[processed++];
|
|
||||||
_b += _a;
|
|
||||||
}
|
|
||||||
|
|
||||||
_a %= 65521;
|
|
||||||
_b %= 65521;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Based on "libbzip2", Copyright (C) 1996-2007 Julian R Seward.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal class BZip2BlockDecoder
|
|
||||||
{
|
|
||||||
private InverseBurrowsWheeler _inverseBurrowsWheeler;
|
|
||||||
private uint _crc;
|
|
||||||
|
|
||||||
public BZip2BlockDecoder(int blockSize)
|
|
||||||
{
|
|
||||||
_inverseBurrowsWheeler = new InverseBurrowsWheeler(blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Crc
|
|
||||||
{
|
|
||||||
get { return _crc; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Process(BitStream bitstream, byte[] outputBuffer, int outputBufferOffset)
|
|
||||||
{
|
|
||||||
_crc = 0;
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
_crc = (_crc << 8) | bitstream.Read(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool rand = bitstream.Read(1) != 0;
|
|
||||||
int origPtr = (int)bitstream.Read(24);
|
|
||||||
|
|
||||||
int thisBlockSize = ReadBuffer(bitstream, outputBuffer, outputBufferOffset);
|
|
||||||
|
|
||||||
_inverseBurrowsWheeler.OriginalIndex = origPtr;
|
|
||||||
_inverseBurrowsWheeler.Process(outputBuffer, outputBufferOffset, thisBlockSize, outputBuffer, outputBufferOffset);
|
|
||||||
|
|
||||||
if (rand)
|
|
||||||
{
|
|
||||||
BZip2Randomizer randomizer = new BZip2Randomizer();
|
|
||||||
randomizer.Process(outputBuffer, outputBufferOffset, thisBlockSize, outputBuffer, outputBufferOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return thisBlockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int ReadBuffer(BitStream bitstream, byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
// The MTF state
|
|
||||||
int numInUse = 0;
|
|
||||||
MoveToFront moveFrontTransform = new MoveToFront();
|
|
||||||
bool[] inUseGroups = new bool[16];
|
|
||||||
for (int i = 0; i < 16; ++i)
|
|
||||||
{
|
|
||||||
inUseGroups[i] = bitstream.Read(1) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
if (inUseGroups[i / 16])
|
|
||||||
{
|
|
||||||
if (bitstream.Read(1) != 0)
|
|
||||||
{
|
|
||||||
moveFrontTransform.Set(numInUse, (byte)i);
|
|
||||||
numInUse++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize 'virtual' Huffman tree from bitstream
|
|
||||||
BZip2CombinedHuffmanTrees huffmanTree = new BZip2CombinedHuffmanTrees(bitstream, numInUse + 2);
|
|
||||||
|
|
||||||
// Main loop reading data
|
|
||||||
int readBytes = 0;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
uint symbol = huffmanTree.NextSymbol();
|
|
||||||
|
|
||||||
if (symbol < 2)
|
|
||||||
{
|
|
||||||
// RLE, with length stored in a binary-style format
|
|
||||||
uint runLength = 0;
|
|
||||||
int bitShift = 0;
|
|
||||||
while (symbol < 2)
|
|
||||||
{
|
|
||||||
runLength += (symbol + 1) << bitShift;
|
|
||||||
bitShift++;
|
|
||||||
|
|
||||||
symbol = huffmanTree.NextSymbol();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte b = moveFrontTransform.Head;
|
|
||||||
while (runLength > 0)
|
|
||||||
{
|
|
||||||
buffer[offset + readBytes] = b;
|
|
||||||
++readBytes;
|
|
||||||
--runLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symbol <= numInUse)
|
|
||||||
{
|
|
||||||
// Single byte
|
|
||||||
byte b = moveFrontTransform.GetAndMove((int)symbol - 1);
|
|
||||||
buffer[offset + readBytes] = b;
|
|
||||||
++readBytes;
|
|
||||||
}
|
|
||||||
else if (symbol == numInUse + 1)
|
|
||||||
{
|
|
||||||
// End of block marker
|
|
||||||
return readBytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid symbol from Huffman table");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Based on "libbzip2", Copyright (C) 1996-2007 Julian R Seward.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents scheme used by BZip2 where multiple Huffman trees are used as a
|
|
||||||
/// virtual Huffman tree, with a logical selector every 50 bits in the bit stream.
|
|
||||||
/// </summary>
|
|
||||||
internal class BZip2CombinedHuffmanTrees
|
|
||||||
{
|
|
||||||
private BitStream _bitstream;
|
|
||||||
private byte[] _selectors;
|
|
||||||
private HuffmanTree[] _trees;
|
|
||||||
|
|
||||||
private HuffmanTree _activeTree;
|
|
||||||
private int _symbolsToNextSelector;
|
|
||||||
private int _nextSelector;
|
|
||||||
|
|
||||||
public BZip2CombinedHuffmanTrees(BitStream bitstream, int maxSymbols)
|
|
||||||
{
|
|
||||||
_bitstream = bitstream;
|
|
||||||
|
|
||||||
Initialize(maxSymbols);
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint NextSymbol()
|
|
||||||
{
|
|
||||||
if (_symbolsToNextSelector == 0)
|
|
||||||
{
|
|
||||||
_symbolsToNextSelector = 50;
|
|
||||||
_activeTree = _trees[_selectors[_nextSelector]];
|
|
||||||
_nextSelector++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_symbolsToNextSelector--;
|
|
||||||
|
|
||||||
return _activeTree.NextSymbol(_bitstream);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Initialize(int maxSymbols)
|
|
||||||
{
|
|
||||||
int numTrees = (int)_bitstream.Read(3);
|
|
||||||
if (numTrees < 2 || numTrees > 6)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid number of tables");
|
|
||||||
}
|
|
||||||
|
|
||||||
int numSelectors = (int)_bitstream.Read(15);
|
|
||||||
if (numSelectors < 1)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid number of selectors");
|
|
||||||
}
|
|
||||||
|
|
||||||
_selectors = new byte[numSelectors];
|
|
||||||
MoveToFront mtf = new MoveToFront(numTrees, true);
|
|
||||||
for (int i = 0; i < numSelectors; ++i)
|
|
||||||
{
|
|
||||||
_selectors[i] = mtf.GetAndMove(CountSetBits(numTrees));
|
|
||||||
}
|
|
||||||
|
|
||||||
_trees = new HuffmanTree[numTrees];
|
|
||||||
for (int t = 0; t < numTrees; ++t)
|
|
||||||
{
|
|
||||||
uint[] lengths = new uint[maxSymbols];
|
|
||||||
|
|
||||||
uint len = _bitstream.Read(5);
|
|
||||||
for (int i = 0; i < maxSymbols; ++i)
|
|
||||||
{
|
|
||||||
if (len < 1 || len > 20)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid length constructing Huffman tree");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (_bitstream.Read(1) != 0)
|
|
||||||
{
|
|
||||||
len = (_bitstream.Read(1) == 0) ? len + 1 : len - 1;
|
|
||||||
|
|
||||||
if (len < 1 || len > 20)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Invalid length constructing Huffman tree");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lengths[i] = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
_trees[t] = new HuffmanTree(lengths);
|
|
||||||
}
|
|
||||||
|
|
||||||
_symbolsToNextSelector = 0;
|
|
||||||
_nextSelector = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte CountSetBits(int max)
|
|
||||||
{
|
|
||||||
byte val = 0;
|
|
||||||
while (_bitstream.Read(1) != 0)
|
|
||||||
{
|
|
||||||
val++;
|
|
||||||
if (val >= max)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Exceeded max number of consecutive bits");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,349 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Based on "libbzip2", Copyright (C) 1996-2007 Julian R Seward.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of a BZip2 decoder.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class BZip2DecoderStream : Stream
|
|
||||||
{
|
|
||||||
private long _position;
|
|
||||||
private Stream _compressedStream;
|
|
||||||
private Ownership _ownsCompressed;
|
|
||||||
private BitStream _bitstream;
|
|
||||||
private BZip2RleStream _rleStream;
|
|
||||||
private BZip2BlockDecoder _blockDecoder;
|
|
||||||
private Crc32 _calcBlockCrc;
|
|
||||||
|
|
||||||
private byte[] _blockBuffer;
|
|
||||||
private uint _blockCrc;
|
|
||||||
private uint _compoundCrc;
|
|
||||||
private uint _calcCompoundCrc;
|
|
||||||
|
|
||||||
private bool _eof;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the BZip2DecoderStream class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The compressed input stream.</param>
|
|
||||||
/// <param name="ownsStream">Whether ownership of stream passes to the new instance.</param>
|
|
||||||
public BZip2DecoderStream(Stream stream, Ownership ownsStream)
|
|
||||||
{
|
|
||||||
_compressedStream = stream;
|
|
||||||
_ownsCompressed = ownsStream;
|
|
||||||
|
|
||||||
_bitstream = new BigEndianBitStream(new BufferedStream(stream));
|
|
||||||
|
|
||||||
// The Magic BZh
|
|
||||||
byte[] magic = new byte[3];
|
|
||||||
magic[0] = (byte)_bitstream.Read(8);
|
|
||||||
magic[1] = (byte)_bitstream.Read(8);
|
|
||||||
magic[2] = (byte)_bitstream.Read(8);
|
|
||||||
if (magic[0] != 0x42 || magic[1] != 0x5A || magic[2] != 0x68)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Bad magic at start of stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
// The size of the decompression blocks in multiples of 100,000
|
|
||||||
int blockSize = (int)_bitstream.Read(8) - 0x30;
|
|
||||||
if (blockSize < 1 || blockSize > 9)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Unexpected block size in header: " + blockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
blockSize *= 100000;
|
|
||||||
|
|
||||||
_rleStream = new BZip2RleStream();
|
|
||||||
_blockDecoder = new BZip2BlockDecoder(blockSize);
|
|
||||||
_blockBuffer = new byte[blockSize];
|
|
||||||
|
|
||||||
if (ReadBlock() == 0)
|
|
||||||
{
|
|
||||||
_eof = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether read access is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether seeking is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an indication of whether write access is permitted.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the stream (the capacity of the underlying buffer).
|
|
||||||
/// </summary>
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets and sets the current position within the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return _position; }
|
|
||||||
set { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes all data to the underlying storage.
|
|
||||||
/// </summary>
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads a number of bytes from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The destination buffer.</param>
|
|
||||||
/// <param name="offset">The start offset within the destination buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to read.</param>
|
|
||||||
/// <returns>The number of bytes read.</returns>
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (buffer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer.Length < offset + count)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Buffer smaller than declared");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Offset less than zero", "offset");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Count less than zero", "count");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_eof)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to read beyond end of stream");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numRead = _rleStream.Read(buffer, offset, count);
|
|
||||||
if (numRead == 0)
|
|
||||||
{
|
|
||||||
// If there was an existing block, check it's crc.
|
|
||||||
if (_calcBlockCrc != null)
|
|
||||||
{
|
|
||||||
if (_blockCrc != _calcBlockCrc.Value)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Decompression failed - block CRC mismatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
_calcCompoundCrc = ((_calcCompoundCrc << 1) | (_calcCompoundCrc >> 31)) ^ _blockCrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read a new block (if any), if none - check the overall CRC before returning
|
|
||||||
if (ReadBlock() == 0)
|
|
||||||
{
|
|
||||||
_eof = true;
|
|
||||||
if (_calcCompoundCrc != _compoundCrc)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Decompression failed - compound CRC");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
numRead = _rleStream.Read(buffer, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
_calcBlockCrc.Process(buffer, offset, numRead);
|
|
||||||
|
|
||||||
// Pre-read next block, so a client that knows the decompressed length will still
|
|
||||||
// have the overall CRC calculated.
|
|
||||||
if (_rleStream.AtEof)
|
|
||||||
{
|
|
||||||
// If there was an existing block, check it's crc.
|
|
||||||
if (_calcBlockCrc != null)
|
|
||||||
{
|
|
||||||
if (_blockCrc != _calcBlockCrc.Value)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Decompression failed - block CRC mismatch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_calcCompoundCrc = ((_calcCompoundCrc << 1) | (_calcCompoundCrc >> 31)) ^ _blockCrc;
|
|
||||||
if (ReadBlock() == 0)
|
|
||||||
{
|
|
||||||
_eof = true;
|
|
||||||
if (_calcCompoundCrc != _compoundCrc)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Decompression failed - compound CRC mismatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_position += numRead;
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes the current stream position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">The origin-relative stream position.</param>
|
|
||||||
/// <param name="origin">The origin for the stream position.</param>
|
|
||||||
/// <returns>The new stream position.</returns>
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the length of the stream (the underlying buffer's capacity).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The new length of the stream.</param>
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a buffer to the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to write.</param>
|
|
||||||
/// <param name="offset">The starting offset within buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to write.</param>
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases underlying resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">Whether this method is called from Dispose.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
if (_compressedStream != null && _ownsCompressed == Ownership.Dispose)
|
|
||||||
{
|
|
||||||
_compressedStream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_compressedStream = null;
|
|
||||||
|
|
||||||
if (_rleStream != null)
|
|
||||||
{
|
|
||||||
_rleStream.Dispose();
|
|
||||||
_rleStream = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int ReadBlock()
|
|
||||||
{
|
|
||||||
ulong marker = ReadMarker();
|
|
||||||
if (marker == 0x314159265359)
|
|
||||||
{
|
|
||||||
int blockSize = _blockDecoder.Process(_bitstream, _blockBuffer, 0);
|
|
||||||
_rleStream.Reset(_blockBuffer, 0, blockSize);
|
|
||||||
_blockCrc = _blockDecoder.Crc;
|
|
||||||
_calcBlockCrc = new Crc32BigEndian(Crc32Algorithm.Common);
|
|
||||||
return blockSize;
|
|
||||||
}
|
|
||||||
else if (marker == 0x177245385090)
|
|
||||||
{
|
|
||||||
_compoundCrc = ReadUint();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Found invalid marker in stream");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint ReadUint()
|
|
||||||
{
|
|
||||||
uint val = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
val = (val << 8) | _bitstream.Read(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong ReadMarker()
|
|
||||||
{
|
|
||||||
ulong marker = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
|
||||||
{
|
|
||||||
marker = (marker << 8) | _bitstream.Read(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return marker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Based on "libbzip2", Copyright (C) 1996-2007 Julian R Seward.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal class BZip2Randomizer : DataBlockTransform
|
|
||||||
{
|
|
||||||
private static readonly int[] RandomVals =
|
|
||||||
{
|
|
||||||
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
|
||||||
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
|
||||||
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
|
||||||
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
|
||||||
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
|
||||||
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
|
||||||
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
|
||||||
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
|
||||||
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
|
||||||
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
|
||||||
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
|
||||||
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
|
||||||
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
|
||||||
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
|
||||||
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
|
||||||
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
|
||||||
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
|
||||||
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
|
||||||
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
|
||||||
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
|
||||||
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
|
||||||
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
|
||||||
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
|
||||||
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
|
||||||
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
|
||||||
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
|
||||||
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
|
||||||
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
|
||||||
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
|
||||||
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
|
||||||
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
|
||||||
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
|
||||||
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
|
||||||
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
|
||||||
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
|
||||||
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
|
||||||
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
|
||||||
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
|
||||||
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
|
||||||
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
|
||||||
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
|
||||||
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
|
||||||
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
|
||||||
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
|
||||||
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
|
||||||
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
|
||||||
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
|
||||||
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
|
||||||
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
|
||||||
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
|
||||||
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
|
||||||
936, 638
|
|
||||||
};
|
|
||||||
|
|
||||||
protected override bool BuffersMustNotOverlap
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int DoProcess(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
if (input != output || inputOffset != outputOffset)
|
|
||||||
{
|
|
||||||
Array.Copy(input, inputOffset, output, outputOffset, inputCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
int randIndex = 1;
|
|
||||||
int nextByte = RandomVals[0] - 2;
|
|
||||||
|
|
||||||
while (nextByte < inputCount)
|
|
||||||
{
|
|
||||||
output[nextByte] ^= 1;
|
|
||||||
nextByte += RandomVals[randIndex++];
|
|
||||||
randIndex &= 0x1FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
return inputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int MaxOutputCount(int inputCount)
|
|
||||||
{
|
|
||||||
return inputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int MinOutputCount(int inputCount)
|
|
||||||
{
|
|
||||||
return inputCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Based on "libbzip2", Copyright (C) 1996-2007 Julian R Seward.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal class BZip2RleStream : Stream
|
|
||||||
{
|
|
||||||
private long _position;
|
|
||||||
private byte[] _blockBuffer;
|
|
||||||
private int _blockOffset;
|
|
||||||
private int _blockRemaining;
|
|
||||||
|
|
||||||
private int _numSame;
|
|
||||||
private byte _lastByte;
|
|
||||||
private int _runBytesOutstanding;
|
|
||||||
|
|
||||||
public BZip2RleStream()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AtEof
|
|
||||||
{
|
|
||||||
get { return _runBytesOutstanding == 0 && _blockRemaining == 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { return _position; }
|
|
||||||
set { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
_position = 0;
|
|
||||||
_blockBuffer = buffer;
|
|
||||||
_blockOffset = offset;
|
|
||||||
_blockRemaining = count;
|
|
||||||
_numSame = -1;
|
|
||||||
_lastByte = 0;
|
|
||||||
_runBytesOutstanding = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
int numRead = 0;
|
|
||||||
|
|
||||||
while (numRead < count && _runBytesOutstanding > 0)
|
|
||||||
{
|
|
||||||
int runCount = Math.Min(_runBytesOutstanding, count);
|
|
||||||
for (int i = 0; i < runCount; ++i)
|
|
||||||
{
|
|
||||||
buffer[offset + numRead] = _lastByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
_runBytesOutstanding -= runCount;
|
|
||||||
numRead += runCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (numRead < count && _blockRemaining > 0)
|
|
||||||
{
|
|
||||||
byte b = _blockBuffer[_blockOffset];
|
|
||||||
++_blockOffset;
|
|
||||||
--_blockRemaining;
|
|
||||||
|
|
||||||
if (_numSame == 4)
|
|
||||||
{
|
|
||||||
int runCount = Math.Min(b, count - numRead);
|
|
||||||
for (int i = 0; i < runCount; ++i)
|
|
||||||
{
|
|
||||||
buffer[offset + numRead] = _lastByte;
|
|
||||||
numRead++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_runBytesOutstanding = b - runCount;
|
|
||||||
_numSame = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (b != _lastByte || _numSame <= 0)
|
|
||||||
{
|
|
||||||
_lastByte = b;
|
|
||||||
_numSame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[offset + numRead] = b;
|
|
||||||
numRead++;
|
|
||||||
_numSame++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_position += numRead;
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a byte stream into a bit stream.
|
|
||||||
/// </summary>
|
|
||||||
internal class BigEndianBitStream : BitStream
|
|
||||||
{
|
|
||||||
private Stream _byteStream;
|
|
||||||
|
|
||||||
private uint _buffer;
|
|
||||||
private int _bufferAvailable;
|
|
||||||
|
|
||||||
private byte[] _readBuffer = new byte[2];
|
|
||||||
|
|
||||||
public BigEndianBitStream(Stream byteStream)
|
|
||||||
{
|
|
||||||
_byteStream = byteStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int MaxReadAhead
|
|
||||||
{
|
|
||||||
get { return 16; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override uint Read(int count)
|
|
||||||
{
|
|
||||||
if (count > 16)
|
|
||||||
{
|
|
||||||
uint result = Read(16) << (count - 16);
|
|
||||||
return result | Read(count - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
EnsureBufferFilled();
|
|
||||||
|
|
||||||
_bufferAvailable -= count;
|
|
||||||
|
|
||||||
uint mask = (uint)((1 << count) - 1);
|
|
||||||
|
|
||||||
return (uint)((_buffer >> _bufferAvailable) & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override uint Peek(int count)
|
|
||||||
{
|
|
||||||
EnsureBufferFilled();
|
|
||||||
|
|
||||||
uint mask = (uint)((1 << count) - 1);
|
|
||||||
|
|
||||||
return (uint)((_buffer >> (_bufferAvailable - count)) & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Consume(int count)
|
|
||||||
{
|
|
||||||
EnsureBufferFilled();
|
|
||||||
|
|
||||||
_bufferAvailable -= count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnsureBufferFilled()
|
|
||||||
{
|
|
||||||
if (_bufferAvailable < 16)
|
|
||||||
{
|
|
||||||
_readBuffer[0] = 0;
|
|
||||||
_readBuffer[1] = 0;
|
|
||||||
_byteStream.Read(_readBuffer, 0, 2);
|
|
||||||
|
|
||||||
_buffer = (uint)((uint)(_buffer << 16) | (uint)(_readBuffer[0] << 8) | (uint)_readBuffer[1]);
|
|
||||||
_bufferAvailable += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for bit streams.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The rules for conversion of a byte stream to a bit stream vary
|
|
||||||
/// between implementations.
|
|
||||||
/// </remarks>
|
|
||||||
internal abstract class BitStream
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the maximum number of bits that can be peeked on the stream.
|
|
||||||
/// </summary>
|
|
||||||
public abstract int MaxReadAhead { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads bits from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="count">The number of bits to read.</param>
|
|
||||||
/// <returns>The bits as a UInt32.</returns>
|
|
||||||
public abstract uint Read(int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Queries data from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="count">The number of bits to query.</param>
|
|
||||||
/// <returns>The bits as a UInt32.</returns>
|
|
||||||
/// <remarks>This method does not consume the bits (i.e. move the file pointer).</remarks>
|
|
||||||
public abstract uint Peek(int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Consumes bits from the stream without returning them.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="count">The number of bits to consume.</param>
|
|
||||||
public abstract void Consume(int count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for block compression algorithms.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class BlockCompressor
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the block size parameter to the algorithm.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Some algorithms may use this to control both compression and decompression, others may
|
|
||||||
/// only use it to control compression. Some may ignore it entirely.
|
|
||||||
/// </remarks>
|
|
||||||
public int BlockSize { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compresses some data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="source">The uncompressed input.</param>
|
|
||||||
/// <param name="sourceOffset">Offset of the input data in <c>source</c>.</param>
|
|
||||||
/// <param name="sourceLength">The amount of uncompressed data.</param>
|
|
||||||
/// <param name="compressed">The destination for the output compressed data.</param>
|
|
||||||
/// <param name="compressedOffset">Offset for the output data in <c>compressed</c>.</param>
|
|
||||||
/// <param name="compressedLength">The maximum size of the compressed data on input, and the actual size on output.</param>
|
|
||||||
/// <returns>Indication of success, or indication the data could not compress into the requested space.</returns>
|
|
||||||
public abstract CompressionResult Compress(byte[] source, int sourceOffset, int sourceLength, byte[] compressed, int compressedOffset, ref int compressedLength);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decompresses some data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="source">The compressed input.</param>
|
|
||||||
/// <param name="sourceOffset">Offset of the input data in <c>source</c>.</param>
|
|
||||||
/// <param name="sourceLength">The amount of compressed data.</param>
|
|
||||||
/// <param name="decompressed">The destination for the output decompressed data.</param>
|
|
||||||
/// <param name="decompressedOffset">Offset for the output data in <c>decompressed</c>.</param>
|
|
||||||
/// <returns>The amount of decompressed data.</returns>
|
|
||||||
public abstract int Decompress(byte[] source, int sourceOffset, int sourceLength, byte[] decompressed, int decompressedOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Possible results of attempting to compress data.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// A compression routine <i>may</i> return <c>Compressed</c>, even if the data
|
|
||||||
/// was 'all zeros' or increased in size. The <c>AllZeros</c> and <c>Incompressible</c>
|
|
||||||
/// values are for algorithms that include special detection for these cases.
|
|
||||||
/// </remarks>
|
|
||||||
public enum CompressionResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The data compressed succesfully.
|
|
||||||
/// </summary>
|
|
||||||
Compressed,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The data was all-zero's.
|
|
||||||
/// </summary>
|
|
||||||
AllZeros,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The data was incompressible (could not fit into destination buffer).
|
|
||||||
/// </summary>
|
|
||||||
Incompressible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
internal abstract class DataBlockTransform
|
|
||||||
{
|
|
||||||
protected abstract bool BuffersMustNotOverlap { get; }
|
|
||||||
|
|
||||||
public int Process(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
if (output.Length < outputOffset + (long)MinOutputCount(inputCount))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(
|
|
||||||
string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"Output buffer to small, must be at least {0} bytes may need to be {1} bytes",
|
|
||||||
MinOutputCount(inputCount),
|
|
||||||
MaxOutputCount(inputCount)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuffersMustNotOverlap)
|
|
||||||
{
|
|
||||||
int maxOut = MaxOutputCount(inputCount);
|
|
||||||
|
|
||||||
if (input == output
|
|
||||||
&& (inputOffset + (long)inputCount > outputOffset)
|
|
||||||
&& (inputOffset <= outputOffset + (long)maxOut))
|
|
||||||
{
|
|
||||||
byte[] tempBuffer = new byte[maxOut];
|
|
||||||
|
|
||||||
int outCount = DoProcess(input, inputOffset, inputCount, tempBuffer, 0);
|
|
||||||
Array.Copy(tempBuffer, 0, output, outputOffset, outCount);
|
|
||||||
|
|
||||||
return outCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DoProcess(input, inputOffset, inputCount, output, outputOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract int DoProcess(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset);
|
|
||||||
|
|
||||||
protected abstract int MaxOutputCount(int inputCount);
|
|
||||||
|
|
||||||
protected abstract int MinOutputCount(int inputCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A canonical Huffman tree implementation.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// A lookup table is created that will take any bit sequence (max tree depth in length),
|
|
||||||
/// indicating the output symbol. In WIM files, in practice, no chunk exceeds 32768 bytes
|
|
||||||
/// in length, so we often end up generating a bigger lookup table than the data it's
|
|
||||||
/// encoding. This makes for exceptionally fast symbol lookups O(1), but is inefficient
|
|
||||||
/// overall.
|
|
||||||
/// </remarks>
|
|
||||||
internal sealed class HuffmanTree
|
|
||||||
{
|
|
||||||
private int _numBits; // Max bits per symbol
|
|
||||||
private int _numSymbols; // Max symbols
|
|
||||||
private uint[] _lengths;
|
|
||||||
private uint[] _buffer;
|
|
||||||
|
|
||||||
public HuffmanTree(uint[] lengths)
|
|
||||||
{
|
|
||||||
_lengths = lengths;
|
|
||||||
_numSymbols = lengths.Length;
|
|
||||||
|
|
||||||
uint maxLength = 0;
|
|
||||||
for (int i = 0; i < _lengths.Length; ++i)
|
|
||||||
{
|
|
||||||
if (_lengths[i] > maxLength)
|
|
||||||
{
|
|
||||||
maxLength = _lengths[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_numBits = (int)maxLength;
|
|
||||||
_buffer = new uint[1 << _numBits];
|
|
||||||
|
|
||||||
Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint[] Lengths
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _lengths;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint NextSymbol(BitStream bitStream)
|
|
||||||
{
|
|
||||||
uint symbol = _buffer[bitStream.Peek(_numBits)];
|
|
||||||
|
|
||||||
// We may have over-read, reset bitstream position
|
|
||||||
bitStream.Consume((int)_lengths[symbol]);
|
|
||||||
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Build()
|
|
||||||
{
|
|
||||||
int position = 0;
|
|
||||||
|
|
||||||
// For each bit-length...
|
|
||||||
for (int i = 1; i <= _numBits; ++i)
|
|
||||||
{
|
|
||||||
// Check each symbol
|
|
||||||
for (uint symbol = 0; symbol < _numSymbols; ++symbol)
|
|
||||||
{
|
|
||||||
if (_lengths[symbol] == i)
|
|
||||||
{
|
|
||||||
int numToFill = 1 << (_numBits - i);
|
|
||||||
for (int n = 0; n < numToFill; ++n)
|
|
||||||
{
|
|
||||||
_buffer[position + n] = symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
position += numToFill;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = position; i < _buffer.Length; ++i)
|
|
||||||
{
|
|
||||||
_buffer[i] = uint.MaxValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal sealed class InverseBurrowsWheeler : DataBlockTransform
|
|
||||||
{
|
|
||||||
private int[] _pointers;
|
|
||||||
private int[] _nextPos;
|
|
||||||
|
|
||||||
public InverseBurrowsWheeler(int bufferSize)
|
|
||||||
{
|
|
||||||
_pointers = new int[bufferSize];
|
|
||||||
_nextPos = new int[256];
|
|
||||||
}
|
|
||||||
|
|
||||||
public int OriginalIndex { get; set; }
|
|
||||||
|
|
||||||
protected override bool BuffersMustNotOverlap
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int DoProcess(byte[] input, int inputOffset, int inputCount, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
int outputCount = inputCount;
|
|
||||||
|
|
||||||
// First find the frequency of each value
|
|
||||||
Array.Clear(_nextPos, 0, _nextPos.Length);
|
|
||||||
for (int i = inputOffset; i < inputOffset + inputCount; ++i)
|
|
||||||
{
|
|
||||||
_nextPos[input[i]]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know they're 'sorted' in the first column, so now can figure
|
|
||||||
// out the position of the first instance of each.
|
|
||||||
int sum = 0;
|
|
||||||
for (int i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
int tempSum = sum;
|
|
||||||
sum += _nextPos[i];
|
|
||||||
_nextPos[i] = tempSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each value in the final column, put a pointer to to the
|
|
||||||
// 'next' character in the first (sorted) column.
|
|
||||||
for (int i = 0; i < inputCount; ++i)
|
|
||||||
{
|
|
||||||
_pointers[_nextPos[input[inputOffset + i]]++] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The 'next' character after the end of the original string is the
|
|
||||||
// first character of the original string.
|
|
||||||
int focus = _pointers[OriginalIndex];
|
|
||||||
|
|
||||||
// We can now just walk the pointers to reconstruct the original string
|
|
||||||
for (int i = 0; i < outputCount; ++i)
|
|
||||||
{
|
|
||||||
output[outputOffset + i] = input[inputOffset + focus];
|
|
||||||
focus = _pointers[focus];
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int MaxOutputCount(int inputCount)
|
|
||||||
{
|
|
||||||
return inputCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override int MinOutputCount(int inputCount)
|
|
||||||
{
|
|
||||||
return inputCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.Compression
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.IO.Compression;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of the Zlib compression algorithm.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Only decompression is currently implemented.</remarks>
|
|
||||||
public class ZlibStream : Stream
|
|
||||||
{
|
|
||||||
private Stream _stream;
|
|
||||||
private CompressionMode _mode;
|
|
||||||
private DeflateStream _deflateStream;
|
|
||||||
private Adler32 _adler32;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the ZlibStream class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream to compress of decompress.</param>
|
|
||||||
/// <param name="mode">Whether to compress or decompress.</param>
|
|
||||||
/// <param name="leaveOpen">Whether closing this stream should leave <c>stream</c> open.</param>
|
|
||||||
public ZlibStream(Stream stream, CompressionMode mode, bool leaveOpen)
|
|
||||||
{
|
|
||||||
_stream = stream;
|
|
||||||
_mode = mode;
|
|
||||||
|
|
||||||
if (mode == CompressionMode.Decompress)
|
|
||||||
{
|
|
||||||
// We just sanity check against expected header values...
|
|
||||||
byte[] headerBuffer = Utilities.ReadFully(stream, 2);
|
|
||||||
ushort header = Utilities.ToUInt16BigEndian(headerBuffer, 0);
|
|
||||||
|
|
||||||
if ((header % 31) != 0)
|
|
||||||
{
|
|
||||||
throw new IOException("Invalid Zlib header found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((header & 0x0F00) != (8 << 8))
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Zlib compression not using DEFLATE algorithm");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((header & 0x0020) != 0)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Zlib compression using preset dictionary");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ushort header =
|
|
||||||
(8 << 8) // DEFLATE
|
|
||||||
| (7 << 12) // 32K window size
|
|
||||||
| 0x80; // Default algorithm
|
|
||||||
header |= (ushort)(31 - (header % 31));
|
|
||||||
|
|
||||||
byte[] headerBuffer = new byte[2];
|
|
||||||
Utilities.WriteBytesBigEndian(header, headerBuffer, 0);
|
|
||||||
stream.Write(headerBuffer, 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_deflateStream = new DeflateStream(stream, mode, leaveOpen);
|
|
||||||
_adler32 = new Adler32();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether the stream can be read.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get { return _deflateStream.CanRead; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether the stream pointer can be changed.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether the stream can be written to.
|
|
||||||
/// </summary>
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get { return _deflateStream.CanWrite; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets and sets the stream position.
|
|
||||||
/// </summary>
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get { throw new NotSupportedException(); }
|
|
||||||
set { throw new NotSupportedException(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Closes the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override void Close()
|
|
||||||
{
|
|
||||||
if (_mode == CompressionMode.Decompress)
|
|
||||||
{
|
|
||||||
// Can only check Adler checksum on seekable streams. Since DeflateStream
|
|
||||||
// aggresively caches input, it normally has already consumed the footer.
|
|
||||||
if (_stream.CanSeek)
|
|
||||||
{
|
|
||||||
_stream.Seek(-4, SeekOrigin.End);
|
|
||||||
byte[] footerBuffer = Utilities.ReadFully(_stream, 4);
|
|
||||||
if (Utilities.ToInt32BigEndian(footerBuffer, 0) != _adler32.Value)
|
|
||||||
{
|
|
||||||
throw new InvalidDataException("Corrupt decompressed data detected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_deflateStream.Close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_deflateStream.Close();
|
|
||||||
|
|
||||||
byte[] footerBuffer = new byte[4];
|
|
||||||
Utilities.WriteBytesBigEndian(_adler32.Value, footerBuffer, 0);
|
|
||||||
_stream.Write(footerBuffer, 0, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes the stream.
|
|
||||||
/// </summary>
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
_deflateStream.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads data from the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to populate.</param>
|
|
||||||
/// <param name="offset">The first byte to write.</param>
|
|
||||||
/// <param name="count">The number of bytes requested.</param>
|
|
||||||
/// <returns>The number of bytes read.</returns>
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckParams(buffer, offset, count);
|
|
||||||
|
|
||||||
int numRead = _deflateStream.Read(buffer, offset, count);
|
|
||||||
_adler32.Process(buffer, offset, numRead);
|
|
||||||
return numRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Seeks to a new position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">Relative position to seek to.</param>
|
|
||||||
/// <param name="origin">The origin of the seek.</param>
|
|
||||||
/// <returns>The new position.</returns>
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes the length of the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The new desired length of the stream.</param>
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes data to the stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">Buffer containing the data to write.</param>
|
|
||||||
/// <param name="offset">Offset of the first byte to write.</param>
|
|
||||||
/// <param name="count">Number of bytes to write.</param>
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckParams(buffer, offset, count);
|
|
||||||
|
|
||||||
_adler32.Process(buffer, offset, count);
|
|
||||||
_deflateStream.Write(buffer, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CheckParams(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (buffer == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 0 || offset > buffer.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Offset outside of array bounds", "offset");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0 || offset + count > buffer.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Array index out of bounds", "count");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The concatenation of multiple streams (read-only, for now).
|
|
||||||
/// </summary>
|
|
||||||
internal class ConcatStream : SparseStream
|
|
||||||
{
|
|
||||||
private SparseStream[] _streams;
|
|
||||||
private Ownership _ownsStreams;
|
|
||||||
private bool _canWrite;
|
|
||||||
|
|
||||||
private long _position;
|
|
||||||
|
|
||||||
public ConcatStream(Ownership ownsStreams, params SparseStream[] streams)
|
|
||||||
{
|
|
||||||
_ownsStreams = ownsStreams;
|
|
||||||
_streams = streams;
|
|
||||||
|
|
||||||
// Only allow writes if all streams can be written
|
|
||||||
_canWrite = true;
|
|
||||||
foreach (var stream in streams)
|
|
||||||
{
|
|
||||||
if (!stream.CanWrite)
|
|
||||||
{
|
|
||||||
_canWrite = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _canWrite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
long length = 0;
|
|
||||||
for (int i = 0; i < _streams.Length; ++i)
|
|
||||||
{
|
|
||||||
length += _streams[i].Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
_position = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
List<StreamExtent> extents = new List<StreamExtent>();
|
|
||||||
|
|
||||||
long pos = 0;
|
|
||||||
for (int i = 0; i < _streams.Length; ++i)
|
|
||||||
{
|
|
||||||
foreach (StreamExtent extent in _streams[i].Extents)
|
|
||||||
{
|
|
||||||
extents.Add(new StreamExtent(extent.Start + pos, extent.Length));
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += _streams[i].Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return extents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
for (int i = 0; i < _streams.Length; ++i)
|
|
||||||
{
|
|
||||||
_streams[i].Flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
int totalRead = 0;
|
|
||||||
int numRead = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
long activeStreamStartPos;
|
|
||||||
int activeStream = GetActiveStream(out activeStreamStartPos);
|
|
||||||
|
|
||||||
_streams[activeStream].Position = _position - activeStreamStartPos;
|
|
||||||
|
|
||||||
numRead = _streams[activeStream].Read(buffer, offset + totalRead, count - totalRead);
|
|
||||||
|
|
||||||
totalRead += numRead;
|
|
||||||
_position += numRead;
|
|
||||||
}
|
|
||||||
while (numRead != 0);
|
|
||||||
|
|
||||||
return totalRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
long effectiveOffset = offset;
|
|
||||||
if (origin == SeekOrigin.Current)
|
|
||||||
{
|
|
||||||
effectiveOffset += _position;
|
|
||||||
}
|
|
||||||
else if (origin == SeekOrigin.End)
|
|
||||||
{
|
|
||||||
effectiveOffset += Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effectiveOffset < 0)
|
|
||||||
{
|
|
||||||
throw new IOException("Attempt to move before beginning of disk");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Position = effectiveOffset;
|
|
||||||
return Position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
long lastStreamOffset;
|
|
||||||
int lastStream = GetStream(Length, out lastStreamOffset);
|
|
||||||
if (value < lastStreamOffset)
|
|
||||||
{
|
|
||||||
throw new IOException(string.Format(CultureInfo.InvariantCulture, "Unable to reduce stream length to less than {0}", lastStreamOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
_streams[lastStream].SetLength(value - lastStreamOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
int totalWritten = 0;
|
|
||||||
while (totalWritten != count)
|
|
||||||
{
|
|
||||||
// Offset of the stream = streamOffset
|
|
||||||
long streamOffset;
|
|
||||||
int streamIdx = GetActiveStream(out streamOffset);
|
|
||||||
|
|
||||||
// Offset within the stream = streamPos
|
|
||||||
long streamPos = _position - streamOffset;
|
|
||||||
_streams[streamIdx].Position = streamPos;
|
|
||||||
|
|
||||||
// Write (limited to the stream's length), except for final stream - that may be
|
|
||||||
// extendable
|
|
||||||
int numToWrite;
|
|
||||||
if (streamIdx == _streams.Length - 1)
|
|
||||||
{
|
|
||||||
numToWrite = count - totalWritten;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numToWrite = (int)Math.Min(count - totalWritten, _streams[streamIdx].Length - streamPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
_streams[streamIdx].Write(buffer, offset + totalWritten, numToWrite);
|
|
||||||
|
|
||||||
totalWritten += numToWrite;
|
|
||||||
_position += numToWrite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (disposing && _ownsStreams == Ownership.Dispose && _streams != null)
|
|
||||||
{
|
|
||||||
foreach (var stream in _streams)
|
|
||||||
{
|
|
||||||
stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_streams = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetActiveStream(out long startPos)
|
|
||||||
{
|
|
||||||
return GetStream(_position, out startPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetStream(long targetPos, out long streamStartPos)
|
|
||||||
{
|
|
||||||
// Find the stream that _position is within
|
|
||||||
streamStartPos = 0;
|
|
||||||
int focusStream = 0;
|
|
||||||
while (focusStream < _streams.Length - 1 && streamStartPos + _streams[focusStream].Length <= targetPos)
|
|
||||||
{
|
|
||||||
streamStartPos += _streams[focusStream].Length;
|
|
||||||
focusStream++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return focusStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckDisposed()
|
|
||||||
{
|
|
||||||
if (_streams == null)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException("ConcatStream");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
internal abstract class Crc32
|
|
||||||
{
|
|
||||||
protected readonly uint[] Table;
|
|
||||||
protected uint _value;
|
|
||||||
|
|
||||||
protected Crc32(uint[] table)
|
|
||||||
{
|
|
||||||
Table = table;
|
|
||||||
_value = 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Value
|
|
||||||
{
|
|
||||||
get { return _value ^ 0xFFFFFFFF; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void Process(byte[] buffer, int offset, int count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
internal enum Crc32Algorithm
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Used in Ethernet, PKZIP, BZIP2, Gzip, PNG, etc. (aka CRC32).
|
|
||||||
/// </summary>
|
|
||||||
Common = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used in iSCSI, SCTP, Btrfs, Vhdx. (aka CRC32C).
|
|
||||||
/// </summary>
|
|
||||||
Castagnoli = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unknown usage. (aka CRC32K).
|
|
||||||
/// </summary>
|
|
||||||
Koopman = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used in AIXM. (aka CRC32Q).
|
|
||||||
/// </summary>
|
|
||||||
Aeronautical = 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates CRC32 of buffers.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class Crc32BigEndian : Crc32
|
|
||||||
{
|
|
||||||
private static readonly uint[][] Tables;
|
|
||||||
|
|
||||||
static Crc32BigEndian()
|
|
||||||
{
|
|
||||||
Tables = new uint[4][];
|
|
||||||
|
|
||||||
Tables[(int)Crc32Algorithm.Common] = CalcTable(0x04C11DB7);
|
|
||||||
Tables[(int)Crc32Algorithm.Castagnoli] = CalcTable(0x1EDC6F41);
|
|
||||||
Tables[(int)Crc32Algorithm.Koopman] = CalcTable(0x741B8CD7);
|
|
||||||
Tables[(int)Crc32Algorithm.Aeronautical] = CalcTable(0x814141AB);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Crc32BigEndian(Crc32Algorithm algorithm)
|
|
||||||
: base(Tables[(int)algorithm])
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint Compute(Crc32Algorithm algorithm, byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
return Process(Tables[(int)algorithm], 0xFFFFFFFF, buffer, offset, count) ^ 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Process(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
_value = Process(Table, _value, buffer, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] CalcTable(uint polynomial)
|
|
||||||
{
|
|
||||||
uint[] table = new uint[256];
|
|
||||||
|
|
||||||
for (uint i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
uint crc = i << 24;
|
|
||||||
|
|
||||||
for (int j = 8; j > 0; --j)
|
|
||||||
{
|
|
||||||
if ((crc & 0x80000000) != 0)
|
|
||||||
{
|
|
||||||
crc = (crc << 1) ^ polynomial;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crc <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table[i] = crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint Process(uint[] table, uint accumulator, byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
uint value = accumulator;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
byte b = buffer[offset + i];
|
|
||||||
value = table[(value >> 24) ^ b] ^ (value << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates CRC32 of buffers.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class Crc32LittleEndian : Crc32
|
|
||||||
{
|
|
||||||
private static readonly uint[][] Tables;
|
|
||||||
|
|
||||||
static Crc32LittleEndian()
|
|
||||||
{
|
|
||||||
Tables = new uint[4][];
|
|
||||||
|
|
||||||
Tables[(int)Crc32Algorithm.Common] = CalcTable(0xEDB88320);
|
|
||||||
Tables[(int)Crc32Algorithm.Castagnoli] = CalcTable(0x82F63B78);
|
|
||||||
Tables[(int)Crc32Algorithm.Koopman] = CalcTable(0xEB31D82E);
|
|
||||||
Tables[(int)Crc32Algorithm.Aeronautical] = CalcTable(0xD5828281);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Crc32LittleEndian(Crc32Algorithm algorithm)
|
|
||||||
: base(Tables[(int)algorithm])
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint Compute(Crc32Algorithm algorithm, byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
return Process(Tables[(int)algorithm], 0xFFFFFFFF, buffer, offset, count) ^ 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Process(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
_value = Process(Table, _value, buffer, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] CalcTable(uint polynomial)
|
|
||||||
{
|
|
||||||
uint[] table = new uint[256];
|
|
||||||
|
|
||||||
table[0] = 0;
|
|
||||||
for (uint i = 0; i <= 255; ++i)
|
|
||||||
{
|
|
||||||
uint crc = i;
|
|
||||||
|
|
||||||
for (int j = 8; j > 0; --j)
|
|
||||||
{
|
|
||||||
if ((crc & 1) != 0)
|
|
||||||
{
|
|
||||||
crc = (crc >> 1) ^ polynomial;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crc >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table[i] = crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint Process(uint[] table, uint accumulator, byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
uint value = accumulator;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
byte b = buffer[offset + i];
|
|
||||||
|
|
||||||
uint temp1 = (value >> 8) & 0x00FFFFFF;
|
|
||||||
uint temp2 = table[(value ^ b) & 0xFF];
|
|
||||||
value = temp1 ^ temp2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides information about a directory on a disc.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This class allows navigation of the disc directory/file hierarchy.
|
|
||||||
/// </remarks>
|
|
||||||
public sealed class DiscDirectoryInfo : DiscFileSystemInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the DiscDirectoryInfo class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fileSystem">The file system the directory info relates to.</param>
|
|
||||||
/// <param name="path">The path within the file system of the directory.</param>
|
|
||||||
internal DiscDirectoryInfo(DiscFileSystem fileSystem, string path)
|
|
||||||
: base(fileSystem, path)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the directory exists.
|
|
||||||
/// </summary>
|
|
||||||
public override bool Exists
|
|
||||||
{
|
|
||||||
get { return FileSystem.DirectoryExists(Path); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the full path of the directory.
|
|
||||||
/// </summary>
|
|
||||||
public override string FullName
|
|
||||||
{
|
|
||||||
get { return base.FullName + @"\"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a directory.
|
|
||||||
/// </summary>
|
|
||||||
public void Create()
|
|
||||||
{
|
|
||||||
FileSystem.CreateDirectory(Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory, even if it's not empty.
|
|
||||||
/// </summary>
|
|
||||||
public override void Delete()
|
|
||||||
{
|
|
||||||
FileSystem.DeleteDirectory(Path, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory, with the caller choosing whether to recurse.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="recursive"><c>true</c> to delete all child node, <c>false</c> to fail if the directory is not empty.</param>
|
|
||||||
public void Delete(bool recursive)
|
|
||||||
{
|
|
||||||
FileSystem.DeleteDirectory(Path, recursive);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a directory and it's contents to a new path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="destinationDirName">The destination directory name.</param>
|
|
||||||
public void MoveTo(string destinationDirName)
|
|
||||||
{
|
|
||||||
FileSystem.MoveDirectory(Path, destinationDirName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all child directories.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An array of child directories.</returns>
|
|
||||||
public DiscDirectoryInfo[] GetDirectories()
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscDirectoryInfo>(FileSystem.GetDirectories(Path), (p) => new DiscDirectoryInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all child directories matching a search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern">The search pattern.</param>
|
|
||||||
/// <returns>An array of child directories, or empty if none match.</returns>
|
|
||||||
/// <remarks>The search pattern can include the wildcards * (matching 0 or more characters)
|
|
||||||
/// and ? (matching 1 character).</remarks>
|
|
||||||
public DiscDirectoryInfo[] GetDirectories(string pattern)
|
|
||||||
{
|
|
||||||
return GetDirectories(pattern, SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all descendant directories matching a search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern">The search pattern.</param>
|
|
||||||
/// <param name="searchOption">Whether to search just this directory, or all children.</param>
|
|
||||||
/// <returns>An array of descendant directories, or empty if none match.</returns>
|
|
||||||
/// <remarks>The search pattern can include the wildcards * (matching 0 or more characters)
|
|
||||||
/// and ? (matching 1 character). The option parameter determines whether only immediate
|
|
||||||
/// children, or all children are returned.</remarks>
|
|
||||||
public DiscDirectoryInfo[] GetDirectories(string pattern, SearchOption searchOption)
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscDirectoryInfo>(FileSystem.GetDirectories(Path, pattern, searchOption), (p) => new DiscDirectoryInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all files.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An array of files.</returns>
|
|
||||||
public DiscFileInfo[] GetFiles()
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscFileInfo>(FileSystem.GetFiles(Path), (p) => new DiscFileInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all files matching a search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern">The search pattern.</param>
|
|
||||||
/// <returns>An array of files, or empty if none match.</returns>
|
|
||||||
/// <remarks>The search pattern can include the wildcards * (matching 0 or more characters)
|
|
||||||
/// and ? (matching 1 character).</remarks>
|
|
||||||
public DiscFileInfo[] GetFiles(string pattern)
|
|
||||||
{
|
|
||||||
return GetFiles(pattern, SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all descendant files matching a search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern">The search pattern.</param>
|
|
||||||
/// <param name="searchOption">Whether to search just this directory, or all children.</param>
|
|
||||||
/// <returns>An array of descendant files, or empty if none match.</returns>
|
|
||||||
/// <remarks>The search pattern can include the wildcards * (matching 0 or more characters)
|
|
||||||
/// and ? (matching 1 character). The option parameter determines whether only immediate
|
|
||||||
/// children, or all children are returned.</remarks>
|
|
||||||
public DiscFileInfo[] GetFiles(string pattern, SearchOption searchOption)
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscFileInfo>(FileSystem.GetFiles(Path, pattern, searchOption), (p) => new DiscFileInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all files and directories in this directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>An array of files and directories.</returns>
|
|
||||||
public DiscFileSystemInfo[] GetFileSystemInfos()
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscFileSystemInfo>(FileSystem.GetFileSystemEntries(Path), (p) => new DiscFileSystemInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all files and directories in this directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pattern">The search pattern.</param>
|
|
||||||
/// <returns>An array of files and directories.</returns>
|
|
||||||
/// <remarks>The search pattern can include the wildcards * (matching 0 or more characters)
|
|
||||||
/// and ? (matching 1 character).</remarks>
|
|
||||||
public DiscFileSystemInfo[] GetFileSystemInfos(string pattern)
|
|
||||||
{
|
|
||||||
return Utilities.Map<string, DiscFileSystemInfo>(FileSystem.GetFileSystemEntries(Path, pattern), (p) => new DiscFileSystemInfo(FileSystem, p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides information about a file on a disc.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiscFileInfo : DiscFileSystemInfo
|
|
||||||
{
|
|
||||||
internal DiscFileInfo(DiscFileSystem fileSystem, string path)
|
|
||||||
: base(fileSystem, path)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file exists.
|
|
||||||
/// </summary>
|
|
||||||
public override bool Exists
|
|
||||||
{
|
|
||||||
get { return FileSystem.FileExists(Path); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an instance of the parent directory.
|
|
||||||
/// </summary>
|
|
||||||
public DiscDirectoryInfo Directory
|
|
||||||
{
|
|
||||||
get { return Parent; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a string representing the directory's full path.
|
|
||||||
/// </summary>
|
|
||||||
public string DirectoryName
|
|
||||||
{
|
|
||||||
get { return Directory.FullName; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether the file is read-only.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsReadOnly
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (Attributes & FileAttributes.ReadOnly) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
Attributes = Attributes | FileAttributes.ReadOnly;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Attributes = Attributes & ~FileAttributes.ReadOnly;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of the current file in bytes.
|
|
||||||
/// </summary>
|
|
||||||
public long Length
|
|
||||||
{
|
|
||||||
get { return FileSystem.GetFileLength(Path); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a file.
|
|
||||||
/// </summary>
|
|
||||||
public override void Delete()
|
|
||||||
{
|
|
||||||
FileSystem.DeleteFile(Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a <see cref="StreamWriter" /> that appends text to the file represented by this <see cref="DiscFileInfo"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The newly created writer.</returns>
|
|
||||||
public StreamWriter AppendText()
|
|
||||||
{
|
|
||||||
return new StreamWriter(Open(FileMode.Append));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="destinationFileName">The destination file.</param>
|
|
||||||
public void CopyTo(string destinationFileName)
|
|
||||||
{
|
|
||||||
CopyTo(destinationFileName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file, allowing overwriting of an existing file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="destinationFileName">The destination file.</param>
|
|
||||||
/// <param name="overwrite">Whether to permit over-writing of an existing file.</param>
|
|
||||||
public void CopyTo(string destinationFileName, bool overwrite)
|
|
||||||
{
|
|
||||||
FileSystem.CopyFile(Path, destinationFileName, overwrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new file for reading and writing.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The newly created stream.</returns>
|
|
||||||
public Stream Create()
|
|
||||||
{
|
|
||||||
return Open(FileMode.Create);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new <see cref="StreamWriter"/> that writes a new text file.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A new stream writer that can write to the file contents.</returns>
|
|
||||||
public StreamWriter CreateText()
|
|
||||||
{
|
|
||||||
return new StreamWriter(Open(FileMode.Create));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a file to a new location.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="destinationFileName">The new name of the file.</param>
|
|
||||||
public void MoveTo(string destinationFileName)
|
|
||||||
{
|
|
||||||
FileSystem.MoveFile(Path, destinationFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the current file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <returns>The newly created stream.</returns>
|
|
||||||
/// <remarks>Read-only file systems only support <c>FileMode.Open</c>.</remarks>
|
|
||||||
public Stream Open(FileMode mode)
|
|
||||||
{
|
|
||||||
return FileSystem.OpenFile(Path, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the current file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <param name="access">The access permissions for the created stream.</param>
|
|
||||||
/// <returns>The newly created stream.</returns>
|
|
||||||
/// <remarks>Read-only file systems only support <c>FileMode.Open</c> and <c>FileAccess.Read</c>.</remarks>
|
|
||||||
public Stream Open(FileMode mode, FileAccess access)
|
|
||||||
{
|
|
||||||
return FileSystem.OpenFile(Path, mode, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens an existing file for read-only access.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The newly created stream.</returns>
|
|
||||||
public Stream OpenRead()
|
|
||||||
{
|
|
||||||
return Open(FileMode.Open, FileAccess.Read);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens an existing file for reading as UTF-8 text.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The newly created reader.</returns>
|
|
||||||
public StreamReader OpenText()
|
|
||||||
{
|
|
||||||
return new StreamReader(OpenRead());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens a file for writing.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The newly created stream.</returns>
|
|
||||||
public Stream OpenWrite()
|
|
||||||
{
|
|
||||||
return Open(FileMode.Open, FileAccess.Write);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal sealed class DiscFileLocator : FileLocator
|
|
||||||
{
|
|
||||||
private DiscFileSystem _fileSystem;
|
|
||||||
private string _basePath;
|
|
||||||
|
|
||||||
public DiscFileLocator(DiscFileSystem fileSystem, string basePath)
|
|
||||||
{
|
|
||||||
_fileSystem = fileSystem;
|
|
||||||
_basePath = basePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Exists(string fileName)
|
|
||||||
{
|
|
||||||
return _fileSystem.FileExists(Utilities.CombinePaths(_basePath, fileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Stream Open(string fileName, FileMode mode, FileAccess access, FileShare share)
|
|
||||||
{
|
|
||||||
return _fileSystem.OpenFile(Utilities.CombinePaths(_basePath, fileName), mode, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override FileLocator GetRelativeLocator(string path)
|
|
||||||
{
|
|
||||||
return new DiscFileLocator(_fileSystem, Utilities.CombinePaths(_basePath, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetFullPath(string path)
|
|
||||||
{
|
|
||||||
return Utilities.CombinePaths(_basePath, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetDirectoryFromPath(string path)
|
|
||||||
{
|
|
||||||
return Utilities.GetDirectoryFromPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string GetFileFromPath(string path)
|
|
||||||
{
|
|
||||||
return Utilities.GetFileFromPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override DateTime GetLastWriteTimeUtc(string path)
|
|
||||||
{
|
|
||||||
return _fileSystem.GetLastWriteTimeUtc(Utilities.CombinePaths(_basePath, path));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool HasCommonRoot(FileLocator other)
|
|
||||||
{
|
|
||||||
DiscFileLocator otherDiscLocator = other as DiscFileLocator;
|
|
||||||
|
|
||||||
if (otherDiscLocator == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common root if the same file system instance.
|
|
||||||
return Object.ReferenceEquals(otherDiscLocator._fileSystem, _fileSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ResolveRelativePath(string path)
|
|
||||||
{
|
|
||||||
return Utilities.ResolveRelativePath(_basePath, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,499 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides the base class for all file systems.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DiscFileSystem : MarshalByRefObject, IFileSystem, IDisposable
|
|
||||||
{
|
|
||||||
private DiscFileSystemOptions _options;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the DiscFileSystem class.
|
|
||||||
/// </summary>
|
|
||||||
protected DiscFileSystem()
|
|
||||||
{
|
|
||||||
_options = new DiscFileSystemOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the DiscFileSystem class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="defaultOptions">The options instance to use for this file system instance.</param>
|
|
||||||
protected DiscFileSystem(DiscFileSystemOptions defaultOptions)
|
|
||||||
{
|
|
||||||
_options = defaultOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finalizes an instance of the DiscFileSystem class.
|
|
||||||
/// </summary>
|
|
||||||
~DiscFileSystem()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the file system options, which can be modified.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DiscFileSystemOptions Options
|
|
||||||
{
|
|
||||||
get { return _options; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a friendly description of the file system type.
|
|
||||||
/// </summary>
|
|
||||||
public abstract string FriendlyName
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file system is read-only or read-write.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>true if the file system is read-write.</returns>
|
|
||||||
public abstract bool CanWrite { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the root directory of the file system.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DiscDirectoryInfo Root
|
|
||||||
{
|
|
||||||
get { return new DiscDirectoryInfo(this, string.Empty); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the volume label.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string VolumeLabel
|
|
||||||
{
|
|
||||||
get { return string.Empty; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file system is thread-safe.
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool IsThreadSafe
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceFile">The source file.</param>
|
|
||||||
/// <param name="destinationFile">The destination file.</param>
|
|
||||||
public virtual void CopyFile(string sourceFile, string destinationFile)
|
|
||||||
{
|
|
||||||
CopyFile(sourceFile, destinationFile, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file, allowing overwriting of an existing file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceFile">The source file.</param>
|
|
||||||
/// <param name="destinationFile">The destination file.</param>
|
|
||||||
/// <param name="overwrite">Whether to permit over-writing of an existing file.</param>
|
|
||||||
public abstract void CopyFile(string sourceFile, string destinationFile, bool overwrite);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the new directory.</param>
|
|
||||||
public abstract void CreateDirectory(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the directory to delete.</param>
|
|
||||||
public abstract void DeleteDirectory(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory, optionally with all descendants.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the directory to delete.</param>
|
|
||||||
/// <param name="recursive">Determines if the all descendants should be deleted.</param>
|
|
||||||
public virtual void DeleteDirectory(string path, bool recursive)
|
|
||||||
{
|
|
||||||
if (recursive)
|
|
||||||
{
|
|
||||||
foreach (string dir in GetDirectories(path))
|
|
||||||
{
|
|
||||||
DeleteDirectory(dir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string file in GetFiles(path))
|
|
||||||
{
|
|
||||||
DeleteFile(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file to delete.</param>
|
|
||||||
public abstract void DeleteFile(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a directory exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the directory exists.</returns>
|
|
||||||
public abstract bool DirectoryExists(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a file exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the file exists.</returns>
|
|
||||||
public abstract bool FileExists(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a file or directory exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the file or directory exists.</returns>
|
|
||||||
public virtual bool Exists(string path)
|
|
||||||
{
|
|
||||||
return FileExists(path) || DirectoryExists(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of directories.</returns>
|
|
||||||
public virtual string[] GetDirectories(string path)
|
|
||||||
{
|
|
||||||
return GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of directories matching the search pattern.</returns>
|
|
||||||
public virtual string[] GetDirectories(string path, string searchPattern)
|
|
||||||
{
|
|
||||||
return GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern, using a value to determine whether to search subdirectories.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <param name="searchOption">Indicates whether to search subdirectories.</param>
|
|
||||||
/// <returns>Array of directories matching the search pattern.</returns>
|
|
||||||
public abstract string[] GetDirectories(string path, string searchPattern, SearchOption searchOption);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of files.</returns>
|
|
||||||
public virtual string[] GetFiles(string path)
|
|
||||||
{
|
|
||||||
return GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of files matching the search pattern.</returns>
|
|
||||||
public virtual string[] GetFiles(string path, string searchPattern)
|
|
||||||
{
|
|
||||||
return GetFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory matching a specified
|
|
||||||
/// search pattern, using a value to determine whether to search subdirectories.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <param name="searchOption">Indicates whether to search subdirectories.</param>
|
|
||||||
/// <returns>Array of files matching the search pattern.</returns>
|
|
||||||
public abstract string[] GetFiles(string path, string searchPattern, SearchOption searchOption);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of all files and subdirectories in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of files and subdirectories matching the search pattern.</returns>
|
|
||||||
public abstract string[] GetFileSystemEntries(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files and subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of files and subdirectories matching the search pattern.</returns>
|
|
||||||
public abstract string[] GetFileSystemEntries(string path, string searchPattern);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceDirectoryName">The directory to move.</param>
|
|
||||||
/// <param name="destinationDirectoryName">The target directory name.</param>
|
|
||||||
public abstract void MoveDirectory(string sourceDirectoryName, string destinationDirectoryName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceName">The file to move.</param>
|
|
||||||
/// <param name="destinationName">The target file name.</param>
|
|
||||||
public virtual void MoveFile(string sourceName, string destinationName)
|
|
||||||
{
|
|
||||||
MoveFile(sourceName, destinationName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a file, allowing an existing file to be overwritten.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceName">The file to move.</param>
|
|
||||||
/// <param name="destinationName">The target file name.</param>
|
|
||||||
/// <param name="overwrite">Whether to permit a destination file to be overwritten.</param>
|
|
||||||
public abstract void MoveFile(string sourceName, string destinationName, bool overwrite);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the specified file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path of the file to open.</param>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <returns>The new stream.</returns>
|
|
||||||
public virtual SparseStream OpenFile(string path, FileMode mode)
|
|
||||||
{
|
|
||||||
return OpenFile(path, mode, FileAccess.ReadWrite);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the specified file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path of the file to open.</param>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <param name="access">The access permissions for the created stream.</param>
|
|
||||||
/// <returns>The new stream.</returns>
|
|
||||||
public abstract SparseStream OpenFile(string path, FileMode mode, FileAccess access);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the attributes of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to inspect.</param>
|
|
||||||
/// <returns>The attributes of the file or directory.</returns>
|
|
||||||
public abstract FileAttributes GetAttributes(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the attributes of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to change.</param>
|
|
||||||
/// <param name="newValue">The new attributes of the file or directory.</param>
|
|
||||||
public abstract void SetAttributes(string path, FileAttributes newValue);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the creation time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The creation time.</returns>
|
|
||||||
public virtual DateTime GetCreationTime(string path)
|
|
||||||
{
|
|
||||||
return GetCreationTimeUtc(path).ToLocalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the creation time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public virtual void SetCreationTime(string path, DateTime newTime)
|
|
||||||
{
|
|
||||||
SetCreationTimeUtc(path, newTime.ToUniversalTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the creation time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The creation time.</returns>
|
|
||||||
public abstract DateTime GetCreationTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the creation time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public abstract void SetCreationTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last access time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last access time.</returns>
|
|
||||||
public virtual DateTime GetLastAccessTime(string path)
|
|
||||||
{
|
|
||||||
return GetLastAccessTimeUtc(path).ToLocalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last access time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public virtual void SetLastAccessTime(string path, DateTime newTime)
|
|
||||||
{
|
|
||||||
SetLastAccessTimeUtc(path, newTime.ToUniversalTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last access time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last access time.</returns>
|
|
||||||
public abstract DateTime GetLastAccessTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last access time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public abstract void SetLastAccessTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last modification time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last write time.</returns>
|
|
||||||
public virtual DateTime GetLastWriteTime(string path)
|
|
||||||
{
|
|
||||||
return GetLastWriteTimeUtc(path).ToLocalTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last modification time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public virtual void SetLastWriteTime(string path, DateTime newTime)
|
|
||||||
{
|
|
||||||
SetLastWriteTimeUtc(path, newTime.ToUniversalTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last modification time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last write time.</returns>
|
|
||||||
public abstract DateTime GetLastWriteTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last modification time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
public abstract void SetLastWriteTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to the file.</param>
|
|
||||||
/// <returns>The length in bytes.</returns>
|
|
||||||
public abstract long GetFileLength(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The file does not need to exist.</remarks>
|
|
||||||
public virtual DiscFileInfo GetFileInfo(string path)
|
|
||||||
{
|
|
||||||
return new DiscFileInfo(this, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The directory path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The directory does not need to exist.</remarks>
|
|
||||||
public virtual DiscDirectoryInfo GetDirectoryInfo(string path)
|
|
||||||
{
|
|
||||||
return new DiscDirectoryInfo(this, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible file system object (file or directory).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file system path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The file system object does not need to exist.</remarks>
|
|
||||||
public virtual DiscFileSystemInfo GetFileSystemInfo(string path)
|
|
||||||
{
|
|
||||||
return new DiscFileSystemInfo(this, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads the boot code of the file system into a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The boot code, or <c>null</c> if not available.</returns>
|
|
||||||
public virtual byte[] ReadBootCode()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable Members
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of this instance, releasing all resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes of this instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">The value <c>true</c> if Disposing.</param>
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flags for the amount of detail to include in a report.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum ReportLevels
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Report no information.
|
|
||||||
/// </summary>
|
|
||||||
None = 0x00,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Report informational level items.
|
|
||||||
/// </summary>
|
|
||||||
Information = 0x01,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Report warning level items.
|
|
||||||
/// </summary>
|
|
||||||
Warnings = 0x02,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Report error level items.
|
|
||||||
/// </summary>
|
|
||||||
Errors = 0x04,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Report all items.
|
|
||||||
/// </summary>
|
|
||||||
All = 0x07
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for objects that validate file system integrity.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Instances of this class do not offer the ability to fix/correct
|
|
||||||
/// file system issues, just to perform a limited number of checks on
|
|
||||||
/// integrity of the file system.</remarks>
|
|
||||||
public abstract class DiscFileSystemChecker
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Checks the integrity of a file system held in a stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reportOutput">A report on issues found.</param>
|
|
||||||
/// <param name="levels">The amount of detail to report.</param>
|
|
||||||
/// <returns><c>true</c> if the file system appears valid, else <c>false</c>.</returns>
|
|
||||||
public abstract bool Check(TextWriter reportOutput, ReportLevels levels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides the base class for both <see cref="DiscFileInfo"/> and <see cref="DiscDirectoryInfo"/> objects.
|
|
||||||
/// </summary>
|
|
||||||
public class DiscFileSystemInfo
|
|
||||||
{
|
|
||||||
private DiscFileSystem _fileSystem;
|
|
||||||
private string _path;
|
|
||||||
|
|
||||||
internal DiscFileSystemInfo(DiscFileSystem fileSystem, string path)
|
|
||||||
{
|
|
||||||
if (path == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("path");
|
|
||||||
}
|
|
||||||
|
|
||||||
_fileSystem = fileSystem;
|
|
||||||
_path = path.Trim('\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the file system the referenced file or directory exists on.
|
|
||||||
/// </summary>
|
|
||||||
public DiscFileSystem FileSystem
|
|
||||||
{
|
|
||||||
get { return _fileSystem; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the file or directory.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string Name
|
|
||||||
{
|
|
||||||
get { return Utilities.GetFileFromPath(_path); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the full path of the file or directory.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string FullName
|
|
||||||
{
|
|
||||||
get { return _path; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the extension part of the file or directory name.
|
|
||||||
/// </summary>
|
|
||||||
public virtual string Extension
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string name = Name;
|
|
||||||
int sepIdx = name.LastIndexOf('.');
|
|
||||||
if (sepIdx >= 0)
|
|
||||||
{
|
|
||||||
return name.Substring(sepIdx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the <see cref="System.IO.FileAttributes"/> of the current <see cref="DiscFileSystemInfo"/> object.
|
|
||||||
/// </summary>
|
|
||||||
public virtual FileAttributes Attributes
|
|
||||||
{
|
|
||||||
get { return FileSystem.GetAttributes(_path); }
|
|
||||||
set { FileSystem.SetAttributes(_path, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the <see cref="DiscDirectoryInfo"/> of the directory containing the current <see cref="DiscFileSystemInfo"/> object.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DiscDirectoryInfo Parent
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_path))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DiscDirectoryInfo(FileSystem, Utilities.GetDirectoryFromPath(_path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file system object exists.
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool Exists
|
|
||||||
{
|
|
||||||
get { return FileSystem.Exists(_path); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the creation time (in local time) of the current <see cref="DiscFileSystemInfo"/> object.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DateTime CreationTime
|
|
||||||
{
|
|
||||||
get { return CreationTimeUtc.ToLocalTime(); }
|
|
||||||
set { CreationTimeUtc = value.ToUniversalTime(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the creation time (in UTC) of the current <see cref="DiscFileSystemInfo"/> object.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DateTime CreationTimeUtc
|
|
||||||
{
|
|
||||||
get { return FileSystem.GetCreationTimeUtc(_path); }
|
|
||||||
set { FileSystem.SetCreationTimeUtc(_path, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the last time (in local time) the file or directory was accessed.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Read-only file systems will never update this value, it will remain at a fixed value.</remarks>
|
|
||||||
public virtual DateTime LastAccessTime
|
|
||||||
{
|
|
||||||
get { return LastAccessTimeUtc.ToLocalTime(); }
|
|
||||||
set { LastAccessTimeUtc = value.ToUniversalTime(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the last time (in UTC) the file or directory was accessed.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Read-only file systems will never update this value, it will remain at a fixed value.</remarks>
|
|
||||||
public virtual DateTime LastAccessTimeUtc
|
|
||||||
{
|
|
||||||
get { return FileSystem.GetLastAccessTimeUtc(_path); }
|
|
||||||
set { FileSystem.SetLastAccessTimeUtc(_path, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the last time (in local time) the file or directory was written to.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DateTime LastWriteTime
|
|
||||||
{
|
|
||||||
get { return LastWriteTimeUtc.ToLocalTime(); }
|
|
||||||
set { LastWriteTimeUtc = value.ToUniversalTime(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the last time (in UTC) the file or directory was written to.
|
|
||||||
/// </summary>
|
|
||||||
public virtual DateTime LastWriteTimeUtc
|
|
||||||
{
|
|
||||||
get { return FileSystem.GetLastWriteTimeUtc(_path); }
|
|
||||||
set { FileSystem.SetLastWriteTimeUtc(_path, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the path to the referenced file.
|
|
||||||
/// </summary>
|
|
||||||
protected string Path
|
|
||||||
{
|
|
||||||
get { return _path; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
public virtual void Delete()
|
|
||||||
{
|
|
||||||
if ((Attributes & FileAttributes.Directory) != 0)
|
|
||||||
{
|
|
||||||
FileSystem.DeleteDirectory(_path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FileSystem.DeleteFile(_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if <paramref name="obj"/> is equivalent to this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to compare.</param>
|
|
||||||
/// <returns><c>true</c> if <paramref name="obj"/> is equivalent, else <c>false</c>.</returns>
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
DiscFileSystemInfo asInfo = obj as DiscFileSystemInfo;
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Compare(Path, asInfo.Path, StringComparison.Ordinal) == 0 && DiscFileSystem.Equals(FileSystem, asInfo.FileSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the hash code for this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The hash code.</returns>
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _path.GetHashCode() ^ _fileSystem.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Common file system options.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Not all options are honoured by all file systems.</remarks>
|
|
||||||
public class DiscFileSystemOptions
|
|
||||||
{
|
|
||||||
private Random _rng;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the DiscFileSystemOptions class.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>You shouldn't normally create a new instance. File systems will provide
|
|
||||||
/// an instance of the correct derived type.</remarks>
|
|
||||||
public DiscFileSystemOptions()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the random number generator the file system should use.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This option is normally <c>null</c>, which is fine for most purposes.
|
|
||||||
/// Use this option when you need to finely control the filesystem for
|
|
||||||
/// reproducibility of behaviour (for example in a test harness).</remarks>
|
|
||||||
public Random RandomNumberGenerator
|
|
||||||
{
|
|
||||||
get { return _rng; }
|
|
||||||
set { _rng = value; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for all disk image builders.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class DiskImageBuilder
|
|
||||||
{
|
|
||||||
private static Dictionary<string, VirtualDiskFactory> s_typeMap;
|
|
||||||
|
|
||||||
private SparseStream _content;
|
|
||||||
private Geometry _geometry;
|
|
||||||
private Geometry _biosGeometry;
|
|
||||||
private GenericDiskAdapterType _adaptorType;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the content for this disk, implying the size of the disk.
|
|
||||||
/// </summary>
|
|
||||||
public SparseStream Content
|
|
||||||
{
|
|
||||||
get { return _content; }
|
|
||||||
set { _content = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the geometry of this disk, will be implied from the content stream if not set.
|
|
||||||
/// </summary>
|
|
||||||
public Geometry Geometry
|
|
||||||
{
|
|
||||||
get { return _geometry; }
|
|
||||||
set { _geometry = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the geometry of this disk, as reported by the BIOS, will be implied from the content stream if not set.
|
|
||||||
/// </summary>
|
|
||||||
public Geometry BiosGeometry
|
|
||||||
{
|
|
||||||
get { return _biosGeometry; }
|
|
||||||
set { _biosGeometry = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the adapter type for created virtual disk, for file formats that encode this information.
|
|
||||||
/// </summary>
|
|
||||||
public virtual GenericDiskAdapterType GenericAdapterType
|
|
||||||
{
|
|
||||||
get { return _adaptorType; }
|
|
||||||
set { _adaptorType = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this file format preserves BIOS geometry information.
|
|
||||||
/// </summary>
|
|
||||||
public virtual bool PreservesBiosGeometry
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, VirtualDiskFactory> TypeMap
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (s_typeMap == null)
|
|
||||||
{
|
|
||||||
InitializeMaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_typeMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an instance that constructs the specified type (and variant) of virtual disk image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The type of image to build (VHD, VMDK, etc).</param>
|
|
||||||
/// <param name="variant">The variant type (differencing/dynamic, fixed/static, etc).</param>
|
|
||||||
/// <returns>The builder instance.</returns>
|
|
||||||
public static DiskImageBuilder GetBuilder(string type, string variant)
|
|
||||||
{
|
|
||||||
VirtualDiskFactory factory;
|
|
||||||
if (!TypeMap.TryGetValue(type, out factory))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unknown disk type '{0}'", type), "type");
|
|
||||||
}
|
|
||||||
|
|
||||||
return factory.GetImageBuilder(variant);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initiates the construction of the disk image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="baseName">The base name for the disk images.</param>
|
|
||||||
/// <returns>A set of one or more logical files that constitute the
|
|
||||||
/// disk image. The first file is the 'primary' file that is normally attached to VMs.</returns>
|
|
||||||
/// <remarks>The supplied <c>baseName</c> is the start of the file name, with no file
|
|
||||||
/// extension. The set of file specifications will indicate the actual name corresponding
|
|
||||||
/// to each logical file that comprises the disk image. For example, given a base name
|
|
||||||
/// 'foo', the files 'foo.vmdk' and 'foo-flat.vmdk' could be returned.</remarks>
|
|
||||||
public abstract DiskImageFileSpecification[] Build(string baseName);
|
|
||||||
|
|
||||||
private static void InitializeMaps()
|
|
||||||
{
|
|
||||||
Dictionary<string, VirtualDiskFactory> typeMap = new Dictionary<string, VirtualDiskFactory>();
|
|
||||||
|
|
||||||
foreach (var type in typeof(VirtualDisk).Assembly.GetTypes())
|
|
||||||
{
|
|
||||||
VirtualDiskFactoryAttribute attr = (VirtualDiskFactoryAttribute)Attribute.GetCustomAttribute(type, typeof(VirtualDiskFactoryAttribute), false);
|
|
||||||
if (attr != null)
|
|
||||||
{
|
|
||||||
VirtualDiskFactory factory = (VirtualDiskFactory)Activator.CreateInstance(type);
|
|
||||||
typeMap.Add(attr.Type, factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s_typeMap = typeMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Describes a particular file that is a constituent part of a virtual disk.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class DiskImageFileSpecification
|
|
||||||
{
|
|
||||||
private string _name;
|
|
||||||
private StreamBuilder _builder;
|
|
||||||
|
|
||||||
internal DiskImageFileSpecification(string name, StreamBuilder builder)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
_builder = builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets name of the file.
|
|
||||||
/// </summary>
|
|
||||||
public string Name
|
|
||||||
{
|
|
||||||
get { return _name; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the object that provides access to the file's content.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A stream object that contains the file's content.</returns>
|
|
||||||
public SparseStream OpenStream()
|
|
||||||
{
|
|
||||||
return _builder.Build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal abstract class FileLocator
|
|
||||||
{
|
|
||||||
public abstract bool Exists(string fileName);
|
|
||||||
|
|
||||||
public abstract Stream Open(string fileName, FileMode mode, FileAccess access, FileShare share);
|
|
||||||
|
|
||||||
public abstract FileLocator GetRelativeLocator(string path);
|
|
||||||
|
|
||||||
public abstract string GetFullPath(string path);
|
|
||||||
|
|
||||||
public abstract string GetDirectoryFromPath(string path);
|
|
||||||
|
|
||||||
public abstract string GetFileFromPath(string path);
|
|
||||||
|
|
||||||
public abstract DateTime GetLastWriteTimeUtc(string path);
|
|
||||||
|
|
||||||
public abstract bool HasCommonRoot(FileLocator other);
|
|
||||||
|
|
||||||
public abstract string ResolveRelativePath(string path);
|
|
||||||
|
|
||||||
internal string MakeRelativePath(FileLocator fileLocator, string path)
|
|
||||||
{
|
|
||||||
if (!HasCommonRoot(fileLocator))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string ourFullPath = GetFullPath(string.Empty) + @"\";
|
|
||||||
string otherFullPath = fileLocator.GetFullPath(path);
|
|
||||||
|
|
||||||
return Utilities.MakeRelativePath(otherFullPath, ourFullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Base class holding information about a file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// File system implementations derive from this class, to provide information about the file system.
|
|
||||||
/// </remarks>
|
|
||||||
public abstract class FileSystemInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the file system.
|
|
||||||
/// </summary>
|
|
||||||
public abstract string Name { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a one-line description of the file system.
|
|
||||||
/// </summary>
|
|
||||||
public abstract string Description { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens a volume using the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="volume">The volume to access.</param>
|
|
||||||
/// <returns>A file system instance.</returns>
|
|
||||||
public DiscFileSystem Open(VolumeInfo volume)
|
|
||||||
{
|
|
||||||
return Open(volume, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens a stream using the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream to access.</param>
|
|
||||||
/// <returns>A file system instance.</returns>
|
|
||||||
public DiscFileSystem Open(Stream stream)
|
|
||||||
{
|
|
||||||
return Open(stream, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens a volume using the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="volume">The volume to access.</param>
|
|
||||||
/// <param name="parameters">Parameters for the file system.</param>
|
|
||||||
/// <returns>A file system instance.</returns>
|
|
||||||
public abstract DiscFileSystem Open(VolumeInfo volume, FileSystemParameters parameters);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens a stream using the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The stream to access.</param>
|
|
||||||
/// <param name="parameters">Parameters for the file system.</param>
|
|
||||||
/// <returns>A file system instance.</returns>
|
|
||||||
public abstract DiscFileSystem Open(Stream stream, FileSystemParameters parameters);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the name of the file system.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The file system name.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a time to/from UTC.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">The time to convert.</param>
|
|
||||||
/// <param name="toUtc"><c>true</c> to convert FAT time to UTC, <c>false</c> to convert UTC to FAT time.</param>
|
|
||||||
/// <returns>The converted time.</returns>
|
|
||||||
public delegate DateTime TimeConverter(DateTime time, bool toUtc);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Class with generic file system parameters.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Note - not all parameters apply to all types of file system.</remarks>
|
|
||||||
public sealed class FileSystemParameters
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the character encoding for file names, or <c>null</c> for default.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Some file systems, such as FAT, don't specify a particular character set for
|
|
||||||
/// file names. This parameter determines the character set that will be used for such
|
|
||||||
/// file systems.</remarks>
|
|
||||||
public Encoding FileNameEncoding { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the algorithm to convert file system time to UTC.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Some file system, such as FAT, don't have a defined way to convert from file system
|
|
||||||
/// time (local time where the file system is authored) to UTC time. This parameter determines
|
|
||||||
/// the algorithm to use.</remarks>
|
|
||||||
public TimeConverter TimeConverter { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The supported Floppy Disk logical formats.
|
|
||||||
/// </summary>
|
|
||||||
public enum FloppyDiskType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 720KiB capacity disk.
|
|
||||||
/// </summary>
|
|
||||||
DoubleDensity = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1440KiB capacity disk.
|
|
||||||
/// </summary>
|
|
||||||
HighDensity = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 2880KiB capacity disk.
|
|
||||||
/// </summary>
|
|
||||||
Extended = 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,497 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Class whose instances represent disk geometries.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Instances of this class are immutable.</remarks>
|
|
||||||
public sealed class Geometry
|
|
||||||
{
|
|
||||||
private int _cylinders;
|
|
||||||
private int _headsPerCylinder;
|
|
||||||
private int _sectorsPerTrack;
|
|
||||||
private int _bytesPerSector;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the Geometry class. The default 512 bytes per sector is assumed.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cylinders">The number of cylinders of the disk.</param>
|
|
||||||
/// <param name="headsPerCylinder">The number of heads (aka platters) of the disk.</param>
|
|
||||||
/// <param name="sectorsPerTrack">The number of sectors per track/cylinder of the disk.</param>
|
|
||||||
public Geometry(int cylinders, int headsPerCylinder, int sectorsPerTrack)
|
|
||||||
{
|
|
||||||
_cylinders = cylinders;
|
|
||||||
_headsPerCylinder = headsPerCylinder;
|
|
||||||
_sectorsPerTrack = sectorsPerTrack;
|
|
||||||
_bytesPerSector = 512;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the Geometry class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cylinders">The number of cylinders of the disk.</param>
|
|
||||||
/// <param name="headsPerCylinder">The number of heads (aka platters) of the disk.</param>
|
|
||||||
/// <param name="sectorsPerTrack">The number of sectors per track/cylinder of the disk.</param>
|
|
||||||
/// <param name="bytesPerSector">The number of bytes per sector of the disk.</param>
|
|
||||||
public Geometry(int cylinders, int headsPerCylinder, int sectorsPerTrack, int bytesPerSector)
|
|
||||||
{
|
|
||||||
_cylinders = cylinders;
|
|
||||||
_headsPerCylinder = headsPerCylinder;
|
|
||||||
_sectorsPerTrack = sectorsPerTrack;
|
|
||||||
_bytesPerSector = bytesPerSector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the Geometry class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The total capacity of the disk.</param>
|
|
||||||
/// <param name="headsPerCylinder">The number of heads (aka platters) of the disk.</param>
|
|
||||||
/// <param name="sectorsPerTrack">The number of sectors per track/cylinder of the disk.</param>
|
|
||||||
/// <param name="bytesPerSector">The number of bytes per sector of the disk.</param>
|
|
||||||
public Geometry(long capacity, int headsPerCylinder, int sectorsPerTrack, int bytesPerSector)
|
|
||||||
{
|
|
||||||
_cylinders = (int)(capacity / (headsPerCylinder * (long)sectorsPerTrack * bytesPerSector));
|
|
||||||
_headsPerCylinder = headsPerCylinder;
|
|
||||||
_sectorsPerTrack = sectorsPerTrack;
|
|
||||||
_bytesPerSector = bytesPerSector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a null geometry, which has 512-byte sectors but zero sectors, tracks or cylinders.
|
|
||||||
/// </summary>
|
|
||||||
public static Geometry Null
|
|
||||||
{
|
|
||||||
get { return new Geometry(0, 0, 0, 512); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of cylinders.
|
|
||||||
/// </summary>
|
|
||||||
public int Cylinders
|
|
||||||
{
|
|
||||||
get { return _cylinders; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of heads (aka platters).
|
|
||||||
/// </summary>
|
|
||||||
public int HeadsPerCylinder
|
|
||||||
{
|
|
||||||
get { return _headsPerCylinder; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of sectors per track.
|
|
||||||
/// </summary>
|
|
||||||
public int SectorsPerTrack
|
|
||||||
{
|
|
||||||
get { return _sectorsPerTrack; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of bytes in each sector.
|
|
||||||
/// </summary>
|
|
||||||
public int BytesPerSector
|
|
||||||
{
|
|
||||||
get { return _bytesPerSector; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total size of the disk (in sectors).
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Use TotalSectorsLong instead, to support very large disks.")]
|
|
||||||
public int TotalSectors
|
|
||||||
{
|
|
||||||
get { return Cylinders * HeadsPerCylinder * SectorsPerTrack; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total size of the disk (in sectors).
|
|
||||||
/// </summary>
|
|
||||||
public long TotalSectorsLong
|
|
||||||
{
|
|
||||||
get { return (long)Cylinders * (long)HeadsPerCylinder * (long)SectorsPerTrack; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total capacity of the disk (in bytes).
|
|
||||||
/// </summary>
|
|
||||||
public long Capacity
|
|
||||||
{
|
|
||||||
get { return TotalSectorsLong * (long)BytesPerSector; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the address of the last sector on the disk.
|
|
||||||
/// </summary>
|
|
||||||
public ChsAddress LastSector
|
|
||||||
{
|
|
||||||
get { return new ChsAddress(_cylinders - 1, _headsPerCylinder - 1, _sectorsPerTrack); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the Geometry is consistent with the values a BIOS can support.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsBiosSafe
|
|
||||||
{
|
|
||||||
get { return _cylinders <= 1024 && _headsPerCylinder <= 255 && _sectorsPerTrack <= 63; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the Geometry is consistent with the values IDE can represent.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsIdeSafe
|
|
||||||
{
|
|
||||||
get { return _cylinders <= 65536 && _headsPerCylinder <= 16 && _sectorsPerTrack <= 255; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the Geometry is representable both by the BIOS and by IDE.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsBiosAndIdeSafe
|
|
||||||
{
|
|
||||||
get { return _cylinders <= 1024 && _headsPerCylinder <= 16 && _sectorsPerTrack <= 63; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 'Large' BIOS geometry for a disk, given it's physical geometry.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ideGeometry">The physical (aka IDE) geometry of the disk.</param>
|
|
||||||
/// <returns>The geometry a BIOS using the 'Large' method for calculating disk geometry will indicate for the disk.</returns>
|
|
||||||
public static Geometry LargeBiosGeometry(Geometry ideGeometry)
|
|
||||||
{
|
|
||||||
int cylinders = ideGeometry.Cylinders;
|
|
||||||
int heads = ideGeometry.HeadsPerCylinder;
|
|
||||||
int sectors = ideGeometry.SectorsPerTrack;
|
|
||||||
|
|
||||||
while (cylinders > 1024 && heads <= 127)
|
|
||||||
{
|
|
||||||
cylinders >>= 1;
|
|
||||||
heads <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Geometry(cylinders, heads, sectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 'LBA Assisted' BIOS geometry for a disk, given it's capacity.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The capacity of the disk.</param>
|
|
||||||
/// <returns>The geometry a BIOS using the 'LBA Assisted' method for calculating disk geometry will indicate for the disk.</returns>
|
|
||||||
public static Geometry LbaAssistedBiosGeometry(long capacity)
|
|
||||||
{
|
|
||||||
int heads;
|
|
||||||
if (capacity <= 504 * Sizes.OneMiB)
|
|
||||||
{
|
|
||||||
heads = 16;
|
|
||||||
}
|
|
||||||
else if (capacity <= 1008 * Sizes.OneMiB)
|
|
||||||
{
|
|
||||||
heads = 32;
|
|
||||||
}
|
|
||||||
else if (capacity <= 2016 * Sizes.OneMiB)
|
|
||||||
{
|
|
||||||
heads = 64;
|
|
||||||
}
|
|
||||||
else if (capacity <= 4032 * Sizes.OneMiB)
|
|
||||||
{
|
|
||||||
heads = 128;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
heads = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sectors = 63;
|
|
||||||
int cylinders = (int)Math.Min(1024, capacity / (sectors * (long)heads * Sizes.Sector));
|
|
||||||
return new Geometry(cylinders, heads, sectors, Sizes.Sector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a geometry into one that is BIOS-safe, if not already.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="geometry">The geometry to make BIOS-safe.</param>
|
|
||||||
/// <param name="capacity">The capacity of the disk.</param>
|
|
||||||
/// <returns>The new geometry.</returns>
|
|
||||||
/// <remarks>This method returns the LBA-Assisted geometry if the given geometry isn't BIOS-safe.</remarks>
|
|
||||||
public static Geometry MakeBiosSafe(Geometry geometry, long capacity)
|
|
||||||
{
|
|
||||||
if (geometry == null)
|
|
||||||
{
|
|
||||||
return LbaAssistedBiosGeometry(capacity);
|
|
||||||
}
|
|
||||||
else if (geometry.IsBiosSafe)
|
|
||||||
{
|
|
||||||
return geometry;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return LbaAssistedBiosGeometry(capacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates a sensible disk geometry for a disk capacity using the VHD algorithm (errs under).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The desired capacity of the disk.</param>
|
|
||||||
/// <returns>The appropriate disk geometry.</returns>
|
|
||||||
/// <remarks>The geometry returned tends to produce a disk with less capacity
|
|
||||||
/// than requested (an exact capacity is not always possible). The geometry returned is the IDE
|
|
||||||
/// (aka Physical) geometry of the disk, not necessarily the geometry used by the BIOS.</remarks>
|
|
||||||
public static Geometry FromCapacity(long capacity)
|
|
||||||
{
|
|
||||||
return FromCapacity(capacity, Utilities.SectorSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates a sensible disk geometry for a disk capacity using the VHD algorithm (errs under).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The desired capacity of the disk.</param>
|
|
||||||
/// <param name="sectorSize">The logical sector size of the disk.</param>
|
|
||||||
/// <returns>The appropriate disk geometry.</returns>
|
|
||||||
/// <remarks>The geometry returned tends to produce a disk with less capacity
|
|
||||||
/// than requested (an exact capacity is not always possible). The geometry returned is the IDE
|
|
||||||
/// (aka Physical) geometry of the disk, not necessarily the geometry used by the BIOS.</remarks>
|
|
||||||
public static Geometry FromCapacity(long capacity, int sectorSize)
|
|
||||||
{
|
|
||||||
int totalSectors;
|
|
||||||
int cylinders;
|
|
||||||
int headsPerCylinder;
|
|
||||||
int sectorsPerTrack;
|
|
||||||
|
|
||||||
// If more than ~128GB truncate at ~128GB
|
|
||||||
if (capacity > 65535 * (long)16 * 255 * sectorSize)
|
|
||||||
{
|
|
||||||
totalSectors = 65535 * 16 * 255;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
totalSectors = (int)(capacity / sectorSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If more than ~32GB, break partition table compatibility.
|
|
||||||
// Partition table has max 63 sectors per track. Otherwise
|
|
||||||
// we're looking for a geometry that's valid for both BIOS
|
|
||||||
// and ATA.
|
|
||||||
if (totalSectors > 65535 * 16 * 63)
|
|
||||||
{
|
|
||||||
sectorsPerTrack = 255;
|
|
||||||
headsPerCylinder = 16;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sectorsPerTrack = 17;
|
|
||||||
int cylindersTimesHeads = totalSectors / sectorsPerTrack;
|
|
||||||
headsPerCylinder = (cylindersTimesHeads + 1023) / 1024;
|
|
||||||
|
|
||||||
if (headsPerCylinder < 4)
|
|
||||||
{
|
|
||||||
headsPerCylinder = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we need more than 1023 cylinders, or 16 heads, try more sectors per track
|
|
||||||
if (cylindersTimesHeads >= (headsPerCylinder * 1024U) || headsPerCylinder > 16)
|
|
||||||
{
|
|
||||||
sectorsPerTrack = 31;
|
|
||||||
headsPerCylinder = 16;
|
|
||||||
cylindersTimesHeads = totalSectors / sectorsPerTrack;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need 63 sectors per track to keep the cylinder count down
|
|
||||||
if (cylindersTimesHeads >= (headsPerCylinder * 1024U))
|
|
||||||
{
|
|
||||||
sectorsPerTrack = 63;
|
|
||||||
headsPerCylinder = 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cylinders = (totalSectors / sectorsPerTrack) / headsPerCylinder;
|
|
||||||
|
|
||||||
return new Geometry(cylinders, headsPerCylinder, sectorsPerTrack, sectorSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a CHS (Cylinder,Head,Sector) address to a LBA (Logical Block Address).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="chsAddress">The CHS address to convert.</param>
|
|
||||||
/// <returns>The Logical Block Address (in sectors).</returns>
|
|
||||||
public long ToLogicalBlockAddress(ChsAddress chsAddress)
|
|
||||||
{
|
|
||||||
return ToLogicalBlockAddress(chsAddress.Cylinder, chsAddress.Head, chsAddress.Sector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a CHS (Cylinder,Head,Sector) address to a LBA (Logical Block Address).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cylinder">The cylinder of the address.</param>
|
|
||||||
/// <param name="head">The head of the address.</param>
|
|
||||||
/// <param name="sector">The sector of the address.</param>
|
|
||||||
/// <returns>The Logical Block Address (in sectors).</returns>
|
|
||||||
public long ToLogicalBlockAddress(int cylinder, int head, int sector)
|
|
||||||
{
|
|
||||||
if (cylinder < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("cylinder", cylinder, "cylinder number is negative");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (head >= _headsPerCylinder)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("head", head, "head number is larger than disk geometry");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (head < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("head", head, "head number is negative");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sector > _sectorsPerTrack)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("sector", sector, "sector number is larger than disk geometry");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sector < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("sector", sector, "sector number is less than one (sectors are 1-based)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (((cylinder * (long)_headsPerCylinder) + head) * _sectorsPerTrack) + sector - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a LBA (Logical Block Address) to a CHS (Cylinder, Head, Sector) address.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logicalBlockAddress">The logical block address (in sectors).</param>
|
|
||||||
/// <returns>The address in CHS form.</returns>
|
|
||||||
public ChsAddress ToChsAddress(long logicalBlockAddress)
|
|
||||||
{
|
|
||||||
if (logicalBlockAddress < 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("logicalBlockAddress", logicalBlockAddress, "Logical Block Address is negative");
|
|
||||||
}
|
|
||||||
|
|
||||||
int cylinder = (int)(logicalBlockAddress / (_headsPerCylinder * _sectorsPerTrack));
|
|
||||||
int temp = (int)(logicalBlockAddress % (_headsPerCylinder * _sectorsPerTrack));
|
|
||||||
int head = temp / _sectorsPerTrack;
|
|
||||||
int sector = (temp % _sectorsPerTrack) + 1;
|
|
||||||
|
|
||||||
return new ChsAddress(cylinder, head, sector);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Translates an IDE (aka Physical) geometry to a BIOS (aka Logical) geometry.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="translation">The translation to perform.</param>
|
|
||||||
/// <returns>The translated disk geometry.</returns>
|
|
||||||
public Geometry TranslateToBios(GeometryTranslation translation)
|
|
||||||
{
|
|
||||||
return TranslateToBios(0, translation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Translates an IDE (aka Physical) geometry to a BIOS (aka Logical) geometry.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="capacity">The capacity of the disk, required if the geometry is an approximation on the actual disk size.</param>
|
|
||||||
/// <param name="translation">The translation to perform.</param>
|
|
||||||
/// <returns>The translated disk geometry.</returns>
|
|
||||||
public Geometry TranslateToBios(long capacity, GeometryTranslation translation)
|
|
||||||
{
|
|
||||||
if (capacity <= 0)
|
|
||||||
{
|
|
||||||
capacity = TotalSectorsLong * 512L;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (translation)
|
|
||||||
{
|
|
||||||
case GeometryTranslation.None:
|
|
||||||
return this;
|
|
||||||
|
|
||||||
case GeometryTranslation.Auto:
|
|
||||||
if (IsBiosSafe)
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Geometry.LbaAssistedBiosGeometry(capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
case GeometryTranslation.Lba:
|
|
||||||
return Geometry.LbaAssistedBiosGeometry(capacity);
|
|
||||||
|
|
||||||
case GeometryTranslation.Large:
|
|
||||||
return Geometry.LargeBiosGeometry(this);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Translation mode '{0}' not yet implemented", translation), "translation");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if this object is equivalent to another.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="obj">The object to test against.</param>
|
|
||||||
/// <returns><c>true</c> if the <paramref name="obj"/> is equivalent, else <c>false</c>.</returns>
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj == null || obj.GetType() != GetType())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Geometry other = (Geometry)obj;
|
|
||||||
|
|
||||||
return _cylinders == other._cylinders && _headsPerCylinder == other._headsPerCylinder
|
|
||||||
&& _sectorsPerTrack == other._sectorsPerTrack && _bytesPerSector == other._bytesPerSector;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the hash code for this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The hash code.</returns>
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _cylinders.GetHashCode() ^ _headsPerCylinder.GetHashCode()
|
|
||||||
^ _sectorsPerTrack.GetHashCode() ^ _bytesPerSector.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a string representation of this object, in the form (C/H/S).
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The string representation.</returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (_bytesPerSector == 512)
|
|
||||||
{
|
|
||||||
return "(" + _cylinders + "/" + _headsPerCylinder + "/" + _sectorsPerTrack + ")";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "(" + _cylinders + "/" + _headsPerCylinder + "/" + _sectorsPerTrack + ":" + _bytesPerSector + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Enumeration of standard BIOS disk geometry translation methods.
|
|
||||||
/// </summary>
|
|
||||||
public enum GeometryTranslation
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Apply no translation.
|
|
||||||
/// </summary>
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Automatic, based on the physical geometry select the most appropriate translation.
|
|
||||||
/// </summary>
|
|
||||||
Auto = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// LBA assisted translation, based on just the disk capacity.
|
|
||||||
/// </summary>
|
|
||||||
Lba = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Bit-shifting translation, based on the physical geometry of the disk.
|
|
||||||
/// </summary>
|
|
||||||
Large = 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface shared by all buffers.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Buffers are very similar to streams, except the buffer has no notion of
|
|
||||||
/// 'current position'. All I/O operations instead specify the position, as
|
|
||||||
/// needed. Buffers also support sparse behaviour.
|
|
||||||
/// </remarks>
|
|
||||||
public interface IBuffer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this buffer can be read.
|
|
||||||
/// </summary>
|
|
||||||
bool CanRead { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this buffer can be modified.
|
|
||||||
/// </summary>
|
|
||||||
bool CanWrite { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current capacity of the buffer, in bytes.
|
|
||||||
/// </summary>
|
|
||||||
long Capacity
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of the buffer that are stored.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This may be an empty enumeration if all bytes are zero.</remarks>
|
|
||||||
IEnumerable<StreamExtent> Extents
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads from the buffer into a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The offset within the buffer to start reading.</param>
|
|
||||||
/// <param name="buffer">The destination byte array.</param>
|
|
||||||
/// <param name="offset">The start offset within the destination buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to read.</param>
|
|
||||||
/// <returns>The actual number of bytes read.</returns>
|
|
||||||
int Read(long pos, byte[] buffer, int offset, int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a byte array into the buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The start offset within the buffer.</param>
|
|
||||||
/// <param name="buffer">The source byte array.</param>
|
|
||||||
/// <param name="offset">The start offset within the source byte array.</param>
|
|
||||||
/// <param name="count">The number of bytes to write.</param>
|
|
||||||
void Write(long pos, byte[] buffer, int offset, int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clears bytes from the buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pos">The start offset within the buffer.</param>
|
|
||||||
/// <param name="count">The number of bytes to clear.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>Logically equivalent to writing <c>count</c> null/zero bytes to the buffer, some
|
|
||||||
/// implementations determine that some (or all) of the range indicated is not actually
|
|
||||||
/// stored. There is no direct, automatic, correspondence to clearing bytes and them
|
|
||||||
/// not being represented as an 'extent' - for example, the implementation of the underlying
|
|
||||||
/// stream may not permit fine-grained extent storage.</para>
|
|
||||||
/// <para>It is always safe to call this method to 'zero-out' a section of a buffer, regardless of
|
|
||||||
/// the underlying buffer implementation.</para>
|
|
||||||
/// </remarks>
|
|
||||||
void Clear(long pos, int count);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Flushes all data to the underlying storage.
|
|
||||||
/// </summary>
|
|
||||||
void Flush();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the capacity of the buffer, truncating if appropriate.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The desired capacity of the buffer.</param>
|
|
||||||
void SetCapacity(long value);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parts of a buffer that are stored, within a specified range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="start">The offset of the first byte of interest.</param>
|
|
||||||
/// <param name="count">The number of bytes of interest.</param>
|
|
||||||
/// <returns>An enumeration of stream extents, indicating stored bytes.</returns>
|
|
||||||
IEnumerable<StreamExtent> GetExtentsInRange(long start, long count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Common interface for reading structures to/from byte arrays.
|
|
||||||
/// </summary>
|
|
||||||
internal interface IByteArraySerializable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total number of bytes the structure occupies.
|
|
||||||
/// </summary>
|
|
||||||
int Size { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads the structure from a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to read from.</param>
|
|
||||||
/// <param name="offset">The buffer offset to start reading from.</param>
|
|
||||||
/// <returns>The number of bytes read.</returns>
|
|
||||||
int ReadFrom(byte[] buffer, int offset);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a structure to a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">The buffer to write to.</param>
|
|
||||||
/// <param name="offset">The buffer offset to start writing at.</param>
|
|
||||||
void WriteTo(byte[] buffer, int offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for all file systems based on a cluster model.
|
|
||||||
/// </summary>
|
|
||||||
public interface IClusterBasedFileSystem : IFileSystem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the size (in bytes) of each cluster.
|
|
||||||
/// </summary>
|
|
||||||
long ClusterSize
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the total number of clusters managed by the file system.
|
|
||||||
/// </summary>
|
|
||||||
long TotalClusters
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a cluster (index) into an absolute byte position in the underlying stream.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cluster">The cluster to convert.</param>
|
|
||||||
/// <returns>The corresponding absolute byte position.</returns>
|
|
||||||
long ClusterToOffset(long cluster);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts an absolute byte position in the underlying stream to a cluster (index).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">The byte position to convert.</param>
|
|
||||||
/// <returns>The cluster containing the specified byte.</returns>
|
|
||||||
long OffsetToCluster(long offset);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a file name to the list of clusters occupied by the file's data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to inspect.</param>
|
|
||||||
/// <returns>The clusters.</returns>
|
|
||||||
/// <remarks>Note that in some file systems, small files may not have dedicated
|
|
||||||
/// clusters. Only dedicated clusters will be returned.</remarks>
|
|
||||||
Range<long, long>[] PathToClusters(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a file name to the extents containing its data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to inspect.</param>
|
|
||||||
/// <returns>The file extents, as absolute byte positions in the underlying stream.</returns>
|
|
||||||
/// <remarks>Use this method with caution - not all file systems will store all bytes
|
|
||||||
/// directly in extents. Files may be compressed, sparse or encrypted. This method
|
|
||||||
/// merely indicates where file data is stored, not what's stored.</remarks>
|
|
||||||
StreamExtent[] PathToExtents(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object that can convert between clusters and files.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The cluster map.</returns>
|
|
||||||
ClusterMap BuildClusterMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface exposed by objects that can provide a structured trace of their content.
|
|
||||||
/// </summary>
|
|
||||||
public interface IDiagnosticTraceable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Writes a diagnostic report about the state of the object to a writer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="writer">The writer to send the report to.</param>
|
|
||||||
/// <param name="linePrefix">The prefix to place at the start of each line.</param>
|
|
||||||
void Dump(TextWriter writer, string linePrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,354 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Common interface for all file systems.
|
|
||||||
/// </summary>
|
|
||||||
public interface IFileSystem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file system is read-only or read-write.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>true if the file system is read-write.</returns>
|
|
||||||
bool CanWrite { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the root directory of the file system.
|
|
||||||
/// </summary>
|
|
||||||
DiscDirectoryInfo Root
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether the file system is thread-safe.
|
|
||||||
/// </summary>
|
|
||||||
bool IsThreadSafe { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceFile">The source file.</param>
|
|
||||||
/// <param name="destinationFile">The destination file.</param>
|
|
||||||
void CopyFile(string sourceFile, string destinationFile);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies an existing file to a new file, allowing overwriting of an existing file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceFile">The source file.</param>
|
|
||||||
/// <param name="destinationFile">The destination file.</param>
|
|
||||||
/// <param name="overwrite">Whether to permit over-writing of an existing file.</param>
|
|
||||||
void CopyFile(string sourceFile, string destinationFile, bool overwrite);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the new directory.</param>
|
|
||||||
void CreateDirectory(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the directory to delete.</param>
|
|
||||||
void DeleteDirectory(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a directory, optionally with all descendants.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the directory to delete.</param>
|
|
||||||
/// <param name="recursive">Determines if the all descendants should be deleted.</param>
|
|
||||||
void DeleteDirectory(string path, bool recursive);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file to delete.</param>
|
|
||||||
void DeleteFile(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a directory exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the directory exists.</returns>
|
|
||||||
bool DirectoryExists(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a file exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the file exists.</returns>
|
|
||||||
bool FileExists(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates if a file or directory exists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to test.</param>
|
|
||||||
/// <returns>true if the file or directory exists.</returns>
|
|
||||||
bool Exists(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of directories.</returns>
|
|
||||||
string[] GetDirectories(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of directories matching the search pattern.</returns>
|
|
||||||
string[] GetDirectories(string path, string searchPattern);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern, using a value to determine whether to search subdirectories.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <param name="searchOption">Indicates whether to search subdirectories.</param>
|
|
||||||
/// <returns>Array of directories matching the search pattern.</returns>
|
|
||||||
string[] GetDirectories(string path, string searchPattern, SearchOption searchOption);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of files.</returns>
|
|
||||||
string[] GetFiles(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of files matching the search pattern.</returns>
|
|
||||||
string[] GetFiles(string path, string searchPattern);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files in a specified directory matching a specified
|
|
||||||
/// search pattern, using a value to determine whether to search subdirectories.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <param name="searchOption">Indicates whether to search subdirectories.</param>
|
|
||||||
/// <returns>Array of files matching the search pattern.</returns>
|
|
||||||
string[] GetFiles(string path, string searchPattern, SearchOption searchOption);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of all files and subdirectories in a specified directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <returns>Array of files and subdirectories matching the search pattern.</returns>
|
|
||||||
string[] GetFileSystemEntries(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of files and subdirectories in a specified directory matching a specified
|
|
||||||
/// search pattern.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to search.</param>
|
|
||||||
/// <param name="searchPattern">The search string to match against.</param>
|
|
||||||
/// <returns>Array of files and subdirectories matching the search pattern.</returns>
|
|
||||||
string[] GetFileSystemEntries(string path, string searchPattern);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceDirectoryName">The directory to move.</param>
|
|
||||||
/// <param name="destinationDirectoryName">The target directory name.</param>
|
|
||||||
void MoveDirectory(string sourceDirectoryName, string destinationDirectoryName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceName">The file to move.</param>
|
|
||||||
/// <param name="destinationName">The target file name.</param>
|
|
||||||
void MoveFile(string sourceName, string destinationName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Moves a file, allowing an existing file to be overwritten.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceName">The file to move.</param>
|
|
||||||
/// <param name="destinationName">The target file name.</param>
|
|
||||||
/// <param name="overwrite">Whether to permit a destination file to be overwritten.</param>
|
|
||||||
void MoveFile(string sourceName, string destinationName, bool overwrite);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the specified file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path of the file to open.</param>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <returns>The new stream.</returns>
|
|
||||||
SparseStream OpenFile(string path, FileMode mode);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the specified file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path of the file to open.</param>
|
|
||||||
/// <param name="mode">The file mode for the created stream.</param>
|
|
||||||
/// <param name="access">The access permissions for the created stream.</param>
|
|
||||||
/// <returns>The new stream.</returns>
|
|
||||||
SparseStream OpenFile(string path, FileMode mode, FileAccess access);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the attributes of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to inspect.</param>
|
|
||||||
/// <returns>The attributes of the file or directory.</returns>
|
|
||||||
FileAttributes GetAttributes(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the attributes of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to change.</param>
|
|
||||||
/// <param name="newValue">The new attributes of the file or directory.</param>
|
|
||||||
void SetAttributes(string path, FileAttributes newValue);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the creation time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The creation time.</returns>
|
|
||||||
DateTime GetCreationTime(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the creation time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetCreationTime(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the creation time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The creation time.</returns>
|
|
||||||
DateTime GetCreationTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the creation time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetCreationTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last access time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last access time.</returns>
|
|
||||||
DateTime GetLastAccessTime(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last access time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetLastAccessTime(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last access time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last access time.</returns>
|
|
||||||
DateTime GetLastAccessTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last access time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetLastAccessTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last modification time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last write time.</returns>
|
|
||||||
DateTime GetLastWriteTime(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last modification time (in local time) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetLastWriteTime(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last modification time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <returns>The last write time.</returns>
|
|
||||||
DateTime GetLastWriteTimeUtc(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the last modification time (in UTC) of a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path of the file or directory.</param>
|
|
||||||
/// <param name="newTime">The new time to set.</param>
|
|
||||||
void SetLastWriteTimeUtc(string path, DateTime newTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the length of a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to the file.</param>
|
|
||||||
/// <returns>The length in bytes.</returns>
|
|
||||||
long GetFileLength(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The file does not need to exist.</remarks>
|
|
||||||
DiscFileInfo GetFileInfo(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The directory path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The directory does not need to exist.</remarks>
|
|
||||||
DiscDirectoryInfo GetDirectoryInfo(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an object representing a possible file system object (file or directory).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file system path.</param>
|
|
||||||
/// <returns>The representing object.</returns>
|
|
||||||
/// <remarks>The file system object does not need to exist.</remarks>
|
|
||||||
DiscFileSystemInfo GetFileSystemInfo(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads the boot code of the file system into a byte array.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The boot code, or <c>null</c> if not available.</returns>
|
|
||||||
byte[] ReadBootCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System.Security.AccessControl;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides the base class for all file systems that support Windows semantics.
|
|
||||||
/// </summary>
|
|
||||||
public interface IWindowsFileSystem : IFileSystem
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the security descriptor associated with the file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to inspect.</param>
|
|
||||||
/// <returns>The security descriptor.</returns>
|
|
||||||
RawSecurityDescriptor GetSecurity(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the security descriptor associated with the file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file or directory to change.</param>
|
|
||||||
/// <param name="securityDescriptor">The new security descriptor.</param>
|
|
||||||
void SetSecurity(string path, RawSecurityDescriptor securityDescriptor);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the reparse point data associated with a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file to query.</param>
|
|
||||||
/// <returns>The reparse point information.</returns>
|
|
||||||
ReparsePoint GetReparsePoint(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the reparse point data on a file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file to set the reparse point on.</param>
|
|
||||||
/// <param name="reparsePoint">The new reparse point.</param>
|
|
||||||
void SetReparsePoint(string path, ReparsePoint reparsePoint);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a reparse point from a file or directory, without deleting the file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to the file or directory to remove the reparse point from.</param>
|
|
||||||
void RemoveReparsePoint(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the short name for a given path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to convert.</param>
|
|
||||||
/// <returns>The short name.</returns>
|
|
||||||
/// <remarks>
|
|
||||||
/// This method only gets the short name for the final part of the path, to
|
|
||||||
/// convert a complete path, call this method repeatedly, once for each path
|
|
||||||
/// segment. If there is no short name for the given path,<c>null</c> is
|
|
||||||
/// returned.
|
|
||||||
/// </remarks>
|
|
||||||
string GetShortName(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the short name for a given file or directory.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path to the file or directory to change.</param>
|
|
||||||
/// <param name="shortName">The shortName, which should not include a path.</param>
|
|
||||||
void SetShortName(string path, string shortName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the standard file information for a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path to the file or directory to query.</param>
|
|
||||||
/// <returns>The standard file information.</returns>
|
|
||||||
WindowsFileInformation GetFileStandardInformation(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the standard file information for a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The full path to the file or directory to query.</param>
|
|
||||||
/// <param name="info">The standard file information.</param>
|
|
||||||
void SetFileStandardInformation(string path, WindowsFileInformation info);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the names of the alternate data streams for a file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to the file.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// The list of alternate data streams (or empty, if none). To access the contents
|
|
||||||
/// of the alternate streams, use OpenFile(path + ":" + name, ...).
|
|
||||||
/// </returns>
|
|
||||||
string[] GetAlternateDataStreams(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the file id for a given path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to get the id of.</param>
|
|
||||||
/// <returns>The file id, or -1.</returns>
|
|
||||||
/// <remarks>
|
|
||||||
/// The returned file id uniquely identifies the file, and is shared by all hard
|
|
||||||
/// links to the same file. The value -1 indicates no unique identifier is
|
|
||||||
/// available, and so it can be assumed the file has no hard links.
|
|
||||||
/// </remarks>
|
|
||||||
long GetFileId(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates whether the file is known by other names.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The file to inspect.</param>
|
|
||||||
/// <returns><c>true</c> if the file has other names, else <c>false</c>.</returns>
|
|
||||||
bool HasHardLinks(string path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Exception thrown when some invalid file system data is found, indicating probably corruption.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class InvalidFileSystemException : IOException
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the InvalidFileSystemException class.
|
|
||||||
/// </summary>
|
|
||||||
public InvalidFileSystemException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the InvalidFileSystemException class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The exception message.</param>
|
|
||||||
public InvalidFileSystemException(string message)
|
|
||||||
: base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the InvalidFileSystemException class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The exception message.</param>
|
|
||||||
/// <param name="innerException">The inner exception.</param>
|
|
||||||
public InvalidFileSystemException(string message, Exception innerException)
|
|
||||||
: base(message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the InvalidFileSystemException class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="info">The serialization info.</param>
|
|
||||||
/// <param name="context">The streaming context.</param>
|
|
||||||
protected InvalidFileSystemException(SerializationInfo info, StreamingContext context)
|
|
||||||
: base(info, context)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
internal sealed class ComponentRecord : DatabaseRecord
|
|
||||||
{
|
|
||||||
public string StatusString;
|
|
||||||
public ExtentMergeType MergeType; // (02 Spanned, Simple, Mirrored) (01 on striped)
|
|
||||||
public uint Unknown1; // Zero
|
|
||||||
public ulong NumExtents; // Could be num disks
|
|
||||||
public uint Unknown2; // Zero
|
|
||||||
public uint LinkId; // Identical on mirrors
|
|
||||||
public ulong Unknown3; // 00 .. 00
|
|
||||||
public ulong VolumeId;
|
|
||||||
public ulong Unknown4; // ??
|
|
||||||
public long StripeSizeSectors;
|
|
||||||
public long StripeStride; // aka num partitions
|
|
||||||
|
|
||||||
protected override void DoReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
base.DoReadFrom(buffer, offset);
|
|
||||||
|
|
||||||
int pos = offset + 0x18;
|
|
||||||
|
|
||||||
Id = ReadVarULong(buffer, ref pos);
|
|
||||||
Name = ReadVarString(buffer, ref pos);
|
|
||||||
StatusString = ReadVarString(buffer, ref pos);
|
|
||||||
MergeType = (ExtentMergeType)ReadByte(buffer, ref pos);
|
|
||||||
Unknown1 = ReadUInt(buffer, ref pos); // Zero
|
|
||||||
NumExtents = ReadVarULong(buffer, ref pos);
|
|
||||||
Unknown2 = ReadUInt(buffer, ref pos);
|
|
||||||
LinkId = ReadUInt(buffer, ref pos);
|
|
||||||
Unknown3 = ReadULong(buffer, ref pos); // Zero
|
|
||||||
VolumeId = ReadVarULong(buffer, ref pos);
|
|
||||||
Unknown4 = ReadVarULong(buffer, ref pos); // Zero
|
|
||||||
|
|
||||||
if ((Flags & 0x1000) != 0)
|
|
||||||
{
|
|
||||||
StripeSizeSectors = ReadVarLong(buffer, ref pos);
|
|
||||||
StripeStride = ReadVarLong(buffer, ref pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
internal class Database
|
|
||||||
{
|
|
||||||
private DatabaseHeader _vmdb;
|
|
||||||
private Dictionary<ulong, DatabaseRecord> _records;
|
|
||||||
|
|
||||||
public Database(Stream stream)
|
|
||||||
{
|
|
||||||
long dbStart = stream.Position;
|
|
||||||
|
|
||||||
byte[] buffer = new byte[Sizes.Sector];
|
|
||||||
stream.Read(buffer, 0, buffer.Length);
|
|
||||||
_vmdb = new DatabaseHeader();
|
|
||||||
_vmdb.ReadFrom(buffer, 0);
|
|
||||||
|
|
||||||
stream.Position = dbStart + _vmdb.HeaderSize;
|
|
||||||
|
|
||||||
buffer = Utilities.ReadFully(stream, (int)(_vmdb.BlockSize * _vmdb.NumVBlks));
|
|
||||||
|
|
||||||
_records = new Dictionary<ulong, DatabaseRecord>();
|
|
||||||
for (int i = 0; i < _vmdb.NumVBlks; ++i)
|
|
||||||
{
|
|
||||||
DatabaseRecord rec = DatabaseRecord.ReadFrom(buffer, (int)(i * _vmdb.BlockSize));
|
|
||||||
if (rec != null)
|
|
||||||
{
|
|
||||||
_records.Add(rec.Id, rec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<DiskRecord> Disks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.Disk)
|
|
||||||
{
|
|
||||||
yield return (DiskRecord)record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<VolumeRecord> Volumes
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.Volume)
|
|
||||||
{
|
|
||||||
yield return (VolumeRecord)record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal DiskGroupRecord GetDiskGroup(Guid guid)
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.DiskGroup)
|
|
||||||
{
|
|
||||||
DiskGroupRecord dgRecord = (DiskGroupRecord)record;
|
|
||||||
if (new Guid(dgRecord.GroupGuidString) == guid || guid == Guid.Empty)
|
|
||||||
{
|
|
||||||
return dgRecord;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<ComponentRecord> GetVolumeComponents(ulong volumeId)
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.Component)
|
|
||||||
{
|
|
||||||
ComponentRecord cmpntRecord = (ComponentRecord)record;
|
|
||||||
if (cmpntRecord.VolumeId == volumeId)
|
|
||||||
{
|
|
||||||
yield return cmpntRecord;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<ExtentRecord> GetComponentExtents(ulong componentId)
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.Extent)
|
|
||||||
{
|
|
||||||
ExtentRecord extentRecord = (ExtentRecord)record;
|
|
||||||
if (extentRecord.ComponentId == componentId)
|
|
||||||
{
|
|
||||||
yield return extentRecord;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal DiskRecord GetDisk(ulong diskId)
|
|
||||||
{
|
|
||||||
return (DiskRecord)_records[diskId];
|
|
||||||
}
|
|
||||||
|
|
||||||
internal VolumeRecord GetVolume(ulong volumeId)
|
|
||||||
{
|
|
||||||
return (VolumeRecord)_records[volumeId];
|
|
||||||
}
|
|
||||||
|
|
||||||
internal VolumeRecord GetVolume(Guid id)
|
|
||||||
{
|
|
||||||
return FindRecord<VolumeRecord>(r => (r.VolumeGuid == id), RecordType.Volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IEnumerable<VolumeRecord> GetVolumes()
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == RecordType.Volume)
|
|
||||||
{
|
|
||||||
yield return (VolumeRecord)record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal T FindRecord<T>(Predicate<T> pred, RecordType typeId)
|
|
||||||
where T : DatabaseRecord
|
|
||||||
{
|
|
||||||
foreach (var record in _records.Values)
|
|
||||||
{
|
|
||||||
if (record.RecordType == typeId)
|
|
||||||
{
|
|
||||||
T t = (T)record;
|
|
||||||
if (pred(t))
|
|
||||||
{
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal class DatabaseHeader
|
|
||||||
{
|
|
||||||
public string Signature; // VMDB
|
|
||||||
public uint NumVBlks; // 00 00 17 24
|
|
||||||
public uint BlockSize; // 00 00 00 80
|
|
||||||
public uint HeaderSize; // 00 00 02 00
|
|
||||||
public ushort Unknown1; // 00 01
|
|
||||||
public ushort VersionNum; // 00 04
|
|
||||||
public ushort VersionDenom; // 00 0a
|
|
||||||
public string GroupName;
|
|
||||||
public string DiskGroupId;
|
|
||||||
public long CommittedSequence; // 0xA
|
|
||||||
public long PendingSequence; // 0xA
|
|
||||||
public uint Unknown2; // 1
|
|
||||||
public uint Unknown3; // 1
|
|
||||||
public uint Unknown4; // 3
|
|
||||||
public uint Unknown5; // 3
|
|
||||||
public long Unknown6; // 0
|
|
||||||
public long Unknown7; // 1
|
|
||||||
public uint Unknown8; // 1
|
|
||||||
public uint Unknown9; // 3
|
|
||||||
public uint UnknownA; // 3
|
|
||||||
public long UnknownB; // 0
|
|
||||||
public uint UnknownC; // 0
|
|
||||||
public DateTime Timestamp;
|
|
||||||
|
|
||||||
public void ReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
Signature = Utilities.BytesToString(buffer, offset + 0x00, 4);
|
|
||||||
NumVBlks = Utilities.ToUInt32BigEndian(buffer, offset + 0x04);
|
|
||||||
BlockSize = Utilities.ToUInt32BigEndian(buffer, offset + 0x08);
|
|
||||||
HeaderSize = Utilities.ToUInt32BigEndian(buffer, offset + 0x0C);
|
|
||||||
Unknown1 = Utilities.ToUInt16BigEndian(buffer, offset + 0x10);
|
|
||||||
VersionNum = Utilities.ToUInt16BigEndian(buffer, offset + 0x12);
|
|
||||||
VersionDenom = Utilities.ToUInt16BigEndian(buffer, offset + 0x14);
|
|
||||||
GroupName = Utilities.BytesToString(buffer, offset + 0x16, 31).Trim('\0');
|
|
||||||
DiskGroupId = Utilities.BytesToString(buffer, offset + 0x35, 0x40).Trim('\0');
|
|
||||||
|
|
||||||
// May be wrong way round...
|
|
||||||
CommittedSequence = Utilities.ToInt64BigEndian(buffer, offset + 0x75);
|
|
||||||
PendingSequence = Utilities.ToInt64BigEndian(buffer, offset + 0x7D);
|
|
||||||
|
|
||||||
Unknown2 = Utilities.ToUInt32BigEndian(buffer, offset + 0x85);
|
|
||||||
Unknown3 = Utilities.ToUInt32BigEndian(buffer, offset + 0x89);
|
|
||||||
Unknown4 = Utilities.ToUInt32BigEndian(buffer, offset + 0x8D);
|
|
||||||
Unknown5 = Utilities.ToUInt32BigEndian(buffer, offset + 0x91);
|
|
||||||
Unknown6 = Utilities.ToInt64BigEndian(buffer, offset + 0x95);
|
|
||||||
Unknown7 = Utilities.ToInt64BigEndian(buffer, offset + 0x9D);
|
|
||||||
Unknown8 = Utilities.ToUInt32BigEndian(buffer, offset + 0xA5);
|
|
||||||
Unknown9 = Utilities.ToUInt32BigEndian(buffer, offset + 0xA9);
|
|
||||||
UnknownA = Utilities.ToUInt32BigEndian(buffer, offset + 0xAD);
|
|
||||||
|
|
||||||
UnknownB = Utilities.ToInt64BigEndian(buffer, offset + 0xB1);
|
|
||||||
UnknownC = Utilities.ToUInt32BigEndian(buffer, offset + 0xB9);
|
|
||||||
|
|
||||||
Timestamp = DateTime.FromFileTimeUtc(Utilities.ToInt64BigEndian(buffer, offset + 0xBD));
|
|
||||||
}
|
|
||||||
|
|
||||||
////private static int CalcChecksum()
|
|
||||||
////{
|
|
||||||
//// // Zero checksum bytes (0x08, 4)
|
|
||||||
//// // Add all byte values for ?? bytes
|
|
||||||
//// throw new NotImplementedException();
|
|
||||||
////}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal abstract class DatabaseRecord
|
|
||||||
{
|
|
||||||
public string Signature; // VBLK
|
|
||||||
public uint Label;
|
|
||||||
public uint Counter;
|
|
||||||
public uint Valid;
|
|
||||||
public uint Flags;
|
|
||||||
public RecordType RecordType;
|
|
||||||
public uint DataLength;
|
|
||||||
|
|
||||||
public ulong Id;
|
|
||||||
public string Name;
|
|
||||||
|
|
||||||
protected DatabaseRecord()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DatabaseRecord ReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
DatabaseRecord result = null;
|
|
||||||
|
|
||||||
if (Utilities.ToInt32BigEndian(buffer, offset + 0xC) != 0)
|
|
||||||
{
|
|
||||||
switch ((RecordType)(buffer[offset + 0x13] & 0xF))
|
|
||||||
{
|
|
||||||
case RecordType.Volume:
|
|
||||||
result = new VolumeRecord();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RecordType.Component:
|
|
||||||
result = new ComponentRecord();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RecordType.Extent:
|
|
||||||
result = new ExtentRecord();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RecordType.Disk:
|
|
||||||
result = new DiskRecord();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RecordType.DiskGroup:
|
|
||||||
result = new DiskGroupRecord();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException("Unrecognized record type: " + buffer[offset + 0x13]);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.DoReadFrom(buffer, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ulong ReadVarULong(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
int length = buffer[offset];
|
|
||||||
|
|
||||||
ulong result = 0;
|
|
||||||
for (int i = 0; i < length; ++i)
|
|
||||||
{
|
|
||||||
result = (result << 8) | buffer[offset + i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += length + 1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static long ReadVarLong(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
return (long)ReadVarULong(buffer, ref offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static string ReadVarString(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
int length = buffer[offset];
|
|
||||||
|
|
||||||
string result = Utilities.BytesToString(buffer, offset + 1, length);
|
|
||||||
offset += length + 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static byte ReadByte(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
return buffer[offset++];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static uint ReadUInt(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
offset += 4;
|
|
||||||
return Utilities.ToUInt32BigEndian(buffer, offset - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static long ReadLong(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
offset += 8;
|
|
||||||
return Utilities.ToInt64BigEndian(buffer, offset - 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ulong ReadULong(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
offset += 8;
|
|
||||||
return Utilities.ToUInt64BigEndian(buffer, offset - 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static string ReadString(byte[] buffer, int len, ref int offset)
|
|
||||||
{
|
|
||||||
offset += len;
|
|
||||||
return Utilities.BytesToString(buffer, offset - len, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Guid ReadBinaryGuid(byte[] buffer, ref int offset)
|
|
||||||
{
|
|
||||||
offset += 16;
|
|
||||||
return Utilities.ToGuidBigEndian(buffer, offset - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void DoReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
Signature = Utilities.BytesToString(buffer, offset + 0x00, 4);
|
|
||||||
Label = Utilities.ToUInt32BigEndian(buffer, offset + 0x04);
|
|
||||||
Counter = Utilities.ToUInt32BigEndian(buffer, offset + 0x08);
|
|
||||||
Valid = Utilities.ToUInt32BigEndian(buffer, offset + 0x0C);
|
|
||||||
Flags = Utilities.ToUInt32BigEndian(buffer, offset + 0x10);
|
|
||||||
RecordType = (RecordType)(Flags & 0xF);
|
|
||||||
DataLength = Utilities.ToUInt32BigEndian(buffer, 0x14);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
internal sealed class DiskGroupRecord : DatabaseRecord
|
|
||||||
{
|
|
||||||
public string GroupGuidString;
|
|
||||||
public uint Unknown1;
|
|
||||||
|
|
||||||
protected override void DoReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
base.DoReadFrom(buffer, offset);
|
|
||||||
|
|
||||||
int pos = offset + 0x18;
|
|
||||||
|
|
||||||
Id = ReadVarULong(buffer, ref pos);
|
|
||||||
Name = ReadVarString(buffer, ref pos);
|
|
||||||
if ((Flags & 0xF0) == 0x40)
|
|
||||||
{
|
|
||||||
GroupGuidString = ReadBinaryGuid(buffer, ref pos).ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GroupGuidString = ReadVarString(buffer, ref pos);
|
|
||||||
}
|
|
||||||
Unknown1 = ReadUInt(buffer, ref pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
internal sealed class DiskRecord : DatabaseRecord
|
|
||||||
{
|
|
||||||
public string DiskGuidString;
|
|
||||||
|
|
||||||
protected override void DoReadFrom(byte[] buffer, int offset)
|
|
||||||
{
|
|
||||||
base.DoReadFrom(buffer, offset);
|
|
||||||
|
|
||||||
int pos = offset + 0x18;
|
|
||||||
|
|
||||||
Id = ReadVarULong(buffer, ref pos);
|
|
||||||
Name = ReadVarString(buffer, ref pos);
|
|
||||||
if ((Flags & 0xF0) == 0x40)
|
|
||||||
{
|
|
||||||
DiskGuidString = ReadBinaryGuid(buffer, ref pos).ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DiskGuidString = ReadVarString(buffer, ref pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using DiscUtils.Partitions;
|
|
||||||
|
|
||||||
internal class DynamicDisk : IDiagnosticTraceable
|
|
||||||
{
|
|
||||||
private VirtualDisk _disk;
|
|
||||||
private PrivateHeader _header;
|
|
||||||
private Database _database;
|
|
||||||
|
|
||||||
internal DynamicDisk(VirtualDisk disk)
|
|
||||||
{
|
|
||||||
_disk = disk;
|
|
||||||
_header = GetPrivateHeader(_disk);
|
|
||||||
|
|
||||||
TocBlock toc = GetTableOfContents();
|
|
||||||
|
|
||||||
long dbStart = (_header.ConfigurationStartLba * 512) + (toc.Item1Start * 512);
|
|
||||||
_disk.Content.Position = dbStart;
|
|
||||||
_database = new Database(_disk.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SparseStream Content
|
|
||||||
{
|
|
||||||
get { return _disk.Content; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public long DataOffset
|
|
||||||
{
|
|
||||||
get { return _header.DataStartLba; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guid Id
|
|
||||||
{
|
|
||||||
get { return new Guid(_header.DiskId); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guid GroupId
|
|
||||||
{
|
|
||||||
get { return string.IsNullOrEmpty(_header.DiskGroupId) ? Guid.Empty : new Guid(_header.DiskGroupId); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Database Database
|
|
||||||
{
|
|
||||||
get { return _database; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dump(TextWriter writer, string linePrefix)
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + "DISK (" + _header.DiskId + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Metadata Version: " + ((_header.Version >> 16) & 0xFFFF) + "." + (_header.Version & 0xFFFF));
|
|
||||||
writer.WriteLine(linePrefix + " Timestamp: " + _header.Timestamp);
|
|
||||||
writer.WriteLine(linePrefix + " Disk Id: " + _header.DiskId);
|
|
||||||
writer.WriteLine(linePrefix + " Host Id: " + _header.HostId);
|
|
||||||
writer.WriteLine(linePrefix + " Disk Group Id: " + _header.DiskGroupId);
|
|
||||||
writer.WriteLine(linePrefix + " Disk Group Name: " + _header.DiskGroupName);
|
|
||||||
writer.WriteLine(linePrefix + " Data Start: " + _header.DataStartLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Data Size: " + _header.DataSizeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Configuration Start: " + _header.ConfigurationStartLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Configuration Size: " + _header.ConfigurationSizeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " TOC Size: " + _header.TocSizeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Next TOC: " + _header.NextTocLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Number of Configs: " + _header.NumberOfConfigs);
|
|
||||||
writer.WriteLine(linePrefix + " Config Size: " + _header.ConfigurationSizeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Number of Logs: " + _header.NumberOfLogs);
|
|
||||||
writer.WriteLine(linePrefix + " Log Size: " + _header.LogSizeLba + " (Sectors)");
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static PrivateHeader GetPrivateHeader(VirtualDisk disk)
|
|
||||||
{
|
|
||||||
if (disk.IsPartitioned)
|
|
||||||
{
|
|
||||||
long headerPos = 0;
|
|
||||||
PartitionTable pt = disk.Partitions;
|
|
||||||
if (pt is BiosPartitionTable)
|
|
||||||
{
|
|
||||||
headerPos = 0xc00;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var part in pt.Partitions)
|
|
||||||
{
|
|
||||||
if (part.GuidType == GuidPartitionTypes.WindowsLdmMetadata)
|
|
||||||
{
|
|
||||||
headerPos = part.LastSector * Sizes.Sector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headerPos != 0)
|
|
||||||
{
|
|
||||||
disk.Content.Position = headerPos;
|
|
||||||
byte[] buffer = new byte[Sizes.Sector];
|
|
||||||
disk.Content.Read(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
PrivateHeader hdr = new PrivateHeader();
|
|
||||||
hdr.ReadFrom(buffer, 0);
|
|
||||||
return hdr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TocBlock GetTableOfContents()
|
|
||||||
{
|
|
||||||
byte[] buffer = new byte[_header.TocSizeLba * 512];
|
|
||||||
_disk.Content.Position = (_header.ConfigurationStartLba * 512) + (1 * _header.TocSizeLba * 512);
|
|
||||||
|
|
||||||
_disk.Content.Read(buffer, 0, buffer.Length);
|
|
||||||
TocBlock tocBlock = new TocBlock();
|
|
||||||
tocBlock.ReadFrom(buffer, 0);
|
|
||||||
|
|
||||||
if (tocBlock.Signature == "TOCBLOCK")
|
|
||||||
{
|
|
||||||
return tocBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,319 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2008-2011, Kenneth Bell
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
|
||||||
// to deal in the Software without restriction, including without limitation
|
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace DiscUtils.LogicalDiskManager
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using DiscUtils.Partitions;
|
|
||||||
|
|
||||||
internal class DynamicDiskGroup : IDiagnosticTraceable
|
|
||||||
{
|
|
||||||
private DiskGroupRecord _record;
|
|
||||||
private Dictionary<Guid, DynamicDisk> _disks;
|
|
||||||
private Database _database;
|
|
||||||
|
|
||||||
internal DynamicDiskGroup(VirtualDisk disk)
|
|
||||||
{
|
|
||||||
_disks = new Dictionary<Guid, DynamicDisk>();
|
|
||||||
|
|
||||||
DynamicDisk dynDisk = new DynamicDisk(disk);
|
|
||||||
_database = dynDisk.Database;
|
|
||||||
_disks.Add(dynDisk.Id, dynDisk);
|
|
||||||
_record = dynDisk.Database.GetDiskGroup(dynDisk.GroupId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(VirtualDisk disk)
|
|
||||||
{
|
|
||||||
DynamicDisk dynDisk = new DynamicDisk(disk);
|
|
||||||
_disks.Add(dynDisk.Id, dynDisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDiagnosticTraceable Members
|
|
||||||
|
|
||||||
public void Dump(TextWriter writer, string linePrefix)
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + "DISK GROUP (" + _record.Name + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Name: " + _record.Name);
|
|
||||||
writer.WriteLine(linePrefix + " Flags: 0x" + (_record.Flags & 0xFFF0).ToString("X4", CultureInfo.InvariantCulture));
|
|
||||||
writer.WriteLine(linePrefix + " Database Id: " + _record.Id);
|
|
||||||
writer.WriteLine(linePrefix + " Guid: " + _record.GroupGuidString);
|
|
||||||
writer.WriteLine();
|
|
||||||
|
|
||||||
writer.WriteLine(linePrefix + " DISKS");
|
|
||||||
foreach (var disk in _database.Disks)
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + " DISK (" + disk.Name + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Name: " + disk.Name);
|
|
||||||
writer.WriteLine(linePrefix + " Flags: 0x" + (disk.Flags & 0xFFF0).ToString("X4", CultureInfo.InvariantCulture));
|
|
||||||
writer.WriteLine(linePrefix + " Database Id: " + disk.Id);
|
|
||||||
writer.WriteLine(linePrefix + " Guid: " + disk.DiskGuidString);
|
|
||||||
|
|
||||||
DynamicDisk dynDisk;
|
|
||||||
if (_disks.TryGetValue(new Guid(disk.DiskGuidString), out dynDisk))
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + " PRIVATE HEADER");
|
|
||||||
dynDisk.Dump(writer, linePrefix + " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteLine(linePrefix + " VOLUMES");
|
|
||||||
foreach (var vol in _database.Volumes)
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + " VOLUME (" + vol.Name + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Name: " + vol.Name);
|
|
||||||
writer.WriteLine(linePrefix + " BIOS Type: " + vol.BiosType.ToString("X2", CultureInfo.InvariantCulture) + " [" + BiosPartitionTypes.ToString(vol.BiosType) + "]");
|
|
||||||
writer.WriteLine(linePrefix + " Flags: 0x" + (vol.Flags & 0xFFF0).ToString("X4", CultureInfo.InvariantCulture));
|
|
||||||
writer.WriteLine(linePrefix + " Database Id: " + vol.Id);
|
|
||||||
writer.WriteLine(linePrefix + " Guid: " + vol.VolumeGuid);
|
|
||||||
writer.WriteLine(linePrefix + " State: " + vol.ActiveString);
|
|
||||||
writer.WriteLine(linePrefix + " Drive Hint: " + vol.MountHint);
|
|
||||||
writer.WriteLine(linePrefix + " Num Components: " + vol.ComponentCount);
|
|
||||||
writer.WriteLine(linePrefix + " Link Id: " + vol.PartitionComponentLink);
|
|
||||||
|
|
||||||
writer.WriteLine(linePrefix + " COMPONENTS");
|
|
||||||
foreach (var cmpnt in _database.GetVolumeComponents(vol.Id))
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + " COMPONENT (" + cmpnt.Name + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Name: " + cmpnt.Name);
|
|
||||||
writer.WriteLine(linePrefix + " Flags: 0x" + (cmpnt.Flags & 0xFFF0).ToString("X4", CultureInfo.InvariantCulture));
|
|
||||||
writer.WriteLine(linePrefix + " Database Id: " + cmpnt.Id);
|
|
||||||
writer.WriteLine(linePrefix + " State: " + cmpnt.StatusString);
|
|
||||||
writer.WriteLine(linePrefix + " Mode: " + cmpnt.MergeType);
|
|
||||||
writer.WriteLine(linePrefix + " Num Extents: " + cmpnt.NumExtents);
|
|
||||||
writer.WriteLine(linePrefix + " Link Id: " + cmpnt.LinkId);
|
|
||||||
writer.WriteLine(linePrefix + " Stripe Size: " + cmpnt.StripeSizeSectors + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Stripe Stride: " + cmpnt.StripeStride);
|
|
||||||
|
|
||||||
writer.WriteLine(linePrefix + " EXTENTS");
|
|
||||||
foreach (var extent in _database.GetComponentExtents(cmpnt.Id))
|
|
||||||
{
|
|
||||||
writer.WriteLine(linePrefix + " EXTENT (" + extent.Name + ")");
|
|
||||||
writer.WriteLine(linePrefix + " Name: " + extent.Name);
|
|
||||||
writer.WriteLine(linePrefix + " Flags: 0x" + (extent.Flags & 0xFFF0).ToString("X4", CultureInfo.InvariantCulture));
|
|
||||||
writer.WriteLine(linePrefix + " Database Id: " + extent.Id);
|
|
||||||
writer.WriteLine(linePrefix + " Disk Offset: " + extent.DiskOffsetLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Volume Offset: " + extent.OffsetInVolumeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Size: " + extent.SizeLba + " (Sectors)");
|
|
||||||
writer.WriteLine(linePrefix + " Component Id: " + extent.ComponentId);
|
|
||||||
writer.WriteLine(linePrefix + " Disk Id: " + extent.DiskId);
|
|
||||||
writer.WriteLine(linePrefix + " Link Id: " + extent.PartitionComponentLink);
|
|
||||||
writer.WriteLine(linePrefix + " Interleave Order: " + extent.InterleaveOrder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal DynamicVolume[] GetVolumes()
|
|
||||||
{
|
|
||||||
List<DynamicVolume> vols = new List<DynamicVolume>();
|
|
||||||
foreach (var record in _database.GetVolumes())
|
|
||||||
{
|
|
||||||
vols.Add(new DynamicVolume(this, record.VolumeGuid));
|
|
||||||
}
|
|
||||||
|
|
||||||
return vols.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal VolumeRecord GetVolume(Guid volume)
|
|
||||||
{
|
|
||||||
return _database.GetVolume(volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal LogicalVolumeStatus GetVolumeStatus(ulong volumeId)
|
|
||||||
{
|
|
||||||
return GetVolumeStatus(_database.GetVolume(volumeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SparseStream OpenVolume(ulong volumeId)
|
|
||||||
{
|
|
||||||
return OpenVolume(_database.GetVolume(volumeId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int CompareExtentOffsets(ExtentRecord x, ExtentRecord y)
|
|
||||||
{
|
|
||||||
if (x.OffsetInVolumeLba > y.OffsetInVolumeLba)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (x.OffsetInVolumeLba < y.OffsetInVolumeLba)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int CompareExtentInterleaveOrder(ExtentRecord x, ExtentRecord y)
|
|
||||||
{
|
|
||||||
if (x.InterleaveOrder > y.InterleaveOrder)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (x.InterleaveOrder < y.InterleaveOrder)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static LogicalVolumeStatus WorstOf(LogicalVolumeStatus x, LogicalVolumeStatus y)
|
|
||||||
{
|
|
||||||
return (LogicalVolumeStatus)Math.Max((int)x, (int)y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LogicalVolumeStatus GetVolumeStatus(VolumeRecord volume)
|
|
||||||
{
|
|
||||||
int numFailed = 0;
|
|
||||||
ulong numOK = 0;
|
|
||||||
LogicalVolumeStatus worst = LogicalVolumeStatus.Healthy;
|
|
||||||
foreach (var cmpnt in _database.GetVolumeComponents(volume.Id))
|
|
||||||
{
|
|
||||||
LogicalVolumeStatus cmpntStatus = GetComponentStatus(cmpnt);
|
|
||||||
worst = WorstOf(worst, cmpntStatus);
|
|
||||||
if (cmpntStatus == LogicalVolumeStatus.Failed)
|
|
||||||
{
|
|
||||||
numFailed++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numOK++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numOK < 1)
|
|
||||||
{
|
|
||||||
return LogicalVolumeStatus.Failed;
|
|
||||||
}
|
|
||||||
else if (numOK == volume.ComponentCount)
|
|
||||||
{
|
|
||||||
return worst;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return LogicalVolumeStatus.FailedRedundancy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private LogicalVolumeStatus GetComponentStatus(ComponentRecord cmpnt)
|
|
||||||
{
|
|
||||||
// NOTE: no support for RAID, so either valid or failed...
|
|
||||||
LogicalVolumeStatus status = LogicalVolumeStatus.Healthy;
|
|
||||||
|
|
||||||
foreach (var extent in _database.GetComponentExtents(cmpnt.Id))
|
|
||||||
{
|
|
||||||
DiskRecord disk = _database.GetDisk(extent.DiskId);
|
|
||||||
if (!_disks.ContainsKey(new Guid(disk.DiskGuidString)))
|
|
||||||
{
|
|
||||||
status = LogicalVolumeStatus.Failed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SparseStream OpenExtent(ExtentRecord extent)
|
|
||||||
{
|
|
||||||
DiskRecord disk = _database.GetDisk(extent.DiskId);
|
|
||||||
|
|
||||||
DynamicDisk diskObj = _disks[new Guid(disk.DiskGuidString)];
|
|
||||||
|
|
||||||
return new SubStream(diskObj.Content, Ownership.None, (diskObj.DataOffset + extent.DiskOffsetLba) * Sizes.Sector, extent.SizeLba * Sizes.Sector);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SparseStream OpenComponent(ComponentRecord component)
|
|
||||||
{
|
|
||||||
if (component.MergeType == ExtentMergeType.Concatenated)
|
|
||||||
{
|
|
||||||
List<ExtentRecord> extents = new List<ExtentRecord>(_database.GetComponentExtents(component.Id));
|
|
||||||
extents.Sort(CompareExtentOffsets);
|
|
||||||
|
|
||||||
// Sanity Check...
|
|
||||||
long pos = 0;
|
|
||||||
foreach (var extent in extents)
|
|
||||||
{
|
|
||||||
if (extent.OffsetInVolumeLba != pos)
|
|
||||||
{
|
|
||||||
throw new IOException("Volume extents are non-contiguous");
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += extent.SizeLba;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SparseStream> streams = new List<SparseStream>();
|
|
||||||
foreach (var extent in extents)
|
|
||||||
{
|
|
||||||
streams.Add(OpenExtent(extent));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ConcatStream(Ownership.Dispose, streams.ToArray());
|
|
||||||
}
|
|
||||||
else if (component.MergeType == ExtentMergeType.Interleaved)
|
|
||||||
{
|
|
||||||
List<ExtentRecord> extents = new List<ExtentRecord>(_database.GetComponentExtents(component.Id));
|
|
||||||
extents.Sort(CompareExtentInterleaveOrder);
|
|
||||||
|
|
||||||
List<SparseStream> streams = new List<SparseStream>();
|
|
||||||
foreach (var extent in extents)
|
|
||||||
{
|
|
||||||
streams.Add(OpenExtent(extent));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StripedStream(component.StripeSizeSectors * Sizes.Sector, Ownership.Dispose, streams.ToArray());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Unknown component mode: " + component.MergeType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SparseStream OpenVolume(VolumeRecord volume)
|
|
||||||
{
|
|
||||||
List<SparseStream> cmpntStreams = new List<SparseStream>();
|
|
||||||
foreach (var component in _database.GetVolumeComponents(volume.Id))
|
|
||||||
{
|
|
||||||
if (GetComponentStatus(component) == LogicalVolumeStatus.Healthy)
|
|
||||||
{
|
|
||||||
cmpntStreams.Add(OpenComponent(component));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmpntStreams.Count < 1)
|
|
||||||
{
|
|
||||||
throw new IOException("Volume with no associated or healthy components");
|
|
||||||
}
|
|
||||||
else if (cmpntStreams.Count == 1)
|
|
||||||
{
|
|
||||||
return cmpntStreams[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new MirrorStream(Ownership.Dispose, cmpntStreams.ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user