diff --git a/extracters/ods2/ODS2-Image.exe b/extracters/ods2/ODS2-Image.exe
new file mode 100644
index 0000000..86a75a7
Binary files /dev/null and b/extracters/ods2/ODS2-Image.exe differ
diff --git a/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj
index f68ba00..5abc981 100644
--- a/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj
+++ b/extracters/ods2/ODS2-Image/ODS2-Image.vcxproj
@@ -36,7 +36,14 @@
-
+
+
+
+
+
+
+
+
Level3
@@ -49,6 +56,21 @@
$(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)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ del $(SolutionDir)$(TargetName)$(TargetExt) >nil.bak 2>&1 || exit /b 0
+
@@ -65,6 +87,16 @@
$(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)
+
+
+
+
+
+ copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)$(TargetExt)
+ $(SolutionDir)$(TargetName)$(TargetExt)
+ $(OutDir)$(TargetName)($(TargetExt)
+ Copying released $(TargetName)$(TargetExt)
+
diff --git a/extracters/ods2/ODS2.exe b/extracters/ods2/ODS2.exe
new file mode 100644
index 0000000..09d0881
Binary files /dev/null and b/extracters/ods2/ODS2.exe differ
diff --git a/extracters/ods2/ODS2.vcxproj b/extracters/ods2/ODS2.vcxproj
index 608aee5..84603f5 100644
--- a/extracters/ods2/ODS2.vcxproj
+++ b/extracters/ods2/ODS2.vcxproj
@@ -34,9 +34,12 @@
true
+
+
false
+ Link
@@ -54,6 +57,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ del $(SolutionDir)$(TargetName)$(TargetExt) >nil.bak 2>&1 || exit /b 0
+
@@ -69,6 +89,15 @@
true
true
+
+
+
+
+
+ copy $(OutDir)$(TargetName)$(TargetExt) $(TargetName)$(TargetExt)
+ $(TargetName)$(TargetExt)
+ Copying $(TargetName)$(TargetExt)
+
diff --git a/extracters/ods2/compat.c b/extracters/ods2/compat.c
index bf2ce64..16ad669 100644
--- a/extracters/ods2/compat.c
+++ b/extracters/ods2/compat.c
@@ -7,13 +7,21 @@
* replacement until very recent IDEs.
* Microsoft doesn't like fopen.
* One needs to use a M$ call to translate system errors.
+ *
+ * Finding out about drive letter assignments is unique to windows.
*/
-#if defined(_MSC_VER) && _MSC_VER < 1900
-
+#include
+#include
#include
#include "compat.h"
+#ifdef _WIN32
+#include
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
@@ -37,10 +45,9 @@ int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
return count;
}
+#endif
-#ifdef _WIN32
-#include
-#include
+#ifdef _MSC_VER
FILE *openf( const char *filename, const char *mode ) {
errno_t err;
@@ -52,7 +59,9 @@ FILE *openf( const char *filename, const char *mode ) {
}
return NULL;
}
+#endif
+#ifdef _WIN32
TCHAR *w32_errstr( DWORD eno, ... ) {
va_list ap;
@@ -71,7 +80,32 @@ TCHAR *w32_errstr( DWORD eno, ... ) {
va_end(ap);
return msg;
}
-#endif
+
+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
/* For ISO C compliance, ensure that there's something in this module */
diff --git a/extracters/ods2/compat.h b/extracters/ods2/compat.h
index 3676805..558d6ce 100644
--- a/extracters/ods2/compat.h
+++ b/extracters/ods2/compat.h
@@ -13,18 +13,20 @@ int c99_snprintf(char *outBuf, size_t size, const char *format, ...);
#endif
-#ifdef _WIN32
-#include
-#include
-
+#ifdef _MSC_VER
FILE *openf( const char *filename, const char *mode );
-
-TCHAR *w32_errstr( DWORD eno, ... );
-
#else
#define openf fopen
#endif
+#ifdef _WIN32
+#include
+#include
+
+TCHAR *w32_errstr( DWORD eno, ... );
+char *driveFromLetter( const char *letter );
+#endif
+
#define UNUSED(x) (void)(x)
#endif
diff --git a/extracters/ods2/diskio.c b/extracters/ods2/diskio.c
index 9305b62..6705f19 100644
--- a/extracters/ods2/diskio.c
+++ b/extracters/ods2/diskio.c
@@ -63,20 +63,57 @@ static char drives[26][4];
* 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.
+ *
+ * To minimize confusion, under Windows, try to pick a pseudo-drive letter that
+ * isn't in use by windows. Avoid A & B unless all >= C are in use. If we can't
+ * find a non-conflicting letter, use the first letter not in use. Under any other
+ * OS, just use the first free letter.
*/
char *diskio_mapfile( const char *filename, int options ) {
int l, L = -1;
+#ifdef _WIN32
+ int ff = -1, ffa = -1;
+#endif
+
for( l = 0; l < 26; l++ ) {
- if( diskfiles[l] == NULL && L < 0 ) L = l;
+ if( diskfiles[l] == NULL && L < 0) {
+#ifdef _WIN32
+ char dl[3] = { 'A', ':', '\0' };
+ dl[0] += l;
+ if( ff < 0 )
+ ff = l;
+ if( driveFromLetter( dl ) == NULL) {
+ if( dl[0] >= 'C' ) {
+ if( L < 0 )
+ L = l;
+ } else {
+ if( ffa < 0 )
+ ffa = l;
+ }
+ }
+#else
+ L = l;
+#endif
+ }
if( diskfiles[l] && strcmp( diskfiles[l], filename ) == 0 ) {
printf( "%s is already mounted as drive %s\n", filename, drives[l] );
return NULL;
}
}
+#ifdef _WIN32
+ if( L < 0 ) {
+ if( ffa >= 0 )
+ L = ffa;
+ else {
+ if( ff >= 0 )
+ L = ff;
+ }
+ }
+#endif
if( L < 0 ) {
printf( "No free drive letters for %s\n", filename );
- return 0;
+ return NULL;
}
snprintf(drives[L], 3, "%c:", L + 'A');
drives[L][3] = options;
diff --git a/extracters/ods2/ods2.c b/extracters/ods2/ods2.c
index dfc7caf..3f56090 100644
--- a/extracters/ods2/ods2.c
+++ b/extracters/ods2/ods2.c
@@ -1,6 +1,8 @@
#define MODULE_NAME ODS2
-/* Feb-2016, v1.4 add readline support, dir/full etc */
+/* Feb-2016, v1.4 add readline support, dir/full etc
+ * See git commit messages for details.
+ */
/* Jul-2003, v1.3hb, some extensions by Hartmut Becker */
@@ -51,7 +53,8 @@
* 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.
+ * Rework command parsing and help. Bugs, bugs & bugs. See git
+ * commit history for details.
*
* 31-AUG-2001 01:04 Hunter Goatley
*
@@ -174,7 +177,7 @@ struct qual {
struct param;
struct CMDSET;
-typedef const char * (hlpfunc_t)(struct CMDSET *cmd, struct param *p, int argc, char **argv);
+typedef const char *(hlpfunc_t)( struct CMDSET *cmd, struct param *p, int argc, char **argv );
struct param {
const char *name;
@@ -207,7 +210,8 @@ static int vms_qual = 1;
static int verify_cmd = 1;
/* checkquals: Given valid qualifier definitions, process qualifer
- * list from a command left to right
+ * list from a command left to right. Also handles parameters and
+ * qualifier values (/Qual=value).
*/
int checkquals(int result, struct qual qualset[],int qualc,char *qualv[])
@@ -254,7 +258,7 @@ int checkquals(int result, struct qual qualset[],int qualc,char *qualv[])
qv++;
nvp = strchr( qv, ')' );
if( nvp == NULL ) {
- printf( "%%ODS2-W-NQP, %c%s is missing ')'\n",
+ printf( "%%ODS2-W-NQP, %c%s %s is missing ')'\n",
toupper( *type ), type+1, qualv[i] );
return -1;
}
@@ -340,7 +344,7 @@ void pwrap( int *pos, const char *fmt, ... ) {
/* dir: a directory routine */
-#define dir_extra (dir_date|dir_fileid|dir_owner|dir_prot|dir_size)
+#define dir_extra (dir_date | dir_fileid | dir_owner | dir_prot | dir_size)
#define dir_date (1 << 0)
#define dir_fileid (1 << 1)
#define dir_owner (1 << 2)
@@ -358,12 +362,12 @@ void pwrap( int *pos, const char *fmt, ... ) {
#define dir_created (1 << 12)
#define dir_expired (1 << 13)
#define dir_modified (1 << 14)
+#define dir_dates (dir_backup | dir_created | dir_expired | dir_modified)
#define dir_allocated (1 << 15)
#define dir_used (1 << 16)
#define dir_sizes (dir_allocated | dir_used)
-#define dir_dates (dir_backup|dir_created|dir_expired|dir_modified)
#define dir_default (dir_heading|dir_names|dir_trailing)
struct qual datekwds[] = { {"created", dir_created, 0, NV, "Date file created (default)"},
@@ -405,7 +409,7 @@ struct qual dirquals[] = { {"brief", dir_default, ~dir_default, NV,
int dir_defopt = dir_default;
struct param dirpars[] = { {"filespec", OPT, VMSFS, NOPA, "for files to select. Wildcards are allowed."},
- { NULL, 0, 0, NOPA, NULL }
+ { NULL, 0, 0, NOPA, NULL }
};
void dirtotal( int options, int size, int alloc ) {
@@ -496,7 +500,7 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
char dir[NAM$C_MAXRSS + 1];
int namelen;
int dirlen = 0;
- int dirfiles = 0,dircount = 0;
+ int dirfiles = 0, dircount = 0;
int dirblocks = 0, diralloc = 0, totblocks = 0, totalloc = 0;
int printcol = 0;
#ifdef DEBUG
@@ -509,7 +513,7 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
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) {
+ memcmp(rsa, dir, nam.nam$b_dev + nam.nam$b_dir) != 0) {
if (dirfiles > 0 && (options & dir_trailing)) {
if (printcol > 0) printf("\n");
printf("\nTotal of %d file%s",dirfiles,(dirfiles == 1 ? "" : "s"));
@@ -643,8 +647,8 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
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_VFC:
+ pwrap( &pos, "Variable length, fixed carriage control %u, maximum %u bytes", (fab.fab$b_fsz? fab.fab$b_fsz: 2), fab.fab$w_mrs ); break;
case FAB$C_STM:
pwrap( &pos, "Stream" ); break;
case FAB$C_STMLF:
@@ -1251,34 +1255,6 @@ unsigned extend(int argc,char *argv[],int qualc,char *qualv[])
}
-#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
@@ -1497,7 +1473,7 @@ const char * sethelp( struct CMDSET *cmd, struct param *p, int argc, char **argv
default:
abort();
}
- return NULL;
+ return NULL;
}
unsigned set(int argc,char *argv[],int qualc,char *qualv[])
@@ -1555,15 +1531,20 @@ unsigned set(int argc,char *argv[],int qualc,char *qualv[])
/* The bits we need when we don't have real VMS routines underneath... */
+struct param dmopars[] = { {"drive_letter", REQ, STRING, NOPA, "Drive containing volume to dismount", },
+ {NULL, 0, 0, NOPA, NULL }
+};
+
unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[])
{
struct DEV *dev;
- int sts = device_lookup(strlen(argv[1]),argv[1],0,&dev);
+ int sts;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
+ sts = device_lookup(strlen(argv[1]),argv[1],0,&dev);
if (sts & 1) {
if (dev->vcb != NULL) {
sts = dismount(dev->vcb);
@@ -1893,7 +1874,7 @@ struct CMDSET cmdset[] = {
{ "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", },
+ { "dismount", dodismount,0,NULL, dmopars, "Dismount a VMS volume", },
{ "mount", domount, 0,mouquals, moupars, "Mount a VMS volume", },
{ "statistics",statis, 0,NULL, NULL, "Display debugging statistics", },
#endif