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