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