diff --git a/.gitignore b/.gitignore
index aff4fdb..0c3df99 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
+
diff --git a/extracters/ods2/00INSTALL.TXT b/extracters/ods2/00INSTALL.TXT
new file mode 100644
index 0000000..6fd5407
--- /dev/null
+++ b/extracters/ods2/00INSTALL.TXT
@@ -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
+
+
diff --git a/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj
new file mode 100644
index 0000000..f68ba00
--- /dev/null
+++ b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj
@@ -0,0 +1,87 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {1FF595D0-8CF9-4EF5-9A1B-A3FF3F3CF24C}
+ ODS2Image
+
+
+
+ Application
+ true
+ MultiByte
+
+
+ Application
+ false
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ DEBUG_BUILD;DISKIMAGE;_MBCS;%(PreprocessorDefinitions)
+
+
+ true
+ $(OutDir)$(TargetName)$(TargetExt)
+ $(OutDir)
+ 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)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ DISKIMAGE;_MBCS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ $(OutDir)
+ 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)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj.filters b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj.filters
new file mode 100644
index 0000000..89e4984
--- /dev/null
+++ b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj.filters
@@ -0,0 +1,54 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/extracters/ods2/ODS2.sln b/extracters/ods2/ODS2.sln
new file mode 100644
index 0000000..dc2935d
--- /dev/null
+++ b/extracters/ods2/ODS2.sln
@@ -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
diff --git a/extracters/ods2/ODS2.vcxproj b/extracters/ods2/ODS2.vcxproj
new file mode 100644
index 0000000..608aee5
--- /dev/null
+++ b/extracters/ods2/ODS2.vcxproj
@@ -0,0 +1,111 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ Win32Proj
+
+
+
+ Application
+ true
+
+
+ Application
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+ DEBUG_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDebugDLL
+ Level3
+ ProgramDatabase
+ Disabled
+
+
+ MachineX86
+ true
+ Console
+ 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)
+
+
+
+
+
+
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+
+
+ MachineX86
+ true
+ Console
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extracters/ods2/ODS2.vcxproj.filters b/extracters/ods2/ODS2.vcxproj.filters
new file mode 100644
index 0000000..046e7f0
--- /dev/null
+++ b/extracters/ods2/ODS2.vcxproj.filters
@@ -0,0 +1,110 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/extracters/ods2/aareadme.txt b/extracters/ods2/aareadme.txt
index 4e72db1..a41db49 100644
--- a/extracters/ods2/aareadme.txt
+++ b/extracters/ods2/aareadme.txt
@@ -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!!)
diff --git a/extracters/ods2/access.c b/extracters/ods2/access.c
index 916c556..67adf08 100644
--- a/extracters/ods2/access.c
+++ b/extracters/ods2/access.c
@@ -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
}
}
}
diff --git a/extracters/ods2/access.h b/extracters/ods2/access.h
index 43dc909..edc023a 100644
--- a/extracters/ods2/access.h
+++ b/extracters/ods2/access.h
@@ -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 */
diff --git a/extracters/ods2/access.h.bak b/extracters/ods2/access.h.bak
deleted file mode 100644
index 54eb28a..0000000
--- a/extracters/ods2/access.h.bak
+++ /dev/null
@@ -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);
diff --git a/extracters/ods2/build.com b/extracters/ods2/build.com
index 3b195b1..1a0ce5d 100644
--- a/extracters/ods2/build.com
+++ b/extracters/ods2/build.com
@@ -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
diff --git a/extracters/ods2/cache.c.bak b/extracters/ods2/cache.c.bak
deleted file mode 100644
index 5bfb869..0000000
--- a/extracters/ods2/cache.c.bak
+++ /dev/null
@@ -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
-#include
-#include
-#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;
-}
diff --git a/extracters/ods2/compat.c b/extracters/ods2/compat.c
new file mode 100644
index 0000000..bf2ce64
--- /dev/null
+++ b/extracters/ods2/compat.c
@@ -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
+#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
+#include
+
+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; }
diff --git a/extracters/ods2/compat.h b/extracters/ods2/compat.h
new file mode 100644
index 0000000..3676805
--- /dev/null
+++ b/extracters/ods2/compat.h
@@ -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
+
+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
+#include
+
+FILE *openf( const char *filename, const char *mode );
+
+TCHAR *w32_errstr( DWORD eno, ... );
+
+#else
+#define openf fopen
+#endif
+
+#define UNUSED(x) (void)(x)
+
+#endif
diff --git a/extracters/ods2/descrip.mms b/extracters/ods2/descrip.mms
index 35ae0e7..47b5f96 100644
--- a/extracters/ods2/descrip.mms
+++ b/extracters/ods2/descrip.mms
@@ -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)
diff --git a/extracters/ods2/direct.c b/extracters/ods2/direct.c
index aa7abd6..dde98f4 100644
--- a/extracters/ods2/direct.c
+++ b/extracters/ods2/direct.c
@@ -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);
diff --git a/extracters/ods2/diskio.c b/extracters/ods2/diskio.c
new file mode 100644
index 0000000..9305b62
--- /dev/null
+++ b/extracters/ods2/diskio.c
@@ -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
+#include
+#include
+#include
+
+#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;
+}
+
diff --git a/extracters/ods2/diskio.h b/extracters/ods2/diskio.h
new file mode 100644
index 0000000..3a31c66
--- /dev/null
+++ b/extracters/ods2/diskio.h
@@ -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
diff --git a/extracters/ods2/makefile.generic b/extracters/ods2/makefile.generic
new file mode 100644
index 0000000..da02a23
--- /dev/null
+++ b/extracters/ods2/makefile.generic
@@ -0,0 +1,95 @@
+# Generic makefile for ods2
+#
+# See makefile., 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
diff --git a/extracters/ods2/makefile.nt b/extracters/ods2/makefile.nt
index 6120065..986638b 100644
--- a/extracters/ods2/makefile.nt
+++ b/extracters/ods2/makefile.nt
@@ -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
diff --git a/extracters/ods2/makefile.solaris b/extracters/ods2/makefile.solaris
index 535f3aa..2af0778 100644
--- a/extracters/ods2/makefile.solaris
+++ b/extracters/ods2/makefile.solaris
@@ -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)
diff --git a/extracters/ods2/makefile.tru64 b/extracters/ods2/makefile.tru64
index e6305db..640e94a 100644
--- a/extracters/ods2/makefile.tru64
+++ b/extracters/ods2/makefile.tru64
@@ -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)
diff --git a/extracters/ods2/makefile.unix b/extracters/ods2/makefile.unix
index 5d123dd..8f86399 100644
--- a/extracters/ods2/makefile.unix
+++ b/extracters/ods2/makefile.unix
@@ -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)
diff --git a/extracters/ods2/ods2.c b/extracters/ods2/ods2.c
index 57fd955..69029b1 100644
--- a/extracters/ods2/ods2.c
+++ b/extracters/ods2/ods2.c
@@ -1,5 +1,6 @@
#define MODULE_NAME ODS2
-#define MODULE_IDENT "V1.3hb"
+
+/* Feb-2016, v1.4 add readline support, dir/full etc */
/* Jul-2003, v1.3hb, some extensions by Hartmut Becker */
@@ -18,15 +19,19 @@
ACCESS.C Routines for accessing ODS2 disks
CACHE.C Routines for managing memory cache
+ COMPAT.C Routines for OS compatibility
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
+ SYSMSG.C Routines to convert status codes to text
+ UPDATE.C Routines for updating ODS2 structures
VMSTIME.C Routines to handle VMS times
On non-VMS platforms PHYVMS.C should be replaced as follows:-
+ Unix PHYUNIX.C
OS/2 PHYOS2.C
Windows 95/NT PHYNT.C
@@ -35,9 +40,18 @@
gcc -fdollars-in-identifiers ods2.c,rms.c,direct.c,
access.c,device.c,cache.c,phyos2.c,vmstime.c
+
+ For accessing disk images (e.g. .ISO or simulator files),
+ replace PHYVMS.C with DISKIO.c and define DISKIMAGE
+
+ The included make/mms/com files do all this for you.
*/
/* Modified by:
+ * Feb 2016 Timothe Litt
+ * Bug fixes, readline support, build on NT without wnaspi32,
+ * Decode error messages, patch from vms2linux.de. VS project files.
+ * Rework command parsing and help. Bugs, bugs & bugs.
*
* 31-AUG-2001 01:04 Hunter Goatley
*
@@ -73,11 +87,24 @@
#define DEBUGx on
#define VMSIOx on
+#define _BSD_SOURCE
+
+#include
#include
#include
#include
#include
+#include "version.h"
+#include "compat.h"
+#ifdef DISKIMAGE
+#include "diskio.h"
+#endif
+#include "sysmsg.h"
+#include "phyio.h"
+#ifdef _WIN32
+#include
+#endif
#ifdef VMSIO
#include
@@ -85,6 +112,7 @@
#include
#include
#include
+
#define sys_parse sys$parse
#define sys_search sys$search
#define sys_open sys$open
@@ -111,11 +139,16 @@
#define PRINT_ATTR (FAB$M_CR | FAB$M_PRN | FAB$M_FTN)
-
+#ifdef USE_READLINE
+#define _XOPEN_SOURCE
+#include
+#include
+#include
+#endif
/* keycomp: routine to compare parameter to a keyword - case insensitive! */
-int keycomp(char *param,char *keywrd)
+int keycomp(const char *param, const char *keywrd)
{
while (*param != '\0') {
if (tolower(*param++) != *keywrd++) return 0;
@@ -123,31 +156,211 @@ int keycomp(char *param,char *keywrd)
return 1;
}
+/* set, clear: bits specified are cleared, then set in value
+ * helpstr: if null, switch not listed in help. If starts with -,
+ * listed as negatable in help
+ */
+struct qual {
+ const char *name;
+ int set;
+ int clear;
+ const char *helpstr;
+};
-/* checkquals: routine to find a qualifer in a list of possible values */
+struct param;
+struct CMDSET;
-int checkquals(char *qualset[],int qualc,char *qualv[])
+typedef const char * (hlpfunc_t)(struct CMDSET *cmd, struct param *p, int argc, char **argv);
+
+struct param {
+ const char *name;
+ enum parflags { REQ, OPT, CND } flags;
+ enum partype { VMSFS, LCLFS, LIST, KEYWD, STRING, CMDNAM, NONE } ptype;
+#define PA(arg) NULL, (arg)
+#define NOPA PA(NULL)
+ hlpfunc_t *hlpfnc;
+ void *arg;
+ const char *helpstr;
+};
+
+/* Command table entry */
+
+struct CMDSET {
+ char *name;
+ unsigned (*proc) (int argc,char *argv[],int qualc,char *qualv[]);
+ unsigned uniq;
+ struct qual *validquals;
+ struct param *params;
+ char *helpstr;
+};
+
+void qualhelp( int par, struct qual *qtable );
+
+/* Qualifier style = vms = /qualifier; else -option
+ */
+
+static int vms_qual = 1;
+static int verify_cmd = 1;
+
+/* checkquals: Given valid qualifier definitions, process qualifer
+ * list from a command left to right
+ */
+
+int checkquals(int result, struct qual 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;
+ int i;
+ const char *type;
+ type = (qualc < 0)? "parameter": "qualifier";
+ qualc = abs( qualc );
+
+ for( i = 0; i < qualc; i++ ) {
+ struct qual *qs, *qp = NULL;
+
+ for( qs = qualset; qs->name != NULL; qs++) {
+ if (keycomp(qualv[i],qs->name)) {
+ if( qp != NULL ) {
+ printf ( "%%ODS2-W-AMBQUAL, %c%s '%s' is ambiguous\n",
+ type[0], type+1, qualv[i] );
+ return -1;
+ }
+ qp = qs;
}
- i++;
}
- if (i >= 0) printf("%%ODS2-W-ILLQUAL, Unknown qualifer '%s' ignored\n",qualv[qualc]);
+ if (qp == NULL) {
+ printf("%%ODS2-W-ILLQUAL, Unknown %s '%s'\n", type, qualv[i]);
+ return -1;
+ }
+ result = (result & ~qp->clear) | qp->set;
}
return result;
}
+int prvmstime(VMSTIME vtime, const char *sfx) {
+ int sts = 0;
+ char tim[24];
+ static const VMSTIME nil;
+ struct dsc_descriptor timdsc;
+
+ if( memcmp( vtime, nil, sizeof(nil) ) ) {
+ timdsc.dsc_w_length = 23;
+ timdsc.dsc_a_pointer = tim;
+ sts = sys_asctim(0,&timdsc,vtime,0);
+ if ((sts & 1) == 0) printf("Asctim error: %s\n",getmsg(sts));
+ tim[23] = '\0';
+ printf(" %s",tim);
+ } else {
+ printf( " %-23s", " " );
+ sts = 1;
+ }
+ if (sfx != NULL)
+ printf( "%s", sfx );
+ return sts;
+}
+
+void pwrap( int *pos, const char *fmt, ... ) {
+ char pbuf[200], *p, *q;
+ va_list ap;
+ va_start(ap, fmt );
+ vsnprintf( pbuf, sizeof(pbuf), fmt, ap );
+ va_end(ap);
+ p = pbuf;
+ while( *p ) {
+ int len;
+ int eol = 0;
+
+ q = strchr( p, '\n' );
+ if( q != NULL ) {
+ *q++ = '\0';
+ eol = 1;
+ len = strlen(p);
+ } else {
+ len = strlen(p);
+ q = p + len;
+ }
+ if( *pos + len > 80 ) {
+ static const char wrap[] = " ";
+ printf( "\n%s", wrap );
+ *pos = sizeof(wrap) -1;
+ if( p[0] == ',' && p[1] == ' ' )
+ p += 2;
+ }
+ *pos += strlen(p);
+ printf( "%s%s", p, eol? "\n":"" );
+ if( eol ) *pos = 0;
+ p = q;
+ }
+}
+
/* dir: a directory routine */
-char *dirquals[] = {"date","file","size",NULL};
+#define dir_extra (dir_date|dir_fileid|dir_owner|dir_prot|dir_size|dir_allocated)
+#define dir_date 1
+#define dir_fileid 2
+#define dir_owner 4
+#define dir_prot 8
+#define dir_size 16
+#define dir_allocated 32
+
+#define dir_grand 64
+#define dir_heading 128
+#define dir_names 256
+#define dir_trailing 512
+#define dir_full 1024
+#define dir_total 2048
+
+#define dir_default (dir_heading|dir_names|dir_trailing)
+
+struct qual dirquals[] = { {"allocated", dir_allocated, 0, "-Include allocated file size (blocks)" },
+ {"noallocated", 0, dir_allocated, NULL },
+ {"brief", dir_default, ~dir_default, "Brief display - names with header/trailer (default)"},
+ {"date", dir_date, 0, "-Include file creation date", },
+ {"nodate", 0, dir_date, NULL, },
+ {"file_id", dir_fileid, 0, "-Include file ID", },
+ {"nofile_id", 0, dir_fileid, NULL },
+ {"full", dir_full|dir_heading|dir_trailing,
+ ~dir_full, "Include full details", },
+ {"grand_total", dir_grand, ~dir_grand & ~(dir_size|dir_allocated),
+ "-Include only grand total",},
+ {"nogrand_total", 0, dir_grand, NULL},
+ {"heading", dir_heading, 0, "-Include heading", },
+ {"noheading", 0, dir_heading, NULL},
+ {"owner", dir_owner, 0, "-Include file owner", },
+ {"noowner", 0, dir_owner, NULL, },
+ {"protection", dir_prot, 0, "-Include file protection", },
+ {"noprotection", 0, dir_prot, NULL, },
+ {"size", dir_size, 0, "-Include file size (blocks)", },
+ {"nosize", 0, dir_size, NULL, },
+ {"total", dir_total|dir_heading,
+ ~dir_total & ~(dir_size|dir_allocated),
+ "Include only directory name and summary",},
+ {"trailing", dir_trailing, 0, "-Include trailing summary line",},
+ {"notrailing", 0, dir_trailing, NULL},
+ {NULL, 0, 0, NULL} };
+int dir_defopt = dir_default;
+
+struct param dirpars[] = { {"filespec", OPT, VMSFS, NOPA, "for files to select. Wildcards are allowed."},
+ { NULL, 0, 0, NOPA, NULL }
+};
+
+void dirtotal( int options, int size, int alloc ) {
+ if ( !(options & (dir_size | dir_allocated)) )
+ return;
+ fputs( ", ", stdout );
+
+ if ( options & dir_size )
+ printf( "%d", size );
+ if ( options & dir_allocated ) {
+ if (options & dir_size) printf( "/" );
+ printf( "%d", alloc );
+ }
+ if ((options & (dir_size|dir_allocated)) == (dir_size|dir_allocated))
+ printf( " block%s",(size ==1 && alloc == 1 ? "" : "s"));
+ else
+ printf( " block%s",(((options & dir_size) && size == 1) ||
+ ((options & dir_allocated) && alloc == 1))? "" : "s");
+ return;
+}
unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
{
@@ -158,23 +371,64 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
struct FAB fab = cc$rms_fab;
struct XABDAT dat = cc$rms_xabdat;
struct XABFHC fhc = cc$rms_xabfhc;
+ struct XABPRO pro = cc$rms_xabpro;
+ struct XABITM itm = cc$rms_xabitm;
+ int nobackup = 0, contigb = 0, contig = 0, directory = 0;
+ struct item_list xitems[] = {
+ { XAB$_UCHAR_NOBACKUP, sizeof(int), NULL, 0 },
+ { XAB$_UCHAR_CONTIG, sizeof(int), NULL, 0 },
+ { XAB$_UCHAR_CONTIGB, sizeof(int), NULL, 0 },
+ { XAB$_UCHAR_DIRECTORY, sizeof(int), NULL, 0 },
+ { 0, 0, NULL, 0 }
+ };
+ UNUSED(argc);
+
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;
+
+ fhc.xab$l_nxt = &pro;
+
+ pro.xab$l_nxt = &itm;
+ xitems[0].buffer = &nobackup;
+ xitems[1].buffer = &contig;
+ xitems[2].buffer = &contigb;
+ xitems[3].buffer = &directory;
+
+ itm.xab$b_mode = XAB$K_SENSEMODE;
+ itm.xab$l_itemlist = xitems;
+
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);
+
+ options = checkquals(dir_defopt,dirquals,qualc,qualv);
+ if( options == -1 )
+ return SS$_BADPARAM;
+
+ if (options & dir_full)
+ options |= dir_extra;
+ if (options & (dir_total | dir_grand)) {
+ options |= dir_trailing;
+ if (options & (dir_extra & ~(dir_size|dir_allocated)))
+ options |= dir_names;
+ } else {
+ if (options & dir_extra)
+ options |= dir_names;
+ }
+
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 dirblocks = 0, diralloc = 0, totblocks = 0, totalloc = 0;
int printcol = 0;
#ifdef DEBUG
res[nam.nam$b_esl] = '\0';
@@ -184,109 +438,228 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
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 (dirfiles > 0 && (options & dir_trailing)) {
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);
- }
+ dirtotal( options, dirblocks, diralloc );
+ 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);
+ if( options & dir_heading) printf("\nDirectory %s\n\n",dir);
filecount += dirfiles;
totblocks += dirblocks;
+ totalloc += diralloc;
dircount++;
dirfiles = 0;
dirblocks = 0;
+ diralloc = 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;
+ if ((options & (dir_heading|dir_extra|dir_full)) == dir_heading) {
+ if( options & dir_names ) {
+ 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;
}
- fputs(rsa + dirlen,stdout);
- printcol += namelen;
} else {
- if (namelen > 18) {
- printf("%s\n ",rsa + dirlen);
- } else {
- printf("%-19s",rsa + dirlen);
+ if (options & dir_names) {
+ if ( (options & dir_heading) == 0 ) printf( "%s",dir );
+ if (namelen > 18) {
+ printf("%s",rsa + dirlen);
+ if( options & dir_extra )
+ printf( "\n " );
+ } else {
+ printf("%-19s",rsa + dirlen);
+ }
}
sts = sys_open(&fab);
if ((sts & 1) == 0) {
- printf("Open error: %d\n",sts);
+ printf("Open error: %s\n", getmsg(sts));
} else {
sts = sys_close(&fab);
- if (options & 2) {
- char fileid[100];
- sprintf(fileid,"(%d,%d,%d)",
+ if (options & dir_fileid) {
+ char fileid[30]; /* 24 bits, 16 bits. 8 bits = 8 + 5 + 3 digits = 16 + (,,)\0 => 21 */
+ if( options & dir_full) printf( " File ID:" );
+ snprintf(fileid,sizeof(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) {
+ diralloc += fab.fab$l_alq;
+ if (options & dir_size) {
unsigned filesize = fhc.xab$l_ebk;
if (fhc.xab$w_ffb == 0) filesize--;
- printf("%9d",filesize);
dirblocks += filesize;
+
+ if (options & dir_names) { /* Don't print w/o names (e.g. totals) */
+ if( options & dir_full) printf( "\nSize: " );
+ printf("%9d",filesize);
+ if( options & (dir_allocated|dir_full)) printf( "/%-9d ",fab.fab$l_alq );
+ }
+ } else {
+ if ( (options & (dir_allocated|dir_names)) == (dir_allocated|dir_names)) {
+ printf( "%9d", fab.fab$l_alq );
+ }
}
- 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);
+#define pprot(val,pos,del) {\
+ unsigned int v = ~(((val) >> (pos)) & xab$m_prot); \
+ if( v & xab$m_noread ) printf( "R" ); \
+ if( v & xab$m_nowrite ) printf( "W" ); \
+ if( v & xab$m_noexe ) printf( "E" ); \
+ if( v & xab$m_nodel ) printf( "D" ); \
+ printf( del ); \
+ }
+ if (options & dir_full) {
+ int pos = 0;
+
+ printf( "Owner: [%o,%o]\n", ((pro.xab$l_uic>>16)&0xFFFF), pro.xab$l_uic&0xFFFF);
+ printf( "Created: " ); prvmstime( dat.xab$q_cdt, "\n" );
+ printf( "Revised: " ); prvmstime( dat.xab$q_rdt, " (" ); printf( "%u)\n", dat.xab$w_rvn );
+ printf( "Expires: " ); prvmstime( dat.xab$q_edt, "\n" );
+ printf( "Backup: " ); prvmstime( dat.xab$q_bdt, "\n" );
+ pwrap( &pos, "File organization: " );
+ switch( fab.fab$b_org ) {
+ case FAB$C_SEQ:
+ pwrap( &pos, "Sequential" ); break;
+ case FAB$C_REL:
+ pwrap( &pos, "Relative" /*, Maximum record number %u", fab.fab$l_mrn*/ ); break;
+ case FAB$C_IDX:
+ pwrap( &pos, "Indexed" ); break; /*, Prolog: 3, Using 4 keys\nIn 3 areas */
+ default:
+ pwrap( &pos, "Unknown (%u)", fab.fab$b_org ); break;
+ }
+ /* File attributes: Allocation: 372, Extend: 3, Maximum bucket size: 3, Global buffer count: 0, No version limit
+ Contiguous best try */
+ pwrap( &pos, "\nFile attributes: " );
+ pwrap( &pos, "Allocation: %u", fab.fab$l_alq );
+ pwrap( &pos, ", Extend: %u", fab.fab$w_deq );
+ /* Missing: , Maximum bucket size: n*/
+ pwrap( &pos, ", Global buffer count: %u", fab.fab$w_gbc );
+ if( fhc.xab$w_verlimit == 0 || fhc.xab$w_verlimit == 32767 )
+ pwrap( &pos, ", No %sversion limit", directory? "default ": "" );
+ else
+ pwrap( &pos, ", %sersion limit: %u", (directory? "Default v": "V"), fhc.xab$w_verlimit );
+ if( contig )
+ pwrap( &pos, ", Contiguous" );
+ if( contigb )
+ pwrap( &pos, ", Contiguous best try" );
+ if( nobackup )
+ pwrap( &pos, ", Backups disabled" );
+ if( directory )
+ pwrap( &pos, ", Directory file" );
+ pwrap( &pos, "\n" );
+
+ pwrap( &pos, "Record format: " );
+ switch( fab.fab$b_rfm ) {
+ default:
+ case FAB$C_UDF:
+ pwrap( &pos, "Undefined" ); break;
+ case FAB$C_FIX:
+ pwrap( &pos, "Fixed length %u byte records", fab.fab$w_mrs ); break;
+ case FAB$C_VAR:
+ pwrap( &pos, "Variable length, maximum %u bytes", fab.fab$w_mrs ); break;
+ case FAB$C_VFC :
+ pwrap( &pos, "Variable length, fixed carriage control %u, maximum %u bytes", fab.fab$w_mrs ); break;
+ case FAB$C_STM:
+ pwrap( &pos, "Stream" ); break;
+ case FAB$C_STMLF:
+ pwrap( &pos, "Stream-LF" ); break;
+ case FAB$C_STMCR:
+ pwrap( &pos, "Stream-CR" ); break;
+ }
+ pwrap( &pos, "\n" );
+
+ pwrap( &pos, "Record attributes: " );
+ if( fab.fab$b_rat == 0 )
+ pwrap( &pos, "None" );
+ else {
+ const char *more = "";
+ if( fab.fab$b_rat & FAB$M_FTN ) {
+ pwrap( &pos, "%sFortran carriage control", more );
+ more = ", ";
+ }
+ if( fab.fab$b_rat & FAB$M_CR ) {
+ pwrap( &pos, "%sCarriage return carriage control", more );
+ more = ", ";
+ }
+ if( fab.fab$b_rat & FAB$M_PRN ) {
+ pwrap( &pos, "%sPrinter control", more );
+ more = ", ";
+ }
+ if( fab.fab$b_rat & FAB$M_BLK ) {
+ pwrap( &pos, "%sNon-spanned", more );
+ }
+ }
+ printf( "\n" );
+ /*
+RMS attributes: None
+Journaling enabled: None
+*/
+ printf( "File protection: System:" );
+ pprot(pro.xab$w_pro,xab$v_system,", Owner:")
+ pprot(pro.xab$w_pro,xab$v_owner,", Group:")
+ pprot(pro.xab$w_pro,xab$v_group,", World:")
+ pprot(pro.xab$w_pro,xab$v_world,"\n");
+ } else { /* !full */
+ if (options & dir_date) {
+ sts = prvmstime( dat.xab$q_cdt, NULL );
+ }
+ if (options & dir_owner) {
+ printf(" [%o,%o]", ((pro.xab$l_uic>>16)&0xFFFF), pro.xab$l_uic&0xFFFF);
+ }
+ if (options & dir_prot) {
+ printf( " (" );
+ pprot(pro.xab$w_pro,xab$v_system,",")
+ pprot(pro.xab$w_pro,xab$v_owner,",")
+ pprot(pro.xab$w_pro,xab$v_group,",")
+ pprot(pro.xab$w_pro,xab$v_world,")")
+ }
}
- printf("\n");
+#undef pprot
+ if (options & dir_names)
+ printf("\n");
}
}
dirfiles++;
}
if (sts == RMS$_NMF) sts = 1;
if (printcol > 0) printf("\n");
- if (dirfiles > 0) {
+ if (options & dir_trailing) {
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);
- }
- }
+ dirtotal( options, dirblocks, diralloc );
+ fputs(".\n",stdout);
+ }
+ filecount += dirfiles;
+ totblocks += dirblocks;
+ totalloc += diralloc;
+ if (options & dir_grand) {
+ printf("\nGrand total of %d director%s, %d file%s",
+ dircount,(dircount == 1 ? "y" : "ies"),
+ filecount,(filecount == 1 ? "" : "s"));
+ dirtotal( options, totblocks, totalloc );
+ 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);
+ printf("%%DIR-E-ERROR Status: %s\n",getmsg(sts));
}
return sts;
}
@@ -295,8 +668,15 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
/* copy: a file copy routine */
#define MAXREC 32767
+struct qual copyquals[] = { {"ascii", 0, 1, "Copy file in ascii mode (default)"},
+ {"binary", 1, 0, "Copy file in binary mode", },
+ {NULL, 0, 0, NULL}
+ };
-char *copyquals[] = {"binary",NULL};
+struct param copypars[] = { {"from_filespec", REQ, VMSFS, NOPA, "for source file. Wildcards are allowed."},
+ {"to_filespec", REQ, LCLFS, NOPA, "for destination file. Wildcards are replaced from source file name."},
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
{
@@ -305,12 +685,17 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
struct FAB fab = cc$rms_fab;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
int filecount = 0;
+
+ UNUSED(argc);
+
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);
- options = checkquals(copyquals,qualc,qualv);
+ options = checkquals(0,copyquals,qualc,qualv);
+ if( options == -1 )
+ return SS$_BADPARAM;
sts = sys_parse(&fab);
if (sts & 1) {
nam.nam$l_rsa = rsa;
@@ -319,7 +704,7 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
while ((sts = sys_search(&fab)) & 1) {
sts = sys_open(&fab);
if ((sts & 1) == 0) {
- printf("%%COPY-F-OPENFAIL, Open error: %d\n",sts);
+ printf("%%COPY-F-OPENFAIL, Open error: %s\n",getmsg(sts));
perror("-COPY-F-ERR ");
} else {
struct RAB rab = cc$rms_rab;
@@ -355,12 +740,12 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
*out++ = '\0';
}
#ifndef _WIN32
- tof = fopen(name,"w");
+ tof = openf(name,"w");
#else
if ((options & 1) == 0 && fab.fab$b_rat & PRINT_ATTR) {
- tof = fopen(name,"w");
+ tof = openf(name,"w");
} else {
- tof = fopen(name,"wb");
+ tof = openf(name,"wb");
}
#endif
if (tof == NULL) {
@@ -394,7 +779,7 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
printf("%%COPY-S-COPIED, %s copied to %s (%d record%s)\n",
rsa,name,records,(records == 1 ? "" : "s"));
} else {
- printf("%%COPY-F-ERROR Status: %d for %s\n",sts,rsa);
+ printf("%%COPY-F-ERROR Status: %s for %s\n",getmsg(sts),rsa);
sts = 1;
}
}
@@ -407,19 +792,28 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
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);
+ printf("%%COPY-F-ERROR Status: %s\n",getmsg(sts));
}
return sts;
}
/* import: a file copy routine */
+struct param importpars[] = { {"from_filespec", REQ, LCLFS, NOPA, "for source file."},
+ {"to_filespec", REQ, VMSFS, NOPA, "for destination file."},
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned import(int argc,char *argv[],int qualc,char *qualv[])
{
- int sts;
+ int sts = 0;
FILE *fromf;
- fromf = fopen(argv[1],"r");
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
+ fromf = openf(argv[1],"r");
if (fromf != NULL) {
struct FAB fab = cc$rms_fab;
fab.fab$l_fna = argv[2];
@@ -442,7 +836,7 @@ unsigned import(int argc,char *argv[],int qualc,char *qualv[])
}
fclose(fromf);
if (!(sts & 1)) {
- printf("%%IMPORT-F-ERROR Status: %d\n",sts);
+ printf("%%IMPORT-F-ERROR Status: %s\n",getmsg(sts));
}
} else {
printf("Can't open %s\n",argv[1]);
@@ -453,15 +847,24 @@ unsigned import(int argc,char *argv[],int qualc,char *qualv[])
/* diff: a simple file difference routine */
+struct param diffpars[] = { {"ods-2_filespec", REQ, VMSFS, NOPA, "for file on ODS-2 volume."},
+ {"local__filespec", REQ, LCLFS, NOPA, "for file on local filesystem."},
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
struct FAB fab = cc$rms_fab;
FILE *tof;
int records = 0;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
- tof = fopen(argv[2],"r");
+ tof = openf(argv[2],"r");
if (tof == NULL) {
printf("Could not open file %s\n",argv[1]);
sts = 0;
@@ -474,9 +877,10 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while ((sts = sys_get(&rab)) & 1) {
- strcpy(rec + rab.rab$w_rsz,"\n");
+ rec[rab.rab$w_rsz++] = '\n';
+ rec[rab.rab$w_rsz] = '\0';
fgets(cpy,MAXREC,tof);
- if (strcmp(rec,cpy) != 0) {
+ if (rab.rab$w_rsz != strlen( cpy ) || memcmp(rec,cpy,rab.rab$w_rsz) != 0) {
printf("%%DIFF-F-DIFFERENT Files are different!\n");
sts = 4;
break;
@@ -494,7 +898,7 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
if (sts & 1) {
printf("%%DIFF-I-Compared %d records\n",records);
} else {
- printf("%%DIFF-F-Error %d in difference\n",sts);
+ printf("%%DIFF-F-Error %s in difference\n",getmsg(sts));
}
return sts;
}
@@ -502,11 +906,19 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
/* typ: a file TYPE routine */
+struct param typepars[] = { {"filespec", REQ, VMSFS, NOPA, "for file on ODS-2 volume."},
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
int records = 0;
struct FAB fab = cc$rms_fab;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
if ((sts = sys_open(&fab)) & 1) {
@@ -529,7 +941,7 @@ unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
if (sts == RMS$_EOF) sts = 1;
}
if ((sts & 1) == 0) {
- printf("%%TYPE-F-ERROR Status: %d\n",sts);
+ printf("%%TYPE-F-ERROR Status: %s\n",getmsg(sts));
}
return sts;
}
@@ -538,6 +950,11 @@ unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
/* search: a simple file search routine */
+struct param searchpars[] = { {"filespec", REQ, VMSFS, NOPA, "for file to search. Wildcards are allowed."},
+ {"string", REQ, STRING, NOPA, "string to search for."},
+ { NULL, 0, 0, NOPA, NULL }
+};
+
unsigned search(int argc,char *argv[],int qualc,char *qualv[])
{
int sts = 0;
@@ -549,6 +966,11 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
register char *searstr = argv[2];
register char firstch = tolower(*searstr++);
register char *searend = searstr + strlen(searstr);
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
{
char *str = searstr;
while (str < searend) {
@@ -573,7 +995,7 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
while ((sts = sys_search(&fab)) & 1) {
sts = sys_open(&fab);
if ((sts & 1) == 0) {
- printf("%%SEARCH-F-OPENFAIL, Open error: %d\n",sts);
+ printf("%%SEARCH-F-OPENFAIL, Open error: %s\n",getmsg(sts));
} else {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
@@ -630,7 +1052,7 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
if (findcount < 1) printf("%%SEARCH-I-NOMATCHES, no strings matched\n");
}
} else {
- printf("%%SEARCH-F-ERROR Status: %d\n",sts);
+ printf("%%SEARCH-F-ERROR Status: %s\n",getmsg(sts));
}
return sts;
}
@@ -638,6 +1060,14 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
/* del: you don't want to know! */
+struct qual delquals[] = { {"log", 1, 0, "-List name of each file deleted. (Default)"},
+ {"nolog", 0, 1, NULL },
+ { NULL, 0, 0, NULL }
+};
+struct param delpars[] = { {"filespec", REQ, VMSFS, NOPA, "for files to be deleted from ODS-2 volume. Wildcards are permitted.."},
+ { NULL, 0, 0, NOPA, NULL }
+};
+
unsigned del(int argc,char *argv[],int qualc,char *qualv[])
{
int sts = 0;
@@ -645,6 +1075,14 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
struct FAB fab = cc$rms_fab;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
int filecount = 0;
+ int options;
+
+ UNUSED(argc);
+
+ options = checkquals(1,delquals,qualc,qualv);
+ if( options == -1 )
+ return SS$_BADPARAM;
+
nam.nam$l_esa = res;
nam.nam$b_ess = NAM$C_MAXRSS;
fab.fab$l_nam = &nam;
@@ -654,40 +1092,55 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
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++;
+ return SS$_BADPARAM;
+ }
+
+ 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: %s\n",getmsg(sts));
+ break;
+ } else {
+ filecount++;
+ if( options & 1 ) {
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);
}
+ 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: %s\n",getmsg(sts));
+ }
+
return sts;
}
/* test: you don't want to know! */
+
+struct param testpars[] = { {"parameter", REQ, STRING, NOPA, "for test."},
+ { NULL, 0, 0, NOPA, NULL }
+};
+
struct VCB *test_vcb;
unsigned test(int argc,char *argv[],int qualc,char *qualv[])
{
int sts = 0;
struct fiddef fid;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
sts = update_create(test_vcb,NULL,"Test.File",&fid,NULL);
printf("Test status of %d (%s)\n",sts,argv[1]);
return sts;
@@ -695,10 +1148,18 @@ unsigned test(int argc,char *argv[],int qualc,char *qualv[])
/* more test code... */
+struct param extendpars[] = { {"ods-2_filespec", REQ, VMSFS, NOPA, "for file on ODS-2 volume."},
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned extend(int argc,char *argv[],int qualc,char *qualv[])
{
int sts;
struct FAB fab = cc$rms_fab;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
fab.fab$b_fac = FAB$M_UPD;
@@ -708,20 +1169,93 @@ unsigned extend(int argc,char *argv[],int qualc,char *qualv[])
sys_close(&fab);
}
if ((sts & 1) == 0) {
- printf("%%EXTEND-F-ERROR Status: %d\n",sts);
+ printf("%%EXTEND-F-ERROR Status: %s\n",getmsg(sts));
}
return sts;
}
+#if defined( _WIN32 ) && !defined( DISKIMAGE )
+char *driveFromLetter( const char *letter ) {
+ DWORD rv = ERROR_INSUFFICIENT_BUFFER;
+ size_t cs = 16;
+ TCHAR *bufp = NULL;
+ do {
+ if( rv == ERROR_INSUFFICIENT_BUFFER ) {
+ TCHAR *newp;
+ cs *= 2;
+ newp = (TCHAR *) realloc( bufp, cs );
+ if( newp == NULL )
+ break;
+ bufp = newp;
+ }
+ rv = QueryDosDevice( letter, bufp, cs );
+ if( rv == 0 ) {
+ rv = GetLastError();
+ continue;
+ }
+ return bufp;
+ } while( rv == ERROR_INSUFFICIENT_BUFFER );
+
+ free( bufp );
+ return NULL;
+}
+#endif
+
+/* show: version */
+
+#define MNAMEX(n) #n
+#define MNAME(n) MNAMEX(n)
+
+void show_version( void ) {
+ printf(" %s %s", MNAME(MODULE_NAME), MODULE_IDENT );
+#ifdef DISKIMAGE
+ printf( " for image files" );
+#endif
+#ifdef USE_READLINE
+ printf(" with readline version %s", rl_library_version );
+#endif
+#ifdef USE_WNASPI32
+# ifdef USE_READLINE
+ printf( " and" );
+# else
+ printf( " with" );
+# endif
+ printf( " direct SCSI access support");
+#endif
+ printf( "\n\n" );
+ return;
+}
/* show: the show command */
-unsigned show(int argc,char *argv[],int qualc,char *qualv[])
-{
- unsigned sts = 1;
- if (keycomp(argv[1],"default")) {
+struct qual showkwds[] = { {"default", 0, 0, "Default directory"},
+#if defined(DISKIMAGE) || defined(_WIN32)
+ {"devices", 1, 0, "Devices"},
+#endif
+ {"qualifier_style", 2, 0, "Qualifier style (Unix, VMS)" },
+ {"time", 3, 0, "Time"},
+ {"verify", 4, 0, "Command file echo" },
+ {"version", 5, 0, "Version"},
+ {NULL, 0, 0, NULL }
+};
+struct param showpars[] = { {"item_name", REQ, KEYWD, PA(showkwds), NULL },
+ {NULL, 0, 0, NOPA, NULL }
+};
+unsigned show(int argc,char *argv[],int qualc,char *qualv[]) {
+ int parnum;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
+ parnum = checkquals( 0, showkwds, -1, argv+1 );
+ switch( parnum ) {
+ default:
+ return SS$_BADPARAM;
+ case 0: {
+ int sts;
unsigned short curlen;
char curdir[NAM$C_MAXRSS + 1];
struct dsc_descriptor curdsc;
@@ -731,28 +1265,85 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[])
curdir[curlen] = '\0';
printf(" %s\n",curdir);
} else {
- printf("Error %d getting default\n",sts);
+ printf("Error %s getting default\n",getmsg(sts));
}
- } else {
- if (keycomp(argv[1],"time")) {
- unsigned sts;
- char timstr[24];
- unsigned short timlen;
- struct dsc_descriptor timdsc;
- timdsc.dsc_w_length = 20;
- timdsc.dsc_a_pointer = timstr;
- sts = sys_asctim(&timlen,&timdsc,NULL,0);
- if (sts & 1) {
- timstr[timlen] = '\0';
- printf(" %s\n",timstr);
- } else {
- printf("%%SHOW-W-TIMERR error %d\n",sts);
- }
+ return sts;
+ }
+ case 2:
+ printf ( " Qualifier style: %s\n", vms_qual? "/VMS": "-unix" );
+ return SS$_NORMAL;
+ case 3: {
+ unsigned sts;
+ char timstr[24];
+ unsigned short timlen;
+ struct dsc_descriptor timdsc;
+
+ timdsc.dsc_w_length = 20;
+ timdsc.dsc_a_pointer = timstr;
+ sts = sys_asctim(&timlen,&timdsc,NULL,0);
+ if (sts & 1) {
+ timstr[timlen] = '\0';
+ printf(" %s\n",timstr);
} else {
- printf("%%SHOW-W-WHAT '%s'?\n",argv[1]);
+ printf("%%SHOW-W-TIMERR error %s\n",getmsg(sts));
}
}
- return sts;
+ return SS$_NORMAL;
+ case 4:
+ printf( "Command file verification is %s\n", (verify_cmd? "on": "off") );
+ return SS$_NORMAL;
+ case 5:
+ show_version();
+ return SS$_NORMAL;
+
+#if defined( _WIN32 ) && !defined( DISKIMAGE )
+ case 1: {
+ TCHAR *namep = NULL, *dname = NULL;
+ TCHAR devname[sizeof("Z:")];
+ int n = 0;
+ TCHAR l;
+
+ for( l = 'A'; l <= 'Z'; l++ ) {
+ snprintf( devname, sizeof( devname ), "%c:", l );
+ dname = namep = driveFromLetter( devname );
+ if( namep != NULL ) {
+ const char *type = NULL;
+#define WINDEVPFX "\\Device\\"
+ if( strncmp( dname, WINDEVPFX, sizeof(WINDEVPFX)-1 ) == 0 )
+ dname += sizeof( WINDEVPFX ) -1;
+#undef WINDEVPFX
+ if( !n++ )
+ printf( "Drv Type PhysicalName\n"
+ "--- --------- ------------\n" );
+ printf( " %s ", devname );
+ switch( GetDriveType( devname ) ) {
+ case DRIVE_REMOVABLE:
+ type = "Removable"; break;
+ case DRIVE_FIXED:
+ type = "Fixed"; break;
+ case DRIVE_REMOTE:
+ type = "Network";
+ dname = NULL; break;
+ case DRIVE_CDROM:
+ type = "CDROM"; break;
+ case DRIVE_RAMDISK:
+ type = "RAMdisk"; break;
+ default:
+ type = "Other";
+ dname = NULL; break;
+ }
+ printf( "%-9s %s\n", type, (dname? dname: "") );
+ free(namep);
+ }
+ }
+ }
+ return SS$_NORMAL;
+#endif
+#ifdef DISKIMAGE
+ case 1:
+ return diskio_showdrives();
+#endif
+ }
}
unsigned setdef_count = 0;
@@ -766,23 +1357,122 @@ void setdef(char *newdef)
if ((sts = sys_setddir(&defdsc,NULL,NULL)) & 1) {
setdef_count++;
} else {
- printf("Error %d setting default to %s\n",sts,newdef);
+ printf("Error %s setting default to %s\n",getmsg(sts),newdef);
}
}
/* set: the set command */
-unsigned set(int argc,char *argv[],int qualc,char *qualv[])
-{
- unsigned sts = 1;
- if (keycomp(argv[1],"default")) {
- setdef(argv[2]);
- } else {
- printf("%%SET-W-WHAT '%s'?\n",argv[1]);
+hlpfunc_t sethelp;
+
+struct qual setkwds[] = { {"default", 0, 0, "Default directory"},
+ {"directory_qualifiers", 1, 0, "Default qualifiers for DIRECTORY command" },
+ {"qualifier_style", 2, 0, "Qualifier style (Unix, VMS)" },
+ {"verify", 3, 0, "-Display commands in indirect files" },
+ {"noverify", 4, 0, NULL },
+ {NULL, 0, 0, NULL }
+};
+struct qual setqskwds[] = {{"unix", 1, 0, "Unix style options, '-option'"},
+ {"vms", 2, 0, "VMS style qualifiers, '/qualifier'"},
+ {NULL, 0, 0, NULL }
+};
+struct param setpars[] = { {"item_name", REQ, KEYWD, PA(setkwds), NULL },
+ {"value" , CND, KEYWD, sethelp, setqskwds, NULL },
+ {NULL, 0, 0, NOPA, NULL },
+};
+
+const char * sethelp( struct CMDSET *cmd, struct param *p, int argc, char **argv ) {
+ int par;
+
+ UNUSED( cmd );
+ UNUSED( argc );
+
+ if( argc == 1 ) {
+ p->helpstr = "";
+ p->ptype = KEYWD;
+ p->arg = setkwds;
+ return "Type 'help set value ITEM' for item details\n";
}
- return sts;
+
+ par = checkquals( 0, setkwds, -1, argv+1 );
+ if( par == -1 )
+ return NULL;
+ switch( par ) {
+ case 0:
+ p->helpstr = "default directory on volume - ";
+ p->ptype = VMSFS;
+ break;
+ case 1:
+ p->helpstr = "directory qualifier name ";
+ p->ptype = KEYWD;
+ p->arg = dirquals;
+ break;
+ case 2:
+ p->helpstr = "style ";
+ p->ptype = KEYWD;
+ p->arg = setqskwds;
+ break;
+ case 3:
+ case 4:
+ p->ptype = NONE;
+ break;
+
+ default:
+ abort();
+ }
+ return NULL;
}
+unsigned set(int argc,char *argv[],int qualc,char *qualv[])
+{
+ int parnum;
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
+ parnum = checkquals( 0, setkwds, -1, argv+1 );
+ switch( parnum ) {
+ default:
+ return SS$_BADPARAM;
+ case 0: /* default */
+ if( qualc ) {
+ printf( "No qualifiers are permitted\n" );
+ return 0;
+ }
+ setdef(argv[2]);
+ return 1;
+ case 1:{ /* directory_qualifiers */
+ int options = checkquals(dir_default,dirquals,qualc,qualv);
+ if( options == -1 )
+ return SS$_BADPARAM;
+ dir_defopt = options;
+ return 1;
+ }
+ case 2: { /* qualifier_style */
+ int par = checkquals (0,setqskwds,1,argv+2);
+ if( par == -1 )
+ return SS$_BADPARAM;
+ switch(par) {
+ default:
+ abort();
+ case 2:
+ vms_qual = 1;
+ break;
+ case 1:
+ vms_qual = 0;
+ break;
+ }
+ return 1;
+ }
+ case 3:
+ verify_cmd = 1;
+ return 1;
+ case 4:
+ verify_cmd = 0;
+ return 1;
+ }
+}
#ifndef VMSIO
@@ -791,21 +1481,41 @@ unsigned set(int argc,char *argv[],int qualc,char *qualv[])
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);
+ int sts = device_lookup(strlen(argv[1]),argv[1],0,&dev);
+
+ UNUSED(argc);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
if (sts & 1) {
if (dev->vcb != NULL) {
sts = dismount(dev->vcb);
+#ifdef DISKIMAGE
+ sts = diskio_unmapdrive( dev->devnam );
+#endif
} else {
sts = SS$_DEVNOTMOUNT;
}
}
- if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %d\n",sts);
+ if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %s\n",getmsg(sts));
return sts;
}
+#define mnt_write 1
-
-char *mouquals[] = {"write",NULL};
+struct qual mouquals[] = { {"readonly", 0, mnt_write,"Only allow reading from volume"},
+ {"write", mnt_write, 0, "Allow writing to volume", },
+ {NULL, 0, 0, NULL } };
+struct param moupars[] = { {"volumes", REQ, LIST, NOPA,
+#ifdef DISKIMAGE
+"disk images in volume set separated by comma"
+#else
+"devices in volume set separated by comma"
+#endif
+ },
+ {"labels", OPT, LIST, NOPA, "volume labels separated by comma" },
+ { NULL, 0, 0, NOPA, NULL }
+};
unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
{
@@ -813,7 +1523,14 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
char *lab = argv[2];
int sts = 1,devices = 0;
char *devs[100],*labs[100];
- int options = checkquals(mouquals,qualc,qualv);
+ int options;
+
+ options = checkquals(0,mouquals,qualc,qualv);
+ if( options == -1 )
+ return SS$_BADPARAM;
+
+ UNUSED(argc);
+
while (*lab != '\0') {
labs[devices++] = lab;
while (*lab != ',' && *lab != '\0') lab++;
@@ -836,23 +1553,37 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
if (devices > 0) {
unsigned i;
struct VCB *vcb;
- sts = mount(options,devices,devs,labs,&vcb);
+#ifdef DISKIMAGE
+ for( i = 0; i < (unsigned)devices; i++ ) {
+ char *drive;
+ drive = diskio_mapfile( devs[i], (options & mnt_write) != 0 );
+ if( drive == NULL )
+ return 0;
+ devs[i] = drive;
+ }
+#endif
+ sts = mount(options&mnt_write,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);
if (setdef_count == 0) {
- char *colon,defdir[256];
- strcpy(defdir,vcb->vcbdev[0].dev->devnam);
- colon = strchr(defdir,':');
+ char *colon,tmp[256],defdir[256];
+ snprintf( tmp, sizeof(tmp), "%s", vcb->vcbdev[0].dev->devnam);
+ colon = strchr(tmp,':');
if (colon != NULL) *colon = '\0';
- strcpy(defdir + strlen(defdir),":[000000]");
+ snprintf( defdir, sizeof(defdir), "%s:[000000]", tmp );
setdef(defdir);
test_vcb = vcb;
}
} else {
- printf("Mount failed with %d\n",sts);
+ printf("Mount failed with %s\n",getmsg(sts));
+#ifdef DISKIMAGE
+ for( i = 0; i < (unsigned)devices; i++ ) {
+ sts = diskio_unmapdrive( devs[i] );
+ }
+#endif
}
}
return sts;
@@ -866,6 +1597,11 @@ void phyio_show(void);
unsigned statis(int argc,char *argv[],int qualc,char *qualv[])
{
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(qualc);
+ UNUSED(qualv);
+
printf("Statistics:-\n");
direct_show();
cache_show();
@@ -875,16 +1611,233 @@ unsigned statis(int argc,char *argv[],int qualc,char *qualv[])
#endif
+void cmdhelp( struct CMDSET *cmdset ) {
+ struct CMDSET *cmd;
+ int n = 0;
+ size_t max = 0;
-/* help: a routine to print a pre-prepared help text... */
+ for( cmd = cmdset; cmd->name; cmd++ ) {
+ if( strlen(cmd->name) > max )
+ max = strlen(cmd->name);
+ }
+ for( cmd = cmdset; cmd->name; cmd++ ) {
+ if( cmd->helpstr == NULL )
+ continue;
+ if( n++ % 4 == 0 )
+ printf( "\n" );
+ printf(" %-*s", (int)max,cmd->name );
+ }
+ printf( "\n" );
+}
+
+void qualhelp( int par, struct qual *qtable ) {
+ struct qual *q;
+ int n = 0;
+ size_t max = 0;
+#define NOSTR "[no]"
+#define NOSTR_LEN (sizeof(NOSTR)-1)
+ for( q = qtable; q->name; q++ ) {
+ if( q->helpstr ) {
+ size_t len = strlen(q->name);
+ if( *q->helpstr == '-' )
+ len += NOSTR_LEN;
+ if( len > max )
+ max = len;
+ }
+ }
+ for( q = qtable; q->name; q++ ) {
+ if( q->helpstr ) {
+ if( !n++ && !par )
+ printf( " %s:\n", par? "Parameters": "Qualifiers" );
+ printf(" %s", par? "": vms_qual? "/" : "-" );
+ if( *q->helpstr == '-' )
+ printf( NOSTR "%-*s - %s\n",
+ (int) (max-NOSTR_LEN), q->name,
+ q->helpstr+1 );
+ else
+ printf("%-*s - %s\n", (int) max, q->name,
+ q->helpstr );
+ }
+ }
+ printf( "\n" );
+}
+#undef NOSTR
+#undef NOSTR_LEN
+
+void parhelp( struct CMDSET *cmd, int argc, char **argv) {
+ struct param *p;
+ struct param *ptable;
+ const char *footer = NULL;
+
+ ptable = cmd->params;
+
+ if( ptable == NULL ) {
+ printf( "%s has no parameters\n", cmd->name );
+ return;
+ }
+
+ if( argc == 0 ) {
+ int col = 0;
+ size_t max = 0;
+
+ for( p = ptable; p->name != NULL; p++ ) {
+ if( 1||p->helpstr ) {
+ size_t len = strlen(p->name);
+ if( len > max )
+ max = len;
+ }
+ }
+ for( p = ptable; p->name != NULL; p++ ) {
+ if(1|| p->helpstr ) {
+ size_t len = strlen(p->name);
+ if( !col ) {
+ printf( " Parameters:\n " );
+ col = 4;
+ } else {
+ if( 1+col + len > 80 ) {
+ printf( "\n " );
+ col = 4;
+ } else {
+ printf ( " " );
+ col++;
+ }
+ }
+ printf( "%-*s", (int)max, p->name );
+ col += len;
+ }
+ }
+ printf( "\n\n Type help PARAMETER for more about each parameter.\n" );
+ return;
+ }
+
+ for( p = ptable; p->name != NULL; p++ ) {
+ if( keycomp( argv[0], p->name ) )
+ break;
+ }
+ if( p->name == NULL ) {
+ printf( "No parameter '%s' found\n", argv[0] );
+ return;
+ }
+ if( p->hlpfnc != NULL )
+ footer = (*p->hlpfnc)(cmd, p, argc, argv);
+ if( p->ptype == NONE ) {
+ printf( "Parameter is not used for this command\n" );
+ return;
+ }
+
+ printf( " %s: ", p->name );
+
+ if( p->flags == OPT )
+ printf( "optional " );
+
+ switch( p->ptype ) {
+ case VMSFS:
+ printf( "VMS file specification %s\n", p->helpstr );
+ break;
+ case LCLFS:
+ printf( "local file specification %s\n", p->helpstr );
+ break;
+ case KEYWD:
+ printf( "%skeyword, one of the following:\n",
+ (p->helpstr == NULL? "": p->helpstr) );
+ qualhelp( 1, (struct qual *)p->arg );
+ break;
+ case LIST:
+ printf( "list, %s\n", p->helpstr );
+ break;
+ case STRING:
+ printf( "%s\n", p->helpstr );
+ break;
+ case CMDNAM:
+ printf( "command name, one of the following:\n");
+ cmdhelp( (struct CMDSET *)p->arg );
+ break;
+ default:
+ abort();
+ }
+ if( footer )
+ printf( "%s", footer );
+
+ return;
+}
+
+/* help: Display help guided by command table. */
+
+struct CMDSET cmdset[];
+
+struct param helppars[] = { {"command", OPT, CMDNAM, PA(cmdset), NULL },
+ {"parameter", OPT, STRING, NOPA, NULL },
+ {"value", OPT, STRING, NOPA, NULL },
+ {NULL, 0, 0, NOPA, NULL },
+};
+
+/* information about the commands we know... */
+unsigned help(int argc,char *argv[],int qualc,char *qualv[]);
+
+struct CMDSET cmdset[] = {
+ { "copy", copy, 0,copyquals,copypars, "Copy a file from VMS to host file", },
+ { "import", import, 0,NULL, importpars, "Copy a file from host to VMS", },
+ { "delete", del, 0,delquals, delpars, "Delete a VMS file", },
+ { "difference",diff, 0,NULL, diffpars, "Compare VMS file to host file", },
+ { "directory", dir, 0,dirquals,dirpars, "List directory of VMS files", },
+ { "exit", NULL, 2,NULL, NULL, "Exit ODS2", },
+ { "extend", extend, 0,NULL, extendpars, NULL },
+ { "help", help, 0,NULL, helppars, "Obtain help on a command", },
+ { "quit", NULL, 2,NULL, NULL, "Exit ODS-2", },
+ { "show", show, 0,NULL, showpars, "Display state", },
+ { "search", search, 0,NULL, searchpars, "Search VMS file for a string", },
+ { "set", set, 0,NULL, setpars, "Set PARAMETER - set HELP for list", },
+#ifndef VMSIO
+ { "dismount", dodismount,0,NULL, NULL, "Dismount a VMS volume", },
+ { "mount", domount, 0,mouquals, moupars, "Mount a VMS volume", },
+ { "statistics",statis, 0,NULL, NULL, "Display debugging statistics", },
+#endif
+ { "test", test, 0,NULL, testpars, NULL },
+ { "type", typ, 0,NULL, typepars, "Display a VMS file on the terminal", },
+ { NULL, NULL, 0,NULL, NULL, NULL } /* ** END MARKER ** */
+};
unsigned help(int argc,char *argv[],int qualc,char *qualv[])
{
- printf("\nODS2 %s\n", MODULE_IDENT);
- 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");
+ struct CMDSET *cmd;
+
+ UNUSED(qualc);
+ UNUSED(qualv);
+
+ if( argc <= 1 ) {
+ show_version();
+
+ printf("\n Please send problems/comments to Paulnank@au1.ibm.com\n");
+
+ printf(" Commands are:\n");
+ cmdhelp( cmdset );
+ printf( "\n Type HELP COMMAND for information on any command.\n" );
+ return 1;
+ }
+
+ for( cmd = cmdset; cmd->name; cmd++ ) {
+ if( keycomp(argv[1],cmd->name) ) {
+ if( argc >= 3 ) {
+ parhelp( cmd, argc-2, argv+2 );
+ return 1;
+ }
+ if( cmd->helpstr == NULL ) {
+ printf( "%s: No help available\n",cmd->name );
+ } else {
+ printf( "%s: %s\n",cmd->name,cmd->helpstr );
+ }
+ if( cmd->validquals != NULL )
+ qualhelp( 0, cmd->validquals );
+ if( cmd->params != NULL )
+ parhelp( cmd, 0, NULL );
+ if( strcmp(cmd->name, "mount") == 0 )
+ phyio_help(stdout);
+ return 1;
+ }
+ }
+ printf( "%s: command not found\n", argv[1] );
+ return 0;
+
printf(" set_default type\n");
printf(" Example:-\n $ mount e:\n");
printf(" $ search e:[vms_common.decc*...]*.h rms$_wld\n");
@@ -895,132 +1848,87 @@ unsigned help(int argc,char *argv[],int qualc,char *qualv[])
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,1
-},
- {
- "import",import,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
-},
- {
- "extend",extend,3,2,2,0
-},
- {
- "help",help,2,1,1,0
-},
- {
- "quit",NULL,2,0,0,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
-},
-#endif
- {
- "test",test,4,2,2,0
-},
- {
- "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);
+ char *ptr;
+ struct CMDSET *cmd, *cp = NULL;
+ unsigned cmdsiz;
+ int minpars, maxpars;
+ struct param *p;
+ int sts;
+
+ ptr = argv[0];
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
- /* cache_flush(); */
-#endif
- }
- }
- return 1;
- }
+ ptr = argv[0];
+ cmdsiz = strlen(ptr);
+
+ for( cmd = cmdset; cmd->name != NULL; cmd++ ) {
+ if( cmdsiz <= strlen( cmd->name ) &&
+ keycomp( ptr, cmd->name ) ) {
+ if( (cmd->uniq && cmdsiz >= cmd->uniq) ) {
+ cp = cmd;
+ break;
}
+ if( cp != NULL ) {
+ printf("%%ODS2-E-AMBCMD, '%s' is ambiguous\n", ptr );
+ return 0;
+ }
+ cp = cmd;
}
- cmd++;
}
- printf("%%ODS2-E-ILLCMD, Illegal or ambiguous command '%s'\n",argv[0]);
- return 1;
+ if( cp == NULL ) {
+ printf("%%ODS2-E-ILLCMD, Unknown command '%s'\n", ptr );
+ return 0;
+ }
+ cmd = cp;
+
+ if (cmd->proc == NULL)
+ return -1;
+
+ minpars =
+ maxpars = 1;
+ for( p = cmd->params; p && p->name != NULL; p++ ) {
+ maxpars++;
+ if( p->flags == REQ )
+ minpars++;
+ }
+
+ if (argc < minpars|| argc > maxpars) {
+ printf("%%ODS2-E-PARAMS, Incorrect number of command parameters\n");
+ return 0;
+ }
+ sts = (*cmd->proc) (argc,argv,qualc,qualv);
+#ifndef VMSIO
+ /* cache_flush(); */
+#endif
+
+ return sts;
}
/* cmdsplit: break a command line into its components */
/*
- * New feature for Unix: '//' stops qualifier parsing (similar to '--'
- * for some Unix tools). This enables us to copy to Unix directories.
- * copy /bin // *.com /tmp/*
- * is split into argv[0] -> "*.com" argv[1] -> "/tmp/*" qualv[0]-> "/bin"
+ * New feature for Unix: '//' or '--' stops qualifier parsing.
+ * This enables us to copy to Unix directories with VMS style /qualifiers.
+ * copy /bin // *.com /tmp/ *
+ * is split into argv[0] -> "*.com" argv[1] -> "/tmp/ *" qualv[0]-> "/bin"
+ *
+ * Of course, one can just "" the string (VMS double quote rules)...
*/
-
+#define MAXITEMS 32
int cmdsplit(char *str)
{
int argc = 0,qualc = 0;
- char *argv[32],*qualv[32];
+ char *argv[MAXITEMS],*qualv[MAXITEMS];
char *sp = str;
int i;
- char q = '/';
- for (i = 0; i < 32; i++) argv[i] = qualv[i] = "";
+ char q = vms_qual? '/': '-';
+ for (i = 0; i < MAXITEMS; i++) argv[i] = qualv[i] = "";
while (*sp != '\0') {
while (*sp == ' ') sp++;
if (*sp != '\0') {
@@ -1031,9 +1939,35 @@ int cmdsplit(char *str)
q = '\0';
continue;
}
+ if( qualc >= MAXITEMS ) {
+ printf( "Too many qualifiers specified\n" );
+ return 0;
+ }
qualv[qualc++] = sp;
} else {
+ if( argc >= MAXITEMS ) {
+ printf( "Too many arguments specified\n" );
+ return 0;
+ }
argv[argc++] = sp;
+ if( *sp == '"' ) {
+ ++argv[argc-1];
+ for( ++sp; *sp && (*sp != '"' || sp[1] == '"'); sp++ ) {
+ if( *sp == '"' )
+ memmove( sp, sp+1, strlen(sp+1)+1 );
+ }
+ if( *sp == '"' ) {
+ *sp++ = '\0';
+ if( *sp && *sp != ' ' ) {
+ printf( "Unterminated string\n" );
+ return 0;
+ }
+ } else {
+ printf( "Unterminated string\n" );
+ return 0;
+ }
+ continue;
+ }
}
while (*sp != ' ' && *sp != q && *sp != '\0') sp++;
if (*sp == '\0') {
@@ -1043,6 +1977,7 @@ int cmdsplit(char *str)
}
}
}
+
if (argc > 0) return cmdexecute(argc,argv,qualc,qualv);
return 1;
}
@@ -1061,7 +1996,7 @@ char *getcmd(char *inp, char *prompt)
char *retstat;
static unsigned long key_table_id = 0;
static unsigned long keyboard_id = 0;
-
+
if (key_table_id == 0)
{
status = smg$create_key_table (&key_table_id);
@@ -1111,78 +2046,158 @@ int main(int argc,char *argv[])
char str[2048];
char *command_line = NULL;
FILE *atfile = NULL;
+#ifdef USE_READLINE
char *p;
- printf(" ODS2 %s\n", MODULE_IDENT);
+ wordexp_t wex;
+ char *rl = NULL;
+ char *hfname = NULL;
+ char mname[3+sizeof( MNAME(MODULE_NAME) )];
+
+ snprintf( mname, sizeof(mname ), "~/.%s", MNAME(MODULE_NAME) );
+ rl_readline_name =
+ p = mname+3;
+ do {
+ *p = tolower( *p );
+ } while( *p++ );
+ memset( &wex, 0, sizeof( wordexp_t ) );
+ if( wordexp( mname, &wex, WRDE_NOCMD ) == 0 && wex.we_wordc == 1 ) {
+ hfname = wex.we_wordv[0];
+ history_truncate_file( hfname, 200 );
+ stifle_history( 200 );
+ read_history( hfname );
+ } else {
+ hfname = NULL;
+ }
+#endif
+
if (argc>1) {
- int i, l=0;
+ int i, l = 0;
for (i=1; i1)
- command_line[l-2]= '\0';
- } else command_line==NULL;
+ } else command_line = NULL;
while (1) {
char *ptr;
if (command_line) {
static int i=0;
- int j=0;
- for (; j %s\n",str);
+ if( verify_cmd )
+ printf("$> %s\n",str);
}
+ ptr = str;
} else {
#ifdef VMS
if (getcmd (str, "$> ") == NULL) break;
+ ptr = str;
+#elif( defined USE_READLINE )
+ if (rl != NULL) {
+ free( rl );
+ }
+ rl =
+ ptr = readline( MNAME(MODULE_NAME) "$> " );
+ if (rl == NULL) {
+ break;
+ } else {
+ if (*rl != '\0') {
+ add_history( rl );
+ }
+ }
#else
printf("$> ");
- if (gets(str) == NULL) break;
+ if (fgets(str, sizeof(str), stdin) == NULL) break;
+ ptr = strchr(str, '\n');
+ if(ptr != NULL) *ptr = '\0';
+ ptr = str;
#endif
}
-}
- ptr = str;
+ }
+
while (*ptr == ' ' || *ptr == '\t') ptr++;
if (strlen(ptr) && *ptr != '!') {
if (*ptr == '@') {
if (atfile != NULL) {
printf("%%ODS2-W-INDIRECT, indirect indirection not permitted\n");
} else {
- if ((atfile = fopen(ptr + 1,"r")) == NULL) {
+ if ((atfile = openf(ptr + 1,"r")) == NULL) {
perror("%%Indirection failed");
printf("\n");
+ free(command_line);
+ command_line = NULL;
+ *str = '\0';
}
}
} else {
- if ((cmdsplit(ptr) & 1) == 0) break;
+ int sts;
+
+ sts = cmdsplit(ptr);
+ if( sts == -1 )
+ break;
+ if ((sts & 1) == 0) {
+ if( atfile != NULL ) {
+ fclose(atfile);
+ atfile = NULL;
+ }
+ free(command_line);
+ command_line = NULL;
+ *str = '\0';
+ }
}
}
}
+#ifdef USE_READLINE
+ if (rl != NULL) {
+ free( rl );
+ }
+ if (hfname != NULL) {
+ write_history( hfname );
+ }
+#endif
if (atfile != NULL) fclose(atfile);
+#ifdef VMS
return 1;
+#else
+ return 0;
+#endif
}
diff --git a/extracters/ods2/ods2.c.bak b/extracters/ods2/ods2.c.bak
deleted file mode 100644
index 49825b2..0000000
--- a/extracters/ods2/ods2.c.bak
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include "descrip.h"
-#include "ssdef.h"
-
-#ifdef VMSIO
-#include
-#include
-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;
-}
diff --git a/extracters/ods2/ods2.rc b/extracters/ods2/ods2.rc
index 879ac3c..9531d35 100644
--- a/extracters/ods2/ods2.rc
+++ b/extracters/ods2/ods2.rc
@@ -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 \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
diff --git a/extracters/ods2/phyio.h b/extracters/ods2/phyio.h
index 0212205..d9150e7 100644
--- a/extracters/ods2/phyio.h
+++ b/extracters/ods2/phyio.h
@@ -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
+
#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
diff --git a/extracters/ods2/phynt.c b/extracters/ods2/phynt.c
index 97a2e76..3d00763 100644
--- a/extracters/ods2/phynt.c
+++ b/extracters/ods2/phynt.c
@@ -25,7 +25,7 @@
#include
#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)
®,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,
- ®,sizeof(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,
- ®,sizeof(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,
+ ®,sizeof(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,
+ ®,sizeof(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;
}
diff --git a/extracters/ods2/phyos2.c b/extracters/ods2/phyos2.c
index 8840018..5d068f2 100644
--- a/extracters/ods2/phyos2.c
+++ b/extracters/ods2/phyos2.c
@@ -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) {
diff --git a/extracters/ods2/phyunix.c b/extracters/ods2/phyunix.c
index ed378b8..b226f1b 100644
--- a/extracters/ods2/phyunix.c
+++ b/extracters/ods2/phyunix.c
@@ -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
+#include
#include
#include
#include
#include
+#include
#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;
diff --git a/extracters/ods2/phyvms.c b/extracters/ods2/phyvms.c
index f88a1dc..6c00ff2 100644
--- a/extracters/ods2/phyvms.c
+++ b/extracters/ods2/phyvms.c
@@ -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)
{
diff --git a/extracters/ods2/rms.c b/extracters/ods2/rms.c
index 839b094..329c262 100644
--- a/extracters/ods2/rms.c
+++ b/extracters/ods2/rms.c
@@ -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;
}
diff --git a/extracters/ods2/rms.h b/extracters/ods2/rms.h
index e875532..8fab192 100644
--- a/extracters/ods2/rms.h
+++ b/extracters/ods2/rms.h
@@ -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;
diff --git a/extracters/ods2/sysmsg.c b/extracters/ods2/sysmsg.c
new file mode 100644
index 0000000..c5eb90c
--- /dev/null
+++ b/extracters/ods2/sysmsg.c
@@ -0,0 +1,88 @@
+/* Timothe Litt litt _at_ acm _ddot_ org */
+
+/* Message code translations for non-VMS systems */
+
+#include
+#include
+
+/* 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
+*/
diff --git a/extracters/ods2/sysmsg.h b/extracters/ods2/sysmsg.h
new file mode 100644
index 0000000..2e8d828
--- /dev/null
+++ b/extracters/ods2/sysmsg.h
@@ -0,0 +1,6 @@
+#ifndef SYSMSG_H
+#define SYSMSG_H
+
+const char *getmsg( unsigned int vmscode );
+
+#endif
diff --git a/extracters/ods2/update.c b/extracters/ods2/update.c
index c9f61cb..a240f92 100644
--- a/extracters/ods2/update.c
+++ b/extracters/ods2/update.c
@@ -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;
diff --git a/extracters/ods2/version.h b/extracters/ods2/version.h
new file mode 100644
index 0000000..2c518ab
--- /dev/null
+++ b/extracters/ods2/version.h
@@ -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