Bug fixes and compiler warnings. Unix readline support, pass 1

Fix various compiler warnings.

Fix bug causing double free when a file isn't found.

Fix bug using uninitialized variable parsing null filename.

Fix bug causing crash when format 3 retrieval pointer encountered.

Add support for readline (command line editing and history on Unix)

Untangle NT I/O so it builds without the direct access SCSI API & works.

Report errors as text messages everywhere.

Add MSVC project files.

Implement most of dir/full

Partially implement XABITM

Add help to command tables.

Allow choice of VMS qualifiers or Unix options.
  mount /write // /dev/cdrom
or
  mount -write /dev/cdrom

Parse quoted strings as command parameters.
   Mount /write "/dev/cdrom"
   search [*...]*.txt "My words for you"

Resolve command, parameter & qualifier ambiguity from tables.

Consolidate the various makefiles into a common file with very small
platform-specific wrappers.  This simplifies maintenance.

Add diskio module to allow easy access to .iso images and simulator files.
Removes requirement for loop device or equivalent.  Builds as a separate
executable.

Writes to the ODS2 volumes are broken.
This commit is contained in:
Timothe Litt 2016-02-26 17:46:46 -05:00
parent 3b052a6aa6
commit 61c8001044
38 changed files with 3289 additions and 2269 deletions

245
.gitignore vendored
View File

@ -2,3 +2,248 @@
*~
*.bak
*.o
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.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 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# 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
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# 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
# 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
# TODO: 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
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# 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
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# 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
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# 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
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml

View File

@ -0,0 +1,43 @@
ODS-2 builds on most platforms using the make utility.
Most of the make logic is in makefile.generic, which is
included by a platform-specific makefile.
The platform-specific files are:
makefile.unix -- Most Unix/Linux platforms
makefile.solaris -- Solaris
makefile.tru64 -- Tru64/DEC OSF/1
makefile.nt -- Windows NT
Select the appropriate platform file & review the definitions.
The easiest way to build ODS-2 is to softlink Makefile to
the platform file. For example:
ln -s makefile.unix Makefile
make clean && make
Alternatively, the following equivalent command can be used:
make -f makefile.unix clean && make -f makefile.unix
If your make doesn't support the "include" directive, you
can run makefile.generic manually. Instructions are in that file.
Copy the resulting object file to a convenient location on your path,
e.g. /usr/local/bin on unix, or add the build directory to the PATH
environment variable on windows.
If you need different definitions for another platform, please
add a new platform-specific file rather than changing makefile.generic.
On VMS, you can use the DCL command procedure build.com to build
with DECC or GCC, with
$ @build
build.com will automatically select decc,vaxc or gcc.
If you have MMS/mmk, use descrip.mms, with
$ mmk
To build with VAXC
$ mmk/macro=vaxc=1

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}</ProjectGuid>
<RootNamespace>ODS2Image</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>DEBUG_BUILD;DISKIMAGE;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
<AdditionalDependencies>access;cache;compat;device;direct;rms;sysmsg;update;vmstime;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>DISKIMAGE;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
<AdditionalDependencies>access;cache;compat;device;direct;rms;sysmsg;update;vmstime;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\access.h" />
<ClInclude Include="..\..\compat.h" />
<ClInclude Include="..\..\descrip.h" />
<ClInclude Include="..\..\phyio.h" />
<ClInclude Include="..\..\rms.h" />
<ClInclude Include="..\..\ssdef.h" />
<ClInclude Include="..\..\sysmsg.h" />
<ClInclude Include="..\diskio.h" />
<ClInclude Include="..\version.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\diskio.c" />
<ClCompile Include="..\ods2.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\access.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\compat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\descrip.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\phyio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\rms.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\ssdef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\sysmsg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\diskio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\version.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\diskio.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ods2.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

29
extracters/ods2/ODS2.sln Normal file
View File

@ -0,0 +1,29 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ODS2", "ODS2.vcxproj", "{BCCEAED2-1732-D796-1F70-040DE5DA42AD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ODS2-Image", "ODS2-Image\ODS2-Image.vcxproj", "{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}"
ProjectSection(ProjectDependencies) = postProject
{BCCEAED2-1732-D796-1F70-040DE5DA42AD} = {BCCEAED2-1732-D796-1F70-040DE5DA42AD}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Debug|Win32.ActiveCfg = Debug|Win32
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Debug|Win32.Build.0 = Debug|Win32
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|Win32.ActiveCfg = Release|Win32
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|Win32.Build.0 = Release|Win32
{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}.Debug|Win32.ActiveCfg = Debug|Win32
{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}.Debug|Win32.Build.0 = Debug|Win32
{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}.Release|Win32.ActiveCfg = Release|Win32
{1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>DEBUG_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>
</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="access.c" />
<ClCompile Include="cache.c" />
<ClCompile Include="compat.c" />
<ClCompile Include="device.c" />
<ClCompile Include="direct.c" />
<ClCompile Include="ods2.c" />
<ClCompile Include="phynt.c" />
<ClCompile Include="rms.c" />
<ClCompile Include="sysmsg.c" />
<ClCompile Include="update.c" />
<ClCompile Include="vmstime.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="access.h" />
<ClInclude Include="cache.h" />
<ClInclude Include="compat.h" />
<ClInclude Include="descrip.h" />
<ClInclude Include="direct.h" />
<ClInclude Include="fibdef.h" />
<ClInclude Include="header.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="phyio.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="rms.h" />
<ClInclude Include="scsidefs.h" />
<ClInclude Include="ssdef.h" />
<ClInclude Include="sysmsg.h" />
<ClInclude Include="version.h" />
<ClInclude Include="vmstime.h" />
<ClInclude Include="wnaspi32.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ods2.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="access.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cache.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="device.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="direct.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ods2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="phynt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rms.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="update.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vmstime.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sysmsg.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="compat.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="access.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cache.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="descrip.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="direct.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fibdef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="header.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="phyio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rms.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="scsidefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ssdef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="vmstime.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="compat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sysmsg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wnaspi32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="version.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ods2.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -46,6 +46,8 @@ How do I build it?
compile using the gcc command:-
gcc -fdollars-in-identifiers ods2.c,rms.c,direct.c,
access.c,device.c,cache.c,phyos2.c,vmstime.c
On unix, use "CCFLAGS=-DUSE_READLINE" "LDFLAGS=-lreadline" for
readline (command history and editing) support.
What can it do?
Basically ODS2 provides cut down DIRECTORY, COPY and
@ -148,18 +150,27 @@ Can I see a command sample?
What commands are supported?
A summary is:-
mount DRIVE:[,DRIVE:...]
mount /write DRIVE:[,DRIVE:...]
directory [/file|/size|/date] [FILE-SPEC]
copy FILE-SPEC OUTPUT-FILE
copy VMSFILE-SPEC HOST-OUTPUT-FILE
delete
difference VMSNAME hostname (0-terminated string diff?!)
dismount DRIVE:
extend
import hostname VMSNAME copy file to ODS-2
search FILE-SPEC STRING
set default DIR-SPEC
show default
show time
statistics
type VMSNAME
exit
Note - DRIVE: is normally the native system drive name,
for example D: might be a CD on a PC - xxx: might be
/dev/xxx on a Unix system.
/dev/xxx on a Unix system. (Actually, on a unix
system, '/' can't be parsed. So specify the last
component - the rest is hardcoded. E.g. /dev/loop0
is specified as /loop0.
- when a list of drives is specified on the mount command
they are assumed to contain a single valid volume set
(this is not validated!!)

View File

@ -24,7 +24,7 @@
#include "ssdef.h"
#include "access.h"
#include "phyio.h"
#include "compat.h"
#define DEBUGx
@ -158,6 +158,9 @@ int wcb_compare(unsigned hashval,void *keyval,void *thiswcb)
{
register struct WCBKEY *wcbkey = (struct WCBKEY *) keyval;
register struct WCB *wcb = (struct WCB *) thiswcb;
UNUSED(hashval);
if (wcbkey->vbn < wcb->loblk) {
return -1; /* Search key is less than this window maps... */
} else {
@ -215,6 +218,9 @@ struct HEAD *premap_indexf(struct FCB *fcb,unsigned *retsts)
void *wcb_create(unsigned hashval,void *keyval,unsigned *retsts)
{
register struct WCB *wcb = (struct WCB *) malloc(sizeof(struct WCB));
UNUSED(hashval);
if (wcb == NULL) {
*retsts = SS$_INSFMEM;
} else {
@ -276,6 +282,10 @@ void *wcb_create(unsigned hashval,void *keyval,unsigned *retsts)
phylen = ((VMSWORD(*mp) & 037777) << 16) + VMSWORD(mp[1]) + 1;
phyblk = (VMSWORD(mp[3]) << 16) | VMSWORD(mp[2]);
mp += 4;
break;
default:
printf( "Unknown type %x\n", (VMSWORD(*mp)>>14) );
exit(1);
}
curvbn += phylen;
if (phylen != 0 && curvbn > wcb->loblk) {
@ -368,16 +378,19 @@ unsigned getwindow(struct FCB * fcb,unsigned vbn,struct VCBDEV **devptr,
void *vioc_manager(struct CACHE * cacheobj,int flushonly)
{
register struct VIOC *vioc = (struct VIOC *) cacheobj;
UNUSED(flushonly);
if (vioc->modmask != 0) {
register struct FCB *fcb = vioc->fcb;
register int length = VIOC_CHUNKSIZE;
register unsigned int length = VIOC_CHUNKSIZE;
register unsigned curvbn = vioc->cache.hashval + 1;
register char *address = (char *) vioc->data;
register unsigned modmask = vioc->modmask;
printf("\nvioc_manager writing vbn %d\n",curvbn);
do {
register unsigned sts;
int wrtlen = 0;
unsigned int wrtlen = 0;
unsigned phyblk,phylen;
struct VCBDEV *vcbdev;
while (length > 0 && (1 & modmask) == 0) {
@ -448,7 +461,7 @@ void *vioc_create(unsigned hashval,void *keyval,unsigned *retsts)
if (vioc == NULL) {
*retsts = SS$_INSFMEM;
} else {
register int length;
register unsigned int length;
register unsigned curvbn = hashval + 1;
register char *address;
register struct FCB *fcb = (struct FCB *) keyval;
@ -499,7 +512,7 @@ unsigned accesschunk(struct FCB *fcb,unsigned vbn,struct VIOC **retvioc,
char **retbuff,unsigned *retblocks,unsigned wrtblks)
{
unsigned sts;
register int blocks;
register unsigned int blocks;
register struct VIOC *vioc;
#ifdef DEBUG
printf("Access chunk %8x %d (%x)\n",base,vbn,fcb->cache.hashval);
@ -590,6 +603,10 @@ void *fcb_manager(struct CACHE *cacheobj,int flushonly)
void *fcb_create(unsigned filenum,void *keyval,unsigned *retsts)
{
register struct FCB *fcb = (struct FCB *) malloc(sizeof(struct FCB));
UNUSED(filenum);
UNUSED(keyval);
if (fcb == NULL) {
*retsts = SS$_INSFMEM;
} else {
@ -718,9 +735,12 @@ unsigned dismount(struct VCB * vcb)
unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],struct VCB **retvcb)
{
register unsigned device,sts;
register unsigned device,sts = 0;
struct VCB *vcb;
struct VCBDEV *vcbdev;
UNUSED(label);
if (sizeof(struct HOME) != 512 || sizeof(struct HEAD) != 512) return SS$_NOTINSTALL;
vcb = (struct VCB *) malloc(sizeof(struct VCB) + (devices - 1) * sizeof(struct VCBDEV));
if (vcb == NULL) return SS$_INSFMEM;
@ -733,7 +753,7 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],stru
sts = SS$_NOSUCHVOL;
vcbdev->dev = NULL;
if (strlen(devnam[device])) {
int hba;
unsigned int hba;
sts = device_lookup(strlen(devnam[device]),devnam[device],1,&vcbdev->dev);
if (!(sts & 1)) break;
for (hba = 1; hba <= HOME_LIMIT; hba++) {
@ -789,8 +809,12 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],stru
vcbdev->clustersize = vcbdev->home.hm2$w_cluster;
vcbdev->max_cluster = (scb->scb$l_volsize + scb->scb$w_cluster - 1) / scb->scb$w_cluster;
deaccesschunk(vioc,0,0,0);
sts = update_freecount(vcbdev,&vcbdev->free_clusters);
printf("Freespace is %d\n",vcbdev->free_clusters);
sts = update_freecount(vcbdev,&vcbdev->free_clusters);
#ifdef DEBUG
printf( "%d of %d blocks are free on %12.12s\n",
vcbdev->free_clusters * vcbdev->clustersize, scb->scb$l_volsize,
vcbdev->home.hm2$t_volname );
#endif
}
}
}

View File

@ -30,6 +30,7 @@ typedef unsigned int vmsswap;
typedef unsigned int vmslong;
#define FH2$M_NOBACKUP 0x2
#define FH2$M_CONTIGB 0x20
#define FH2$M_CONTIG 0x80
#define FH2$M_DIRECTORY 0x2000
#define FH2$M_MARKDEL 0x8000
@ -229,20 +230,21 @@ struct DIRCACHE {
#define VCB_WRITE 1
struct VCBDEV {
struct DEV *dev; /* Pointer to device info */
struct FCB *idxfcb; /* Index file control block */
struct FCB *mapfcb; /* Bitmap file control block */
unsigned clustersize; /* Cluster size of the device */
unsigned max_cluster; /* Total clusters on the device */
unsigned free_clusters; /* Free clusters on disk volume */
struct HOME home; /* Volume home block */
};
struct VCB {
unsigned status; /* Volume status */
unsigned devices; /* Number of volumes in set */
struct FCB *fcb; /* File control block tree */
struct DIRCACHE *dircache; /* Directory cache tree */
struct VCBDEV {
struct DEV *dev; /* Pointer to device info */
struct FCB *idxfcb; /* Index file control block */
struct FCB *mapfcb; /* Bitmap file control block */
unsigned clustersize; /* Cluster size of the device */
unsigned max_cluster; /* Total clusters on the device */
unsigned free_clusters; /* Free clusters on disk volume */
struct HOME home; /* Volume home block */
} vcbdev[1]; /* List of volumes devices */
struct VCBDEV vcbdev[1]; /* List of volumes devices */
}; /* Volume control block */
@ -251,7 +253,7 @@ struct DEV {
struct VCB *vcb; /* Pointer to volume (if mounted) */
unsigned handle; /* Device physical I/O handle */
unsigned status; /* Device physical status */
unsigned sectors; /* Device physical sectors */
unsigned long long sectors; /* Device physical sectors */
unsigned sectorsize; /* Device physical sectorsize */
char devnam[1]; /* Device name */
}; /* Device information */

View File

@ -1,237 +0,0 @@
/* Access.h v1.2 Definitions for file access routines */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
ODS2 is distributed freely for all members of the
VMS community to use. However all derived works
must maintain comments in their source to acknowledge
the contibution of the original author.
*/
#include "cache.h"
#include "vmstime.h"
#define swapw(w) (w[0]<<16 | w[1])
#define FH2$M_NOBACKUP 0x2
#define FH2$M_CONTIG 0x80
#define FH2$M_DIRECTORY 0x2000
#define FH2$M_MARKDEL 0x8000
#define FH2$M_ERASE 0x20000
typedef unsigned char u_byte;
typedef unsigned short u_word;
typedef unsigned int u_long;
struct UIC {
u_word u_grp;
u_word u_mem;
};
struct fiddef {
u_word fid$w_num;
u_word fid$w_seq;
u_byte fid$b_rvn;
u_byte fid$b_nmx;
};
struct RECATTR {
u_byte fat$b_rtype;
u_byte fat$b_rattrib;
u_word fat$w_rsize;
u_word fat$l_hiblk[2];
u_word fat$l_efblk[2];
u_word fat$w_ffbyte;
u_byte fat$b_bktsize;
u_byte fat$b_vfcsize;
u_word fat$w_maxrec;
u_word fat$w_defext;
u_word fat$w_gbc;
u_byte fat$_UU0[8];
u_word fat$w_versions;
};
struct HOME {
u_long hm2$l_homelbn;
u_long hm2$l_alhomelbn;
u_long hm2$l_altidxlbn;
u_word hm2$w_struclev;
u_word hm2$w_cluster;
u_word hm2$w_homevbn;
u_word hm2$w_alhomevbn;
u_word hm2$w_altidxvbn;
u_word hm2$w_ibmapvbn;
u_long hm2$l_ibmaplbn;
u_long hm2$l_maxfiles;
u_word hm2$w_ibmapsize;
u_word hm2$w_resfiles;
u_word hm2$w_devtype;
u_word hm2$w_rvn;
u_word hm2$w_setcount;
u_word hm2$w_volchar;
struct UIC hm2$w_volowner;
u_long hm2$l_reserved1;
u_word hm2$w_protect;
u_word hm2$w_fileprot;
u_word hm2$w_reserved2;
u_word hm2$w_checksum1;
struct TIME hm2$q_credate;
u_byte hm2$b_window;
u_byte hm2$b_lru_lim;
u_word hm2$w_extend;
struct TIME hm2$q_retainmin;
struct TIME hm2$q_retainmax;
struct TIME hm2$q_revdate;
u_byte hm2$r_min_class[20];
u_byte hm2$r_max_class[20];
u_byte hm2$t_reserved3[320];
u_long hm2$l_serialnum;
char hm2$t_strucname[12];
char hm2$t_volname[12];
char hm2$t_ownername[12];
char hm2$t_format[12];
u_word hm2$w_reserved4;
u_word hm2$w_checksum2;
};
struct IDENT {
char fi2$t_filename[20];
u_word fi2$w_revision;
struct TIME fi2$q_credate;
struct TIME fi2$q_revdate;
struct TIME fi2$q_expdate;
struct TIME fi2$q_bakdate;
char fi2$t_filenamext[66];
};
struct HEAD {
u_byte fh2$b_idoffset;
u_byte fh2$b_mpoffset;
u_byte fh2$b_acoffset;
u_byte fh2$b_rsoffset;
u_word fh2$w_seg_num;
u_word fh2$w_struclev;
struct fiddef fh2$w_fid;
struct fiddef fh2$w_ext_fid;
struct RECATTR fh2$w_recattr;
u_long fh2$l_filechar;
u_word fh2$w_reserved1;
u_byte fh2$b_map_inuse;
u_byte fh2$b_acc_mode;
struct UIC fh2$l_fileowner;
u_word fh2$w_fileprot;
struct fiddef fh2$w_backlink;
u_byte fh2$b_journal;
u_byte fh2$b_ru_active;
u_word fh2$w_reserved2;
u_long fh2$l_highwater;
u_byte fh2$b_reserved3[8];
u_byte fh2$r_class_prot[20];
u_byte fh2$r_restofit[402];
u_word fh2$w_checksum;
};
struct EXT {
unsigned phylen;
unsigned phyblk;
}; /* Physical extent entry */
#define EXTMAX 20
struct WCB {
struct CACHE cache;
unsigned loblk,hiblk; /* Range of window */
unsigned hd_base; /* File blocks prior to header */
unsigned extcount; /* Extents in use */
struct EXT ext[EXTMAX]; /* Mapping extents */
struct fiddef hd_fid; /* Header info to create other WCBs */
}; /* Window control block */
#define VIOC_CHUNKSIZE 4
struct VIOC {
struct CACHE cache;
struct FCB *fcb; /* File this chunk is for */
unsigned wrtmask; /* Bit mask for writable blocks */
unsigned modmask; /* Bit mask for modified blocks */
char data[VIOC_CHUNKSIZE][512]; /* Chunk data */
}; /* Chunk of a file */
struct FCB {
struct CACHE cache;
struct VCB *vcb; /* Volume this file is for */
struct VIOC *headvioc; /* Index file chunk for file header */
struct HEAD *head; /* Pointer to header block */
struct WCB *wcb; /* Window control block tree */
struct VIOC *vioc; /* Virtual I/O chunk tree */
unsigned modmask; /* headvioc chunk modmask */
unsigned hiblock; /* Highest block mapped */
unsigned highwater; /* First high water block */
unsigned char rvn; /* Initial file relative volume */
}; /* File control block */
struct DIRCACHE {
struct CACHE cache;
int dirlen; /* Length of directory name */
struct fiddef dirid; /* File ID of directory */
char dirnam[1]; /* Directory name */
}; /* Directory cache entry */
#define VCB_WRITE 1
struct VCB {
unsigned status; /* Volume status */
unsigned devices; /* Number of volumes in set */
struct HEAD *idxboot; /* Pointer to index file boot header */
struct FCB *fcb; /* File control block tree */
struct DIRCACHE *dircache; /* Directory cache tree */
struct VCBDEV {
struct DEV *dev; /* Pointer to device info */
struct FCB *idxfcb; /* Index file control block */
struct FCB *mapfcb; /* Bitmap file control block */
struct HOME home; /* Volume home block */
} vcbdev[1]; /* List of volumes devices */
}; /* Volume control block */
struct DEV {
struct CACHE cache;
struct VCB *vcb; /* Pointer to volume (if mounted) */
unsigned handle; /* Device physical I/O handle */
unsigned status; /* Device physical status */
unsigned sectors; /* Device physical sectors */
unsigned sectorsize; /* Device physical sectorsize */
int devlen; /* Length of device name */
char devnam[1]; /* Device name */
}; /* Device information */
unsigned device_lookup(unsigned devlen,char *devnam,int create,struct DEV **retdev);
unsigned dismount(struct VCB *vcb);
unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],struct VCB **vcb);
unsigned accesserase(struct VCB *vcb,struct fiddef *fid);
unsigned deaccessfile(struct FCB *fcb);
unsigned accessfile(struct VCB *vcb,struct fiddef *fid,
struct FCB **fcb,unsigned wrtflg);
unsigned deaccesschunk(struct VIOC *vioc,unsigned modmask,int reuse);
unsigned accesschunk(struct FCB *fcb,unsigned vbn,struct VIOC **retvioc,
char **retbuff,unsigned *retblocks,unsigned wrtblks,
unsigned *retmodmask);

View File

@ -14,13 +14,16 @@ $ default=f$parse(f$environment("PROCEDURE"),,,"DEVICE","SYNTAX_ONLY")+ -
$ set def 'default'
$
$ call cc ods2 'p1'
$ call cc ods2 'p1'+"/object=ods2i.obj/define=DISKIMAGE"
$ call cc rms 'p1'
$ call cc direct 'p1'
$ call cc diskio 'p1'
$ call cc access 'p1'
$ call cc device 'p1'
$ call cc cache 'p1'
$ call cc phyvms 'p1'
$ call cc update 'p1'
$ call cc sysmsg 'p1'
$ call cc vmstime 'p1'
$
$ write sys$error "''f$time()' Linking..."
@ -29,12 +32,13 @@ $ then library = ",vaxcrtl.tmp/option"
$ create vaxcrtl.tmp
sys$share:vaxcrtl/share
$ endif
$ link 'p2' ods2,rms,direct,access,device,cache,phyvms,vmstime,update 'library'
$ link 'p2' /exe=ods2i.exe ods2i,rms,direct,access,device,cache,diskio,sysmsg,vmstime,update 'library'
$ link 'p2' ods2,rms,direct,access,device,cache,phyvms,sysmsg,vmstime,update 'library'
$ write sys$error "''f$time()' Done"
$ exit
$
$cc: subroutine
$ if f$search(p1+".obj;").nes."" then if f$cvtime(f$file(p1+".obj;","CDT")).ges.f$cvtime(f$file(p1+".c;","CDT")) then exit
$!$ if f$search(p1+".obj;").nes."" then if f$cvtime(f$file(p1+".obj;","CDT")).ges.f$cvtime(f$file(p1+".c;","CDT")) then exit
$ write sys$error "''f$time()' Compiling ''p1'..."
$ cc 'p2' 'p1'
$ exit

View File

@ -1,411 +0,0 @@
/* Cache.c v1.2 Caching control routines */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
ODS2 is distributed freely for all members of the
VMS community to use. However all derived works
must maintain comments in their source to acknowledge
the contibution of the original author.
*/
/* Caching seems to have a big impact on performance!!!
This version based on number of objects - probably
should change it to use space occupied by objects.
Currently use vanilla binary trees - could either
use hashing or balanced trees for better performance. */
/* The theory is that all cachable objects share a common
cache pool. Any object with a reference count of zero
is a candidate for destruction. All cacheable objects
have a 'struct CACHE' as the first item of the object
so that cache pointers and object pointers are interchangeable.
All cache objects are also part of a binary tree so that
they can be located. There are many instances of these
binary trees: for files on a volume, for chunks (segments)
of files, etc. Also each object can have an object manager:
a routine to handle special object deletion requirements
(for example to remove all file chunks before removing a
file), or to flush objects (write modified chunks to disk). */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "ssdef.h"
#include "cache.h"
#define DEBUG on
/* Set limits for number of unaccessed cache entries... */
#define CACHELIM 64
#define CACHEGOAL 25
int cachesearches = 0;
int cachecreated = 0;
int cachedeleted = 0;
int cachepeak = 0;
int cachecount = 0;
int cachefreecount = 0;
struct CACHE cachelist = {NULL,NULL,NULL,&cachelist,&cachelist,NULL,0,0,1};
/* cacheshow - to print cache statistics */
void cacheshow(void)
{
printf("CACHESHOW Searches: %d Created: %d Peak: %d Count: %d Free: %d\n",
cachesearches,cachecreated,cachepeak,cachecount,cachefreecount);
}
void cachedump(void)
{
register struct CACHE *cacheobj = cachelist.lstcache;
printf("%8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s cachelist\n","Object",
"Parent","Left","Right","Value","Status","Count");
while (cacheobj != &cachelist) {
printf("%8p %8p %8p %8p %8x %8x %8d\n",
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
cacheobj = cacheobj->lstcache;
}
}
/* cacheprint - debugging tool to print out a cache subtree... */
void cacheprint(struct CACHE *cacheobj,int level)
{
if (cacheobj != NULL) {
int i;
cacheprint(cacheobj->left,level + 1);
for (i = 0; i < level; i++) printf(" ");
printf("%8x %8x %8x %d\n",
cacheobj,cacheobj->keyval,cacheobj->status,cacheobj->refcount);
cacheprint(cacheobj->right,level + 1);
}
}
/* cacherefcount - compute reference count for cache subtree... */
int cacherefcount(struct CACHE *cacheobj)
{
register int refcount = 0;
if (cacheobj != NULL) {
if (cacheobj->left != NULL) refcount += cacherefcount(cacheobj->left);
if (cacheobj->right != NULL) refcount += cacherefcount(cacheobj->right);
refcount += cacheobj->refcount;
}
return refcount;
}
/* cachefree - blow away item from cache - allow item to select a proxy (!)
and adjust 'the tree' containing the item. */
int freeactive = 0; /* In case object managers re-call cachefree... :-( */
struct CACHE *cachefree(struct CACHE *cacheobj)
{
if (cacheobj->refcount != 0) {
char str[100];
printf("cachelist, object to delete still inuse?\n");
printf("%8p %8p %8p %8p %8x %8x %8d\n",
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
printf("Type RETURN: ");
fgets(str, sizeof(str)-1, stdin);
return NULL;
} else {
register struct CACHE *proxyobj;
while (cacheobj->objmanager != NULL) {
freeactive = 1;
proxyobj = (*cacheobj->objmanager) (cacheobj);
freeactive = 0;
if (proxyobj == NULL) return NULL;
if (proxyobj == cacheobj) break;
cacheobj = proxyobj;
}
if ((cacheobj->status & CACHE_MODIFIED) && cacheobj->objmanager == NULL)
printf("cachelist No manager to write modified cache\n");
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
if (cacheobj->parent != NULL) { /* Check if in tree... */
if (cacheobj->left == NULL) {
if (cacheobj->right == NULL) {
*(cacheobj->parent) = NULL;
} else {
cacheobj->right->parent = cacheobj->parent;
*(cacheobj->parent) = cacheobj->right;
}
} else {
if (cacheobj->right == NULL) {
cacheobj->left->parent = cacheobj->parent;
*(cacheobj->parent) = cacheobj->left;
} else {
register struct CACHE *leftpath = cacheobj->left;
register struct CACHE *rightpath = cacheobj->right;
while (1) {
if (leftpath->right == NULL) {
leftpath->right = cacheobj->right;
cacheobj->right->parent = &leftpath->right;
cacheobj->left->parent = cacheobj->parent;
*(cacheobj->parent) = cacheobj->left;
break;
} else {
if (rightpath->left == NULL) {
rightpath->left = cacheobj->left;
cacheobj->left->parent = &rightpath->left;
cacheobj->right->parent = cacheobj->parent;
*(cacheobj->parent) = cacheobj->right;
break;
} else {
leftpath = leftpath->right;
rightpath = rightpath->left;
}
}
}
}
}
}
if (--cachecount < 0) printf("cachelist, cache current too small\n");
cachefreecount--;
cachedeleted--;
#ifdef DEBUG
cacheobj->parent = NULL;
cacheobj->left = NULL;
cacheobj->right = NULL;
cacheobj->nxtcache = NULL;
cacheobj->lstcache = NULL;
cacheobj->objmanager = NULL;
cacheobj->keyval = 0;
cacheobj->status = 0;
cacheobj->refcount = 0;
#endif
free(cacheobj);
return cacheobj;
}
}
/* cachepurge - trim size of free list */
void cachepurge()
{
register struct CACHE *cacheobj = cachelist.lstcache;
while (cachefreecount > CACHEGOAL && cacheobj != &cachelist) {
register struct CACHE *lastobj = cacheobj->lstcache;
#ifdef DEBUG
if (cacheobj->lstcache->nxtcache != cacheobj ||
cacheobj->nxtcache->lstcache != cacheobj ||
*(cacheobj->parent) != cacheobj) {
printf("CACHE pointers in bad shape! %p %p %p - %p\n",
cacheobj->lstcache->nxtcache,cacheobj,cacheobj->nxtcache->lstcache,*(cacheobj->parent));
}
#endif
if (cacheobj->refcount == 0) {
if (cachefree(cacheobj) != lastobj) cacheobj = lastobj;
} else {
cacheobj = lastobj;
}
}
}
/* cacheflush - flush modified entries in cache */
void cacheflush()
{
register struct CACHE *cacheobj = cachelist.lstcache;
while (cacheobj != &cachelist) {
if (cacheobj->status & CACHE_MODIFIED) {
if (cacheobj->objmanager != NULL) {
(*cacheobj->objmanager) (cacheobj);
} else {
printf("CACHEFLUSH No manager to write modified cache\n");
}
}
cacheobj = cacheobj->lstcache;
}
}
/* cachedelete - delete an object from cache */
struct CACHE *cachedelete(struct CACHE *cacheobj)
{
if (cacheobj != NULL) {
register struct CACHE *cachedel;
do {
cachedel = cachefree(cacheobj);
} while (cachedel != NULL && cachedel != cacheobj);
}
return cacheobj;
}
/* cachedeltree: delete cache subtree */
void cachedeltree(struct CACHE *cacheobj)
{
if (cacheobj != NULL) {
if (cacheobj->left != NULL) cachedeltree(cacheobj->left);
if (cacheobj->right != NULL) cachedeltree(cacheobj->right);
if (cacheobj->refcount == 0) cachedelete(cacheobj);
}
}
/* cacheuntouch - decrement object reference count */
unsigned cacheuntouch(struct CACHE *cacheobj,unsigned reuse,unsigned modflg)
{
if (cacheobj->refcount < 1) {
char str[100];
printf("%8p %8p %8p %8p %8x %8x %8d\n",
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
printf("CACHE untouch TOO FAR!\n");
printf("Type RETURN: ");
fgets(str, sizeof(str), stdin);
return 64;
} else {
if (modflg) {
if ((cacheobj->status & CACHE_WRITE) == 0) return SS$_WRITLCK;
cacheobj->status |= CACHE_MODIFIED;
}
if (--cacheobj->refcount == 0) {
/* Move to new list position... */
if (reuse == 0 && cacheobj != cachelist.lstcache) {
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
cacheobj->nxtcache = &cachelist;
cacheobj->lstcache = cachelist.lstcache;
cachelist.lstcache->nxtcache = cacheobj;
cachelist.lstcache = cacheobj;
}
cacheobj->status &= ~CACHE_WRITE;
if (++cachefreecount > CACHELIM && freeactive == 0) cachepurge();
}
}
return 1;
}
/* cachetouch - add one to reference count */
void cachetouch(struct CACHE *cacheobj)
{
if (cacheobj->refcount++ < 1) {
#ifdef DEBUG
if (cacheobj->lstcache->nxtcache != cacheobj ||
cacheobj->nxtcache->lstcache != cacheobj ||
*(cacheobj->parent) != cacheobj) {
printf("CACHE pointers in bad shape! %p %p %p - %p\n",
cacheobj->lstcache->nxtcache,cacheobj,cacheobj->nxtcache->lstcache,*(cacheobj->parent));
}
#endif
cachefreecount--;
}
/* Move object to head of list... */
if (cacheobj != cachelist.nxtcache) {
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
cacheobj->lstcache = &cachelist;
cacheobj->nxtcache = cachelist.nxtcache;
cachelist.nxtcache->lstcache = cacheobj;
cachelist.nxtcache = cacheobj;
}
}
/* cachesearch - to find or create cache entries...
The grand plan here was to use a hash code as a quick key
and call a compare function for duplicates. So far no data
type actually works like this - they either have a unique binary
key, or all records rely on the compare function - sigh!
Never mind, the potential is there! :-) */
void *cachesearch(void **root,unsigned keyval,unsigned keylen,void *key,
int (*cmpfunc) (unsigned keylen,void *key,void *node),
unsigned *createsize)
{
register struct CACHE *parentobj = NULL;
register struct CACHE *cacheobj,**parent = (struct CACHE **) root;
cachesearches++;
while ((cacheobj = *parent) != NULL) {
parentobj = cacheobj;
if (cacheobj->keyval == keyval) {
register int cmp = 0;
if (cmpfunc != NULL)
cmp = (*cmpfunc) (keylen,key,(void *) cacheobj);
if (cmp == 0) {
cachetouch(cacheobj);
return cacheobj;
} else {
if (cmp < 0) {
parent = &cacheobj->left;
} else {
parent = &cacheobj->right;
}
}
} else {
if (cacheobj->keyval < keyval) {
parent = &cacheobj->left;
} else {
parent = &cacheobj->right;
}
}
}
if (*createsize > sizeof(struct CACHE)) {
cacheobj = (struct CACHE *) malloc(*createsize);
if (cacheobj != NULL) {
cacheobj->parent = parent;
cacheobj->left = NULL;
cacheobj->right = NULL;
cacheobj->objmanager = NULL;
cacheobj->keyval = keyval;
cacheobj->status = 0;
cacheobj->refcount = 1;
*parent = cacheobj;
*createsize = 0;
cachecreated++;
/* Add to cache list... */
cacheobj->lstcache = &cachelist;
cacheobj->nxtcache = cachelist.nxtcache;
cachelist.nxtcache->lstcache = cacheobj;
cachelist.nxtcache = cacheobj;
if (parentobj != NULL) {
/* Attempt to mix up the tree a little... */
if (parentobj->left == NULL) {
*parentobj->parent = cacheobj;
cacheobj->parent = parentobj->parent;
parentobj->parent = &cacheobj->left;
cacheobj->left = parentobj;
parentobj->right = NULL;
} else {
if (parentobj->right == NULL) {
*parentobj->parent = cacheobj;
cacheobj->parent = parentobj->parent;
parentobj->parent = &cacheobj->right;
cacheobj->right = parentobj;
parentobj->left = NULL;
}
}
}
if (cachecount++ >= cachepeak) cachepeak = cachecount;
}
}
return cacheobj;
}

78
extracters/ods2/compat.c Normal file
View File

@ -0,0 +1,78 @@
/* Timothe Litt February 2016 */
/* This module contains compatibility code, currently just
* to support Microsoft Windows.
*
* Microsoft deprecates sprintf, but doesn't supply standard
* replacement until very recent IDEs.
* Microsoft doesn't like fopen.
* One needs to use a M$ call to translate system errors.
*/
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdio.h>
#include "compat.h"
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#ifdef _WIN32
#include <errno.h>
#include <windows.h>
FILE *openf( const char *filename, const char *mode ) {
errno_t err;
FILE *fd = NULL;
err = fopen_s( &fd, filename, mode );
if( err == 0 ) {
return fd;
}
return NULL;
}
TCHAR *w32_errstr( DWORD eno, ... ) {
va_list ap;
TCHAR *msg;
if( eno == 0 )
eno = GetLastError();
va_start(ap,eno);
if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, eno, 0,
(LPSTR)&msg, 1, &ap ) == 0 ) {
msg = (TCHAR *)malloc( 32 );
snprintf( msg, 32, "(%u)", eno );
}
va_end(ap);
return msg;
}
#endif
#endif
/* For ISO C compliance, ensure that there's something in this module */
void dummy_compat ( void ) { return; }

30
extracters/ods2/compat.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef COMPAT_H
#define COMPAT_H
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
#include <stdarg.h>
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
int c99_snprintf(char *outBuf, size_t size, const char *format, ...);
#endif
#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
FILE *openf( const char *filename, const char *mode );
TCHAR *w32_errstr( DWORD eno, ... );
#else
#define openf fopen
#endif
#define UNUSED(x) (void)(x)
#endif

View File

@ -29,28 +29,46 @@ OPTFILE =
OPTIONS =
.ENDIF
OBJS = ODS2,RMS,DIRECT,ACCESS,DEVICE,CACHE,PHYVMS,UPDATE,VMSTIME
OBJS = $(ODS2_OBJS) $(ODS2I_OBJS)
COMMON_OBJS = RMS,DIRECT,ACCESS,DEVICE,CACHE,UPDATE,SYSMSG,VMSTIME
ODS2_OBJS = ODS2$(OBJ) $(COMMON_OBJS) PHYVMS
ODS2I_OBJS = ODS2I$(OBJ) $(COMON_OBJS) DISKIO
ODS2 : ODS2$(EXE) ODS2I(EXE)
ODS2I$(EXE) : ODS2I$(OLB)($(ODS2I_OBJS))$(OPTFILE)
$(LINK) $(LINKFLAGS) ODS2I$(OLB)/INCLUDE=($(ODS2I_OBJS))$(OPTIONS)
ODS2$(EXE) : ODS2$(OLB)($(OBJS))$(OPTFILE)
$(LINK)$(LINKFLAGS) ODS2$(OLB)/INCLUDE=($(OBJS))$(OPTIONS)
$(LINK)$(LINKFLAGS) ODS2$(OLB)/INCLUDE=($(ODS2_OBJS))$(OPTIONS)
vmstime$(obj) : vmstime.c vmstime.h
vmstime$(OBJ) : vmstime.c vmstime.h
cache$(obj) : cache.c cache.h ssdef.h
sysmsg$(OBJ) : sysmsg.c sysmsg.h ssdef.h rms.h
phyvms$(obj) : phyvms.c phyio.h ssdef.h
diskio$(OBJ) : diskio sysmsg.h ssdef.h rms.h
device$(obj) : device.c ssdef.h access.h phyio.h
cache$(OBJ) : cache.c cache.h ssdef.h
access$(obj) : access.c ssdef.h access.h phyio.h
phyvms$(OBJ) : phyvms.c phyio.h ssdef.h
update$(obj) : update.c ssdef.h access.h
device$(OBJ) : device.c ssdef.h access.h phyio.h
direct$(obj) : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
access$(OBJ) : access.c ssdef.h access.h phyio.h
rms$(obj) : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
update$(OBJ) : update.c ssdef.h access.h
ods2$(obj) : ods2.c ssdef.h descrip.h access.h rms.h
direct$(OBJ) : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
rms$(OBJ) : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
ods2$(OBJ) : ods2.c compat.h sysmsg.h phyio.h ssdef.h descrip.h access.h rms.h
CFLAGS=$(CFLAGS)/DEFINE=DISKIMAGE
ods2i$(OBJ) : ods2.c compat.h diskio.h sysmsg.h phyio.h ssdef.h descrip.h access.h rms.h
VAXCRTL.OPT :
@ open/write tmp $(MMS$TARGET)

View File

@ -136,12 +136,15 @@ int name_match(char *spec,int spec_len,char *dirent,int dirent_len)
register char sch = *name;
if (sch != '*') {
register char ech = *entry;
if (sch != ech) if (toupper(sch) != toupper(ech))
if (sch == '%') {
percent = MAT_NE;
} else {
break;
}
if (sch != ech) {
if (toupper(sch) != toupper(ech)) {
if (sch == '%') {
percent = MAT_NE;
} else {
break;
}
}
}
} else {
break;
}
@ -294,7 +297,8 @@ unsigned insert_ent(struct FCB * fcb,unsigned eofblk,unsigned curblk,
struct VIOC *newvioc;
unsigned newblk = eofblk + 1;
direct_splits++;
printf("Splitting record... %d %d\n",dr,de);
printf("Splitting record... %s %u,%u,%u,%u\n", dr->dir$name,de->dir$fid.fid$w_num,
de->dir$fid.fid$w_seq,de->dir$fid.fid$b_rvn,de->dir$fid.fid$b_nmx);
if (newblk > fcb->hiblock) {
printf("I can't extend a directory yet!!\n");
exit(0);
@ -353,7 +357,8 @@ unsigned insert_ent(struct FCB * fcb,unsigned eofblk,unsigned curblk,
register unsigned reclen = (dr->dir$namecount +
sizeof(struct dir$rec)) & ~1;
register struct dir$rec *nbr = (struct dir$rec *) newbuf;
printf("Super split %d %d\n",dr,de);
printf("Super split %s %u,%u,%u,%u\n", dr->dir$name,de->dir$fid.fid$w_num,
de->dir$fid.fid$w_seq,de->dir$fid.fid$b_rvn,de->dir$fid.fid$b_nmx);
memcpy(newbuf,buffer,reclen);
memcpy(newbuf + reclen,de,((char *) nr - (char *) de) + 2);
nbr->dir$size = VMSWORD(reclen + ((char *) nr - (char *) de) - 2);

218
extracters/ods2/diskio.c Normal file
View File

@ -0,0 +1,218 @@
/* diskio.c - ANSI C Disk I/O - for .ISO and simulator disks */
/* Timothe Litt Feb 2016
*
* This is part of ODS2 written by Paul Nankervis,
* email address: Paulnank@au1.ibm.com
*
* ODS2 is distributed freely for all members of the
* VMS community to use. However all derived works
* must maintain comments in their source to acknowledge
* the contibution of the original author.
*/
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#if __FILE_OFFSET_BITS == 64
# undef fseek
# ifdef _WIN32
# define fseek _fseeki64
# undef off_t
# define off_t __int64
# else
# define fseek fseeko
# endif
#endif
#include "compat.h"
#include "phyio.h"
#include "ssdef.h"
unsigned init_count = 0;
unsigned read_count = 0;
unsigned write_count = 0;
#define MAX_DEVS 64
FILE *handles[1+MAX_DEVS];
void phyio_show(void)
{
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
init_count,read_count,write_count);
}
void phyio_help(FILE *fp ) {
fprintf( fp, "Specify the file containing a disk image to be mounted.\n" );
fprintf( fp, "E.g. mount mydisk.iso\n" );
fprintf( fp, "A drive letter will be assigned to the image. Use that\n" );
fprintf( fp, "letter to refer to the VMS volume in subsequent commands\n" );
return;
}
static char *diskfiles[26];
static char drives[26][4];
/* Deeper code assumes that the device name is terminated by ':' and that this is
* the physical device. To keep it happy, map the next free drive letter to this
* filename, and use it to identify the device. phyio_init will check the mapping table
* to get the actual filename to open.
*/
char *diskio_mapfile( const char *filename, int options ) {
int l, L = -1;
for( l = 0; l < 26; l++ ) {
if( diskfiles[l] == NULL && L < 0 ) L = l;
if( diskfiles[l] && strcmp( diskfiles[l], filename ) == 0 ) {
printf( "%s is already mounted as drive %s\n", filename, drives[l] );
return NULL;
}
}
if( L < 0 ) {
printf( "No free drive letters for %s\n", filename );
return 0;
}
snprintf(drives[L], 3, "%c:", L + 'A');
drives[L][3] = options;
free(diskfiles[L]);
diskfiles[L] = (char *) malloc( (l = strlen(filename) + 1) );
snprintf( diskfiles[L], l, "%s", filename );
printf( "%s assigned to %s\n", drives[L], diskfiles[L] );
return drives[L];
}
int diskio_showdrives( void ) {
int n = 0;
int l;
size_t max;
int sts = 1;
max = sizeof( "Filename" ) -1;
for( l = 0; l < 26; l++ ) {
if( diskfiles[l] != NULL && strlen(diskfiles[l]) > max )
max = strlen(diskfiles[l]);
}
for( l = 0; l < 26; l++ ) {
if( diskfiles[l] == NULL )
continue;
if( !n++ ) {
printf( "Drv Sts Filename\n"
"--- --- " );
while( max-- ) fputc( '-', stdout );
printf( "\n" );
}
printf( " %s %-3s %s\n", drives[l], (drives[l][3] &1)? "RW": "RO", diskfiles[l] );
}
if( n == 0 ) {
printf( "No drives assigned\n" );
sts = 0;
}
return sts;
}
int diskio_unmapdrive( const char *drive ) {
if( diskfiles[drive[0]-'A'] == NULL ) {
return 0;
}
free(diskfiles[drive[0]-'A']);
diskfiles[drive[0]-'A'] = NULL;
return 1;
}
unsigned phyio_init( int devlen,char *devnam,unsigned *handle,struct phyio_info *info ) {
size_t hi;
int i;
UNUSED ( devlen );
info->status = 0;
info->sectors = 0;
info->sectorsize = 0;
*handle = ~0;
for( hi = 1; hi < MAX_DEVS && handles[hi] != NULL; hi++ )
;
if( hi >= MAX_DEVS ) {
return SS$_IVCHAN;
}
if( (devnam[0] < 'A' || devnam[0] > 'Z') || devnam[1] != ':' ) {
printf ( "%s is not a mapped device name\n", devnam );
return SS$_NOSUCHFILE;
}
i = *devnam - 'A';
if( diskfiles[i] == NULL ) {
printf ( "%s is not a mapped device name\n", devnam );
return SS$_NOSUCHFILE;
}
handles[hi] = openf ( diskfiles[i], (drives[i][3] & 1)? "rb+": "rb" );
if( handles[hi] == NULL ) {
perror( diskfiles[i] );
return SS$_NOSUCHFILE;
}
++init_count;
*handle = hi;
return SS$_NORMAL;
}
unsigned phyio_close(unsigned handle) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
return SS$_NOIOCHAN;
}
fclose ( handles[handle] );
handles[handle] = NULL;
return SS$_NORMAL;
}
unsigned phyio_read( unsigned handle,unsigned block,unsigned length,char *buffer ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
return SS$_IVCHAN;
}
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
perror( "seek" );
return SS$_DATACHECK;
}
if( fread( buffer, 1, length, handles[handle] ) != length ) {
perror( "read" );
return SS$_DATACHECK;
}
++read_count;
return SS$_NORMAL;
}
unsigned phyio_write( unsigned handle,unsigned block,unsigned length,char *buffer ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
return SS$_IVCHAN;
}
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
perror( "seek" );
return SS$_DATACHECK;
}
abort();
if( fwrite( buffer, 1, length, handles[handle] ) != length ) {
perror( "write" );
return SS$_DATACHECK;
}
++write_count;
return SS$_NORMAL;
}

43
extracters/ods2/diskio.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef DISKIO_H
#define DISKIO_H
/* diskio.h - ANSI C Disk I/O - for .ISO and simulator disks */
/* Timothe Litt Feb 2016
*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
ODS2 is distributed freely for all members of the
VMS community to use. However all derived works
must maintain comments in their source to acknowledge
the contibution of the original author.
*/
/* To set up physical I/O for a new system a group of phyio
routines need to be set up. They are:-
phyio_show() which doesn't need to do anything - but
it would generally print some statistics
about the other phyio calls.
phyio_init() to prepare a device for use by future
read/write calls. The device name would usually
map to a local device - for example rra: to /dev/rra
on a Unix system. The call needs to return a handle
(channel, file handle, reference number...) for
future reference, and optionally some device
information.
phyio_read() will return a specified number of bytes into a
buffer from the start of a 512 byte block on the
device referred to by the handle.
phyio_write() will write a number of bytes out to a 512 byte block
address on a device.
*/
char *diskio_mapfile( const char *filename, int options );
int diskio_unmapdrive( const char *drive );
int diskio_showdrives( void );
#endif

View File

@ -0,0 +1,95 @@
# Generic makefile for ods2
#
# See makefile.<osname>, which normally includes it
#
# If your make doesn't support include, these can be
# specified manually, for example:
# make CC=gcc "CCFLAGS=-O4 -f" OBJ=.o \
# PHYSIO=phyunix DEFS=-DUSE_READLINE LDFLAGS=-lreadline
#
# or just combine the files you need with an editor.
#
# ###
# OS-Specific defines
# These variables are available
# Other defines = "-DDEBUG_BUILD" "-D_FILE_OFFSET_BITS=32"
#DEFS =
# Libraries, e.g. -lreadline
#LDFLAGS =
# Object file suffix
#OBJ = .o
# Physical IO module
#PHYSIO = phyunix
# Extra physical IO headers
#PHYSIOH =
# #####################################################
all : ods2 ods2i
OBJS = $(ODS2_OBJS) $(ODS2I_OBJS)
COMMON_OBJS = \
access$(OBJ) \
cache$(OBJ) \
compat$(OBJ)\
device$(OBJ) \
direct$(OBJ) \
rms$(OBJ) \
sysmsg$(OBJ) \
update$(OBJ) \
vmstime$(OBJ)
ODS2_OBJS = ods2$(OBJ) $(COMMON_OBJS) $(PHYSIO)$(OBJ)
ODS2I_OBJS = ods2i$(OBJ) $(COMMON_OBJS) diskio$(OBJ)
ods2 : $(ODS2_OBJS) $(LIBS)
$(CC) $(CCFLAGS) -o ods2 $(ODS2_OBJS) $(LDFLAGS)
ods2i : $(ODS2I_OBJS)
$(CC) $(CCFLAGS) -o ods2i $(ODS2I_OBJS) $(LDFLAGS)
access$(OBJ) : access.c ssdef.h access.h phyio.h compat.h
$(CC) -c $(CCFLAGS) $(DEFS) access.c
cache$(OBJ) : cache.c cache.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) cache.c
compat$(OBJ) : compat.c compat.h
$(CC) -c $(CCFLAGS) $(DEFS) compat.c
device$(OBJ) : device.c ssdef.h access.h phyio.h
$(CC) -c $(CCFLAGS) $(DEFS) device.c
direct$(OBJ) : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) direct.c
diskio$(OBJ) : diskio.c diskio.h compat.h phyio.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) diskio.c
ods2$(OBJ) : ods2.c compat.h sysmsg.h phyio.h ssdef.h descrip.h access.h rms.h version.h
$(CC) -c $(CCFLAGS) $(VERSION) $(DEFS) ods2.c
ods2i$(OBJ) : ods2.c compat.h diskio.h sysmsg.h phyio.h ssdef.h descrip.h access.h rms.h version.h
$(CC) -c $(CCFLAGS) $(DEFS) -DDISKIMAGE -o ods2i$(OBJ) ods2.c
$(PHYSIO)$(OBJ) : $(PHYSIO).c phyio.h ssdef.h compat.h $(PHYSIOH)
$(CC) -c $(CCFLAGS) $(DEFS) $(PHYSIO).c
rms$(OBJ) : rms.c rms.h compat.h direct.h access.h fibdef.h descrip.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) rms.c
sysmsg$(OBJ) : sysmsg.c sysmsg.h rms.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) sysmsg.c
update$(OBJ) : update.c ssdef.h access.h
$(CC) -c $(CCFLAGS) $(DEFS) update.c
vmstime$(OBJ) : vmstime.c vmstime.h
$(CC) -c $(CCFLAGS) $(DEFS) vmstime.c

View File

@ -1,53 +1,23 @@
# Makefile for Windows NT
#
CCFLAGS = "-Oxs"
DEFS = "-DVERSION=\"v1.3\""
# For the direct SCSI module
#DEFS = -DUSE_WNASPI32
#LDFLAGS = wnaspi32.lib
#PHYSIOH = wnaspi32.h scsidefs.h
#LIBS = wnaspi32.lib
all : ods2
OBJ = .OBJ
PHYSIO = phynt
OBJS = ods2.obj \
rms.obj \
direct.obj \
update.obj \
access.obj \
device.obj \
phynt.obj \
cache.obj \
vmstime.obj
ods2 : $(OBJS) wnaspi32.lib
$(CC) $(CCFLAGS) -oods2 $(OBJS) wnaspi32.lib
vmstime.obj : vmstime.c vmstime.h
$(CC) -c $(CCFLAGS) $(DEFS) vmstime.c
cache.obj : cache.c cache.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) cache.c
phynt.obj : phynt.c phyio.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) phynt.c
device.obj : device.c ssdef.h access.h phyio.h
$(CC) -c $(CCFLAGS) $(DEFS) device.c
access.obj : access.c ssdef.h access.h phyio.h
$(CC) -c $(CCFLAGS) $(DEFS) access.c
update.obj : update.c ssdef.h access.h
$(CC) -c $(CCFLAGS) $(DEFS) update.c
direct.obj : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) direct.c
rms.obj : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
$(CC) -c $(CCFLAGS) $(DEFS) rms.c
ods2.obj : ods2.c ssdef.h descrip.h access.h rms.h
$(CC) -c $(CCFLAGS) $(DEFS) ods2.c
include makefile.generic
wnaspi32.lib : wnaspi32.def
LIB /DEF:WNASPI32.DEF /MACHINE:IX86
clean:
del *.obj
del *.exe
del $(OBJS)
del ods2.exe

View File

@ -1,36 +1,22 @@
# Makefile for solaris OS
CCFLAGS = "-g"
# Use gcc
DEFS = "-DVERSION=\"v1.3\""
CC=gcc
all : ods2
CCFLAGS = -O4 -g
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
gcc $(CCFLAGS) -oods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
DEFS = -DUSE_READLINE
LDFLAGS = -lreadline
vmstime.o : vmstime.c vmstime.h
gcc -c $(CCFLAGS) $(DEFS) vmstime.c
# Object file extension
OBJ = .o
cache.o : cache.c cache.h ssdef.h
gcc -c $(CCFLAGS) $(DEFS) cache.c
# Physical I/O module
PHYSIO = phyunix
PHYSIOH =
phyunix.o : phyunix.c phyio.h ssdef.h
gcc -c $(CCFLAGS) $(DEFS) phyunix.c
include makefile.generic
device.o : device.c ssdef.h access.h phyio.h
gcc -c $(CCFLAGS) $(DEFS) device.c
access.o : access.c ssdef.h access.h phyio.h
gcc -c $(CCFLAGS) $(DEFS) access.c
update.o : update.c ssdef.h access.h
gcc -c $(CCFLAGS) $(DEFS) update.c
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
gcc -c $(CCFLAGS) $(DEFS) direct.c
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
gcc -c $(CCFLAGS) $(DEFS) rms.c
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
gcc -c $(CCFLAGS) $(DEFS) ods2.c
clean:
rm -f ods2 $(OBJS)

View File

@ -1,34 +1,19 @@
# Makefile for Tru64 (DEC/OSF1)
#
CCFLAGS = "-g"
CCFLAGS = -O4 -g
all : ods2
# DEFS = -DUSE_READLINE
# LDFLAGS = -lreadline
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
cc $(CCFLAGS) -o ods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
# Object file extension
OBJ = .o
vmstime.o : vmstime.c vmstime.h
cc -c $(CCFLAGS) $(DEFS) vmstime.c
# Physical I/O module
PHYSIO = phyunix
PHYSIOH =
cache.o : cache.c cache.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) cache.c
include makefile.generic
phyunix.o : phyunix.c phyio.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) phyunix.c
device.o : device.c ssdef.h access.h phyio.h
cc -c $(CCFLAGS) $(DEFS) device.c
access.o : access.c ssdef.h access.h phyio.h
cc -c $(CCFLAGS) $(DEFS) access.c
update.o : update.c ssdef.h access.h
cc -c $(CCFLAGS) $(DEFS) update.c
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) direct.c
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) rms.c
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
cc -c $(CCFLAGS) $(DEFS) ods2.c
clean:
rm -f ods2 $(OBJS)

View File

@ -1,36 +1,24 @@
# Makefile for most Unix distributions
#
CCFLAGS = -O4
CCFLAGS = -O4 -g
#-O0 -g -DUSE_READLINE -Wall -pedantic
# Extra warns about $ in identifiers...
# -Wextra
DEFS = "-DVERSION=\"v1.3\""
# Include readline support
all : ods2
DEFS = -DUSE_READLINE
LDFLAGS = -lreadline
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
cc $(CCFLAGS) -o ods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
# Object file extension
OBJ = .o
vmstime.o : vmstime.c vmstime.h
cc -c $(CCFLAGS) $(DEFS) vmstime.c
# Physical I/O module
PHYSIO = phyunix
PHYSIOH =
cache.o : cache.c cache.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) cache.c
include makefile.generic
phyunix.o : phyunix.c phyio.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) phyunix.c
device.o : device.c ssdef.h access.h phyio.h
cc -c $(CCFLAGS) $(DEFS) device.c
access.o : access.c ssdef.h access.h phyio.h
cc -c $(CCFLAGS) $(DEFS) access.c
update.o : update.c ssdef.h access.h
cc -c $(CCFLAGS) $(DEFS) update.c
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) direct.c
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
cc -c $(CCFLAGS) $(DEFS) rms.c
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
cc -c $(CCFLAGS) $(DEFS) ods2.c
clean:
rm -f ods2 ods2i $(OBJS)

File diff suppressed because it is too large Load Diff

View File

@ -1,895 +0,0 @@
/* ODS2.C v1.2 Mainline ODS2 program */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
ODS2 is distributed freely for all members of the
VMS community to use. However all derived works
must maintain comments in their source to acknowledge
the contibution of the original author.
The modules in ODS2 are:-
ACCESS.C Routines for accessing ODS2 disks
CACHE.C Routines for managing memory cache
DEVICE.C Routines to maintain device information
DIRECT.C Routines for handling directories
ODS2.C The mainline program
PHYVMS.C Routine to perform physical I/O
RMS.C Routines to handle RMS structures
VMSTIME.C Routines to handle VMS times
On non-VMS platforms PHYVMS.C should be replaced as follows:-
OS/2 PHYOS2.C
Windows 95/NT PHYNT.C
For example under OS/2 the program is compiled using the GCC
compiler with the single command:-
gcc -fdollars-in-identifiers ods2.c,rms.c,direct.c,
access.c,device.c,cache.c,phyos2.c,vmstime.c
*/
/* This version will compile and run using normal VMS I/O by
defining VMSIO
*/
/* This is the top level set of routines. It is fairly
simple minded asking the user for a command, doing some
primitive command parsing, and then calling a set of routines
to perform whatever function is required (for example COPY).
Some routines are implemented in different ways to test the
underlying routines - for example TYPE is implemented without
a NAM block meaning that it cannot support wildcards...
(sorry! - could be easily fixed though!)
*/
#define DEBUGx on
#define VMSIOx on
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "descrip.h"
#include "ssdef.h"
#ifdef VMSIO
#include <starlet.h>
#include <rms.h>
unsigned sys$setddir();
#else
#include "rms.h"
#include "access.h"
#endif
#define PRINT_ATTR (FAB$M_CR | FAB$M_PRN | FAB$M_FTN)
/* keycomp: routine to compare parameter to a keyword - case insensitive! */
int keycomp(char *param,char *keywrd)
{
while (*param != '\0') {
if (tolower(*param++) != *keywrd++) return 0;
}
return 1;
}
/* checkquals: routine to find a qualifer in a list of possible values */
int checkquals(char *qualset[],int qualc,char *qualv[])
{
int result = 0;
while (qualc-- > 0) {
int i = 0;
while (qualset[i] != NULL) {
if (keycomp(qualv[qualc],qualset[i])) {
result |= 1 << i;
i = -1;
break;
}
i++;
}
if (i >= 0) printf("%%ODS2-W-ILLQUAL, Unknown qualifer '%s' ignored\n",qualv[qualc]);
}
return result;
}
/* dir: a directory routine */
char *dirquals[] = {"date","file","size",NULL};
unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
{
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
int sts,options;
int filecount = 0;
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
struct XABDAT dat = cc$rms_xabdat;
struct XABFHC fhc = cc$rms_xabfhc;
nam.nam$l_esa = res;
nam.nam$b_ess = NAM$C_MAXRSS;
fab.fab$l_nam = &nam;
fab.fab$l_xab = &dat;
dat.xab$l_nxt = &fhc;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
fab.fab$l_dna = "*.*;*";
fab.fab$b_dns = strlen(fab.fab$l_dna);
options = checkquals(dirquals,qualc,qualv);
sts = sys$parse(&fab);
if (sts & 1) {
char dir[NAM$C_MAXRSS + 1];
int namelen;
int dirlen = 0;
int dirfiles = 0,dircount = 0;
int dirblocks = 0,totblocks = 0;
int printcol = 0;
#ifdef DEBUG
res[nam.nam$b_esl] = '\0';
printf("Parse: %s\n",res);
#endif
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ((sts = sys$search(&fab)) & 1) {
if (dirlen != nam.nam$b_dev + nam.nam$b_dir ||
memcmp(rsa,dir,nam.nam$b_dev + nam.nam$b_dir) != 0) {
if (dirfiles > 0) {
if (printcol > 0) printf("\n");
printf("\nTotal of %d file%s",dirfiles,(dirfiles == 1 ? "" : "s"));
if (options & 4) {
printf(", %d block%s.\n",dirblocks,(dirblocks == 1 ? "" : "s"));
} else {
fputs(".\n",stdout);
}
}
dirlen = nam.nam$b_dev + nam.nam$b_dir;
memcpy(dir,rsa,dirlen);
dir[dirlen] = '\0';
printf("\nDirectory %s\n\n",dir);
filecount += dirfiles;
totblocks += dirblocks;
dircount++;
dirfiles = 0;
dirblocks = 0;
printcol = 0;
}
rsa[nam.nam$b_rsl] = '\0';
namelen = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
if (options == 0) {
if (printcol > 0) {
int newcol = (printcol + 20) / 20 * 20;
if (newcol + namelen >= 80) {
fputs("\n",stdout);
printcol = 0;
} else {
printf("%*s",newcol - printcol," ");
printcol = newcol;
}
}
fputs(rsa + dirlen,stdout);
printcol += namelen;
} else {
if (namelen > 18) {
printf("%s\n ",rsa + dirlen);
} else {
printf("%-19s",rsa + dirlen);
}
sts = sys$open(&fab);
if ((sts & 1) == 0) {
printf("Open error: %d\n",sts);
} else {
sts = sys$close(&fab);
if (options & 2) {
char fileid[100];
sprintf(fileid,"(%d,%d,%d)",
(nam.nam$b_fid_nmx << 16) | nam.nam$w_fid_num,
nam.nam$w_fid_seq,nam.nam$b_fid_rvn);
printf(" %-22s",fileid);
}
if (options & 4) {
unsigned filesize = fhc.xab$l_ebk;
if (fhc.xab$w_ffb == 0) filesize--;
printf("%9d",filesize);
dirblocks += filesize;
}
if (options & 1) {
char tim[24];
struct dsc$descriptor timdsc;
timdsc.dsc$w_length = 23;
timdsc.dsc$a_pointer = tim;
sts = sys$asctim(0,&timdsc,&dat.xab$q_cdt,0);
if ((sts & 1) == 0) printf("Asctim error: %d\n",sts);
tim[23] = '\0';
printf(" %s",tim);
}
printf("\n");
}
}
dirfiles++;
}
if (sts == RMS$_NMF) sts = 1;
if (printcol > 0) printf("\n");
if (dirfiles > 0) {
printf("\nTotal of %d file%s",dirfiles,(dirfiles == 1 ? "" : "s"));
if (options & 4) {
printf(", %d block%s.\n",dirblocks,(dirblocks == 1 ? "" : "s"));
} else {
fputs(".\n",stdout);
}
filecount += dirfiles;
totblocks += dirblocks;
if (dircount > 1) {
printf("\nGrand total of %d director%s, %d file%s",
dircount,(dircount == 1 ? "y" : "ies"),
filecount,(filecount == 1 ? "" : "s"));
if (options & 4) {
printf(", %d block%s.\n",totblocks,(totblocks == 1 ? "" : "s"));
} else {
fputs(".\n",stdout);
}
}
}
}
if (sts & 1) {
if (filecount < 1) printf("%%DIRECT-W-NOFILES, no files found\n");
} else {
printf("%%DIR-E-ERROR Status: %d\n",sts);
}
return sts;
}
/* copy: a file copy routine */
#define MAXREC 32767
unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
int filecount = 0;
nam.nam$l_esa = res;
nam.nam$b_ess = NAM$C_MAXRSS;
fab.fab$l_nam = &nam;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
sts = sys$parse(&fab);
if (sts & 1) {
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ((sts = sys$search(&fab)) & 1) {
sts = sys$open(&fab);
if ((sts & 1) == 0) {
printf("%%COPY-F-OPENFAIL, Open error: %d\n",sts);
perror("-COPY-F-ERR ");
} else {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
if ((sts = sys$connect(&rab)) & 1) {
FILE *tof;
char name[NAM$C_MAXRSS + 1];
unsigned records = 0;
{
char *out = name,*inp = argv[2];
int dot = 0;
while (*inp != '\0') {
if (*inp == '*') {
inp++;
if (dot) {
memcpy(out,nam.nam$l_type + 1,nam.nam$b_type - 1);
out += nam.nam$b_type - 1;
} else {
unsigned length = nam.nam$b_name;
if (*inp == '\0') length += nam.nam$b_type;
memcpy(out,nam.nam$l_name,length);
out += length;
}
} else {
if (*inp == '.') {
dot = 1;
} else {
if (strchr(":]\\/",*inp)) dot = 0;
}
*out++ = *inp++;
}
}
*out++ = '\0';
}
tof = fopen(name,"w");
if (tof == NULL) {
printf("%%COPY-F-OPENOUT, Could not open %s\n",name);
perror("-COPY-F-ERR ");
} else {
char rec[MAXREC + 2];
filecount++;
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while ((sts = sys$get(&rab)) & 1) {
unsigned rsz = rab.rab$w_rsz;
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
if (fwrite(rec,rsz,1,tof) == 1) {
records++;
} else {
printf("%%COPY-F- fwrite error!!\n");
perror("-COPY-F-ERR ");
break;
}
}
if (fclose(tof)) {
printf("%%COPY-F- fclose error!!\n");
perror("-COPY-F-ERR ");
}
}
sys$disconnect(&rab);
if (sts == RMS$_EOF) {
rsa[nam.nam$b_rsl] = '\0';
printf("%%COPY-S-COPIED, %s copied to %s (%d record%s)\n",
rsa,name,records,(records == 1 ? "" : "s"));
sts = 1;
}
}
sys$close(&fab);
}
}
if (sts == RMS$_NMF) sts = 1;
}
if (sts & 1) {
if (filecount > 0) printf("%%COPY-S-NEWFILES, %d file%s created\n",
filecount,(filecount == 1 ? "" : "s"));
} else {
printf("%%COPY-F-ERROR Status: %d\n",sts);
}
return sts;
}
/* diff: a simple file difference routine */
unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
struct FAB fab = cc$rms_fab;
FILE *tof;
int records = 0;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
tof = fopen(argv[2],"r");
if (tof == NULL) {
printf("Could not open file %s\n",argv[1]);
sts = 0;
} else {
if ((sts = sys$open(&fab)) & 1) {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
if ((sts = sys$connect(&rab)) & 1) {
char rec[MAXREC + 2],cpy[MAXREC + 1];
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while ((sts = sys$get(&rab)) & 1) {
strcpy(rec + rab.rab$w_rsz,"\n");
fgets(cpy,MAXREC,tof);
if (strcmp(rec,cpy) != 0) {
printf("%%DIFF-F-DIFFERENT Files are different!\n");
sts = 4;
break;
} else {
records++;
}
}
sys$disconnect(&rab);
}
sys$close(&fab);
}
fclose(tof);
if (sts == RMS$_EOF) sts = 1;
}
if (sts & 1) {
printf("%%DIFF-I-Compared %d records\n",records);
} else {
printf("%%DIFF-F-Error %d in difference\n",sts);
}
return sts;
}
/* typ: a file TYPE routine */
unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
int records = 0;
struct FAB fab = cc$rms_fab;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
if ((sts = sys$open(&fab)) & 1) {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
if ((sts = sys$connect(&rab)) & 1) {
char rec[MAXREC + 2];
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while ((sts = sys$get(&rab)) & 1) {
unsigned rsz = rab.rab$w_rsz;
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
rec[rsz++] = '\0';
fputs(rec,stdout);
records++;
}
sys$disconnect(&rab);
}
sys$close(&fab);
if (sts == RMS$_EOF) sts = 1;
}
if ((sts & 1) == 0) {
printf("%%TYPE-F-ERROR Status: %d\n",sts);
}
return sts;
}
/* search: a simple file search routine */
unsigned search(int argc,char *argv[],int qualc,char *qualv[])
{
int sts = 0;
int filecount = 0;
int findcount = 0;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
register char *searstr = argv[2];
register char firstch = tolower(*searstr++);
register char *searend = searstr + strlen(searstr);
{
char *str = searstr;
while (str < searend) {
*str = tolower(*str);
str++;
}
}
nam = cc$rms_nam;
fab = cc$rms_fab;
nam.nam$l_esa = res;
nam.nam$b_ess = NAM$C_MAXRSS;
fab.fab$l_nam = &nam;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
fab.fab$l_dna = "";
fab.fab$b_dns = strlen(fab.fab$l_dna);
sts = sys$parse(&fab);
if (sts & 1) {
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ((sts = sys$search(&fab)) & 1) {
sts = sys$open(&fab);
if ((sts & 1) == 0) {
printf("%%SEARCH-F-OPENFAIL, Open error: %d\n",sts);
} else {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
if ((sts = sys$connect(&rab)) & 1) {
int printname = 1;
char rec[MAXREC + 2];
filecount++;
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while ((sts = sys$get(&rab)) & 1) {
register char *strng = rec;
register char *strngend = strng + (rab.rab$w_rsz - (searend - searstr));
while (strng < strngend) {
register char ch = *strng++;
if (ch == firstch || (ch >= 'A' && ch <= 'Z' && ch + 32 == firstch)) {
register char *str = strng;
register char *cmp = searstr;
while (cmp < searend) {
register char ch2 = *str++;
ch = *cmp;
if (ch2 != ch && (ch2 < 'A' || ch2 > 'Z' || ch2 + 32 != ch)) break;
cmp++;
}
if (cmp >= searend) {
findcount++;
rec[rab.rab$w_rsz] = '\0';
if (printname) {
rsa[nam.nam$b_rsl] = '\0';
printf("\n******************************\n%s\n\n",rsa);
printname = 0;
}
fputs(rec,stdout);
if (fab.fab$b_rat & PRINT_ATTR) fputc('\n',stdout);
break;
}
}
}
}
sys$disconnect(&rab);
}
if (sts == SS$_NOTINSTALL) {
printf("%%SEARCH-W-NOIMPLEM, file operation not implemented\n");
sts = 1;
}
sys$close(&fab);
}
}
if (sts == RMS$_NMF || sts == RMS$_FNF) sts = 1;
}
if (sts & 1) {
if (filecount < 1) {
printf("%%SEARCH-W-NOFILES, no files found\n");
} else {
if (findcount < 1) printf("%%SEARCH-I-NOMATCHES, no strings matched\n");
}
} else {
printf("%%SEARCH-F-ERROR Status: %d\n",sts);
}
return sts;
}
/* del: you don't want to know! */
unsigned del(int argc,char *argv[],int qualc,char *qualv[])
{
int sts = 0;
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
int filecount = 0;
nam.nam$l_esa = res;
nam.nam$b_ess = NAM$C_MAXRSS;
fab.fab$l_nam = &nam;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
printf("WARNING! This bit is broken - volume corruption VERY likely!\n");
sts = sys$parse(&fab);
if (sts & 1) {
if (nam.nam$b_ver < 2) {
printf("%%DELETE-F-NOVER, you must specify a version!!\n");
} else {
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ((sts = sys$search(&fab)) & 1) {
sts = sys$erase(&fab);
if ((sts & 1) == 0) {
printf("%%DELETE-F-DELERR, Delete error: %d\n",sts);
} else {
filecount++;
rsa[nam.nam$b_rsl] = '\0';
printf("%%DELETE-I-DELETED, Deleted %s\n",rsa);
}
}
if (sts == RMS$_NMF) sts = 1;
}
if (sts & 1) {
if (filecount < 1) {
printf("%%DELETE-W-NOFILES, no files deleted\n");
}
} else {
printf("%%DELETE-F-ERROR Status: %d\n",sts);
}
}
return sts;
}
/* show: the show command */
unsigned show(int argc,char *argv[],int qualc,char *qualv[])
{
unsigned sts = 1;
if (keycomp(argv[1],"default")) {
unsigned short curlen;
char curdir[NAM$C_MAXRSS + 1];
struct dsc$descriptor curdsc;
curdsc.dsc$w_length = NAM$C_MAXRSS;
curdsc.dsc$a_pointer = curdir;
if ((sts = sys$setddir(NULL,&curlen,&curdsc)) & 1) {
curdir[curlen] = '\0';
printf(" %s\n",curdir);
} else {
printf("Error %d getting default\n",sts);
}
} else {
if (keycomp(argv[1],"time")) {
char timstr[24];
unsigned short timlen;
struct dsc$descriptor timdsc;
timdsc.dsc$w_length = 23;
timdsc.dsc$a_pointer = timstr;
sys$asctim(&timlen,&timdsc,NULL,0);
timstr[timlen] = '\0';
printf(" %s\n",timstr);
} else {
printf("%%SHOW-W-WHAT '%s'?\n",argv[1]);
}
}
return sts;
}
/* set: the set command */
unsigned set(int argc,char *argv[],int qualc,char *qualv[])
{
unsigned sts = 1;
if (keycomp(argv[1],"default")) {
struct dsc$descriptor defdsc;
defdsc.dsc$a_pointer = argv[2];
defdsc.dsc$w_length = strlen(defdsc.dsc$a_pointer);
if (((sts = sys$setddir(&defdsc,NULL,NULL)) & 1) == 0) {
printf("Error %d setting default to %s\n",sts,argv[2]);
}
} else {
printf("%%SET-W-WHAT '%s'?\n",argv[1]);
}
return sts;
}
#ifndef VMSIO
/* The bits we need when we don't have real VMS routines underneath... */
unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[])
{
struct DEV *dev;
register int sts = device_lookup(strlen(argv[1]),argv[1],0,&dev);
if (sts & 1) {
if (dev->vcb != NULL) {
sts = dismount(dev->vcb);
} else {
sts = SS$_DEVNOTMOUNT;
}
}
if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %d\n",sts);
return sts;
}
char *mouquals[] = {"write",NULL};
unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
{
char *dev = argv[1];
char *lab = argv[2];
int sts = 1,devices = 0;
char *devs[100],*labs[100];
int options = checkquals(mouquals,qualc,qualv);
while (*lab != '\0') {
labs[devices++] = lab;
while (*lab != ',' && *lab != '\0') lab++;
if (*lab != '\0') {
*lab++ = '\0';
} else {
break;
}
}
devices = 0;
while (*dev != '\0') {
devs[devices++] = dev;
while (*dev != ',' && *dev != '\0') dev++;
if (*dev != '\0') {
*dev++ = '\0';
} else {
break;
}
}
if (devices > 0) {
unsigned i;
struct VCB *vcb;
sts = mount(options,devices,devs,labs,&vcb);
if (sts & 1) {
for (i = 0; i < vcb->devices; i++)
if (vcb->vcbdev[i].dev != NULL)
printf("%%MOUNT-I-MOUNTED, Volume %12.12s mounted on %s\n",
vcb->vcbdev[i].home.hm2$t_volname,vcb->vcbdev[i].dev->devnam);
} else {
printf("Mount failed with %d\n",sts);
}
}
return sts;
}
void directshow(void);
void phyio_show(void);
/* statis: print some simple statistics */
unsigned statis(int argc,char *argv[],int qualc,char *qualv[])
{
printf("Statistics:-\n");
directshow();
cacheshow();
phyio_show();
return 1;
}
/* dump: a simple debugging aid */
unsigned dump(int argc,char *argv[],int qualc,char *qualv[])
{
printf("Cache Dump:-\n");
cachedump();
return 1;
}
#endif
/* help: a routine to print a pre-prepared help text... */
unsigned help(int argc,char *argv[],int qualc,char *qualv[])
{
printf("\nODS2 v1.2\n");
printf(" Please send problems/comments to Paulnank@au1.ibm.com\n");
printf(" Commands are:\n");
printf(" copy difference directory exit\n");
printf(" mount show_default show_time search\n");
printf(" set_default type\n");
printf(" Example:-\n $ mount e:\n");
printf(" $ search e:[vms$common.decc*...]*.h rms$_wld\n");
printf(" $ set default e:[sys0.sysmgr]\n");
printf(" $ copy *.com;-1 c:\\*.*\n");
printf(" $ directory/file/size/date [-.sys*...].%%\n");
printf(" $ exit\n");
return 1;
}
/* informaion about the commands we know... */
struct CMDSET {
char *name;
unsigned (*proc) (int argc,char *argv[],int qualc,char *qualv[]);
int minlen;
int minargs;
int maxargs;
int maxquals;
} cmdset[] = {
{
"copy",copy,3,3,3,0
},
{
"delete",del,3,2,2,0
},
{
"difference",diff,3,3,3,0
},
{
"directory",dir,3,1,2,6
},
{
"exit",NULL,2,0,0,0
},
{
"help",help,2,1,1,0
},
{
"show",show,2,2,2,0
},
{
"search",search,3,3,3,0
},
{
"set",set,3,2,3,0
},
#ifndef VMSIO
{
"dismount",dodismount,3,2,2,0
},
{
"mount",domount,3,2,3,2
},
{
"statistics",statis,3,1,1,0
},
{
"dump",dump,3,1,1,0
},
#endif
{
"type",typ,3,2,2,0
},
{
NULL,NULL,0,0,0,0
}
};
/* cmdexecute: identify and execute a command */
int cmdexecute(int argc,char *argv[],int qualc,char *qualv[])
{
char *ptr = argv[0];
struct CMDSET *cmd = cmdset;
unsigned cmdsiz = strlen(ptr);
while (*ptr != '\0') {
*ptr = tolower(*ptr);
ptr++;
}
while (cmd->name != NULL) {
if (cmdsiz >= cmd->minlen && cmdsiz <= strlen(cmd->name)) {
if (keycomp(argv[0],cmd->name)) {
if (cmd->proc == NULL) {
return 0;
} else {
if (argc < cmd->minargs || argc > cmd->maxargs) {
printf("%%ODS2-E-PARAMS, Incorrect number of command parameters\n");
} else {
if (qualc > cmd->maxquals) {
printf("%%ODS2-E-QUALS, Too many command qualifiers\n");
} else {
(*cmd->proc) (argc,argv,qualc,qualv);
#ifndef VMSIO
cacheflush();
#endif
}
}
return 1;
}
}
}
cmd++;
}
printf("%%ODS2-E-ILLCMD, Illegal or ambiguous command '%s'\n",argv[0]);
return 1;
}
/* cmdsplit: break a command line into its components */
int cmdsplit(char *str)
{
int argc = 0,qualc = 0;
char *argv[32],*qualv[32];
char *sp = str;
int i;
for (i = 0; i < 32; i++) argv[i] = qualv[i] = "";
while (*sp != '\0') {
while (*sp == ' ') sp++;
if (*sp != '\0') {
if (*sp == '/') {
*sp++ = '\0';
qualv[qualc++] = sp;
} else {
argv[argc++] = sp;
}
while (*sp != ' ' && *sp != '/' && *sp != '\0') sp++;
if (*sp == '\0') {
break;
} else {
if (*sp != '/') *sp++ = '\0';
}
}
}
if (argc > 0) return cmdexecute(argc,argv,qualc,qualv);
return 1;
}
/* main: the simple mainline of this puppy... */
int main(int argc,char *argv[])
{
char str[2048];
printf(" ODS2 v1.2\n");
while (1) {
printf("$> ");
if (gets(str) == NULL) break;
if (strlen(str)) if ((cmdsplit(str) & 1) == 0) break;
}
return 1;
}

View File

@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "windows.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,3
PRODUCTVERSION 1,0,0,3
FILEVERSION 1,0,0,4
PRODUCTVERSION 1,0,0,4
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -46,15 +46,15 @@ BEGIN
BEGIN
VALUE "Comments", "This application reads ODS-2 (VMS) disks under Windows NT and Windows 2000\0"
VALUE "CompanyName", "Paul Nankervis <paulnank@au1.ibm.com>\0"
VALUE "FileDescription", "ODS-2 Reader for Windows\0"
VALUE "FileVersion", "V1.3\0"
VALUE "FileDescription", "ODS-2 Reader for Windows (Modified)\0"
VALUE "FileVersion", "V1.4\0"
VALUE "InternalName", "ODS2\0"
VALUE "LegalCopyright", "Copyright © 2001\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "ODS2.EXE\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "ODS2\0"
VALUE "ProductVersion", "V1.3\0"
VALUE "ProductVersion", "V1.4\0"
VALUE "SpecialBuild", "\0"
END
END
@ -80,7 +80,7 @@ END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""windows.h""\r\n"
"\0"
END

View File

@ -1,4 +1,7 @@
/* Phyio.h v1.2-2 Definition of Physical I/O routines */
#ifndef PHYIO_H
#define PHYIO_H
/* Phyio.h v1.2-2 Definition of Physical I/O routines */
/*
This is part of ODS2 written by Paul Nankervis,
@ -30,11 +33,13 @@
*/
#include <stdio.h>
#define PHYIO_READONLY 1
struct phyio_info {
unsigned status;
unsigned sectors;
unsigned long long sectors;
unsigned sectorsize;
};
@ -42,3 +47,6 @@ void phyio_show(void);
unsigned phyio_init(int devlen,char *devnam,unsigned *handle,struct phyio_info *info);
unsigned phyio_read(unsigned handle,unsigned block,unsigned length,char *buffer);
unsigned phyio_write(unsigned handle,unsigned block,unsigned length,char *buffer);
void phyio_help(FILE *fp );
#endif

View File

@ -25,7 +25,7 @@
#include <memory.h>
#include "ssdef.h"
#include "compat.h"
/*
@ -42,6 +42,7 @@
you find a better way please let me know... Paulnank@au1.ibm.com
*/
#ifdef USE_WNASPI32
#include "wnaspi32.h"
#include "scsidefs.h"
@ -239,8 +240,25 @@ unsigned aspi_initialize(short *dev_type,short *dev_bus,short *dev_id,unsigned *
printf("Could not find suitable ASPI device\n");
return 8;
}
#else
unsigned aspi_read(short bus,short id,unsigned sector,unsigned sectorsize,char *buffer)
{
fprintf( stderr, "wnaspi32 support not compiled in this version\n" );
exit(1);
}
unsigned aspi_write(short bus,short id,unsigned sector,unsigned sectorsize,char *buffer)
{
fprintf( stderr, "wnaspi32 support not compiled in this version\n" );
exit(1);
}
unsigned aspi_initialize(short *dev_type,short *dev_bus,short *dev_id,unsigned *sectsize)
{
fprintf( stderr, "wnaspi32 support not compiled in this version\n" );
exit(1);
}
unsigned int ASPI_status = 0,ASPI_HaStat = 0,ASPI_TargStat = 0;
#endif
/* Some NT definitions... */
@ -412,7 +430,9 @@ unsigned phy_getsect(unsigned chan,unsigned sector)
&reg,sizeof(reg),
&cb,0);
if (!fResult || (reg.reg_Flags & 0x0001)) {
printf("Sector %d read failed %d\n",sector,GetLastError());
TCHAR *msg = w32_errstr(0);
printf("Sector %d read failed %s\n",sector,msg);
LocalFree(msg);
sts = SS$_PARITY;
}
}
@ -464,111 +484,147 @@ void phyio_show(void)
/* Initialize device by opening it, locking it and getting it ready.. */
void phyio_help(FILE *fp ) {
fprintf( fp, "Specify the device to be mounted as a drive letter.\n" );
fprintf( fp, "E.g. mount D:\n" );
#ifdef USE_WNASPI32
fprintf( fp, "If the drive letter is C: or higher, commands are\n" );
fprintf( fp, "sent directly to the drive, bypassing system drivers.\n" );
fprintf( fp, "The drive must be a SCSI device\n" );
#endif
fprintf( fp, "The drive letter must be between A: and Z:.\n" );
fprintf( fp, "The drive is accessed as a physical device, which may require privileges.\n" );
fprintf( fp, "Use show DEVICES for a list of available devices.\n" );
fprintf( fp, "Use ODS2-Image to work with disk images such as .ISO or simulator files.\n" );
return;
}
unsigned phyio_init(int devlen,char *devnam,unsigned *chanptr,struct phyio_info *info)
{
unsigned sts = 1;
unsigned chan = chan_count;
if (chan < CHAN_MAX - 1 && devlen == 2 &&
toupper(*devnam) >= 'A' && *(devnam + 1) == ':') {
HANDLE hDrive;
chantab[chan].device_status = 0;
chantab[chan].device_name = toupper(*devnam);
chantab[chan].device_dtype = -1;
if (chan >= CHAN_MAX - 1)
return SS$_IVCHAN;
if( !(devlen == 2 &&
toupper(*devnam) >= 'A' && toupper(*devnam) <= 'Z' && *(devnam + 1) == ':') )
return SS$_NOSUCHDEV;
chantab[chan].device_status = 0;
chantab[chan].device_name = toupper(*devnam);
chantab[chan].device_dtype = -1;
do {
HANDLE hDrive;
#ifdef USE_WNASPI32
/* Use ASPI for devices past C... */
if (toupper(*devnam) > 'C') {
sts = aspi_initialize(&chantab[chan].device_dtype,
&chantab[chan].device_bus,&chantab[chan].device_id,
&chantab[chan].sectorsize);
&chantab[chan].device_bus,&chantab[chan].device_id,
&chantab[chan].sectorsize);
if ((sts & 1) == 0) return sts;
} else {
break;
}
#endif
if (is_NT > 1) getsysversion();
if (is_NT > 1) getsysversion();
/* NT stuff */
/* NT stuff */
if (is_NT) {
char ntname[20];
DISK_GEOMETRY Geometry;
sprintf(ntname,"\\\\.\\%s",devnam);
chantab[chan].handle = hDrive = CreateFile(ntname,
GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
if (hDrive == INVALID_HANDLE_VALUE) {
printf("Open %s failed %d\n",devnam,GetLastError());
return SS$_NOSUCHDEV;
}
if (LockVolume(hDrive) == FALSE) {
printf("LockVolume %s failed %d\n",devnam,GetLastError());
return 72;
}
if (!GetDiskGeometry(hDrive,&Geometry)) {
printf("GetDiskGeometry %s failed %d\n",devnam,GetLastError());
return 80;
}
chantab[chan].sectorsize = Geometry.BytesPerSector;
info->sectors = Geometry.Cylinders.QuadPart * Geometry.TracksPerCylinder *
Geometry.SectorsPerTrack;
} else {
/* W95 stuff */
DIOC_REGISTERS reg;
DEVICEPARAM deviceparam;
BOOL fResult;
DWORD cb;
chantab[chan].handle = hDrive = CreateFile("\\\\.\\vwin32",
0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
if (hDrive == INVALID_HANDLE_VALUE) {
printf("Open %s failed %d\n",devnam,GetLastError());
return SS$_NOSUCHDEV;
}
reg.reg_EAX = 0x440d;
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
reg.reg_ECX = 0x084a; /* Lock volume */
reg.reg_EDX = 0;
reg.reg_Flags = 0x0000; /* Permission */
fResult = DeviceIoControl(hDrive,VWIN32_DIOC_DOS_IOCTL,
&reg,sizeof(reg),&reg,sizeof(reg),&cb,0);
if (!fResult || (reg.reg_Flags & 0x0001)) {
printf("Volume lock failed (%d)\n",GetLastError());
return SS$_DEVNOTALLOC;
}
reg.reg_EAX = 0x440d;
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
reg.reg_ECX = 0x0860; /* Get device parameters */
reg.reg_EDX = (DWORD) & deviceparam;
reg.reg_Flags = 0x0001; /* set carry flag */
fResult = DeviceIoControl(hDrive,
VWIN32_DIOC_DOS_IOCTL,
&reg,sizeof(reg),
&reg,sizeof(reg),
&cb,0);
if (!fResult || (reg.reg_Flags & 0x0001)) {
printf("Volume get parameters failed (%d)\n",GetLastError());
return 8;
}
chantab[chan].sectorsize = deviceparam.sec_size;
if (is_NT) {
char ntname[20];
DISK_GEOMETRY Geometry;
snprintf(ntname,sizeof(ntname),"\\\\.\\%s",devnam);
chantab[chan].handle = hDrive = CreateFile(ntname,
GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
if (hDrive == INVALID_HANDLE_VALUE) {
TCHAR *msg = w32_errstr(0);
printf("Open %s failed %s\n",devnam,msg);
LocalFree(msg);
return SS$_NOSUCHDEV;
}
info->sectors = 0;
if (LockVolume(hDrive) == FALSE) {
TCHAR *msg = w32_errstr(0);
printf("LockVolume %s failed %s\n",devnam,msg);
LocalFree(msg);
return 72;
}
if (!GetDiskGeometry(hDrive,&Geometry)) {
TCHAR *msg = w32_errstr(0);
printf("GetDiskGeometry %s failed %s\n",devnam,msg);
LocalFree(msg);
return 80;
}
chantab[chan].sectorsize = Geometry.BytesPerSector;
info->sectors = Geometry.Cylinders.QuadPart * Geometry.TracksPerCylinder *
Geometry.SectorsPerTrack;
break;
}
chantab[chan].IoBuffer = VirtualAlloc(NULL,chantab[chan].sectorsize,
MEM_COMMIT,PAGE_READWRITE);
chantab[chan].last_sector = 99999;
*chanptr = chan_count++;
info->status = 0;
info->sectorsize = chantab[chan].sectorsize;
init_count++;
return 1;
} else {
return SS$_IVCHAN;
}
/* W95 stuff */
{
DIOC_REGISTERS reg;
DEVICEPARAM deviceparam;
BOOL fResult;
DWORD cb;
chantab[chan].handle = hDrive = CreateFile("\\\\.\\vwin32",
0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
if (hDrive == INVALID_HANDLE_VALUE) {
TCHAR *msg = w32_errstr(0);
printf("Open %s failed %s\n",devnam,msg);
LocalFree(msg);
return SS$_NOSUCHDEV;
}
reg.reg_EAX = 0x440d;
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
reg.reg_ECX = 0x084a; /* Lock volume */
reg.reg_EDX = 0;
reg.reg_Flags = 0x0000; /* Permission */
fResult = DeviceIoControl(hDrive,VWIN32_DIOC_DOS_IOCTL,
&reg,sizeof(reg),&reg,sizeof(reg),&cb,0);
if (!fResult || (reg.reg_Flags & 0x0001)) {
TCHAR *msg = w32_errstr(0);
printf("Volume lock failed (%s)\n",msg);
LocalFree(msg);
return SS$_DEVNOTALLOC;
}
reg.reg_EAX = 0x440d;
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
reg.reg_ECX = 0x0860; /* Get device parameters */
reg.reg_EDX = (DWORD) & deviceparam;
reg.reg_Flags = 0x0001; /* set carry flag */
fResult = DeviceIoControl(hDrive,
VWIN32_DIOC_DOS_IOCTL,
&reg,sizeof(reg),
&reg,sizeof(reg),
&cb,0);
if (!fResult || (reg.reg_Flags & 0x0001)) {
TCHAR *msg = w32_errstr(0);
printf("Volume get parameters failed (%s)\n",msg);
LocalFree(msg);
return 8;
}
chantab[chan].sectorsize = deviceparam.sec_size;
info->sectors = 0;
break;
}
} while(0);
chantab[chan].IoBuffer = VirtualAlloc(NULL,chantab[chan].sectorsize,
MEM_COMMIT,PAGE_READWRITE);
chantab[chan].last_sector = ~0U;
*chanptr = chan_count++;
info->status = 0;
info->sectorsize = chantab[chan].sectorsize;
init_count++;
return 1;
}

View File

@ -61,6 +61,15 @@ struct HANDLE {
int hand_drive;
} handle[HANDLE_MAX];
void phyio_help(FILE *fp ) {
fprintf( fp, "Specify the device to be mounted as a drive letter\n" );
fprintf( fp, "E.g. mount D:\n" );
fprintf( fp, "The drive letter must be between A: and Z:\n" );
fprintf( fp, "The drive is accessed as a physical device\n" );
fprintf( fp, "Use ODS2-Image to work with disk images such as .ISO or simulator files.\n" );
return;
}
unsigned phyio_init(int devlen,char *devnam,unsigned *hand,struct phyio_info *info)
{
if (hand_count < HANDLE_MAX - 1) {

View File

@ -1,4 +1,4 @@
/* PHYVMS.c v1.3 Physical I/O module for Unix */
/* PHYUNIX.c v1.3 Physical I/O module for Unix */
/*
This is part of ODS2 written by Paul Nankervis,
@ -14,13 +14,21 @@
If the user mounts cd0 we open up /dev/cd0 for access.
*/
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include "phyio.h"
#include "ssdef.h"
#include "compat.h"
#if defined(__digital__) && defined(__unix__)
#define DEV_PREFIX "/devices/rdisk/%s"
@ -42,16 +50,30 @@ void phyio_show(void)
init_count,read_count,write_count);
}
void phyio_help(FILE *fp ) {
fprintf( fp, "Specify the device to be mounted as using the format:\n" );
fprintf( fp, " mount %s%s\n\n", DEV_PREFIX, "device" );
fprintf( fp, "For example, if you are using " DEV_PREFIX "\n", "cdrom0" );
fprintf( fp, " ODS2$> mount cdrom0\n\n" );
fprintf( fp, "Use ODS2-Image to work with disk images such as .ISO or simulator files.\n" );
fprintf( fp, "Alternatively, you can mount the image on a loop device.\n" );
return;
}
unsigned phyio_init(int devlen,char *devnam,unsigned *handle,struct phyio_info *info)
{
int vmsfd;
char *cp,devbuf[200];
UNUSED(devlen);
init_count++;
info->status = 0; /* We don't know anything about this device! */
info->sectors = 0;
info->sectorsize = 0;
sprintf(devbuf,DEV_PREFIX,devnam);
snprintf(devbuf,sizeof(devbuf),DEV_PREFIX,devnam);
cp = strchr(devbuf,':');
if (cp != NULL) *cp = '\0';
vmsfd = open(devbuf,O_RDWR);
@ -71,19 +93,19 @@ unsigned phyio_close(unsigned handle)
unsigned phyio_read(unsigned handle,unsigned block,unsigned length,char *buffer)
{
int res;
off_t res;
#ifdef DEBUG
printf("Phyio read block: %d into %x (%d bytes)\n",block,buffer,length);
#endif
read_count++;
if ((res = lseek(handle,block*512,0)) < 0) {
perror("lseek ");
printf("lseek failed %d\n",res);
printf("lseek failed %" PRIuMAX "u\n",(uintmax_t)res);
return SS$_PARITY;
}
if ((res = read(handle,buffer,length)) != length) {
if ((res = read(handle,buffer,length)) != (ssize_t)length) {
perror("read ");
printf("read failed %d\n",res);
printf("read failed %" PRIuMAX "u\n",(uintmax_t)res);
return SS$_PARITY;
}
return SS$_NORMAL;

View File

@ -60,6 +60,14 @@ void phyio_show(void)
init_count,read_count,write_count);
}
void phyio_help(FILE *fp ) {
fprintf( fp, "Specify the device to be mounted as a VMS device or logical name\n" );
fprintf( fp, "E.g. mount DUB0:\n" );
fprintf( fp, "You will need the LOGIO privilege\n" );
fprintf( fp, "Use ODS2-Image to work with disk images such as .ISO or simulator files.\n" );
return;
}
unsigned phyio_init(int devlen,char *devnam,unsigned *handle,struct phyio_info *info)
{

View File

@ -1,5 +1,5 @@
/* check for cr - return terminator - update file length */
/* RMS.c v1.3 RMS components */
/* RMS.c v1.4 RMS components */
/*
This is part of ODS2 written by Paul Nankervis,
@ -34,7 +34,7 @@
#include "rms.h"
#include "access.h"
#include "direct.h"
#include "compat.h"
/* Table of file name component delimeters... */
@ -49,7 +49,7 @@ char char_delim[] = {
unsigned name_delim(char *str,int len,int size[5])
{
register unsigned ch;
register unsigned ch = 0;
register char *curptr = str;
register char *endptr = curptr + len;
register char *begptr = curptr;
@ -190,9 +190,13 @@ unsigned dircache(struct VCB *vcb,char *dirnam,int dirlen,struct fiddef *dirid)
#define STATUS_TMPDIR 2
#define STATUS_WILDCARD 4
#define WCDALLOC_SIZE(size) (sizeof(struct WCCDIR)+(size))
struct WCCDIR {
struct WCCDIR *wcd_next;
struct WCCDIR *wcd_prev;
#ifdef DEBUG
size_t size;
#endif
int wcd_status;
int wcd_wcc;
int wcd_prelen;
@ -207,6 +211,12 @@ struct WCCDIR {
#define STATUS_TMPWCC 16
#define MAX_FILELEN 1024
/* Allocation sise for WCCFILE = block + max len wcd_sernam.
* WCCDIRs are allocated smaller on the chain..
* Why 256? The byte lengths?
*/
#define WCFALLOC_SIZE (sizeof(struct WCCFILE)+256)
struct WCCFILE {
struct FAB *wcf_fab;
struct VCB *wcf_vcb;
@ -220,21 +230,31 @@ struct WCCFILE {
/* Function to remove WCCFILE and WCCDIR structures when not required */
void cleanup_wcf(struct WCCFILE *wccfile)
void cleanup_wcf(struct WCCFILE **wccfilep)
{
struct WCCFILE *wccfile;
wccfile = *wccfilep;
*wccfilep = NULL;
if (wccfile != NULL) {
struct WCCDIR *wcc = wccfile->wcf_wcd.wcd_next;
wccfile->wcf_wcd.wcd_next = NULL;
wccfile->wcf_wcd.wcd_prev = NULL;
/* should deaccess volume */
free(wccfile);
while (wcc != NULL) {
struct WCCDIR *next = wcc->wcd_next;
wcc->wcd_next = NULL;
wcc->wcd_prev = NULL;
#ifdef DEBUG
memset(wcc,0,wcc->size);
#endif
free(wcc);
wcc = next;
}
#ifdef DEBUG
memset(wccfile,0,WCFALLOC_SIZE);
#endif
free(wccfile);
}
}
@ -249,7 +269,10 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
struct dsc_descriptor fibdsc,resdsc;
struct NAM *nam = fab->fab$l_nam;
wcc = &wccfile->wcf_wcd;
if (fab->fab$w_ifi != 0) return RMS$_IFI;
if (fab->fab$w_ifi != 0) {
sts = RMS$_IFI;
goto cleanup;
}
/* if first time through position at top directory... WCCDIR */
@ -322,7 +345,8 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
if (nam->nam$b_rsl <= nam->nam$b_rss) {
memcpy(nam->nam$l_rsa,wccfile->wcf_result,nam->nam$b_rsl);
} else {
return RMS$_RSS;
sts = RMS$_RSS;
goto cleanup;
}
}
memcpy(&wccfile->wcf_fid,&fibblk.fib$w_fid_num,sizeof(struct fiddef));
@ -348,11 +372,17 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
if (wcc->wcd_prev != NULL) wcc->wcd_prev->wcd_next = wcc->wcd_next;
wcc = wcc->wcd_next;
memcpy(wccfile->wcf_result + wcc->wcd_prelen + wcc->wcd_reslen - 6,".DIR;1",6);
#ifdef DEBUG
memset(savwcc, 0, savwcc->size);
#endif
free(savwcc);
} else {
if ((wccfile->wcf_status & STATUS_RECURSE) && wcc->wcd_prev == NULL) {
struct WCCDIR *newwcc;
newwcc = (struct WCCDIR *) malloc(sizeof(struct WCCDIR) + 8);
newwcc = (struct WCCDIR *) calloc(1,WCDALLOC_SIZE(8));
#ifdef DEBUG
newwcc->size = WCDALLOC_SIZE(8);
#endif
newwcc->wcd_next = wcc->wcd_next;
newwcc->wcd_prev = wcc;
newwcc->wcd_wcc = 0;
@ -368,7 +398,6 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
memcpy(newwcc->wcd_sernam,"*.DIR;1",7);
newwcc->wcd_prelen = wcc->wcd_prelen;
wcc = newwcc;
} else {
if (wcc->wcd_next != NULL) {
#ifdef DEBUG
@ -394,9 +423,10 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
}
}
}
cleanup_wcf(wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
fab->fab$w_ifi = 0; /* must dealloc memory blocks! */
cleanup:
cleanup_wcf(&wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
return sts;
}
@ -407,7 +437,8 @@ unsigned sys_search(struct FAB *fab)
{
struct NAM *nam = fab->fab$l_nam;
struct WCCFILE *wccfile;
if (nam == NULL) return RMS$_NAM;
if (nam == NULL)
return RMS$_NAM;
wccfile = (struct WCCFILE *) nam->nam$l_wcc;
if (wccfile == NULL) return RMS$_WCC;
return do_search(fab,wccfile);
@ -430,12 +461,15 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
char *dna = fab->fab$l_dna;
struct NAM *nam = fab->fab$l_nam;
int sts;
int fna_size[5] = {0, 0, 0, 0, 0},dna_size[5] = {0, 0, 0, 0, 0};
if (fab->fab$w_ifi != 0) return RMS$_IFI;
if (nam != NULL) if (nam->nam$l_wcc == 0) {
cleanup_wcf((struct WCCFILE *) nam->nam$l_wcc);
nam->nam$l_wcc = 0;
}
int fna_size[5] = {0, 0, 0, 0, 0},
dna_size[5] = {0, 0, 0, 0, 0};
if (fab->fab$w_ifi != 0)
return RMS$_IFI;
if (nam != NULL && nam->nam$l_wcc == 0) {
struct WCCFILE *wcc = (struct WCCFILE *)nam->nam$l_wcc;
cleanup_wcf(&wcc);
nam->nam$l_wcc = 0;
}
/* Break up file specifications... */
sts = name_delim(fna,fab->fab$b_fns,fna_size);
@ -447,9 +481,9 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
/* Make WCCFILE entry for rest of processing */
{
wccfile = (struct WCCFILE *) malloc(sizeof(struct WCCFILE) + 256);
if (wccfile == NULL) return SS$_INSFMEM;
memset(wccfile,0,sizeof(struct WCCFILE)+256);
wccfile = (struct WCCFILE *) calloc(1,WCFALLOC_SIZE);
if (wccfile == NULL)
return SS$_INSFMEM;
wccfile->wcf_fab = fab;
wccfile->wcf_vcb = NULL;
wccfile->wcf_fcb = NULL;
@ -496,7 +530,10 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
len--;
src++;
if (count < 2 || (count == 7 &&
memcmp(dir,"[000000",7) == 0)) return RMS$_DIR;
memcmp(dir,"[000000",7) == 0)) {
cleanup_wcf(&wccfile);
return RMS$_DIR;
}
while (count > 1) {
if (dir[--count] == '.') break;
}
@ -505,13 +542,19 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
src = "[000000]";
dirlen = len = 8;
} else {
if (*src != '.' && *src != ']') return RMS$_DIR;
if (*src != '.' && *src != ']') {
cleanup_wcf(&wccfile);
return RMS$_DIR;
}
if (*src == '.' && count < 2) {
src++;
len--;
}
dirlen = len + count;
if ((ess -= count) < 0) return RMS$_ESS;
if ((ess -= count) < 0) {
cleanup_wcf(&wccfile);
return RMS$_ESS;
}
memcpy(esa,dir,count);
esa += count;
}
@ -523,7 +566,10 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
}
dna += dna_size[field];
def += default_size[field];
if ((ess -= len) < 0) return RMS$_ESS;
if ((ess -= len) < 0) {
cleanup_wcf(&wccfile);
return RMS$_ESS;
}
while (len-- > 0) {
register char ch;
*esa++ = ch = *src++;
@ -549,12 +595,14 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
if (nam->nam$b_esl <= nam->nam$b_ess) {
memcpy(nam->nam$l_esa,wccfile->wcf_result,nam->nam$b_esl);
} else {
cleanup_wcf(&wccfile);
return RMS$_ESS;
}
}
}
sts = 1;
if (nam != NULL) if (nam->nam$b_nop & NAM$M_SYNCHK) sts = 0;
if (nam != NULL && (nam->nam$b_nop & NAM$M_SYNCHK))
sts = 0;
/* Now build up WCC structures as required */
@ -564,8 +612,14 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
struct WCCDIR *wcc;
struct DEV *dev;
sts = device_lookup(fna_size[0],wccfile->wcf_result,0,&dev);
if ((sts & 1) == 0) return sts;
if ((wccfile->wcf_vcb = dev->vcb) == NULL) return SS$_DEVNOTMOUNT;
if ((sts & 1) == 0) {
cleanup_wcf(&wccfile);
return sts;
}
if ((wccfile->wcf_vcb = dev->vcb) == NULL) {
cleanup_wcf(&wccfile);
return SS$_DEVNOTMOUNT;
}
wcc = &wccfile->wcf_wcd;
wcc->wcd_prev = NULL;
wcc->wcd_next = NULL;
@ -606,11 +660,16 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
if (char_delim[*dirptr++ & 127]) break;
seglen++;
} while (dirsiz + seglen < dirlen);
wcd = (struct WCCDIR *) malloc(sizeof(struct WCCDIR) + seglen + 8);
wcd = (struct WCCDIR *) calloc(1,WCDALLOC_SIZE(seglen + 8));
#ifdef DEBUG
wcd->size = WCDALLOC_SIZE(seglen + 8);
#endif
/* calloc()
wcd->wcd_wcc = 0;
wcd->wcd_status = 0;
wcd->wcd_prelen = 0;
wcd->wcd_reslen = 0;
*/
memcpy(wcd->wcd_sernam,dirnam + dirsiz,seglen);
memcpy(wcd->wcd_sernam + seglen,".DIR;1",7);
wcd->wcd_serdsc.dsc_w_length = seglen + 6;
@ -628,6 +687,10 @@ memset(wccfile,0,sizeof(struct WCCFILE)+256);
wcc->wcd_reslen = 0;
wcc->wcd_serdsc.dsc_w_length = fna_size[2] + fna_size[3] + fna_size[4];
wcc->wcd_serdsc.dsc_a_pointer = wcc->wcd_sernam;
if (wcc->wcd_serdsc.dsc_w_length >= 256) {
printf( "serdsc length too long %u\n", wcc->wcd_serdsc.dsc_w_length );
abort();
}
memcpy(wcc->wcd_sernam,wccfile->wcf_result + fna_size[0] + fna_size[1],
wcc->wcd_serdsc.dsc_w_length);
#ifdef DEBUG
@ -708,6 +771,8 @@ unsigned sys_connect(struct RAB *rab)
unsigned sys_disconnect(struct RAB *rab)
{
UNUSED(rab);
return 1;
}
@ -739,30 +804,32 @@ unsigned sys_get(struct RAB *rab)
switch (rfm = rab->rab$l_fab->fab$b_rfm) {
case FAB$C_STMLF:
delim = 1;
break;
break;
case FAB$C_STMCR:
delim = 2;
break;
break;
case FAB$C_STM:
delim = 3;
break;
break;
case FAB$C_VFC:
reclen += rab->rab$l_fab->fab$b_fsz;
break;
case FAB$C_FIX:
if (reclen < rab->rab$l_fab->fab$w_mrs) return RMS$_RTB;
if (reclen < rab->rab$l_fab->fab$w_mrs)
return RMS$_RTB;
reclen = rab->rab$l_fab->fab$w_mrs;
break;
}
offset = rab->rab$w_rfa[2] % 512;
block = (rab->rab$w_rfa[1] << 16) + rab->rab$w_rfa[0];
if (block == 0) block = 1;
if (block == 0)
block = 1;
{
unsigned eofblk = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_efblk);
if (block > eofblk || (block == eofblk &&
offset >= VMSWORD(fcb->head->fh2$w_recattr.fat$w_ffbyte))) return RMS$_EOF;
offset >= VMSWORD(fcb->head->fh2$w_recattr.fat$w_ffbyte)))
return RMS$_EOF;
}
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0);
@ -784,9 +851,9 @@ unsigned sys_get(struct RAB *rab)
cpylen = 0;
while (1) {
int dellen = 0;
int seglen = blocks * 512 - offset;
if (delim) {
if (delim >= 3) {
unsigned int seglen = blocks * 512 - offset;
if (delim) {
if (delim >= 3) {
char *ptr = buffer + offset;
if (dellen == 1 && *ptr != '\n') {
if (cpylen >= reclen) {
@ -812,10 +879,11 @@ unsigned sys_get(struct RAB *rab)
if (ch == '\r') dellen = 1;
}
seglen = ptr - (buffer + offset) - dellen;;
} else {
} else {
char *ptr = buffer + offset;
char term = '\r';
if (delim == 1) term = '\n';
if (delim == 1)
term = '\n';
while (seglen-- > 0) {
if (*ptr++ == term) {
dellen = 1;
@ -826,11 +894,14 @@ unsigned sys_get(struct RAB *rab)
seglen = ptr - (buffer + offset) - dellen;;
}
} else {
if (seglen > reclen - cpylen) seglen = reclen - cpylen;
if (seglen > reclen - cpylen)
seglen = reclen - cpylen;
if (rfm == FAB$C_VFC && cpylen < rab->rab$l_fab->fab$b_fsz) {
unsigned fsz = rab->rab$l_fab->fab$b_fsz - cpylen;
if (fsz > seglen) fsz = seglen;
if (rab->rab$l_rhb) memcpy(rab->rab$l_rhb + cpylen,buffer + offset,fsz);
if (fsz > seglen)
fsz = seglen;
if (rab->rab$l_rhb)
memcpy(rab->rab$l_rhb + cpylen,buffer + offset,fsz);
cpylen += fsz;
offset += fsz;
seglen -= fsz;
@ -841,7 +912,7 @@ unsigned sys_get(struct RAB *rab)
seglen = reclen - cpylen;
sts = RMS$_RTB;
}
memcpy(recbuff,buffer + offset,seglen);
memcpy(recbuff,buffer + offset,seglen);
recbuff += seglen;
cpylen += seglen;
}
@ -852,8 +923,8 @@ unsigned sys_get(struct RAB *rab)
block += offset / 512;
offset %= 512;
if ((delim == 0 && cpylen >= reclen) || delim == 99) {
break;
} else {
break;
} else {
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0);
if ((sts & 1) == 0) {
if (sts == SS$_ENDOFFILE) sts = RMS$_EOF;
@ -862,7 +933,8 @@ unsigned sys_get(struct RAB *rab)
offset = 0;
}
}
if (rfm == FAB$C_VFC) cpylen -= rab->rab$l_fab->fab$b_fsz;
if (rfm == FAB$C_VFC)
cpylen -= rab->rab$l_fab->fab$b_fsz;
rab->rab$w_rsz = cpylen;
rab->rab$w_rfa[0] = block & 0xffff;
@ -887,33 +959,33 @@ unsigned sys_put(struct RAB *rab)
recbuff = rab->rab$l_rbf;
delim = 0;
switch (rfm = rab->rab$l_fab->fab$b_rfm) {
case FAB$C_STMLF:
if (reclen < 1) {
delim = 1;
} else {
if (recbuff[reclen] != '\n') delim = 1;
}
break;
case FAB$C_STMCR:
if (reclen < 1) {
delim = 2;
} else {
if (recbuff[reclen] != '\r') delim = 2;
}
break;
case FAB$C_STM:
if (reclen < 2) {
delim = 3;
} else {
if (recbuff[reclen-1] != '\r' || recbuff[reclen] != '\n') delim = 3;
}
break;
case FAB$C_VFC:
reclen += rab->rab$l_fab->fab$b_fsz;
break;
case FAB$C_FIX:
if (reclen != rab->rab$l_fab->fab$w_mrs) return RMS$_RSZ;
break;
case FAB$C_STMLF:
if (reclen < 1) {
delim = 1;
} else {
if (recbuff[reclen] != '\n') delim = 1;
}
break;
case FAB$C_STMCR:
if (reclen < 1) {
delim = 2;
} else {
if (recbuff[reclen] != '\r') delim = 2;
}
break;
case FAB$C_STM:
if (reclen < 2) {
delim = 3;
} else {
if (recbuff[reclen-1] != '\r' || recbuff[reclen] != '\n') delim = 3;
}
break;
case FAB$C_VFC:
reclen += rab->rab$l_fab->fab$b_fsz;
break;
case FAB$C_FIX:
if (reclen != rab->rab$l_fab->fab$w_mrs) return RMS$_RSZ;
break;
}
block = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_efblk);
@ -930,55 +1002,58 @@ unsigned sys_put(struct RAB *rab)
cpylen = 0;
while (1) {
int seglen = blocks * 512 - offset;
unsigned int seglen = blocks * 512 - offset;
if (seglen > reclen - cpylen) seglen = reclen - cpylen;
if (rfm == FAB$C_VFC && cpylen < rab->rab$l_fab->fab$b_fsz) {
unsigned fsz = rab->rab$l_fab->fab$b_fsz - cpylen;
if (fsz > seglen) fsz = seglen;
if (fsz > seglen)
fsz = seglen;
if (rab->rab$l_rhb) {
memcpy(buffer + offset,rab->rab$l_rhb + cpylen,fsz);
} else {
memset(buffer + offset,0,fsz);
}
}
cpylen += fsz;
offset += fsz;
seglen -= fsz;
}
if (seglen) {
memcpy(buffer + offset,recbuff,seglen);
memcpy(buffer + offset,recbuff,seglen);
recbuff += seglen;
cpylen += seglen;
offset += seglen;
}
if (delim && offset < blocks * 512) {
if (delim && offset < blocks * 512) {
offset++;
switch (delim) {
case 1:
*buffer = '\n';
delim = 0;
break;
case 2:
*buffer = '\r';
delim = 0;
break;
case 3:
*buffer = '\r';
if (offset < blocks * 512) {
offset++;
*buffer = '\n';
delim = 0;
} else {
delim = 2;
}
break;
case 1:
*buffer = '\n';
delim = 0;
break;
case 2:
*buffer = '\r';
delim = 0;
break;
case 3:
*buffer = '\r';
if (offset < blocks * 512) {
offset++;
*buffer = '\n';
delim = 0;
} else {
delim = 2;
}
break;
}
}
sts = deaccesschunk(vioc,block,blocks,1);
if ((sts & 1) == 0) return sts;
if ((sts & 1) == 0)
return sts;
block += blocks;
if (cpylen >= reclen && delim == 0) {
break;
} else {
break;
} else {
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,1);
if ((sts & 1) == 0) return sts;
offset = 0;
@ -1004,8 +1079,10 @@ unsigned sys_display(struct FAB *fab)
struct HEAD *head = ifi_table[fab->fab$w_ifi]->wcf_fcb->head;
unsigned short *pp = (unsigned short *) head;
struct IDENT *id = (struct IDENT *) (pp + head->fh2$b_idoffset);
int ifi_no = fab->fab$w_ifi;
if (ifi_no == 0 || ifi_no >= IFI_MAX) return RMS$_IFI;
if (ifi_no == 0 || ifi_no >= IFI_MAX)
return RMS$_IFI;
fab->fab$l_alq = VMSSWAP(head->fh2$w_recattr.fat$l_hiblk);
fab->fab$b_bks = head->fh2$w_recattr.fat$b_bktsize;
fab->fab$w_deq = VMSWORD(head->fh2$w_recattr.fat$w_defext);
@ -1017,36 +1094,67 @@ unsigned sys_display(struct FAB *fab)
fab->fab$b_rat = head->fh2$w_recattr.fat$b_rattrib;
while (xab != NULL) {
switch (xab->xab$b_cod) {
case XAB$C_DAT:
memcpy(&xab->xab$q_bdt,id->fi2$q_bakdate,sizeof(id->fi2$q_bakdate));
memcpy(&xab->xab$q_cdt,id->fi2$q_credate,sizeof(id->fi2$q_credate));
memcpy(&xab->xab$q_edt,id->fi2$q_expdate,sizeof(id->fi2$q_expdate));
memcpy(&xab->xab$q_rdt,id->fi2$q_revdate,sizeof(id->fi2$q_revdate));
xab->xab$w_rvn = id->fi2$w_revision;
case XAB$C_DAT:{
memcpy(&xab->xab$q_bdt,id->fi2$q_bakdate,sizeof(id->fi2$q_bakdate));
memcpy(&xab->xab$q_cdt,id->fi2$q_credate,sizeof(id->fi2$q_credate));
memcpy(&xab->xab$q_edt,id->fi2$q_expdate,sizeof(id->fi2$q_expdate));
memcpy(&xab->xab$q_rdt,id->fi2$q_revdate,sizeof(id->fi2$q_revdate));
xab->xab$w_rvn = id->fi2$w_revision;
}
break;
case XAB$C_FHC:{
struct XABFHC *fhc = (struct XABFHC *) xab;
fhc->xab$b_atr = head->fh2$w_recattr.fat$b_rattrib;
fhc->xab$b_bkz = head->fh2$w_recattr.fat$b_bktsize;
fhc->xab$w_dxq = VMSWORD(head->fh2$w_recattr.fat$w_defext);
fhc->xab$l_ebk = VMSSWAP(head->fh2$w_recattr.fat$l_efblk);
fhc->xab$w_ffb = VMSWORD(head->fh2$w_recattr.fat$w_ffbyte);
if (fhc->xab$l_ebk == 0) {
fhc->xab$l_ebk = fab->fab$l_alq;
if (fhc->xab$w_ffb == 0) fhc->xab$l_ebk++;
}
fhc->xab$w_gbc = VMSWORD(head->fh2$w_recattr.fat$w_gbc);
fhc->xab$l_hbk = VMSSWAP(head->fh2$w_recattr.fat$l_hiblk);
fhc->xab$b_hsz = head->fh2$w_recattr.fat$b_vfcsize;
fhc->xab$w_lrl = VMSWORD(head->fh2$w_recattr.fat$w_maxrec);
fhc->xab$w_verlimit = VMSWORD(head->fh2$w_recattr.fat$w_versions);
}
break;
case XAB$C_PRO:{
struct XABPRO *pro = (struct XABPRO *) xab;
pro->xab$w_pro = VMSWORD(head->fh2$w_fileprot);
memcpy(&pro->xab$l_uic,&head->fh2$l_fileowner,4);
}
break;
case XAB$C_ITM:{
struct XABITM *itm = (struct XABITM *) xab;
struct item_list *list;
vmslong fch = VMSLONG( head->fh2$l_filechar );
if( itm->xab$b_mode != XAB$K_SENSEMODE )
break;
case XAB$C_FHC:{
struct XABFHC *fhc = (struct XABFHC *) xab;
fhc->xab$b_atr = head->fh2$w_recattr.fat$b_rattrib;
fhc->xab$b_bkz = head->fh2$w_recattr.fat$b_bktsize;
fhc->xab$w_dxq = VMSWORD(head->fh2$w_recattr.fat$w_defext);
fhc->xab$l_ebk = VMSSWAP(head->fh2$w_recattr.fat$l_efblk);
fhc->xab$w_ffb = VMSWORD(head->fh2$w_recattr.fat$w_ffbyte);
if (fhc->xab$l_ebk == 0) {
fhc->xab$l_ebk = fab->fab$l_alq;
if (fhc->xab$w_ffb == 0) fhc->xab$l_ebk++;
}
fhc->xab$w_gbc = VMSWORD(head->fh2$w_recattr.fat$w_gbc);
fhc->xab$l_hbk = VMSSWAP(head->fh2$w_recattr.fat$l_hiblk);
fhc->xab$b_hsz = head->fh2$w_recattr.fat$b_vfcsize;
fhc->xab$w_lrl = VMSWORD(head->fh2$w_recattr.fat$w_maxrec);
fhc->xab$w_verlimit = VMSWORD(head->fh2$w_recattr.fat$w_versions);
}
break;
case XAB$C_PRO:{
struct XABPRO *pro = (struct XABPRO *) xab;
pro->xab$w_pro = VMSWORD(head->fh2$w_fileprot);
memcpy(&pro->xab$l_uic,&head->fh2$l_fileowner,4);
for( list = itm->xab$l_itemlist; list->code != 0 || list->length != 0; list++ ) {
list->retlen = sizeof(int);
switch( list->code ) {
case XAB$_UCHAR_NOBACKUP:
*((int *)list->buffer) = (fch & FH2$M_NOBACKUP) != 0; break;
case XAB$_UCHAR_CONTIGB:
*((int *)list->buffer) = (fch & FH2$M_CONTIGB) != 0; break;
case XAB$_UCHAR_CONTIG:
*((int *)list->buffer) = (fch & FH2$M_CONTIG) != 0; break;
case XAB$_UCHAR_DIRECTORY:
*((int *)list->buffer) = (fch & FH2$M_DIRECTORY) != 0; break;
case XAB$_UCHAR_MARKDEL:
*((int *)list->buffer) = (fch & FH2$M_MARKDEL) != 0; break;
default:
list->retlen = 0;
break;
}
}
}
break;
default:
break;
}
xab = xab->xab$l_nxt;
}
@ -1061,13 +1169,15 @@ unsigned sys_close(struct FAB *fab)
{
int sts;
int ifi_no = fab->fab$w_ifi;
if (ifi_no < 1 || ifi_no >= IFI_MAX) return RMS$_IFI;
if (ifi_no < 1 || ifi_no >= IFI_MAX)
return RMS$_IFI;
sts = deaccessfile(ifi_table[ifi_no]->wcf_fcb);
if (sts & 1) {
ifi_table[ifi_no]->wcf_fcb = NULL;
if (ifi_table[ifi_no]->wcf_status & STATUS_TMPWCC) {
cleanup_wcf(ifi_table[ifi_no]);
if (fab->fab$l_nam != NULL) fab->fab$l_nam->nam$l_wcc = 0;
cleanup_wcf(&ifi_table[ifi_no]);
if (fab->fab$l_nam != NULL)
fab->fab$l_nam->nam$l_wcc = 0;
}
fab->fab$w_ifi = 0;
ifi_table[ifi_no] = NULL;
@ -1085,9 +1195,15 @@ unsigned sys_open(struct FAB *fab)
int wcc_flag = 0;
struct WCCFILE *wccfile = NULL;
struct NAM *nam = fab->fab$l_nam;
if (fab->fab$w_ifi != 0) return RMS$_IFI;
while (ifi_table[ifi_no] != NULL && ifi_no < IFI_MAX) ifi_no++;
if (ifi_no >= IFI_MAX) return RMS$_IFI;
while (ifi_table[ifi_no] != NULL && ifi_no < IFI_MAX)
ifi_no++;
if (ifi_no >= IFI_MAX)
return RMS$_IFI;
if (nam != NULL) {
wccfile = (struct WCCFILE *) nam->nam$l_wcc;
}
@ -1099,6 +1215,8 @@ unsigned sys_open(struct FAB *fab)
sts = RMS$_WLD;
} else {
sts = do_search(fab,wccfile);
if ((sts & 1) == 0)
wcc_flag = 0;
}
wccfile->wcf_status |= STATUS_TMPWCC;
}
@ -1115,7 +1233,7 @@ unsigned sys_open(struct FAB *fab)
sys_display(fab);
}
if (wcc_flag && ((sts & 1) == 0)) {
cleanup_wcf(wccfile);
cleanup_wcf(&wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
}
return sts;
@ -1145,6 +1263,8 @@ unsigned sys_erase(struct FAB *fab)
sts = RMS$_WLD;
} else {
sts = do_search(fab,wccfile);
if ((sts & 1) == 0)
wcc_flag = 0;
}
}
} else {
@ -1173,7 +1293,7 @@ unsigned sys_erase(struct FAB *fab)
}
}
if (wcc_flag) {
cleanup_wcf(wccfile);
cleanup_wcf(&wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
}
return sts;
@ -1185,6 +1305,7 @@ unsigned sys_create(struct FAB *fab)
unsigned sts;
int ifi_no = 1;
int wcc_flag = 0;
struct WCCFILE *wccfile = NULL;
struct NAM *nam = fab->fab$l_nam;
if (fab->fab$w_ifi != 0) return RMS$_IFI;
@ -1201,6 +1322,8 @@ unsigned sys_create(struct FAB *fab)
sts = RMS$_WLD;
} else {
sts = do_search(fab,wccfile);
if ((sts & 1) == 0)
wcc_flag = 0;
if (sts == RMS$_FNF) sts = 1;
}
}
@ -1209,11 +1332,13 @@ unsigned sys_create(struct FAB *fab)
}
if (sts & 1) {
struct fibdef fibblk;
struct dsc_descriptor fibdsc,serdsc;
struct dsc_descriptor fibdsc; /* ,serdsc; */
fibdsc.dsc_w_length = sizeof(struct fibdef);
fibdsc.dsc_a_pointer = (char *) &fibblk;
/* Unused
serdsc.dsc_w_length = wccfile->wcf_wcd.wcd_reslen;
serdsc.dsc_a_pointer = wccfile->wcf_result + wccfile->wcf_wcd.wcd_prelen;
*/
memcpy(&fibblk.fib$w_did_num,&wccfile->wcf_wcd.wcd_dirid,sizeof(struct fiddef));
fibblk.fib$w_nmctl = 0;
fibblk.fib$l_acctl = 0;
@ -1233,8 +1358,10 @@ unsigned sys_create(struct FAB *fab)
fab->fab$w_ifi = ifi_no;
}
}
cleanup_wcf(wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
if( wcc_flag ) {
cleanup_wcf(&wccfile);
if (nam != NULL) nam->nam$l_wcc = 0;
}
return sts;
}

View File

@ -32,12 +32,11 @@
#define NAM$C_MAXRSS 255
#define NAM$M_SYNCHK 1
#define FAB$M_NAM 0x1000000
#define XAB$C_DAT 18
#define XAB$C_FHC 29
#define XAB$C_PRO 19
#define XAB$C_ITM 36
struct XABDAT {
void *xab$l_nxt;
@ -80,13 +79,56 @@ struct XABFHC cc$rms_xabfhc = {NULL,XAB$C_FHC,0,0,0,0,0,0,0,0,0,0};
extern struct XABFHC cc$rms_xabfhc;
#endif
#define XAB$K_SENSEMODE 1
/* #define XAB$K_SETMODE 2 */
#define XAB$_UCHAR 128
#define XAB$_UCHAR_NOBACKUP 130 /* (set,sense) FCH$V_NOBACKUP */
#define XAB$_UCHAR_WRITEBACK 131 /* (sense) FCH$V_WRITEBACK */
#define XAB$_UCHAR_READCHECK 132 /* (set,sense) FCH$V_READCHECK */
#define XAB$_UCHAR_WRITECHECK 133 /* (set,sense) FCH$V_WRITECHECK */
#define XAB$_UCHAR_CONTIGB 134 /* (set,sense) FCH$V_CONTIGB */
#define XAB$_UCHAR_LOCKED 135 /* (set,sense) FCH$V_LOCKED */
#define XAB$_UCHAR_CONTIG 136 /* (sense) FCH$V_CONTIG */
#define XAB$_UCHAR_SPOOL 138 /* (sense) FCH$V_SPOOL */
#define XAB$_UCHAR_DIRECTORY 139 /* (sense) FCH$V_DIRECTORY */
#define XAB$_UCHAR_BADBLOCK 140 /* (sense) FCH$V_BADBLOCK */
#define XAB$_UCHAR_MARKDEL 141 /* (sense) FCH$V_BADBLOCK */
struct item_list {
unsigned short int code;
unsigned short int length;
void *buffer;
int retlen;
};
struct XABITM {
void *xab$l_nxt;
int xab$b_cod;
struct item_list *xab$l_itemlist;
int xab$b_mode;
};
#ifdef RMS$INITIALIZE
struct XABITM cc$rms_xabitm = {NULL,XAB$C_ITM,NULL,0};
#else
extern struct XABITM cc$rms_xabitm;
#endif
#define xab$m_noread 1
#define xab$m_nowrite 2
#define xab$m_noexe 4
#define xab$m_nodel 8
#define xab$m_prot (xab$m_noread|xab$m_nowrite|xab$m_noexe|xab$m_nodel)
#define xab$v_system 0
#define xab$v_owner 4
#define xab$v_group 8
#define xab$v_world 12
struct XABPRO {
void *xab$l_nxt;
int xab$b_cod;
int xab$w_pro;
int xab$l_uic;
unsigned int xab$w_pro;
unsigned int xab$l_uic;
};
#ifdef RMS$INITIALIZE
@ -185,6 +227,38 @@ extern struct RAB cc$rms_rab;
#define FAB$C_STMLF 5
#define FAB$C_STMCR 6
/* FAB$L_FOP */
#define FAB$M_ASY 1
#define FAB$M_MXV 2
#define FAB$M_SUP 4
#define FAB$M_TMP 8
#define FAB$M_TMD 16
#define FAB$M_DFW 32
#define FAB$M_SQO 64
#define FAB$M_RWO 128
#define FAB$M_POS 256
#define FAB$M_WCK 512
#define FAB$M_NEF 1024
#define FAB$M_RWC 2048
#define FAB$M_DMO 4096
#define FAB$M_SPL 8192
#define FAB$M_SCF 16384
#define FAB$M_DLT 32768
#define FAB$M_NFS 65536
#define FAB$M_UFO 131072
#define FAB$M_PPF 262144
#define FAB$M_INP 524288
#define FAB$M_CTG 1048576
#define FAB$M_CBT 2097152
#define FAB$M_SYNCSTS 4194304
#define FAB$M_RCK 8388608
#define FAB$M_NAM 16777216
#define FAB$M_CIF 33554432
#define FAB$M_ESC 134217728
#define FAB$M_TEF 268435456
#define FAB$M_OFP 536870912
#define FAB$M_KFO 1073741824
struct FAB {
struct NAM *fab$l_nam;
int fab$w_ifi;
@ -195,9 +269,9 @@ struct FAB {
int fab$l_alq;
int fab$b_bks;
int fab$w_deq;
int fab$b_fsz;
unsigned int fab$b_fsz;
int fab$w_gbc;
int fab$w_mrs;
unsigned int fab$w_mrs;
int fab$l_fop;
int fab$b_org;
int fab$b_rat;

88
extracters/ods2/sysmsg.c Normal file
View File

@ -0,0 +1,88 @@
/* Timothe Litt litt _at_ acm _ddot_ org */
/* Message code translations for non-VMS systems */
#include <stdio.h>
#include <stdlib.h>
/* Should replace with lib$sys_getmsg under VMS
#ifndef VMS
*/
#include "ssdef.h"
#include "rms.h"
#include "compat.h"
static
const struct VMSMSG {
unsigned int code;
const char *const text;
} *mp, vms2text[] = {
{RMS$_BUG, "%RMS-F-BUG, fatal RMS condition detected, process deleted"},
{RMS$_DIR, "%RMS-F-DIR, error in directory name"},
{RMS$_DNF, "%RMS-E-DNF, directory not found"},
{RMS$_EOF, "%RMS-E-EOF, end of file detected"},
{RMS$_ESS, "%RMS-F-ESS, expanded string area too small"},
{RMS$_FNF, "%RMS-E-FNF, file not found"},
{RMS$_FNM, "%RMS-F-FNM, error in file name"},
{RMS$_IFI, "%RMS-F-IFI, invalid internal file identifier (IFI) value"},
{RMS$_NAM, "%RMS-F-NAM, invalid NAM block or NAM block not accessible"},
{RMS$_NMF, "%RMS-E-NMF, no more files found"},
{RMS$_RSS, "%RMS-F-RSS, invalid resultant string size"},
{RMS$_RSZ, "%RMS-F-RSZ, invalid record size"},
{RMS$_RTB, "%RMS-W-RTB, !UL byte record too large for user's buffer"},
{RMS$_WCC, "%RMS-E-WCC, invalid wild card context (WCC) value"},
{RMS$_WLD, "%RMS-F-WLD, invalid wildcard operation"},
{SS$_ABORT, "%SYSTEM-F-ABORT, abort"},
{SS$_BADFILENAME, "%SYSTEM-W-BADFILENAME, bad file name syntax"},
{SS$_BADIRECTORY, "%SYSTEM-W-BADIRECTORY, bad directory file format"},
{SS$_BADPARAM, "%SYSTEM-F-BADPARAM, bad parameter value"},
{SS$_BUGCHECK, "%SYSTEM-F-BUGCHECK, internal consistency failure"},
{SS$_DATACHECK, "%SYSTEM-F-DATACHECK, write check error"},
{SS$_DEVICEFULL, "%SYSTEM-W-DEVICEFULL, device full - allocation failure"},
{SS$_DEVMOUNT, "%SYSTEM-F-DEVMOUNT, device is already mounted"},
{SS$_DEVNOTALLOC, "%SYSTEM-W-DEVNOTALLOC, device not allocated"},
{SS$_DEVNOTDISM, "%SYSTEM-F-DEVNOTDISM, device not dismounted"},
{SS$_DEVNOTMOUNT, "%SYSTEM-F-DEVNOTMOUNT, device is not mounted"},
{SS$_DUPFILENAME, "%SYSTEM-W-DUPFILENAME, duplicate file name"},
{SS$_DUPLICATE, "%SYSTEM-F-DUPLNAM, duplicate name"},
{SS$_ENDOFFILE, "%SYSTEM-W-ENDOFFILE, end of file"},
{SS$_FILELOCKED, "%SYSTEM-W-FILELOCKED, file is deaccess locked"},
{SS$_FILESEQCHK, "%SYSTEM-W-FILESEQCHK, file identification sequence number check"},
{SS$_ILLEFC, "%SYSTEM-F-ILLEFC, illegal event flag cluster"},
{SS$_INSFMEM, "%SYSTEM-F-INSFMEM, insufficient dynamic memory"},
{SS$_ITEMNOTFOUND, "%SYSTEM-W-ITEMNOTFOUND, requested item cannot be returned"},
{SS$_IVCHAN, "%SYSTEM-F-IVCHAN, invalid I/O channel"},
{SS$_IVDEVNAM, "%SYSTEM-F-IVDEVNAM, invalid device name"},
{SS$_NOIOCHAN, "%SYSTEM-F-NOIOCHAN, no I/O channel available"},
{SS$_NOMOREFILES, "%SYSTEM-W-NOMOREFILES, no more files"},
{SS$_NORMAL, "%SYSTEM-S-NORMAL, normal successful completion"},
{SS$_NOSUCHDEV, "%SYSTEM-W-NOSUCHDEV, no such device available"},
{SS$_NOSUCHFILE, "%SYSTEM-W-NOSUCHFILE, no such file"},
{SS$_NOSUCHVOL, "%SYSTEM-E-NOSUCHVOL, No such volume"},
{SS$_NOTINSTALL, "%SYSTEM-F-NOTINSTALL, writable shareable images must be installed"},
{SS$_PARITY, "%SYSTEM-F-PARITY, parity error"},
{SS$_UNSUPVOLSET, "%SYSTEM-E-UNSUPVOLSET, Volume set not supported"},
{SS$_WASCLR, "%SYSTEM-S-NORMAL, normal successful completion"},
{SS$_WASSET, "%SYSTEM-S-WASSET, Event flag was set"},
{SS$_WRITLCK, "%SYSTEM-F-WRITLCK, write lock error"},
{0, NULL},
};
const char *getmsg( unsigned int vmscode ) {
char fmt[] = "%SYSTEM-E-NOSUCHMSG, Unknown message code %08X";
static char buf[sizeof(fmt)+8+1];
for( mp = vms2text; mp->text; mp++ ) {
if( vmscode == mp-> code ) {
return mp->text;
}
}
snprintf( buf, sizeof(buf), fmt, vmscode );
return buf;
}
/*
#endif
*/

6
extracters/ods2/sysmsg.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef SYSMSG_H
#define SYSMSG_H
const char *getmsg( unsigned int vmscode );
#endif

View File

@ -33,7 +33,7 @@ struct VCBDEV *rvn_to_dev(struct VCB *vcb,unsigned rvn);
unsigned update_freecount(struct VCBDEV *vcbdev,unsigned *retcount)
{
register unsigned sts;
register unsigned sts = 1;
register unsigned free_clusters = 0;
register unsigned map_block, map_end = (vcbdev->max_cluster + 4095) / 4096 + 2;
for (map_block = 2; map_block < map_end; ) {
@ -270,7 +270,7 @@ unsigned update_findhead(struct VCBDEV *vcbdev,unsigned *rethead_no,
*work_ptr |= 1 << bit_no;
modify_flag = 1;
if ((*headbuff)->fh2$w_checksum != 0 || (*headbuff)->fh2$w_fid.fid$w_num != 0 ||
VMSLONG((*headbuff)->fh2$l_filechar) & FH2$M_MARKDEL == 0) {
(VMSLONG((*headbuff)->fh2$l_filechar) & FH2$M_MARKDEL) == 0) {
sts = deaccesschunk(*retvioc,0,0,0);
} else {
*rethead_no = head_no + 1;
@ -302,6 +302,9 @@ unsigned update_addhead(struct VCB *vcb,char *filename,struct fiddef *back,
struct IDENT *id;
struct HEAD *head;
struct VCBDEV *vcbdev = NULL;
if( rethead != NULL ) *rethead = NULL;
for (device = 0; device < vcb->devices; device++) {
if (vcb->vcbdev[device].dev != NULL) {
if (vcb->vcbdev[device].free_clusters > free_space) {
@ -315,7 +318,7 @@ unsigned update_addhead(struct VCB *vcb,char *filename,struct fiddef *back,
sts = update_findhead(vcbdev,&head_no,vioc,&head,idxblk);
if (!(sts & 1)) return sts;
printf("Header %d index %d rvn %d\n",head_no,idxblk,rvn);
printf("Header %d index %u rvn %u\n",head_no,*idxblk,rvn);
fid->fid$w_num = head_no;
fid->fid$w_seq = ++head->fh2$w_fid.fid$w_seq;
if (fid->fid$w_seq == 0) fid->fid$w_seq = 1;
@ -354,6 +357,7 @@ unsigned update_addhead(struct VCB *vcb,char *filename,struct fiddef *back,
unsigned short check = checksum((vmsword *) head);
head->fh2$w_checksum = VMSWORD(check);
}
if( rethead != NULL ) *rethead = head;
return 1;
}
@ -424,7 +428,7 @@ unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig)
sts = bitmap_search(vcbdev,&start_pos,&block_count);
printf("Update_extend %d %d\n",start_pos,block_count);
if (sts & 1) {
if (block_count < 1 || contig && block_count * vcbdev->clustersize < blocks) {
if (block_count < 1 || (contig && block_count * vcbdev->clustersize < blocks)) {
sts = SS$_DEVICEFULL;
} else {
register unsigned short *mp;

10
extracters/ods2/version.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef VERSION_H
#define VERSION_H
#ifdef DEBUG_BUILD
#define MODULE_IDENT "Debug build"
#else
#define MODULE_IDENT "v1.4"
#endif
#endif