Backlog of work since 2016

Too much to list all, but includes (in no particular order):
 - Cleanup for 64-bit builds, MSVC warnings.
 - Structured help
 - Help file compiler.
 - Supports volsets, writes/create work.
 - Support for I18n in messages, help.
 - Makefiles.
 - Initialize volume/volset
 - Command line editing/history

Builds and works on Linux and Windows (VS).
Not recently built or tested on other platforms, but
not intentinonally broken.
This commit is contained in:
Timothe Litt
2022-10-10 09:35:17 -04:00
parent e94ba41122
commit 66e00b9900
121 changed files with 93496 additions and 12135 deletions

9
.gitignore vendored
View File

@@ -3,6 +3,13 @@
*.bak
*.o
*.orig
*.vhd
*.iso
pc/*
*.simh_dsk
*.swp
*.exe
*.lst
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
@@ -33,6 +40,8 @@ bld/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
\~AutoRecover.*
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{50B74AC8-ED54-475B-BA94-6CAABA45F6A5}</ProjectGuid>
<RootNamespace>genmsgen</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

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

3
extracters/libvhd/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.so
*.so.*

View File

@@ -1,200 +1,200 @@
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef __BLKTAP2_UUID_H__
#define __BLKTAP2_UUID_H__
#if defined(__linux__)
#include <uuid/uuid.h>
typedef struct {
uuid_t uuid;
} blk_uuid_t;
static inline int blk_uuid_is_nil(blk_uuid_t *uuid)
{
return uuid_is_null(uuid->uuid);
}
static inline void blk_uuid_generate(blk_uuid_t *uuid)
{
uuid_generate(uuid->uuid);
}
static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size)
{
(void) size;
uuid_unparse(uuid->uuid, out);
}
static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in)
{
uuid_parse(in, uuid->uuid);
}
static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src)
{
uuid_copy(dst->uuid, src->uuid);
}
static inline void blk_uuid_clear(blk_uuid_t *uuid)
{
uuid_clear(uuid->uuid);
}
static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2)
{
return uuid_compare(uuid1->uuid, uuid2->uuid);
}
#elif defined(__NetBSD__)
#include <uuid.h>
#include <string.h>
#include <stdlib.h>
typedef uuid_t blk_uuid_t;
static inline int blk_uuid_is_nil(blk_uuid_t *uuid)
{
uint32_t status;
return uuid_is_nil((uuid_t *)uuid, &status);
}
static inline void blk_uuid_generate(blk_uuid_t *uuid)
{
uint32_t status;
uuid_create((uuid_t *)uuid, &status);
}
static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size)
{
uint32_t status;
char *_out = NULL;
uuid_to_string((uuid_t *)uuid, &_out, &status);
strlcpy(out, _out, size);
free(_out);
}
static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in)
{
uint32_t status;
uuid_from_string(in, (uuid_t *)uuid, &status);
}
static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src)
{
memcpy((uuid_t *)dst, (uuid_t *)src, sizeof(uuid_t));
}
static inline void blk_uuid_clear(blk_uuid_t *uuid)
{
memset((uuid_t *)uuid, 0, sizeof(uuid_t));
}
static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2)
{
uint32_t status;
return uuid_compare((uuid_t *)uuid1, (uuid_t *)uuid2, &status);
}
#elif defined(_WIN32)
#include <Rpc.h>
typedef UUID blk_uuid_t;
static size_t strlcpy( char *dst, const char *src, size_t size ) {
size_t srclen;
size--;
srclen = strlen( src );
if( srclen > size )
srclen = size;
memcpy( dst, src, srclen );
dst[srclen] = '\0';
return (srclen);
}
static inline int blk_uuid_is_nil( blk_uuid_t *uuid )
{
RPC_STATUS status;
return UuidIsNil( (uuid_t *)uuid, &status );
}
static inline void blk_uuid_generate( blk_uuid_t *uuid )
{
RPC_STATUS status;
status = UuidCreate( (uuid_t *)uuid );
if( status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY )
return;
abort();
}
static inline void blk_uuid_to_string( blk_uuid_t *uuid, char *out, size_t size )
{
RPC_CSTR _out = NULL;
if( UuidToString( (uuid_t *)uuid, &_out ) != RPC_S_OK )
return;
strlcpy( out, (const char *)_out, size );
RpcStringFree( &_out );
return;
}
static inline void blk_uuid_from_string( blk_uuid_t *uuid, const char *in )
{
UuidFromString( (RPC_CSTR)in, (uuid_t *)uuid );
}
static inline void blk_uuid_copy( blk_uuid_t *dst, blk_uuid_t *src )
{
memcpy( (uuid_t *)dst, (uuid_t *)src, sizeof( uuid_t ) );
}
static inline void blk_uuid_clear( blk_uuid_t *uuid )
{
memset( (uuid_t *)uuid, 0, sizeof( uuid_t ) );
}
static inline int blk_uuid_compare( blk_uuid_t *uuid1, blk_uuid_t *uuid2 )
{
RPC_STATUS status;
return UuidCompare( (uuid_t *)uuid1, (uuid_t *)uuid2, &status );
}
#else
#error "Please update blk_uuid.h for your OS"
#endif
#endif /* __BLKTAP2_UUID_H__ */
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef __BLKTAP2_UUID_H__
#define __BLKTAP2_UUID_H__
#if defined(__linux__)
#include <uuid/uuid.h>
typedef struct {
uuid_t uuid;
} blk_uuid_t;
static inline int blk_uuid_is_nil(blk_uuid_t *uuid)
{
return uuid_is_null(uuid->uuid);
}
static inline void blk_uuid_generate(blk_uuid_t *uuid)
{
uuid_generate(uuid->uuid);
}
static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size)
{
(void) size;
uuid_unparse(uuid->uuid, out);
}
static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in)
{
uuid_parse(in, uuid->uuid);
}
static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src)
{
uuid_copy(dst->uuid, src->uuid);
}
static inline void blk_uuid_clear(blk_uuid_t *uuid)
{
uuid_clear(uuid->uuid);
}
static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2)
{
return uuid_compare(uuid1->uuid, uuid2->uuid);
}
#elif defined(__NetBSD__)
#include <uuid.h>
#include <string.h>
#include <stdlib.h>
typedef uuid_t blk_uuid_t;
static inline int blk_uuid_is_nil(blk_uuid_t *uuid)
{
uint32_t status;
return uuid_is_nil((uuid_t *)uuid, &status);
}
static inline void blk_uuid_generate(blk_uuid_t *uuid)
{
uint32_t status;
uuid_create((uuid_t *)uuid, &status);
}
static inline void blk_uuid_to_string(blk_uuid_t *uuid, char *out, size_t size)
{
uint32_t status;
char *_out = NULL;
uuid_to_string((uuid_t *)uuid, &_out, &status);
strlcpy(out, _out, size);
free(_out);
}
static inline void blk_uuid_from_string(blk_uuid_t *uuid, const char *in)
{
uint32_t status;
uuid_from_string(in, (uuid_t *)uuid, &status);
}
static inline void blk_uuid_copy(blk_uuid_t *dst, blk_uuid_t *src)
{
memcpy((uuid_t *)dst, (uuid_t *)src, sizeof(uuid_t));
}
static inline void blk_uuid_clear(blk_uuid_t *uuid)
{
memset((uuid_t *)uuid, 0, sizeof(uuid_t));
}
static inline int blk_uuid_compare(blk_uuid_t *uuid1, blk_uuid_t *uuid2)
{
uint32_t status;
return uuid_compare((uuid_t *)uuid1, (uuid_t *)uuid2, &status);
}
#elif defined(_WIN32)
#include <Rpc.h>
typedef UUID blk_uuid_t;
static size_t strlcpy( char *dst, const char *src, size_t size ) {
size_t srclen;
size--;
srclen = strlen( src );
if( srclen > size )
srclen = size;
memcpy( dst, src, srclen );
dst[srclen] = '\0';
return (srclen);
}
static inline int blk_uuid_is_nil( blk_uuid_t *uuid )
{
RPC_STATUS status;
return UuidIsNil( (uuid_t *)uuid, &status );
}
static inline void blk_uuid_generate( blk_uuid_t *uuid )
{
RPC_STATUS status;
status = UuidCreate( (uuid_t *)uuid );
if( status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY )
return;
abort();
}
static inline void blk_uuid_to_string( blk_uuid_t *uuid, char *out, size_t size )
{
RPC_CSTR _out = NULL;
if( UuidToString( (uuid_t *)uuid, &_out ) != RPC_S_OK )
return;
strlcpy( out, (const char *)_out, size );
RpcStringFree( &_out );
return;
}
static inline void blk_uuid_from_string( blk_uuid_t *uuid, const char *in )
{
UuidFromString( (RPC_CSTR)in, (uuid_t *)uuid );
}
static inline void blk_uuid_copy( blk_uuid_t *dst, blk_uuid_t *src )
{
memcpy( (uuid_t *)dst, (uuid_t *)src, sizeof( uuid_t ) );
}
static inline void blk_uuid_clear( blk_uuid_t *uuid )
{
memset( (uuid_t *)uuid, 0, sizeof( uuid_t ) );
}
static inline int blk_uuid_compare( blk_uuid_t *uuid1, blk_uuid_t *uuid2 )
{
RPC_STATUS status;
return UuidCompare( (uuid_t *)uuid1, (uuid_t *)uuid2, &status );
}
#else
#error "Please update blk_uuid.h for your OS"
#endif
#endif /* __BLKTAP2_UUID_H__ */

View File

@@ -1,363 +1,363 @@
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef _VHD_LIB_H_
#define _VHD_LIB_H_
#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#if defined(__linux__)
#include <endian.h>
#include <byteswap.h>
#elif defined(__NetBSD__)
#include <sys/endian.h>
#include <sys/bswap.h>
#elif defined(_WIN32)
#undef BYTE_ORDER
#undef LITTLE_ENDIAN
#define BYTE_ORDER 1234
#define LITTLE_ENDIAN 1234
#define bswap_16(val) _byteswap_ushort(val)
#define bswap_32(val) _byteswap_ulong(val)
#define bswap_64(val) _byteswap_uint64(val)
#endif
#include "blk_uuid.h"
#include "vhd.h"
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#if defined(_WIN32) && defined(LIBVHD_DLL)
#ifdef LIBVHD_EXPORTS
#define LIBVHD_API __declspec(dllexport)
#else
#define LIBVHD_API __declspec(dllimport)
#endif
#else
#define LIBVHD_API
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#if defined(__linux__) || defined(_WIN32)
#define BE16_IN(foo) (*(foo)) = bswap_16(*(foo))
#define BE32_IN(foo) (*(foo)) = bswap_32(*(foo))
#define BE64_IN(foo) (*(foo)) = bswap_64(*(foo))
#define BE16_OUT(foo) (*(foo)) = bswap_16(*(foo))
#define BE32_OUT(foo) (*(foo)) = bswap_32(*(foo))
#define BE64_OUT(foo) (*(foo)) = bswap_64(*(foo))
#elif defined(__NetBSD__)
#define BE16_IN(foo) (*(foo)) = bswap16(*(foo))
#define BE32_IN(foo) (*(foo)) = bswap32(*(foo))
#define BE64_IN(foo) (*(foo)) = bswap64(*(foo))
#define BE16_OUT(foo) (*(foo)) = bswap16(*(foo))
#define BE32_OUT(foo) (*(foo)) = bswap32(*(foo))
#define BE64_OUT(foo) (*(foo)) = bswap64(*(foo))
#endif
#else
#define BE16_IN(foo)
#define BE32_IN(foo)
#define BE64_IN(foo)
#define BE32_OUT(foo)
#define BE32_OUT(foo)
#define BE64_OUT(foo)
#endif
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define VHD_MAX_NAME_LEN 1024
#define VHD_BLOCK_SHIFT 21
#define VHD_BLOCK_SIZE (1ULL << VHD_BLOCK_SHIFT)
#define UTF_16 "UTF-16"
#define UTF_16LE "UTF-16LE"
#define UTF_16BE "UTF-16BE"
#define VHD_OPEN_RDONLY 0x00001
#define VHD_OPEN_RDWR 0x00002
#define VHD_OPEN_FAST 0x00004
#define VHD_OPEN_STRICT 0x00008
#define VHD_OPEN_IGNORE_DISABLED 0x00010
#define VHD_FLAG_CREAT_PARENT_RAW 0x00001
#define vhd_flag_set(word, flag) ((word) |= (flag))
#define vhd_flag_clear(word, flag) ((word) &= ~(flag))
#define vhd_flag_test(word, flag) ((word) & (flag))
#ifndef _WIN32x
#define ENABLE_FAILURE_TESTING 1
#endif
#define FAIL_REPARENT_BEGIN 0
#define FAIL_REPARENT_LOCATOR 1
#define FAIL_REPARENT_END 2
#define FAIL_RESIZE_BEGIN 3
#define FAIL_RESIZE_DATA_MOVED 4
#define FAIL_RESIZE_METADATA_MOVED 5
#define FAIL_RESIZE_END 6
#define NUM_FAIL_TESTS 7
#ifdef ENABLE_FAILURE_TESTING
#define TEST_FAIL_AT(point) \
if (TEST_FAIL[point]) { \
printf("Failing at %s\n", ENV_VAR_FAIL[point]); exit(EINVAL); }
#ifdef _WIN32
#define TEST_FAIL_EXTERN_VARS \
LIBVHD_API extern const char* ENV_VAR_FAIL[]; \
LIBVHD_API extern int TEST_FAIL[];
#else
#define TEST_FAIL_EXTERN_VARS \
extern const char* ENV_VAR_FAIL[]; \
extern int TEST_FAIL[];
#endif
#else
#define TEST_FAIL_AT(point)
#define TEST_FAIL_EXTERN_VARS
#endif /* ENABLE_FAILURE_TESTING */
static const char VHD_POISON_COOKIE[] = "v_poison";
typedef struct hd_ftr vhd_footer_t;
typedef struct dd_hdr vhd_header_t;
typedef struct vhd_bat vhd_bat_t;
typedef struct vhd_batmap vhd_batmap_t;
typedef struct dd_batmap_hdr vhd_batmap_header_t;
typedef struct prt_loc vhd_parent_locator_t;
typedef struct vhd_context vhd_context_t;
typedef uint32_t vhd_flag_creat_t;
struct vhd_bat {
uint32_t spb;
uint32_t entries;
uint32_t *bat;
};
struct vhd_batmap {
vhd_batmap_header_t header;
char *map;
};
struct vhd_context {
int fd;
char *file;
int oflags;
int is_block;
uint32_t spb;
uint32_t bm_secs;
vhd_header_t header;
vhd_footer_t footer;
vhd_bat_t bat;
vhd_batmap_t batmap;
};
static inline uint32_t
secs_round_up(uint64_t bytes)
{
return (uint32_t)((bytes + (VHD_SECTOR_SIZE - 1)) >> VHD_SECTOR_SHIFT);
}
static inline uint32_t
secs_round_up_no_zero(uint64_t bytes)
{
uint32_t result;
result = secs_round_up(bytes);
return ( result? result : 1);
}
static inline uint64_t
vhd_sectors_to_bytes(uint64_t sectors)
{
return sectors << VHD_SECTOR_SHIFT;
}
static inline uint64_t
vhd_bytes_padded(uint64_t bytes)
{
return vhd_sectors_to_bytes(secs_round_up_no_zero(bytes));
}
static inline int
vhd_type_dynamic(vhd_context_t *ctx)
{
return (ctx->footer.type == HD_TYPE_DYNAMIC ||
ctx->footer.type == HD_TYPE_DIFF);
}
static inline int
vhd_creator_tapdisk(vhd_context_t *ctx)
{
return !strncmp(ctx->footer.crtr_app, "tap", 3);
}
static inline int
vhd_disabled(vhd_context_t *ctx)
{
return (!memcmp(ctx->footer.cookie,
VHD_POISON_COOKIE, sizeof(ctx->footer.cookie)));
}
static inline size_t
vhd_parent_locator_size(vhd_parent_locator_t *loc)
{
/*
* MICROSOFT_COMPAT
* data_space *should* be in sectors,
* but sometimes we find it in bytes
*/
if (loc->data_space < 512)
return (size_t)vhd_sectors_to_bytes(loc->data_space);
else if (loc->data_space % 512 == 0)
return loc->data_space;
else
return 0;
}
static inline int
vhd_parent_raw(vhd_context_t *ctx)
{
return blk_uuid_is_nil(&ctx->header.prt_uuid);
}
LIBVHD_API void libvhd_set_log_level(int);
LIBVHD_API int vhd_test_file_fixed(const char *, int *);
LIBVHD_API uint32_t vhd_time(time_t time);
LIBVHD_API size_t vhd_time_to_string(uint32_t timestamp, char *target);
LIBVHD_API uint32_t vhd_chs(uint64_t size);
LIBVHD_API uint32_t vhd_checksum_footer(vhd_footer_t *);
LIBVHD_API uint32_t vhd_checksum_header(vhd_header_t *);
LIBVHD_API uint32_t vhd_checksum_batmap(vhd_batmap_t *);
LIBVHD_API void vhd_footer_in(vhd_footer_t *);
LIBVHD_API void vhd_footer_out(vhd_footer_t *);
LIBVHD_API void vhd_header_in(vhd_header_t *);
LIBVHD_API void vhd_header_out(vhd_header_t *);
LIBVHD_API void vhd_bat_in(vhd_bat_t *);
LIBVHD_API void vhd_bat_out(vhd_bat_t *);
LIBVHD_API void vhd_batmap_header_in(vhd_batmap_t *);
LIBVHD_API void vhd_batmap_header_out(vhd_batmap_t *);
LIBVHD_API int vhd_validate_footer(vhd_footer_t *footer);
LIBVHD_API int vhd_validate_header(vhd_header_t *header);
LIBVHD_API int vhd_validate_batmap_header(vhd_batmap_t *batmap);
LIBVHD_API int vhd_validate_batmap(vhd_batmap_t *batmap);
LIBVHD_API int vhd_validate_platform_code(uint32_t code);
LIBVHD_API int vhd_open(vhd_context_t *, const char *file, int flags);
LIBVHD_API void vhd_close(vhd_context_t *);
LIBVHD_API int vhd_create(const char *name, uint64_t bytes, int type, vhd_flag_creat_t);
/* vhd_snapshot: the bytes parameter is optional and can be 0 if the snapshot
* is to have the same size as the (first non-empty) parent */
LIBVHD_API int vhd_snapshot(const char *snapshot, uint64_t bytes, const char *parent,
vhd_flag_creat_t);
LIBVHD_API int vhd_hidden(vhd_context_t *, int *);
LIBVHD_API int vhd_chain_depth(vhd_context_t *, int *);
LIBVHD_API off_t vhd_position(vhd_context_t *);
LIBVHD_API int vhd_seek(vhd_context_t *, off_t, int);
LIBVHD_API int vhd_read(vhd_context_t *, void *, size_t);
LIBVHD_API int vhd_write(vhd_context_t *, void *, size_t);
LIBVHD_API int vhd_offset(vhd_context_t *, uint32_t, uint32_t *);
LIBVHD_API int vhd_end_of_headers(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_end_of_data(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_batmap_header_offset(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_get_header(vhd_context_t *);
LIBVHD_API int vhd_get_footer(vhd_context_t *);
LIBVHD_API int vhd_get_bat(vhd_context_t *);
LIBVHD_API int vhd_get_batmap(vhd_context_t *);
LIBVHD_API void vhd_put_header(vhd_context_t *);
LIBVHD_API void vhd_put_footer(vhd_context_t *);
LIBVHD_API void vhd_put_bat(vhd_context_t *);
LIBVHD_API void vhd_put_batmap(vhd_context_t *);
LIBVHD_API int vhd_has_batmap(vhd_context_t *);
LIBVHD_API int vhd_batmap_test(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API void vhd_batmap_set(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API void vhd_batmap_clear(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API int vhd_get_phys_size(vhd_context_t *, off_t *);
LIBVHD_API int vhd_set_phys_size(vhd_context_t *, off_t);
LIBVHD_API int vhd_bitmap_test(vhd_context_t *, char *, uint32_t);
LIBVHD_API void vhd_bitmap_set(vhd_context_t *, char *, uint32_t);
LIBVHD_API void vhd_bitmap_clear(vhd_context_t *, char *, uint32_t);
LIBVHD_API int vhd_parent_locator_count(vhd_context_t *);
LIBVHD_API int vhd_parent_locator_get(vhd_context_t *, char **);
LIBVHD_API int vhd_parent_locator_read(vhd_context_t *, vhd_parent_locator_t *, char **);
LIBVHD_API int vhd_find_parent(vhd_context_t *, const char *, char **);
LIBVHD_API int vhd_parent_locator_write_at(vhd_context_t *, const char *,
off_t, uint32_t, size_t,
vhd_parent_locator_t *);
LIBVHD_API int vhd_header_decode_parent(vhd_context_t *, vhd_header_t *, char **);
LIBVHD_API int vhd_change_parent(vhd_context_t *, char *parent_path, int raw);
LIBVHD_API int vhd_read_footer(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_read_footer_at(vhd_context_t *, vhd_footer_t *, off_t);
LIBVHD_API int vhd_read_footer_strict(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_read_header(vhd_context_t *, vhd_header_t *);
LIBVHD_API int vhd_read_header_at(vhd_context_t *, vhd_header_t *, off_t);
LIBVHD_API int vhd_read_bat(vhd_context_t *, vhd_bat_t *);
LIBVHD_API int vhd_read_batmap(vhd_context_t *, vhd_batmap_t *);
LIBVHD_API int vhd_read_bitmap(vhd_context_t *, uint32_t block, char **bufp);
LIBVHD_API int vhd_read_block(vhd_context_t *, uint32_t block, char **bufp);
LIBVHD_API int vhd_write_footer(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_write_footer_at(vhd_context_t *, vhd_footer_t *, off_t);
LIBVHD_API int vhd_write_header(vhd_context_t *, vhd_header_t *);
LIBVHD_API int vhd_write_header_at(vhd_context_t *, vhd_header_t *, off_t);
LIBVHD_API int vhd_write_bat(vhd_context_t *, vhd_bat_t *);
LIBVHD_API int vhd_write_batmap(vhd_context_t *, vhd_batmap_t *);
LIBVHD_API int vhd_write_bitmap(vhd_context_t *, uint32_t block, char *bitmap);
LIBVHD_API int vhd_write_block(vhd_context_t *, uint32_t block, char *data);
LIBVHD_API int vhd_io_read(vhd_context_t *, char *, uint64_t, uint32_t);
LIBVHD_API int vhd_io_write(vhd_context_t *, char *, uint64_t, uint32_t);
#endif
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef _VHD_LIB_H_
#define _VHD_LIB_H_
#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#if defined(__linux__)
#include <endian.h>
#include <byteswap.h>
#elif defined(__NetBSD__)
#include <sys/endian.h>
#include <sys/bswap.h>
#elif defined(_WIN32)
#undef BYTE_ORDER
#undef LITTLE_ENDIAN
#define BYTE_ORDER 1234
#define LITTLE_ENDIAN 1234
#define bswap_16(val) _byteswap_ushort(val)
#define bswap_32(val) _byteswap_ulong(val)
#define bswap_64(val) _byteswap_uint64(val)
#endif
#include "blk_uuid.h"
#include "vhd.h"
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#if defined(_WIN32) && defined(LIBVHD_DLL)
#ifdef LIBVHD_EXPORTS
#define LIBVHD_API __declspec(dllexport)
#else
#define LIBVHD_API __declspec(dllimport)
#endif
#else
#define LIBVHD_API
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#if defined(__linux__) || defined(_WIN32)
#define BE16_IN(foo) (*(foo)) = bswap_16(*(foo))
#define BE32_IN(foo) (*(foo)) = bswap_32(*(foo))
#define BE64_IN(foo) (*(foo)) = bswap_64(*(foo))
#define BE16_OUT(foo) (*(foo)) = bswap_16(*(foo))
#define BE32_OUT(foo) (*(foo)) = bswap_32(*(foo))
#define BE64_OUT(foo) (*(foo)) = bswap_64(*(foo))
#elif defined(__NetBSD__)
#define BE16_IN(foo) (*(foo)) = bswap16(*(foo))
#define BE32_IN(foo) (*(foo)) = bswap32(*(foo))
#define BE64_IN(foo) (*(foo)) = bswap64(*(foo))
#define BE16_OUT(foo) (*(foo)) = bswap16(*(foo))
#define BE32_OUT(foo) (*(foo)) = bswap32(*(foo))
#define BE64_OUT(foo) (*(foo)) = bswap64(*(foo))
#endif
#else
#define BE16_IN(foo)
#define BE32_IN(foo)
#define BE64_IN(foo)
#define BE32_OUT(foo)
#define BE32_OUT(foo)
#define BE64_OUT(foo)
#endif
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define VHD_MAX_NAME_LEN 1024
#define VHD_BLOCK_SHIFT 21
#define VHD_BLOCK_SIZE (1ULL << VHD_BLOCK_SHIFT)
#define UTF_16 "UTF-16"
#define UTF_16LE "UTF-16LE"
#define UTF_16BE "UTF-16BE"
#define VHD_OPEN_RDONLY 0x00001
#define VHD_OPEN_RDWR 0x00002
#define VHD_OPEN_FAST 0x00004
#define VHD_OPEN_STRICT 0x00008
#define VHD_OPEN_IGNORE_DISABLED 0x00010
#define VHD_FLAG_CREAT_PARENT_RAW 0x00001
#define vhd_flag_set(word, flag) ((word) |= (flag))
#define vhd_flag_clear(word, flag) ((word) &= ~(flag))
#define vhd_flag_test(word, flag) ((word) & (flag))
#ifndef _WIN32x
#define ENABLE_FAILURE_TESTING 1
#endif
#define FAIL_REPARENT_BEGIN 0
#define FAIL_REPARENT_LOCATOR 1
#define FAIL_REPARENT_END 2
#define FAIL_RESIZE_BEGIN 3
#define FAIL_RESIZE_DATA_MOVED 4
#define FAIL_RESIZE_METADATA_MOVED 5
#define FAIL_RESIZE_END 6
#define NUM_FAIL_TESTS 7
#ifdef ENABLE_FAILURE_TESTING
#define TEST_FAIL_AT(point) \
if (TEST_FAIL[point]) { \
printf("Failing at %s\n", ENV_VAR_FAIL[point]); exit(EINVAL); }
#ifdef _WIN32
#define TEST_FAIL_EXTERN_VARS \
LIBVHD_API extern const char* ENV_VAR_FAIL[]; \
LIBVHD_API extern int TEST_FAIL[];
#else
#define TEST_FAIL_EXTERN_VARS \
extern const char* ENV_VAR_FAIL[]; \
extern int TEST_FAIL[];
#endif
#else
#define TEST_FAIL_AT(point)
#define TEST_FAIL_EXTERN_VARS
#endif /* ENABLE_FAILURE_TESTING */
static const char VHD_POISON_COOKIE[] = "v_poison";
typedef struct hd_ftr vhd_footer_t;
typedef struct dd_hdr vhd_header_t;
typedef struct vhd_bat vhd_bat_t;
typedef struct vhd_batmap vhd_batmap_t;
typedef struct dd_batmap_hdr vhd_batmap_header_t;
typedef struct prt_loc vhd_parent_locator_t;
typedef struct vhd_context vhd_context_t;
typedef uint32_t vhd_flag_creat_t;
struct vhd_bat {
uint32_t spb;
uint32_t entries;
uint32_t *bat;
};
struct vhd_batmap {
vhd_batmap_header_t header;
char *map;
};
struct vhd_context {
int fd;
char *file;
int oflags;
int is_block;
uint32_t spb;
uint32_t bm_secs;
vhd_header_t header;
vhd_footer_t footer;
vhd_bat_t bat;
vhd_batmap_t batmap;
};
static inline uint32_t
secs_round_up(uint64_t bytes)
{
return (uint32_t)((bytes + (VHD_SECTOR_SIZE - 1)) >> VHD_SECTOR_SHIFT);
}
static inline uint32_t
secs_round_up_no_zero(uint64_t bytes)
{
uint32_t result;
result = secs_round_up(bytes);
return ( result? result : 1);
}
static inline uint64_t
vhd_sectors_to_bytes(uint64_t sectors)
{
return sectors << VHD_SECTOR_SHIFT;
}
static inline uint64_t
vhd_bytes_padded(uint64_t bytes)
{
return vhd_sectors_to_bytes(secs_round_up_no_zero(bytes));
}
static inline int
vhd_type_dynamic(vhd_context_t *ctx)
{
return (ctx->footer.type == HD_TYPE_DYNAMIC ||
ctx->footer.type == HD_TYPE_DIFF);
}
static inline int
vhd_creator_tapdisk(vhd_context_t *ctx)
{
return !strncmp(ctx->footer.crtr_app, "tap", 3);
}
static inline int
vhd_disabled(vhd_context_t *ctx)
{
return (!memcmp(ctx->footer.cookie,
VHD_POISON_COOKIE, sizeof(ctx->footer.cookie)));
}
static inline size_t
vhd_parent_locator_size(vhd_parent_locator_t *loc)
{
/*
* MICROSOFT_COMPAT
* data_space *should* be in sectors,
* but sometimes we find it in bytes
*/
if (loc->data_space < 512)
return (size_t)vhd_sectors_to_bytes(loc->data_space);
else if (loc->data_space % 512 == 0)
return loc->data_space;
else
return 0;
}
static inline int
vhd_parent_raw(vhd_context_t *ctx)
{
return blk_uuid_is_nil(&ctx->header.prt_uuid);
}
LIBVHD_API void libvhd_set_log_level(int);
LIBVHD_API int vhd_test_file_fixed(const char *, int *);
LIBVHD_API uint32_t vhd_time(time_t time);
LIBVHD_API size_t vhd_time_to_string(uint32_t timestamp, char *target);
LIBVHD_API uint32_t vhd_chs(uint64_t size);
LIBVHD_API uint32_t vhd_checksum_footer(vhd_footer_t *);
LIBVHD_API uint32_t vhd_checksum_header(vhd_header_t *);
LIBVHD_API uint32_t vhd_checksum_batmap(vhd_batmap_t *);
LIBVHD_API void vhd_footer_in(vhd_footer_t *);
LIBVHD_API void vhd_footer_out(vhd_footer_t *);
LIBVHD_API void vhd_header_in(vhd_header_t *);
LIBVHD_API void vhd_header_out(vhd_header_t *);
LIBVHD_API void vhd_bat_in(vhd_bat_t *);
LIBVHD_API void vhd_bat_out(vhd_bat_t *);
LIBVHD_API void vhd_batmap_header_in(vhd_batmap_t *);
LIBVHD_API void vhd_batmap_header_out(vhd_batmap_t *);
LIBVHD_API int vhd_validate_footer(vhd_footer_t *footer);
LIBVHD_API int vhd_validate_header(vhd_header_t *header);
LIBVHD_API int vhd_validate_batmap_header(vhd_batmap_t *batmap);
LIBVHD_API int vhd_validate_batmap(vhd_batmap_t *batmap);
LIBVHD_API int vhd_validate_platform_code(uint32_t code);
LIBVHD_API int vhd_open(vhd_context_t *, const char *file, int flags);
LIBVHD_API void vhd_close(vhd_context_t *);
LIBVHD_API int vhd_create(const char *name, uint64_t bytes, int type, vhd_flag_creat_t);
/* vhd_snapshot: the bytes parameter is optional and can be 0 if the snapshot
* is to have the same size as the (first non-empty) parent */
LIBVHD_API int vhd_snapshot(const char *snapshot, uint64_t bytes, const char *parent,
vhd_flag_creat_t);
LIBVHD_API int vhd_hidden(vhd_context_t *, int *);
LIBVHD_API int vhd_chain_depth(vhd_context_t *, int *);
LIBVHD_API off_t vhd_position(vhd_context_t *);
LIBVHD_API int vhd_seek(vhd_context_t *, off_t, int);
LIBVHD_API int vhd_read(vhd_context_t *, void *, size_t);
LIBVHD_API int vhd_write(vhd_context_t *, void *, size_t);
LIBVHD_API int vhd_offset(vhd_context_t *, uint32_t, uint32_t *);
LIBVHD_API int vhd_end_of_headers(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_end_of_data(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_batmap_header_offset(vhd_context_t *ctx, off_t *off);
LIBVHD_API int vhd_get_header(vhd_context_t *);
LIBVHD_API int vhd_get_footer(vhd_context_t *);
LIBVHD_API int vhd_get_bat(vhd_context_t *);
LIBVHD_API int vhd_get_batmap(vhd_context_t *);
LIBVHD_API void vhd_put_header(vhd_context_t *);
LIBVHD_API void vhd_put_footer(vhd_context_t *);
LIBVHD_API void vhd_put_bat(vhd_context_t *);
LIBVHD_API void vhd_put_batmap(vhd_context_t *);
LIBVHD_API int vhd_has_batmap(vhd_context_t *);
LIBVHD_API int vhd_batmap_test(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API void vhd_batmap_set(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API void vhd_batmap_clear(vhd_context_t *, vhd_batmap_t *, uint32_t);
LIBVHD_API int vhd_get_phys_size(vhd_context_t *, off_t *);
LIBVHD_API int vhd_set_phys_size(vhd_context_t *, off_t);
LIBVHD_API int vhd_bitmap_test(vhd_context_t *, char *, uint32_t);
LIBVHD_API void vhd_bitmap_set(vhd_context_t *, char *, uint32_t);
LIBVHD_API void vhd_bitmap_clear(vhd_context_t *, char *, uint32_t);
LIBVHD_API int vhd_parent_locator_count(vhd_context_t *);
LIBVHD_API int vhd_parent_locator_get(vhd_context_t *, char **);
LIBVHD_API int vhd_parent_locator_read(vhd_context_t *, vhd_parent_locator_t *, char **);
LIBVHD_API int vhd_find_parent(vhd_context_t *, const char *, char **);
LIBVHD_API int vhd_parent_locator_write_at(vhd_context_t *, const char *,
off_t, uint32_t, size_t,
vhd_parent_locator_t *);
LIBVHD_API int vhd_header_decode_parent(vhd_context_t *, vhd_header_t *, char **);
LIBVHD_API int vhd_change_parent(vhd_context_t *, char *parent_path, int raw);
LIBVHD_API int vhd_read_footer(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_read_footer_at(vhd_context_t *, vhd_footer_t *, off_t);
LIBVHD_API int vhd_read_footer_strict(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_read_header(vhd_context_t *, vhd_header_t *);
LIBVHD_API int vhd_read_header_at(vhd_context_t *, vhd_header_t *, off_t);
LIBVHD_API int vhd_read_bat(vhd_context_t *, vhd_bat_t *);
LIBVHD_API int vhd_read_batmap(vhd_context_t *, vhd_batmap_t *);
LIBVHD_API int vhd_read_bitmap(vhd_context_t *, uint32_t block, char **bufp);
LIBVHD_API int vhd_read_block(vhd_context_t *, uint32_t block, char **bufp);
LIBVHD_API int vhd_write_footer(vhd_context_t *, vhd_footer_t *);
LIBVHD_API int vhd_write_footer_at(vhd_context_t *, vhd_footer_t *, off_t);
LIBVHD_API int vhd_write_header(vhd_context_t *, vhd_header_t *);
LIBVHD_API int vhd_write_header_at(vhd_context_t *, vhd_header_t *, off_t);
LIBVHD_API int vhd_write_bat(vhd_context_t *, vhd_bat_t *);
LIBVHD_API int vhd_write_batmap(vhd_context_t *, vhd_batmap_t *);
LIBVHD_API int vhd_write_bitmap(vhd_context_t *, uint32_t block, char *bitmap);
LIBVHD_API int vhd_write_block(vhd_context_t *, uint32_t block, char *data);
LIBVHD_API int vhd_io_read(vhd_context_t *, char *, uint64_t, uint32_t);
LIBVHD_API int vhd_io_write(vhd_context_t *, char *, uint64_t, uint32_t);
#endif

View File

@@ -1,59 +1,59 @@
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef _RELATIVE_PATH_H_
#define _RELATIVE_PATH_H_
#define MAX_NAME_LEN 1000
#if defined(_WIN32) && defined(LIBVHD_DLL)
#ifdef LIBVHD_EXPORTS
#define LIBVHD_API __declspec(dllexport)
#else
#define LIBVHD_API __declspec(dllimport)
#endif
#else
#define LIBVHD_API
#endif
/*
* returns a relative path from @src to @dest
* result should be freed
*/
LIBVHD_API char *relative_path_to(char *src, char *dest, int *err);
#ifdef _WIN32
LIBVHD_API char *realpath( const char *path, char *resolved );
LIBVHD_API int asprintf( char **result, const char *fmt, ... );
#endif
#endif
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef _RELATIVE_PATH_H_
#define _RELATIVE_PATH_H_
#define MAX_NAME_LEN 1000
#if defined(_WIN32) && defined(LIBVHD_DLL)
#ifdef LIBVHD_EXPORTS
#define LIBVHD_API __declspec(dllexport)
#else
#define LIBVHD_API __declspec(dllimport)
#endif
#else
#define LIBVHD_API
#endif
/*
* returns a relative path from @src to @dest
* result should be freed
*/
LIBVHD_API char *relative_path_to(char *src, char *dest, int *err);
#ifdef _WIN32
LIBVHD_API char *realpath( const char *path, char *resolved );
LIBVHD_API int asprintf( char **result, const char *fmt, ... );
#endif
#endif

View File

@@ -1,228 +1,228 @@
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef __VHD_H__
#define __VHD_H__
#include <inttypes.h>
typedef uint32_t u32;
typedef uint64_t u64;
/* #define DEBUG 1 */
/* ---------------------------------------------------------------------- */
/* General definitions. */
/* ---------------------------------------------------------------------- */
#define VHD_SECTOR_SIZE 512
#define VHD_SECTOR_SHIFT 9
/* ---------------------------------------------------------------------- */
/* This is the generic disk footer, used by all disks. */
/* ---------------------------------------------------------------------- */
struct hd_ftr {
char cookie[8]; /* Identifies original creator of the disk */
u32 features; /* Feature Support -- see below */
u32 ff_version; /* (major,minor) version of disk file */
u64 data_offset; /* Abs. offset from SOF to next structure */
u32 timestamp; /* Creation time. secs since 1/1/2000GMT */
char crtr_app[4]; /* Creator application */
u32 crtr_ver; /* Creator version (major,minor) */
u32 crtr_os; /* Creator host OS */
u64 orig_size; /* Size at creation (bytes) */
u64 curr_size; /* Current size of disk (bytes) */
u32 geometry; /* Disk geometry */
u32 type; /* Disk type */
u32 checksum; /* 1's comp sum of this struct. */
blk_uuid_t uuid; /* Unique disk ID, used for naming parents */
char saved; /* one-bit -- is this disk/VM in a saved state? */
char hidden; /* tapdisk-specific field: is this vdi hidden? */
char reserved[426]; /* padding */
};
/* VHD cookie string. */
static const char HD_COOKIE[9] = "conectix";
/* Feature fields in hd_ftr */
#define HD_NO_FEATURES 0x00000000
#define HD_TEMPORARY 0x00000001 /* disk can be deleted on shutdown */
#define HD_RESERVED 0x00000002 /* NOTE: must always be set */
/* Version field in hd_ftr */
#define HD_FF_VERSION 0x00010000
/* Known creator OS type fields in hd_ftr.crtr_os */
#define HD_CR_OS_WINDOWS 0x5769326B /* (Wi2k) */
#define HD_CR_OS_MACINTOSH 0x4D616320 /* (Mac ) */
#define HD_CR_OS_UNIX 0x556E6978 /* (Unix) */
#define HD_CR_OS_VMS 0x4F564D53 /* (OVMS) */
/*
* version 0.1: little endian bitmaps
* version 1.1: big endian bitmaps; batmap
* version 1.2: libvhd
* version 1.3: batmap version bump to 1.2
*/
#define VHD_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
#define VHD_CURRENT_VERSION VHD_VERSION(1, 3)
/* Disk geometry accessor macros. */
/* Geometry is a triple of (cylinders (2 bytes), tracks (1 byte), and
* secotrs-per-track (1 byte))
*/
#define GEOM_GET_CYLS(_g) (((_g) >> 16) & 0xffff)
#define GEOM_GET_HEADS(_g) (((_g) >> 8) & 0xff)
#define GEOM_GET_SPT(_g) ((_g) & 0xff)
#define GEOM_ENCODE(_c, _h, _s) (((_c) << 16) | ((_h) << 8) | (_s))
/* type field in hd_ftr */
#define HD_TYPE_NONE 0
#define HD_TYPE_FIXED 2 /* fixed-allocation disk */
#define HD_TYPE_DYNAMIC 3 /* dynamic disk */
#define HD_TYPE_DIFF 4 /* differencing disk */
/* String table for hd.type */
#ifdef __GNUC__
__attribute__((unused))
#endif
static const char *HD_TYPE_STR[7] = {
"None", /* 0 */
"Reserved (deprecated)", /* 1 */
"Fixed hard disk", /* 2 */
"Dynamic hard disk", /* 3 */
"Differencing hard disk", /* 4 */
"Reserved (deprecated)", /* 5 */
"Reserved (deprecated)" /* 6 */
};
#define HD_TYPE_MAX 6
struct prt_loc {
u32 code; /* Platform code -- see defines below. */
u32 data_space; /* Number of 512-byte sectors to store locator */
u32 data_len; /* Actual length of parent locator in bytes */
u32 res; /* Must be zero */
u64 data_offset; /* Absolute offset of locator data (bytes) */
};
/* Platform Codes */
#define PLAT_CODE_NONE 0x0
#define PLAT_CODE_WI2R 0x57693272 /* deprecated */
#define PLAT_CODE_WI2K 0x5769326B /* deprecated */
#define PLAT_CODE_W2RU 0x57327275 /* Windows relative path (UTF-16) */
#define PLAT_CODE_W2KU 0x57326B75 /* Windows absolute path (UTF-16) */
#define PLAT_CODE_MAC 0x4D616320 /* MacOS alias stored as a blob. */
#define PLAT_CODE_MACX 0x4D616358 /* File URL (UTF-8), see RFC 2396. */
/* ---------------------------------------------------------------------- */
/* This is the dynamic disk header. */
/* ---------------------------------------------------------------------- */
struct dd_hdr {
char cookie[8]; /* Should contain "cxsparse" */
u64 data_offset; /* Byte offset of next record. (Unused) 0xffs */
u64 table_offset; /* Absolute offset to the BAT. */
u32 hdr_ver; /* Version of the dd_hdr (major,minor) */
u32 max_bat_size; /* Maximum number of entries in the BAT */
u32 block_size; /* Block size in bytes. Must be power of 2. */
u32 checksum; /* Header checksum. 1's comp of all fields. */
blk_uuid_t prt_uuid; /* ID of the parent disk. */
u32 prt_ts; /* Modification time of the parent disk */
u32 res1; /* Reserved. */
char prt_name[512]; /* Parent unicode name. */
struct prt_loc loc[8]; /* Parent locator entries. */
char res2[256]; /* Reserved. */
};
/* VHD cookie string. */
static const char DD_COOKIE[9] = "cxsparse";
/* Version field in hd_ftr */
#define DD_VERSION 0x00010000
/* Default blocksize is 2 meg. */
#define DD_BLOCKSIZE_DEFAULT 0x00200000
#define DD_BLK_UNUSED 0xFFFFFFFF
struct dd_batmap_hdr {
char cookie[8]; /* should contain "tdbatmap" */
u64 batmap_offset; /* byte offset to batmap */
u32 batmap_size; /* batmap size in sectors */
u32 batmap_version; /* version of batmap */
u32 checksum; /* batmap checksum -- 1's complement of batmap */
};
static const char VHD_BATMAP_COOKIE[9] = "tdbatmap";
/*
* version 1.1: signed char checksum
*/
#define VHD_BATMAP_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
#define VHD_BATMAP_CURRENT_VERSION VHD_BATMAP_VERSION(1, 2)
/* Layout of a dynamic disk:
*
* +-------------------------------------------------+
* | Mirror image of HD footer (hd_ftr) (512 bytes) |
* +-------------------------------------------------+
* | Sparse drive header (dd_hdr) (1024 bytes) |
* +-------------------------------------------------+
* | BAT (Block allocation table) |
* | - Array of absolute sector offsets into the |
* | file (u32). |
* | - Rounded up to a sector boundary. |
* | - Unused entries are marked as 0xFFFFFFFF |
* | - max entries in dd_hdr->max_bat_size |
* +-------------------------------------------------+
* | Data Block 0 |
* | Bitmap (padded to 512 byte sector boundary) |
* | - each bit indicates whether the associated |
* | sector within this block is used. |
* | Data |
* | - power-of-two multiple of sectors. |
* | - default 2MB (4096 * 512) |
* | - Any entries with zero in bitmap should be |
* | zero on disk |
* +-------------------------------------------------+
* | Data Block 1 |
* +-------------------------------------------------+
* | ... |
* +-------------------------------------------------+
* | Data Block n |
* +-------------------------------------------------+
* | HD Footer (511 bytes) |
* +-------------------------------------------------+
*/
#endif
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifndef __VHD_H__
#define __VHD_H__
#include <inttypes.h>
typedef uint32_t u32;
typedef uint64_t u64;
/* #define DEBUG 1 */
/* ---------------------------------------------------------------------- */
/* General definitions. */
/* ---------------------------------------------------------------------- */
#define VHD_SECTOR_SIZE 512
#define VHD_SECTOR_SHIFT 9
/* ---------------------------------------------------------------------- */
/* This is the generic disk footer, used by all disks. */
/* ---------------------------------------------------------------------- */
struct hd_ftr {
char cookie[8]; /* Identifies original creator of the disk */
u32 features; /* Feature Support -- see below */
u32 ff_version; /* (major,minor) version of disk file */
u64 data_offset; /* Abs. offset from SOF to next structure */
u32 timestamp; /* Creation time. secs since 1/1/2000GMT */
char crtr_app[4]; /* Creator application */
u32 crtr_ver; /* Creator version (major,minor) */
u32 crtr_os; /* Creator host OS */
u64 orig_size; /* Size at creation (bytes) */
u64 curr_size; /* Current size of disk (bytes) */
u32 geometry; /* Disk geometry */
u32 type; /* Disk type */
u32 checksum; /* 1's comp sum of this struct. */
blk_uuid_t uuid; /* Unique disk ID, used for naming parents */
char saved; /* one-bit -- is this disk/VM in a saved state? */
char hidden; /* tapdisk-specific field: is this vdi hidden? */
char reserved[426]; /* padding */
};
/* VHD cookie string. */
static const char HD_COOKIE[9] = "conectix";
/* Feature fields in hd_ftr */
#define HD_NO_FEATURES 0x00000000
#define HD_TEMPORARY 0x00000001 /* disk can be deleted on shutdown */
#define HD_RESERVED 0x00000002 /* NOTE: must always be set */
/* Version field in hd_ftr */
#define HD_FF_VERSION 0x00010000
/* Known creator OS type fields in hd_ftr.crtr_os */
#define HD_CR_OS_WINDOWS 0x5769326B /* (Wi2k) */
#define HD_CR_OS_MACINTOSH 0x4D616320 /* (Mac ) */
#define HD_CR_OS_UNIX 0x556E6978 /* (Unix) */
#define HD_CR_OS_VMS 0x4F564D53 /* (OVMS) */
/*
* version 0.1: little endian bitmaps
* version 1.1: big endian bitmaps; batmap
* version 1.2: libvhd
* version 1.3: batmap version bump to 1.2
*/
#define VHD_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
#define VHD_CURRENT_VERSION VHD_VERSION(1, 3)
/* Disk geometry accessor macros. */
/* Geometry is a triple of (cylinders (2 bytes), tracks (1 byte), and
* secotrs-per-track (1 byte))
*/
#define GEOM_GET_CYLS(_g) (((_g) >> 16) & 0xffff)
#define GEOM_GET_HEADS(_g) (((_g) >> 8) & 0xff)
#define GEOM_GET_SPT(_g) ((_g) & 0xff)
#define GEOM_ENCODE(_c, _h, _s) (((_c) << 16) | ((_h) << 8) | (_s))
/* type field in hd_ftr */
#define HD_TYPE_NONE 0
#define HD_TYPE_FIXED 2 /* fixed-allocation disk */
#define HD_TYPE_DYNAMIC 3 /* dynamic disk */
#define HD_TYPE_DIFF 4 /* differencing disk */
/* String table for hd.type */
#ifdef __GNUC__
__attribute__((unused))
#endif
static const char *HD_TYPE_STR[7] = {
"None", /* 0 */
"Reserved (deprecated)", /* 1 */
"Fixed hard disk", /* 2 */
"Dynamic hard disk", /* 3 */
"Differencing hard disk", /* 4 */
"Reserved (deprecated)", /* 5 */
"Reserved (deprecated)" /* 6 */
};
#define HD_TYPE_MAX 6
struct prt_loc {
u32 code; /* Platform code -- see defines below. */
u32 data_space; /* Number of 512-byte sectors to store locator */
u32 data_len; /* Actual length of parent locator in bytes */
u32 res; /* Must be zero */
u64 data_offset; /* Absolute offset of locator data (bytes) */
};
/* Platform Codes */
#define PLAT_CODE_NONE 0x0
#define PLAT_CODE_WI2R 0x57693272 /* deprecated */
#define PLAT_CODE_WI2K 0x5769326B /* deprecated */
#define PLAT_CODE_W2RU 0x57327275 /* Windows relative path (UTF-16) */
#define PLAT_CODE_W2KU 0x57326B75 /* Windows absolute path (UTF-16) */
#define PLAT_CODE_MAC 0x4D616320 /* MacOS alias stored as a blob. */
#define PLAT_CODE_MACX 0x4D616358 /* File URL (UTF-8), see RFC 2396. */
/* ---------------------------------------------------------------------- */
/* This is the dynamic disk header. */
/* ---------------------------------------------------------------------- */
struct dd_hdr {
char cookie[8]; /* Should contain "cxsparse" */
u64 data_offset; /* Byte offset of next record. (Unused) 0xffs */
u64 table_offset; /* Absolute offset to the BAT. */
u32 hdr_ver; /* Version of the dd_hdr (major,minor) */
u32 max_bat_size; /* Maximum number of entries in the BAT */
u32 block_size; /* Block size in bytes. Must be power of 2. */
u32 checksum; /* Header checksum. 1's comp of all fields. */
blk_uuid_t prt_uuid; /* ID of the parent disk. */
u32 prt_ts; /* Modification time of the parent disk */
u32 res1; /* Reserved. */
char prt_name[512]; /* Parent unicode name. */
struct prt_loc loc[8]; /* Parent locator entries. */
char res2[256]; /* Reserved. */
};
/* VHD cookie string. */
static const char DD_COOKIE[9] = "cxsparse";
/* Version field in hd_ftr */
#define DD_VERSION 0x00010000
/* Default blocksize is 2 meg. */
#define DD_BLOCKSIZE_DEFAULT 0x00200000
#define DD_BLK_UNUSED 0xFFFFFFFF
struct dd_batmap_hdr {
char cookie[8]; /* should contain "tdbatmap" */
u64 batmap_offset; /* byte offset to batmap */
u32 batmap_size; /* batmap size in sectors */
u32 batmap_version; /* version of batmap */
u32 checksum; /* batmap checksum -- 1's complement of batmap */
};
static const char VHD_BATMAP_COOKIE[9] = "tdbatmap";
/*
* version 1.1: signed char checksum
*/
#define VHD_BATMAP_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
#define VHD_BATMAP_CURRENT_VERSION VHD_BATMAP_VERSION(1, 2)
/* Layout of a dynamic disk:
*
* +-------------------------------------------------+
* | Mirror image of HD footer (hd_ftr) (512 bytes) |
* +-------------------------------------------------+
* | Sparse drive header (dd_hdr) (1024 bytes) |
* +-------------------------------------------------+
* | BAT (Block allocation table) |
* | - Array of absolute sector offsets into the |
* | file (u32). |
* | - Rounded up to a sector boundary. |
* | - Unused entries are marked as 0xFFFFFFFF |
* | - max entries in dd_hdr->max_bat_size |
* +-------------------------------------------------+
* | Data Block 0 |
* | Bitmap (padded to 512 byte sector boundary) |
* | - each bit indicates whether the associated |
* | sector within this block is used. |
* | Data |
* | - power-of-two multiple of sectors. |
* | - default 2MB (4096 * 512) |
* | - Any entries with zero in bitmap should be |
* | zero on disk |
* +-------------------------------------------------+
* | Data Block 1 |
* +-------------------------------------------------+
* | ... |
* +-------------------------------------------------+
* | Data Block n |
* +-------------------------------------------------+
* | HD Footer (511 bytes) |
* +-------------------------------------------------+
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,442 +1,442 @@
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "relative-path.h"
#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#include <Shlwapi.h>
#define strdup _strdup
#else
#include <syslog.h>
#endif
#define DELIMITER '/'
#define FN __func__
#define EPRINTF(a) rpath_log_error a
static void rpath_log_error( const char *func, const char *fmt, ... )
#ifdef __GNUC__
__attribute__((format(printf,2,3)));
#else
;
#endif
#ifndef LIBVHD_HAS_SYSLOG
#ifdef _WIN32
#define LIBVHD_HAS_SYSLOG 0
#else
#define LIBVHD_HAS_SYSLOG 1
#endif
#endif
#define sfree(ptr) \
do { \
free(ptr); \
ptr = NULL; \
} while (0)
#ifdef _WIN32
LIBVHD_API char *realpath( const char *path, char *resolved ) {
char *p;
DWORD len;
p = resolved;
if( resolved == NULL ) {
resolved = malloc( 1+ MAX_PATH + 1 );
if( resolved == NULL ) {
return NULL;
}
}
if( (len = GetFullPathName( path[0] == '/'? path+1:path, MAX_PATH + 1, resolved, NULL )) == 0 ) {
if( p == NULL )
free( resolved );
return NULL;
}
if( len > MAX_PATH ) {
if( p != NULL )
return NULL;
if( (p = realloc( resolved, len )) == NULL ) {
free( resolved );
return NULL;
}
resolved = p;
len = GetFullPathName( path, MAX_PATH + 1, resolved, NULL );
if( len > MAX_PATH || len == 0 ) {
free( resolved );
return NULL;
}
}
for( p = resolved; *p; p++ ) {
if( *p == '\\')
*p = '/';
}
for( p = resolved; isalpha( *p ); p++ )
;
if( *p == ':' ) { /* Hide drive under '/' for callers. */
memmove( resolved + 1, resolved, strlen( resolved ) +1 );
resolved[0] = '/'; /* Callers must skip '/' when touching filesystem. */
}
return resolved;
}
LIBVHD_API int asprintf( char **result, const char *fmt, ... ) {
int len;
va_list ap;
char *np;
/* It would be better to va_copy() the list and do a prescan,
* but va_copy apparently has issues with versions of MS C
* still in the field. This approach is ugly and wasteful, but
* should work. (A KB just isn't what it used to be...)
*/
if( (*result = malloc( 1 * 100 * 1000 + 1 )) == NULL )
return -1;
va_start( ap, fmt );
len = vsprintf( *result, fmt, ap );
np = realloc( *result, len + 1 );
if( np != NULL )
*result = np;
return len;
}
#endif
/*
* count number of tokens between DELIMITER characters
*/
int count_nodes(char *path)
{
int i;
char *tmp;
if (!path)
return 0;
for (i = 0, tmp = path; *tmp != '\0'; tmp++)
if (*tmp == DELIMITER)
i++;
return i;
}
/*
* return copy of next node in @path, or NULL
* @path is moved to the end of the next node
* @err is set to -errno on failure
* copy should be freed
*/
static char *
next_node(char **path, int *err)
{
int ret;
char *tmp, *start;
if (!path || !*path) {
*err = -EINVAL;
return NULL;
}
*err = 0;
start = *path;
for (tmp = *path; *tmp != '\0'; tmp++)
if (*tmp == DELIMITER) {
int size;
char *node;
size = tmp - start + 1;
node = malloc(size);
if (!node) {
*err = -ENOMEM;
return NULL;
}
ret = snprintf(node, size, "%s", start);
if (ret < 0) {
free(node);
*err = -EINVAL;
return NULL;
}
*path = tmp;
return node;
}
return NULL;
}
/*
* count number of nodes in common betwee @to and @from
* returns number of common nodes, or -errno on failure
*/
static int
count_common_nodes(char *to, char *from)
{
int err, common;
char *to_node, *from_node;
if (!to || !from)
return -EINVAL;
err = 0;
common = 0;
to_node = NULL;
from_node = NULL;
do {
to_node = next_node(&to, &err);
if (err || !to_node)
break;
from_node = next_node(&from, &err);
if (err || !from_node)
break;
if (strncmp(to_node, from_node, MAX_NAME_LEN))
break;
++to;
++from;
++common;
sfree(to_node);
sfree(from_node);
} while (1);
sfree(to_node);
sfree(from_node);
if (err)
return err;
return common;
}
/*
* construct path of @count '../', './' if @count is zero, or NULL on error
* result should be freed
*/
static char *
up_nodes(int count)
{
char *path, *tmp;
int i, ret, len, size;
if (!count)
return strdup("./");
len = strlen("../");
size = len * count;
if (size >= MAX_NAME_LEN)
return NULL;
path = malloc(size + 1);
if (!path)
return NULL;
tmp = path;
for (i = 0; i < count; i++) {
ret = sprintf(tmp, "../");
if (ret < 0 || ret != len) {
free(path);
return NULL;
}
tmp += ret;
}
return path;
}
/*
* return pointer to @offset'th node of path or NULL on error
*/
static char *
node_offset(char *from, int offset)
{
char *path;
if (!from || !offset)
return NULL;
for (path = from; *path != '\0'; path++) {
if (*path == DELIMITER)
if (--offset == 0)
return path + 1;
}
return NULL;
}
/*
* return a relative path from @from to @to
* result should be freed
*/
LIBVHD_API
char *
relative_path_to(char *from, char *to, int *err)
{
int from_nodes, common;
char *to_absolute, *from_absolute;
char *up, *common_target_path, *relative_path;
*err = 0;
up = NULL;
to_absolute = NULL;
from_absolute = NULL;
relative_path = NULL;
if (strnlen(to, MAX_NAME_LEN) == MAX_NAME_LEN ||
strnlen(from, MAX_NAME_LEN) == MAX_NAME_LEN) {
EPRINTF((FN,"invalid input; max path length is %d\n",
MAX_NAME_LEN));
*err = -ENAMETOOLONG;
return NULL;
}
to_absolute = realpath(to, NULL);
if (!to_absolute) {
EPRINTF((FN,"failed to get absolute path of %s\n", to));
*err = -errno;
goto out;
}
from_absolute = realpath(from, NULL);
if (!from_absolute) {
EPRINTF((FN,"failed to get absolute path of %s\n", from));
*err = -errno;
goto out;
}
if (strnlen(to_absolute, MAX_NAME_LEN) == MAX_NAME_LEN ||
strnlen(from_absolute, MAX_NAME_LEN) == MAX_NAME_LEN) {
EPRINTF((FN,"invalid input; max path length is %d\n",
MAX_NAME_LEN));
*err = -ENAMETOOLONG;
goto out;
}
/* count nodes in source path */
from_nodes = count_nodes(from_absolute);
/* count nodes in common */
common = count_common_nodes(to_absolute + 1, from_absolute + 1);
if (common < 0) {
EPRINTF((FN,"failed to count common nodes of %s and %s: %d\n",
to_absolute, from_absolute, common));
*err = common;
goto out;
}
/* move up to common node */
up = up_nodes(from_nodes - common - 1);
if (!up) {
EPRINTF((FN,"failed to allocate relative path for %s: %d\n",
from_absolute, -ENOMEM));
*err = -ENOMEM;
goto out;
}
/* get path from common node to target */
common_target_path = node_offset(to_absolute, common + 1);
if (!common_target_path) {
EPRINTF((FN,"failed to find common target path to %s: %d\n",
to_absolute, -EINVAL));
*err = -EINVAL;
goto out;
}
/* get relative path */
if (asprintf(&relative_path, "%s%s", up, common_target_path) == -1) {
EPRINTF((FN,"failed to construct final path %s%s: %d\n",
up, common_target_path, -ENOMEM));
relative_path = NULL;
*err = -ENOMEM;
goto out;
}
out:
sfree(up);
sfree(to_absolute);
sfree(from_absolute);
return relative_path;
}
static void rpath_log_error( const char *func, const char *fmt, ... )
{
char *buf, nilbuf;
size_t ilen, len;
va_list ap;
ilen = sizeof( "tap-err:%s: " ) + strlen( func ) -2;
va_start(ap, fmt );
len = vsnprintf( &nilbuf, 1, fmt, ap );
va_end( ap );
if( (buf = malloc( ilen + len + 1 )) == NULL ) {
#if LIBVHD_HAS_SYSLOG
syslog( LOG_INFO, "tap-err:%s: Out of memory", func );
#else
fprintf( stderr, "tap-err%s: Out of memory for %s\n", func, fmt );
#endif
return;
}
va_start(ap, fmt);
(void) snprintf( buf, ilen, "tap-err:%s: ", func );
(void) vsnprintf( buf + ilen -1, len+1, fmt, ap );
va_end( ap );
len += ilen -1;
if( buf[ len -1 ] != '\n' )
buf[len++] = '\n';
buf[len] = '\0';
#if LIBVHD_HAS_SYSLOG
syslog(LOG_INFO, buf);
#else
fputs( buf, stderr );
#endif
free( buf );
return;
}
/* Copyright (c) 2008, XenSource Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of XenSource Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified March 2016 Timothe Litt to work under windows.
* Copyright (C) 2016 Timothe Litt
* Modifications subject to the same license terms as above,
* substituting "Timothe Litt" for "XenSource Inc."
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "relative-path.h"
#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#include <Shlwapi.h>
#define strdup _strdup
#else
#include <syslog.h>
#endif
#define DELIMITER '/'
#define FN __func__
#define EPRINTF(a) rpath_log_error a
static void rpath_log_error( const char *func, const char *fmt, ... )
#ifdef __GNUC__
__attribute__((format(printf,2,3)));
#else
;
#endif
#ifndef LIBVHD_HAS_SYSLOG
#ifdef _WIN32
#define LIBVHD_HAS_SYSLOG 0
#else
#define LIBVHD_HAS_SYSLOG 1
#endif
#endif
#define sfree(ptr) \
do { \
free(ptr); \
ptr = NULL; \
} while (0)
#ifdef _WIN32
LIBVHD_API char *realpath( const char *path, char *resolved ) {
char *p;
DWORD len;
p = resolved;
if( resolved == NULL ) {
resolved = malloc( 1+ MAX_PATH + 1 );
if( resolved == NULL ) {
return NULL;
}
}
if( (len = GetFullPathName( path[0] == '/'? path+1:path, MAX_PATH + 1, resolved, NULL )) == 0 ) {
if( p == NULL )
free( resolved );
return NULL;
}
if( len > MAX_PATH ) {
if( p != NULL )
return NULL;
if( (p = realloc( resolved, len )) == NULL ) {
free( resolved );
return NULL;
}
resolved = p;
len = GetFullPathName( path, MAX_PATH + 1, resolved, NULL );
if( len > MAX_PATH || len == 0 ) {
free( resolved );
return NULL;
}
}
for( p = resolved; *p; p++ ) {
if( *p == '\\')
*p = '/';
}
for( p = resolved; isalpha( *p ); p++ )
;
if( *p == ':' ) { /* Hide drive under '/' for callers. */
memmove( resolved + 1, resolved, strlen( resolved ) +1 );
resolved[0] = '/'; /* Callers must skip '/' when touching filesystem. */
}
return resolved;
}
LIBVHD_API int asprintf( char **result, const char *fmt, ... ) {
int len;
va_list ap;
char *np;
/* It would be better to va_copy() the list and do a prescan,
* but va_copy apparently has issues with versions of MS C
* still in the field. This approach is ugly and wasteful, but
* should work. (A KB just isn't what it used to be...)
*/
if( (*result = malloc( 1 * 100 * 1000 + 1 )) == NULL )
return -1;
va_start( ap, fmt );
len = vsprintf( *result, fmt, ap );
np = realloc( *result, len + 1 );
if( np != NULL )
*result = np;
return len;
}
#endif
/*
* count number of tokens between DELIMITER characters
*/
int count_nodes(char *path)
{
int i;
char *tmp;
if (!path)
return 0;
for (i = 0, tmp = path; *tmp != '\0'; tmp++)
if (*tmp == DELIMITER)
i++;
return i;
}
/*
* return copy of next node in @path, or NULL
* @path is moved to the end of the next node
* @err is set to -errno on failure
* copy should be freed
*/
static char *
next_node(char **path, int *err)
{
int ret;
char *tmp, *start;
if (!path || !*path) {
*err = -EINVAL;
return NULL;
}
*err = 0;
start = *path;
for (tmp = *path; *tmp != '\0'; tmp++)
if (*tmp == DELIMITER) {
int size;
char *node;
size = tmp - start + 1;
node = malloc(size);
if (!node) {
*err = -ENOMEM;
return NULL;
}
ret = snprintf(node, size, "%s", start);
if (ret < 0) {
free(node);
*err = -EINVAL;
return NULL;
}
*path = tmp;
return node;
}
return NULL;
}
/*
* count number of nodes in common betwee @to and @from
* returns number of common nodes, or -errno on failure
*/
static int
count_common_nodes(char *to, char *from)
{
int err, common;
char *to_node, *from_node;
if (!to || !from)
return -EINVAL;
err = 0;
common = 0;
to_node = NULL;
from_node = NULL;
do {
to_node = next_node(&to, &err);
if (err || !to_node)
break;
from_node = next_node(&from, &err);
if (err || !from_node)
break;
if (strncmp(to_node, from_node, MAX_NAME_LEN))
break;
++to;
++from;
++common;
sfree(to_node);
sfree(from_node);
} while (1);
sfree(to_node);
sfree(from_node);
if (err)
return err;
return common;
}
/*
* construct path of @count '../', './' if @count is zero, or NULL on error
* result should be freed
*/
static char *
up_nodes(int count)
{
char *path, *tmp;
int i, ret, len, size;
if (!count)
return strdup("./");
len = strlen("../");
size = len * count;
if (size >= MAX_NAME_LEN)
return NULL;
path = malloc(size + 1);
if (!path)
return NULL;
tmp = path;
for (i = 0; i < count; i++) {
ret = sprintf(tmp, "../");
if (ret < 0 || ret != len) {
free(path);
return NULL;
}
tmp += ret;
}
return path;
}
/*
* return pointer to @offset'th node of path or NULL on error
*/
static char *
node_offset(char *from, int offset)
{
char *path;
if (!from || !offset)
return NULL;
for (path = from; *path != '\0'; path++) {
if (*path == DELIMITER)
if (--offset == 0)
return path + 1;
}
return NULL;
}
/*
* return a relative path from @from to @to
* result should be freed
*/
LIBVHD_API
char *
relative_path_to(char *from, char *to, int *err)
{
int from_nodes, common;
char *to_absolute, *from_absolute;
char *up, *common_target_path, *relative_path;
*err = 0;
up = NULL;
to_absolute = NULL;
from_absolute = NULL;
relative_path = NULL;
if (strnlen(to, MAX_NAME_LEN) == MAX_NAME_LEN ||
strnlen(from, MAX_NAME_LEN) == MAX_NAME_LEN) {
EPRINTF((FN,"invalid input; max path length is %d\n",
MAX_NAME_LEN));
*err = -ENAMETOOLONG;
return NULL;
}
to_absolute = realpath(to, NULL);
if (!to_absolute) {
EPRINTF((FN,"failed to get absolute path of %s\n", to));
*err = -errno;
goto out;
}
from_absolute = realpath(from, NULL);
if (!from_absolute) {
EPRINTF((FN,"failed to get absolute path of %s\n", from));
*err = -errno;
goto out;
}
if (strnlen(to_absolute, MAX_NAME_LEN) == MAX_NAME_LEN ||
strnlen(from_absolute, MAX_NAME_LEN) == MAX_NAME_LEN) {
EPRINTF((FN,"invalid input; max path length is %d\n",
MAX_NAME_LEN));
*err = -ENAMETOOLONG;
goto out;
}
/* count nodes in source path */
from_nodes = count_nodes(from_absolute);
/* count nodes in common */
common = count_common_nodes(to_absolute + 1, from_absolute + 1);
if (common < 0) {
EPRINTF((FN,"failed to count common nodes of %s and %s: %d\n",
to_absolute, from_absolute, common));
*err = common;
goto out;
}
/* move up to common node */
up = up_nodes(from_nodes - common - 1);
if (!up) {
EPRINTF((FN,"failed to allocate relative path for %s: %d\n",
from_absolute, -ENOMEM));
*err = -ENOMEM;
goto out;
}
/* get path from common node to target */
common_target_path = node_offset(to_absolute, common + 1);
if (!common_target_path) {
EPRINTF((FN,"failed to find common target path to %s: %d\n",
to_absolute, -EINVAL));
*err = -EINVAL;
goto out;
}
/* get relative path */
if (asprintf(&relative_path, "%s%s", up, common_target_path) == -1) {
EPRINTF((FN,"failed to construct final path %s%s: %d\n",
up, common_target_path, -ENOMEM));
relative_path = NULL;
*err = -ENOMEM;
goto out;
}
out:
sfree(up);
sfree(to_absolute);
sfree(from_absolute);
return relative_path;
}
static void rpath_log_error( const char *func, const char *fmt, ... )
{
char *buf, nilbuf;
size_t ilen, len;
va_list ap;
ilen = sizeof( "tap-err:%s: " ) + strlen( func ) -2;
va_start(ap, fmt );
len = vsnprintf( &nilbuf, 1, fmt, ap );
va_end( ap );
if( (buf = malloc( ilen + len + 1 )) == NULL ) {
#if LIBVHD_HAS_SYSLOG
syslog( LOG_INFO, "tap-err:%s: Out of memory", func );
#else
fprintf( stderr, "tap-err%s: Out of memory for %s\n", func, fmt );
#endif
return;
}
va_start(ap, fmt);
(void) snprintf( buf, ilen, "tap-err:%s: ", func );
(void) vsnprintf( buf + ilen -1, len+1, fmt, ap );
va_end( ap );
len += ilen -1;
if( buf[ len -1 ] != '\n' )
buf[len++] = '\n';
buf[len] = '\0';
#if LIBVHD_HAS_SYSLOG
syslog(LOG_INFO, buf);
#else
fputs( buf, stderr );
#endif
free( buf );
return;
}

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{0b040f93-b411-4ceb-b55b-5aae6c27347d}</ProjectGuid>
<RootNamespace>makehelp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;DEBUG_BUILD;USE_VLD</PreprocessorDefinitions>
<ConformanceMode>Default</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUG_BUILD;USE_VLD</PreprocessorDefinitions>
<ConformanceMode>Default</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(CoreLibraryDependencies);Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\ods2\compat.c" />
<ClCompile Include="..\ods2\makehelp.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

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

5
extracters/ods2/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
ods2
makehelp
genmsg
testdata
attic

View File

@@ -1,3 +1,2 @@
--memcheck:leak-check=yes
--suppressions=valgrind_suppressions_readline
--suppressions=valgrind_suppressions_ods2

View File

@@ -11,6 +11,8 @@ The platform-specific files are:
Select the appropriate platform file & review the definitions.
For Unix-like OSs, defaults are set in makefile.unixdefs.
The easiest way to build ODS-2 is to softlink Makefile to
the platform file. For example:
ln -s makefile.unix Makefile
@@ -19,16 +21,51 @@ the platform file. For example:
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,
Copy the resulting object file, the .HLB, and .MDF files 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.
The .HLB files contain the (compiled) help text. The MDF files contain
message strings. Both are binary files, may be architecture-specific,
and can be localized.
Building from source requires Perl and uses data from VMS message and header files.
Unless you are localizing messages, the included files suffice. The procedure
for extracting localized messages from VMS is documented in the message script..
VHD support requires the libvhd in simtools/extracters/libvhd and
simtools/extracters/vhd-tools. Note that these are different from the
vhd support in simH.
ods2 includes RMS emulation that is fairly complete (except for indexed organization).
Messages use a VMS getmsg emulation; .msg files are localizable.
If you have an alternate message file (e.g. for I18n), it will be a
.mdf file (e.g. ods2_en_us.mdf), which should also be placed in a convenient
place.
The help source is in .hlp files, which are structured text. They are compiled
into .hlb files by makehelp. en_us.hlp is the base file; any translations should
use the same naming convention. The makefiles generate ods2_en_us.hlb. The
helpfile can be selected by the ODS2HELP environment variable, and/or the
set helpfile command.
The default help library filename is "ods2.hlb", in the same directory as
the ods2 executable. This file is made a symlink or copy of the default
language by the makefile. If another available language is desired,
softlink (or copy) the desired language file to it (or set the ODS2HELP
environment variable.)
E.g. for US English help: ln -s ods2_en_us.hlb ods2.hlb
If you need different definitions for another platform, please
add a new platform-specific file rather than changing makefile.generic.
For development, I use a wrapper on make called "strictmake" to keep the sources
as clean as possible; it enables extra warnings from gcc (and filters a few). I
also use "grind" to run with valgrind to keep the code leak free. Currently,
the only exception is that libedit doesn't completely clean up on exit.
On VMS, you can use the DCL command procedure build.com to build
with DECC or GCC, with
$ @build
@@ -40,4 +77,15 @@ If you have MMS/mmk, use descrip.mms, with
To build with VAXC
$ mmk/macro=vaxc=1
For Microsoft Windows, use Visual Studio - the free Community Edition works.
A solution file is included in ODS2's git repository. x64, x86 builds are
supported. Debug builds include Visual Leak Detector (a free tool), but
that can be turned off. VLD indicates that ODS2 is leak-free on Windows.
I build for Windows with the sources on a Linux share. This makes it easy
to test changes with one copy of the source. The object files do not overlap;
the VS directories are excluded from git. For convenience, the windows .EXEs
are copied to the git working directory.
Bug reports, contributions, and feature requests are welcome
at https://github.com/open-simh/simtools/issues.

View File

@@ -0,0 +1,175 @@
ODS2 provides access to DEC Files-11 On-Disk Structure Level 2 volumes from
Unix, VMS & Windows hosts.
It is capable of reading and writing physical volumes, such as SCSI disks and
CDROMs, as well as SimH simulator files (native, and optionally VHD).
The original code was developed by Paul Nankervis, email address: Paulnank@au1.ibm.com.
This version has been extensively re-worked - debugged, completed and enhanced - by
Timothe Litt - litt@acm.org. It also contains contributions from Larry Baker of
the USGS and from Hunter Goatley. The VHD support is open-source from the Xen
project - with some minor changes on Unix & some significant changes for Windows.
This version provides full read and write support for ODS2 volumes - physical and
virtual. It can initialize volumes, create, read, write, and extend files. It
allows files to be copied between the host filesystem and the Files-11 volume(s),
converting all RMS formats except indexed. Volume sets and multiple independent volumes
can be accessed simultaneously.
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 contributions
of the original author and subsequent contributors. This is free software; no warranty
is offered, and while we believe it to be useful, you use it at your own risk.
There are opportunities for additional contributions, among them:
- message file translations
- help file completion and translations
- testing on other host platforms
Please use the https://github.com/open-simh/simtools repository for pull
requests and issues.
ODS2 starts by executing a command file, which it looks for in the following order:
The environment variable (or logical name) ODS2INIT
The user's home directory
Windows: %HOMEDRIVE%%HOMEPATH%\.ods2.ini
VMS: SYS$LOGIN:_ODS2.INI
Unix: $HOME/.ods2.ini
This can be used to specify defaults, mount a favorite device...
No error is reported if the file does not exist.
Next, ODS2 executes any commands specified on the command line.
Multiple command are separated by '$' (most shells require $ to be quoted).
Finally, ODS2 enters interactive mode. Under Unix, with READLINE support, command
history is preserved in $HOME/.ods2.
The HELP command provides full command syntax, which is very similar to DCL.
The help text is located in ods2.hlb, in the same directory as ODS2. You can
set the environment variable ODS2HELP to an alternate helpfile or use the
set helpfile command. Note that helpfiles are binary - see 00INSTALL.TXT..
N.B. The default help library filename is "ods2.hlb", in the same directory as
the ods2 executable. This file is made a symlink or copy of the default
language by the makefile. If another available language is desired,
softlink (or copy) the desired language file to it (or set the ODS2HELP
environment variable.)
E.g. for US English help: ln -s ods2_en_us.hlb ods2.hlb
The following is a brief summary of commonly-used command sequences.
Abbreviations can be used. Full VMS filenames (device:[dir.sfd...]name.ext;gen)
can be used for files on the FILES-11 volume. Wildcards are supported for most
commands. Wildcards can be used on the host filesystem, e.g. when copying files
to the volume.
The most important command for any program:
ODS2$> EXIT
(QUIT also works.)
Create a new Files-11 volume:
ODS2$> INITIALIZE /medium:RM02/LOG rm02.vhd myvolume
N.B. The .vhd file type will create a dynamic (sparse) VHD-format simulator file.
It is important to specify the medium type, as FILES-11 is sensitve to volume
size and geometry.
Create a directory:
ODS2$> CREATE/DIRECTORY/LOG [FRED.PAKS]
Copy files to the volume:
ODS2$> COPY /TO_FILES-11/ASCII *.txt *.doc [FRED.PAKS]*.*
Set default directory on the volume:
ODS2$> SET DEFAULT [FRED.PAKS]
See what's there:
ODS2$> DIR /DATE/SIZE
Copy files from the volume:
ODS2$> COPY /FROM_FILES-11/ASCII *.txt *.*
Mount an existing volume:
ODS2$> MOUNT /medium:RM02 /WRITE rmo2.vhd myvolume
N.B. The volume name is optional, but if specified must match.
Dismount the volume:
ODS2$> DISMOUNT A:
(The drive letter will vary - it's reported by INITIALIZE/MOUNT)
N.B. It's VERY important to dismount the volume, especially if it's mounted
for write. ODS2 makes heavy use of caching, and any interruption will
leave it in an inconsistent state.
Inspect a file on the volume:
ODS2$> TYPE/PAGE *.TXT
Obtain information:
ODS2$> SHOW DEVICES
ODS2$> SHOW VOLUMES
Interactively create a file:
ODS2$> CREATE FILE.TXT
mumble
gobble
^D
(or ^Z on Windows/VMS)
Delete a file
ODS2$> DELETE FILE.TXT;2
More advanced usage:
When asked for confirmation, the VMS DCL responses are accepted:
0, no, false : Don't do this action, ask again for additional items
1, yes, true : Proceed with this action, ask again for additional items
quit : Don't do this action, and don't consider any more items
all : Proceed with this action, and do all other items without asking
Lines beginning with ';' or '!' are considered comments, and ignored. This
may be used for commenting command files.
With editline (libedit) support, a comment entry is made in the command history
when an initialization file is opened. This can be used to trace initialization
issues. editlline also uses ~/.editrc and can be customized using the
'ods2' tag. editline is a Unix command history editor that can be compiled
with ods2. 'man 7 editline' and 'man 5 editrc' for usage details. editline
is available on most Linux distributions; building ods2 requires the corresponding
-dev(el) package.
It may be necessary to quote command arguments, e.g. when specifying a
file name on a Unix system that includes '/'. Use '"' or "'"; double
the quote character to include it in the string. e.g. """hello""" produces
"hello"
Alternatively, you can switch to unix-style options with SET QUALIFIER_STYLE UNIX.
A heuristic is used to distinguish physical devices from simulator disk image
files in the mount and initialize commands. Use /device or /image if it
guesses wrong.
It is possible to mount multiple volumes simultaneously, though not
(currently) to move files directly from one Files-11 volume to another.
It is possible to mount volumesets, though this hasn't been completely debugged.
Command files can be executed with @filename. They can be nested.
Favorite directory and/or copy qualifiers can be set in the .ini file, e.g.
SET DIRECTORY /DATE/SIZE
With VHD support, you can write to a snapshot of the volume:
ODS2$> MOUNT /SNAPSHOTS_OF=myvolume.vhd testvolume.vhd /write
For more details on these and other capabilities, use the HELP command.
For build/installation information, see 00INSTALL.TXT
Bug reports, contributions, and feature requests are welcome
at https://github.com/open-simh/simtools/issues.
-- Timothe Litt
April 2016, October 2022

1
extracters/ods2/Makefile Symbolic link
View File

@@ -0,0 +1 @@
makefile.unix

Binary file not shown.

35
extracters/ods2/ODS2.sln Normal file → Executable file
View File

@@ -1,20 +1,51 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ODS2", "ODS2.vcxproj", "{BCCEAED2-1732-D796-1F70-040DE5DA42AD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genmsg-en", "genmsg-en\genmsg-en.vcxproj", "{5AC343A4-5F8B-47F1-982B-7E44B3208748}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "makehelp", "..\makehelp\makehelp.vcxproj", "{0B040F93-B411-4CEB-B55B-5AAE6C27347D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
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}.Debug|x64.ActiveCfg = Debug|x64
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Debug|x64.Build.0 = Debug|x64
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|Win32.ActiveCfg = Release|Win32
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|Win32.Build.0 = Release|Win32
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|x64.ActiveCfg = Release|x64
{BCCEAED2-1732-D796-1F70-040DE5DA42AD}.Release|x64.Build.0 = Release|x64
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Debug|Win32.ActiveCfg = Debug|Win32
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Debug|Win32.Build.0 = Debug|Win32
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Debug|x64.ActiveCfg = Debug|x64
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Debug|x64.Build.0 = Debug|x64
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Release|Win32.ActiveCfg = Release|Win32
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Release|Win32.Build.0 = Release|Win32
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Release|x64.ActiveCfg = Release|x64
{5AC343A4-5F8B-47F1-982B-7E44B3208748}.Release|x64.Build.0 = Release|x64
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Debug|Win32.ActiveCfg = Debug|Win32
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Debug|Win32.Build.0 = Debug|Win32
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Debug|x64.ActiveCfg = Debug|x64
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Debug|x64.Build.0 = Debug|x64
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Release|Win32.ActiveCfg = Release|Win32
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Release|Win32.Build.0 = Release|Win32
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Release|x64.ActiveCfg = Release|x64
{0B040F93-B411-4CEB-B55B-5AAE6C27347D}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E61B3FE9-F8F6-44C6-AF2F-E3CEDB9B04B7}
EndGlobalSection
EndGlobal

119
extracters/ods2/ODS2.vcxproj Normal file → Executable file
View File

@@ -5,25 +5,44 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{BCCEAED2-1732-D796-1F70-040DE5DA42AD}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -31,19 +50,33 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<CustomBuildAfterTargets>
</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<CustomBuildAfterTargets />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>USE_VLD;DEBUG_BUILD;USE_VHD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -52,6 +85,7 @@
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>vhd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessToFile>false</PreprocessToFile>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
@@ -66,14 +100,41 @@
</Command>
</PostBuildEvent>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)_$(PlatformShortName)_debug$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)_$(PlatformShortName)_debug$(TargetExt)</Outputs>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
<PreBuildEvent>
<Command>del $(SolutionDir)$(TargetName)$(TargetExt) &gt;nil.bak 2&gt;&amp;1 || exit /b 0</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>USE_VLD;DEBUG_BUILD;USE_VHD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>vhd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessToFile>false</PreprocessToFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>Rpcrt4.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>
</DelayLoadDLLs>
</Link>
<PostBuildEvent>
<Command>
</Command>
<Outputs>
</Outputs>
<Inputs>
</Inputs>
<Message>
</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)_$(PlatformShortName)_debug$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)_$(PlatformShortName)_debug$(TargetExt)</Outputs>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
<PreBuildEvent>
<Command>del $(SolutionDir)$(TargetName)$(TargetExt) &gt;nil.bak 2&gt;&amp;1 || exit /b 0</Command>
@@ -100,8 +161,34 @@
</Command>
</PostBuildEvent>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)$(TargetExt)</Outputs>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)_$(PlatformShortName)$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)_$(PlatformShortName)$(TargetExt)</Outputs>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>USE_VHD;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>vhd\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>Rpcrt4.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)_$(PlatformShortName)$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)_$(PlatformShortName)$(TargetExt)</Outputs>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
@@ -114,6 +201,7 @@
<ClCompile Include="createcmd.c" />
<ClCompile Include="debug.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="deletecmd.c" />
<ClCompile Include="device.c" />
@@ -123,7 +211,6 @@
<ClCompile Include="dismountcmd.c" />
<ClCompile Include="extendcmd.c" />
<ClCompile Include="helpcmd.c" />
<ClCompile Include="importcmd.c" />
<ClCompile Include="initialcmd.c" />
<ClCompile Include="initvol.c" />
<ClCompile Include="mountcmd.c" />
@@ -131,17 +218,19 @@
<ClCompile Include="phynt.c" />
<ClCompile Include="phyvhd.c" />
<ClCompile Include="phyvirt.c" />
<ClCompile Include="renamecmd.c" />
<ClCompile Include="rms.c" />
<ClCompile Include="searchcmd.c" />
<ClCompile Include="setcmd.c" />
<ClCompile Include="showcmd.c" />
<ClCompile Include="spawncmd.c" />
<ClCompile Include="sysmsg.c" />
<ClCompile Include="typecmd.c" />
<ClCompile Include="termio.c" />
<ClCompile Include="update.c" />
<ClCompile Include="vhd\libvhd.c" />
<ClCompile Include="vhd\relative-path.c" />
<ClCompile Include="vmstime.c" />
<ClCompile Include="winfile.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="access.h" />
@@ -170,11 +259,17 @@
<ClInclude Include="vhd\relative-path.h" />
<ClInclude Include="vhd\vhd.h" />
<ClInclude Include="vmstime.h" />
<ClInclude Include="winfile.h" />
<ClInclude Include="wnaspi32.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ods2.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="default.mt">
<FileType>Document</FileType>
</ClInclude>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

15
extracters/ods2/ODS2.vcxproj.filters Normal file → Executable file
View File

@@ -90,9 +90,6 @@
<ClCompile Include="helpcmd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="importcmd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="initialcmd.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -111,7 +108,13 @@
<ClCompile Include="spawncmd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="typecmd.c">
<ClCompile Include="winfile.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="termio.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="renamecmd.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -197,6 +200,10 @@
<ClInclude Include="cmddef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="winfile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="default.mt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ods2.rc">

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,22 @@
/* Access.h 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.
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _ACCESS_H
#define _ACCESS_H
#include "ods2.h"
#include "cache.h"
#include "f11def.h"
#include "vmstime.h"
@@ -21,14 +25,14 @@
struct WCB {
struct CACHE cache;
unsigned loblk,hiblk; /* Range of window */
unsigned hd_basevbn; /* File blocks prior to header */
uint32_t loblk, hiblk; /* Range of window */
uint32_t hd_basevbn; /* File blocks prior to header */
unsigned hd_seg_num; /* Header segment number */
struct fiddef hd_fid; /* Header FID */
unsigned short extcount; /* Extents in use */
unsigned phylen[EXTMAX];
unsigned phyblk[EXTMAX];
unsigned char rvn[EXTMAX];
uint32_t phylen[EXTMAX];
uint32_t phyblk[EXTMAX];
uint8_t rvn[EXTMAX];
}; /* Window control block */
#define VIOC_CHUNKSIZE 4
@@ -48,29 +52,32 @@ struct FCB {
struct HEAD *head; /* Pointer to header block */
struct WCB *wcb; /* Window control block tree */
struct VIOC *vioc; /* Virtual I/O chunk tree */
unsigned headvbn; /* vbn for file header */
unsigned hiblock; /* Highest block mapped */
unsigned highwater; /* First high water block */
uint32_t headvbn; /* vbn for file header */
uint32_t hiblock; /* Highest block mapped */
uint32_t highwater; /* First high water block */
unsigned char status; /* FCB status bits */
#define FCB_WRITE 1 /* FCB open for write... */
unsigned char rvn; /* Initial file relative volume */
#define FCB_WRITTEN 2 /* Modified */
#define FCB_RDTSET 4 /* Revision date set by create */
uint8_t 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 */
struct fiddef parent;
struct dir$r_ent entry;
struct dir$r_rec record;
};
#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 */
uint32_t clustersize; /* Cluster size of the device */
uint32_t max_cluster; /* Total clusters on the device */
uint32_t free_clusters; /* Free clusters on disk volume */
struct HOME home; /* Volume home block */
};
struct VCB {
@@ -89,35 +96,66 @@ void show_volumes( void );
/* returns NULL if RVN illegal or device not mounted */
#define RVN_TO_DEV( vcb, rvn ) ( ( rvn < 2 ) ? \
vcb->vcbdev : \
( ( rvn <= vcb->devices ) ? \
&vcb->vcbdev[rvn - 1] : \
NULL \
) \
)
#define RVN_TO_DEV( vcb, rvn ) ( ( rvn < 2 ) ? \
vcb->vcbdev : \
( ( rvn <= vcb->devices ) ? \
&vcb->vcbdev[rvn - 1] : \
NULL \
) \
)
void fid_copy(struct fiddef *dst,struct fiddef *src,unsigned rvn);
struct NEWFILE {
struct RECATTR recattr;
VMSTIME credate;
VMSTIME revdate;
VMSTIME expdate;
VMSTIME bakdate;
f11word verlimit;
f11word revision;
uint32_t fileprot;
f11long filechar;
struct UIC fileowner;
};
unsigned dismount(struct VCB *vcb);
unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[] );
void fid_copy( struct fiddef *dst, struct fiddef *src, unsigned rvn );
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);
vmscond_t dismount( struct VCB *vcb, options_t options);
vmscond_t mount( options_t flags, unsigned devices, char *devnam[], char *label[] );
vmscond_t accesserase( struct VCB *vcb, struct fiddef *fid );
vmscond_t deaccessfile( struct FCB *fcb );
vmscond_t accessfile( struct VCB *vcb, struct fiddef *fid,
struct FCB **fcb, unsigned wrtflg );
vmscond_t deaccesschunk( struct VIOC *vioc, uint32_t wrtvbn, int wrtblks, int reuse );
vmscond_t accesschunk( struct FCB *fcb, uint32_t vbn, struct VIOC **retvioc,
char **retbuff, uint32_t *retblocks, uint32_t wrtblks );
vmscond_t access_extend( struct FCB *fcb, uint32_t blocks, unsigned contig );
vmscond_t deallocfile(struct FCB *fcb);
unsigned deaccesschunk(struct VIOC *vioc,unsigned wrtvbn,int wrtblks,int reuse);
unsigned accesschunk(struct FCB *fcb,unsigned vbn,struct VIOC **retvioc,
char **retbuff,unsigned *retblocks,unsigned wrtblks);
unsigned access_extend(struct FCB *fcb,unsigned blocks,unsigned contig);
unsigned update_freecount(struct VCBDEV *vcbdev,unsigned *retcount);
unsigned update_create(struct VCB *vcb,struct fiddef *did,char *filename,
struct fiddef *fid,struct FCB **fcb);
unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig);
f11word checksumn( f11word *block, int count );
f11word checksum( f11word *block );
void access_rundown( void );
/* These live in update.c, which contains the write part of access */
vmscond_t update_freecount( struct VCBDEV *vcbdev, uint32_t *retcount );
vmscond_t update_create( struct VCB *vcb, struct fiddef *did, char *filename,
struct fiddef *fid, struct NEWFILE *attrs, struct FCB **fcb );
vmscond_t update_extend( struct FCB *fcb, uint32_t blocks, unsigned contig );
vmscond_t update_truncate( struct FCB *fcb, uint32_t newsize );
/* These are used by update.c */
vmscond_t deaccesshead( struct VIOC *vioc, struct HEAD *head, uint32_t idxblk );
vmscond_t accesshead( struct VCB *vcb, struct fiddef *fid, uint32_t seg_num,
struct VIOC **vioc, struct HEAD **headbuff,
uint32_t *retidxblk, unsigned wrtflg );
vmscond_t getwindow( struct FCB * fcb, uint32_t vbn, struct VCBDEV **devptr,
uint32_t *phyblk, uint32_t *phylen, struct fiddef *hdrfid,
uint32_t *hdrseq );
#endif /* # ifndef _ACCESS_H */

View File

@@ -4,7 +4,7 @@ $
$ default = F$Environment( "DEFAULT" )
$ this = F$Environment( "PROCEDURE" )
$ src = F$Parse( this, , , "DEVICE", "SYNTAX_ONLY" ) + -
F$Parse( this, , , "DIRECTORY", "SYNTAX_ONLY" )
F$Parse( this, , , "DIRECTORY", "SYNTAX_ONLY" )
$
$ If ( P1 .eqs. "CLEAN" )
$ Then

View File

@@ -1,50 +1,53 @@
/* Cache.c 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/*
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, file windows, file chunks
(segments) 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).
The main routines is cache_find() which is used to search for and
place objects in a binary tree which is located by a tree pointer.
cache_touch() and cache_untouch() are used to bump and decrement
reference counts. Any object with a reference count of zero is a
candidate for destruction - but if it requires special action
before it is destroyed, such as deleting a subtree, flushing data
to disk, etc, then it should have an 'object manager' function
assigned which will be called at deletion time to take care of these
needs.
This version of the cache routines attempts to maintain binary tree
balance by dynamically changing tree shape during search functions.
All objects remain in the binary tree until destruction so that they
can be re-used at any time. Objects with a zero reference count are
special in that they are kept in a 'least recently used' linked list.
When the reference count is decemented a flag is used to indicate
whether the object is likely to be referenced again so that the object
can be put in the 'correct' end of this list.
Note: These routines are 'general' in that do not know anything
about ODS2 objects or structures....
*/
* 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, file windows, file chunks
* (segments) 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).
*
* The main routines is cache_find() which is used to search for and
* place objects in a binary tree which is located by a tree pointer.
* cache_touch() and cache_untouch() are used to bump and decrement
* reference counts. Any object with a reference count of zero is a
* candidate for destruction - but if it requires special action
* before it is destroyed, such as deleting a subtree, flushing data
* to disk, etc, then it should have an 'object manager' function
* assigned which will be called at deletion time to take care of these
* needs.
*
* This version of the cache routines attempts to maintain binary tree
* balance by dynamically changing tree shape during search functions.
* All objects remain in the binary tree until destruction so that they
* can be re-used at any time. Objects with a zero reference count are
* special in that they are kept in a 'least recently used' linked list.
* When the reference count is decemented a flag is used to indicate
* whether the object is likely to be referenced again so that the object
* can be put in the 'correct' end of this list.
*
* Note: These routines are 'general' in that do not know anything
* about ODS2 objects or structures....
*/
#if !defined( DEBUG ) && defined( DEBUG_CACHE )
#define DEBUG DEBUG_CACHE
@@ -80,7 +83,7 @@ static int cachedeletes = 0;
static int cachedeleteing = FALSE; /* Cache deletion in progress... */
struct CACHE lrulist = {&lrulist,&lrulist,NULL,NULL,NULL,NULL,0,0,1,0};
struct CACHE lrulist = {&lrulist, &lrulist, NULL, NULL, NULL, NULL, 0, 0, 1, 0};
static void cache_deleter( struct CACHE *cacheobj, struct CACHE **actualobj );
@@ -91,10 +94,10 @@ static void cache_deleter( struct CACHE *cacheobj, struct CACHE **actualobj );
void cache_show(void)
{
printf("CACHE_SHOW Find %d Create %d Purge %d Peak %d Count %d Free %d\n",
cachefinds,cachecreated,cachepurges,cachepeak,cachecount,
cachefinds, cachecreated, cachepurges, cachepeak, cachecount,
cachefreecount);
if (cachecreated - cachedeletes != cachecount) {
printf(" - Deleted %d\n",cachedeletes);
printf(" - Deleted %d\n", cachedeletes);
}
}
@@ -102,10 +105,10 @@ void cache_show(void)
/* cache_refcount() - compute reference count for cache subtree... */
int cache_refcount(struct CACHE *cacheobj)
{
int cache_refcount( struct CACHE *cacheobj ) {
register int refcount = 0;
if (cacheobj != NULL) {
if( cacheobj != NULL ) {
refcount = cacheobj->refcount;
if (cacheobj->left != NULL) {
refcount += cache_refcount(cacheobj->left);
@@ -134,7 +137,7 @@ static void cache_deleter( struct CACHE *cacheobj, struct CACHE **actualobj ) {
while (cacheobj->objmanager != NULL) {
register struct CACHE *proxyobj;
cachedeleteing = TRUE;
proxyobj = (*cacheobj->objmanager) (cacheobj,FALSE);
proxyobj = (*cacheobj->objmanager) (cacheobj, FALSE);
cachedeleteing = FALSE;
if( proxyobj == NULL ) {
if( actualobj != NULL )
@@ -145,12 +148,13 @@ static void cache_deleter( struct CACHE *cacheobj, struct CACHE **actualobj ) {
cacheobj = proxyobj;
}
#if DEBUG
if (cachedeleteing) printf("CACHE deletion while delete in progress\n");
if (cachedeleteing)
printf("CACHE deletion while delete in progress\n");
#endif
if (cacheobj->refcount != 0) {
#if DEBUG
printf("CACHE attempt to delete referenced object %d:%d\n",
cacheobj->objtype,cacheobj->hashval);
cacheobj->objtype, cacheobj->hashval);
#endif
abort();
if( actualobj != NULL )
@@ -206,20 +210,24 @@ static void cache_deleter( struct CACHE *cacheobj, struct CACHE **actualobj ) {
*actualobj = cacheobj;
free(cacheobj); /* This may be the supplied object, or it may have been replaced by a proxy. */
return;
return;
}
/************************************************************** cache_purge() */
/* cache_purge() - trim size of free list */
void cache_purge(int all)
{
void cache_purge( int all ) {
if (!cachedeleteing) {
register struct CACHE *cacheobj = lrulist.lastlru;
register struct CACHE *cacheobj;
cacheobj = lrulist.lastlru;
cachepurges++;
while ( (all || cachefreecount > CACHEGOAL) && cacheobj != &lrulist) {
register struct CACHE *lastobj = cacheobj->lastlru;
while( (all || cachefreecount > CACHEGOAL) && cacheobj != &lrulist ) {
register struct CACHE *lastobj;
lastobj = cacheobj->lastlru;
#if DEBUG
if (cacheobj->lastlru->nextlru != cacheobj ||
cacheobj->nextlru->lastlru != cacheobj ||
@@ -242,14 +250,16 @@ void cache_purge(int all)
/* cache_flush() - flush modified entries in cache */
void cache_flush(void)
{
register struct CACHE *cacheobj = lrulist.lastlru;
while (cacheobj != &lrulist) {
void cache_flush(void) {
register struct CACHE *cacheobj;
for( cacheobj = lrulist.lastlru;
cacheobj != &lrulist;
cacheobj = cacheobj->lastlru ) {
if (cacheobj->objmanager != NULL) {
(*cacheobj->objmanager) (cacheobj,TRUE);
(*cacheobj->objmanager) (cacheobj, TRUE);
}
cacheobj = cacheobj->lastlru;
}
}
@@ -257,11 +267,12 @@ void cache_flush(void)
/* cache_remove() - delete all possible objects from cache subtree */
void cache_remove(struct CACHE *cacheobj)
{
void cache_remove( struct CACHE *cacheobj ) {
if (cacheobj != NULL) {
if (cacheobj->left != NULL) cache_remove(cacheobj->left);
if (cacheobj->right != NULL) cache_remove(cacheobj->right);
if (cacheobj->left != NULL)
cache_remove(cacheobj->left);
if (cacheobj->right != NULL)
cache_remove(cacheobj->right);
if (cacheobj->refcount == 0) {
struct CACHE *delobj;
do {
@@ -275,8 +286,7 @@ void cache_remove(struct CACHE *cacheobj)
/* cache_touch() - to increase the access count on an object... */
void cache_touch(struct CACHE *cacheobj)
{
void cache_touch(struct CACHE *cacheobj) {
if (cacheobj->refcount++ == 0) {
#if DEBUG
if (cacheobj->nextlru == NULL || cacheobj->lastlru == NULL) {
@@ -294,19 +304,23 @@ void cache_touch(struct CACHE *cacheobj)
/************************************************************ cache_untouch() */
/* cache_untouch() - to deaccess an object... */
/* Deaccess an object.
* Recycle => TRUE puts object at front of LRU list, indicating that
* it's likely to be reused soon. Note that untouch() can
* trigger a purge, so the object can be deleted on return.
* This won't happen if recycle is TRUE because purge will maintain
* CACHEGOAL LRU entries, which must be non-zero.
*/
void cache_untouch(struct CACHE *cacheobj,int recycle)
{
if (cacheobj->refcount > 0) {
if (--cacheobj->refcount == 0) {
if (++cachefreecount >= CACHELIM) cache_purge(FALSE);
void cache_untouch( struct CACHE *cacheobj, int recycle ) {
if( cacheobj->refcount > 0 ) {
if( --cacheobj->refcount == 0 ) {
#if DEBUG
if (cacheobj->nextlru != NULL || cacheobj->lastlru != NULL) {
if( cacheobj->nextlru != NULL || cacheobj->lastlru != NULL ) {
printf("CACHE LRU pointers corrupt\n");
}
#endif
if (recycle) {
if( recycle ) {
cacheobj->nextlru = lrulist.nextlru;
cacheobj->lastlru = &lrulist;
cacheobj->nextlru->lastlru = cacheobj;
@@ -317,6 +331,8 @@ void cache_untouch(struct CACHE *cacheobj,int recycle)
cacheobj->lastlru->nextlru = cacheobj;
lrulist.lastlru = cacheobj;
}
if( ++cachefreecount >= CACHELIM )
cache_purge(FALSE);
}
} else {
#if DEBUG
@@ -329,43 +345,51 @@ void cache_untouch(struct CACHE *cacheobj,int recycle)
/*************************************************************** cache_find() */
/* cache_find() - 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! :-)
*
* This version will call a creation function to allocate and
* initialize an object if it is not found.
*/
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! :-)
This version will call a creation function to allocate and
initialize an object if it is not found.
*/
void *cache_find( void **root, unsigned hashval, void *keyval, unsigned *retsts,
int (*compare_func) ( unsigned hashval, void *keyval,
void *cache_find( void **root, uint32_t hashval, void *keyval, vmscond_t *retsts,
int (*compare_func) ( uint32_t hashval, void *keyval,
void *node ),
void *(*create_func) ( unsigned hashval, void *keyval,
unsigned *retsts ) ) {
void *(*create_func) ( uint32_t hashval, void *keyval,
vmscond_t *retsts ) ) {
register struct CACHE *cacheobj,**parent = (struct CACHE **) root;
register struct CACHE *cacheobj, **parent;
parent = (struct CACHE **) root;
cachefinds++;
while ((cacheobj = *parent) != NULL) {
register int cmp = hashval - cacheobj->hashval;
while( (cacheobj = *parent) != NULL ) {
register int cmp;
cmp = hashval - cacheobj->hashval;
#if DEBUG
if (cacheobj->parent != parent) {
printf("CACHE Parent pointer is corrupt\n");
}
#endif
if (cmp == 0 && compare_func != NULL) {
cmp = (*compare_func) (hashval,keyval,cacheobj);
cmp = (*compare_func) (hashval, keyval, cacheobj);
}
if (cmp == 0) {
cache_touch(cacheobj);
if (retsts != NULL) *retsts = SS$_NORMAL;
if (retsts != NULL)
*retsts = SS$_NORMAL;
return cacheobj;
}
if (cmp < 0) {
#ifdef IMBALANCE
register struct CACHE *left_path = cacheobj->left;
register struct CACHE *left_path;
left_path = cacheobj->left;
if (left_path != NULL && cacheobj->balance-- < -IMBALANCE) {
cacheobj->left = left_path->right;
if (cacheobj->left != NULL) {
@@ -380,7 +404,9 @@ void *cache_find( void **root, unsigned hashval, void *keyval, unsigned *retsts,
parent = &cacheobj->left;
}
} else {
register struct CACHE *right_path = cacheobj->right;
register struct CACHE *right_path;
right_path = cacheobj->right;
if (right_path != NULL && cacheobj->balance++ > IMBALANCE) {
cacheobj->right = right_path->left;
if (cacheobj->right != NULL) {
@@ -402,9 +428,10 @@ void *cache_find( void **root, unsigned hashval, void *keyval, unsigned *retsts,
}
}
if (create_func == NULL) {
if (retsts != NULL) *retsts = SS$_ITEMNOTFOUND;
if (retsts != NULL)
*retsts = SS$_ITEMNOTFOUND;
} else {
cacheobj = (*create_func) (hashval,keyval,retsts);
cacheobj = (*create_func) (hashval, keyval, retsts);
if (cacheobj != NULL) {
cacheobj->nextlru = NULL;
cacheobj->lastlru = NULL;
@@ -416,7 +443,8 @@ void *cache_find( void **root, unsigned hashval, void *keyval, unsigned *retsts,
cacheobj->balance = 0;
*parent = cacheobj;
cachecreated++;
if (cachecount++ >= cachepeak) cachepeak = cachecount;
if (cachecount++ >= cachepeak)
cachepeak = cachecount;
}
}
return cacheobj;

View File

@@ -1,14 +1,17 @@
/* Cache.h Definitions for cache 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _CACHE_H
#define _CACHE_H
@@ -19,21 +22,24 @@
#define signed signed
#endif
#include "ods2.h"
struct CACHE {
struct CACHE *nextlru; /* next object on least recently used list */
struct CACHE *lastlru; /* last object on least recently used list */
struct CACHE *left; /* left branch of binary tree */
struct CACHE *right; /* right branch of binary tree */
struct CACHE **parent; /* address of pointer to this object */
void *(*objmanager) (struct CACHE * cacheobj,int flushonly);
unsigned hashval; /* object hash value */
void *(*objmanager) ( struct CACHE * cacheobj, int flushonly );
uint32_t hashval; /* object hash value */
short refcount; /* object reference count */
signed char balance; /* object tree imbalance factor */
signed char objtype; /* object type (for debugging) */
#define OBJTYPE_DEV 1
#define OBJTYPE_FCB 2
#define OBJTYPE_WCB 3
#define OBJTYPE_DEV 1
#define OBJTYPE_FCB 2
#define OBJTYPE_WCB 3
#define OBJTYPE_VIOC 7
#define OBJTYPE_DIR 8
};
void cache_show(void);
@@ -44,10 +50,10 @@ void cache_flush(void);
void cache_remove(struct CACHE *cacheobj);
void cache_touch(struct CACHE * cacheobj);
void cache_untouch(struct CACHE * cacheobj,int recycle);
void *cache_find( void **root, unsigned hashval, void *keyval, unsigned *retsts,
int (*compare_func) ( unsigned hashval, void *keyval,
void *cache_find( void **root, uint32_t hashval, void *keyval, vmscond_t *retsts,
int (*compare_func) ( uint32_t hashval, void *keyval,
void *node ),
void *(*create_func) ( unsigned hashval, void *keyval,
unsigned *retsts ) );
void *(*create_func) ( uint32_t hashval, void *keyval,
vmscond_t *retsts ) );
#endif /* #ifndef _CACHE_H */

View File

@@ -2,21 +2,31 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _CMDDEF_H
#define _CMDDEF_H
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -38,11 +48,10 @@
#include "sysmsg.h"
#define MAXREC 32767
#define PRINT_ATTR ( FAB$M_CR | FAB$M_PRN | FAB$M_FTN )
#define DT_NAME "drive_type"
#define DT_NAME "medium_type"
#define DECL_CMD(x) unsigned do ## x(int argc,char **argv,int qualc,char **qualv)
#define DECL_CMD(x) vmscond_t do ## x(int argc,char **argv,int qualc,char **qualv)
typedef struct CMDSET CMDSET_t;
typedef struct param param_t;
@@ -52,11 +61,13 @@ typedef CMDSET_t *CMDSETp_t;
typedef param_t *paramp_t;
typedef qual_t *qualp_t;
typedef vmscond_t (*cmdproc_t) (int argc,char *argv[],int qualc,char *qualv[]);
/* Command table entry */
struct CMDSET {
char *name;
unsigned (*proc) (int argc,char *argv[],int qualc,char *qualv[]);
cmdproc_t proc;
int uniq;
qualp_t validquals;
paramp_t params;
@@ -64,45 +75,132 @@ struct CMDSET {
};
/* set, clear: bits specified are cleared, then set in value
* qtype = qualifier's value type. + => value required, - optional, 0 none
* Following macros simplify setting up the tables.
* helpstr: if null, switch not listed in help. If starts with -,
* listed as negatable in help
* listed as negatable in help. If null string (""), listed
* as value table. Otherwise, .hlp file lookup key.
*/
#define NV NOVAL, NULL
#define KV(list) KEYVAL, list
#define CV(list) KEYCOL, list
#define DV(val) DECVAL, val
#define SV(val) STRVAL, ((void *)val)
#define PV(val) PROT, ((void *)val)
#define UV(val) UIC, ((void *)val)
/* Use VOPT(XX()) for optional value */
#define VOPT(def) -def
struct qual {
const char *name;
int set;
int clear;
enum qualtype { NOVAL, KEYVAL, KEYCOL, DECVAL, STRVAL } qtype;
options_t set;
options_t clear;
enum qualtype { opt_optional = -1, NOVAL = 0, /* enum must be signed */
KEYVAL, KEYCOL, DECVAL, STRVAL, PROT, UIC } qtype;
void *arg;
const char *helpstr;
char *helpstr;
};
typedef const char *(hlpfunc_t)( CMDSET_t *cmd, param_t *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;
enum parflags { REQ = 1, OPT = 2, CND = 4, NOLIM = 8 } flags;
enum partype { NONE = 0, FSPEC, LIST, KEYWD, QUALS, STRING } ptype;
#define PA(arg) NULL, (arg)
#define NOPA PA(NULL)
hlpfunc_t *hlpfnc;
void *arg;
const char *helpstr;
char *helpstr;
};
extern int vms_qual;
/* Default qualifer sets */
struct defquals {
struct defquals *next;
int qualc;
char **qualv;
char *data[1];
};
typedef struct defquals defquals_t;
typedef defquals_t *defqualsp_t;
extern const char *qstyle_s;
#define qstyle_c (qstyle_s[0])
extern int verify_cmd;
extern int error_exit;
vmscond_t parselist( int *nret, char ***items, size_t min, char *arg );
vmscond_t checkquals( options_t *result, options_t defval,
qualp_t qualset, int qualc,char **qualv );
int parselist( char ***items, size_t min, char *arg, const char *label );
int checkquals( int result, qual_t qualset[],int qualc,char *qualv[] );
int keycomp(const char *param, const char *keywrd);
char *fgetline( FILE *stream, int keepnl );
vmscond_t confirm_cmd( vmscond_t status, ... );
int prvmstime(VMSTIME vtime, const char *sfx);
void pwrap( int *pos, const char *fmt, ... );
vmscond_t sethelpfile( char *filename, char *env, char *pname );
vmscond_t showhelpfile( void );
vmscond_t helptopic( options_t options, char *topic, ... );
#define HLP_OPTIONAL 0x00000001
#define HLP_WRAP 0x00000002
#define HLP_RELOAD 0x00000004
#define HLP_ABBREV 0x00000008
typedef struct pause {
size_t interval;
size_t lineno;
vmscond_t prompt;
} pause_t;
vmscond_t put_c( int c, FILE *outf, pause_t *pause );
vmscond_t put_str( const char *buf, FILE *outf, pause_t *pause );
vmscond_t put_strn( const char *buf, size_t len, FILE *outf, pause_t *pause );
void termchar( int *width, int *height );
vmscond_t prvmstime(FILE *of, VMSTIME vtime, const char *sfx);
void pwrap( FILE *of, int *pos, const char *fmt, ... );
#ifdef HELPFILEDEFS
/* File and index structures private to helpcmd and makehelp. */
/* Helpfile magic cookie, version & header */
#define HLP_MAGIC "ODS2HLP"
#define HLP_VERSION 1
typedef struct hlphdr {
char magic[ sizeof(HLP_MAGIC) ];
uint32_t version;
uint32_t psize, ssize, tsize;
time_t ddate;
size_t size;
} hlphdr_t;
/* In-memory pointer / file offsets */
typedef union ptr {
void *ptr;
ptrdiff_t ofs;
} ptr_t;
/* Help tree topic nodes (including root) */
typedef struct hlproot {
ptr_t topics; /*struct hlptopic * */
size_t ntopics;
} hlproot_t;
/* Help topic data under each node */
typedef struct hlptopic {
ptr_t key; /* char * */
ptr_t text; /* char * */
hlproot_t subtopics;
uint32_t keylen;
} hlptopic_t;
#endif /* HELPFILEDEFS */
#endif

View File

@@ -12,7 +12,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* This module contains compatibility code, currently just
@@ -35,6 +38,7 @@
#endif
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -48,6 +52,7 @@
#else
#ifdef _WIN32
#include <windows.h>
#include <shlwapi.h> /* PathSearchAndQualify() */
#else
#include <unistd.h>
#include <sys/types.h>
@@ -119,21 +124,20 @@ const char *ods2_strerror( int errn ) {
TCHAR *w32_errstr( DWORD eno, ... ) {
va_list ap;
TCHAR *msg;
TCHAR *msg = NULL;
if( eno == NO_ERROR )
eno = GetLastError();
va_start(ap,eno);
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 );
msg = (TCHAR *)malloc( 64 );
if( msg == NULL ) {
perror( "malloc" );
printf( "Original error number (%u)\n", eno );
printf( "Out of memory reporting Windows error(%u\n", eno );
} else
(void) snprintf( msg, 32, "(%u)", eno );
(void) snprintf( msg, 64, "(%u)", eno );
}
va_end(ap);
return msg;
@@ -143,7 +147,7 @@ TCHAR *w32_errstr( DWORD eno, ... ) {
char *driveFromLetter( const char *letter ) {
DWORD rv = ERROR_INSUFFICIENT_BUFFER;
size_t cs = 16;
DWORD cs = 16;
TCHAR *bufp = NULL;
do {
@@ -180,7 +184,7 @@ char *get_env( const char *name ) {
return NULL;
if ((r = malloc( i )) == NULL )
return NULL;
(void)getenv_s( &i, r, i, "USERNAME" );
(void)getenv_s( &i, r, i, name );
return r;
#else
char *t;
@@ -207,10 +211,12 @@ char *get_username( void ) {
size_t i;
#ifdef VMS
char uame[12 + 1] = "UNKNOWN ";
struct dsc$descriptor_s userdsc = { sizeof( uname ) - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, uname };
struct dsc$descriptor_s userdsc = { sizeof( uname ) - 1,
DSC$K_DTYPE_T,
DSC$K_CLASS_S, uname };
r = "UNKNOWN";
if( lib$getjpi( &JPI$_USERNAME, 0, 0, 0, &userdsc, 0 ) & STS$M_SUCCESS ) {
if( $SUCCESSFUL(lib$getjpi( &JPI$_USERNAME, 0, 0, 0, &userdsc, 0 )) ) {
for( i = sizeof( uname ) - 1; i >= 0; i-- ) {
if( uname[i] == ' ' )
uname[i] = '\0';
@@ -251,3 +257,194 @@ char *get_username( void ) {
memcpy( username, r, i + 1 );
return username;
}
/******************************************************************* homefile () */
char *homefile( int dotfile, const char *filename, const char *ext ) {
char * prefix, *delim, *name;
size_t pfxlen, dellen, namlen, extlen;
#ifdef _WIN32
char *drive;
prefix = drive = get_env( "HOMEDRIVE" );
if( drive != NULL ) {
prefix = get_env( "HOMEPATH" );
if( prefix != NULL ) {
dellen = strlen( drive );
pfxlen = strlen( prefix );
if( (name = malloc( dellen + pfxlen + 1 )) == NULL ) {
free( prefix );
free( drive );
return NULL;
}
memcpy( name, drive, dellen );
memcpy( name+dellen, prefix, pfxlen +1 );
free( prefix );
prefix = name;
}
free( drive );
}
delim = dotfile? "\\.": "\\";
#elif defined( VMS )
prefix = get_env( "SYS$LOGIN" );
delim = dotfile? "_": "";
#else
prefix = get_env( "HOME" );
delim = dotfile? "/." : "/";
#endif
pfxlen = prefix? strlen( prefix ) : 0;
dellen = strlen( delim );
namlen = strlen( filename );
extlen = ext? strlen( ext ) : 0;
if( (name = malloc( pfxlen+dellen+namlen+extlen+1)) == NULL )
return NULL;
/* N.B. There is no buffer overrun here */
if( pfxlen )
memcpy( name, prefix, pfxlen );
memcpy( name+pfxlen, delim, dellen );
memcpy( name+pfxlen+dellen, filename, namlen+1 );
if( ext )
memcpy( name+pfxlen+dellen+namlen, ext, extlen+1 );
free( prefix );
return name;
}
/************************************************************* get_realpath() */
char *get_realpath( const char *filnam ) {
#ifdef _WIN32
size_t n;
char *path, resultant_path[MAX_PATH];
if ( filnam == NULL || strpbrk( filnam, "*?" ) != NULL ||
!PathSearchAndQualify( filnam, /* pcszPath */
resultant_path, /* pszFullyQualifiedPath */
/* cchFullyQualifiedPath */
sizeof( resultant_path )
) ) {
return NULL;
}
n = strlen( resultant_path );
path = (char *) malloc( n + 1 );
if ( path != NULL ) {
memcpy( path, resultant_path, n + 1 );
}
return path;
#elif defined VMS
#define MAXPATH 255
size_t n;
unsigned short resultant_path[1 + ( ( MAXPATH + 1 ) / 2)];
char *path;
unsigned long context, sts, flags;
struct dsc$descriptor filespec = {
0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL
};
struct dsc$descriptor resultant_filespec = {
MAXPATH, DSC$K_DTYPE_T, DSC$K_CLASS_VS, (char *) resultant_path
};
path = NULL;
if ( filnam != NULL ) {
filespec.dsc$w_length = strlen( filnam );
filespec.dsc$a_pointer = (char *) filnam;
*resultant_path = 0;
context = 0;
flags = LIB$M_FIL_NOWILD;
sts = lib$find_file( &filespec, &resultant_filespec, &context,
NULL, NULL, &sts, &flags );
lib$find_file_end( &context );
if( $SUCCESSFUL(sts) ) {
n = *resultant_path;
path = (char *) malloc( n + 1 );
if ( path != NULL ) {
memcpy( path, resultant_path + 1, n );
path[n] = '\0';
}
}
}
return path;
#elif defined unix || 1
size_t n;
char *path, resolved_path[PATH_MAX+1];
if ( filnam == NULL || realpath( filnam, resolved_path ) == NULL ) {
return NULL;
}
n = strlen( resolved_path );
path = (char *) malloc( n + 1 );
if ( path != NULL ) {
memcpy( path, resolved_path, n + 1 );
}
return path;
#endif
}
/******************************************************************** Ctime() */
char *Ctime( time_t *tval ) {
char *buf;
#ifdef _WIN32
if( (buf = malloc( 26 )) == NULL ) return NULL;
if( ctime_s( buf, 26, tval ) != 0 ) {
free( buf );
return NULL;
}
#else
char *cbuf;
if( (buf = malloc( 25 )) == NULL ) return NULL;
if( (cbuf = ctime( tval )) == NULL ) {
free( buf );
return NULL;
}
memcpy( buf, cbuf, 24 );
#endif
buf[24] = '\0';
return buf;
}
/******************************************************************* fgetline() */
/* Read a line of input - unlimited length
* Removes \n, returns NULL at EOF
* If *buf is NULL, one is allocated of size *bufsize.
* Thereafter, it is reused. Expanded if necessary.
* Caller responsible for free()
*/
char *fgetline( FILE *stream, int keepnl, char **buf, size_t *bufsize ) {
int c;
size_t idx = 0;
if( *buf == NULL && (*buf = malloc( *bufsize )) == NULL ) {
perror( "malloc" );
exit(EXIT_FAILURE);
}
while( (c = getc( stream )) != EOF && c != '\n' ) {
if( idx + (keepnl != 0) +2 > *bufsize ) { /* Now + char + (? \n) + \0 */
char *nbuf;
*bufsize += 32;
nbuf = (char *) realloc( *buf, *bufsize );
if( nbuf == NULL ) {
perror( "realloc" );
exit(EXIT_FAILURE);
}
*buf = nbuf;
}
buf[0][idx++] = c;
}
if( c == '\n' ) {
if( keepnl )
buf[0][idx++] = '\n';
} else {
if( c == EOF && idx == 0 ) {
buf[0][0] = '\0';
return NULL;
}
}
buf[0][idx] = '\0';
return *buf;
}

View File

@@ -12,19 +12,22 @@
* 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 contributions of the original author and
* subsequent contributors.
*/
#ifndef COMPAT_H
#define COMPAT_H
#include <stdio.h>
#include <time.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
#include <stdarg.h>
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
int c99_snprintf(char *outBuf, size_t size, const char *format, ...);
@@ -43,7 +46,7 @@ FILE *openf( const char *filename, const char *mode );
#include <windows.h>
#include <direct.h>
#undef getcwd
#define getcwd _getcwd
#define getcwd(_buf,_siz) _getcwd((_buf), (int)(_siz))
#undef chdir
#define chdir _chdir
#undef tzset
@@ -52,8 +55,15 @@ FILE *openf( const char *filename, const char *mode );
#define setenv(name, value, overwrite) _putenv_s(name, value)
#undef unsetenv
#define unsetenv(name) _putenv_s(name,"")
#undef unlink
#define unlink _unlink
#define Unlink _unlink
#define Fileno(x) _fileno(x)
#include <io.h>
#include <sys/stat.h>
#define Chmod _chmod
#ifndef S_IREAD
#define S_IREAD _S_IREAD
#define S_IWRITE _S_IWRITE
#endif
#undef strerror
#define strerror(n) ods2_strerror(n)
@@ -64,10 +74,17 @@ char *driveFromLetter( const char *letter );
#else /* Not WIN32 */
#include <unistd.h>
#define Unlink unlink
#define Fileno(x) fileno(x)
#define Chmod chmod
#endif
char *get_username( void );
char *get_env( const char *name );
char *homefile( int dotfile, const char *filename, const char *ext );
char *get_realpath( const char *filnam );
char *Ctime( time_t *tval );
char *fgetline( FILE *stream, int keepnl, char **buf, size_t *bufsize );
#define UNUSED(x) (void)(x)

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_CREATECMD )
@@ -17,36 +20,654 @@
#include "cmddef.h"
#include "f11def.h"
static vmscond_t create_directory( options_t options, int argc, char** argv );
static vmscond_t create_file( options_t options, int argc, char** argv );
/******************************************************************* dotest() */
param_t createpars[] = { {"parameter", REQ, STRING, NOPA, "for create."},
{ NULL, 0, 0, NOPA, NULL }
/******************************************************************* docreate() */
#define create_log OPT_GENERIC_1
#define create_dir OPT_GENERIC_2
#define create_owner OPT_GENERIC_3
#define create_protect OPT_GENERIC_4
#define create_volume OPT_GENERIC_5
#define create_verlim OPT_GENERIC_6
#define create_recfmt (OPT_GENERIC_10|OPT_GENERIC_9|OPT_GENERIC_8)
#define create_v_recfmt (OPT_V_GENERIC + 7)
#define create_b4 (OPT_SHARED_2|OPT_SHARED_1)
#define create_v_b4 0
#define create_after (OPT_SHARED_4|OPT_SHARED_3)
#define create_v_after 2
#define create_prn_none 0
#define create_prn_nl 1
#define create_prn_c0 2
#define create_prn_vfu 3
#define create_prn OPT_SHARED_17
#define create_ftn OPT_SHARED_18
#define create_cr OPT_SHARED_19
#define create_span OPT_SHARED_20
static uint32_t b4n, aftn;
static uint32_t vfclen;
static uint32_t reclen;
static uint32_t verlimit;
static uint32_t volume;
static uint32_t protection;
static uint32_t ownuic;
static qual_t
prnb4[] = { {"none", create_prn_none << create_v_b4,
create_b4, NV, "commands create qual_cc print b4 none"},
{"nl", create_prn_nl << create_v_b4,
create_b4, DV(&b4n), "commands create qual_cc print b4 nl"},
{"ctl", create_prn_c0, create_b4, DV(&b4n), "commands create qual_cc print b4 ctl"},
{"vfu", create_prn_vfu << create_v_b4,
create_b4, DV(&b4n), "commands create qual_cc print b4 vfu"},
{NULL, 0, 0, NV, NULL}
};
static qual_t
prnafter[] = { {"none", create_prn_none << create_v_after,
create_after, NV, "commands create qual_cc print b4 none"},
{"nl", create_prn_nl << create_v_after,
create_after, DV(&aftn), "commands create qual_cc print b4 nl"},
{"ctl", create_prn_c0, create_b4, DV(&aftn), "commands create qual_cc print b4 ctl"},
{"vfu", create_prn_vfu << create_v_after,
create_after, DV(&aftn), "commands create qual_cc print b4 vfu"},
{NULL, 0, 0, NV, NULL}
};
#if 0
extern struct VCB *test_vcb;
#endif
static qual_t
prnkwds[] = { {"before", 0, create_b4, KV(prnb4), "commands create qual_cc print b4"},
{"after", 0, create_after, KV(prnafter), "commands create qual_cc print after"},
/* docreate: you don't want to know! */
{NULL, OPT_NOSORT, 0, NV, NULL}
};
static qual_t
cckwds[] = { {"fortran", create_ftn, create_cr|create_prn, NV,
"commands create qual_cc fortran"},
{"carriage_return", create_cr, create_ftn|create_prn, NV,
"commands create qual_cc cr"},
{"print", create_prn|(FAB$C_VFC<<create_v_recfmt),
create_ftn|create_cr|create_recfmt, KV(prnkwds),
"commands create qual_cc print"},
{"none", 0, create_ftn|create_cr|create_prn, NV,
"commands create qual_cc none"},
{NULL, 0, 0, NV, NULL}
};
static qual_t
fmtkwds[] = { {"fixed", (FAB$C_FIX +1) << create_v_recfmt,
create_recfmt, DV(&reclen),
"commands create qual_recfmt fixed"},
{"variable", (FAB$C_VAR +1) << create_v_recfmt,
create_recfmt, NV,
"commands create qual_recfmt variable"},
{"vfc", (FAB$C_VFC +1) << create_v_recfmt,
create_recfmt, VOPT(DV(&vfclen)),
"commands create qual_recfmt vfc"},
{"stream", (FAB$C_STM +1) << create_v_recfmt,
create_recfmt, NV,
"commands create qual_recfmt stream"},
{"streamlf", (FAB$C_STMLF +1) << create_v_recfmt,
create_recfmt, NV,
"commands create qual_recfmt streamlf"},
{"streamcr", (FAB$C_STMCR +1) << create_v_recfmt,
create_recfmt, NV,
"commands create qual_recfmt streamcr"},
{"undefined", (FAB$C_UDF +1) << create_v_recfmt,
create_recfmt, NV,
"commands create qual_recfmt undefined"},
{NULL, 0, 0, NV, NULL}
};
qual_t
createquals[] = { {"log", create_log, 0, NV,
"-commands create qual_log"},
{"nolog", 0, create_log, NV, NULL },
{"directory", create_dir, 0, NV,
"commands create qual_directory"},
{"version_limit", create_verlim, 0, DV(&verlimit),
"commands create qual_verlim"},
#if 0
{"volume", create_volume, 0, DV(&volume),
"commands create qual_volume"},
#endif
{"owner_uic", create_owner, 0, UV(&ownuic),
"commands create qual_owner" },
{"protection", create_protect, 0, PV(&protection),
"commands create qual_protection"},
{"record_format", 0, 0, KV(fmtkwds),
"commands create qual_recfmt"},
{"carriage_control", 0, 0, KV(cckwds),
"commands create qual_cc"},
{"span", create_span, 0, NV, "commands create qual_span"},
{"nospan", 0, create_span,NV, NULL},
{ NULL, 0, 0, NV, NULL }
};
param_t
createpars[] = { {"parameter", REQ, STRING, NOPA, "commands create filespec"},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(create) {
unsigned sts = 0;
struct fiddef fid;
vmscond_t sts;
options_t options;
vfclen = 0;
reclen = 0;
if( $FAILS(sts = checkquals( &options, create_span, createquals, qualc, qualv )) ) {
return sts;
}
if( options & create_dir )
return create_directory( options, argc, argv );
return create_file( options, argc, argv );
}
/******************************************************************* create_directory() */
static vmscond_t create_directory( options_t options, int argc, char **argv ) {
vmscond_t sts;
char tdir[NAM$C_MAXRSS+1],
rsname[NAM$C_MAXRSS+1];
struct FAB fab = cc$rms_fab;
struct NAM nam = cc$rms_nam;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
#if 0 /* Needs to call RMS, etc */
sts = update_create( test_vcb, NULL, "Test.File", &fid, NULL );
#else
memset( &fid, 0, sizeof( struct fiddef ) );
#endif
printf( "Create status of %d (%s)\n", sts, argv[1] );
do {
int level;
char newdir[NAM$C_MAXRSS + 1], *p;
uint8_t newlen, devlen, newdirlen, tmplen, sfdlen;
struct XABPRO parpro;
struct XABFHC parfhc;
parpro = cc$rms_xabpro;
parfhc = cc$rms_xabfhc;
nam.nam$b_ess = sizeof( newdir ) -1;
nam.nam$l_esa = newdir;
nam.nam$b_rss = sizeof( rsname ) -1;
nam.nam$l_rsa = rsname;
fab.fab$l_nam = &nam;
fab.fab$b_fac = 0;
fab.fab$l_fop = FAB$M_OFP;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna);
/* Check syntax & see if specified directory exists */
sts = sys_parse( &fab );
tdir[nam.nam$b_rsl] = '\0';
newdir[nam.nam$b_esl] = '\0';
devlen = nam.nam$b_dev;
newdirlen = nam.nam$b_dir;
newlen = devlen + newdirlen;
if( $SUCCESSFUL(sts) &&
!(nam.nam$l_fnb & (NAM$M_EXP_NAME | NAM$M_EXP_TYPE |
NAM$M_EXP_VER | NAM$M_WILDCARD)) ) {
rsname[newlen] = '\0';
sts = printmsg( CREATE_EXISTS, 0, rsname );
break;
}
if( $FAILED(sts) && !$MATCHCOND(sts, RMS$_DNF) ) {
sts = printmsg( sts, 0 );
break;
}
if( nam.nam$l_fnb & (NAM$M_EXP_NAME | NAM$M_EXP_TYPE |
NAM$M_EXP_VER | NAM$M_WILDCARD) ) {
sts = printmsg( RMS$_DIR, 0 );
break;
}
/* Scan from MFD down to apply defaults and fill in missing
* SFDs.
*/
p = newdir+devlen+1;
memcpy( tdir, newdir, devlen );
memcpy( tdir+devlen, "[000000]000000.DIR;1",
sizeof( "[000000]000000.DIR;1" ) -1 );
tmplen = sizeof( "[000000]" ) -1;
sfdlen = sizeof( "000000" ) -1;
level = 0;
fab.fab$b_fns =
nam.nam$b_ess =
fab.fab$b_dns = 0;
nam.nam$l_rlf = NULL;
nam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &fab ); /* Release context */
fab.fab$l_nam = NULL;
fab.fab$l_fna = tdir;
sts = SS$_NORMAL;
while( TRUE ) {
uint32_t directory;
uint16_t retlen;
struct XABFHC fhc;
struct XABPRO pro;
struct XABITM itm;
struct item_list xitems[] = {
{ XAB$_UCHAR_DIRECTORY, sizeof(int), NULL, 0 },
{ 0, 0, NULL, 0 }
};
fhc = cc$rms_xabfhc;
pro = cc$rms_xabpro;
itm = cc$rms_xabitm;
itm.xab$l_nxt = &fhc;
xitems[0].buffer = &directory; xitems[0].retlen = &retlen;
itm.xab$b_mode = XAB$K_SENSEMODE;
itm.xab$l_itemlist = xitems;
pro.xab$l_nxt = &itm;
fab.fab$l_xab = &pro;
fab.fab$b_fns = devlen+tmplen+sfdlen+6;
tdir[fab.fab$b_fns] = '\0';
if( $SUCCESSFUL(sys_open(&fab)) ) {
fab.fab$l_xab = NULL;
sys_close( &fab );
if( !directory ) {
sts = printmsg( CREATE_NOTDIR, 0, tdir );
break;
}
parpro = pro;
parfhc = fhc;
} else {
struct FAB nfab = cc$rms_fab;
struct NAM nam = cc$rms_nam;
struct XABALL all = cc$rms_xaball;
all.xab$l_alq = 1;
if( options & create_volume )
all.xab$w_vol = (uint16_t)volume;
fhc = parfhc;
if( options & create_verlim )
fhc.xab$w_verlimit = verlimit;
fhc.xab$l_nxt = &all;
pro = parpro;
pro.xab$w_pro |= ( ((xab$m_nodel) << xab$v_system) |
((xab$m_nodel) << xab$v_owner) |
((xab$m_nodel) << xab$v_group) |
((xab$m_nodel) << xab$v_world) );
if( options & create_protect ) {
pro.xab$w_pro = (uint16_t)
((pro.xab$w_pro & ~(protection >> 16)) |
(uint16_t)protection);
}
if( options & create_owner ) {
pro.xab$l_uic = ownuic;
}
itm.xab$l_nxt = &fhc;
directory = 1;
itm.xab$b_mode = XAB$K_SETMODE;
pro.xab$l_nxt = &itm;
nfab.fab$l_xab = &pro;
nam.nam$b_rss = sizeof( rsname ) -1;
nam.nam$l_rsa = rsname;
nfab.fab$l_nam = &nam;
nfab.fab$b_fac = 0;
nfab.fab$l_fop = FAB$M_OFP;
nfab.fab$b_org = FAB$C_SEQ;
nfab.fab$b_rat = FAB$M_BLK;
nfab.fab$b_rfm = FAB$C_VAR;
fhc.xab$w_lrl =
nfab.fab$w_mrs = 512;
nfab.fab$b_fns = fab.fab$b_fns;
nfab.fab$l_fna = fab.fab$l_fna;
sts = sys_create( &nfab );
rsname[nam.nam$b_rsl] = '\0';
if( $FAILED(sts) ) {
printmsg( CREATE_CREDIRFAIL, 0, rsname );
sts = printmsg( sts, MSG_CONTINUE, CREATE_CREDIRFAIL );
} else {
if( $FAILS(sts = sys_close(&nfab)) ) {
printmsg(CREATE_CLOSEOUT, 0, rsname);
sts = printmsg(sts, MSG_CONTINUE, CREATE_CLOSEOUT);
}
}
nfab.fab$b_fns =
nam.nam$b_ess = 0;
nfab.fab$b_dns = 0;
nam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &nfab );
if( $FAILED(sts) )
break;
if( options & create_log )
sts = printmsg( CREATE_CREATED, 0, rsname );
}
if( *p == ']' )
break;
switch( level++ ) {
case 0:
break;
case 1:
memmove( tdir+devlen+1, tdir+devlen+tmplen, sfdlen );
tmplen = 1+ sfdlen +1;
tdir[devlen+tmplen-1] = ']';
break;
default:
tdir[devlen+tmplen -1] = '.';
tmplen += 1 + sfdlen;
tdir[devlen+tmplen -1] = ']';
break;
}
for( sfdlen = 0; *p != '.' && *p != ']'; sfdlen++ )
tdir[devlen+tmplen+sfdlen] = *p++;
memcpy( tdir+devlen+tmplen+sfdlen, ".DIR;1", 6 );
if( *p == '.' )
++p;
}
} while( 0 );
if( nam.nam$l_fnb & (NAM$M_EXP_NAME | NAM$M_EXP_TYPE |
NAM$M_EXP_VER | NAM$M_WILDCARD) ) {
sts = printmsg( RMS$_DIR, 0 );
}
fab.fab$b_fns =
nam.nam$b_ess =
fab.fab$b_dns = 0;
nam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &fab );
return sts;
}
/******************************************************************* create_file() */
static vmscond_t create_file( options_t options, int argc, char** argv ) {
vmscond_t sts;
char *buf = NULL;
size_t bufsize = 80;
char vfc[2], rsbuf[NAM$C_MAXRSS + 1];
struct NAM nam;
struct FAB fab;
struct RAB rab;
struct XABPRO pro;
UNUSED( argc );
nam = cc$rms_nam;
fab = cc$rms_fab;
rab = cc$rms_rab;
pro = cc$rms_xabpro;
nam.nam$l_esa = NULL;
nam.nam$b_ess = 0;
nam.nam$b_rss = sizeof( rsbuf ) -1;
nam.nam$l_rsa = rsbuf;
if( options & (create_protect|create_owner) ) {
fab.fab$l_xab = &pro;
if( options & create_protect ) {
pro.xab$w_pro = (uint16_t)
((pro.xab$w_pro & ~(protection >> 16)) |
(uint16_t)protection);
}
if( options & create_owner ) {
pro.xab$l_uic = ownuic;
}
}
fab.fab$l_nam = &nam;
fab.fab$b_fac = FAB$M_PUT;
fab.fab$l_fop = FAB$M_OFP | FAB$M_TEF;
fab.fab$b_org = FAB$C_SEQ;
if( !(options & create_recfmt) ) {
options |= (FAB$C_VAR +1) << create_v_recfmt;
if( !(options & (create_prn|create_ftn|create_cr)) )
options |= create_cr;
}
fab.fab$b_rfm = ((options & create_recfmt) >> create_v_recfmt) -1;
switch( fab.fab$b_rfm ) {
case FAB$C_STM:
case FAB$C_STMLF:
case FAB$C_STMCR:
fab.fab$b_rat |= FAB$M_CR;
break;
case FAB$C_VFC:
fab.fab$b_fsz = vfclen;
break;
}
if( !(options & create_span) )
fab.fab$b_rat |= FAB$M_BLK;
if( options & create_ftn )
fab.fab$b_rat |= FAB$M_FTN;
if( options & create_cr )
fab.fab$b_rat |= FAB$M_CR;
if( options & create_prn ) {
fab.fab$b_rat |= FAB$M_PRN;
fab.fab$b_fsz = 2;
fab.fab$b_rfm = FAB$C_VFC;
switch( (options & create_b4) >> create_v_b4 ) {
case create_prn_none:
vfc[0] = 0;
break;
case create_prn_nl:
if( b4n < 1 || b4n > 127 )
return printmsg( CREATE_INVALIDNL, 0 );
vfc[0] = b4n & 0x7f;
break;
case create_prn_c0:
if( b4n > 31 )
return printmsg( CREATE_INVALIDC0, 0 );
vfc[0] = 0x80 | b4n;
break;
case create_prn_vfu:
if( b4n < 1 || b4n > 16 )
return printmsg( CREATE_INVALIDVFU, 0 );
vfc[0] = (0xC0 | (b4n -1)) & 0xff;
}
switch( (options & create_after) >> create_v_after ) {
case create_prn_none:
vfc[1] = 0;
break;
case create_prn_nl:
if( aftn < 1 || aftn > 127 )
return printmsg( CREATE_INVALIDNL, 0 );
vfc[1] = aftn & 0x7f;
break;
case create_prn_c0:
if( aftn > 31 )
return printmsg( CREATE_INVALIDC0, 0 );
vfc[1] = 0x80 | aftn;
break;
case create_prn_vfu:
if( aftn < 1 || aftn > 16 )
return printmsg( CREATE_INVALIDVFU, 0 );
vfc[1] = (0xC0 | (aftn -1)) & 0xff;
}
} /* prn */
/*
fab.fab$w_deq = 5;
fab.fab$l_alq = 100;
*/
fab.fab$w_mrs = (uint16_t)reclen;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna);
do {
char *input;
sts = sys_create( &fab );
rsbuf[nam.nam$b_rsl] = '\0';
if( $FAILED(sts) )
break;
rab.rab$l_fab = &fab;
if( $FAILS(sts = sys_connect( &rab )) )
break;
if( options & create_prn )
rab.rab$l_rhb = vfc;
if( options & create_log ) {
printmsg( CREATE_READY, 0, rsbuf );
printmsg( CREATE_TERMEOF, MSG_CONTINUE, CREATE_READY,
#if defined( VMS ) || defined( _WIN32 )
"Control-Z"
#ifdef _WIN32
" Enter"
#endif
#else
"Control-D"
#endif
);
}
while( (input = fgetline( stdin, FALSE, &buf, &bufsize )) != NULL ) {
size_t len;
len = strlen( input );
sts = SS$_NORMAL;
#if 0
if( len && input[len -1] == '\r' )
len--;
#endif
rab.rab$l_rbf = input;
switch( fab.fab$b_rfm ) {
case FAB$C_FIX:
if( len > (size_t)fab.fab$w_mrs )
len = fab.fab$w_mrs;
else if( len < (size_t)fab.fab$w_mrs ) {
char *p = input;
if( bufsize < fab.fab$w_mrs ) {
p = realloc( buf, fab.fab$w_mrs );
if( p == NULL ) {
sts = SS$_INSFMEM;
break;
}
bufsize = fab.fab$w_mrs;
rab.rab$l_rbf =
buf =
input = p;
}
p += len;
len = fab.fab$w_mrs - len;
while( len-- )
*p++ = ' ';
len = fab.fab$w_mrs;
}
break;
case FAB$C_VFC:
if( !(options & create_prn) ) {
if( len < fab.fab$b_fsz ) {
sts = RMS$_RFM;
break;
}
rab.rab$l_rhb = input;
rab.rab$l_rbf = input + fab.fab$b_fsz;
len -= fab.fab$b_fsz;
}
break;
}
if( $SUCCESSFUL(sts) ) {
rab.rab$w_rsz = (uint16_t)len;
sts = sys_put(&rab);
}
if( $FAILED(sts) )
break;
}
break;
} while( 0 );
if( buf != NULL ) free( buf );
if( $FAILED(sts) ) {
vmscond_t rsts;
int err;
err = errno;
rsts = printmsg( sts, 0, nam.nam$b_rsl? rsbuf: argv[1] );
if( err )
printmsg( ODS2_OSERROR, MSG_CONTINUE, sts, strerror( err ) );
sts = rsts;
}
sys_disconnect( &rab );
if( $SUCCESSFUL( sts ) ) {
if( $FAILS(sts = sys_close( &fab )) ) {
vmscond_t rsts;
int err;
err = errno;
rsts = printmsg( CREATE_CLOSEOUT, 0,
nam.nam$b_rsl? rsbuf: argv[1] );
printmsg( sts, MSG_CONTINUE, rsts, nam.nam$b_rsl? rsbuf: argv[1] );
if( err )
printmsg( ODS2_OSERROR, MSG_CONTINUE, sts, strerror( err ) );
sts = rsts;
}
} else {
sys_close( &fab );
}
if( $SUCCESSFUL( sts ) && (options & create_log) )
sts = printmsg( CREATE_CREATED, 0, rsbuf );
return sts;
}

View File

@@ -14,7 +14,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/

1419
extracters/ods2/default.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_DELETECMD )
@@ -17,69 +20,160 @@
#include "cmddef.h"
#ifdef _WIN32
#undef DELETE
#endif
/***************************************************************** dodelete() */
#define delete_log OPT_GENERIC_1
#define delete_log OPT_GENERIC_1
#define delete_confirm OPT_GENERIC_2
qual_t delquals[] = { {"log", delete_log, 0, NV, "-List name of each file deleted. (Default)"},
{"nolog", 0, delete_log, NV, NULL },
{ NULL, 0, 0, NV, NULL }
qual_t delquals[] = { {"log", delete_log, 0, NV,
"-commands delete qual_log"},
{"nolog", 0, delete_log, NV, NULL },
{"confirm", delete_confirm, 0, NV,
"-commands delete qual_confirm"},
{"noconfirm", 0, delete_confirm, NV, NULL},
{ NULL, 0, 0, NV, NULL }
};
param_t delpars[] = { {"filespec", REQ, VMSFS, NOPA,
"for files to be deleted from ODS-2 volume. Wildcards are permitted.."},
param_t delpars[] = { {"filespec", REQ | NOLIM, FSPEC, NOPA,
"commands delete filespec"},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(delete) {
int sts = 0;
char res[NAM$C_MAXRSS + 1], rsa[NAM$C_MAXRSS + 1];
vmscond_t sts = 0;
char esa[NAM$C_MAXRSS + 1], rsa[NAM$C_MAXRSS + 1];
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
int options, filecount = 0;
options_t options, filecount = 0;
vmscond_t confirm = ODS2_CONFIRM_ALL;
UNUSED(argc);
if( $FAILS(sts = checkquals( &options, delete_log, delquals, qualc, qualv )) ) {
return sts;
}
options = checkquals( delete_log, delquals, qualc, qualv );
if( options == -1 )
return SS$_BADPARAM;
if( options & delete_confirm )
confirm = DELETE_CONFIRM;
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 & STS$M_SUCCESS ) {
if (nam.nam$b_ver < 2) {
printf( "%s\n", getmsg( DELETE$_DELVER, MSG_FULL) );
return SS$_BADPARAM;
--argc;
++argv;
while( ($SUCCESSFUL(sts) ||
$VMS_STATUS_SEVERITY(sts) <= STS$K_WARNING ) && argc-- ) {
nam.nam$l_esa = esa;
nam.nam$b_ess = sizeof(esa) -1;
fab.fab$l_nam = &nam;
fab.fab$l_fna = argv++[0];
fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna);
if( $FAILS(sts = sys_parse( &fab )) ) {
printmsg( DELETE_NOTDELETED, 0, fab.fab$l_fna );
sts = printmsg( sts,MSG_CONTINUE, DELETE_NOTDELETED );
break;
}
esa[nam.nam$b_esl] = '\0';
if( !(nam.nam$l_fnb & NAM$M_EXP_VER) ) {
sts = printmsg( $SETFAC(SHR$_DELVER,DELETE), 0 );
break;
}
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ( ( sts = sys_search( &fab ) ) & STS$M_SUCCESS ) {
sts = sys_erase(&fab);
if ( !( sts & STS$M_SUCCESS ) ) {
printf("%%DELETE-F-DELERR, Delete error: %s\n",getmsg(sts, MSG_TEXT));
nam.nam$b_rss = sizeof(rsa) -1;
fab.fab$l_fop = 0;
while( TRUE ) {
uint32_t directory;
uint16_t retlen;
struct FAB ffab = cc$rms_fab;
struct RAB rab = cc$rms_rab;
struct XABITM itm = cc$rms_xabitm;
struct item_list xitems[] = {
{ XAB$_UCHAR_DIRECTORY, sizeof(directory), NULL, 0 },
{ 0, 0, NULL, 0 }
};
if( $FAILS(sts = sys_search( &fab )) ) {
if( $MATCHCOND(sts, RMS$_NMF) )
break;
printmsg( DELETE_NOTDELETED, 0,
(nam.nam$b_esl? esa: fab.fab$l_fna) );
sts = printmsg( sts, MSG_CONTINUE, DELETE_NOTDELETED );
break;
} else {
filecount++;
if( options & delete_log ) {
rsa[nam.nam$b_rsl] = '\0';
printf("%%DELETE-I-DELETED, Deleted %s\n",rsa);
}
rsa[nam.nam$b_rsl] = '\0';
if( $MATCHCOND( confirm, DELETE_CONFIRM) )
confirm = confirm_cmd( confirm, rsa );
if( !$MATCHCOND( confirm, ODS2_CONFIRM_ALL ) ) {
if( $MATCHCOND( confirm, ODS2_CONFIRM_YES ) ) {
confirm = DELETE_CONFIRM;
} else if( $MATCHCOND( confirm, ODS2_CONFIRM_NO ) ) {
confirm = DELETE_CONFIRM;
continue;
} else { /* ODS2_CONFIRM_QUIT */
sts = confirm;
break;
}
}
}
if( sts == RMS$_NMF ) sts = SS$_NORMAL;
}
if( sts & STS$M_SUCCESS ) {
if( filecount < 1 ) {
printf( "%%DELETE-W-NOFILES, no files deleted\n" );
}
} else {
printf( "%%DELETE-F-ERROR Status: %s\n", getmsg(sts, MSG_TEXT) );
xitems[0].buffer = &directory; xitems[0].retlen = &retlen;
itm.xab$b_mode = XAB$K_SENSEMODE;
itm.xab$l_itemlist = xitems;
ffab.fab$l_xab = &itm;
ffab.fab$l_fna = rsa;
ffab.fab$b_fns = nam.nam$b_rsl;
ffab.fab$b_fac = FAB$M_GET;
if( $FAILS(sys_open( &ffab )) ) {
sts = printmsg( DELETE_OPENIN, 0, rsa );
continue;
}
if( directory ) {
rab.rab$l_fab = &ffab;
if( $FAILS(sts = sys_connect( &rab )) ) {
printmsg( DELETE_OPENIN, 0, rsa );
sts = printmsg( sts, MSG_CONTINUE, DELETE_OPENIN );
} else {
sts = sys_get( &rab );
if( $MATCHCOND( sts, RMS$_EOF ) ) {
sts = SS$_NORMAL;
} else { /* RMS$_RTB if a record exists */
printmsg( DELETE_NOTDELETED, 0, rsa );
sts = printmsg( DELETE_DIRNOTEMPTY, MSG_CONTINUE, DELETE_NOTDELETED );
}
sys_disconnect( &rab );
}
}
sys_close( &ffab );
if( $FAILED(sts) ) {
continue;
}
if( $FAILS(sts = sys_erase(&ffab)) ) {
printmsg( DELETE_NOTDELETED, 0, rsa );
sts = printmsg( sts, MSG_CONTINUE, DELETE_NOTDELETED );
continue;
}
filecount++;
if( options & delete_log )
sts = printmsg( DELETE_DELETED, 0, rsa);
} /* search */
if( $MATCHCOND( sts, ODS2_CONFIRM_QUIT ) )
break;
if( $MATCHCOND(sts, RMS$_NMF) )
sts = SS$_NORMAL;
} /* arg */
if( $SUCCESSFUL(sts) || $MATCHCOND( sts, ODS2_CONFIRM_QUIT ) ) {
if( filecount < 1 )
sts = printmsg( DELETE_NOFILES, 0 );
else if( filecount != 1 )
sts = printmsg( DELETE_NFILES, 0, filecount );
}
fab.fab$b_fns =
fab.fab$b_dns = 0;
nam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &fab ); /* Discard context */
return sts;
}

View File

@@ -7,7 +7,8 @@
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 contributions of the original author and
* subsequent contributors.
1.4 Changed declarations NOT to define DOLLAR identifiers
unless DOLLAR is defined (some compilers can't handle $'s!)

View File

@@ -30,7 +30,7 @@ OPTIONS =
.ENDIF
# The next line is automatically generated. Do not change the format or split into multiple lines
OBJS = ODS2 ACCESS CACHE COMPAT COPYCMD CREATECMD DEBUG DELETECMD DEVICE DIFFCMD DIRCMD DIRECT DISMOUNTCMD EXTENDCMD HELPCMD IMPORTCMD INITIALCMD INITVOL MOUNTCMD PHYVMS PHYVIRT RMS SEARCHCMD SETCMD SHOWCMD SPAWNCMD SYSMSG TYPECMD UPDATE VMSTIME
OBJS = ODS2 ACCESS CACHE COMPAT COPYCMD CREATECMD DEBUG DELETECMD DEVICE DIFFCMD DIRCMD DIRECT DISMOUNTCMD EXTENDCMD HELPCMD INITIALCMD INITVOL MOUNTCMD PHYVMS PHYVIRT RMS SEARCHCMD SETCMD SHOWCMD SPAWNCMD SYSMSG UPDATE VMSTIME
ODS2$(EXE) : ODS2$(OLB)($(OBJS))$(OPTFILE)
$(LINK)$(LINKFLAGS) ODS2$(OLB)/INCLUDE=($(OBJS))$(OPTIONS)
@@ -45,118 +45,110 @@ VAXCRTL.OPT :
# ### BEGIN RULES ###
ODS2$(OBJ): VERSION.H
ODS2$(OBJ): CMDDEF.H
ODS2$(OBJ): COMPAT.H
ODS2$(OBJ): ODS2.H RMS.H
ODS2$(OBJ): VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H CACHE.H PHYVIRT.H
ODS2$(OBJ): VERSION.H CMDDEF.H
ODS2$(OBJ): COMPAT.H
ODS2$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
ODS2$(OBJ): SSDEF.H STSDEF.H SYSMSG.H CACHE.H PHYVIRT.H
ACCESS$(OBJ): SSDEF.H ACCESS.H CACHE.H F11DEF.H
ACCESS$(OBJ): VMSTIME.H
ACCESS$(OBJ): DESCRIP.H STSDEF.H DEVICE.H PHYIO.H INITVOL.H ODS2.H PHYVIRT.H
ACCESS$(OBJ): COMPAT.H
ACCESS$(OBJ): DESCRIP.H STSDEF.H DEVICE.H ODS2.H PHYIO.H INITVOL.H PHYVIRT.H
ACCESS$(OBJ): COMPAT.H
ACCESS$(OBJ): SYSMSG.H
CACHE$(OBJ): CACHE.H ODS2.H SSDEF.H
CACHE$(OBJ): CACHE.H ODS2.H
CACHE$(OBJ): SSDEF.H
COMPAT$(OBJ): COMPAT.H
COMPAT$(OBJ): DESCRIP.H STSDEF.H
COPYCMD$(OBJ): CMDDEF.H
COPYCMD$(OBJ): COMPAT.H
COPYCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
COPYCMD$(OBJ): STSDEF.H SYSMSG.H
CREATECMD$(OBJ): CMDDEF.H
COMPAT$(OBJ): DESCRIP.H STSDEF.H
COPYCMD$(OBJ): CMDDEF.H
COPYCMD$(OBJ): COMPAT.H ODS2.H
COPYCMD$(OBJ): RMS.H F11DEF.H VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
CREATECMD$(OBJ): CMDDEF.H
CREATECMD$(OBJ): COMPAT.H
CREATECMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
CREATECMD$(OBJ): STSDEF.H SYSMSG.H F11DEF.H
CREATECMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H
CREATECMD$(OBJ): DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
DEBUG$(OBJ): DEBUG.H
DELETECMD$(OBJ): CMDDEF.H
DELETECMD$(OBJ): CMDDEF.H
DELETECMD$(OBJ): COMPAT.H
DELETECMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
DELETECMD$(OBJ): STSDEF.H SYSMSG.H
DEVICE$(OBJ): ODS2.H ACCESS.H CACHE.H F11DEF.H
DEVICE$(OBJ): VMSTIME.H
DELETECMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H
DELETECMD$(OBJ): DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
DEVICE$(OBJ): ODS2.H
DEVICE$(OBJ): ACCESS.H CACHE.H F11DEF.H VMSTIME.H
DEVICE$(OBJ): DESCRIP.H SSDEF.H STSDEF.H DEVICE.H PHYIO.H
DIFFCMD$(OBJ): CMDDEF.H
DIFFCMD$(OBJ): CMDDEF.H
DIFFCMD$(OBJ): COMPAT.H
DIFFCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
DIFFCMD$(OBJ): STSDEF.H SYSMSG.H
DIRCMD$(OBJ): CMDDEF.H
DIFFCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
DIFFCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H
DIRCMD$(OBJ): CMDDEF.H
DIRCMD$(OBJ): COMPAT.H
DIRCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
DIRCMD$(OBJ): STSDEF.H SYSMSG.H
DIRCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
DIRCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H
DIRECT$(OBJ): ACCESS.H CACHE.H F11DEF.H
DIRECT$(OBJ): VMSTIME.H
DIRECT$(OBJ): DESCRIP.H SSDEF.H STSDEF.H DIRECT.H FIBDEF.H ODS2.H
DISMOUNTCMD$(OBJ): CMDDEF.H
DISMOUNTCMD$(OBJ): COMPAT.H
DIRECT$(OBJ): DESCRIP.H SSDEF.H STSDEF.H DIRECT.H FIBDEF.H ODS2.H SYSMSG.H
DISMOUNTCMD$(OBJ): CMDDEF.H
DISMOUNTCMD$(OBJ): COMPAT.H
DISMOUNTCMD$(OBJ): ODS2.H
DISMOUNTCMD$(OBJ): RMS.H VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H ACCESS.H
DISMOUNTCMD$(OBJ): CACHE.H F11DEF.H
DISMOUNTCMD$(OBJ): DEVICE.H PHYIO.H
EXTENDCMD$(OBJ): CMDDEF.H
DISMOUNTCMD$(OBJ): RMS.H F11DEF.H VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
DISMOUNTCMD$(OBJ): ACCESS.H CACHE.H DEVICE.H PHYIO.H
EXTENDCMD$(OBJ): CMDDEF.H
EXTENDCMD$(OBJ): COMPAT.H
EXTENDCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
EXTENDCMD$(OBJ): STSDEF.H SYSMSG.H
HELPCMD$(OBJ): CMDDEF.H
EXTENDCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H
EXTENDCMD$(OBJ): DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
HELPCMD$(OBJ): CMDDEF.H
HELPCMD$(OBJ): COMPAT.H
HELPCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
HELPCMD$(OBJ): STSDEF.H SYSMSG.H
IMPORTCMD$(OBJ): CMDDEF.H
IMPORTCMD$(OBJ): COMPAT.H
IMPORTCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
IMPORTCMD$(OBJ): STSDEF.H SYSMSG.H
INITIALCMD$(OBJ): CMDDEF.H
HELPCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
HELPCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H VERSION.H
INITIALCMD$(OBJ): CMDDEF.H
INITIALCMD$(OBJ): COMPAT.H
INITIALCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H
INITIALCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H ACCESS.H CACHE.H F11DEF.H
INITIALCMD$(OBJ): DEVICE.H
INITIALCMD$(OBJ): PHYIO.H INITVOL.H PHYVIRT.H
INITVOL$(OBJ): COMPAT.H
INITIALCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H
INITIALCMD$(OBJ): DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
INITIALCMD$(OBJ): ACCESS.H CACHE.H DEVICE.H PHYIO.H INITVOL.H PHYVIRT.H
INITVOL$(OBJ): COMPAT.H
INITVOL$(OBJ): F11DEF.H
INITVOL$(OBJ): VMSTIME.H
INITVOL$(OBJ): DESCRIP.H SSDEF.H STSDEF.H INITVOL.H ODS2.H PHYVIRT.H RMS.H
MOUNTCMD$(OBJ): CMDDEF.H
INITVOL$(OBJ): SYSMSG.H
MOUNTCMD$(OBJ): CMDDEF.H
MOUNTCMD$(OBJ): COMPAT.H
MOUNTCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
MOUNTCMD$(OBJ): STSDEF.H SYSMSG.H ACCESS.H CACHE.H F11DEF.H
MOUNTCMD$(OBJ): DEVICE.H
MOUNTCMD$(OBJ): PHYIO.H PHYVIRT.H
PHYVMS$(OBJ): DESCRIP.H RMS.H VMSTIME.H SSDEF.H STSDEF.H
MOUNTCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
MOUNTCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H ACCESS.H
MOUNTCMD$(OBJ): CACHE.H DEVICE.H PHYIO.H PHYVIRT.H
PHYVMS$(OBJ): DESCRIP.H RMS.H F11DEF.H
PHYVMS$(OBJ): VMSTIME.H
PHYVMS$(OBJ): SSDEF.H STSDEF.H
PHYVMS$(OBJ): ODS2.H PHYIO.H PHYVIRT.H
PHYVIRT$(OBJ): COMPAT.H
PHYVIRT$(OBJ): COMPAT.H
PHYVIRT$(OBJ): DEVICE.H
PHYVIRT$(OBJ): ACCESS.H CACHE.H F11DEF.H
PHYVIRT$(OBJ): ACCESS.H CACHE.H F11DEF.H
PHYVIRT$(OBJ): VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H
PHYVIRT$(OBJ): PHYIO.H ODS2.H PHYVIRT.H
RMS$(OBJ): ACCESS.H CACHE.H
RMS$(OBJ): F11DEF.H VMSTIME.H
RMS$(OBJ): DESCRIP.H SSDEF.H STSDEF.H DEVICE.H PHYIO.H DIRECT.H FIBDEF.H ODS2.H
RMS$(OBJ): RMS.H COMPAT.H
PHYVIRT$(OBJ): ODS2.H PHYIO.H PHYVIRT.H
RMS$(OBJ): ACCESS.H CACHE.H F11DEF.H
RMS$(OBJ): VMSTIME.H DESCRIP.H
RMS$(OBJ): SSDEF.H STSDEF.H DEVICE.H ODS2.H PHYIO.H DIRECT.H FIBDEF.H RMS.H
RMS$(OBJ): COMPAT.H
RMS$(OBJ): SYSMSG.H
SEARCHCMD$(OBJ): CMDDEF.H
SEARCHCMD$(OBJ): CMDDEF.H
SEARCHCMD$(OBJ): COMPAT.H
SEARCHCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
SEARCHCMD$(OBJ): STSDEF.H SYSMSG.H
SETCMD$(OBJ): CMDDEF.H
SEARCHCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H
SEARCHCMD$(OBJ): DESCRIP.H SSDEF.H STSDEF.H SYSMSG.H
SETCMD$(OBJ): CMDDEF.H
SETCMD$(OBJ): COMPAT.H
SETCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
SETCMD$(OBJ): STSDEF.H SYSMSG.H
SHOWCMD$(OBJ): CMDDEF.H
SETCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
SETCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H
SHOWCMD$(OBJ): CMDDEF.H
SHOWCMD$(OBJ): COMPAT.H
SHOWCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
SHOWCMD$(OBJ): STSDEF.H SYSMSG.H ACCESS.H CACHE.H F11DEF.H
SHOWCMD$(OBJ): DIRECT.H PHYIO.H
SHOWCMD$(OBJ): PHYVIRT.H VERSION.H
SPAWNCMD$(OBJ): CMDDEF.H
SHOWCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
SHOWCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H ACCESS.H
SHOWCMD$(OBJ): CACHE.H DIRECT.H PHYIO.H PHYVIRT.H VERSION.H
SPAWNCMD$(OBJ): CMDDEF.H
SPAWNCMD$(OBJ): COMPAT.H
SPAWNCMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
SPAWNCMD$(OBJ): STSDEF.H SYSMSG.H
SYSMSG$(OBJ): SSDEF.H RMS.H
SYSMSG$(OBJ): VMSTIME.H DESCRIP.H STSDEF.H COMPAT.H
SPAWNCMD$(OBJ): ODS2.H RMS.H F11DEF.H VMSTIME.H DESCRIP.H
SPAWNCMD$(OBJ): SSDEF.H STSDEF.H SYSMSG.H
SYSMSG$(OBJ): ODS2.H SSDEF.H RMS.H F11DEF.H VMSTIME.H
SYSMSG$(OBJ): DESCRIP.H STSDEF.H COMPAT.H
SYSMSG$(OBJ): SYSMSG.H
TYPECMD$(OBJ): CMDDEF.H
TYPECMD$(OBJ): COMPAT.H
TYPECMD$(OBJ): ODS2.H RMS.H VMSTIME.H DESCRIP.H SSDEF.H
TYPECMD$(OBJ): STSDEF.H SYSMSG.H
SYSMSG$(OBJ): DEFAULT.MT
UPDATE$(OBJ): ACCESS.H CACHE.H
UPDATE$(OBJ): F11DEF.H
UPDATE$(OBJ): VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H DEVICE.H PHYIO.H ODS2.H
UPDATE$(OBJ): F11DEF.H VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H DEVICE.H ODS2.H
UPDATE$(OBJ): PHYIO.H INITVOL.H
VMSTIME$(OBJ): VMSTIME.H DESCRIP.H SSDEF.H STSDEF.H
VMSTIME$(OBJ): ODS2.H

View File

@@ -1,21 +1,26 @@
/* Device.c Module to remember and find devices...*/
/*
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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* Should have mechanism to return actual device name... */
/* This module is simple enough - it just keeps track of
device names and initialization... */
* device names and initialization...
*/
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -34,32 +39,30 @@
#endif
#endif
static void *device_create( unsigned devsiz, void *keyval, unsigned *retsts );
static int device_compare( unsigned keylen, void *keyval, void *node );
static void *device_create( uint32_t devsiz, void *keyval, vmscond_t *retsts );
static int device_compare( uint32_t keylen, void *keyval, void *node );
static struct DEV *dev_root = NULL;
/************************************************************ device_create() */
/* device_create() creates a device object... */
/* device_create() creates a device object...
*/
static void *device_create( unsigned devsiz, void *keyval, unsigned *retsts ) {
static void *device_create( uint32_t devsiz, void *keyval, vmscond_t *retsts ) {
register struct DEV *dev;
dev = (struct DEV *) malloc( sizeof( struct DEV ) + devsiz + 1 );
dev = (struct DEV *) calloc( 1, offsetof( struct DEV, devnam ) + devsiz + 2 );
if ( dev == NULL ) {
*retsts = SS$_INSFMEM;
return NULL;
}
dev->cache.objmanager = NULL;
dev->cache.objtype = OBJTYPE_DEV;
dev->vcb = NULL;
dev->access = 0;
dev->context = NULL;
memcpy( dev->devnam, keyval, devsiz );
memcpy( dev->devnam + devsiz, ":", 2 );
*retsts = SS$_NORMAL;
return dev;
}
@@ -77,7 +80,7 @@ void device_done( struct DEV *dev ) {
#endif
abort();
}
cache_untouch( &dev->cache, FALSE );
cache_untouch( &dev->cache, TRUE );
if( dev->cache.refcount == 0 ) /* Safe because on LRU list */
cache_delete( &dev->cache );
return;
@@ -87,11 +90,14 @@ void device_done( struct DEV *dev ) {
/* device_compare() compares a device name to that of a device object... */
static int device_compare( unsigned keylen, void *keyval, void *node ) {
static int device_compare( uint32_t keylen, void *keyval, void *node ) {
register int cmp;
register const char *keynam = (const char *) keyval;
register const char *devnam = ((const struct DEV *) node)->devnam;
register const char *keynam;
register const char *devnam;
keynam = (const char *) keyval;
devnam = ((const struct DEV *) node)->devnam;
cmp = 0;
while ( keylen-- > 0 ) {
@@ -110,10 +116,11 @@ static int device_compare( unsigned keylen, void *keyval, void *node ) {
/* device_lookup() is to to find devices... */
unsigned device_lookup( unsigned devlen, char *devnam, int create,
vmscond_t device_lookup( size_t devlen, char *devnam, int create,
struct DEV **retdev ) {
unsigned sts, devsiz;
vmscond_t sts;
size_t devsiz;
register struct DEV *dev;
for ( devsiz = 0; devsiz < devlen; devsiz++ ) {
@@ -121,15 +128,18 @@ unsigned device_lookup( unsigned devlen, char *devnam, int create,
break;
}
}
dev = (struct DEV *) cache_find( (void *) &dev_root, devsiz, devnam, &sts,
dev = (struct DEV *) cache_find( (void *) &dev_root, (uint32_t)devsiz, devnam, &sts,
device_compare,
create ? device_create : NULL );
if ( dev == NULL ) {
if ( sts == SS$_ITEMNOTFOUND ) {
if ( $MATCHCOND(sts, SS$_ITEMNOTFOUND) ) {
sts = SS$_NOSUCHDEV;
}
} else {
*retdev = dev;
if( retdev == NULL )
device_done( dev );
else
*retdev = dev;
sts = SS$_NORMAL;
}
return sts;

View File

@@ -1,14 +1,17 @@
/* Device.h Definitions for device routines */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
* 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _DEVICE_H
#define _DEVICE_H
@@ -21,12 +24,13 @@
#include <sys/types.h>
#include "access.h"
#include "cache.h"
#include "ods2.h"
#include "phyio.h"
struct DEV { /* Device information */
struct CACHE cache;
struct VCB *vcb; /* Pointer to volume (if mounted) */
int access; /* Device mount options (e.g., /Write) */
options_t access; /* Device mount options (e.g., /Write) */
void *context; /* Context for implementation */
#ifdef _WIN32
@@ -57,7 +61,7 @@ struct DEV { /* Device information */
char devnam[1]; /* Device name */
};
unsigned device_lookup( unsigned devlen, char *devnam, int create,
vmscond_t device_lookup( size_t devlen, char *devnam, int create,
struct DEV **retdev );
void device_done( struct DEV *dev );

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_DIFFCMD )
@@ -16,81 +19,136 @@
#endif
#include "cmddef.h"
#include "phyio.h"
/******************************************************************* dodiff() */
/* dodiff: a simple file difference routine */
param_t 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 }
static uint32_t maxdiffs;
#define diff_maxdiff OPT_GENERIC_1
#define diff_binary OPT_GENERIC_2
qual_t
diffquals[] = {{"maximum_differences", diff_maxdiff, 0, DV(&maxdiffs), "commands difference qual_maxdiff"},
{"nomaximum_differences", 0, diff_maxdiff, NV, NULL },
{"binary", diff_binary, 0, NV, "commands difference qual_binary"},
{ NULL, 0, 0, NV, NULL }
};
param_t
diffpars[] = { {"Files-11_filespec", REQ, FSPEC, NOPA, "commands difference Files-11_spec"},
{"local_filespec", REQ, FSPEC, NOPA, "commands difference local_spec"},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(diff) {
int sts, records = 0;
char *rec, *cpy = NULL;
vmscond_t sts;
options_t options;
uint32_t records, diffs = 0;
char *rec, *cpy = NULL, *buf = NULL;
size_t bufsize = 80;
char *name;
FILE *tof;
struct FAB fab = cc$rms_fab;
struct RAB rab = cc$rms_rab;
struct NAM nam = cc$rms_nam;
char rsname[NAM$C_MAXRSS+1];
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
name = argv[1];
sts = SS$_BADFILENAME;
if ( *name == '\0' ) {
if( $FAILS(sts = checkquals( &options, 0, diffquals, qualc, qualv )) )
return sts;
name = get_realpath( argv[2] );
records = 0;
nam.nam$l_rsa = rsname;
nam.nam$b_rss = (uint8_t)(sizeof( rsname) - 1);
fab.fab$l_nam = &nam;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = (uint8_t)strlen( fab.fab$l_fna );
if ( (tof = openf( name? name: argv[2], "r" )) == NULL ) {
int err;
err = errno;
printmsg( DIFF_OPENIN, 0, name? name: argv[2] );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE, DIFF_OPENIN, strerror(err) );
free( name );
return sts;
}
records = 0;
fab.fab$l_fna = name;
fab.fab$b_fns = strlen( fab.fab$l_fna );
tof = openf( argv[2], "r" );
if ( tof == NULL ) {
printf("%%ODS2-E-OPENERR, Could not open file %s\n",name);
perror( " - " );
return SS$_NOSUCHFILE;
}
sts = sys_open( &fab );
if ( sts & STS$M_SUCCESS ) {
if( $SUCCESSFUL(sts = sys_open( &fab )) ) {
rab.rab$l_fab = &fab;
sts = sys_connect( &rab );
if( sts & STS$M_SUCCESS ) {
nam.nam$l_rsa[nam.nam$b_rsl] = '\0';
if( $SUCCESSFUL(sts = sys_connect( &rab )) ) {
if( (rec = malloc( MAXREC + 2 )) == NULL ) {
perror( "malloc" );
int err;
err = errno;
sts = SS$_INSFMEM;
printmsg( sts, 0 );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE, sts, strerror(err) );
} else {
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while( (sts = sys_get( &rab )) & STS$M_SUCCESS ) {
while( $SUCCESSFUL(sts = sys_get( &rab )) ) {
rec[rab.rab$w_rsz] = '\0';
cpy = fgetline( tof, FALSE );
++records;
cpy = fgetline( tof, FALSE, &buf, &bufsize );
if( cpy == NULL ||
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;
if( options & diff_binary )
sts = printmsg( DIFF_DIFFER, 0, records );
else
printf( "************\n"
"File %s\n"
"%5u %.*s\n"
"******\n"
"File %s\n"
"%5u %s\n"
"************\n",
rsname,
records, rab.rab$w_rsz, rec,
name,
records, cpy? cpy: "<EOF>" );
if( (++diffs > maxdiffs && (options & diff_maxdiff)) || cpy == NULL )
break;
}
free( cpy );
cpy = NULL;
records++;
}
if( cpy != NULL ) free( cpy );
free( rec );
rec = cpy = NULL;
}
sys_disconnect(&rab);
}
sys_close(&fab);
} else {
printmsg( DIFF_OPENIN, 0, argv[1] );
sts = printmsg( sts, MSG_CONTINUE, DIFF_OPENIN );
}
if( sts == RMS$_EOF ) {
if( (cpy = fgetline( tof, FALSE, &buf, &bufsize )) == NULL )
sts = SS$_NORMAL;
else {
if( diffs < maxdiffs )
sts = printmsg( DIFF_DIFFER, 0, records );
}
}
if( buf != NULL ) free( buf );
fclose(tof);
if (sts == RMS$_EOF) sts = SS$_NORMAL;
if ( sts & STS$M_SUCCESS ) {
printf( "%%DIFF-I-Compared %d records\n", records );
} else if ( sts != 4 ) {
printf("%%DIFF-F-Error %s in difference\n",getmsg(sts, MSG_TEXT));
if( $SUCCESSFUL(sts) ) {
sts = printmsg( DIFF_COMPARED, 0, records );
} else if( !$MATCHCOND(sts, DIFF_DIFFER) ) {
sts = printmsg( sts, 0, rab.rab$l_stv );
}
free( name );
return sts;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,31 @@
/* Direct.h Definitions for directory 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _DIRECT_H
#define _DIRECT_H
#include <stdint.h>
#include "access.h"
#include "descrip.h"
#include "f11def.h"
#include "ods2.h"
void direct_show( void );
unsigned direct(struct VCB *vcb,struct dsc_descriptor *fibdsc,
struct dsc_descriptor *filedsc,unsigned short *reslen,
struct dsc_descriptor *resdsc,unsigned action);
vmscond_t direct( struct VCB *vcb, struct dsc_descriptor *fibdsc,
struct dsc_descriptor *filedsc, uint16_t *reslen,
struct dsc_descriptor *resdsc, unsigned action );
#define DIRECT_FIND 0
#define DIRECT_DELETE 1
@@ -28,4 +33,7 @@ unsigned direct(struct VCB *vcb,struct dsc_descriptor *fibdsc,
#define MODIFIES(action) (action != DIRECT_FIND)
vmscond_t direct_dirid( struct VCB *vcb, struct dsc$descriptor *dirdsc,
struct fiddef *dirid, struct fiddef *fid );
#endif /* #ifndef _DIRECT_H */

View File

@@ -4,7 +4,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_DISMOUNTCMD )
@@ -22,28 +25,40 @@
/******************************************************************* dodismount() */
param_t dmopars[] = { {"drive_letter", REQ, STRING, NOPA, "Drive containing volume to dismount", },
{NULL, 0, 0, NOPA, NULL }
qual_t
dmoquals[] = { {"log", MOU_LOG, 0, NV,
"-commands dismount qual_log"},
{"nolog", 0, MOU_LOG, NV, NULL },
{NULL, 0, 0, NV, NULL }
};
param_t
dmopars[] = { {"drive_name", REQ, STRING, NOPA,
"commands dismount drive"},
{NULL, 0, 0, NOPA, NULL}
};
DECL_CMD(dismount) {
vmscond_t sts;
options_t options;
struct DEV *dev;
int sts;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
sts = device_lookup( strlen(argv[1]), argv[1], FALSE, &dev );
if( sts & STS$M_SUCCESS ) {
if( $FAILS(sts = checkquals( &options, MOU_LOG, dmoquals, qualc, qualv )) ) {
return sts;
}
if( $SUCCESSFUL(sts = device_lookup( (uint32_t)strlen(argv[1]),
argv[1], FALSE, &dev )) ) {
device_done( dev );
if( dev->vcb != NULL ) {
sts = dismount( dev->vcb );
sts = dismount( dev->vcb, options );
} else {
sts = SS$_DEVNOTMOUNT;
}
}
if( !(sts & STS$M_SUCCESS) )
printf("%%DISMOUNT-E-STATUS Error: %s\n",getmsg(sts, MSG_TEXT));
return sts;
}

912
extracters/ods2/en_us.hlp Normal file
View File

@@ -0,0 +1,912 @@
! Help file for ODS2
! Contains help text for topics that don't need a condition code, or are too long
! for condition code messages, which are limited to 255 bytes.
!
! Format:
! Lines beginning with a digit + space + TOPIC are search keys.
! Similar to the VMS HELP librarian, there are 9 hierarchical levels
! of keys. However, unlike the VMS HELP librarian, browsing is controlled
! by the command tables & the text allows printf() substitutions.
!
! The key names are not case-sensitive. Most key names are
! coded in the command tables of ODS2 and can not be changed
! unless a corresponding change is made to the tables.
!
! All other lines contain topic text.
!
! If a line ends in '$' newline, the newline will not be displayed.
!
! A topic consists of all lines following the search key until
! another search key or EOF is encountered.
!
1 CREDITS
The orginal version of ods2 was developed by Paul Nankervis
<Paulnank@au1.ibm.com>
This modified version was developed by Timothe Litt, and
incorporates significant previous modifications by Larry
Baker of the USGS and by Hunter Goatley
This code may be freely distributed within the VMS community
providing that the contributions of the original author and
subsequent contributors are acknowledged in the help text and
source files. This is free software; no warranty is offered,
and while we believe it to be useful, you use it at your own risk.
Please send problem reports/comments to litt@acm.org
!
1 COMMANDS
ODS2 has the following commands:
2 copy
Copy one or more files from a Files-11 volume to the local filesystem
or from the local filesystem to a Files-11 volume.
3 fromspec
One or more file specifications to copy.
The syntax of each filespec depends on the direction of the copy.
Files on the Files-11 volume use Files-11 syntax. Files on the
local filesystem use the local filespec syntax.
Wildcards may be used.
3 tospec
File specification for the destination file. The syntax of each
filespec depends on the direction of the copy. Files on the
Files-11 volume use Files-11 syntax. Files on the local
filesystem use the local filespec syntax.
Wildcards are replaced from the source file name.
3 qual_ascii
Copy file in ASCII mode (default).
ASCII mode converts local files to/from Files-11 records.
3 qual_binary
Copy file in binary mode.
Binary mode ...
3 qual_append
Append data to existing file.
Default is to create, create a new version or supersede per the output
filesystem's conventions.
3 qual_from
Copy file from files-11 volume to local file.
3 qual_to
Copy file(s) from local filesystem to files-11 volume.
3 qual_log
Log files copied.
3 qual_confirm
Prompt for confirmation of each file copied.
See HELP SYNTAX CONFIRM for details.
3 qual_cc
Carriage control for file records copied TO files-11 volume.
Does not apply to files copied FROM files-11 volumes.
4 none
No carriage control (default).
4 fortran
FORTRAN carriage control in column 1.
4 cr
Records are preceded by <LF> and followed by <CR>.
4 print
Records are VFC format with 2 bytes of encoded carriage control.
One of the following can be used for each carriage-control qualifier.
To specify both BEFORE and AFTER, use
/carriage=print=before=specifier /carriage=print=after=specifier.
Do not specify the record_format qualifier.
! Following group is used for print=before AND =after as the text would be identical
5 b4
Carriage control applied before record is printed.
6 none
No paper motion.
6 nl
Advance n lines (1-127).
6 ctl
Output ASCII C0 control character n (0 - 31).
6 vfu
Advance to VFU channel n (1-16).
5 after
Carriage control applied after record is printed.
3 qual_recfmt
Record format for files copied TO files-11 volume.
Default is variable with carriage_return carriage control.
Does not apply to files copied FROM files-11 volume.
4 fixed
Fixed length records, n bytes.
Input will be padded or truncated to this length.
4 variable
Variable length records.
4 vfc
Variable length records with fixed length header.
Header is first n characters of input.
4 stream
Stream format with <CR><LF> record delimiters.
4 streamlf
Stream format with <LF> record delimiters.
4 streamcr
Stream format with <CR> record delimiters.
4 undefined
Stream format with no record delimiters.
3 qual_span
Allow records to cross block boundaries. (default)
Does not apply to stream files.
3 qual_verlim
Specify the version limit for a file.
3 qual_volume
Specify the volume (of a volume set) on which the file will
be placed.
3 qual_owner
Specifies the UIC of the owner of files copied TO a files-11 volume.
Default is parent directory's owner.
3 qual_protection
Specifies the protection of files copied TO a files-11 volume.
The default file protection is set when the volume is initialized.
2 create
Create Files-11 files or directories.
3 filespec
Filespec of the file or directory to be created.
Wildcards are not permitted.
3 qual_directory
Create a new Files-11 directory or subdirectory.
Note that it is possible to create a series of nested
subdirectories with a single CREATE/DIRECTORY command.
3 qual_log
List name of each file or directory created.
3 qual_cc
Carriage control for file records.
Does not apply to directories.
4 none
No carriage control (default).
4 fortran
FORTRAN carriage control in column 1.
4 cr
Records are preceded by <LF> and followed by <CR>.
4 print
Records are VFC format with 2 bytes of encoded carriage control.
One of the following can be used for each carriage-control qualifier.
To specify both BEFORE and AFTER, use
/carriage=print=before=specifier /carriage=print=after=specifier.
Do not specify the record_format qualifier.
! Following group is used for print=before AND =after as the text would be identical
5 b4
Carriage control applied before record is printed.
6 none
No paper motion.
6 nl
Advance n lines (1-127).
6 ctl
Output ASCII C0 control character n (0 - 31).
6 vfu
Advance to VFU channel n (1-16).
5 after
Carriage control applied after record is printed.
3 qual_recfmt
Record format when creating file.
Default is variable with carriage_return carriage control.
Does not apply to directories.
4 fixed
Fixed length records, n bytes.
Input will be padded or truncated to this length.
4 variable
Variable length records.
4 vfc
Variable length records with fixed length header.
Header is first n characters of input.
4 stream
Stream format with <CR><LF> record delimiters.
4 streamlf
Stream format with <LF> record delimiters.
4 streamcr
Stream format with <CR> record delimiters.
4 undefined
Stream format with no record delimiters.
3 qual_span
Allow records to cross block boundaries. (default)
Does not apply to stream files or directories.
3 qual_verlim
Specify the version limit for a file, or the default version limit
for a directory.
3 qual_volume
Specify the volume (of a volume set) on which the file or directory will
be placed.
3 qual_owner
Specifies the UIC of the owner of the file or directory.
Default is parent directory's owner.
3 qual_protection
Specifies the protection of the file or directory.
The default file protection is set when the volume is initialized.
The default directory protection is inherited from the
directory's parent, with all delete permissions removed.
3 qual_vfc
Include fixed header of VFC records copied as data.
Ignored for PRINT format files.
2 delete
Delete Files-11 files or directories.
3 filespec
File specification(s) for Files-11 file(s) to be deleted.
Wildcards are permitted.
3 qual_log
List name of each file deleted. (Default)
3 qual_confirm
Prompt for confirmation of each file deleted.
See HELP SYNTAX CONFIRM for details.
2 difference
Compare a file on the Files-11 volume to a file on the local filesystem and
report the differences.
3 Files-11_spec
File specification for a file on a Files-11 volume.
3 local_spec
File specification for a file on the local filesystem.
3 qual_binary
Compares the file as binary; does not output difference records.
3 qual_maxdiff
Maximum number of differences to report.
2 directory
List files on a Files-11 volume.
3 filespec
Specification of files to list. Files-11 wildcards are supported.
Default is *.*;*
3 qual_brief
Brief display - names with header/trailer (default)
3 qual_fileid
Include file ID
3 qual_full
Include all details
3 qual_grand
Include only grand total
3 qual_heading
Include heading
3 qual_owner
Include file owner
3 qual_output
Write ouput to a local file
3 qual_protection
Include file protection
3 qual_total
Include only directory name and summary
3 qual_trailing
Include trailing summary line
3 qual_map
Include map area of file header.
3 qual_pack
Normal packing of fields. Negated,
outputs format for automation.
3 qual_size
Size of file.
4 size_both
Number of blocks allocated and used.
4 size_alloc
Number of blocks allocated to file.
4 size_used
Number of blocks used for data. (default)
3 qual_date
File date(s). Multiple dates are displayed in the order:
Date created, date modified, date expired and date of backup.
4 date_created
Date file created (default)
4 date_modified
Date file modified
4 date_expired
Date file expired
4 date_backup
Date of last backup
2 dismount
Dismount a Files-11 volume. If the volume is a member
of a mounted volumeset, the entire volumeset is dismounted.
3 drive
Drive containing volume to dismount.
3 qual_log
Display the name of the volume(s) dismounted.
2 echo
Print a string.
2 exit
Dismount all Files-11 volumes and exit ODS2
2 extend
Extend or truncate a Files-11 file.
This changes the number of blocks allocated to a file, but does
not change the data contained in the file.
Note that allocation is always a multiple of the volume's cluster size.
3 filespec
Specifies the name of the file on the File-11 volume to extend or truncate.
Wildcards are not permitted.
3 qual_allocate
The number of blocks to add to the file's allocation.
3 qual_truncate
Truncate allocation to the current end-of-file.
2 help
The HELP command describes ODS2 comands and functions.
Help is available for each command, and for general topics.
Without parameters, HELP lists the commands and topics for which
help is available.
HELP TOPIC displays the help for the named topic.
Additional levels of help are available for some topics and
commands.
HELP COMMAND PARAMETER displays the help for the parameters of a
command. The word 'parameter' lists all parameters; use the name
of a parameter (shown by the topic help) for details of just one.
For some complex commands, another level of help is available
with HELP COMMAND PARAMETER ARGUMENT.
To learn about common command elements, see the SYNTAX topic.
3 topic
Topic or command for which you want help.
For a list, type HELP<CR>
3 subtopic
Subtopic - parameter, value, or item
2 initialize
Create a new filesystem.
ALL EXISTING DATA ON THE MEDIA WILL BE LOST.
3 devspec
Local file specification for device or disk image to be initialized.
ALL EXISTING DATA ON THE MEDIA WILL BE LOST.
3 volspec
Volume label for new volume, which must be unique within a volumeset.
Volume labels are no more than 12 characters long.
Only alphanumeric characters, '$', '-', and '_' are legal.
3 qual_media
Media type (DEC model name). This determines the media size, geometry
and (in some cases) interleave.
3 qual_bootblock
Places boot block in non-standard location, which is inadvisable.
3 qual_clustersize
Cluster size (blocks) is the unit of storage allocation.
3 qual_confirm
Prompt for confirmation (default).
See HELP SYNTAX CONFIRM for details.
3 qual_create
Create a new disk image file of the specified type. Default.
Will not overwrite existing file.
3 qual_directories
Number of directory entries to pre-allocate in the MFD.
3 qual_fileprot
Default file protection for volume, default (S:RWED,O:RWED,G:RE,W:)
3 qual_headers
Number of file headers to pre-allocate.
3 qual_extension
Default extension size (blocks) for files on volume.
3 qual_windows
Default number of mapping pointers per file window.
3 qual_index
Placement hint for index file. One of:
4 begin
Place index file in lowest available LBNs.
4 block
Place index file near specific LBN.
4 middle
Place index file near middle of volume. (default)
3 qual_image
Initialize a disk image file.
3 qual_device
Initialize a physical device.
3 qual_log
Show progress and details of file structure.
3 qual_replace
Replace filesystem in existing image file. Will not change
media type.
3 qual_mount
Mount volume after initialization completes.
3 qual_maxfiles
Maximum number of files volume can (ever) contain.
3 qual_owneruic
Volume owner's UIC. Default is [1,1].
3 qual_protection
Volume protection. The default is (S:RWED,O:RWED,G:RWED,W:RWED).
3 qual_username
Volume owner's username. The default your username on the local system.
2 mount
Mount a Files-11 volume or volumeset. Mounting a volume makes the files
that it contains accessible to ods2. The volume must be initialized to be mounted.
While a volume is mounted, ods2 caches data creating a potentially inconsistent
state. It must not be accessed by any other means until dismounted.
See HELP INITIALIZE for information on initializing a volume.
See HELP DISMOUNT for information on dismounting a volume.
3 volumes
List of devices or files containing volumes to mount.
Multiple containers must comprise a volumeset and must be specified
in ascending order of relative volume number.
Separate list items with comma.
3 labels
List of volume labels corresponding to each container.
Separate list items with comma.
If specified, must match label(s) in the Files-11 metadata.
3 qual_media
Media type (DEC model name). This determines the media size, geometry
and (in some cases) interleave.
A mount can fail if the wrong media type is specified.
3 qual_image
The containers are disk image files.
3 qual_log
Show progress
3 qual_readonly
Only permit reading from the volume.
3 qual_snapshot
Create snapshot(s) of the (existing) VHD disk(s) specified by this qualifier.
See HELP SPECIFY_MOUNT for more information.
3 qual_device
The containers are raw devices.
3 qual_write
Allow both reading from and writing to the volume.
2 quit
Dismount all Files-11 volumes and exit ODS2.
2 rename
Rename files on Files-11 volume.
3 fromspec
Filespec of existing file on Files-11 volume.
Wildcards can be used.
3 tospec
New filespec for file.
The '*' wildcard can be used to copy components from the original filename(s).
(Currently only [*] and [*...] are supported for the directory.)
Can change directory, name, type, version, but not device.
3 qual_confirm
Prompt for confirmation.
See HELP SYNTAX CONFIRM for details.
3 qual_log
Show progress
2 search
Search Files-11 file(s) for one or more strings.
3 filespec
File on Files-11 volume to search.
Wildcards are permitted.
3 string
One or more strings to earch for in the file(s).
Multiple strings are compared with each record as specified by
the MATCH qualifier.
3 qual_confirm
Prompt for confirmation before searching each file.
See HELP SYNTAX CONFIRM for details.
3 qual_exact
Strings are compared matching the string to the record exactly.
By default, uppercase and lowercase are treated as equivalent.
3 qual_heading
Print a heading with the name of each file that matches.
By default, a heading is only printed if the filespec contained a wildcard.
3 qual_highlight
Highlight text that matches specified string(s), using one or more of
the following renderings:
4 highlight_blink
Blink matching text
4 highlight_bold
Render matching text as bold (default)
4 highlight_hardcopy
Render matching text for a non-ANSI device
4 highlight_reverse
Render matching text in reverse video
4 highlight_underline
Underline matching text
3 qual_log
Display summary results for each file examined
3 qual_match
Match requirement for string(s)
4 match_and
Record must match all specified strings.
4 match_or
Record must match at least one specfied string. (default)
4 match_nand
Record must not contain all specified strings, but may contain some.
4 match_nor
Record must not contain any specified string.
3 qual_nowindow
Do not display records that match search critera.
3 qual_numbers
Display line number with matching records.
3 qual_page
Paginate output; pause every n lines. Default: terminal height.
See HELP SYNTAX PAGINATE for details.
2 set
Set a parameter or default.
3 item_name
The following items can be set:
4 type_cwd
Working (default) directory for local files.
4 type_dirquals
Directory$
4 type_copyquals
Copy$
4 type_setdef
Default device and directory for Files-11 volume.
4 type_setmsg
Message definition file name and/or message display option qualifiers.
4 type_searchquals
Search$
4 type_qualstyle
Style$
4 item_cwd
Working directory on local system.
4 item_dirquals
Default qualifiers for DIRECTORY command.
4 item_copyquals
Default qualifiers for COPY command.
4 item_setdef
Default directory on Files-11 volume.
4 item_history_limit
Maximum number of lines of command history to retain.
4 item_key_bindings
Manipulate libedit key bindings using its 'bind' command
4 item_setmsg
Message definition file or display option qualifiers.
4 item_helpfile
Help library file
4 item_seterrxit
Cause exit when a command results in an error.
4 item_searchquals
Default qualifiers for SEARCH command.
4 item_qualstyle
Qualifer style.
4 item_verify
Display commands in indirect files.
4 item_msgfac
Display facility name
4 item_msgsev
Display severity code
4 item_msgid
Display identification
4 item_msgtext
Display message text
4 item_default
Use default (built-in) messages
3 value
xxx
4 value_unix
Unix style options, '-option'
4 value_dcl
DCL style qualifiers, '/qualifier'
2 show
Display a parameter or default.
3 copy
Default qualifiers for COPY command
3 cwd
Working directory on local system
3 default
Default Files-11 device & directory
3 devices
Raw devices for mounting Files-11 volumes and virtual devices
mapped to mounted disk image files.
3 directory
Default qualifiers set for DIRECTORY command
3 qstyle
Qualifier style (DCL, Unix)
3 search
Default qualifiers set for SEARCH command
3 statistics
Debugging statistics
3 terminal
Terminal dimensions used for paged output.
3 time
Time of day
3 verify
Command file echo state
3 history
Command history
Qualifier:
/max-entries=n - Maximum number of history entries to display
3 helpfile
Name of current help library file
3 version
Version and configuration of ODS2
3 volumes
Mounted volumes' attributes
3 message
Name of current message definition file
2 spawnnt
Open a command subprocess, cmd.
Return to ods2 with the EXIT command to the cmd interpreter.
2 spawnunix
Open a command shell subprocess. The SHELL environment variable determines
which shell is run. If SHELL is not defined, /bin/sh is run.
Return to ODS2 with the exit command to the shell.
2 spawnvms
Open an interactive DCL command subprocess.
Return to ODS2 with the LOGOUT command to DCL.
2 type
Display one or more Files-11 files on the terminal.
3 filespec
One or more Files-11 file specifications to display.
Wildcards may be used.
3 qual_page
Paginate output; pause every n lines. Default: terminal height.
See HELP SYNTAX PAGINATE for details.
3 qual_vfc
Include fixed header of VFC records.
Ignored for PRINT format files.
1 INVOCATION
INVOKING ODS2
Invoke %s from your shell's command line. %s commands
may be specified on the invocation line. Separate multiple
commands on the invocation line with '$'.
If present, an initialization file is executed automatically
before any other commands, including commands on the invocation line.
2 NT
The environment variable ODS2INIT specifies the initialization file.
If ODS2INIT is not defined, %s%s\.%s.INI is used.
2 VMS
The logical name ODS2INIT specifies the initialization file.
If ODS2INIT is not defined, SYS$LOGIN:_%s.INI is used.
2 UNIX
The environment variable ODS2INIT specifies the initialization file.
If ODS2INIT is not defined, ~/.%s.ini is used.
2 LIBEDIT
%s uses the libedit command history editor. libedit reads the editrc
file for configuration data. See 'man 5 editrc' and 'man 7 editline' for usage details.
!
1 MOUNT
You can mount a volume(-set) from either physical devices
such a CDROM or hard disk drive, or files containing an
image of a volume, such as a .ISO file or simulator disk image.
To mount a disk image, use the %simage qualifier and
specify the filename as the parameter.
If the filename contains %s, specify it in double quotes
Mount will assign a virtual device name to each volume.
You can select a virtual device name using the format
dka100=my_files.iso
To mount a physical device, use the format:
!
2 NT
mount D:
Any drive letter mapped to a physical drive can be used.
The drive is accessed as a physical device, which may require privileges.
Use SHOW DEVICES for a list of available devices.
!
2 NTASPI
mount D:
Any drive letter mapped to a physical drive can be used.
If the drive letter is C: or higher, commands are
sent directly to the drive, bypassing system drivers.
The drive must be a SCSI device.
The drive is accessed as a physical device, which may require privileges.
Use SHOW DEVICES for a list of available devices.
!
2 OS2
Specify the device to be mounted as a drive letter.
E.g. mount D:
The drive letter must be between A: and Z:
The drive is accessed as a physical device.
!
2 UNIX
mount device
The device must be in %s.
For example, if you are using %s
ODS2$> mount cdrom0
Use SHOW DEVICES for a list of available devices.
!
2 VMS
mount DUB0:
The device can be specified as a physical device or logical name.
You will need the LOGIO privilege.
Use SHOW DEVICES for a list of available devices.
2 VHD
To create and mount a snapshot of a VHD-based volume set, use the
%ssnapshot_of qualifier.
Specify the existing volumes' filenames as an argument to %ssnapshot, and
list the corresponding filenames to be created as the mount parameter.
See the VHD_IMAGE_FILES topic for more information.
!
2 VOLSET
To mount a volume set, specify all the members in RVN order
as a comma-separated list.
If you specify a list of volume labels, they must be in
the same order as the volumes, and each must match the label
stored in the data
!
1 SYNTAX
SYNTAX
%s commands roughly follow DCL/VMS syntax, which has the
general form
VERB /Qualifier(s) parameter parameter ...
If you prefer Unix-style options to DCL qualifiers, use
SET QUALIFIER_STYLE UNIX
No logical names or symbols are supported.
Command arguments can be quoted. If parameters (e.g. filenames)
contain '%s', you can either quote them or indicate the end of
of qualifers with with '%s%s'.
2 COMMAND_FILES
COMMAND FILES
Command files allow you to automate operations, especially those
that you do more than once. A command file consists of ods2
commands exactly as you would type them, one per line.
We recommend that you do not abbreviate commands or command
elements in command files.
Command files are executed with @filespec.
They can be nested up to %u levels deep.
A command file can be automatically executed each time ods2 is
invoked. See the description of initialization files in
HELP INVOCATION
2 CONFIRM
Several command provide the CONFIRM qualifier, which causes a prompt
for confirmation of the operation. This is especially useful for
destructive and/or wildcarded operations.
The following responses are valid:
YES NO QUIT
TRUE FALSE Ctrl/Z
1 0 ALL
<Return>
You can use any combination of uppercase and lowercase letters
for word responses. Word responses can be abbreviated to one or
more letters (for example, T, TR, or TRU for TRUE), but these
abbreviations must be unique. Affirmative answers are YES, TRUE,
and 1. Negative answers include: NO, FALSE, 0, and pressing
the Return key. Entering QUIT or pressing Ctrl/Z indicates that
you want to stop processing the command at that point. When you
respond by entering ALL, the command continues to process, but no
further prompts are given. If you type a response other than one
of those in the list, ODS2 issues an error message and redisplays
the prompt.
2 PAGINATE
Commands with the /PAGE qualifier allow you to request that output
be paginated; that is, pause every 'n' lines. This prevents
large amounts of output from scrolling off the screen.
N defaults to the height of the terminal window.
When the output pauses, you are prompted and to make one of the
following choices:
<CR> Continue processing and display the next 'n' lines of output.
F<CR> Finish processing without any further pauses.
Q<CR> Stop processing the command.
End-of-file (Ctrl/Z or Ctrl/D (Unix) has the same effect as Q.
2 QUALIFIERS
Qualifiers provide additional direction to a a command. In other
environments, they may be known as "switches" or "options."
Qualifiers consist of a "/" followed by a keyword, which may
be abbreviated. (SET QUALIFIER_STYLE UNIX replaces the "/" with "-".)
Some qualifiers have a complement; e.g. /LOG and /NOLOG. These
are identifed in the help as /[NO]qualname, and the affirmative
sense is the one documented.
Some qualifiers accept a value; e.g. /DATE=CREATE. The value
is separated from the qualifier by '=' (':' is also accepted).
Qualifier values can be a a list, in which case the list members
are separated by comma. The list may be enclosed in parentheses.
2 UIC
A UIC is a "User Identification Code", which identifies the ownershipe
of a file or volume when applying file protection rules.
File and volume protections are not enforced by ODS-2, but are enforced
by other operating environments. ODS-2 allows you to specify and
display protections for interoperability with those environments.
Under some operating systems, the UIC can be specified as an alphanumeric
name, e.g. [SYSTEM]. ODS-2 does not support this format.
ODS-2 supports the numeric form of UICs, which is [group,member],
where group and member are up-to 6 digit octal numbers. Each has a
maximum value of 177777. The square brackets and comma are required.
2 PROTECTION
Files-11 protection divides accessors into four groups: SYSTEM, OWNER,
GROUP, and WORLD.
SYSTEM refers to system-privileged utilities, such as BACKUP.
OWNER refers to accesses from processes running under the OWNER UIC.
GROUP refers to accesses from processes running under a UIC which matches the [group,] field of the owner.
WORLD encompasses any other access.
Protection controls 4 access types: Read, Write, Execute and Delete.
(Execute is also known as Create when the protection is applied to
a directory or volume.)
Protection is specifed as a 4-tuple in the form
(SYSTEM:RWED,OWNER:RWED,GROUP:RWED,WORLD:RWED)
The group name can be abbreviated to one character.
To specify no access, specify the group name but omit the value.
If the group name is omitted entirely, that group's access is not
modified.
2 FILE_SPECS
A Files-11 file specification is comprised of 5 fields, each of
which is optional. The full form is:
device:[directory]name.type;version
Device is the name of device containing a volume.
Directory is the name of a directory (or "folder") containing
one or more files. Directories are hierarchical; a directory can
contain sub-directories up to a depth of 8 levels. Subdirectories
are delimited by '.'; e.g. [outer.inner.middle] The highest level
directory is called the Master File Directory, or MFD. It has the
name '[000000]', and is implicit.
Name is the name of a file.
Type (or "extension") indicates the type of data in the file (by convention).
Version (or "generation") allows multiple copies of a file with the same
device, directory, name and type to be retained. Version numbers
have a range of 1 through 32767;
Some commands allow groups of files to be refered to with wildcards.
The wildcard '%' matches exactly one character. '*' matches any
number of characters including zero. '...' in a directory matches
'and all lower directories'. Wildcards are not permitted for device names.
Version ';' (no number) means 'the highest generation' for an input file.
For an output file, it means 'the next higher' generation.
When fields are omitted from a file specification, they are replaced
by an application-specific default, or absent that, from the
'default' file specification specified by SET DEFAULT. The latter
can include a device and directory, but no file name, type or version.
Each file specification component is limited to 39 characters.
!
1 VHD_IMAGE_FILES
Virtual Hard Disk (VHD) is a disk image format published by Microsoft as an
"open specification". It is used by many simulators, including SimH.
VHD covers three kinds of disk images:
Fixed - A fixed size disk image
Dynamic - A sparse disk image; space in the container is allocated
as the OS uses it.
Difference - A sparse disk image containing only changes to a Dynamic
image. Also called a "snapshot".
ODS2 can read and write all three VHD formats, which must
have a file type of .vhd (or .VHD) to be recognized.
ODS2 currently only initializes Dynamic disks. Mount can create a
snapshot of a dynamic disk. This can be useful for experimentation
when you might want to roll-back changes.
Note that once a snapshot has been taken of a Dynamic disk, the
original (parent) disk must not be modified, as this would invalidate
the snapshot. You can take snapshots of snapshots.
The vhdtools collection provides a utility that can merge snapshots
into their parent disk. It also supports other maintenance functions.
!

748
extracters/ods2/en_us.msg Normal file
View File

@@ -0,0 +1,748 @@
! All facilities defined here must be listed in the message compiler.
!
! This file defines all the ODS2-specific messages. The message compiler
! (a perl script, not the VMS utility) compiles this into a .h and mdf files for
! ODS2. Note that none of the facility codes chosen are registered with
! DEC :-). Also note that these are all customer facilites; they will not
! conflict with VMS facilities of the same name. Reconstructed messages from
! the VMS facilities are merged with this file when it is compiled.
! The comments in the (auto-generated) ssdef.h explain how to generate
! those sources. Only necessary if you are translating (I18n)...
!
! Copyright (C) 2016, 2022 Timothe Litt - litt at acm .org
!
! Provided as part of the ODS2 utility, originally 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 contributions of the original author and
! subsequent contributors. This is free software; no
! warranty is offered, and while we believe it to be useful,
! you use it at your own risk. This is free software; no
! warranty is offered, and while we believe it to be useful,
! you use it at your own risk.
! ********************************************************************************
.FACILITY ODS2,84
.LITERAL ODS2_OFFSET = ODS2_FACILITY - ^X800
.SEVERITY WARNING
.LITERAL ODS2_NORMAL = (ODS2_OFFSET@16) + SHR_NORMAL + SHR_SUCCESS
.LITERAL ODS2_OPENIN = (ODS2_OFFSET@16) + SHR_OPENIN + SHR_WARN
.SEVERITY SUCCESS
.BASE 200
CONFIRM_ALL </CONFIRM ALL response>
CONFIRM_YES </CONFIRM YES response>
CONFIRM_NO </CONFIRM NO response> /WARNING
CONFIRM_QUIT </CONFIRM QUIT response> /WARNING
EXIT <exiting>
.SEVERITY INFO
.BASE 400
MSGFILE <Message definition file: !AZ> /FAO=1
INVDEF <!AZ does not exist> /FAO=1
HELPFILE <Help library file: !AZ> /FAO=1
HELPFILEVER1 <Version !UL !UL-bit created !AZ> /FAO=3 /IDENT=HELPFILEVER
HELPFILEVER2 <Version !UL !UL/!UL-bit created !AZ> /FAO=4 /IDENT=HELPFILEVER
.SEVERITY WARNING
.BASE 600
FILHDRACC <unable to read file header>
SETCWD <failed to set cwd>
LOCALE <unable to set locale>
.SEVERITY ERROR
.BASE 800
AMBIGUOUS <!AZ '!AZ' is ambiguous> /FAO=2
UNKNOWN <unrecognized !AZ '!AZ'> /FAO=2
NOVALUE <no value allowed for !AZ !AZ> /FAO=2
VALUEREQ <value required for !AZ !AZ> /FAO=2
NOPAREN <value is missng ')' for !AZ '!AZ'> /FAO=2
TOOMANY <too many !AZ specified> /FAO=1
TOOFEW <too few !AZ specified> /FAO=1
MAXIND <maximum indirect command file nesting limit (!UL) exceeded> /FAO=1
UNTERMSTR <unterminated quoted string>
INVNUMBER <!AZ is not a valid number> /FAO=1
NOQUALS <no qualifiers specified>
NOQUALSOK <no qualifiers permitted> /IDENT=NOQUALS
NOPAROK <no parameters permitted>
INCONQUAL <inconsistent use of qualifiers>
BADPRO <invalid syntax for file or directory protection>
BADUIC <invalid syntax for UIC. [group,member] must be numeric>
BADVALUE <invalid value>
OPENIND <failed to open indirect command file !AZ> /FAO=1
NOSHELL <failed to run !AZ> /FAO=1
OSERROR <the last host OS error was: !AZ> /FAO=1
OSERRORNO <the last host OS error was !UL.> /FAO=1 /IDENT=OSERROR
VMSTIME <failed to convert VMS time quadword>
FCS2DV <rename operation failed--different devices specified>
BADORG <unsupported file organization>
ILLDIRWRT <directories may not be written as files>
FILESTRUCT <unsupported file structure level !UL.!UL> /FAO=2
.SEVERITY SEVERE
.BASE 1000
INITIALFAIL <initialization failed>
BADMSGFILE <invalid message file format>
NOMSG <message number !8XL> /FAO_COUNT=1
.END
! ********************************************************************************
.FACILITY COPY,85
.LITERAL COPY_OFFSET = COPY_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
.LITERAL COPY_COPIEDB = (COPY_OFFSET@16) + SHR_COPIEDB + SHR_INFO
.LITERAL COPY_COPIEDR = (COPY_OFFSET@16) + SHR_COPIEDR + SHR_INFO
COPIEDU <!AZ copied to !AZ (!UL byte!%S)> /IDENT=COPIED /FAO=3
CONFIRM <copy !AZ to !AZ? > /FAO=2
COPIED <!UL file(s) copied> /FAO=1
NOFILES <no files found>
DIRNOTCOPIED <!AZ is a directory, not copied> /FAO=1
.SEVERITY WARNING
.BASE 600
.LITERAL COPY_OPENIN = (COPY_OFFSET@16) + SHR_OPENIN + SHR_WARN
PROTERR <failed to set protection for !AZ> /FAO=1
NOMATCH <no local files match !AZ> /FAO=1
.SEVERITY ERROR
.BASE 800
.LITERAL COPY_CLOSEOUT = (COPY_OFFSET@16) + SHR_CLOSEOUT + SHR_ERROR
.LITERAL COPY_OPENIN = (COPY_OFFSET@16) + SHR_OPENIN + SHR_ERROR
.LITERAL COPY_OPENOUT = (COPY_OFFSET@16) + SHR_OPENOUT + SHR_ERROR
.LITERAL COPY_PARSEFAIL = (COPY_OFFSET@16) + SHR_PARSEFAIL + SHR_ERROR
.LITERAL COPY_SEARCHFAIL = (COPY_OFFSET@16) + SHR_SEARCHFAIL + SHR_ERROR
.LITERAL COPY_READERR = (COPY_OFFSET@16) + SHR_READERR + SHR_ERROR
.LITERAL COPY_WRITEERR = (COPY_OFFSET@16) + SHR_WRITEERR + SHR_ERROR
.LITERAL COPY_INVALIDNL = (COPY_OFFSET@16) + SHR_INVALIDNL + SHR_ERROR
.LITERAL COPY_INVALIDVFU = (COPY_OFFSET@16) + SHR_INVALIDVFU + SHR_ERROR
.LITERAL COPY_INVALIDC0 = (COPY_OFFSET@16) + SHR_INVALIDC0 + SHR_ERROR
NONAME <no file name specified for output>
.SEVERITY SEVERE
.BASE 1000
NOMEM <out of memory expanding !AZ> /GAO=1
GLOBABT <read error expanding !AZ> /FAO=1
GLOBERR <unknown error !UL processing !AZ> /FAO=2
.END
! ********************************************************************************
.FACILITY CREATE,86
.LITERAL CREATE_OFFSET = CREATE_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
.LITERAL CREATE_EXISTS = (CREATE_OFFSET@16) + SHR_EXISTS + SHR_INFO
.LITERAL CREATE_CREATED = (CREATE_OFFSET@16) + SHR_CREATED + SHR_INFO
READY <!AZ is open for output. Type lines of text ending with Enter> /FAO=1
TERMEOF <terminate input with !AZ> /FAO=1
.SEVERITY ERROR
.BASE 800
CREDIRFAIL <failed to create directory !AZ> /FAO=1
.LITERAL CREATE_NOTDIR = (CREATE_OFFSET@16) + SHR_NOTDIR + SHR_ERROR
.LITERAL CREATE_CLOSEOUT = (CREATE_OFFSET@16) + SHR_CLOSEOUT + SHR_ERROR
.LITERAL CREATE_INVALIDNL = (CREATE_OFFSET@16) + SHR_INVALIDNL + SHR_ERROR
.LITERAL CREATE_INVALIDVFU = (CREATE_OFFSET@16) + SHR_INVALIDVFU + SHR_ERROR
.LITERAL CREATE_INVALIDC0 = (CREATE_OFFSET@16) + SHR_INVALIDC0 + SHR_ERROR
.END
! ********************************************************************************
.FACILITY DELETE,87
.LITERAL DELETE_OFFSET = DELETE_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
CONFIRM <delete !AZ? > /FAO:1
DELETED <deleted !AZ> /FAO=1
NFILES <!UL files deleted> /FAO=1 /IDENT=DELETED
.SEVERITY WARNING
.BASE 600
.LITERAL DELETE_OPENIN = (DELETE_OFFSET@16) + SHR_OPENIN + SHR_WARN
NOFILES <no files deleted>
NOTDELETED <error deleting !AZ> /FAO=1
DIRNOTEMPTY <directory is not empty>
.SEVERITY ERROR
.BASE 800
.SEVERITY SEVERE
.BASE 1000
.END
! ********************************************************************************
.FACILITY DIFF,88
.LITERAL DIFF_OFFSET = DIFF_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
NODIFF <no differences encountered>
.SEVERITY INFO
.BASE 400
COMPARED <compared !UL record(s)> /FAO=1
.SEVERITY WARNING
.BASE 600
.LITERAL DIFF_OPENIN = (DIFF_OFFSET@16) + SHR_OPENIN + SHR_ERROR
DIFFER <files differ at record !UL>
.END
! ********************************************************************************
.FACILITY DIRECT,89
.LITERAL DIRECT_OFFSET = DIRECT_FACILITY - ^X800
.SEVERITY WARNING
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
DIRHEAD <!/Directory !AZ!/!/> /FAO=1
FULLSIZE <!/Size: !9UL> /FAO=1
GRANDTOT <!/Grand total of !UL directory!%S, !UL file!%S> /FAO=2
FILETOTAL <!/Total of !UL file!%S> /FAO=1
USEDTOT <!UL block!%S> /FAO=1
ALLOCTOT <!UL block!%S> /FAO=1
BOTHSIZE <!UL/!UL block!%S> /FAO=2
OWNER <owner: [!OW,!OW]> /FAO=2
CREATED <created: >
REVISED <revised: >
EXPIRES <expires: >
BACKUP <backup: >
FILEORG <file organization: >
SEQORG <sequential>
RELORG <relative>
IDXORG <indexed>
UNKORG <unknown (!UL)> /FAO=1
FILEATT <!/File attributes: >
ALLOC <allocation: !UL> /FAO=1
EXTEND <, Extend: !UW> /FAO=1
GBC <, Global buffer count: !UW> /FAO=1
VERLIMIT <, Version limit: !UW> /FAO=1
DIRLIMIT <, Default version limit: !UW> /FAO=1
NOVERLIMIT <, No version limit>
NODIRLIMIT <, No default version limit>
CONTIG <, Contiguous>
CONTIGB <, Contiguous best try>
NOBACKUP <, Backups disabled>
DIRECTORY <, Directory file>
WRITEBACK <, Writeback>
READCHECK <, Read verification>
WRITECHECK <, Write verification>
LOCKED <, File locked>
SPOOL <, Spool file>
MARKDEL <, Marked for deletion>
BADBLOCK <, Contains bad block>
EOFPOS <end of file: Block !UL, byte !UW!/> /FAO=2
RECFMT <record format: >
RECUDF <undefined>
RECFIX <fixed length !UW byte records> /FAO=1
RECVAR <variable length, maximum !UW bytes> /FAO=1
RECVFC <VFC, !UB byte header, maximum !UW bytes> /FAO=2
RECSTM <stream>
RECSTMLF <stream-LF>
RECSTMCR <stream-CR>
RECATT <Record attributes: >
RECATT_NONE <none>
RECATT_FTN <!AZFortran carriage control> /FAO=1
RECATT_CR <!AZCarriage return carriage control> /FAO=1
RECATT_PRN <!AZPrint file carriage control> /FAO=1
RECATT_BLK <!AZNon-spanned> /FAO=1
PROT_SYS <File protection: System:>
PROT_OWNER <, Owner:>
PROT_GROUP <, Group:>
PROT_WORLD <, World:>
UIC < [!OW,!OW]> /FAO=2
IDNAME <!/Header filename: !AZ> /FAO=1
EXTNHDR <extension header: !UW, Extension FID (!UL,!UW,!UB)> /FAO=4
HDROFFSETS <ID area offset (words):!UB!/Map area offset: !UB!/ACL area offset: !UB!/Reserved area offset: !UB> /FAO=4
STRUCLEVEL <structure level: !UB.!UB> /FAO=2
MAPSIZE <map area size: !UL, in use: !UL!/Cluster size: !UL!/Highest VBN allocated: !UL> /FAO=4
MAPHIGHWATER <highest VBN written: !UL> /FAO=1
MAPHEADER <!/Retrieval pointers:!/ VBN F Count Start LBN End LBN!/--------- - --------- --------- --------->
MAPFMT0 <format 0: !XW> /FAO=1
MAPENTRY <!9UL !UW !9UL !9UL !9UL> /FAO=5
MAPFREE "!9UL <= First free" /FAO=1
.SEVERITY WARNING
.BASE 600
.LITERAL DIRECT_NOFILES = (DIRECT_OFFSET@16) + SHR_NOFILES + SHR_WARN
.SEVERITY ERROR
.BASE 800
.LITERAL DIRECT_OPENOUT = (DIRECT_OFFSET@16) + SHR_OPENOUT + SHR_ERROR
.SEVERITY SEVERE
.BASE 1000
.END
! ********************************************************************************
.FACILITY DISM,90
.LITERAL DISM_OFFSET = DISM_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
DISMOUNTD <volume !12AD of volume set !12AD dismounted> /FAO=4 /IDENT=DISMOUNTED
DISMOUNTDV <volume !12AD dismounted> /FAO=2 /IDENT=DISMOUNTED
DISMAL <all members of !12AD have been dismounted>
.SEVERITY WARNING
.BASE 600
CANNOTDMT <!12AD cannot be dismounted> /FAO=2
.SEVERITY ERROR
.BASE 800
.SEVERITY SEVERE
.BASE 1000
DEVNOTDISM <device not dismounted>
USERFILES <!SL user file(s) open on volume> /FAO=1
.END
! ********************************************************************************
.FACILITY EXTEND,91
.LITERAL EXTEND_OFFSET = EXTEND_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
NEWSIZE <new allocated size is !UL block!%S> /FAO=1
.SEVERITY ERROR
.BASE 800
CONFLQUAL <can not specify both !AZallocate and !AZtruncate> /FAO=2
.END
! ********************************************************************************
.FACILITY HELP,92
.LITERAL HELP_OFFSET = HELP_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
TERMWID <A minimum terminal window width of !UL is recommended for correct formatting of HELP> /FAO=1
TERMSIZE <Terminal width is !UL, height is !UL> /FAO:2
KEYWORD < keyword, one of the following:>
KEYWORDS < keywords, one or more of the following:>
QUALIFIER < qualifier, one of the following>
QUALIFIERS < qualifiers, one or more of the following>
LIST <list, !AZ> /FAO=1
LISTS <lists, !AZ> /FAO=1
HEAD < Commands are:>
MORE < Additional information:>
EXPLAIN < Type HELP COMMAND or HELP TOPIC for information on any command or topic.!/ Type HELP HELP for information on the help system.>
NOCMDHELP <!AZ: No help available> /FAO=1
NOPARHELP <no parameter '!AZ' found> /FAO=1
PARNOTACT <parameter is not used for this command>
NOPARAMS <!AZ has no parameters> /FAO=1
PARHEADING <!/ Parameters:!/ >
PARNOLIMIT < "*" indicates that a parameter can be used more than once.>
PAREXPLAIN < Type help !AZ PARAMETER for more about each parameter.> /FAO=1
QUALHEAD <qualifiers>
SETVALUE <type 'help set value ITEM' for item details>
SHOWCWD < Current working directory is !AZ> /FAO=1
SHOWDEFQ < Default qualifiers for !AZ command> /FAO=1
SHOWNODEFQ < None set>
SHOWQSTYLE < Qualifier style: !AZ> /FAO=1
SHOWSTATS <Statistics:>
SHOWVERON <Command file verification is on>
SHOWVEROFF <Command file verification is off>
SHOWVERS < !AZ !AZ built !AZ !AZ> /FAO=4
SHOWVERSRL < !AZ !AZ built !AZ !AZ with libedit version !UL.!UL> /FAO=6
SHOWVERSCSI < Direct SCSI access is supported>
SHOWVERNOVHD < VHD format image file support is not configured>
SHOWVERPLATFM < Platform: !AZ> /FAO=1
SHOWVERCOMPLR < Compiler: !AZ, version !AZ> /FAO=2
SHOWVLD < Visual Leak Detector is configured>
SHOWCMDHISTLN <!5UL: !AZ> /FAO=2
SHOWMSGPRINTED <(printed): >
.SEVERITY WARNING
.BASE 600
.SEVERITY ERROR
.BASE 800
OPENHLP <failed to open help file !AZ> /FAO=1
NOHELP <can't locate help topic "!AZ" in !AZ> /FAO=2
HELPFMT <help file !AZ has invalid format or is empty> /FAO=1 /IDENT=NOHELP
HELPLEVEL <help level error at line !UL> /FAO=1
NOTEXT <no text for topic !AZ at line !UL> /FAO=2
NOTEXT2 <no text for topic !AZ> /FAO=1 /IDENT=HELPNOTEXT
SHOWNOCMDHIST <No command history exists>
SETCMDHISTVAL <Command history limit must be greater than zero>
.END
! ********************************************************************************
.FACILITY INIT,93
.LITERAL INIT_OFFSET = INIT_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
CONFIRM_PHY <this will delete all data on the physical device !AZ. Proceed? > /FAO:1 /IDENT=CONFIRM
CONFIRM_VIRT <this will delete all data in !AZ and initialize a !AZ image file. Proceed? > /FAO:2 /IDENT=CONFIRM
START_PHY <initializing !AZ on device !AZ as !AZ> /FAO=3 /IDENT=STARTING
START_VIRT <initializing !AZ on disk image !AZ as !AZ> /FAO=3 /IDENT=STARTNG
VOLINIT <!AZ initialized successfully> /FAO=1
SIZING1 <volume size !UL blocks, cluster size !UL, maximum files !UL> /IDENT=SIZING /FAO=3
SIZING2 <preallocated !UL file headers !UL directory entries> /IDENT=SIZING /FAO=2
PLACED1 <boot block at LBN !UL, HOM blocks at LBNs !UL and !UL> /IDENT=SIZING /FAO=3
PLACED2 < MFD at LBN !UL, index file at LBNs !UL thru !UL> /IDENT=SIZING /FAO=3
MFGBAD <writing manufacturer's bad block index>
SWBAD <writing software bad block descriptor>
.SEVERITY WARNING
.BASE 600
INVOPT <!AZcreate and !AZreplace only apply to disk image files> /FAO=2
.SEVERITY ERROR
.BASE 800
BADVOLLABEL <volume label must be 1-12 alphanumeric charactes>
BADUSERNAME <username must be 1-12 alphanumeric characters>
BADMEDIUM <unknown medium '!AZ'; HELP INITIALIZE for list> /FAO=1
.SEVERITY SEVERE
.BASE 1000
TOOSMALL <device is too small to hold a useful Files-11 volume>
NOHOMLOC <no good block found for primary HOM block>
NOHOM2LOC <no good block found for secondary HOM block> /IDENT=NOHOMLOC
.END
! ********************************************************************************
.FACILITY IO,94
.LITERAL IO_OFFSET = IO_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
STATS <initializations: !UL Reads: !UL Writes: !UL> /FAO=3
LARGEFILE "large files and devices (>2GB) are supported"
NOLARGEFILE "large files and devices (>2GB) are NOT supported"
UNXDEVHDR < Physical devices>
NODEVS <no devices found>
NTDEVHEADER < Physical devices!/ Drv Type Physical Name!/ --- --------- ------------->
NTDEVREMOVABLE < !AZ Removable !AZ> /FAO=2
NTDEVFIXED < !AZ Fixed !AZ> /FAO=2
NTDEVREMOTE < !AZ Network> /FAO=1
NTDEVCDROM < !AZ CDROM !AZ> /FAO=2
NTDEVRAMDISK < !AZ RAMdisk !AZ> /FAO=2
NTDEVOTHER < !AZ Other> /FAO=1
VNODEVS < No virtual devices are assigned>
VDEVHEADER < Virtual devices>
VHDAVAIL <VHD format image files are supported>
VHDNOTAVAIL <VHD format image file support is configured, but not available>
VHDFMTSTART <formatting !AZ> /FAO=1
VHDFMTEND <VHD volume formatting completed>
VMSMOUNT <device !AZ mounted /FOREIGN> /FAO=1
VMSDMT <device !AZ dismounted> /FAO=1
.SEVERITY WARNING
.BASE 600
VHDSAVED <!AZ contains a suspended system and should not be modified> /FAO=1
.SEVERITY ERROR
.BASE 800
NOVHD <VHD disk support is not available in this version>
ISVIRTDEV <!AD is a virtual device> /FAO=2
VIRTDEVINUSE <!AZ is in use by !AZ> /FAO=2
VIRTFILEINUSE <!AZ is in use on virtual drive !AZ> /FAO=2
BADPATH <invalid path: !AZ> /FAO=1
DIRRDERR <error reading directory !AZ> /FAO=1
LOCKVOL <error locking volume on !AZ> /FAO=1
NOGEO <unable to obtain geometry for !AZ> /FAO=1
OPENDEV <error opening !AZ> /FAO=1
READERR <read error at sector !UL> /FAO=1
READLEN <read error at lbn !UL, got !UL, expected !UL> /FAO=3
WRITELEN <read error at lbn !UL, got !UL, expected !UL> /FAO=3
SEEKERR <seek failure at sector !UL> /FAO=1
WRITEERR <write error at sector !UL> /FAO=1
UNXNOTREG <!AZ is not a regular file> /FAO=1
UNXNOTBLK <!AZ is not a block device> /FAO=1
EXISTS <file !AZ already exists, not superseded> /FAO=1
RDBLK2BIG <read from non-existent LBN !UL> /FAO=1 /IDENT=BLK2BIG
WRBLK2BIG <write to non-existent LBN !UL> /FAO=1 /IDENT=BLK2BIG
VHDONLY <!AZ Snapshots can only be taken of VHD format image files> /FAO=1
VHDSNAPFAIL <snapshot of !AZ failed> /FAO=1
VHDMEM <failed to allocate memory for VHD>
VHDCREATEERR <error creating VHD volume !AZ> /FAO=1
VMSDEVSCAN <error scanning devices>
VMSNOMOUNT <unable to mount device !AZ /FOREIGN> /FAO=1
VMSNODMT <unable to dismount device !AZ> /FAO=1
.SEVERITY SEVERE
.BASE 1000
OFFSET_TOO_BIG <Volume is too large for local file system: needs 64-bit I/O>
VHDNOLIB <VHD library !AZ could not be loaded> /FAO=1
VHDNOSYM <symbol !AZ not present in !AZ> /FAO=2
VHDNOTVALID <the VHD library !AZ is not usable> /FAO=1
.END
! ********************************************************************************
.FACILITY MOUNT,95
.LITERAL MOUNT_OFFSET = MOUNT_FACILITY - ^X800
.SEVERITY WARNING
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
MOUNTED <!12AD mounted on !AZ> /FAO=3
SNAPOK <!AZ created from !AZ> /FAO=2
VSMOUNTED <volume set !12AD mounted> /FAO=1
WRITELCK <!AZ can not be written, mounted read-only> /FAO=1
.SEVERITY WARNING
.BASE 600
BADSCB <invalid storage control block on !AZ> /FAO=1
.SEVERITY ERROR
.BASE 800
BADLABEL <label !AZ is too long> /FAO=1
FAILED <mount failed>
HOMBLKCHK <!UL home block software consistency error!%S> /FAO=1
BITMAPSYS <unable to access BITMAP.SYS on !AZ> /FAO=1
BITUPDFAIL <unable to compute disk usage for !AZ> /FAO=1
INCONVOL <volume '!12AD' on !AZ is a member of '!12AD', not a member of '!12AD'> /FAO=7
NOTSAME <you must specify the same number of existing files (!UL) with !AZSNAPSHOT as filenames to create (!UL)> /FAO=3
RVN1NOTMNT <volume 1 of the volume set must be mounted>
VOLOOO <RVN !UL of '!12AD' is '!12AD'. !AZ contains '!AD'> /FAO=8
VOLSETSYS <unable to access VOLSET.SYS on !AZ> /FAO=1
WRONGRVN <device !AZ contains !12AD, which is RVN !UW of !12AD. !UL of !12AD expected> /FAO=9 /IDENT=WRONGVOL
NOTVSMEM <device !AZ contains !12AD, which is not part of a volume set. RVN !UL of !12AD expected> /FAO=6
WRONGVOL <device !AZ contains volume '!12AD', '!12AD' expected> /FAO=5
WRONGVOLCNT <volume set !12AD has !UL members, but !UL specified> /FAO=3
WRONGVOLMEM <volume set name on !AZ is '!12AD', but VOLSET.SYS is for '!12AD'> /FAO=5
.SEVERITY SEVERE
.BASE 1000
.END
! ********************************************************************************
.FACILITY RENAME,96
.LITERAL RENAME_OFFSET = RENAME_FACILITY - ^X800
.SEVERITY SUCCESS
.BASE 200
.SEVERITY INFO
.BASE 400
RENAMED <!AZ renamed to !AZ> /FAO=2
CONFIRM <rename !AZ to !AZ? > /FAO=2
NRENAMED <!UL file(s) renamed> /FAO=1 /IDENT=RENAMED
NOFILES <no files renamed>
.SEVERITY WARNING
.BASE 600
.SEVERITY ERROR
.BASE 800
FAILED <rename !AZ to !AZ failed> /FAO=2
.LITERAL RENAME_PARSEFAIL = (RENAME_OFFSET@16) + SHR_PARSEFAIL + SHR_ERROR
.LITERAL RENAME_SEARCHFAIL = (RENAME_OFFSET@16) + SHR_SEARCHFAIL + SHR_ERROR
.SEVERITY SEVERE
.BASE 1000
.END
! ********************************************************************************
.FACILITY SEARCH,97
.LITERAL SEARCH_OFFSET = SEARCH_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
CONFIRM <search !AZ? > /FAO=1
NOMATCH <no strings matched>
MATCHED <!AZ searched, !UL record!%S, !UL match!%S> /FAO=3
FILE <!AZ searched, !UL record!%S, no matches> /FAO=2
.SEVERITY WARNING
.BASE 600
.LITERAL SEARCH_OPENIN = (SEARCH_OFFSET@16) + SHR_OPENIN + SHR_WARN
.LITERAL SEARCH_NOFILES = (SEARCH_OFFSET@16) + SHR_NOFILES + SHR_WARN
.LITERAL SEARCH_CONTINUE = (SEARCH_OFFSET@16) + SHR_CONTINUE + SHR_INFO
.SEVERITY ERROR
.BASE 800
.LITERAL SEARCH_PARSEFAIL = (SEARCH_OFFSET@16) + SHR_PARSEFAIL + SHR_ERROR
.LITERAL SEARCH_SEARCHFAIL = (SEARCH_OFFSET@16) + SHR_SEARCHFAIL + SHR_ERROR
BADSTRING <search string !UL too short> /FAO=1
.END
! ********************************************************************************
.FACILITY TYPE,98
.LITERAL TYPE_OFFSET = TYPE_FACILITY - ^X800
.SEVERITY INFO
.BASE 400
.LITERAL TYPE_CONTINUE = (TYPE_OFFSET@16) + SHR_CONTINUE + SHR_INFO
.SEVERITY WARNING
.BASE 600
.LITERAL TYPE_OPENIN = (TYPE_OFFSET@16) + SHR_OPENIN + SHR_WARN
.SEVERITY ERROR
.BASE 800
.LITERAL TYPE_PARSEFAIL = (TYPE_OFFSET@16) + SHR_PARSEFAIL + SHR_ERROR
.LITERAL TYPE_SEARCHFAIL = (TYPE_OFFSET@16) + SHR_SEARCHFAIL + SHR_ERROR
.END
! ********************************************************************************
.FACILITY SHR,0 /SHARED
.LITERAL SHR_WARN = 0
.LITERAL SHR_SUCCESS = 1
.LITERAL SHR_ERROR = 2
.LITERAL SHR_INFO = 3
.LITERAL SHR_SEVERE = 4
! Convention shared with DEC:
! All shared messaged defined as WARNING so that user can
! add one of the severity codes above
.SEVERITY WARNING
.BASE 0
NORMAL <normal successful completion>
.BASE 600
CONTINUE " Type <CR> to continue, f<CR> to finish, q<cr> to abort "
CLOSEIN <error closing !AZ as input> /FAO=1
CLOSEOUT <error closing !AZ as output> /FAO=1
COPIEDB <!AZ copied to !AZ (!UL block!%S)> /IDENT=COPIED /FAO=3
COPIEDR <!AZ copied to !AZ (!UL record!%S)> /IDENT=COPIED /FAO=3
CREATED <!AZ created> /FAO=1
EXISTS <!AZ already exists> /FAO=1
INVALIDNL <VFC newline count must be between 1 and 128>
INVALIDVFU <VFU channel must be between 1 an 16>
INVALIDC0 <VFC ASCII control must be between 0 and 31>
NOFILES <no files found>
NOTDIR <!AZ is not a directory> /FAO=1
OPENIN <error opening !AZ as input> /FAO=1
OPENOUT <error opening !AZ for output> /FAO=1
PARSEFAIL <error parsing !AZ> /FAO=1
READERR <error reading !AZ> /FAO=1
SEARCHFAIL <error searching for !AZ> /FAO=1
WRITEERR <error writing !AZ> /FAO=1
.END

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_EXTENDCMD )
@@ -19,32 +22,67 @@
/***************************************************************** doextend() */
static uint32_t alq;
/* more test code... */
#define xtnd_truncate OPT_GENERIC_1
#define xtnd_allocate OPT_GENERIC_2
param_t extendpars[] = { {"ods-2_filespec", REQ, VMSFS, NOPA, "for file on ODS-2 volume."},
{ NULL, 0, 0, NOPA, NULL }
qual_t
extendquals[] = { {"allocate", xtnd_allocate, 0, DV(&alq),
"commands extend qual_allocate"},
{"truncate", xtnd_truncate, 0, NV,
"commands extend qual_truncate"},
{NULL, 0, 0, NV, NULL }
};
param_t
extendpars[] = { {"filespec", REQ, FSPEC, NOPA, "commands extend filespec"},
{NULL, 0, 0, NOPA, NULL}
};
DECL_CMD(extend) {
int sts;
struct FAB fab = cc$rms_fab;
vmscond_t sts;
options_t options;
struct FAB fab;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
fab = cc$rms_fab;
alq = 0;
if( $FAILS(sts = checkquals( &options, 0, extendquals, qualc, qualv )) ) {
return sts;
}
if( !(~options & (xtnd_allocate|xtnd_truncate)) )
return printmsg( EXTEND_CONFLQUAL, 0, qstyle_s, qstyle_s );
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen(fab.fab$l_fna);
fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna);
fab.fab$b_fac = FAB$M_UPD;
sts = sys_open( &fab );
if ( sts & STS$M_SUCCESS ) {
fab.fab$l_alq = 32;
sts = sys_extend(&fab);
sys_close(&fab);
if( options & xtnd_truncate )
fab.fab$l_fop |= FAB$M_TEF;
if( $SUCCESSFUL(sts = sys_open( &fab )) ) {
if( alq ) {
fab.fab$l_alq = alq;
sts = sys_extend(&fab);
}
sys_close( &fab );
fab.fab$l_alq = 0;
if( $SUCCESSFUL(sts) ) {
sts = sys_open( &fab );
sys_close( &fab );
}
}
if ( !( sts & STS$M_SUCCESS ) ) {
printf("%%EXTEND-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
if( $FAILED(sts) ) {
sts = printmsg(sts, 0);
} else {
sts = printmsg( EXTEND_NEWSIZE, 0, fab.fab$l_alq );
}
return sts;
}

View File

@@ -1,14 +1,17 @@
/* Access.h Definitions for file access routines */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
* 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _F11DEF_H
#define _F11DEF_H
@@ -17,53 +20,75 @@
#include "vmstime.h"
#ifndef ODS2_BIG_ENDIAN
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ODS2_BIG_ENDIAN 1
#endif
#else
#define ODS2_BIG_ENDIAN 0
#endif
#elif !defined(__GNUC__) /* GLIB can define some of these with older GCC */
#if defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)
#define ODS2_BIG_ENDIAN 1
#endif
#endif
#endif
#ifdef ODS2_BIG_ENDIAN
#define F11LONG( l ) ( ( (l) & 0x000000ff ) << 24 | \
( (l) & 0x0000ff00 ) << 8 | \
( (l) & 0x00ff0000 ) >> 8 | \
(l) >> 24 )
#define F11WORD( w ) ( ( (w) & 0x00ff ) << 8 | \
(w) >> 8 )
#define F11SWAP( l ) ( ( (l) & 0x00ff0000 ) << 8 | \
( (l) & 0xff000000 ) >> 8 | \
( (l) & 0x000000ff ) << 8 | \
( (l) & 0x0000ff00 ) >> 8 )
#else
#define F11LONG( l ) (l)
#define F11WORD( w ) (w)
#define F11SWAP( l ) ( ( (l) & 0x0000ffff ) << 16 | \
(l) >> 16 )
#define ODS2_BIG_ENDIAN 0
#endif
#else
#define ODS2_BIG_ENDIAN 0
#endif
#endif
typedef uint8_t f11byte;
#if ODS2_BIG_ENDIAN
#define F11LONG( l ) ((f11long)( ( (l) & 0x000000ff ) << 24 | \
( (l) & 0x0000ff00 ) << 8 | \
( (l) & 0x00ff0000 ) >> 8 | \
(l) >> 24 ))
#define F11WORD( w ) ((f11word)( ( (w) & 0x00ff ) << 8 | \
(w) >> 8 ))
#define F11SWAP( l ) ((f11long)( ( (l) & 0x00ff0000 ) << 8 | \
( (l) & 0xff000000 ) >> 8 | \
( (l) & 0x000000ff ) << 8 | \
( (l) & 0x0000ff00 ) >> 8 ))
#else
#define F11LONG( l ) ((f11long)(l))
#define F11WORD( w ) ((f11word)(w))
#define F11SWAP( l ) ((f11long)( ( (l) & 0x0000ffff ) << 16 | \
(l) >> 16 ))
#endif
typedef uint8_t f11byte;
typedef uint16_t f11word;
typedef uint32_t f11swap;
typedef uint32_t f11long;
#define FH2$M_WASCONTIG 0x00001
#define FH2$M_NOBACKUP 0x00002
#define FH2$M_WRITEBACK 0x00004
#define FH2$M_READCHECK 0x00008
#define FH2$M_WRITECHECK 0x00010
#define FH2$M_CONTIGB 0x00020
#define FH2$M_LOCKED 0x00040
#define FH2$M_CONTIG 0x00080
#define FH2$M_DIRECTORY 0x02000
#define FH2$M_MARKDEL 0x08000
#define FH2$M_ERASE 0x20000
#define FH2$M_BADACL 0x000800
#define FH2$M_SPOOL 0x001000
#define FH2$M_DIRECTORY 0x002000
#define FH2$M_BADBLOCK 0x004000
#define FH2$M_MARKDEL 0x008000
#define FH2$M_NOCHARGE 0x010000
#define FH2$M_ERASE 0x020000
#define FH2$M_NOMOVE 0x200000
#ifdef __ALPHA
#pragma member_alignment save
#pragma nomember_alignment
#endif
#ifdef __GNUC__
#pragma pack(push,1)
#endif
struct UIC {
f11word uic$w_mem;
f11word uic$w_grp;
@@ -75,6 +100,48 @@ struct fiddef {
f11byte fid$b_rvn;
f11byte fid$b_nmx;
};
#define NULL_FID(fidadr) ((fidadr)->fid$w_num == 0 && \
(fidadr)->fid$w_seq == 0 && \
(fidadr)->fid$b_rvn ==0 && \
(fidadr)->fid$b_nmx == 0 )
#define FID_MATCH(fid1,fid2,rvn) ((fid1)->fid$w_num == (fid2)->fid$w_num && \
(fid1)->fid$w_seq == (fid2)->fid$w_seq && \
((fid1)->fid$b_rvn? (fid1)->fid$b_rvn: rvn) == \
((fid2)->fid$b_rvn? (fid2)->fid$b_rvn: rvn) && \
(fid1)->fid$b_nmx == (fid1)->fid$b_nmx )
#define FID$C_INDEXF 1
#define FID$C_BITMAP 2
#define FID$C_BADBLK 3
#define FID$C_MFD 4
#define FID$C_CORIMG 5
#define FID$C_VOLSET 6
#define FID$C_CONTIN 7
#define FID$C_BACKUP 8
#define FID$C_BADLOG 9
#define FID$C_FREFIL 10
#define FID$C_MAXRES 10
#define prot$m_system 0x000F
#define prot$v_system 0
#define prot$m_owner 0x00F0
#define prot$v_owner 4
#define prot$m_group 0x0F00
#define prot$v_group 8
#define prot$m_world 0xF000
#define prot$v_world 12
#define prot$m_noread 0x1
#define prot$m_nowrite 0x2
#define prot$m_noexe 0x4
#define prot$m_nodel 0x8
#define prot$m_none (prot$m_noread|prot$m_nowrite|prot$m_noexe|prot$m_nodel)
#define prot$m_norestrict 0x0
#define SETPROT( sys, own, grp, wld ) \
( ((sys) << prot$v_system) | ((own) << prot$v_owner) | \
((grp) << prot$v_group) | ((wld) << prot$v_world) )
struct RECATTR {
f11byte fat$b_rtype;
@@ -166,12 +233,32 @@ struct HEAD {
f11byte fh2$b_ru_active;
f11word fh2$w_reserved2;
f11long fh2$l_highwater;
#define FH2$C_LENGTH 80 /* (offsetof( struct HEAD, fh2$l_highwater) +
sizeof( f11long ))
*/
f11byte fh2$b_reserved3[8];
f11byte fh2$r_class_prot[20];
f11byte fh2$r_restofit[402];
struct fh2$r_class_prot {
f11byte cls$b_secur_lev;
f11byte cls$b_integ_lev;
f11word reserved4;
f11byte cls$q_secur_cat[8];
f11byte cls$q_integ_cat[8];
} fh2$r_class_prot;
f11byte fh2$r_vardata[402];
f11word fh2$w_checksum;
};
#define STRUCLEV (0x0201)
#define FM2$M_FORMAT1 (1 << 14)
#define FM2$M_FORMAT2 (2 << 14)
#define FM2$M_FORMAT3 (3 << 14)
#define FM2$C_FMT1_MAXLBN ((1 << 22) - 1)
#define FM2$C_FMT1_MAXCNT (256)
#define FM2$C_FMT2_MAXLBN (0xFFFFFFFF)
#define FM2$C_FMT2_MAXCNT (1 << 14)
#define FM2$C_FMT3_MAXLBN (0xFFFFFFFF)
#define FM2$C_FMT3_MAXCNT (1 << 30)
struct SCB {
f11word scb$w_struclev;
f11word scb$w_cluster;
@@ -209,6 +296,9 @@ struct dir$r_ent {
struct fiddef dir$w_fid;
};
#ifdef __GNUC__
#pragma pack(pop)
#endif
#ifdef __ALPHA
#pragma member_alignment restore

View File

@@ -1,14 +1,17 @@
/* Fibdef.h Definition of 'struct fibdef' */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
* 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _FIBDEF_H
#define _FIBDEF_H

View File

@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5AC343A4-5F8B-47F1-982B-7E44B3208748}</ProjectGuid>
<RootNamespace>genmsgen</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<CustomBuildAfterTargets>Link</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<CustomBuildBeforeTargets>
</CustomBuildBeforeTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<CustomBuildBeforeTargets>
</CustomBuildBeforeTargets>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<PreBuildEvent>
<Command>del $(SolutionDir)$(TargetName)$(TargetExt) &gt;nil-en.bak 2&gt;&amp;1 || exit /b 0</Command>
</PreBuildEvent>
<CustomBuildStep>
<Command>
</Command>
<Message>
</Message>
<Outputs>
</Outputs>
<Inputs>
</Inputs>
</CustomBuildStep>
<Link>
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<PreBuildEvent>
<Command>del $(SolutionDir)$(TargetName)$(TargetExt) &gt;nil-en.bak 2&gt;&amp;1 || exit /b 0</Command>
</PreBuildEvent>
<CustomBuildStep>
<Command>
</Command>
<Message>
</Message>
<Outputs>
</Outputs>
<Inputs>
</Inputs>
</CustomBuildStep>
<Link>
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)$(TargetExt) </Command>
<Outputs>$(SolutionDir)$(TargetName)$(TargetExt)</Outputs>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<CustomBuildStep>
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)$(TargetExt) </Command>
<Message>Copying $(TargetName)$(TargetExt)</Message>
<Outputs>$(SolutionDir)$(TargetName)$(TargetExt)</Outputs>
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\genmsg.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sysmsg.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

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

363
extracters/ods2/genmsg.c Normal file
View File

@@ -0,0 +1,363 @@
/* Timothe Litt March 2016
* Copyright (C) 2016 Timothe litt
* litt at acm dot org
*
* Free for use with the ODS2 package. All other rights reserved.
*/
/*
* This is distributed as part of ODS2, originally 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* Write a message data file.
*
* Update/translate messages in cc.msg (en_us.msg)
* The makefiles handle this:
*
* message -bt vms_messages.msg en_us.msg en_us.mt
* cc genmsg '-DTABLEFILE="en_us.mt"' -o genmsg
* genmsg en_us.mdf
* rm -f genmsg
* ods2 set message en_us
*
* For translations:
* message -br vms_messages_fr.msg fr_ca.msg fr_ca.mt
* cc genmsg '-DTABLEFILE="fr_ca.mt"' -o genmsg
* genmsg fr_ca.mdf
* rm -f genmsg
* ods2 set message fr_ca
*/
#ifndef TABLEFILE
#define TABLEFILE "default.md"
#endif
#define _XOPEN_SOURCE
#ifdef _MSC_VER /* fopen*/
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#define SYSMSG_INTERNAL
#include "sysmsg.h"
#include "ssdef.h"
#include "stsdef.h"
static const char
hdrrec[] = { MSG_HEADER_REC },
facrec[] = { MSG_FAC_REC },
msgrec[] = { MSG_MSG_REC },
summary1[] = { "%s: %"PRIu32 " facilities, %"PRIu32 " messages" },
summary2[] = { ", file size %"PRIuMAX " writtten to " };
static const char facdatafmt[] = { "{ \"%s\", UINT32_C(%"PRIu32")},\n" };
static const char msgdatafmt[] = { "{ \"%s\", \"%s\", UINT32_C(0x%08"PRIX32"), UINT32_C(%"PRIu32") },\n" };
/* For portability of .mdf files, need fixed length encodings for host-specific
* format descriptors... This re-encodes them without source changes:
*/
#undef PRIo8
#undef PRIo16
#undef PRIo32
#undef PRIo64
#define PRIo8 "\001A"
#define PRIo16 "\001B"
#define PRIo32 "\001C"
#define PRIo64 "\001D"
#undef PRIu8
#undef PRIu16
#undef PRIu32
#undef PRIu64
#define PRIu8 "\001E"
#define PRIu16 "\001F"
#define PRIu32 "\001G"
#define PRIu64 "\001H"
#undef PRIX8
#undef PRIX16
#undef PRIX32
#undef PRIX64
#define PRIX8 "\001I"
#define PRIX16 "\001J"
#define PRIX32 "\001K"
#define PRIX64 "\001L"
#undef PRId8
#undef PRId16
#undef PRId32
#undef PRId64
#define PRId8 "\001M"
#define PRId16 "\001N"
#define PRId32 "\001O"
#define PRId64 "\001P"
/* Instantiate the tables from ssdef.h (whatever language; it's essentially an object file)
*/
static
struct VMSFAC fac2text[] = {
#define GENERATE_FACTAB
#include TABLEFILE
};
static
struct VMSMSG vms2text[] = {
#define GENERATE_MSGTAB
#include TABLEFILE
};
static void putbyte( char c, size_t idx, char **buf, size_t *size );
/******************************************************************* main() */
int main( int argc, char **argv ) {
struct VMSFAC *fp;
struct VMSMSG *mp;
FILE *ofp;
int ac, quiet = 0, help = 0, newh = 0;
char **av, *pname, *outname = NULL;
ac = argc; av = argv;
pname = argv[0];
if( argc <= 1 ) help = 1;
for( ; argc > 1; --argc, ++argv ) {
if( !strcmp( argv[1], "--" ) ) break;
if( *argv[1] == '-' && argv[1][1] ) {
char *p;
for( p = argv[1]+1; *p; p++ ) {
switch( *p ) {
case 'h':
help = 1;
break;
case 'd':
newh = 1;
break;
case 'q':
quiet = 1;
break;
default:
fprintf( stderr, "Unknown option %c\n", argv[1][1] );
exit( EXIT_FAILURE );
}
}
} else {
break;
}
}
if( help ) {
fprintf( stderr, "%s - Generate ODS2 message file\n\n"
" Options: -q -- suppress informational messages\n"
" -d -- generate a data file for built-in table\n"
"./message -bt vms_messages.msg ods2_en.msg en_us.mt\n"
"cc genmsg '-DTABLEFILE=\"en_us.mt\"'\n"
"./genmsg en_us.mdf\n"
"./ods2 set message en_us\n"
" ./genmsg -d default.md\n", pname
);
exit( EXIT_SUCCESS );
}
if( argc > 1 ) {
if( strcmp( argv[1], "-" ) ) {
outname = argv[1];
}
--argc; ++argv;
}
qsort( fac2text, (uint32_t)(sizeof(fac2text)/sizeof(fac2text[0]))-1,
sizeof(fac2text[0]), &faccmp );
qsort( vms2text, (uint32_t)(sizeof(vms2text)/sizeof(vms2text[0])),
sizeof(vms2text[0]), &msgcmp );
if( outname == NULL )
ofp = stdout;
else if( (ofp = fopen( outname, "wb" )) == NULL ) {
perror( outname );
exit( EXIT_FAILURE );
}
if( !quiet ) {
fprintf( stderr, summary1, TABLEFILE,
(uint32_t)(sizeof(fac2text)/sizeof(fac2text[0])) -1,
(uint32_t)(sizeof(vms2text)/sizeof(vms2text[0])) );
}
if( newh ) { /* Generate a new .h file for built-in defaults */
size_t i, bufsize = 80;
char *buf = NULL;
fprintf( ofp,
"/* This is an automatically-generated file.\n"
" * Command:" );
for( ; ac > 0; --ac, ++av )
fprintf( ofp, " %s", *av );
fprintf( ofp,
"\n"
" * Compiled-in version of a message table\n"
" * This technlology was developed by Timothe Litt, and is\n"
" * free to use with the ODS2 package, originally developed by\n"
" * Paul Nankervis <Paulnank@au1.ibm.com>.\n"
" * ODS2 may be freely distributed within the VMS community\n"
" * providing that the contributions of the original author and\n"
" * subsequent contributors are acknowledged in the help text and\n"
" * source files. This is free software; no warranty is offered,\n"
" * and while we believe it to be useful, you use it at your own risk.\n"
" */\n\n" );
fprintf( ofp,
"#ifdef GENERATE_FACTAB\n"
"#undef GENERATE_FACTAB\n" );
for( i = 0; i < (uint32_t)(sizeof(fac2text)/sizeof(fac2text[0]))-1; i++ ) {
fprintf( ofp, facdatafmt, fac2text[i].text, fac2text[i].code );
}
fprintf( ofp,
"#endif\n"
"#ifdef GENERATE_MSGTAB\n"
"#undef GENERATE_MSGTAB\n" );
for( i = 0; i < (uint32_t)(sizeof(vms2text)/sizeof(vms2text[0])); i++ ) {
char *p;
size_t idx;
p = vms2text[i].text;
for( idx = 0; *p; p++ ) {
char c = *p;
switch( c ) {
case '"':
case '\\':
putbyte( '\\', idx++, &buf, &bufsize );
break;
case '\n':
putbyte( '\\', idx++, &buf, &bufsize );
c = 'n';
break;
case '\001': {
const char *xpn;
putbyte( '"', idx++, &buf, &bufsize );
c = *++p;
xpn = prisym[ c - PRI_CODEBASE ];
while( *xpn ) {
putbyte( *xpn++, idx++, &buf, &bufsize );
}
putbyte( '"', idx++, &buf, &bufsize );
continue;
}
default:
break;
}
putbyte( c, idx++, &buf, &bufsize );
}
putbyte( '\0', idx++, &buf, &bufsize );
fprintf( ofp, msgdatafmt,
vms2text[i].ident, buf,
vms2text[i].code, vms2text[i].nargs );
}
fprintf( ofp,
"#endif\n" );
if( ofp != stdout )
fclose( ofp );
if( !quiet ) {
if( ofp == stdout )
fputc( '\n', stderr );
else
fprintf( stderr, ", written to %s\n", outname );
}
exit( EXIT_SUCCESS );
}
/* File header record. Version + number of facilities + number of message definitions
*/
fprintf( ofp, hdrrec,
(uint32_t)(sizeof(fac2text)/sizeof(fac2text[0])) -1,
(uint32_t)(sizeof(vms2text)/sizeof(vms2text[0])) );
fputc( '\0', ofp );
/* Output each facility with its associated string.
* Always produce an end-marker for the string.
*/
for( fp = fac2text; fp < fac2text + sizeof(fac2text)/sizeof(fac2text[0]) -1; fp++ ) {
fprintf( ofp, facrec, fp->code );
if( fp->text )
fprintf( ofp, "%s", fp->text );
fputc( '\0', ofp );
}
/* Same for each message definition, but two strings.
*/
for( mp = vms2text; mp < vms2text + sizeof(vms2text)/sizeof(vms2text[0]); mp++ ) {
fprintf( ofp, msgrec,
mp->code, mp->nargs );
if( mp->ident )
fprintf( ofp, "%s", mp->ident );
fputc( '\0', ofp );
if( mp->text )
fprintf( ofp, "%s", mp->text );
fputc( '\0', ofp );
}
/* wrap up */
fprintf( ofp, MSG_EOF_REC );
fputc( '\0', ofp );
if( ferror(ofp) ) {
perror( "write" );
exit( EXIT_FAILURE );
}
if( !quiet && ofp != stdout )
fprintf( stderr, summary2, (uintmax_t)ftell(ofp) );
if( ofp != stdout )
fclose( ofp );
if( !quiet ) {
if( ofp == stdout )
fputc( '\n', stderr );
else
fprintf( stderr, "%s\n", outname );
}
exit( EXIT_SUCCESS );
}
static void putbyte( char c, size_t idx, char **buf, size_t *size ) {
if( *buf == NULL || idx+1 > *size ) {
*buf = realloc( *buf, *size += 32 );
if( *buf == NULL ) {
perror( "realloc" );
exit( EXIT_FAILURE );
}
}
buf[0][idx++] = c;
return;
}

18
extracters/ods2/grind Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
# Run ods2 with listed arguments
PROG=./ods2
#
# Save valgrind output in grind.txt~ for analysis
# Display full output on TTY
# Merge rules in suppress.txt~ with output, creating newsuppress.txt~
touch suppress.txt~
valgrind --gen-suppressions=all \
--show-leak-kinds=all \
--leak-check=full \
--num-callers=30 \
$PROG "$@" \
3>&1 1>&2 2>&3 | tee /dev/stderr grind.txt~ | \
grindmerge -f suppress.txt~ >newsuppress.txt~

File diff suppressed because it is too large Load Diff

View File

@@ -1,119 +0,0 @@
/* 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.
*/
#if !defined( DEBUG ) && defined( DEBUG_IMPORTCMD )
#define DEBUG DEBUG_IMPORTCMD
#else
#ifndef DEBUG
#define DEBUG 0
#endif
#endif
#include "cmddef.h"
/***************************************************************** doimport() */
#define import_binary OPT_GENERIC_1
#define import_log OPT_GENERIC_2
qual_t importquals[] = { {"ascii", 0, import_binary, NV,
"Transfer file in ascii mode (default)"},
{"binary", import_binary, 0, NV, "Transfer file in binary mode", },
{NULL, 0, 0, NV, NULL}
};
param_t importpars[] = { {"from_filespec", REQ, LCLFS, NOPA, "for source file."},
{"to_filespec", REQ, VMSFS, NOPA, "for destination file."},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(import) {
int options;
unsigned sts;
char *name;
FILE *fromf;
struct FAB fab = cc$rms_fab;
struct RAB rab = cc$rms_rab;
UNUSED(argc);
options = checkquals( 0, importquals, qualc, qualv );
if( options == -1 )
return SS$_BADPARAM;
sts = SS$_BADFILENAME;
name = argv[1]; /*unquote( argv[1] );*/
if ( *name == '\0' ) {
return sts;
}
fromf = openf( name, (options & import_binary)? "rb": "r" );
if( fromf == NULL ) {
printf( "%%ODS2-E-OPENERR, Can't open %s\n", name );
perror( " - " );
return sts;
}
fab.fab$b_fac = FAB$M_PUT;
fab.fab$l_fop = FAB$M_OFP | FAB$M_TEF;
fab.fab$b_org = FAB$C_SEQ;
if( options & import_binary ) {
fab.fab$w_mrs = 512;
fab.fab$b_rfm = FAB$C_FIX;
} else {
fab.fab$b_rat = 0;
fab.fab$b_rfm = FAB$C_STM;
}
fab.fab$l_fna = argv[2];
fab.fab$b_fns = strlen( fab.fab$l_fna );
sts = sys_create( &fab );
if ( sts & STS$M_SUCCESS ) {
rab.rab$l_fab = &fab;
sts = sys_connect( &rab );
if ( sts & STS$M_SUCCESS ) {
if( options & import_binary ) {
char *buf;
size_t len;
if( (buf = malloc( 512 )) == NULL )
sts = SS$_INSFMEM;
else {
rab.rab$l_rbf = buf;
while( (len = fread( buf, 1, 512, fromf )) > 0 ) {
if( len != 512 )
memset( buf + len, 0, 512 - len );
rab.rab$w_rsz = len;
sts = sys_put( &rab );
if( !(sts & STS$M_SUCCESS) ) {
break;
}
}
free( buf );
buf = NULL;
}
} else {
while ( (rab.rab$l_rbf = fgetline( fromf, TRUE )) != NULL ) {
rab.rab$w_rsz = strlen( rab.rab$l_rbf );
sts = sys_put( &rab );
free( rab.rab$l_rbf );
if ( !( sts & STS$M_SUCCESS ) ) {
break;
}
}
}
sys_disconnect( &rab );
}
sys_close( &fab );
}
fclose( fromf );
if ( !(sts & STS$M_SUCCESS) ) {
printf("%%IMPORT-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}

View File

@@ -1,10 +1,15 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_INITIALCMD )
@@ -15,6 +20,7 @@
#endif
#endif
#include "compat.h"
#include "cmddef.h"
#include "access.h"
@@ -26,76 +32,127 @@
static struct NEWVOL initpars;
#define init_beg OPT_GENERIC_1
#define init_mid OPT_GENERIC_2
#define init_blk OPT_GENERIC_3
#define init_mount OPT_GENERIC_4
#define init_beg OPT_GENERIC_1
#define init_mid OPT_GENERIC_2
#define init_blk OPT_GENERIC_3
#define init_mount OPT_GENERIC_4
#define init_disp OPT_GENERIC_5
#define init_confirm OPT_GENERIC_6
#define init_uic OPT_GENERIC_7
#define init_dtype OPT_GENERIC_8
qual_t idxkwds[] = { {"beginning", init_beg, init_mid|init_blk, NV,
"Place index file in lowest available LBNs"},
{"block", init_blk, init_beg|init_mid, DV(&initpars.indexlbn),
"Place index file near specific LBN"},
{"middle", init_mid, init_beg|init_blk, NV,
"Place index file near middle of volume (default)"},
{NULL, 0, 0, NV, NULL}
};
static qual_t
idxkwds[] =
{ {"beginning", init_beg, init_mid|init_blk, NV,
"commands initialize qual_index begin"},
{"block", init_blk, init_beg|init_mid, DV(&initpars.indexlbn),
"commands initialize qual_index block"},
{"middle", init_mid, init_beg|init_blk, NV,
"commands initialize qual_index middle"},
{NULL, 0, 0, NV, NULL}
};
qual_t iniquals[] = { {DT_NAME, 0, MOU_DEVTYPE, CV(NULL), "Drive type (DEC model name) "},
{"cluster_size", 0, 0, DV(&initpars.clustersize),
"Cluster size (blocks)" },
{"create", PHY_CREATE|MOU_VIRTUAL, 0, NV, "Create a new image file" },
{"directories", 0, 0, DV(&initpars.directories),
"Directory entries to pre-allocate" },
{"headers", 0, 0, DV(&initpars.headers),
"File headers to pre-allocate" },
{"index", 0, init_beg|init_mid|init_blk, KV(idxkwds),
"Index file placement hint"},
{"image", PHY_CREATE|MOU_VIRTUAL, 0, NV,
"Initialize a disk image file", },
{"log", MOU_LOG, 0, NV, "-Show progress"},
{"nolog", 0, MOU_LOG, NV, NULL},
{"replace", MOU_VIRTUAL, PHY_CREATE, NV,
"Replace filesystem in existing image file" },
{"mount", init_mount, 0, NV, "-Mount volume after initializing it"},
{"nomount", 0, init_mount, NV, NULL },
{"virtual", PHY_CREATE|MOU_VIRTUAL, 0, NV, NULL, },
{"maximum_files", 0, 0, DV(&initpars.maxfiles),
"Maximum number of files volume can (ever) contain" },
{"owner_uic", 0, 0, SV(&initpars.useruic),
"Volume owner's UIC, default [1,1]"},
{"user_name", 0, 0, SV(&initpars.username),
"Volume owner's username, default yours"},
{NULL, 0, 0, NV, NULL } };
qual_t
iniquals[] =
{ {DT_NAME, 0, MOU_DEVTYPE, CV(NULL),
"commands initialize qual_media"},
{"bootblock", 0, 0, DV(&initpars.bootlbn),
"commands initialize qual_bootblock"},
{"cluster_size", 0, 0, DV(&initpars.clustersize),
"commands initialize qual_clustersize" },
{"confirm", init_confirm, 0, NV,
"-commands initialize qual_confirm"},
{"noconfirm", 0, init_confirm,
NV, NULL},
{"create", init_disp|PHY_CREATE,
0, NV,
"commands initialize qual_create" },
{"directories", 0, 0, DV(&initpars.directories),
"commands initialize qual_directories" },
{"file_protection", 0, 0, PV(&initpars.fileprot),
"commands initialize qual_fileprot"},
{"headers", 0, 0, DV(&initpars.headers),
"commands initialize qual_headers" },
{"extension", 0, 0, DV(&initpars.extension),
"commands initialize qual_extension" },
{"windows", 0, 0, DV(&initpars.windows),
"commands initialize qual_windows" },
{"index", 0, init_beg|init_mid|init_blk, KV(idxkwds),
"commands initialize qual_index"},
{"image", init_dtype | MOU_VIRTUAL,
0, NV,
"commands initialize qual_image", },
{"device", init_dtype, MOU_VIRTUAL, NV,
"commands initialize qual_device", },
{"log", MOU_LOG, 0, NV, "-commands initialize qual_log"},
{"nolog", 0, MOU_LOG, NV, NULL},
{"replace", init_disp, PHY_CREATE,
NV,
"commands initialize qual_replace" },
{"mount", init_mount, 0, NV,
"-commands initialize qual_mount"},
{"nomount", 0, init_mount, NV, NULL },
{"virtual", init_dtype | MOU_VIRTUAL, 0, NV, NULL, },
{"maximum_files", 0, 0, DV(&initpars.maxfiles),
"commands initialize qual_maxfiles" },
{"owner_uic", init_uic, 0, UV(&initpars.useruic),
"commands initialize qual_owneruic"},
{"protection", 0, 0, PV(&initpars.volprot),
"commands initialize qual_protection"},
{"user_name", 0, 0, SV(&initpars.username),
"commands initialize qual_username"},
param_t inipars[] = { {"device", REQ, LCLFS, NOPA,
"for device or disk image to be initialized.\n "
"ALL EXISTING DATA WILL BE LOST."
},
{"labels", REQ, LCLFS, NOPA, "volume label for new volume" },
{ NULL, 0, 0, NOPA, NULL }
};
{ NULL, 0, 0, NV, NULL }
};
param_t
inipars[] =
{ {"device", REQ, FSPEC, NOPA, "commands initialize devspec" },
{"labels", REQ, STRING, NOPA, "commands initialize volspec" },
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(initial) {
int sts = SS$_NORMAL;
vmscond_t sts = SS$_NORMAL;
options_t options;
char *devname = NULL;
size_t len;
struct DEV *dev;
int options;
UNUSED(argc);
devname = argv[1];
options = checkquals( PHY_CREATE | init_mid | init_mount, iniquals, qualc, qualv );
do {
memset( &initpars, 0, sizeof( initpars ) );
initpars.extension = 5;
initpars.windows = 7;
if( options == -1 ) {
sts = SS$_BADPARAM;
sts = checkquals( &options, init_confirm | init_mid | init_mount,
iniquals, qualc, qualv );
do {
size_t len;
struct DEV *dev;
char *p;
if( $FAILED( sts ) ) {
break;
}
options |= MOU_WRITE;
if( !(options & MOU_VIRTUAL) )
options &= ~PHY_CREATE;
if( !(options & init_dtype) && (p = strchr( devname, '.' )) ) {
len = strlen( p+1 );
if( len >= 1 && len == strspn( p+1, "0123456789" ".;-_"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" ) )
options |= MOU_VIRTUAL;
}
if( options & MOU_VIRTUAL ) {
if( !(options & init_disp) ) /* Disposition (/create/replace)? */
options |= PHY_CREATE;
} else {
if( options & init_disp ) {
printmsg( INIT_INVOPT, 0, qstyle_s, qstyle_s );
}
}
if( options & init_mid )
initpars.indexlbn = INIT_INDEX_MIDDLE;
@@ -104,24 +161,30 @@ DECL_CMD(initial) {
if( (options & init_blk) && initpars.indexlbn == INIT_INDEX_MIDDLE )
initpars.indexlbn--;
initpars.options = 0;
if( options & MOU_LOG )
initpars.options |= INIT_LOG;
if( options & MOU_VIRTUAL )
initpars.options |= INIT_VIRTUAL;
if( options & init_uic )
initpars.options |= INIT_OWNUIC;
initpars.devtype = disktype[(options & MOU_DEVTYPE) >> MOU_V_DEVTYPE].name;
len = strlen( argv[2] );
if( len > 12 || !*argv[2] ||
strspn( argv[2], VOL_ALPHABET ) != len ) {
printf( "Volume label must be between 1 and 12 alphanumeric characters long\n" );
sts = SS$_BADPARAM;
sts = printmsg( INIT_BADVOLLABEL, 0 );
break;
}
initpars.label = argv[2];
if( !((sts = virt_open( &devname, options, &dev )) & STS$M_SUCCESS) )
if( (options & init_confirm) &&
$FAILS(sts = confirm_cmd( (options & MOU_VIRTUAL)?
INIT_CONFIRM_VIRT: INIT_CONFIRM_PHY,
devname, initpars.devtype )) )
break;
if( $FAILS(sts = virt_open( &devname, options, &dev )) )
break;
if( !(dev->access & MOU_WRITE) ) {
@@ -130,11 +193,11 @@ DECL_CMD(initial) {
break;
}
initpars.devnam = devname;
if( !((sts = initvol( dev, &initpars )) & STS$M_SUCCESS) ) {
if( $FAILS(sts = initvol( dev, &initpars )) ) {
virt_close( dev );
break;
}
if( !((sts = virt_close( dev )) & STS$M_SUCCESS) )
if( $FAILS(sts = virt_close( dev )) )
break;
if( options & init_mount ) {
@@ -143,18 +206,15 @@ DECL_CMD(initial) {
}
} while( 0 );
initpars.username =
initpars.useruic = NULL;
if( sts & STS$M_SUCCESS )
if( $SUCCESSFUL( sts ) )
return sts;
printf( "%%ODS2-E-FAILED, Initialize failed: %s\n", getmsg( sts, MSG_TEXT ) );
sts = printmsg( sts, 0 );
if( (options & (MOU_VIRTUAL|PHY_CREATE)) == (MOU_VIRTUAL|PHY_CREATE) &&
!( (sts & STS$M_COND_ID) == (SS$_DUPFILENAME & STS$M_COND_ID) ||
(sts & STS$M_COND_ID) == (SS$_IVDEVNAM & STS$M_COND_ID) ) ) {
(void) unlink( argv[1] );
!( $MATCHCOND(sts, SS$_DUPFILENAME) ||
$MATCHCOND(sts, SS$_IVDEVNAM) ) ) {
(void) Unlink( argv[1] );
}
return sts;

File diff suppressed because it is too large Load Diff

View File

@@ -12,30 +12,42 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _INITVOL_H
#define _INITVOL_H
#include <stdint.h>
#include "ods2.h"
struct NEWVOL {
const char *label;
const char *devtype;
const char *devnam;
const char *username;
const char *useruic;
uint32_t useruic;
unsigned options;
unsigned clustersize;
unsigned maxfiles;
unsigned headers;
unsigned indexlbn;
unsigned directories;
uint32_t clustersize;
uint32_t maxfiles;
uint32_t headers;
uint32_t indexlbn;
uint32_t directories;
uint32_t bootlbn;
uint32_t volprot;
uint32_t fileprot;
uint32_t extension;
uint32_t windows;
};
#define INIT_INDEX_MIDDLE (~0U)
#define INIT_LOG (1 << 0)
#define INIT_VIRTUAL (1 << 1)
#define INIT_LOG (1 << 0)
#define INIT_VIRTUAL (1 << 1)
#define INIT_OWNUIC (1 << 2)
#define INIT_VOLPROT (1 << 3)
#define INIT_FILEPROT (1 << 4)
#define VOL_ALPHABET "abcdefghijklmnopqrstuvwxyz$-_" \
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
@@ -78,7 +90,10 @@ struct SWBAD {
#pragma member_alignment restore
#endif
unsigned initvol( void *dev, struct NEWVOL *params );
unsigned int delta_from_index( size_t index );
vmscond_t initvol( void *dev, struct NEWVOL *params );
uint32_t delta_from_index( size_t index );
vmscond_t addmappointers( struct HEAD *fhd,
uint32_t *start, uint32_t *n, int sparse );
#endif

View File

@@ -1,123 +1,132 @@
# DO NOT DELETE
ods2.o: version.h cmddef.h
ods2.o: version.h
ods2.o: cmddef.h
ods2.o: compat.h
ods2.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
ods2.o: stsdef.h sysmsg.h cache.h phyvirt.h
ods2.o: ods2.h
ods2.o: rms.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h
ods2.o: cache.h phyvirt.h
access.o: ssdef.h access.h
access.o: cache.h f11def.h
access.o: vmstime.h descrip.h stsdef.h device.h phyio.h initvol.h ods2.h
access.o: phyvirt.h compat.h
access.o: sysmsg.h
cache.o: cache.h ods2.h ssdef.h
access.o: ods2.h
access.o: cache.h f11def.h vmstime.h
access.o: descrip.h stsdef.h device.h phyio.h initvol.h phyvirt.h compat.h
access.o: sysmsg.h
cache.o: cache.h
cache.o: ods2.h
cache.o: ssdef.h
compat.o: compat.h
compat.o: descrip.h stsdef.h
copycmd.o: cmddef.h
copycmd.o: compat.h
copycmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
copycmd.o: stsdef.h sysmsg.h
copycmd.o: compat.h ods2.h rms.h
copycmd.o: f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h
createcmd.o: cmddef.h
createcmd.o: compat.h
createcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
createcmd.o: stsdef.h sysmsg.h f11def.h
createcmd.o: ods2.h rms.h f11def.h vmstime.h
createcmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
debug.o: debug.h
deletecmd.o: cmddef.h
deletecmd.o: compat.h
deletecmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
deletecmd.o: stsdef.h sysmsg.h
device.o: ods2.h access.h cache.h
device.o: f11def.h vmstime.h
device.o: descrip.h ssdef.h stsdef.h device.h phyio.h
deletecmd.o: ods2.h rms.h f11def.h vmstime.h
deletecmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
device.o: ods2.h
device.o: access.h cache.h f11def.h
device.o: vmstime.h descrip.h ssdef.h stsdef.h device.h phyio.h
diffcmd.o: cmddef.h
diffcmd.o: compat.h
diffcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
diffcmd.o: stsdef.h sysmsg.h
diffcmd.o: compat.h
diffcmd.o: ods2.h rms.h f11def.h vmstime.h
diffcmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
diffcmd.o: phyio.h
dircmd.o: cmddef.h
dircmd.o: compat.h
dircmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
dircmd.o: stsdef.h sysmsg.h
direct.o: access.h cache.h
direct.o: f11def.h vmstime.h
direct.o: descrip.h ssdef.h stsdef.h direct.h fibdef.h ods2.h
dircmd.o: ods2.h rms.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h
direct.o: access.h ods2.h
direct.o: cache.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h direct.h
direct.o: fibdef.h sysmsg.h
dismountcmd.o: cmddef.h
dismountcmd.o: compat.h
dismountcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
dismountcmd.o: stsdef.h sysmsg.h access.h cache.h f11def.h
dismountcmd.o: device.h
dismountcmd.o: ods2.h rms.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h
dismountcmd.o: sysmsg.h access.h cache.h device.h
dismountcmd.o: phyio.h
extendcmd.o: cmddef.h
extendcmd.o: compat.h
extendcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
extendcmd.o: stsdef.h sysmsg.h
extendcmd.o: ods2.h rms.h f11def.h vmstime.h
extendcmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
helpcmd.o: ods2.h
helpcmd.o: cmddef.h
helpcmd.o: compat.h
helpcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
helpcmd.o: stsdef.h sysmsg.h
importcmd.o: cmddef.h
importcmd.o: compat.h
importcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
importcmd.o: stsdef.h sysmsg.h
helpcmd.o: compat.h
helpcmd.o: rms.h f11def.h vmstime.h descrip.h
helpcmd.o: ssdef.h stsdef.h sysmsg.h version.h
initialcmd.o: compat.h
initialcmd.o: cmddef.h
initialcmd.o: compat.h
initialcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
initialcmd.o: stsdef.h sysmsg.h access.h cache.h f11def.h
initialcmd.o: device.h
initialcmd.o: phyio.h initvol.h phyvirt.h
initialcmd.o: ods2.h rms.h f11def.h vmstime.h descrip.h
initialcmd.o: ssdef.h stsdef.h sysmsg.h access.h
initialcmd.o: cache.h device.h phyio.h initvol.h phyvirt.h
initvol.o: compat.h
initvol.o: f11def.h
initvol.o: vmstime.h descrip.h ssdef.h stsdef.h
initvol.o: initvol.h ods2.h phyvirt.h rms.h
initvol.o: f11def.h vmstime.h descrip.h
initvol.o: ssdef.h stsdef.h initvol.h ods2.h phyvirt.h rms.h sysmsg.h
mountcmd.o: compat.h
mountcmd.o: cmddef.h
mountcmd.o: compat.h
mountcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
mountcmd.o: stsdef.h sysmsg.h access.h cache.h f11def.h
mountcmd.o: device.h phyio.h phyvirt.h phyvhd.h
phyunix.o: device.h
phyunix.o: access.h cache.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h
phyunix.o: phyio.h ods2.h phyvirt.h compat.h
mountcmd.o: ods2.h rms.h f11def.h vmstime.h descrip.h
mountcmd.o: ssdef.h stsdef.h sysmsg.h access.h
mountcmd.o: cache.h device.h phyio.h phyvirt.h phyvhd.h
phyunix.o: cmddef.h
phyunix.o: compat.h ods2.h rms.h
phyunix.o: f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h device.h
phyunix.o: access.h cache.h phyio.h phyvirt.h
phyvirt.o: compat.h
phyvirt.o: device.h access.h cache.h f11def.h
phyvirt.o: vmstime.h
phyvirt.o: descrip.h ssdef.h stsdef.h phyio.h ods2.h phyvirt.h phyvhd.h
rms.o: access.h cache.h f11def.h
rms.o: vmstime.h descrip.h ssdef.h stsdef.h
rms.o: device.h phyio.h direct.h fibdef.h ods2.h rms.h compat.h
rms.o: sysmsg.h
phyvirt.o: device.h access.h ods2.h cache.h f11def.h vmstime.h descrip.h
phyvirt.o: ssdef.h stsdef.h phyio.h phyvirt.h sysmsg.h phyvhd.h
renamecmd.o: cmddef.h
renamecmd.o: compat.h
renamecmd.o: ods2.h rms.h f11def.h vmstime.h
renamecmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
rms.o: access.h ods2.h
rms.o: cache.h
rms.o: f11def.h vmstime.h descrip.h ssdef.h stsdef.h device.h phyio.h
rms.o: direct.h fibdef.h rms.h compat.h
rms.o: sysmsg.h
searchcmd.o: cmddef.h
searchcmd.o: compat.h
searchcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
searchcmd.o: stsdef.h sysmsg.h
searchcmd.o: ods2.h rms.h f11def.h vmstime.h
searchcmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
setcmd.o: cmddef.h
setcmd.o: compat.h
setcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
setcmd.o: stsdef.h sysmsg.h
setcmd.o: ods2.h rms.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h
showcmd.o: cmddef.h
showcmd.o: compat.h
showcmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
showcmd.o: stsdef.h sysmsg.h
showcmd.o: access.h cache.h f11def.h
showcmd.o: direct.h phyio.h
showcmd.o: phyvhd.h phyvirt.h version.h
showcmd.o: compat.h
showcmd.o: ods2.h rms.h f11def.h vmstime.h
showcmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
showcmd.o: access.h cache.h direct.h phyio.h
showcmd.o: phyvhd.h phyvirt.h version.h
spawncmd.o: cmddef.h
spawncmd.o: compat.h
spawncmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
spawncmd.o: stsdef.h sysmsg.h
sysmsg.o: ssdef.h rms.h vmstime.h
sysmsg.o: descrip.h stsdef.h compat.h
spawncmd.o: ods2.h rms.h f11def.h vmstime.h
spawncmd.o: descrip.h ssdef.h stsdef.h sysmsg.h
sysmsg.o: ods2.h ssdef.h rms.h
sysmsg.o: f11def.h vmstime.h descrip.h stsdef.h compat.h
sysmsg.o: sysmsg.h
typecmd.o: cmddef.h
typecmd.o: compat.h
typecmd.o: ods2.h rms.h vmstime.h descrip.h ssdef.h
typecmd.o: stsdef.h sysmsg.h
update.o: access.h cache.h
update.o: f11def.h vmstime.h
update.o: descrip.h ssdef.h stsdef.h device.h phyio.h ods2.h
vmstime.o: vmstime.h descrip.h ssdef.h stsdef.h
phyvhd.o: device.h
phyvhd.o: access.h cache.h f11def.h
phyvhd.o: vmstime.h descrip.h ssdef.h stsdef.h
phyvhd.o: phyio.h ods2.h phyvirt.h vhd/libvhd.h
phyvhd.o: vhd/blk_uuid.h vhd/vhd.h
termio.o: cmddef.h
termio.o: compat.h ods2.h rms.h f11def.h vmstime.h
termio.o: descrip.h ssdef.h stsdef.h sysmsg.h
update.o: access.h ods2.h
update.o: cache.h f11def.h vmstime.h descrip.h ssdef.h stsdef.h device.h
update.o: phyio.h initvol.h
vmstime.o: vmstime.h descrip.h ssdef.h
vmstime.o: stsdef.h ods2.h
phyvhd.o: compat.h
phyvhd.o: device.h access.h
phyvhd.o: ods2.h
phyvhd.o: cache.h f11def.h vmstime.h
phyvhd.o: descrip.h ssdef.h stsdef.h phyio.h phyvirt.h sysmsg.h
phyvhd.o: vhd/libvhd.h
phyvhd.o: vhd/blk_uuid.h vhd/vhd.h phyvhd.h
vhd/libvhd.o: vhd/libvhd.h
vhd/libvhd.o: vhd/blk_uuid.h vhd/vhd.h vhd/relative-path.h
vhd/relative-path.o: vhd/relative-path.h
genmsg.o: sysmsg.h
genmsg.o: ods2.h
genmsg.o: ssdef.h stsdef.h
makehelp.o: compat.h
makehelp.o: cmddef.h
makehelp.o: ods2.h rms.h
makehelp.o: f11def.h vmstime.h descrip.h ssdef.h stsdef.h sysmsg.h

View File

@@ -6,41 +6,20 @@
# otherwise, every little change means updating all
# the os-specific makefiles.
#
# See makefile.<osname>, which normally includes it
# For Unix and Unix-ish OSs, variables are defaulted
# in makefile.unixdefs, which is included by
# makefile.<osname>. Per-OS customizations are set
# by makefile.<osname>, which then includes this file.
#
# 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
# If your make doesn't support include (are any left?),
# combine the files with an editor.
#
# or just combine the files you need with an editor.
# Life will be simpler if you softlink Makefile to makefile.<osname>
# e.g. ln -s makefile.unix Makefile
#
# ###
# OS-Specific defines
# These variables are available
# Other defines = "-DDEBUG_BUILD" "-D_FILE_OFFSET_BITS=32"
#DEFS =
# Libraries, e.g. -lreadline
#LDLIBS =
# Linker flags
#LDFLAGS =
# Object file suffix
#OBJ = .o
# Executable file suffix
#EXE =
# Physical IO module
#PHYSIO = phyunix
# Extra physical IO headers
#PHYSIOH =
# See makefile.unixdefs for a list of the available variables.
# VHD format options
@@ -48,11 +27,26 @@ include $(VHDOPTS)
# #####################################################
DEPENDS = makefile.depends
MAKEDEPEND = makedepend
SED = sed
# Language files are of the form LL_CC.{msg, hlp}
# Where: LL is a language code (e.g. en), and
# CC is a country code (e.g. us)
# .msg files are the message definitions
# .hlp file are the helpfile text
#
# The base language is en_us, but translations are welcome.
all : ods2$(EXE)
# Filenames of these forms will automatically generate the
# runtime-loadable help (.hlb) and message (.mdf) files.
# Note that translated messages from a VMS system are required
# for each language; these are generated with the (DECUS)
# unmessage utility, are are named "vms_msgdump.<lang>.msg.
# Output from the message utility has more details.
MSGLANGS = $(wildcard ??_??.msg)
HLPLANGS = $(wildcard ??_??.hlp)
all : ods2$(EXE) helpfiles msgfiles
SRCS = ods2.c \
access.c \
@@ -69,19 +63,19 @@ direct.c \
dismountcmd.c \
extendcmd.c \
helpcmd.c \
importcmd.c \
initialcmd.c \
initvol.c \
mountcmd.c \
$(PHYSIO).c \
phyvirt.c \
renamecmd.c \
rms.c \
searchcmd.c \
setcmd.c \
showcmd.c \
spawncmd.c \
sysmsg.c \
typecmd.c \
termio.c \
update.c \
vmstime.c \
$(VHDLIB)
@@ -107,15 +101,19 @@ vclist:
@echo $(SRCS) | sed -e's/ */\n/g' | sort | uniq
# This processing is so the kit can contain a generic, up-to-date depends file
# I don't want to require makedepend for people to build from source.
# I do want the file to be accurate when shipped, so auto-maintained.
# makedepend will include all the system library includes, which is not
# without requiring makedepend when rebuilding from source.
#
# Raw makedepend will include all the system library includes, which is not
# helpful for this case. So the sed processing removes dependencies that
# start with "/" - e.g. /usr/include and friends.
#
# The sleep is because make uses high-precision timing; the output can appear
# to be in the future by a few msec.
$(DEPENDS): $(MAKEFILE_LIST)
touch $(DEPENDS)
2>/dev/null $(MAKEDEPEND) -o$(OBJ) -I. -f- -- $(CFLAGS) $(CPPFLAGS) $(DEFS) -- $(SRCS) | $(SED) -e's/ \/[^ ]*\.h/ /g' -e'/^[^:]*: *$$/d' -e's/ */ /g' >$(DEPENDS)
2>/dev/null $(MAKEDEPEND) -o$(OBJ) -I. -f- -- $(CFLAGS) $(CPPFLAGS) $(DEFS) -- $(SRCS) genmsg.c makehelp.c | $(SED) -e's/ \/[^ ]*\.h/ /g' -e'/^[^:]*: *$$/d' -e's/ */ /g' >$(DEPENDS)
@sleep 2
-include $(DEPENDS)
@@ -133,3 +131,63 @@ descrip.mms : $(SRCS) $(DEPENDS)
ods2$(EXE) : $(OBJS) $(LIBS)
$(CC) $(LDFLAGS) -o ods2$(EXE) $(OBJS) $(LDLIBS)
# Message definition files: These provide the text for every condition (message) code.
#
# For a new translation:
# create a new <lang>.msg file, based on an existing one (e.g. en_us.msg)
# make does the rest
# To test, ods2 set message ods2_<lang>.mdf
# Runtime-loadable message file for I18n supports:
msgfiles : $(foreach LANG,$(MSGLANGS),ods2_$(basename $(LANG)).mdf)
ods2_%.mdf : %.mt genmsg.c
$(CC) $(CCFLAGS) $(CPPFLAGS) $(DEFS) $(LDFLAGS) '-DTABLEFILE="$<"' -o genmsg$(EXE) genmsg.c $(LDLIBS)
$(RUN)genmsg$(EXE) -q $@
@$(DELETE) genmsg$(EXE)
# Build ssdef (condition code definitions) from .msg files.
# Requires Perl. Generate ssdef.msg for documentatation.
# The output is not language-specific (aside from the documention file)
# It's merely the #defines for the facility numbers and condition codes.
ssdef.h : $(ODS2LANG).msg vms_messages_$(ODS2LANG).msg message
$(MESSAGE) -q vms_messages_$(ODS2LANG).msg $(ODS2LANG).msg ssdef.h
$(MESSAGE) -m -q vms_messages_$(ODS2LANG).msg $(ODS2LANG).msg ssdef.msg
# Compile-time message definition data file: #included in sysmsg to
# compile default/fallback definitions.
default.md : $(ODS2LANG).mt genmsg.c
$(CC) $(CCFLAGS) $(CPPFLAGS) $(DEFS) $(LDFLAGS) '-DTABLEFILE="$<"' -o genmsg$(EXE) genmsg.c $(LDLIBS)
$(RUN)genmsg$(EXE) -dq $@
@$(DELETE) genmsg$(EXE)
sysmsg$(OBJ) : default.md
# Build message table from .msg file.
# Requires Perl.
%.mt : %.msg vms_messages_$(basename %).msg message
$(MESSAGE) -q -t $(filter-out message,$^) $@
# VMS messages for each language
vms_messages_%.msg : vms_msgdump.%.msg message vms_msgdefs.h
$(MESSAGE) -m -q vms_msgdefs.h $< $@
# Help files
helpfiles : ods2.hlb $(foreach LANG,$(HLPLANGS),ods2_$(basename $(LANG)).hlb)
ods2_%.hlb : %.hlp makehelp$(EXE)
$(RUN)makehelp$(EXE) -q $< $@
makehelp$(EXE) : makehelp.o compat.o
$(CC) $(CCFLAGS) $(CPPFLAGS) $(DEFS) $(LDFLAGS) -o makehelp$(EXE) makehelp.o compat.o $(LDLIBS)
ods2.hlb : ods2_$(ODS2LANG).hlb
$(LN) $< $@

View File

@@ -2,33 +2,14 @@
# Makefile for solaris OS
# Start with generic unix
include makefile.unixdefs
# Use gcc
CC=gcc
CCFLAGS = -O4 -g
DEFS = -DUSE_READLINE
LDFLAGS = -lreadline -ltermcap
# Include VHD format image file support
VHDOPTS = makefile-vhd.unix
# Object file extension
OBJ = .o
DELETE = "rm -f"
# Physical I/O module
PHYSIO = phyunix
PHYSIOH =
TOPMAKE = makefile.solaris
all:
clean:
rm -f ods2 $(OBJS)
include makefile.generic

View File

@@ -3,29 +3,25 @@
# Makefile for Tru64 (DEC/OSF1)
#
# Start with generic unix
include makefile.unixdefs
# Use gcc
CC=gcc
TOPMAKE = makefile.solaris
include makefile.generic
CCFLAGS = -O4 -g
# DEFS = -DUSE_READLINE
# LDFLAGS = -lreadline -ltermcap
# I don't think we have libedit
# Include VHD format image file support
VHDOPTS = makefile-vhd.unix
# Object file extension
OBJ = .o
DELETE = rm -f
# Physical I/O module
PHYSIO = phyunix
PHYSIOH =
DEFS =
LDLIBS =
TOPMAKE = makefile.tru64
all:
clean:
rm -f ods2 $(OBJS)
include makefile.generic

View File

@@ -3,39 +3,9 @@
# Makefile for most Unix distributions
#
# Special defines, e.g.
# DEFS="-DDEBUG_RMS -DDEBUG_BUILD -D_FILE_OFFSET_BITS=32"
CCFLAGS = -O4 -g
#-O0 -g -DUSE_READLINE -Wall -pedantic
# Extra warns about $ in identifiers...
# -Wextra
# Include readline support
DEFS = -DUSE_READLINE
LDLIBS = -lreadline -ltermcap
# Include VHD format image file support
VHDOPTS = makefile-vhd.unix
# Object file extension
OBJ = .o
EXE =
DELETE = rm -f
# Physical I/O module
PHYSIO = phyunix
include makefile.unixdefs
TOPMAKE = makefile.unix
all:
clean:
rm -f ods2$(EXE) $(OBJS)
include makefile.generic

View File

@@ -0,0 +1,78 @@
# -*- Makefile -*-
# Basic variable definitions for Unix & Unix-like OSs
#
# OS-specific file can redefine selectively
# Special defines, e.g.
# DEFS="-DDEBUG_RMS -DDEBUG_BUILD -D_FILE_OFFSET_BITS=32"
CCFLAGS = -O4 -g
#-O0 -g -DUSE_LIBEDIT -Wall -pedantic
# Extra warns about $ in identifiers...
# -Wextra
# Large file support
DEFS += "-D_FILE_OFFSET_BITS=64"
# Include editline support
DEFS += -DUSE_LIBEDIT
LDLIBS = -ledit -ltermcap
# Include VHD format image file support
VHDOPTS = makefile-vhd.unix
# Default language
ODS2LANG = en_us
# Object file extension
OBJ = .o
# Executable file extension
EXE =
# Delete file - must be one file spec, as VMS needs commas
DELETE = rm -f
# How to run a program
RUN = ./
# Copy a file
COPY = cp -p
# Softlink a file
LN = ln -sf
# Physical I/O module
PHYSIO = phyunix
# The top level makefile (used for recursive make)
#TOPMAKE = makefile.unix
# Files to clean
CLEANFILES = ods2$(EXE) genmsg$(EXE) makehelp$(EXE) $(OBJS) *.mt *.md *.mdf *.hlb vms_messages_*.msg ssdef.h ssdef.msg
# How to run Perl
PERL = LC_ALL="C" perl
# Name of dependencies file & how to build
DEPENDS = makefile.depends
MAKEDEPEND = makedepend
# How to run sed
SED = sed
# How to run message
MESSAGE = $(PERL) message
all:
clean:
rm -f $(CLEANFILES)

View File

@@ -9,7 +9,11 @@
CCFLAGS = -O4 -g
#LDLIBS = -lreadline -ltermcap
#LDLIBS = -ledit -ltermcap
# Default language
ODS2LANG = en_us
# Object file extension
OBJ = .OBJ
@@ -19,14 +23,24 @@ EXE = .EXE
DELETE = DELETE
GEN = ";*"
RUN = mcr sys$disk:[]
COPY = COPY
LN = COPY
# Physical I/O module
PHYSIO = phyvms
TOPMAKE = makefile.vms
SED = sed
DEPENDS = makefile.depends
MAKEDEPEND = makedepend
all:
clean:
$(DELETE) *.$(OBJ)$(GEN),*.$(EXE)$(GEN)
$(DELETE) *.$(OBJ)$(GEN),*.$(EXE)$(GEN), $.mt$(GEN), *.mdf$(GEN)
include makefile.generic

649
extracters/ods2/makehelp.c Normal file
View File

@@ -0,0 +1,649 @@
/* Copyright (c) Timothe Litt <litt@acm.org>
*/
/* Help file compiler
*/
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "compat.h"
#define HELPFILEDEFS
#include "cmddef.h"
#define INEXT ".hlp"
#define OUTEXT ".hlb"
#define LSTEXT ".lst"
#ifdef _WIN64
#define OUTPFX "win64-ods2_"
#define DDLIM '\\'
#elif defined( _WIN32 )
#define OUTPFX "win-ods2_"
#define DDLIM '\\'
#elif defined( VMS )
#define OUTPFX "ods2_"
#define DDLIM ']'
#else
#define OUTPFX "ods2_"
#define DDLIM '/'
#endif
/* Leaks are not an issue since this program exits after every command.
* However, the leak detector is handy for debugging other issues.
*/
#if defined( _WIN32 ) && defined(_MSC_VER) && defined( DEBUG_BUILD ) && defined( USE_VLD )
/* Normally done in the project file, but VLD is optional and I'd rather not provide
* instructions as they vary by IDE version. See http://vld.codeplex.com/ if interested.
*/
#include "C:\\Program Files (x86)\\Visual Leak Detector\\include\\vld.h"
#pragma comment (lib,"C:\\Program Files (x86)\\Visual Leak Detector\\lib\\Win32\\vld.lib")
#endif
typedef struct hlpstat {
size_t topics[9];
size_t keymem[9];
size_t txtmem[9];
size_t ntopics;
size_t keymemtot;
size_t txtmemtot;
} hlpstat_t;
static void pstats( FILE *of, char *outname, hlpstat_t *stats, size_t memsize );
static size_t hlpsize( hlproot_t *root );
static int rdhelp( hlproot_t *root, const char *filename );
static void helpsort( hlproot_t *root );
static int hlpcmp( const void *qa, const void *qb );
static void savehlp( hlproot_t *oroot, hlproot_t *iroot,
char *base, char **sp, char **pp,
unsigned lvl, hlpstat_t *stats );
static int printdata( FILE *of, unsigned level, hlproot_t *root,
int text, hlpstat_t *stats );
/* ******************************************************************* main() */
int main( int argc, char **argv ) {
int opth = 0, optd = 0, optD = 0, optq = 0;
char *inname = NULL, *outname = NULL, *pname;
int outmalloced = FALSE;
size_t memsize = 0;
hlproot_t inroot;
hlphdr_t *hdr;
hlpstat_t stats;
struct stat instat;
char *base, *pp, *sp;
FILE *of = NULL;
memset( &inroot, 0, sizeof( inroot ) );
inroot.topics.ptr = NULL;
inroot.ntopics = 0;
pname = argv[0];
if( argc <= 1 ) opth = TRUE;
for( ; argc > 1; --argc, ++argv ) {
if( !strcmp( argv[1], "--" ) ) break;
if( *argv[1] == '-' && argv[1][1] ) {
char *p;
for( p = argv[1]+1; *p; p++ ) {
switch( *p ) {
case 'h':
opth = TRUE;
break;
case 'd':
optd = TRUE;
break;
case 'D':
optD = TRUE;
break;
case 'q':
optq = TRUE;
break;
default:
fprintf( stderr, "Unknown option %c\n", argv[1][1] );
exit( EXIT_FAILURE );
}
}
} else {
break;
}
}
if( opth ) {
printf( "%s [opts] [in" INEXT " [out" OUTEXT "]]\n"
" -h This help\n"
" -d Dump structure of input\n"
" -D Dump structure of input with topic text\n"
" -q Suppress statistics report\n"
" -- End of options\n"
" - is stdin/out\n"
"If an output file is not specified, the input filename\n"
"prefixed by " OUTPFX " is used. " OUTEXT " replaces the "
"input name's extension.\n"
"With -d or -D, " LSTEXT " replaces the input name's extension.\n"
"The " OUTEXT " files are architecture-dependent.\n"
"Under Windows, the default output file is prefixed\n"
"with 'win-' or 'win64-'.\n", pname? pname : "makehelp" );
exit( EXIT_SUCCESS );
}
if( argc > 1 ) {
if( strcmp( argv[1], "-" ) ) {
inname = argv[1];
}
--argc; ++argv;
}
if( argc > 1 ) {
if( strcmp( argv[1], "-" ) ) {
outname = argv[1];
}
--argc; ++argv;
} else {
if( inname != NULL ) {
char *p, *outext;
size_t inlen, extsiz, addlen;
ptrdiff_t plen = 0;
inlen = strlen( inname );
outext = ( optd || optD )? LSTEXT : OUTEXT;
addlen =
extsiz = strlen( outext ) +1;
#ifdef OUTPFX
addlen += sizeof( OUTPFX ) -1;
#endif
outname = malloc( inlen + addlen );
if( outname == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
outmalloced = TRUE;
#ifdef OUTPFX
if( (p = strrchr( inname, DDLIM )) != NULL ) {
plen = (p - inname) +1;
p = outname + plen;
memcpy( outname, inname, plen );
} else
p = outname;
memcpy( p, OUTPFX, sizeof( OUTPFX ) -1 );
memcpy( p + sizeof( OUTPFX ) -1,
inname + plen, strlen( inname + plen ) +1 );
#else
memcpy( outname, inname + plen, inlen +1 ); /* plen == 0, ensures it's used */
#endif
if( (p = strrchr( outname, '.' )) != NULL && strchr( p, DDLIM ) == NULL ) {
*p = '\0';
}
memcpy( outname + strlen(outname), outext, extsiz );
}
}
if( argc >1 ) {
fprintf( stderr, "Too many command arguments\n" );
exit( EXIT_FAILURE );
}
if( optd || optD ) {
if( outname == NULL )
of = stdout;
else {
of = openf( outname, "w" );
if( !of ) {
perror( outname );
if( outmalloced) free( outname );
exit( EXIT_FAILURE );
}
}
}
memset( &stats, 0, sizeof( stats ) );
memset( &instat, 0, sizeof( instat ) );
if( inname == NULL || stat( inname, &instat ) != 0 )
instat.st_mtime = 0;
if( !optq ) {
time_t now;
FILE *pf;
char *rpi = NULL;
if( inname != NULL )
rpi = get_realpath( inname );
pf = (optd || optD)? of : stderr;
fprintf( pf, "Topic structure of %s\n",
inname? (rpi? rpi : inname) : "<stdin>" );
if( rpi ) free( rpi );
if( instat.st_mtime != 0 ) {
char *mt;
mt = Ctime( &instat.st_mtime );
if( mt != NULL ) {
now = time( &now );
fprintf( pf, "File: %s ", mt );
free( mt );
mt = Ctime( &now );
if( mt != NULL ) {
fprintf( pf, "as of %s", mt );
free( mt );
}
fprintf( pf, "\n" );
}
}
fprintf( pf,
"---------------------------------------------------------------\n" );
}
if( rdhelp( &inroot, inname ) ) {
if( outmalloced) free( outname );
perror( inname );
if( of && of != stdout && of != stderr ) fclose( of );
exit( EXIT_FAILURE );
}
memsize = sizeof( inroot) + hlpsize( &inroot );
if( optd || optD ) {
printdata( of, 1, &inroot, optD, &stats );
if( !optq ) pstats( of, outname, &stats, memsize );
if( of && of != stdout && of != stderr ) fclose( of );
if( outmalloced) free( outname );
exit( EXIT_SUCCESS );
}
base = malloc( sizeof( hlphdr_t ) + memsize );
if( !base ) {
perror("malloc");
exit( EXIT_FAILURE );
}
hdr = (hlphdr_t *)base;
sp = base + sizeof( hlphdr_t );
pp = sp + memsize;
memset( hdr, 0, sizeof( *hdr ) );
memcpy( hdr->magic, HLP_MAGIC, sizeof( HLP_MAGIC ) );
hdr->version = HLP_VERSION;
hdr->psize = sizeof( void * );
hdr->ssize = sizeof( size_t );
hdr->tsize = sizeof( time_t );
hdr->ddate = instat.st_mtime;
hdr->size = memsize;
savehlp( NULL, &inroot, base, &sp, &pp, 1, &stats );
if( outname == NULL )
of = stdout;
else {
of = openf( outname, "wb" );
if( !of ) {
perror( outname );
if( outmalloced) free( outname );
exit( EXIT_FAILURE );
}
}
if( !optq) pstats( stderr, outname, &stats, memsize );
fwrite( base, 1, memsize + sizeof( hlphdr_t ), of );
if( of && of != stdout && of != stderr ) fclose( of );
free( base );
if( outmalloced) free( outname );
exit( EXIT_SUCCESS );
}
/* ***************************************************************** pstats() */
static void pstats( FILE *of, char *outname, hlpstat_t *stats, size_t memsize ) {
size_t i;
char *p = NULL;
if( outname != NULL && (p = get_realpath( outname )) != NULL )
outname = p;
fprintf( of,
"\n---------------------------------------------------------------\n"
"Summary of: %s\n", outname == NULL? "<stdout>" : outname );
if( p != NULL ) free( p );
for( i = 0; i < 9; i++ ) {
if( stats->topics[i] ) {
fprintf( of,
"Level %u topics: %4u Key memory: %5u bytes Text memory: %5u\n",
(unsigned)i+1, (unsigned)stats->topics[i],
(unsigned)stats->keymem[i],
(unsigned)stats->txtmem[i] );
stats->ntopics++;
stats->keymemtot += stats->keymem[i];
stats->txtmemtot += stats->txtmem[i];
}
}
fprintf( of, " Total topics: %4u Key memory: %5u bytes Text memory: %5u\n",
(unsigned)stats->ntopics, (unsigned)stats->keymemtot,
(unsigned)stats->txtmemtot );
fprintf( of, " Index memory: %5u bytes Data memory: %5u\n",
(unsigned)(memsize - (stats->keymemtot + stats->txtmemtot)),
(unsigned)(stats->keymemtot + stats->txtmemtot));
return;
}
/* **************************************************************** hlpsize() */
static size_t hlpsize( hlproot_t *root ) {
hlptopic_t *hlp;
size_t size = 0;
if( root->ntopics == 0 ) {
fprintf( stderr, "Encountered an empty root\n" );
return size;
}
for( hlp = root->topics.ptr;
hlp < (hlptopic_t *)root->topics.ptr + root->ntopics; hlp++ ) {
size += strlen( hlp->key.ptr ) +1;
size += strlen( hlp->text.ptr ) +1;
if( hlp->subtopics.ntopics )
size += hlpsize( &hlp->subtopics );
}
size += root->ntopics * sizeof( hlptopic_t );
return size;
}
/*************************************************************** rdhelp() */
static
int rdhelp( hlproot_t *toproot, const char *filename ) {
FILE *fp;
size_t bufsize = 80;
char *buf = NULL, *rec;
hlproot_t *root = NULL;
hlptopic_t *hlp = NULL,
*tpath[9];
unsigned int level = 0, n, lineno = 0;
if( filename == NULL )
fp = stdin;
else {
if( (fp = openf( filename, "r" )) == NULL )
return errno;
}
memset( tpath, 0, sizeof( tpath ) );
for( rec = NULL; ; ) {
char *p, *t;
size_t txtlen = 0, len;
/* Read initial search key */
if( rec == NULL ) {
++lineno;
if( (rec = fgetline( fp, FALSE, &buf, &bufsize )) == NULL )
break; /* EOF */
}
if( (p = strchr( rec, '\r' )) != NULL ) {
*p = '\0';
}
p = rec + 2;
if( rec[0] == '!' ||
!(strlen(rec) >= 3 &&
rec[0] >= '1' && rec[0] <= '9' &&
rec[1] == ' ' && isprint( p[ (len = strspn( p, " " )) ]) ) ) {
rec = NULL;
continue; /* Comment or not a search key record */
}
p += len; /* Search key starts after level + 1 or more spaces */
/* Start new topic */
n = rec[0] - '1';
if( n <= level ) {
if( n )
root = &tpath[n-1]->subtopics;
else
root = toproot;
} else if( n != level +1 ) {
free( buf );
if( filename != NULL) fclose( fp );
fprintf( stderr, "Level error at line %u\n", lineno );
exit( EXIT_FAILURE );
} else { /* hlp can't be NULL, for code analyzer */
if( hlp ) root = &hlp->subtopics;
}
level = n;
if( !root ) exit(EXIT_FAILURE); /* More code analyzer */
if( (hlp = realloc( root->topics.ptr,
(root->ntopics + 1) * sizeof( hlptopic_t ) )) == NULL ) {
free( buf );
if( filename != NULL) fclose( fp );
return errno;
}
root->topics.ptr = hlp;
hlp += root->ntopics++;
tpath[level] = hlp;
len = strlen( p ) + 1;
if( (hlp->key.ptr = malloc( len )) == NULL ) {
free( buf );
if( filename != NULL) fclose( fp );
return errno;
}
memcpy( hlp->key.ptr, p, len );
hlp->keylen = (uint32_t)(len -1);
hlp->text.ptr = NULL;
hlp->subtopics.topics.ptr = NULL;
hlp->subtopics.ntopics = 0;
/* Add text */
while( (rec = fgetline( fp, TRUE, &buf, &bufsize )) != NULL ) {
++lineno;
if( (p = strchr( rec, '\r' )) != NULL ) {
*p++ = '\n';
*p = '\0';
}
if( rec[0] == '!' ) { /* Comment */
continue;
}
p = rec;
if( strlen(p) >= 3 &&
(rec[0] >= '1' && rec[0] <= '9') &&
rec[1] == ' ' && isprint( p[ strspn( p + 2, " " ) ] ) ) {
if( (p = strchr( p, '\n' )) )
*p = '\0';
break; /* New search key, rescan this record */
}
len = strlen( p );
if( len >= 2 && p[len-2] == '$' && p[len-1] == '\n' ) {
p[len-2] = '\0'; /* Strip \n for lines ending in $ */
--len;
}
++len;
if( hlp->text.ptr ) {
if(txtlen != strlen(hlp->text.ptr)) printf( "len mismatch\n");
} else if( txtlen ) printf( "Missing text\n");
if( (t = realloc( hlp->text.ptr, txtlen + len)) == NULL ) {
free( buf );
if( filename != NULL) fclose( fp );
return errno;
}
hlp->text.ptr = t;
memcpy( (char *)hlp->text.ptr + txtlen, p, len );
txtlen += --len;
rec = NULL;
} /* Add topic text */
if( hlp->text.ptr == NULL ) {
fprintf( stderr, "No text for %s at line %u\n",
(char *)hlp->key.ptr, lineno );
free( rec );
if( filename != NULL) fclose( fp );
exit( EXIT_FAILURE );
}
} /* Add topic */
free( buf );
if( filename != NULL) fclose( fp );
if( toproot->ntopics == 0 ) {
fprintf( stderr, "No topics found at line %u\n", lineno );
exit( EXIT_FAILURE );
}
helpsort( toproot );
return 0;
}
/*************************************************************** helpsort() */
static void helpsort( hlproot_t *root ) {
hlptopic_t *hlp;
if( root->topics.ptr == NULL ) {
fprintf( stderr, "Node has no topics\n" );
exit( EXIT_FAILURE );
}
for( hlp = root->topics.ptr;
hlp < (hlptopic_t *)root->topics.ptr + root->ntopics; hlp++ ) {
if( hlp->text.ptr == NULL ) {
fprintf( stderr, "No text for %s\n", (char *)hlp->key.ptr );
exit( EXIT_FAILURE );
}
if( hlp->subtopics.topics.ptr )
helpsort( &hlp->subtopics );
}
qsort( root->topics.ptr, root->ntopics, sizeof( hlptopic_t ), &hlpcmp );
return;
}
/***************************************************************** hlpcmp() */
static int hlpcmp( const void *ta, const void *tb ) {
const char *a, *b;
size_t alen, blen;
a = ((hlptopic_t *)ta)->key.ptr;
b = ((hlptopic_t *)tb)->key.ptr;
alen = ((hlptopic_t *)ta)->keylen;
blen = ((hlptopic_t *)tb)->keylen;
while( alen && blen ) {
int c;
c = tolower( (unsigned char)*a ) - tolower( (unsigned char)*b );
if( c != 0 )
return c;
++a; ++b; --alen; --blen;
}
return (int)(alen - blen);
}
/* **************************************************************** savehlp() */
static void savehlp( hlproot_t *oroot, hlproot_t *iroot,
char *base,char **sp, char **pp,
unsigned lvl, hlpstat_t *stats ) {
size_t t;
hlptopic_t *ihlp, *ohlp;
hlproot_t *rp;
/* sp allocates structures toward increasing addresses.
* pp allocates strings toward decreasing addresses.
* This ensures that alignment is accounted for.
* All pointers in the input tree are offsets in the output.
*/
if( oroot == NULL ) { /* Top root */
rp = (hlproot_t *)*sp;
*sp = (char *)(rp + 1);
memset( rp, 0, sizeof( *rp ) );
} else
rp = oroot; /* Subtopic root */
ohlp = (hlptopic_t *)*sp; /* Topic list for this root */
rp->topics.ofs = (char *)ohlp - base;
t =
rp->ntopics = iroot->ntopics;
t *= sizeof( hlptopic_t );
*sp += t;
memset( ohlp, 0, t );
for( ihlp = iroot->topics.ptr, t = 0; t < iroot->ntopics; ihlp++, t++ ) {
size_t len;
stats->topics[lvl-1]++;
memset( ohlp, 0, sizeof( *ohlp ) );
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning (disable: 6001)
#endif
/* N.B. Pointers ARE initialized */
len = strlen( ihlp->key.ptr ) +1;
stats->keymem[lvl-1] += len;
*pp = (char *)*pp - len;
memcpy( *pp, ihlp->key.ptr, len );
free( (void *)ihlp->key.ptr );
ohlp->key.ofs = *pp - base;
ohlp->keylen = (uint32_t)len -1;
len = strlen( ihlp->text.ptr ) +1;
stats->txtmem[lvl-1] += len;
*pp = (char *)*pp - len;
memcpy( *pp, ihlp->text.ptr, len );
free( (void *)ihlp->text.ptr );
#ifdef _MSC_VER
#pragma warning(pop)
#endif
ohlp->text.ofs = *pp - base;
ohlp->subtopics.ntopics = ihlp->subtopics.ntopics;
if( ihlp->subtopics.ntopics ) {
ohlp->subtopics.topics.ofs = *sp - base;
savehlp( &ohlp->subtopics, &ihlp->subtopics, base, sp, pp,
lvl+1, stats );
} else {
ohlp->subtopics.topics.ofs = 0;
}
++ohlp;
}
free( (void *)iroot->topics.ptr );
return;
}
/*************************************************************** printdata() */
static int printdata( FILE *of, unsigned level, hlproot_t *root,
int text, hlpstat_t *stats ) {
int sts;
hlptopic_t *hlp;
if( root->topics.ptr == NULL )
return 1;
for( hlp = root->topics.ptr;
hlp < (hlptopic_t *)root->topics.ptr + root->ntopics; hlp++ ) {
stats->topics[level-1]++;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning (disable: 6001)
#endif
/* N.B. Pointers ARE initialized */
fprintf( of, "%*s %u %s\n", level, "", level, (char *)hlp->key.ptr );
free( hlp->key.ptr );
if( hlp->text.ptr == NULL )
return 0;
stats->keymem[level-1] += (size_t)hlp->keylen+1;
stats->txtmem[level-1] += strlen( (char *)hlp->text.ptr ) +1;
if( text )
printf( "%s\n", (char *)hlp->text.ptr );
free( hlp->text.ptr );
#ifdef _MSC_VER
#pragma warning(pop)
#endif
if( hlp->subtopics.topics.ptr != NULL &&
!(sts = printdata( of, level +1, &hlp->subtopics, text, stats )) )
return sts;
}
free( root->topics.ptr );
root->topics.ptr = NULL;
root->ntopics = 0;
return 1;
}

1188
extracters/ods2/message Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_MOUNTCMD )
@@ -15,6 +18,7 @@
#endif
#endif
#include "compat.h"
#include "cmddef.h"
#include "access.h"
@@ -31,80 +35,117 @@ static char *parents = NULL;
void mounthelp(void);
#define mou_snapshot OPT_GENERIC_1
#define mou_dtype OPT_GENERIC_2
qual_t mouquals[] = { {DT_NAME, 0, MOU_DEVTYPE, CV(NULL), "Drive type (DEC model name) "},
{"image", MOU_VIRTUAL, 0, NV, "Mount a disk image file", },
{"log", MOU_LOG, 0, NV, "-Show progress"},
{"nolog", 0, MOU_LOG, NV, NULL},
{"readonly", 0, MOU_WRITE, NV, "Only allow reading from volume"},
qual_t
mouquals[] = { {DT_NAME, 0, MOU_DEVTYPE, CV(NULL),
"commands mount qual_media"},
{"image", mou_dtype | MOU_VIRTUAL,
0, NV,
"commands mount qual_image"},
{"log", MOU_LOG, 0, NV,
"-commands mount qual_log"},
{"nolog", 0, MOU_LOG, NV, NULL},
{"readonly", 0, MOU_WRITE, NV,
"commands mount qual_readonly"},
#ifdef USE_VHD
{"snapshots_of", MOU_VIRTUAL | MOU_WRITE | mou_snapshot, PHY_CREATE, SV(&parents),
"Create snapshot(s) of the (existing) VHD disk(s) specified by this qualifier." },
{"snapshots_of",
MOU_VIRTUAL | MOU_WRITE | mou_snapshot,
PHY_CREATE, SV(&parents),
"commands mount qual_snapshot"},
#endif
{"virtual", MOU_VIRTUAL, 0, NV, NULL, },
{"write", MOU_WRITE, 0, NV, "Allow writing to volume", },
{NULL, 0, 0, NV, NULL } };
{"device", mou_dtype, MOU_VIRTUAL, NV,
"commands mount qual_device"},
{"virtual", mou_dtype | MOU_VIRTUAL, 0,
NV, NULL},
{"write", MOU_WRITE, 0, NV,
"-commands mount qual_write"},
{"nowrite" , 0, MOU_WRITE, NV, NULL},
param_t moupars[] = { {"volumes", REQ, LIST, NOPA,
"devices or disk image(s) of volume set in RVN order separated by comma"
},
{"labels", OPT, LIST, NOPA, "volume labels in RVN order separated by comma" },
{ NULL, 0, 0, NOPA, NULL }
{NULL, 0, 0, NV, NULL} };
param_t
moupars[] = { {"volumes", REQ, LIST, NOPA, "commands mount volumes"},
{"labels", OPT, LIST, NOPA, "commands mount labels"},
{ NULL, 0, 0, NOPA, NULL }
};
/******************************************************************* domount() */
DECL_CMD(mount) {
int sts = 1, devices = 0;
vmscond_t sts = 1;
int devices = 0;
size_t i;
char **devs = NULL, **labs = NULL;
int options;
options_t options;
#ifdef USE_VHD
int nparents = 0;
size_t i;
char **parfiles = NULL;
#endif
options = checkquals( 0, mouquals, qualc, qualv );
if( options == -1 )
return SS$_BADPARAM;
UNUSED(argc);
if( (devices = parselist( &devs, 0, argv[1], "devices")) < 0 )
return SS$_BADPARAM;
if( parselist( &labs, devices, argv[2], "labels") < 0 ) {
free( devs );
return SS$_BADPARAM;
if( $FAILS(sts = checkquals( &options, MOU_LOG, mouquals, qualc, qualv )) ) {
return sts;
}
if( $FAILS(sts = parselist( &devices, &devs, 0, argv[1])) )
return sts;
if( $FAILS(sts = parselist( NULL, &labs, devices, argv[2])) ) {
free( devs );
return sts;
}
if( !(options & mou_dtype) ) {
for( i = 0; i < (unsigned)devices; i++ ) {
size_t len;
char *p;
if( (p = strchr( devs[i], '.' )) != NULL ) {
len = strlen( p+1 );
if( len >= 1 && len == strspn( p+1, "0123456789" ".;-_"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" ) )
options |= MOU_VIRTUAL;
}
}
}
#ifdef USE_VHD
if( options & mou_snapshot ) {
nparents = parselist( &parfiles, devices, parents, "parent VHD files " );
if( $FAILS(sts = parselist( &nparents, &parfiles, devices, parents )) ) {
free( devs );
free( labs );
return sts;
}
if( nparents != devices ) {
printf( "%%ODS2-E-NOTSAME, You must specify the same number of existing files (%u) with %cSNAPSHOT as filenames to create (%u)\n",
nparents, vms_qual? '/': '-', devices );
sts = printmsg( MOUNT_NOTSAME, 0, nparents, qstyle_c, devices );
free( parfiles );
return SS$_BADPARAM;
free( devs );
free( labs );
return sts;
}
for( i = 0; i < (size_t)nparents; i++ ) {
sts = phyvhd_snapshot( devs[i], parfiles[i] );
if( !(sts & STS$M_SUCCESS) ) {
if( (sts & STS$M_COND_ID) != (SS$_DUPFILENAME & STS$M_COND_ID) ) {
(void) unlink( devs[i] );
if( $FAILS(sts = phyvhd_snapshot( devs[i], parfiles[i] )) ) {
if( !$MATCHCOND(sts, SS$_DUPFILENAME) ) {
(void) Unlink( devs[i] );
}
while( i > 0 ) {
--i;
(void) unlink( devs[i] );
(void) Unlink( devs[i] );
}
free( parfiles );
return SS$_BADPARAM;
free( devs );
free( labs );
return sts;
}
}
if( options & MOU_LOG ) {
for( i = 0; i < (size_t)nparents; i++ )
printf( "%%ODS2-I-SNAPOK, %s created from %s\n",
devs[i], parfiles[i] );
sts = printmsg( MOUNT_SNAPOK, 0, devs[i], parfiles[i] );
}
options |= MOU_WRITE;
free( parfiles );
@@ -112,42 +153,31 @@ DECL_CMD(mount) {
}
#endif
if (devices > 0) {
sts = mount( options | MOU_LOG, devices, devs, labs );
if( !(sts & STS$M_SUCCESS) )
printf("%%ODS2-E-MOUNTERR, Mount failed with %s\n", getmsg(sts, MSG_TEXT));
}
if( devices > 0 )
sts = mount( options, devices, devs, labs );
free( devs );
free( labs );
return sts;
}
void mounthelp(void) {
printf( "\n" );
printf( "You can mount a volume(-set) from either physical devices\n" );
printf( "such a CDROM or hard disk drive, or files containing an\n" );
printf( "image of a volume, such as a .ISO file or simulator disk\n\n" );
printf( "To mount a disk image, use the %cimage qualifier and\n",
(vms_qual? '/': '-') );
printf( "specify the filename as the parameter.\n\n" );
printf( "If the filename contains %c, specify it in double quotes\n\n",
(vms_qual? '/': '-') );
printf( "Mount will assign a virtual device name to each volume.\n" );
printf( "You can select a virtual device name using the format\n" );
printf( " dka100=my_files.iso\n\n" );
printf( "To mount a physical device, use the format:\n" );
phyio_help(stdout);
printf( "To mount a volume set, specify all the members in RVN order\n" );
printf( "as a comma-separated list.\n\n" );
printf( "If you specify a list of volume labels, they must be in\n" );
printf( "the same order as the volumes, and each must match the label\n" );
printf( "stored in the data\n" );
/*************************************************************** domounthelp() */
DECL_CMD(mounthelp) {
UNUSED( argc );
UNUSED( argv );
UNUSED( qualc );
UNUSED( qualv );
(void) helptopic( 0, "MOUNT", qstyle_s, qstyle_s );
phyio_help();
(void) helptopic( 0, "MOUNT VOLSET" );
#ifdef USE_VHD
printf( "\nTo create and mount a snapshot of a VHD-based volume set, use the %csnapshot_of qualifier.\n", vms_qual? '/': '-' );
printf( "Specify the existing volumes' filenames as an argument to %csnapshot, and\n", vms_qual? '/': '-' );
printf( "list the corresponding filenames to be created as the mount parameter.\n" );
(void) helptopic( 0, "MOUNT VHD", qstyle_s, qstyle_s );
#endif
return;
return SS$_NORMAL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,18 @@
* ods2.h
*/
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _ODS2_H
#define _ODS2_H
@@ -16,29 +28,91 @@
#include "debug.h"
#endif
#include <stdint.h>
typedef uint32_t vmscond_t;
#define $MATCHCOND( c1, c2 ) ( ((c1) & STS$M_FAC_SP)? \
((c1) & STS$M_COND_ID) == ((c2) & STS$M_COND_ID): \
((c1) & STS$M_MSG_NO) == ((c2) & STS$M_MSG_NO) )
#define $SETLEVEL(cond, LEVEL) (((cond) & ~STS$M_SEVERITY) | STS$K_ ## LEVEL)
#define $SETFAC(cond,fac) (((cond) & ~STS$M_FAC_NO) | (fac ## _FACILITY << STS$V_FAC_NO))
#define $SHRMSG(cond,fac,LEVEL) $SETLEVEL((((cond) & STS$M_FAC_SP)? (cond): $SETFAC(cond,fac)),LEVEL)
#define $FAILED(cond) !((cond) & STS$M_SUCCESS)
#define $FAILS(cond) !((cond) & STS$M_SUCCESS)
#define $SUCCESSFUL(cond) (((cond) & STS$M_SUCCESS))
#define $PRINTED(cond) (((cond) & STS$M_INHIB_MSG) != 0)
/* Option bits common to I/O, access, visible outside the ODS-2 parser */
#define MOU_WRITE (1 << 0)
#define MOU_VIRTUAL (1 << 1)
#define MOU_LOG (1 << 2)
#define PHY_CREATE (1 << 3)
#define PHY_VHDDSK (1 << 4)
#define MOU_WRITE OPT_SHARED_1
#define MOU_VIRTUAL OPT_SHARED_2
#define MOU_LOG OPT_SHARED_3
#define PHY_CREATE OPT_SHARED_4
#define PHY_VHDDSK OPT_SHARED_5
#define OS_MOUNTED OPT_SHARED_6
/* OPT_SHARED_7 is free */
/* DEVTYPE can probably be shrunk by several bits */
#define MOU_V_DEVTYPE (OPT_V_SHARED + 8)
#define MOU_DEVTYPE ((((options_t)(1u) << MOU_S_DEVTYPE) -1) << MOU_V_DEVTYPE)
#define MOU_S_DEVTYPE (12)
/* I/O option bits overlaid for use by non-I/O commands */
#define OPT_V_SHARED (0)
#define OPT_SHARED_1 (((options_t)1u) << (OPT_V_SHARED + 0))
#define OPT_SHARED_2 (((options_t)1u) << (OPT_V_SHARED + 1))
#define OPT_SHARED_3 (((options_t)1u) << (OPT_V_SHARED + 2))
#define OPT_SHARED_4 (((options_t)1u) << (OPT_V_SHARED + 3))
#define OPT_SHARED_5 (((options_t)1u) << (OPT_V_SHARED + 4))
#define OPT_SHARED_6 (((options_t)1u) << (OPT_V_SHARED + 5))
#define OPT_SHARED_7 (((options_t)1u) << (OPT_V_SHARED + 6))
#define OPT_SHARED_8 (((options_t)1u) << (OPT_V_SHARED + 7))
#define OPT_SHARED_9 (((options_t)1u) << (OPT_V_SHARED + 8))
#define OPT_SHARED_10 (((options_t)1u) << (OPT_V_SHARED + 9))
#define OPT_SHARED_11 (((options_t)1u) << (OPT_V_SHARED + 10))
#define OPT_SHARED_12 (((options_t)1u) << (OPT_V_SHARED + 11))
#define OPT_SHARED_13 (((options_t)1u) << (OPT_V_SHARED + 12))
#define OPT_SHARED_14 (((options_t)1u) << (OPT_V_SHARED + 13))
#define OPT_SHARED_15 (((options_t)1u) << (OPT_V_SHARED + 14))
#define OPT_SHARED_16 (((options_t)1u) << (OPT_V_SHARED + 15))
#define OPT_SHARED_17 (((options_t)1u) << (OPT_V_SHARED + 16))
#define OPT_SHARED_18 (((options_t)1u) << (OPT_V_SHARED + 17))
#define OPT_SHARED_19 (((options_t)1u) << (OPT_V_SHARED + 18))
#define OPT_SHARED_20 (((options_t)1u) << (OPT_V_SHARED + 19))
#define MOU_V_DEVTYPE (8)
#define MOU_DEVTYPE (0xffff << MOU_V_DEVTYPE)
#define MOU_S_DEVTYPE (16)
/* Option bits that will not conflict with I/O */
#define OPT_GENERIC_1 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 0) )
#define OPT_GENERIC_2 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 1) )
#define OPT_GENERIC_3 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 2) )
#define OPT_GENERIC_4 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 3) )
#define OPT_GENERIC_5 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 4) )
#define OPT_GENERIC_6 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 5) )
#define OPT_GENERIC_7 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 6) )
#define OPT_GENERIC_8 (1 << (MOU_V_DEVTYPE + MOU_S_DEVTYPE + 7) )
#define OPT_V_GENERIC (MOU_V_DEVTYPE + MOU_S_DEVTYPE)
#define OPT_GENERIC_1 ((options_t)(1u << (OPT_V_GENERIC + 0)))
#define OPT_GENERIC_2 ((options_t)(1u << (OPT_V_GENERIC + 1)))
#define OPT_GENERIC_3 ((options_t)(1u << (OPT_V_GENERIC + 2)))
#define OPT_GENERIC_4 ((options_t)(1u << (OPT_V_GENERIC + 3)))
#define OPT_GENERIC_5 ((options_t)(1u << (OPT_V_GENERIC + 4)))
#define OPT_GENERIC_6 ((options_t)(1u << (OPT_V_GENERIC + 5)))
#define OPT_GENERIC_7 ((options_t)(1u << (OPT_V_GENERIC + 6)))
#define OPT_GENERIC_8 ((options_t)(1u << (OPT_V_GENERIC + 7)))
#define OPT_GENERIC_9 ((options_t)(1u << (OPT_V_GENERIC + 8)))
#define OPT_GENERIC_10 ((options_t)(1u << (OPT_V_GENERIC + 9)))
#define OPT_GENERIC_11 ((options_t)(1u << (OPT_V_GENERIC + 10)))
#define OPT_GENERIC_12 ((options_t)(1u << (OPT_V_GENERIC + 11)))
#define OPT_NOSORT (1 << 31)
#if (OPT_V_GENERIC+11 > 31)
#error options_t overflow, change size or definitions in ods2.h
#endif
/* This bit is set in the table end marker and does not overlap the
* data bits. The decision to sort is made after a scan of the entire
* table that computes some statistics that do not depend on order.
*/
#define OPT_NOSORT ((options_t)(1u << 31))
typedef int32_t options_t;
#endif /* #ifndef _ODS2_H */

View File

@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,1
PRODUCTVERSION 2,0,0,1
FILEVERSION 3,0,0,0
PRODUCTVERSION 3,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -44,17 +44,17 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "This application reads ODS-2 (VMS) disks under Windows NT and Windows 2000\0"
VALUE "CompanyName", "Paul Nankervis <paulnank@au1.ibm.com>\0"
VALUE "FileDescription", "ODS-2 Reader for Windows (Modified)\0"
VALUE "FileVersion", "V2.1\0"
VALUE "Comments", "ODS-2 (VMS) disk reader/writer for Windows NT-based OS\0"
VALUE "CompanyName", "Paul Nankervis <paulnank@au1.ibm.com>, Timothe Litt <litt@acm.org>\0"
VALUE "FileDescription", "ODS-2 Reader/Writer for Windows (Modified)\0"
VALUE "FileVersion", "V3.0\0"
VALUE "InternalName", "ODS2\0"
VALUE "LegalCopyright", "Copyright <EFBFBD> 2001, 2016\0"
VALUE "LegalCopyright", "Copyright \251 2001, 2016, 2022\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "ODS2.EXE\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "ODS2\0"
VALUE "ProductVersion", "V2.1\0"
VALUE "ProductVersion", "V3.0.0.0\0"
VALUE "SpecialBuild", "\0"
END
END

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,44 +1,49 @@
/* Phyio.h Definition of Physical I/O 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* 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_path() returns the full path of the supplied filnam.a The
returned character string must be deallocated by the
caller.
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_done() makes a device unavailable.
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.
*/
* 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_path() returns the full path of the supplied filnam.a The
* returned character string must be deallocated by the
* caller.
* 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_done() makes a device unavailable.
* 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.
*/
#ifndef _PHYIO_H
#define _PHYIO_H
#include <stdint.h>
#include <stdio.h>
#include "ods2.h"
#define PHYIO_READONLY 1
typedef enum showtype {
@@ -50,15 +55,14 @@ typedef enum showtype {
struct DEV;
void phyio_show( showtype_t type );
char *phyio_path( const char *filnam );
unsigned phyio_init( struct DEV *dev );
unsigned phyio_done( struct DEV *dev );
vmscond_t phyio_init( struct DEV *dev );
vmscond_t phyio_done( struct DEV *dev );
typedef unsigned (*phy_iord_t)( struct DEV *dev, unsigned block, unsigned length,
char *buffer );
typedef unsigned (*phy_iowr_t)( struct DEV *dev, unsigned block, unsigned length,
const char *buffer );
typedef vmscond_t( *phy_iord_t )( struct DEV *dev, uint32_t block,
uint32_t length, char *buffer );
typedef vmscond_t( *phy_iowr_t )( struct DEV *dev, uint32_t block,
uint32_t length, const char *buffer );
void phyio_help(FILE *fp );
void phyio_help( void );
#endif /* #ifndef _PHYIO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,28 @@
/* PHYOS2.C v1.2 Physical I/O module for OS2 */
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* This version implemented to read from Floppy or CD by
guessing that A: or B: will be a floppy and anything
else is probably a CD? */
* guessing that A: or B: will be a floppy and anything
* else is probably a CD?
*/
/* This module has not been compiled in quite some time, and
* while some effort has been made to keep up with API changes,
* it requires quite a bit of work to bring it up to date.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
@@ -12,22 +30,33 @@
#define INCL_DOSDEVIOCTL
#define INCL_NOPMAPI
#include <os2.h>
#include "ods2.h"
#include "phyio.h"
#include "ssdef.h"
#include "sysmsg.h"
static unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
char *buffer );
static unsigned phyio_write( struct DEV *dev, unsigned block, unsigned length,
const char *buffer );
static vmscond_t phyio_read( struct DEV *dev, uint32_t block, uint32_t length,
char *buffer );
static vmscond_t phyio_write( struct DEV *dev, uint32_t block, uint32_t length,
const char *buffer );
unsigned init_count = 0;
unsigned read_count = 0;
unsigned write_count = 0;
void phyio_show(void)
{
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
init_count,read_count,write_count);
void phyio_show( showtype_t type ) {
switch( type ) {
case SHOW_STATS:
printmsg( IO_STATS, MSG_TEXT, init_count, read_count, write_count );
return;
case SHOW_FILE64:
printmsg( IO_NOLARGEFILE, MSG_TEXT );
return;
case SHOW_DEVICES:
return;
default:
abort();
}
}
@@ -64,23 +93,19 @@ 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" );
void phyio_help( void ) {
(void) helptopic( 0, "MOUNT OS2" );
return;
}
NOTE: This will not compile. The API for phyio_init has changed to
taking a DEV struct. I'm leaving it this way becauses I don't have the
ability to test under OS2. This was left undone when the API was changed...
before my time.
before my time. /TL
unsigned phyio_init(int devlen,char *devnam,unsigned *hand,struct phyio_info *info)
{
vmscond_t phyio_init(int devlen,char *devnam,unsigned *hand,struct phyio_info *info) {
dev->devread = phyio_read;
dev->devwrite = phyio_write;
@@ -149,9 +174,7 @@ unsigned phyio_init(int devlen,char *devnam,unsigned *hand,struct phyio_info *in
}
}
unsigned phy_getsect(HFILE hfile,unsigned sector,char *buffer)
{
static vmscond_t phy_getsect(HFILE hfile, uint32_t sector,char *buffer) {
ULONG ulPinout,ulDinout;
ULONG stat;
char rawsect[SECTORSIZE + 304];
@@ -171,13 +194,8 @@ unsigned phy_getsect(HFILE hfile,unsigned sector,char *buffer)
return 1;
}
static unsigned phyio_read(unsigned handno,unsigned block,unsigned length,char *buffer)
{
register unsigned sts = 1;
static vmscond_t phyio_read(unsigned handno, uint32_t block, uint32_t length, char *buffer) {
register vmscond_t sts = SS$_NORMAL;
#if DEBUG
printf("PHYIO_READ block %d length %d\n",block,length);
#endif
@@ -215,7 +233,7 @@ static unsigned phyio_read(unsigned handno,unsigned block,unsigned length,char *
}
}
}
if (sts & 1) {
if( $SUCCESSFUL(sts) ) {
read_count++;
} else {
printf("PHYOS2 Error %d Block %d Length %d\n",sts,block,length);
@@ -223,9 +241,7 @@ static unsigned phyio_read(unsigned handno,unsigned block,unsigned length,char *
return sts;
}
static unsigned phyio_write(unsigned handle,unsigned block,unsigned length,char *buffer)
{
static vmscond_t phyio_write(unsigned handle, uint32_t block, uint32_t length, char *buffer) {
write_count++;
return SS$_WRITLCK;
}

View File

@@ -1,13 +1,16 @@
/* PHYUNIX.c Physical I/O module for Unix */
/*
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.
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/*
@@ -21,7 +24,8 @@
/* DO NOT MOVE THIS DEFINITION */
/* */
#ifndef _FILE_OFFSET_BITS /* */
#define _FILE_OFFSET_BITS 64 /* 64-bit off_t (glibc V2.2.x and later) */
#error _FILE_OFFSET_BITS must be defined in the makefile */
/* It MUST be consistent across all modules. */
#endif /* */
/* */
/******************************************************************************/
@@ -47,6 +51,7 @@
#include <sys/types.h>
#include <unistd.h>
#include "cmddef.h"
#include "device.h"
#include "ods2.h"
#include "phyio.h"
@@ -74,17 +79,243 @@ struct devdat {
unsigned high;
};
static unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
char *buffer );
static unsigned phyio_write( struct DEV *dev, unsigned block, unsigned length,
const char *buffer );
static vmscond_t phyio_read( struct DEV *dev, uint32_t block, uint32_t length,
char *buffer );
static vmscond_t phyio_write( struct DEV *dev, uint32_t block, uint32_t length,
const char *buffer );
static void showdevs( void );
static int devcmp( const void *d1, const void *d2 );
/*************************************************************** showdevs() */
/*************************************************************** phyio_init() */
static int devcmp( const void *d1, const void *d2 ) {
return strcmp( ((struct devdat *)d1)->name, ((struct devdat *)d2)->name );
unsigned phyio_init( struct DEV *dev ) {
vmscond_t sts = SS$_NORMAL;
size_t n;
int fd, oflags, saverr = 0;
char *device;
struct stat statbuf;
init_count++;
dev->handle = -1;
dev->devread = phyio_read;
dev->devwrite = phyio_write;
if( dev->access & MOU_VIRTUAL ) {
const char *virtual;
virtual = virt_lookup( dev->devnam );
if ( virtual == NULL ) {
return SS$_NOSUCHDEV;
}
n = strlen( virtual );
device = (char *) malloc( n + 1 );
if( device == NULL )
return SS$_INSFMEM;
memcpy( device, virtual, n + 1 );
} else {
n = sizeof( DEV_PREFIX ) + strlen( dev->devnam );
device = (char *) malloc( n );
if ( device == NULL )
return SS$_INSFMEM;
memcpy( device, DEV_PREFIX, sizeof( DEV_PREFIX ) -1 );
memcpy( device+sizeof( DEV_PREFIX ) -1, dev->devnam, n +1 - sizeof( DEV_PREFIX ) );
device[n - 2] = '\0'; /* Remove ':' from device name */
}
oflags = (dev->access & MOU_WRITE )? O_RDWR : O_RDONLY;
if( (dev->access & (MOU_VIRTUAL|PHY_CREATE)) == (MOU_VIRTUAL|PHY_CREATE) )
oflags |= O_CREAT | O_EXCL;
fd = open( device, oflags, 0644 );
if( fd < 0 )
saverr = errno;
#if DEBUG
printf( "%d = open( \"%s\", %s%s )\n", fd, device,
(dev->access & MOU_WRITE )? "O_RDWR" : "O_RDONLY",
(dev->access & PHY_CREATE)? "|O_CREAT|O_EXCL, 0666" : "" );
#endif
if ( fd < 0 && (dev->access & (MOU_WRITE|PHY_CREATE)) == MOU_WRITE ) {
dev->access &= ~MOU_WRITE;
fd = open( device, O_RDONLY );
#if DEBUG
printf( "%d = open( \"%s\", O_RDONLY )\n", fd, device );
#endif
}
dev->handle = fd;
if( fd >= 0 ) {
if( fstat( fd, &statbuf ) == 0 ) {
if( dev->access & MOU_VIRTUAL ) {
if( !S_ISREG(statbuf.st_mode) ) {
sts = printmsg( IO_UNXNOTREG, 0, device );
close( fd );
dev->handle = -1;
} else
dev->eofptr = statbuf.st_size;
} else {
if( !S_ISBLK(statbuf.st_mode ) ) {
sts = printmsg( IO_UNXNOTBLK, 0, device );
close( fd );
dev->handle = -1;
}
}
} else {
if( !saverr )
saverr = errno;
close( fd );
dev->handle = -1;
fd = -1;
}
}
if ( fd < 0 ) {
switch( saverr ) {
case EEXIST:
printmsg( IO_EXISTS, 0, device );
sts = SS$_DUPFILENAME | STS$M_INHIB_MSG;
break;
default:
printmsg( IO_OPENDEV, 0, device );
printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_OPENDEV, strerror( saverr ) );
sts = ((dev->access & MOU_VIRTUAL) ? SS$_NOSUCHFILE : SS$_NOSUCHDEV) |
STS$M_INHIB_MSG;
}
}
free( device );
return sts;
}
/*************************************************************** phyio_done() */
vmscond_t phyio_done( struct DEV *dev ) {
if( dev->handle != -1 )
close( dev->handle );
dev->handle = -1;
return SS$_NORMAL;
}
/*************************************************************** phyio_read() */
static vmscond_t phyio_read( struct DEV *dev, uint32_t block,
uint32_t length, char *buffer ) {
vmscond_t sts;
ssize_t res;
off_t pos;
#if DEBUG
printf("Phyio read block: %d into %p (%d bytes)\n",
block, buffer, length );
#endif
read_count++;
pos = (off_t) block * (off_t) 512;
if( (pos = lseek( dev->handle, pos, SEEK_SET )) < 0 ) {
int err;
err = errno;
printmsg( IO_SEEKERR, block );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_SEEKERR, strerror(err) );
return sts;
}
if( (res = read( dev->handle, buffer, length )) != (ssize_t)length ) {
int err;
if( res == 0 ) {
return SS$_ENDOFFILE;
}
err = errno;
printmsg( IO_READERR, 0, block );
if( res == (off_t)-1 ) {
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_READERR, strerror(err) );
} else {
sts = printmsg( IO_READLEN, MSG_CONTINUE, IO_READERR,
block, (uint32_t)res, length );
}
return sts;
}
return SS$_NORMAL;
}
/************************************************************** phyio_write() */
static vmscond_t phyio_write( struct DEV *dev, uint32_t block,
uint32_t length, const char *buffer ) {
vmscond_t sts;
off_t pos;
ssize_t res;
#if DEBUG
printf("Phyio write block: %d from %p (%d bytes)\n",
block, buffer, length );
#endif
write_count++;
pos = (off_t) block * (off_t) 512;
if( ( pos = lseek( dev->handle, pos, SEEK_SET ) ) < 0 ) {
int err;
err = errno;
printmsg( IO_SEEKERR, block );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_SEEKERR, strerror(err) );
return sts;
}
if( ( res = write( dev->handle, buffer, length ) ) != (ssize_t)length ) {
int err;
err = errno;
printmsg( IO_WRITEERR, 0, block );
if( res == (off_t)-1 ) {
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_WRITEERR, strerror(err) );
} else {
sts = printmsg( IO_WRITELEN, MSG_CONTINUE, IO_WRITEERR,
block, (uint32_t)res, length );
}
return sts;
}
return SS$_NORMAL;
}
/*************************************************************** phyio_help() */
void phyio_help( void ) {
char devpfx[] = { DEV_PREFIX };
devpfx[ sizeof( devpfx ) -2 ] = '\0'; /* Remove trailing '/' */
(void) helptopic( 0, "MOUNT UNIX", devpfx, DEV_PREFIX "cdrom0" );
return;
}
/*************************************************************** phyio_show() */
void phyio_show( showtype_t type ) {
switch( type ) {
case SHOW_STATS:
printmsg( IO_STATS, MSG_TEXT, init_count, read_count, write_count );
return;
case SHOW_FILE64:
printmsg( (sizeof( off_t ) < 8)? IO_NOLARGEFILE: IO_LARGEFILE, MSG_TEXT );
return;
case SHOW_DEVICES:
printmsg( IO_UNXDEVHDR, MSG_TEXT );
showdevs();
return;
default:
abort();
}
}
/*************************************************************** showdevs() */
static void showdevs( void ) {
DIR *dirp;
size_t i, cpl, n = 0, max = 0;
@@ -106,14 +337,17 @@ static void showdevs( void ) {
break;
len = strlen( dp->d_name );
fs = malloc( sizeof( DEV_PREFIX ) + len );
if( fs == NULL )
if( (fs = malloc( sizeof( DEV_PREFIX ) + len )) == NULL )
break;
memcpy( fs, DEV_PREFIX, sizeof( DEV_PREFIX ) -1 );
memcpy( fs + sizeof( DEV_PREFIX ) -1, dp->d_name, len +1 );
if( stat( fs, &stb ) == -1 ) {
perror( fs );
int err;
err = errno;
printmsg( IO_DIRRDERR, 0, fs );
printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_DIRRDERR, strerror( err ) );
free( fs );
continue;
}
@@ -154,8 +388,11 @@ static void showdevs( void ) {
(void) closedir(dirp);
}
if( errno != 0 ) {
printf( "%%ODS2-W-DIRERR, Error reading %s\n", DEV_PREFIX );
perror( " - " );
int err;
err = errno;
printmsg( IO_DIRRDERR, 0, DEV_PREFIX );
printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_DIRRDERR, strerror( err ) );
for( i = 0; i < n; i++ )
free( (*list)[i].name );
free( list );
@@ -163,7 +400,7 @@ static void showdevs( void ) {
}
if( n == 0 ) {
printf( "%%ODS2-I-NODEV, No devices found\n" );
printmsg( IO_NODEVS, 0 );
return;
}
@@ -208,236 +445,8 @@ static void showdevs( void ) {
return;
}
/*************************************************************** phyio_show() */
/*************************************************************** devcmp() */
void phyio_show( showtype_t type ) {
switch( type ) {
case SHOW_STATS:
printf( "PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
init_count, read_count, write_count );
return;
case SHOW_FILE64:
printf( "Large ODS-2 image files (>2GB) are %ssupported.\n",
(sizeof( off_t ) < 8)? "NOT ": "" );
return;
case SHOW_DEVICES:
printf( " Physical devices\n" );
showdevs();
return;
default:
abort();
}
}
void phyio_help(FILE *fp ) {
fprintf( fp, " mount device\nThe device must be in %.*s.\n\n",
(int)(sizeof( DEV_PREFIX ) -2), DEV_PREFIX );
fprintf( fp, "For example, if you are using " DEV_PREFIX "%s\n", "cdrom0" );
fprintf( fp, " ODS2$> mount cdrom0\n" );
fprintf( fp, "For a list of devices, see SHOW DEVICES\n\n" );
return;
}
/*************************************************************** phyio_path() */
char *phyio_path( const char *filnam ) {
size_t n;
char *path, resolved_path[PATH_MAX+1];
if ( filnam == NULL || realpath( filnam, resolved_path ) == NULL ) {
return NULL;
}
n = strlen( resolved_path );
path = (char *) malloc( n + 1 );
if ( path != NULL ) {
memcpy( path, resolved_path, n + 1 );
}
return path;
}
/*************************************************************** phyio_init() */
unsigned phyio_init( struct DEV *dev ) {
int sts = SS$_NORMAL;
size_t n;
int fd, saverr = 0;
char *device;
const char *virtual;
struct stat statbuf;
init_count++;
dev->handle = -1;
dev->devread = phyio_read;
dev->devwrite = phyio_write;
if( dev->access & MOU_VIRTUAL ) {
virtual = virt_lookup( dev->devnam );
if ( virtual == NULL ) {
return SS$_NOSUCHDEV;
}
n = strlen( virtual );
device = (char *) malloc( n + 1 );
if( device == NULL )
return SS$_INSFMEM;
memcpy( device, virtual, n + 1 );
} else {
n = sizeof( DEV_PREFIX ) + strlen( dev->devnam );
device = (char *) malloc( n );
if ( device == NULL )
return SS$_INSFMEM;
memcpy( device, DEV_PREFIX, sizeof( DEV_PREFIX ) -1 );
memcpy( device+sizeof( DEV_PREFIX ) -1, dev->devnam, n +1 - sizeof( DEV_PREFIX ) );
device[n - 2] = '\0'; /* Remove : from device name */
}
fd = open( device,
((dev->access & MOU_WRITE )? O_RDWR : O_RDONLY) |
((dev->access & (MOU_VIRTUAL|PHY_CREATE)) == (MOU_VIRTUAL|PHY_CREATE)?
O_CREAT | O_EXCL : 0),
0644 );
if( fd < 0 )
saverr = errno;
#if DEBUG
printf( "%d = open( \"%s\", %s%s )\n", fd, device,
(dev->access & MOU_WRITE )? "O_RDWR" : "O_RDONLY",
(dev->access & PHY_CREATE)? "|O_CREAT|O_EXCL, 0666" : "" );
#endif
if ( fd < 0 && (dev->access & (MOU_WRITE|PHY_CREATE)) == MOU_WRITE ) {
dev->access &= ~MOU_WRITE;
fd = open( device, O_RDONLY );
#if DEBUG
printf( "%d = open( \"%s\", O_RDONLY )\n", fd, device );
#endif
}
dev->handle = fd;
if( fd >= 0 ) {
if( fstat( fd, &statbuf ) == 0 ) {
if( dev->access & MOU_VIRTUAL ) {
if( !S_ISREG(statbuf.st_mode) ) {
printf( "%%ODS2-E-NOTFILE, %s is not a regular file\n", device );
close( fd );
dev->handle = -1;
sts = SS$_IVDEVNAM;
} else
dev->eofptr = statbuf.st_size;
} else {
if( !S_ISBLK(statbuf.st_mode ) ) {
printf( "%%ODS2-E-NOTFILE, %s is not a block device\n", device );
close( fd );
dev->handle = -1;
sts = SS$_IVDEVNAM;
}
}
} else {
if( !saverr )
saverr = errno;
close( fd );
dev->handle = -1;
fd = -1;
}
}
if ( fd < 0 ) {
#if DEBUG
errno = saverr;
perror( "open" );
#endif
errno = saverr;
switch( errno ) {
case EEXIST:
printf( "%%ODS2-E-EXISTS, File %s already exists, not superseded\n", device );
sts = SS$_DUPFILENAME;
break;
default:
printf( "%%ODS2-E-OPENERR, Open %s: %s\n", device, strerror( errno ) );
sts = (dev->access & MOU_VIRTUAL) ? SS$_NOSUCHFILE : SS$_NOSUCHDEV;
}
}
free( device );
return sts;
}
/*************************************************************** phyio_done() */
unsigned phyio_done( struct DEV *dev ) {
if( dev->handle != -1 )
close( dev->handle );
dev->handle = -1;
return SS$_NORMAL;
}
/*************************************************************** phyio_read() */
static unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
char *buffer ) {
ssize_t res;
off_t pos;
#if DEBUG
printf("Phyio read block: %d into %p (%d bytes)\n",
block, buffer, length );
#endif
read_count++;
pos = (off_t) block * (off_t) 512;
if ( ( pos = lseek( dev->handle, pos, SEEK_SET ) ) < 0 ) {
perror( "lseek " );
printf("lseek failed %" PRIuMAX "\n",(uintmax_t)pos);
return SS$_PARITY;
}
if ( ( res = read( dev->handle, buffer, length ) ) != length ) {
if( res == 0 ) {
return SS$_ENDOFFILE;
}
if( res == (off_t)-1 ) {
perror( "%%ODS2-F-READERR, read failed" );
} else {
printf( "%%ODS2-F-READERR, read failed with bc = %" PRIuMAX " for length %u, lbn %u\n",
(uintmax_t)res, length, block );
}
return SS$_PARITY;
}
return SS$_NORMAL;
}
/************************************************************** phyio_write() */
static unsigned phyio_write( struct DEV *dev, unsigned block, unsigned length,
const char *buffer ) {
off_t pos;
ssize_t res;
#if DEBUG
printf("Phyio write block: %d from %p (%d bytes)\n",
block, buffer, length );
#endif
write_count++;
pos = (off_t) block * (off_t) 512;
if ( ( pos = lseek( dev->handle, pos, SEEK_SET ) ) < 0 ) {
perror( "lseek " );
printf( "lseek failed %" PRIuMAX "\n", (uintmax_t)pos );
return SS$_PARITY;
}
if ( ( res = write( dev->handle, buffer, length ) ) != length ) {
if( res == (off_t)-1 ) {
perror( "%%ODS2-F-WRITEERR, write failed" );
} else {
printf( "%%ODS2-F-WRITEERR, write failed with bc = %" PRIuMAX " for length %u, lbn %u\n",
(uintmax_t)res, length, block );
}
return SS$_PARITY;
}
return SS$_NORMAL;
static int devcmp( const void *d1, const void *d2 ) {
return strcmp( ((struct devdat *)d1)->name, ((struct devdat *)d2)->name );
}

View File

@@ -14,7 +14,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_PHYVHD )
@@ -30,7 +33,7 @@
#endif
#ifndef phyvhd_MINSIZE
#define phyvhd_MINSIZE (20 * 1000 * 1000)
#define phyvhd_MINSIZE (0)
#endif
#include <errno.h>
@@ -48,13 +51,16 @@
#define _aligned_free free
#endif
#include "compat.h"
#include "device.h"
#include "ods2.h"
#include "phyvirt.h"
#include "ssdef.h"
#include "stsdef.h"
#include "sysmsg.h"
#include "libvhd.h"
#include "phyvhd.h"
typedef vhd_context_t *vhd_contextp;
typedef vhd_context_t vhd_context;
@@ -98,12 +104,11 @@ static void *libvhd = NULL;
#define vhdresolve(s) do { \
if( libvhd != NULL && \
(s ## _fcn = (s ## _p)dlsym( libvhd, #s )) == NULL ) { \
printf( "VHD format image files can not be used\n" ); \
printf( "%%ODS2-F-NOSYM, Missing symbol %s in " LIBVHDSO(USE_LIBVHD) "\n", #s ); \
printmsg( IO_VHDNOSYM, 0, #s, LIBVHDSO(USE_LIBVHD) ); \
dlclose( libvhd ); \
libvhd = NULL; \
} \
} while( 0 )
} while( 0 )
#else
#define vhd_open_fcn vhd_open
@@ -120,10 +125,10 @@ static void *libvhd = NULL;
#endif
static unsigned phyvhd_read( struct DEV *dev, unsigned lbn, unsigned length,
char *buffer );
static unsigned phyvhd_write( struct DEV *dev, unsigned lbn, unsigned length,
const char *buffer );
static vmscond_t phyvhd_read( struct DEV *dev, uint32_t lbn, uint32_t length,
char *buffer );
static vmscond_t phyvhd_write( struct DEV *dev, uint32_t lbn, uint32_t length,
const char *buffer );
/*********************************************************** phyvhd_available() */
int phyvhd_available( int query ) {
@@ -136,13 +141,11 @@ int phyvhd_available( int query ) {
const char *err;
if( query )
printf( "VHD format image file support is configud, but not available\n" );
printmsg( IO_VHDNOTAVAIL, MSG_TEXT );
printf( "%%ODS2-F-NOLIB, " LIBVHDSO(USE_LIBVHD) " not could not be loaded (see vhdtools or XEN libraries)" );
printmsg( IO_VHDNOLIB, 0, LIBVHDSO(USE_LIBVHD) );
if( (err = dlerror()) != NULL )
printf( ": %s\n", err );
else
putchar( '\n' );
printmsg( ODS2_OSERROR, MSG_CONTINUE, O_VHDNOLIB, err );
return FALSE;
}
@@ -157,14 +160,15 @@ int phyvhd_available( int query ) {
vhdresolve( vhd_io_write );
if( libvhd == NULL ) {
printf( "%%ODS2-F-BADLIB, the " LIBVHDSO(USE_LIBVHD) " library is not valid\n" );
printmsg( IO_VHDNOTVALID, MSG_CONTINUE,
IO_VHDNOSYM, LIBVHDSO(USE_LIBVHD) );
return FALSE;
}
}
#endif
if( query )
printf( "VHD format image files can be used\n" );
printmsg( IO_VHDAVAIL, MSG_TEXT );
return TRUE;
}
@@ -174,29 +178,35 @@ int phyvhd_available( int query ) {
#pragma warning(disable: 4996) /* MS complains about _open, which is open() */
#endif
/*********************************************************** phyvhd_snapshot() */
unsigned phyvhd_snapshot( const char *filename, const char *parent ) {
vmscond_t phyvhd_snapshot( const char *filename, const char *parent ) {
int fd, err;
char *p;
if( !( (p = strrchr( filename, '.')) != NULL && ( !strcmp( p, ".vhd" ) ||
!strcmp( p, ".VHD" ) ) ) ) {
printf( "%%ODS2-E-NOTVHD, %s: Snapshots can only be taken of VHD format image files\n", filename );
return SS$_DUPFILENAME;
return printmsg( IO_VHDONLY, 0, filename );
}
#ifdef USE_LIBVHD
if( libvhd == NULL && !phyvhd_available( FALSE ) )
return SS$_NOTINSTALL;
return IO_VHDNOTVALID | STS$M_INHIB_MSG;
#endif
#ifdef _WIN32
fd = _open( filename, _O_RDWR | _O_CREAT | _O_EXCL, 0644 );
fd = _open( filename, _O_BINARY | _O_RDWR | _O_CREAT | _O_EXCL, 0644 );
#else
fd = open( filename, O_RDWR | O_CREAT | O_EXCL, 0644 );
#endif
if( fd == -1 ) {
printf( "%%ODS2-E-EXISTS, %s already exists\n", filename );
return SS$_DUPFILENAME;
int err;
if( errno == EEXIST ) {
printmsg( IO_EXISTS, 0, filename );
return SS$_DUPFILENAME | STS$M_INHIB_MSG;
}
err = errno;
printmsg( IO_OPENDEV, 0, filename );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_OPENDEV, strerror( err ) );
}
err = vhd_snapshot_fcn( filename, 0, parent, 0 );
close( fd );
@@ -204,14 +214,12 @@ unsigned phyvhd_snapshot( const char *filename, const char *parent ) {
if( err == 0 )
return SS$_NORMAL;
printf( "%%ODS2-E-NOSNAP, snapshot failed\n" );
errno = -err;
perror( " - " );
return SS$_DEVOFFLINE;
printmsg( IO_VHDSNAPFAIL, 0, parent );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_VHDSNAPFAIL, strerror( -err ) );
}
/*********************************************************** phyvhd_init() */
unsigned phyvhd_init( struct DEV *dev ) {
vmscond_t phyvhd_init( struct DEV *dev ) {
int err;
char *fname;
unsigned status;
@@ -229,7 +237,7 @@ unsigned phyvhd_init( struct DEV *dev ) {
#ifdef USE_LIBVHD
if( libvhd == NULL && !phyvhd_available( FALSE ) )
return SS$_NOTINSTALL;
return IO_VHDNOTVALID | STS$M_INHIB_MSG;
#endif
libvhd_set_log_level_fcn( -1 );
@@ -242,27 +250,23 @@ unsigned phyvhd_init( struct DEV *dev ) {
#ifdef _WIN32
if( (dev->IoBuffer = _aligned_malloc( phyvhd_BUFSIZE, align )) == NULL ) {
printf( "Unable to allocate memory for bufer\n" );
return SS$_INSFMEM;
return printmsg( IO_VHDMEM, 0 );
}
if( (dev->context = _aligned_malloc( sizeof( vhd_context ), align )) == NULL ) {
printf( "Unable to allocate memory for context\n" );
_aligned_free(dev->IoBuffer);
dev->IoBuffer = NULL;
return SS$_INSFMEM;
return printmsg( IO_VHDMEM, 0 );
}
#else
if( posix_memalign( (void**)&dev->IoBuffer, align, phyvhd_BUFSIZE ) != 0 ) {
printf( "Unable to allocate memory for bufer\n" );
return SS$_INSFMEM;
return printmsg( IO_VHDMEM, 0 );
}
if( posix_memalign( (void**)&dev->context, align,
sizeof( vhd_context ) ) != 0 ) {
printf( "Unable to allocate memory for context\n" );
free(dev->IoBuffer);
dev->IoBuffer = NULL;
return SS$_INSFMEM;
return printmsg( IO_VHDMEM, 0 );
}
#endif
@@ -272,38 +276,41 @@ unsigned phyvhd_init( struct DEV *dev ) {
if( dev->access & PHY_CREATE ) {
disktypep_t dp;
uint64_t size;
int fd;
int fd;
#ifdef _WIN32
fd = _open( fname, _O_RDWR | _O_CREAT | _O_EXCL, 0644 );
fd = _open( fname, _O_BINARY | _O_RDWR | _O_CREAT | _O_EXCL, 0644 );
#else
fd = open( fname, O_RDWR | O_CREAT | O_EXCL, 0644 );
#endif
if( fd == -1 ) {
close( fd );
status = SS$_DUPFILENAME;
break;
}
if( dev->access & MOU_LOG )
printf( "%%ODS2-I-VHDINIT, Formatting %s\n", fname );
printmsg( IO_VHDFMTSTART, 0, fname );
dp = dev->disktype;
size = ((uint64_t)dp->sectors) * dp->tracks * dp->cylinders * dp->sectorsize;
size = (size + 511) / 512;
size *= 512;
#if phyvhd_MINSIZE == 0
err = vhd_create_fcn( fname, size, HD_TYPE_DYNAMIC, 0 );
#else
err = vhd_create_fcn( fname, size, (size >= phyvhd_MINSIZE?
HD_TYPE_DYNAMIC: HD_TYPE_FIXED),
0 );
#endif
close( fd );
if( err != 0 ) {
errno = -err;
perror( "vhd create" );
status = SS$_NOSUCHDEV;
printmsg( IO_VHDCREATEERR, 0, fname );
status = printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_VHDCREATEERR,
strerror( -err ) );
break;
}
if( dev->access & MOU_LOG )
printf( "%%ODS2-I-VHDDONE, VHD volume formatting completed\n" );
printmsg( IO_VHDFMTEND, 0 );
}
err = vhd_open_fcn( dev->context, fname,
(dev->access & MOU_WRITE)?
@@ -314,18 +321,18 @@ unsigned phyvhd_init( struct DEV *dev ) {
err = vhd_open_fcn( dev->context, fname, VHD_OPEN_RDONLY | VHD_OPEN_STRICT );
}
if( err != 0 ) {
errno = -err;
perror( "vhd open" );
status = SS$_NOSUCHDEV;
printmsg( IO_OPENDEV, 0, fname );
status = printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_OPENDEV,
strerror( -err ) );
break;
}
if( (dev->access & MOU_WRITE) && ((vhd_contextp)dev->context)->footer.saved ) {
printf( "%%ODS2-W-VHDSAVED, %s contains a suspended system and should not be modified\n", fname );
printmsg( IO_VHDSAVED, 0, fname );
}
dev->eofptr = (off_t)(((vhd_contextp)dev->context)->footer.curr_size);
} while( 0 );
if( !(status & STS$M_SUCCESS) ) {
if( $FAILED(status) ) {
_aligned_free( dev->context );
_aligned_free( dev->IoBuffer );
dev->context =
@@ -371,14 +378,14 @@ void phyvhd_show( struct DEV *dev, size_t column ) {
return;
}
/*********************************************************** phyvhd_read() */
static unsigned phyvhd_read( struct DEV *dev, unsigned lbn, unsigned length,
char *buffer ) {
unsigned status;
static vmscond_t phyvhd_read( struct DEV *dev, uint32_t lbn,
uint32_t length, char *buffer ) {
vmscond_t status;
int err;
status = SS$_NORMAL;
while( length > 0 ) {
unsigned rdsize;
uint32_t rdsize;
rdsize = (length + 511) / 512;
rdsize = ( (rdsize > phyvhd_BUFSIZE/512)?
@@ -386,8 +393,10 @@ static unsigned phyvhd_read( struct DEV *dev, unsigned lbn, unsigned length,
if( (err = vhd_io_read_fcn(dev->context, dev->IoBuffer, lbn, rdsize)) != 0 ) {
if( err == -ERANGE )
return SS$_ILLBLKNUM;
return SS$_PARITY;
return printmsg( IO_RDBLK2BIG, 0, lbn );
printmsg( IO_READERR, 0, lbn );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_READERR,
strerror( -err ) );
}
lbn += rdsize;
rdsize *= 512;
@@ -403,14 +412,14 @@ static unsigned phyvhd_read( struct DEV *dev, unsigned lbn, unsigned length,
/*********************************************************** phyvhd_write() */
static unsigned phyvhd_write( struct DEV *dev, unsigned lbn, unsigned length,
const char *buffer ) {
unsigned status;
static vmscond_t phyvhd_write( struct DEV *dev, uint32_t lbn,
uint32_t length, const char *buffer ) {
vmscond_t status;
int err;
status = SS$_NORMAL;
while( length > 0 ) {
unsigned wrsize, iosize;
uint32_t wrsize, iosize;
iosize = (length + 511) / 512;
iosize = ( (iosize > phyvhd_BUFSIZE/512)?
@@ -425,8 +434,10 @@ static unsigned phyvhd_write( struct DEV *dev, unsigned lbn, unsigned length,
if( (err = vhd_io_write_fcn(dev->context, dev->IoBuffer, lbn, iosize)) != 0 ) {
if( err == -ERANGE )
return SS$_ILLBLKNUM;
return SS$_PARITY;
return printmsg( IO_WRBLK2BIG, 0, lbn );
printmsg( IO_WRITEERR, 0, lbn );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_WRITEERR,
strerror( -err ) );
}
lbn += iosize;
}
@@ -434,7 +445,7 @@ static unsigned phyvhd_write( struct DEV *dev, unsigned lbn, unsigned length,
}
/*********************************************************** phyvhd_close() */
unsigned phyvhd_close( struct DEV *dev ) {
vmscond_t phyvhd_close( struct DEV *dev ) {
if( dev->context != NULL ) {
vhd_close_fcn( dev->context );
_aligned_free( dev->context );

View File

@@ -1,11 +1,26 @@
/*
* This is distributed as part of ODS2, originally 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _PHYVHD_H
#define _PHYVHD_H 1
#include "ods2.h"
struct DEV;
unsigned phyvhd_snapshot( const char *filename, const char *parent );
unsigned phyvhd_init( struct DEV *dev );
unsigned phyvhd_close( struct DEV *dev );
vmscond_t phyvhd_snapshot( const char *filename, const char *parent );
vmscond_t phyvhd_init( struct DEV *dev );
vmscond_t phyvhd_close( struct DEV *dev );
void phyvhd_show( struct DEV *dev, size_t column );
int phyvhd_available( int query );

View File

@@ -18,14 +18,17 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* A virtual device is used when normal file I/O is desired, e.g. to
* a disk image (simulator, .iso).
*
* A virtual device is established on the command line by specifying
* /virtual to the mount command.
* /image to the mount or initialize command, or by defaulting.
* If the device name is of the form dev:file, dev: becomes the
* virtual device name. Otherwise, a suitable name is created.
*
@@ -34,7 +37,7 @@
* device specific transformations, such as interleave and skew.
*
* It also provides an access layer for VHD format image files, on
* platforms where libvhd is available.
* platforms where libvhd is available.
*/
#if !defined( DEBUG ) && defined( DEBUG_PHYVIRT )
@@ -46,6 +49,7 @@
#endif
#include <ctype.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -57,6 +61,7 @@
#include "phyio.h"
#include "phyvirt.h"
#include "ssdef.h"
#include "sysmsg.h"
static struct VDEV {
struct VDEV *next;
@@ -69,96 +74,66 @@ static struct VDEV {
#include "phyvhd.h"
#endif
static int virt_compare( unsigned keylen, const char *keynam,
static int virt_compare( uint32_t keylen, const char *keynam,
const char *devnam );
static struct VDEV *virt_insert( const char *devnam, unsigned devsiz,
static struct VDEV *virt_insert( const char *devnam, uint32_t devsiz,
const char *path );
static void virt_remove( const char *devnam, unsigned devsiz );
unsigned virt_open( char **devname, unsigned flags, struct DEV **dev );
static unsigned virt_makedev( char *devnam, char **vname );
static void virt_remove( const char *devnam, uint32_t devsiz );
static vmscond_t virt_makedev( char *devnam, char **vname );
static char *autodev( void );
static unsigned virt_assign( char *devnam, struct DEV *dev );
unsigned virt_close( struct DEV *dev );
static unsigned maplbn( unsigned lbn, disktypep_t dp, unsigned sect );
unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
char *buffer ) ;
unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
const char *buffer );
unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
char *buffer );
unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
char *buffer );
static vmscond_t virt_assign( char *devnam, struct DEV *dev );
static vmscond_t maplbn( uint32_t lbn, disktypep_t dp, uint32_t sect );
static size_t get_devsiz( const char *devnam );
/************************************************************* virt_show() */
void virt_show( const char *devnam ) {
unsigned devsiz;
void virt_show( void ) {
struct VDEV *vp;
size_t maxd = sizeof( "Device" ) -1,
maxp = sizeof( "File" ) -1,
n;
if( devnam == NULL ) {
size_t maxd = sizeof( "Device" ) -1,
maxp = sizeof( "File" ) -1,
n;
if( virt_device_list == NULL ) {
printf( " No virtual devices are assigned\n" );
return;
}
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
n = strlen( vp->devnam );
if( n > maxd )
maxd = n;
n = strlen( vp->path );
if( n > maxp )
maxp =n;
}
if( maxp > 64 )
maxp = 64;
printf( " Virtual devices\n" );
printf( " %-*s %s\n ", (int)maxd, "Device", "File" );
for( n = 0; n < maxd; n++ ) putchar( '-' );
putchar( ' ');
for( n = 0; n < maxp; n++ ) putchar( '-' );
putchar( '\n' );
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
n = strlen( vp->path );
printf( " %-*s %-*.*s", (int)maxd, vp->devnam, (int)maxp,
(int)maxp, (n > maxp)? vp->path+(n-maxp): vp->path );
#ifdef USE_VHD
if( vp->dev->access & PHY_VHDDSK )
phyvhd_show( vp->dev, 2 + maxd + 1 + maxp + 1 );
#endif
putchar( '\n' );
}
} else {
devsiz = get_devsiz( devnam );
if( devsiz == 0 ) {
return;
}
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
if( virt_compare( devsiz, (char *) devnam, vp->devnam ) == 0 ) {
printf( " %s => %s\n", vp->devnam, vp->path );
return;
}
}
if( virt_device_list == NULL ) {
printmsg( IO_VNODEVS, MSG_TEXT );
return;
}
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
n = strlen( vp->devnam );
if( n > maxd )
maxd = n;
n = strlen( vp->path );
if( n > maxp )
maxp =n;
}
if( maxp > 64 )
maxp = 64;
printmsg( IO_VDEVHEADER, MSG_TEXT );
printf( " %-*s %s\n ", (int)maxd, "Device", "File" );
for( n = 0; n < maxd; n++ ) putchar( '-' );
putchar( ' ');
for( n = 0; n < maxp; n++ ) putchar( '-' );
putchar( '\n' );
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
n = strlen( vp->path );
printf( " %-*s %-*.*s", (int)maxd, vp->devnam, (int)maxp,
(int)maxp, (n > maxp)? vp->path+(n-maxp): vp->path );
#ifdef USE_VHD
if( vp->dev->access & PHY_VHDDSK )
phyvhd_show( vp->dev, 2 + maxd + 1 + maxp + 1 );
#endif
putchar( '\n' );
}
return;
}
/********************************************************** virt_compare() */
static int virt_compare( unsigned keylen, const char *keynam,
const char *devnam ) {
static int virt_compare( uint32_t keylen, const char *keynam,
const char *devnam ) {
register int cmp;
cmp = 0;
@@ -179,11 +154,10 @@ static int virt_compare( unsigned keylen, const char *keynam,
/* virt_lookup() finds virtual devices... */
char *virt_lookup( const char *devnam ) {
unsigned devsiz;
uint32_t devsiz;
struct VDEV *vp;
devsiz = get_devsiz( devnam );
devsiz = (uint32_t)get_devsiz( devnam );
if( devsiz == 0 ) {
return NULL;
}
@@ -197,9 +171,9 @@ char *virt_lookup( const char *devnam ) {
/*********************************************************** virt_insert() */
static struct VDEV *virt_insert( const char *devnam, unsigned devsiz,
static struct VDEV *virt_insert( const char *devnam, uint32_t devsiz,
const char *path ) {
unsigned pathsiz;
size_t pathsiz;
struct VDEV *vp, **vpp, **here;
here = NULL;
@@ -215,7 +189,8 @@ static struct VDEV *virt_insert( const char *devnam, unsigned devsiz,
if( vp == NULL ) {
return NULL;
}
vp->devnam = (char *) malloc( devsiz + 1 );
vp->devnam = (char *) malloc( (size_t)devsiz + 1 );
vp->path = (char *) malloc( (pathsiz = strlen( path )) + 1 );
if( vp->devnam == NULL || vp->path == NULL ) {
@@ -236,7 +211,7 @@ static struct VDEV *virt_insert( const char *devnam, unsigned devsiz,
/*********************************************************** virt_remove() */
static void virt_remove( const char *devnam, unsigned devsiz ) {
static void virt_remove( const char *devnam, uint32_t devsiz ) {
struct VDEV *vp, **vpp;
@@ -257,8 +232,8 @@ static void virt_remove( const char *devnam, unsigned devsiz ) {
* devices. Calls phyio_init with everything straightend out.
*/
unsigned virt_open( char **devname, unsigned flags, struct DEV **dev ) {
unsigned sts;
vmscond_t virt_open( char **devname, uint32_t flags, struct DEV **dev ) {
vmscond_t sts;
flags &= ~PHY_VHDDSK;
@@ -269,28 +244,22 @@ unsigned virt_open( char **devname, unsigned flags, struct DEV **dev ) {
#ifdef USE_VHD
flags |= PHY_VHDDSK;
#else
printf( "%%ODS2-W-NOVHD, VHD disk support is not available in this version\n" );
return SS$_IVDEVNAM;
return printmsg( IO_NOVHD, 0 );
#endif
}
sts = virt_makedev( *devname, devname );
if( !(sts & STS$M_SUCCESS) )
if( $FAILS( sts = virt_makedev( *devname, devname )) )
return sts;
} else {
if( virt_lookup( *devname ) != NULL ) {
int devsiz;
devsiz = get_devsiz( *devname );
printf( "%%ODS2-E-VIRTDEV, %.*s is a virtual device\n",
(int)devsiz, *devname );
return SS$_DEVMOUNT;
devsiz = (int)get_devsiz( *devname );
return printmsg( IO_ISVIRTDEV, 0, devsiz, *devname );
}
}
sts = device_lookup( strlen( *devname ), *devname, TRUE, dev );
if( !(sts & STS$M_SUCCESS) ) {
if( $FAILS(sts = device_lookup( strlen( *devname ), *devname, TRUE, dev )) ) {
if( flags & MOU_VIRTUAL )
virt_remove( *devname, get_devsiz( *devname ) );
virt_remove( *devname, (uint32_t)get_devsiz( *devname ) );
return sts;
}
(*dev)->access = flags; /* Requested mount options */
@@ -301,15 +270,16 @@ unsigned virt_open( char **devname, unsigned flags, struct DEV **dev ) {
#ifdef USE_VHD
sts = phyvhd_init( *dev );
#else
return SS$_IVDEVNAM;
device_done( *dev );
return printmsg( IO_NOVHD, 0 );
#endif
} else {
sts = phyio_init( *dev );
}
if( (flags & MOU_VIRTUAL) ) {
if( sts & STS$M_SUCCESS ) {
if( !((sts = virt_assign( *devname, *dev )) & STS$M_SUCCESS) ) {
if( $SUCCESSFUL(sts) ) {
if( $FAILS(sts = virt_assign( *devname, *dev )) ) {
#ifdef USE_VHD
if( flags & PHY_VHDDSK )
phyvhd_close( *dev );
@@ -318,8 +288,10 @@ unsigned virt_open( char **devname, unsigned flags, struct DEV **dev ) {
phyio_done( *dev );
device_done( *dev );
}
} else
virt_remove( *devname, get_devsiz( *devname ) );
} else {
virt_remove( *devname, (uint32_t)get_devsiz( *devname ) );
device_done( *dev );
}
}
return sts;
}
@@ -332,9 +304,9 @@ unsigned virt_open( char **devname, unsigned flags, struct DEV **dev ) {
* file might not exist yet. (initialize)
*/
static unsigned virt_makedev( char *devnam, char **vname ) {
static vmscond_t virt_makedev( char *devnam, char **vname ) {
struct VDEV *vp;
unsigned devsiz;
uint32_t devsiz;
char *path = NULL;
char *p;
@@ -342,15 +314,14 @@ static unsigned virt_makedev( char *devnam, char **vname ) {
*p = '\0';
path = ++p;
if( (p = virt_lookup( devnam)) != NULL ) {
printf( "%%ODS2-E-INUSE, %s is in use by %s\n", devnam, p );
return SS$_DEVALLOC;
return printmsg( IO_VIRTDEVINUSE, 0, devnam, p );
}
} else {
path = devnam;
devnam = autodev();
}
devsiz = get_devsiz( devnam );
devsiz = (uint32_t)get_devsiz( devnam );
if( devsiz == 0 ) {
return SS$_BADPARAM;
}
@@ -414,6 +385,7 @@ char *autodev( void ) {
int i = 0;
char t[ sizeof(devnam) ];
memset( t, 0, sizeof(t) );
n = d;
do {
ldiv_t r;
@@ -440,12 +412,13 @@ char *autodev( void ) {
* virt_open will close the physical device if we have problems.
*/
static unsigned virt_assign( char *devnam, struct DEV *dev ) {
unsigned devsiz;
static vmscond_t virt_assign( char *devnam, struct DEV *dev ) {
vmscond_t sts;
uint32_t devsiz;
char *p;
struct VDEV *vp, **vpp;
devsiz = get_devsiz( devnam );
devsiz = (uint32_t)get_devsiz( devnam );
if( devsiz == 0 ) {
return SS$_BADPARAM;
}
@@ -457,19 +430,19 @@ static unsigned virt_assign( char *devnam, struct DEV *dev ) {
if( vp == NULL )
return SS$_BADPARAM;
if( (p = phyio_path( vp->path )) == NULL || strlen( p ) == 0 ) {
printf( "%%ODS2-E-BADPATH, Invalid path: %s\n", vp->path );
if( (p = get_realpath( vp->path )) == NULL || strlen( p ) == 0 ) {
sts = printmsg( IO_BADPATH, 0, vp->path );
free( p );
virt_remove( devnam, devsiz );
return SS$_BADPARAM;
return sts;
}
for( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
if( (*vpp != vp) && strcmp( (*vpp)->path, p ) == 0 ) {
printf( "%%ODS2-E-MAPPED, %s is in use on virtual drive %s\n", p, (*vpp)->devnam );
sts = printmsg( IO_VIRTFILEINUSE, 0, p, (*vpp)->devnam );
free( p );
virt_remove( devnam, devsiz );
return SS$_DEVALLOC;
return sts;
}
}
@@ -486,14 +459,14 @@ static unsigned virt_assign( char *devnam, struct DEV *dev ) {
* Wraps phyio_done;
*/
unsigned virt_close( struct DEV *dev ) {
unsigned devsiz;
unsigned sts;
vmscond_t virt_close( struct DEV *dev ) {
uint32_t devsiz;
vmscond_t sts;
cache_flush();
if( dev->access & MOU_VIRTUAL ) {
devsiz = get_devsiz( dev->devnam );
devsiz = (uint32_t)get_devsiz( dev->devnam );
virt_remove( dev->devnam, devsiz );
}
#ifdef USE_VHD
@@ -510,8 +483,8 @@ unsigned virt_close( struct DEV *dev ) {
/* Map an LBN as viewed by the OS to each of its physical sectors.
*/
static unsigned maplbn( unsigned lbn, disktypep_t dp, unsigned sect ) {
unsigned c, t, s;
static vmscond_t maplbn( uint32_t lbn, disktypep_t dp, uint32_t sect ) {
uint32_t c, t, s;
ldiv_t r;
lbn = (lbn * (512 / dp->sectorsize)) + sect;
@@ -534,14 +507,15 @@ static unsigned maplbn( unsigned lbn, disktypep_t dp, unsigned sect ) {
/*********************************************************** virt_read() */
unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
vmscond_t virt_read( struct DEV *dev, uint32_t lbn, uint32_t length,
char *buffer ) {
disktypep_t dp;
char *lbnbuf = NULL;
unsigned status, secblk;
vmscond_t status;
uint32_t secblk;
off_t devlimit, end, eofptr;
#ifdef DEBUG_DISKIO
unsigned inlbn = lbn, inlen = length;
uint32_t inlbn = lbn, inlen = length;
char *inbuf = buffer;
#endif
@@ -577,21 +551,19 @@ unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
if( dp->reserved == 0 && dp->interleave == 0 && dp->skew == 0 ) {
if( (dev->access & MOU_VIRTUAL) &&
(end = ((off_t)lbn * 512 + length)) > eofptr ) {
unsigned avail;
uint32_t avail;
off_t start;
if( end > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Read from non-existent block %lu\n",
((end + dp->sectorsize -1)/dp->sectorsize) );
return SS$_ILLBLKNUM;
return printmsg( IO_RDBLK2BIG, 0,
((end + dp->sectorsize -1)/dp->sectorsize) );
}
start = (off_t)lbn * 512;
if( start < eofptr ) {
avail = (unsigned)( eofptr - start );
avail = (uint32_t)( eofptr - start );
status = dev->devread( dev, lbn, avail, buffer );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, lbn, avail, buffer )) )
return status;
length -= avail;
@@ -617,15 +589,15 @@ unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
abort(); /* TODO *** Handle large sectors, e.g. CDROM 2K where multiple LBNs fit into one. */
secblk = 512 / dp->sectorsize;
if( (lbnbuf = malloc( 512 * 2 )) == NULL )
if( (lbnbuf = malloc( (size_t)512 * 2 )) == NULL )
return SS$_INSFMEM;
while( length > 0 && (status & STS$M_SUCCESS) ) {
unsigned pbn;
unsigned s;
while( length > 0 && $SUCCESSFUL(status) ) {
uint32_t pbn;
uint32_t s;
for( s = 0; s < secblk && length > 0; s++ ) {
unsigned n;
uint32_t n;
ldiv_t r;
pbn = maplbn( lbn, dp, s );
@@ -636,32 +608,29 @@ unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
if( (dev->access & MOU_VIRTUAL) &&
(end = ((off_t)r.quot * 512 + n)) > eofptr ) {
unsigned avail;
uint32_t avail;
off_t start;
if( ((off_t)pbn * (long)dp->sectorsize) + (long)n - r.rem > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Read from non-existent block %lu\n",
status = printmsg( IO_RDBLK2BIG, 0,
(((pbn * dp->sectorsize + n) + dp->sectorsize -1) /
dp->sectorsize) -1 );
status = SS$_ILLBLKNUM;
break;
}
start = (off_t)r.quot * 512;
if( start < eofptr ) {
avail = (unsigned)( eofptr - start );
avail = (uint32_t)( eofptr - start );
status = dev->devread( dev, r.quot, avail, lbnbuf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, r.quot, avail, lbnbuf )) )
return status;
memset( lbnbuf+avail, 0, n - avail );
memset( lbnbuf+avail, 0, (size_t)n - avail );
} else
memset( lbnbuf, 0, n );
} else {
status = dev->devread( dev, r.quot, n, lbnbuf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, r.quot, n, lbnbuf )) )
break;
}
n = (dp->sectorsize > length)? length: dp->sectorsize;
@@ -680,14 +649,15 @@ unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
/*********************************************************** virt_write() */
unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
vmscond_t virt_write( struct DEV *dev, uint32_t lbn, uint32_t length,
const char *buffer ) {
disktypep_t dp;
char *lbnbuf = NULL;
unsigned status, secblk;
vmscond_t status;
uint32_t secblk;
off_t devlimit, start, end;
#ifdef DEBUG_DISKIO
unsigned inlbn = lbn, inlen = length;
uint32_t inlbn = lbn, inlen = length;
const char *inbuf = buffer;
#endif
@@ -701,18 +671,16 @@ unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
if( dp->reserved == 0 && dp->interleave == 0 && dp->skew == 0 ) {
if( (end + 511)/512 > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Write to non-existent block %lu\n",
((end + dp->sectorsize -1)/dp->sectorsize) );
return SS$_ILLBLKNUM;
return printmsg( IO_WRBLK2BIG, 0,
((end + dp->sectorsize -1)/dp->sectorsize) );
}
status = dev->devwrite( dev, lbn, length, buffer );
#ifdef DEBUG_DISKIO
dumpblock( inlbn, inlen, inbuf, "Virt Write, status %08X", status );
#endif
if( (status & STS$M_SUCCESS) && (dev->access & MOU_VIRTUAL) ) {
if( end > dev->eofptr ) {
dev->eofptr = end;
}
if( $SUCCESSFUL(status) &&
(dev->access & MOU_VIRTUAL) && (end > dev->eofptr) ) {
dev->eofptr = end;
}
return status;
}
@@ -723,15 +691,15 @@ unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
abort(); /* TODO *** Handle large sectors, e.g. CDROM 2K where multiple LBNs fit into one. */
secblk = 512 / dp->sectorsize;
if( (lbnbuf = malloc( 512 * 2 )) == NULL )
if( (lbnbuf = malloc( (size_t)512 * 2 )) == NULL )
return SS$_INSFMEM;
while( length > 0 && (status & STS$M_SUCCESS) ) {
unsigned pbn;
unsigned s;
while( length > 0 && $SUCCESSFUL(status) ) {
uint32_t pbn;
uint32_t s;
for( s = 0; s < secblk && length > 0; s++ ) {
unsigned n, m;
uint32_t n, m;
ldiv_t r;
pbn = maplbn( lbn, dp, s );
@@ -743,26 +711,24 @@ unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
start = (off_t)r.quot * 512;
m = ((n + 511) / 512) * 512;
if( start < dev->eofptr && (off_t)(start + m) > dev->eofptr )
m = (unsigned)(dev->eofptr - start);
m = (uint32_t)(dev->eofptr - start);
if( dev->access & MOU_VIRTUAL ) {
if( ((off_t)pbn * (long)dp->sectorsize) + ((long)n - r.rem) > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Write to non-existent block %lu\n",
(((pbn * dp->sectorsize) + (n - r.rem) +
dp->sectorsize -1) / dp->sectorsize ) -1 );
status = SS$_ILLBLKNUM;
status = printmsg( IO_WRBLK2BIG, 0,
(((pbn * dp->sectorsize) + (n - r.rem) +
dp->sectorsize -1) / dp->sectorsize ) -1 );
break;
}
}
memset( lbnbuf, 0, 512 * 2 );
memset( lbnbuf, 0, (size_t)512 * 2 );
if( start < dev->eofptr ) {
status = dev->devread( dev, r.quot, m, lbnbuf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, r.quot, m, lbnbuf )) )
break;
if( m < n )
memset( lbnbuf+m, 0, n - m );
memset( lbnbuf+m, 0, (size_t)n - m );
}
memcpy( lbnbuf+r.rem, buffer, n - r.rem );
memcpy( lbnbuf+r.rem, buffer, (size_t)n - r.rem );
end = start + n;
if( end > dev->eofptr ) {
status = dev->devwrite( dev, r.quot, n, lbnbuf );
@@ -770,7 +736,7 @@ unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
} else
status = dev->devwrite( dev, r.quot, m, lbnbuf );
if( !(status & STS$M_SUCCESS) )
if( $FAILED(status) )
break;
n -= r.rem;
buffer += n;
@@ -788,14 +754,14 @@ unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
/*********************************************************** virt_readp() */
unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
vmscond_t virt_readp( struct DEV *dev, uint32_t pbn, uint32_t length,
char *buffer ) {
disktypep_t dp;
unsigned status;
vmscond_t status;
off_t devlimit, eofptr;
off_t fp, offset;
char *buf;
unsigned avail;
uint32_t avail;
dp = dev->disktype;
@@ -807,9 +773,8 @@ unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
fp = ((off_t)pbn) * dp->sectorsize;
if( fp + (off_t)length > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Read from non-existent block %lu\n",
return printmsg( IO_RDBLK2BIG, 0,
((fp + length + dp->sectorsize -1)/dp->sectorsize) );
return SS$_ILLBLKNUM;
}
if( dev->access & MOU_VIRTUAL ) {
@@ -829,13 +794,12 @@ unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
offset = fp % 512;
avail = (unsigned)(eofptr - fp);
avail = (uint32_t)(eofptr - fp);
if( avail > length )
avail = length;
if( offset == 0 ) {
status = dev->devread( dev, (unsigned) (fp / 512), avail, buffer );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, (uint32_t) (fp / 512), avail, buffer )) )
return status;
length -= avail;
@@ -849,9 +813,10 @@ unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
#endif
return status;
}
if( (buf = malloc( (size_t) (offset + avail) )) == NULL )
if( (buf = malloc( ((size_t)offset + avail) )) == NULL )
return SS$_INSFMEM;
status = dev->devread( dev, (unsigned) (fp / 512), (unsigned) (offset + avail), buf );
status = dev->devread( dev, (uint32_t) (fp / 512),
(uint32_t) (offset + avail), buf );
memcpy( buffer, buf+offset, avail );
free( buf );
@@ -868,16 +833,16 @@ unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
/*********************************************************** virt_writep() */
unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
vmscond_t virt_writep( struct DEV *dev, uint32_t pbn, uint32_t length,
char *buffer ) {
disktypep_t dp;
unsigned status;
vmscond_t status;
off_t devlimit;
off_t fp, offset;
char *buf = NULL;
unsigned avail, n, m;
uint32_t avail, n, m;
#ifdef DEBUG_DISKIO
unsigned inpbn = pbn, inlen = length;
uint32_t inpbn = pbn, inlen = length;
const char *inbuf = buffer;
#endif
@@ -891,15 +856,14 @@ unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
fp = ((off_t)pbn) * dp->sectorsize;
if( fp + (off_t)length > devlimit ) {
printf( "%%ODS2-E-BLK2BIG, Write to non-existent block %lu\n",
return printmsg( IO_WRBLK2BIG, 0,
((fp + length + dp->sectorsize -1)/dp->sectorsize) );
return SS$_ILLBLKNUM;
}
offset = fp % 512;
if( offset == 0 && length % 512 == 0 ) {
status = dev->devwrite( dev, (unsigned)(fp / 512), length, buffer );
status = dev->devwrite( dev, (uint32_t)(fp / 512), length, buffer );
#ifdef DEBUG_DISKIO
dumpblock( inpbn, inlen, inbuf, "Phys Write, status %08X", status );
#endif
@@ -916,12 +880,11 @@ unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
do {
if( offset != 0 ) {
avail = (unsigned) ( devlimit - (fp -offset) );
avail = (uint32_t) ( devlimit - (fp -offset) );
n = (avail > 512)? 512: avail;
status = dev->devread( dev, (unsigned) (fp / 512), n, buf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, (uint32_t) (fp / 512), n, buf )) )
break;
m = (n > length)? length: n;
@@ -930,16 +893,14 @@ unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
buffer += m;
length -= m;
status = dev->devwrite( dev, (unsigned) (fp / 512), n, buf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devwrite( dev, (uint32_t) (fp / 512), n, buf )) )
break;
fp += n;
}
if( (n = length / 512) > 0 ) {
n *= 512;
status = dev->devwrite( dev, (unsigned) (fp / 512), n, buffer );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devwrite( dev, (uint32_t) (fp / 512), n, buffer )) )
break;
buffer += n;
@@ -948,12 +909,11 @@ unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
}
if( length > 0 ) {
avail = (unsigned) ( devlimit - fp );
avail = (uint32_t) ( devlimit - fp );
n = (avail > 512)? 512: avail;
status = dev->devread( dev, (unsigned) (fp / 512), n, buf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devread( dev, (uint32_t) (fp / 512), n, buf )) )
break;
m = (n > length)? length: n;
@@ -962,8 +922,7 @@ unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
buffer += m;
length -= m;
status = dev->devwrite( dev, (unsigned) (fp / 512), n, buf );
if( !(status & STS$M_SUCCESS) )
if( $FAILS(status = dev->devwrite( dev, (uint32_t) (fp / 512), n, buf )) )
break;
fp += n;
@@ -1024,6 +983,8 @@ disktype_t disktype[] = {
DISK(RM02, 32, 5, 823, DISK_BAD144)
DISK(RM03, 32, 5, 823, DISK_BAD144)
DISK(RP02, 10, 20, 203, DISK_BAD144)
DISK(RP03, 10, 20, 406, DISK_BAD144)
DISK(RP04, 22, 19, 411, DISK_BAD144)
DISK(RP05, 22, 19, 411, DISK_BAD144)
DISK(RM80, 31, 14, 559, DISK_BAD144)
@@ -1031,6 +992,9 @@ disktype_t disktype[] = {
DISK(RM05, 32, 19, 823, DISK_BAD144)
DISK(RP07, 50, 32, 630, DISK_BAD144)
DISKS(RS03, 128, 64, 1, 64, 0, DISK_BAD144)
DISKS(RS04, 256, 64, 1, 64, 0, DISK_BAD144)
#if 0 /* Not useful now as RSX20-F used ODS-1 */
DISKS(RM02-T, 576, 30, 5, 823, 0, DISK_BAD144)
DISKS(RM03-T, 576, 30, 5, 823, 0, DISK_BAD144)

View File

@@ -14,7 +14,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _PHYVIRT_H
@@ -27,9 +30,9 @@ typedef disktype_t *disktypep_t;
struct disktype {
const char *name;
unsigned long sectorsize, sectors, tracks, cylinders;
unsigned long reserved, interleave, skew;
unsigned int flags;
uint32_t sectorsize, sectors, tracks, cylinders;
uint32_t reserved, interleave, skew;
uint32_t flags;
#define DISK_BAD144 1
#define DISK_BADSW 2
};
@@ -39,19 +42,19 @@ extern size_t max_disktype;
struct DEV;
void virt_show( const char *devnam );
unsigned virt_open( char **devname, unsigned flags, struct DEV **dev );
void virt_show( void );
vmscond_t virt_open( char **devname, uint32_t flags, struct DEV **dev );
char *virt_lookup( const char *devnam );
unsigned virt_close( struct DEV *dev );
vmscond_t virt_close( struct DEV *dev );
unsigned virt_read( struct DEV *dev, unsigned lbn, unsigned length,
vmscond_t virt_read( struct DEV *dev, uint32_t lbn, uint32_t length,
char *buffer );
unsigned virt_write( struct DEV *dev, unsigned lbn, unsigned length,
vmscond_t virt_write( struct DEV *dev, uint32_t lbn, uint32_t length,
const char *buffer );
unsigned virt_readp( struct DEV *dev, unsigned pbn, unsigned length,
vmscond_t virt_readp( struct DEV *dev, uint32_t pbn, uint32_t length,
char *buffer );
unsigned virt_writep( struct DEV *dev, unsigned pbn, unsigned length,
vmscond_t virt_writep( struct DEV *dev, uint32_t pbn, uint32_t length,
char *buffer );
#ifdef USE_VHD

View File

@@ -1,20 +1,23 @@
/* PHYVMS.c Physical I/O module for VMS */
/*
This is part of ODS2 written by Paul Nankervis,
email address: Paulnank@au1.ibm.com
* 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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* How come VMS is so much easier to do physical I/O on than
those other ^%$@*! systems? I can't believe that they have
different command sets for different device types, and can
even have different command sets depending on what mode they
are called from! Sigh. */
* those other ^%$@*! systems? I can't believe that they have
* different command sets for different device types, and can
* even have different command sets depending on what mode they
* are called from! Sigh. */
/* Modified by:
*
@@ -88,10 +91,10 @@ unsigned sys$dassgn();
#include "phyio.h"
#include "phyvirt.h"
static unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
char *buffer );
static unsigned phyio_write( struct DEV *dev, unsigned block, unsigned length,
const char *buffer );
static vmscond_t phyio_read( struct DEV *dev, uint32_t block,
uint32_t length, char *buffer );
static vmscond_t phyio_write( struct DEV *dev, uint32_t block,
uint32_t length, const char *buffer );
struct ITMLST {
unsigned short length;
@@ -100,11 +103,6 @@ struct ITMLST {
unsigned short *retlen;
};
#define chk( sts ) { register chksts; \
if ( !( ( chksts = sts ) & STS$M_SUCCESS ) ) \
lib$stop( chksts ); \
}
#define MSGID(sts) ((sts) & (STS$M_COND_ID|STS$M_SEVERITY))
static unsigned init_count = 0;
@@ -113,7 +111,7 @@ static unsigned write_count = 0;
/*************************************************************** showdevs() */
static void showdevs( void ) {
unsigned long status;
vmscond_t status;
size_t max = 0;
int pass;
@@ -174,12 +172,13 @@ static void showdevs( void ) {
case SS$_NOMOREDEV:
break;
case SS$_NOSUCHDEV:
printf( "No devices found\n" );
printmsg( IO_NODEVS, MSG_TEXT );
break;
case SS$_NORMAL:
break;
default:
printf( "%%ODS2-W-ERRDEV, Error scanning devices: %s\n",
getmsg( status, MSG_TEXT ) );
printmsg( IO_VMSDEVSCAN, 0 );
printmsg( status, MSG_CONTINUE, IO_VMSDEVSCAN );
break;
}
return;
@@ -190,12 +189,10 @@ static void showdevs( void ) {
void phyio_show( showtype_t type ) {
switch( type ) {
case SHOW_STATS:
printf( "PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
init_count, read_count, write_count );
printmsg( IO_STATS, MSG_TEXT, init_count, read_count, write_count );
return;
case SHOW_FILE64:
printf( "Large ODS-2 image files (>2GB) are %ssupported.\n",
(sizeof( off_t ) < 8)? "NOT ": "" );
printmsg( (sizeof( off_t ) < 8)? IO_NOLARGEFILE: IO_LARGEFILE, MSG_TEXT );
return;
case SHOW_DEVICES:
printf( " Physical devices\n" );
@@ -206,61 +203,19 @@ void phyio_show( showtype_t type ) {
}
}
/*************************************************************** phyio_help() */
void phyio_help(FILE *fp ) {
fprintf( fp, "mount DUB0:\n" );
fprintf( fp, "The device can be specified as a physical device or logical name\n" );
fprintf( fp, "You will need the LOGIO privilege\n" );
fprintf( fp, "Use show DEVICES for a list of available devices.\n" );
fprintf( fp, "For a list of devices, use the DCL SHOW DEVICE command.\n\n" );
(void) helptopic( 0, "MOUNT VMS" );
return;
}
/*************************************************************** phyio_path() */
#define MAXPATH 255
char *phyio_path( const char *filnam ) {
size_t n;
unsigned short resultant_path[1 + ( ( MAXPATH + 1 ) / 2)];
char *path;
unsigned long context, sts, flags;
struct dsc$descriptor filespec = {
0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL
};
struct dsc$descriptor resultant_filespec = {
MAXPATH, DSC$K_DTYPE_T, DSC$K_CLASS_VS, (char *) resultant_path
};
path = NULL;
if ( filnam != NULL ) {
filespec.dsc$w_length = strlen( filnam );
filespec.dsc$a_pointer = (char *) filnam;
*resultant_path = 0;
context = 0;
flags = LIB$M_FIL_NOWILD;
sts = lib$find_file( &filespec, &resultant_filespec, &context,
NULL, NULL, &sts, &flags );
lib$find_file_end( &context );
if ( sts & STS$M_SUCCESS ) {
n = *resultant_path;
path = (char *) malloc( n + 1 );
if ( path != NULL ) {
memcpy( path, resultant_path + 1, n );
path[n] = '\0';
}
}
}
return path;
}
/*************************************************************** phyio_init() */
unsigned phyio_init( struct DEV *dev ) {
vmscond_t phyio_init( struct DEV *dev ) {
unsigned long sts;
vmscond_t sts;
const char *virtual;
init_count++;
@@ -290,17 +245,18 @@ unsigned phyio_init( struct DEV *dev ) {
vmsfd = open( virtual, O_RDONLY, 0444, opnopts );
}
if ( vmsfd < 0 ) {
int err;
switch( errno ) {
case EEXIST:
printf( "%%ODS2-E-EXISTS, File %s already exists, not superseded\n",
virtual );
sts = SS$_DUPFILENAME;
break;
printmsg( IO_EXISTS, 0, virtual );
return SS$_DUPFILENAME | STS$M_INHIB_MSG;
default:
printf( "%%ODS2-E-OPENERR, Open %s: %s\n",
virtual, strerror( errno ) );
err = errno;
printmsg( IO_OPENDEV, 0, virtual );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, IO_OPENDEV,
strerror( err ) );
}
return SS$_NOSUCHFILE;
}
dev->handle = vmsfd;
@@ -308,14 +264,13 @@ unsigned phyio_init( struct DEV *dev ) {
fab = cc$rms_fab; /* Make this a real FAB (bid and bln) */
fab.fab$l_fna = (char *) virtual;
fab.fab$b_fns = strlen( virtual );
sts = sys$open( &fab ); /* Lookup file, get file size */
if ( sts & STS$M_SUCCESS ) {
if( $SUCCESSFUL(sts = sys$open( &fab )) {/* Lookup file, get file size */
dev->sectors = fab.fab$l_alq;
sys$close( &fab );
if ( sizeof( off_t ) < 8 && dev->sectors > 0x3FFFFF ) {
close( vmsfd );
dev->handle = -1;
return SS$_OFFSET_TOO_BIG; /* Sorry, need 64-bit off_t */
return printmsg( IO_OFFSET_TOO_BIG, 0 ); /* Need 64-bit off_t */
}
}
} else { /* Physical */
@@ -335,24 +290,23 @@ unsigned phyio_init( struct DEV *dev ) {
};
/* Get some device information: device name, class, and mount status */
memset( devname, 0, sizeof( devname ) );
devdsc.dsc$w_length = strlen( dev->devnam );
devdsc.dsc$a_pointer = dev->devnam;
sts = sys$getdviw( EFN$C_ENF, 0, &devdsc, &dvi_itmlst, iosb, 0, 0, 0 );
if ( !( sts & STS$M_SUCCESS ) ) {
if( $FAILS(sts = sys$getdviw( EFN$C_ENF, 0, &devdsc, &dvi_itmlst,
iosb, 0, 0, 0 )) ) {
return sts;
}
if ( devclass != DC$_DISK ) { /* If not a disk, return an error */
if( devclass != DC$_DISK ) { /* If not a disk, return an error */
return SS$_IVDEVNAM;
}
dev->sectors = cylinders * tracks * sectors;
if ( !( devchar & DEV$M_MNT ) ) {
#if 0
if( !(devchar & DEV$M_MNT) ) {
#if 1
/*
* This code will mount the disk if it's not already mounted. However,
* there's no good way to ensure we dismount a disk we mounted (no
* easy way to walk the list of devices at exit), so it's been #ifdefed
* out. If you enable it, the "mount" command will mount the disk, but
* it'll stay mounted by the process running ODS2, even after image exit.
* This code will mount the disk if it's not already mounted.
* If you enable it, the "mount" command will mount the disk, but
* it'll stay mounted by the process running ODS2 if ODS2 exits abnormally.
*/
unsigned long mntflags[2];
struct ITMLST mnt_itmlst[3] = {
@@ -362,21 +316,27 @@ unsigned phyio_init( struct DEV *dev ) {
};
mnt_itmlst[0].length = strlen( devname );
mntflags[0] = MNT$M_FOREIGN | MNT$M_NOASSIST | MNT$M_NOMNTVER;
if ( !( dev->access & MOU_WRITE ) ) {
if( !(dev->access & MOU_WRITE) ) {
mntflags[0] |= MNT$M_NOWRITE;
}
mntflags[1] = 0;
sts = sys$mount( &mnt_itmlst );
if ( !( sts & STS$M_SUCCESS ) && ( dev->access & MOU_WRITE ) ) {
if( $FAILED(sts) && (dev->access & MOU_WRITE) ) {
dev->access &= ~MOU_WRITE;
mntflags[0] |= MNT$M_NOWRITE;
sts = sys$mount( &mnt_itmlst );
}
if( $SUCCESSFUL(sts) ) {
dev->access |= OS_MOUNTED;
printmsg( IO_VMSMOUNT, 0, devname );
} else {
printmsg( IO_VMSNOMOUNT, 0, devname );
}
#else
sts = SS$_DEVNOTMOUNT;
#endif
}
if ( sts & STS$M_SUCCESS ) {
if( $SUCCESSFUL(sts) ) {
sts = sys$assign( &devdsc, &dev->handle, 0, 0, 0, 0 );
}
}
@@ -386,73 +346,129 @@ unsigned phyio_init( struct DEV *dev ) {
/*************************************************************** phyio_done() */
unsigned phyio_done( struct DEV *dev ) {
vmscond_t phyio_done( struct DEV *dev ) {
vmscond_t status;
status = SS$_NORMAL;
if ( dev->access & MOU_VIRTUAL ) {
close( dev->handle );
virt_device( dev->devnam, NULL );
} else {
#if 1
if( dev->access & OS_MOUNTED ) {
struct dsc$descriptor devdsc;
devdsc.dsc$b_dtype = DSC$K_DTYPE_T;
devdsc.dsc$b_class = DSC$K_CLASS_S;
devdsc.dsc$w_length = strlen( dev->devnam );
devdsc.dsc$a_pointer = dev->devnam;
if( $SUCCESSFUL(status = sys$dismou( &devdsc, 0 )) ) {
printmsg( IO_VMSDMT, 0, dev->devnam );
} else {
printmsg( IO_VMSNODMT, 0, dev->devnam );
}
dev->access &= ~OS_MOUNTED;
}
#endif
sys$dassgn( dev->handle );
}
dev->handle = 0;
return SS$_NORMAL;
return status;
}
/*************************************************************** phyio_read() */
static unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
char *buffer ) {
static vmscond_t phyio_read( struct DEV *dev, uint32_t block, uint32_t length,
char *buffer ) {
vmscond_t sts;
#if DEBUG
printf("Phyio read block: %d into %x (%d bytes)\n",block,buffer,length);
#endif
read_count++;
if ( dev->access & MOU_VIRTUAL ) {
if( dev->access & MOU_VIRTUAL ) {
int res;
if ( ( res = lseek( dev->handle, block * 512, SEEK_SET ) ) < 0 ) {
perror( "lseek " );
printf( "lseek failed %d\n", res );
return SS$_PARITY;
if( (res = lseek( dev->handle, block * 512, SEEK_SET )) < 0 ) {
int err;
err = errno;
printmsg( IO_SEEKERR, block );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_SEEKERR, strerror(err) );
return sts;
}
if ( ( res = read( dev->handle, buffer, length ) ) != length ) {
if( (res = read( dev->handle, buffer, length )) != length ) {
int err;
if( res == 0 ) {
return SS$_ENDOFFILE;
}
perror( "read " );
printf( "read failed %d\n", res );
return SS$_PARITY;
err = errno;
printmsg( IO_READERR, 0, block );
if( res == (off_t)-1 ) {
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_READERR, strerror(err) );
} else {
sts = printmsg( IO_READLEN, MSG_CONTINUE, IO_READERR,
block, (uint32_t)res, length );
}
return sts;
}
return SS$_NORMAL;
} else {
return sys$qiow( 1, dev->handle, IO$_READLBLK, NULL, 0, 0,
unsigned short int iosb[4];
return sys$qiow( EFN$C_ENF, dev->handle, IO$_READLBLK, iosb, 0, 0,
buffer, length, block, 0, 0, 0 );
}
}
/************************************************************** phyio_write() */
static unsigned phyio_write( struct DEV *dev, unsigned block, unsigned length,
const char *buffer ) {
static vmscond_t phyio_write( struct DEV *dev, uint32_t block, uint32_t length,
const char *buffer ) {
vmscond_t sts;
#if DEBUG
printf("Phyio write block: %d from %x (%d bytes)\n",block,buffer,length);
#endif
write_count++;
if ( dev->access & MOU_VIRTUAL ) {
if( dev->access & MOU_VIRTUAL ) {
int res;
if ( ( res = lseek( dev->handle, block * 512, 0 ) ) < 0 ) {
perror( "lseek " );
printf( "lseek failed %d\n", res );
return SS$_PARITY;
if( (res = lseek( dev->handle, block * 512, 0 )) < 0 ) {
int err;
err = errno;
printmsg( IO_SEEKERR, block );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_SEEKERR, strerror(err) );
return sts;
}
if ( ( res = write( dev->handle, buffer, length ) ) != length ) {
perror( "write " );
printf( "write failed %d\n", res );
return SS$_PARITY;
if( (res = write( dev->handle, buffer, length )) != length ) {
int err;
err = errno;
printmsg( IO_WRITEERR, 0, block );
if( res == (off_t)-1 ) {
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE,
IO_WRITEERR, strerror(err) );
} else {
sts = printmsg( IO_WRITELEN, MSG_CONTINUE, IO_WRITEERR,
block, (uint32_t)res, length );
}
return sts;
}
return SS$_NORMAL;
} else {
return sys$qiow( 1, dev->handle, IO$_WRITELBLK, NULL, 0, 0,
unsigned short int iosb[4];
return sys$qiow( EFN$C_ENF, dev->handle, IO$_WRITELBLK, iosb, 0, 0,
buffer, length, block, 0, 0, 0 );
}
}

214
extracters/ods2/renamecmd.c Normal file
View File

@@ -0,0 +1,214 @@
/* This is part of ODS2, originally 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_RENAMECMD )
#define DEBUG DEBUG_RENAMECMD
#else
#ifndef DEBUG
#define DEBUG 0
#endif
#endif
#include "cmddef.h"
/******************************************************************* dorename() */
/* rename a file */
#define rename_log OPT_GENERIC_1
#define rename_confirm OPT_GENERIC_2
qual_t
renamequals[] = { {"log", rename_log, 0, NV,
"-commands rename qual_log"},
{"nolog", 0, rename_log, NV, NULL},
{"confirm", rename_confirm, 0, NV,
"-commands rename qual_confirm"},
{"noconfirm", 0, rename_confirm, NV, NULL},
{NULL, 0, 0, NV, NULL}
};
param_t
renamepars[] = { {"from_filespec", REQ, FSPEC, NOPA,
"commands rename fromspec"},
{"to_filespec", REQ, FSPEC, NOPA,
"commands rename tospec"},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(rename) {
options_t options;
vmscond_t sts = 0;
vmscond_t confirm = ODS2_CONFIRM_ALL;
uint32_t renamecnt = 0;
struct FAB ofab, nfab;
struct NAM onam, nnam;
char oes[NAM$C_MAXRSS+1], nes[NAM$C_MAXRSS+1],
ors[NAM$C_MAXRSS+1], nrs[NAM$C_MAXRSS+1];
UNUSED(argc);
if( $FAILS(sts = checkquals( &options, 0, renamequals, qualc, qualv )) ) {
return sts;
}
if( options & rename_confirm )
confirm = RENAME_CONFIRM;
/* Old spec, possibly wild */
onam = cc$rms_nam;
onam.nam$l_esa = oes;
onam.nam$b_ess = sizeof( oes ) -1;
onam.nam$l_rsa = ors;
onam.nam$b_rss = sizeof( ors ) -1;
ofab = cc$rms_fab;
ofab.fab$l_nam = &onam;
ofab.fab$l_fna = argv[1];
ofab.fab$b_fns = (uint8_t)strlen(ofab.fab$l_fna);
do {
if( $FAILS(sts = sys_parse(&ofab)) ) {
printmsg( RENAME_PARSEFAIL, 0, ofab.fab$l_fna );
sts = printmsg( sts, MSG_CONTINUE, RENAME_PARSEFAIL );
break;
}
oes[onam.nam$b_esl] = '\0';
while( $SUCCESSFUL(sts) ) {
struct FAB rfab;
struct NAM rnam;
char res[NAM$C_MAXRSS+1], rrs[NAM$C_MAXRSS+1];
if( $FAILS(sts = sys_search( &ofab )) ) {
if( $MATCHCOND(sts, RMS$_NMF) ) {
sts = SS$_NORMAL;
break;
}
printmsg( RENAME_SEARCHFAIL, 0, onam.nam$l_esa );
sts = printmsg( sts, MSG_CONTINUE, RENAME_SEARCHFAIL );
break;
}
ors[onam.nam$b_rsl] = '\0';
/* New spec */
nnam = cc$rms_nam;
nnam.nam$l_esa = nes;
nnam.nam$b_ess = sizeof( nes ) -1;
nnam.nam$l_rsa = nrs;
nnam.nam$b_rss = sizeof( nrs ) -1;
nnam.nam$l_rlf = &onam;
nfab = cc$rms_fab;
nfab.fab$l_nam = &nnam;
nfab.fab$l_fna = argv[2];
nfab.fab$b_fns = (uint8_t)strlen(nfab.fab$l_fna);
nfab.fab$l_fop = FAB$M_OFP;
if( $FAILS(sts = sys_parse(&nfab)) ) {
printmsg( RENAME_PARSEFAIL, 0, nfab.fab$l_fna );
sts = printmsg( sts, MSG_CONTINUE, RENAME_PARSEFAIL );
break;
}
nes[nnam.nam$b_esl] = '\0';
/* Old resultant spec for rename */
rnam = cc$rms_nam;
rnam.nam$l_esa = res;
rnam.nam$b_ess = sizeof( res ) -1;
rnam.nam$l_rsa = rrs;
rnam.nam$b_rss = sizeof( rrs ) -1;
rfab = cc$rms_fab;
rfab.fab$l_nam = &rnam;
rfab.fab$l_fna = onam.nam$l_rsa;
rfab.fab$b_fns = onam.nam$b_rsl;
if( $MATCHCOND( confirm, RENAME_CONFIRM) )
confirm = confirm_cmd( confirm, ors, nes );
if( !$MATCHCOND( confirm, ODS2_CONFIRM_ALL ) ) {
if( $MATCHCOND( confirm, ODS2_CONFIRM_YES ) ) {
confirm = RENAME_CONFIRM;
} else if( $MATCHCOND( confirm, ODS2_CONFIRM_NO ) ) {
confirm = RENAME_CONFIRM;
continue;
} else { /* ODS2_CONFIRM_QUIT */
sts = confirm;
break;
}
}
sts = sys_rename( &rfab, NULL, NULL, &nfab );
res[rnam.nam$b_esl] = '\0';
rrs[rnam.nam$b_rsl] = '\0';
nes[nnam.nam$b_esl] = '\0';
nrs[nnam.nam$b_rsl] = '\0';
if( $SUCCESSFUL(sts) ) {
renamecnt++;
if( options & rename_log )
sts = printmsg( RENAME_RENAMED, 0, rrs, nrs );
} else {
printmsg( RENAME_FAILED, 0,
rnam.nam$b_rsl? rrs: rnam.nam$b_esl? res: rfab.fab$l_fna,
nnam.nam$b_rsl? nrs: nnam.nam$b_rsl? nes: nfab.fab$l_fna );
sts = printmsg( sts, MSG_CONTINUE, RENAME_FAILED );
}
rfab.fab$b_fns =
rnam.nam$b_ess =
rfab.fab$b_dns = 0;
rnam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &rfab );
if( $FAILED(sts) && $VMS_STATUS_SEVERITY(sts) > STS$K_WARNING )
break;
} /* search old files */
} while( 0 );
if( options & rename_log ) {
vmscond_t st2 = 0;
if( renamecnt > 1 ) {
st2 = printmsg( RENAME_NRENAMED, 0, renamecnt );
} else if( renamecnt == 0 && $SUCCESSFUL(sts) )
st2 = printmsg( RENAME_NOFILES, 0 );
if( $SUCCESSFUL(sts) )
sts = st2;
}
ofab.fab$b_fns =
onam.nam$b_ess =
ofab.fab$b_dns = 0;
onam.nam$l_rlf = NULL;
onam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &ofab );
nfab.fab$b_fns =
nnam.nam$b_ess =
nfab.fab$b_dns = 0;
nnam.nam$l_rlf = NULL;
nnam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &nfab );
return sts;
}

View File

@@ -1,10 +1,11 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by ODS2.rc
//
/* {{NO_DEPENDENCIES}}
* Microsoft Developer Studio generated include file.
* Used by ODS2.rc
*/
/* Next default values for new objects
*/
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,72 @@
/* RMS.h RMS routine definitions */
/*
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.
*/
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#ifndef _RMS_H
#define _RMS_H
#include <stdint.h>
#include "ods2.h"
#include "f11def.h"
#include "vmstime.h"
#define RMS$_FACILITY 1
#define NAM$C_MAXRSS 255u
#define NAM$M_SYNCHK 0x8u
#define NAM$S_DVI 32u
#define RMS$_RTB 98728
#define RMS$_EOF 98938
#define RMS$_FNF 98962
#define RMS$_NMF 99018
#define RMS$_WCC 99050
#define RMS$_BUG 99380
#define RMS$_DIR 99532
#define RMS$_ESS 99588
#define RMS$_FNM 99628
#define RMS$_IFI 99684
#define RMS$_NAM 99804
#define RMS$_RSS 99988
#define RMS$_RSZ 100004
#define RMS$_WLD 100164
#define RMS$_DNF 114762
#define XAB$C_DAT 18u
#define XAB$C_ALL 20u
#define XAB$C_FHC 29u
#define XAB$C_PRO 19u
#define XAB$C_RDT 30u
#define XAB$C_ITM 36u
#define NAM$C_MAXRSS 255
#define NAM$M_SYNCHK 0x8
/* N.B. xab$l_nxt and xab$b_cod MUST have the same offsets in all XABs */
#define XAB$C_DAT 18
#define XAB$C_FHC 29
#define XAB$C_PRO 19
#define XAB$C_ITM 36
struct XABALL {
void *xab$l_nxt;
uint8_t xab$b_cod;
uint16_t xab$w_vol;
uint32_t xab$l_alq;
uint16_t xab$w_deq;
uint8_t xab$b_bkz;
};
#ifdef RMS$INITIALIZE
struct XABALL cc$rms_xaball = { NULL, XAB$C_ALL, 0,
0, 0, 0 };
#else
extern struct XABALL cc$rms_xaball;
#endif
struct XABRDT {
void *xab$l_nxt;
uint8_t xab$b_cod;
uint16_t xab$w_rvn;
VMSTIME xab$q_rdt;
};
#ifdef RMS$INITIALIZE
struct XABRDT cc$rms_xabrdt = { NULL, XAB$C_RDT, 0, VMSTIME_ZERO };
#else
extern struct XABRDT cc$rms_xabrdt;
#endif
struct XABDAT {
void *xab$l_nxt;
int xab$b_cod;
int xab$w_rvn;
uint8_t xab$b_cod;
uint16_t xab$w_rvn;
VMSTIME xab$q_bdt;
VMSTIME xab$q_cdt;
VMSTIME xab$q_edt;
@@ -52,241 +74,288 @@ struct XABDAT {
};
#ifdef RMS$INITIALIZE
struct XABDAT cc$rms_xabdat = {NULL,XAB$C_DAT,0,
VMSTIME_ZERO, VMSTIME_ZERO,
VMSTIME_ZERO, VMSTIME_ZERO};
struct XABDAT cc$rms_xabdat = { NULL, XAB$C_DAT, 0,
VMSTIME_ZERO, VMSTIME_ZERO,
VMSTIME_ZERO, VMSTIME_ZERO };
#else
extern struct XABDAT cc$rms_xabdat;
#endif
struct XABFHC {
void *xab$l_nxt;
int xab$b_cod;
int xab$b_atr;
int xab$b_bkz;
int xab$w_dxq;
int xab$l_ebk;
int xab$w_ffb;
int xab$w_gbc;
int xab$l_hbk;
int xab$b_hsz;
int xab$w_lrl;
int xab$w_verlimit;
uint8_t xab$b_cod;
uint8_t xab$b_atr;
uint16_t xab$w_ffb;
uint32_t xab$l_ebk;
uint32_t xab$l_hbk;
uint16_t xab$w_lrl;
uint16_t xab$w_dxq;
uint16_t xab$w_gbc;
uint16_t xab$w_verlimit;
uint8_t xab$b_bkz;
uint8_t xab$b_hsz;
};
#ifdef RMS$INITIALIZE
struct XABFHC cc$rms_xabfhc = {NULL,XAB$C_FHC,0,0,0,0,0,0,0,0,0,0};
struct XABFHC cc$rms_xabfhc = { NULL, XAB$C_FHC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#else
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 */
#define XAB$K_SENSEMODE 1u
#define XAB$K_SETMODE 2u
#define XAB$_UCHAR 128u
#define XAB$_UCHAR_NOBACKUP 130u /* (set, sense) FCH$V_NOBACKUP */
#define XAB$_UCHAR_WRITEBACK 131u /* (sense) FCH$V_WRITEBACK */
#define XAB$_UCHAR_READCHECK 132u /* (set, sense) FCH$V_READCHECK */
#define XAB$_UCHAR_WRITECHECK 133u /* (set, sense) FCH$V_WRITECHECK */
#define XAB$_UCHAR_CONTIGB 134u /* (set, sense) FCH$V_CONTIGB */
#define XAB$_UCHAR_LOCKED 135u /* (set, sense) FCH$V_LOCKED */
#define XAB$_UCHAR_CONTIG 136u /* (sense) FCH$V_CONTIG */
#define XAB$_UCHAR_SPOOL 138u /* (sense) FCH$V_SPOOL */
#define XAB$_UCHAR_DIRECTORY 139u /* (sense) FCH$V_DIRECTORY */
#define XAB$_UCHAR_BADBLOCK 140u /* (sense) FCH$V_BADBLOCK */
#define XAB$_UCHAR_MARKDEL 141u /* (sense) FCH$V_BADBLOCK */
struct item_list {
unsigned short int code;
unsigned short int length;
void *buffer;
int retlen;
uint16_t code;
uint16_t length;
void *buffer;
uint16_t *retlen;
};
struct XABITM {
void *xab$l_nxt;
int xab$b_cod;
void *xab$l_nxt;
uint8_t xab$b_cod;
uint8_t xab$b_mode;
struct item_list *xab$l_itemlist;
int xab$b_mode;
};
#ifdef RMS$INITIALIZE
struct XABITM cc$rms_xabitm = {NULL,XAB$C_ITM,NULL,0};
struct XABITM cc$rms_xabitm = {NULL, XAB$C_ITM, 0, NULL};
#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
#define xab$m_noread 1u
#define xab$m_nowrite 2u
#define xab$m_noexe 4u
#define xab$m_nodel 8u
#define xab$m_prot (xab$m_noread|xab$m_nowrite|xab$m_noexe|xab$m_nodel)
#define xab$v_system 0u
#define xab$v_owner 4u
#define xab$v_group 8u
#define xab$v_world 12u
struct XABPRO {
void *xab$l_nxt;
int xab$b_cod;
unsigned int xab$w_pro;
unsigned int xab$l_uic;
void *xab$l_nxt;
uint8_t xab$b_cod;
uint16_t xab$w_pro;
uint32_t xab$l_uic;
};
#ifdef RMS$INITIALIZE
struct XABPRO cc$rms_xabpro = {NULL,XAB$C_PRO,0,0};
struct XABPRO cc$rms_xabpro = { NULL, XAB$C_PRO, 0, 0 };
#else
extern struct XABPRO cc$rms_xabpro;
#endif
#define NAM$M_WILDCARD 0x100
#define NAM$M_EXP_VER UINT32_C(0x00000001)
#define NAM$M_EXP_TYPE UINT32_C(0x00000002)
#define NAM$M_EXP_NAME UINT32_C(0x00000004)
#define NAM$M_WILD_VER UINT32_C(0x00000008)
#define NAM$M_WILD_TYPE UINT32_C(0x00000010)
#define NAM$M_WILD_NAME UINT32_C(0x00000020)
#define NAM$M_EXP_DIR UINT32_C(0x00000040)
#define NAM$M_EXP_DEV UINT32_C(0x00000080)
#define NAM$M_WILDCARD UINT32_C(0x00000100)
#define NAM$M_SEARCH_LIST UINT32_C(0x00000800)
#define NAM$M_CNCL_DEV UINT32_C(0x00001000)
#define NAM$M_ROOT_DIR UINT32_C(0x00002000)
#define NAM$M_LOWVER UINT32_C(0x00004000)
#define NAM$M_HIGHVER UINT32_C(0x00008000)
#define NAM$M_PPF UINT32_C(0x00010000)
#define NAM$M_NODE UINT32_C(0x00020000)
#define NAM$M_QUOTED UINT32_C(0x00040000)
#define NAM$M_GRP_MBR UINT32_C(0x00080000)
#define NAM$M_WILD_DIR UINT32_C(0x00100000)
#define NAM$M_DIR_LVLS UINT32_C(0x00e00000)
#define NAM$V_DIR_LVLS 20u
#define NAM$M_WILD_UFD UINT32_C(0x01000000)
#define NAM$M_WILD_SFD1 UINT32_C(0x02000000)
#define NAM$M_WILD_SFD2 UINT32_C(0x04000000)
#define NAM$M_WILD_SFD3 UINT32_C(0x08000000)
#define NAM$M_WILD_SFD4 UINT32_C(0x10000000)
#define NAM$M_WILD_SFD5 UINT32_C(0x20000000)
#define NAM$M_WILD_SFD6 UINT32_C(0x40000000)
#define NAM$M_WILD_SFD7 UINT32_C(0x80000000)
/* The following are aliased to WILD_UFD, WILD_SFD1 */
#define NAM$M_WILD_GRP UINT32_C(0x01000000)
#define NAM$M_WILD_MBR UINT32_C(0x02000000)
struct NAM {
unsigned short nam$w_did_num;
unsigned short nam$w_did_seq;
unsigned char nam$b_did_rvn;
unsigned char nam$b_did_nmx;
unsigned short nam$w_fid_num;
unsigned short nam$w_fid_seq;
unsigned char nam$b_fid_rvn;
unsigned char nam$b_fid_nmx;
int nam$b_ess;
int nam$b_rss;
int nam$b_esl;
char *nam$l_esa;
int nam$b_rsl;
char *nam$l_rsa;
int nam$b_dev;
char *nam$l_dev;
int nam$b_dir;
char *nam$l_dir;
int nam$b_name;
char *nam$l_name;
int nam$b_type;
char *nam$l_type;
int nam$b_ver;
char *nam$l_ver;
void *nam$l_wcc;
int nam$b_nop;
int nam$l_fnb;
char *nam$l_esa;
char *nam$l_rsa;
char *nam$l_dev;
char *nam$l_dir;
char *nam$l_name;
char *nam$l_type;
char *nam$l_ver;
struct NAM *nam$l_rlf;
void *nam$l_wcc;
struct fiddef nam$w_fid;
struct fiddef nam$w_did;
uint32_t nam$l_fnb;
char nam$t_dvi[1+NAM$S_DVI];
uint8_t nam$b_ess;
uint8_t nam$b_esl;
uint8_t nam$b_rss;
uint8_t nam$b_rsl;
uint8_t nam$b_dev;
uint8_t nam$b_dir;
uint8_t nam$b_name;
uint8_t nam$b_type;
uint8_t nam$b_ver;
uint8_t nam$b_nop;
};
#ifdef RMS$INITIALIZE
struct NAM cc$rms_nam = {0,0,0,0,0,0,0,0,0,0,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,0,0,NULL};
struct NAM cc$rms_nam = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, {0, 0, 0, 0}, {0, 0, 0, 0}, 0,
{ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 },
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
#else
extern struct NAM cc$rms_nam;
#endif
#define RAB$C_SEQ 0
#define RAB$C_RFA 2
/* rab$b_rac */
#define RAB$C_SEQ 0u
#define RAB$C_RFA 2u
/* rab$l_rop */
#define RAB$M_TPT 2
#define RAB$M_EOF 256u
struct RAB {
struct RAB *rab$a__next;
struct FAB *rab$l_fab;
char *rab$l_ubf;
char *rab$l_rhb;
char *rab$l_rbf;
unsigned rab$w_usz;
unsigned rab$w_rsz;
int rab$b_rac;
unsigned short rab$w_rfa[3];
char *rab$l_ubf;
char *rab$l_rhb;
char *rab$l_rbf;
uint32_t rab$l_stv;
uint32_t rab$l_rop;
uint32_t rab$w_isi;
uint16_t rab$w_usz;
uint16_t rab$w_rsz;
uint8_t rab$b_rac;
uint16_t rab$w_rfa[3];
};
#ifdef RMS$INITIALIZE
struct RAB cc$rms_rab = {NULL,NULL,NULL,NULL,0,0,0,{0,0,0}};
struct RAB cc$rms_rab = { NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, 0, 0, {0, 0, 0} };
#else
extern struct RAB cc$rms_rab;
#endif
/* FAB$B_ORG : N.B. These are all high nibble values for fat$b_rtype */
#define FAB$C_SEQ 0u
#define FAB$C_REL 16u
#define FAB$C_IDX 32u
#define FAB$C_HSH 48u
#define FAB$C_SEQ 0
#define FAB$C_REL 16
#define FAB$C_IDX 32
#define FAB$C_HSH 48
/* FAB$B_RAT : N.B. These are all low nibble values for fat$b_rtype */
#define FAB$M_FTN 0x1u
#define FAB$M_CR 0x2u
#define FAB$M_PRN 0x4u
#define FAB$M_BLK 0x8u
#define FAB$M_FTN 0x1
#define FAB$M_CR 0x2
#define FAB$M_PRN 0x4
#define FAB$M_BLK 0x8
/* FAB$B_FAC */
#define FAB$M_PUT 0x1u
#define FAB$M_GET 0x2u
#define FAB$M_DEL 0x4u
#define FAB$M_UPD 0x8u
#define FAB$M_TRN 0x10u
#define FAB$M_BIO 0x20u
#define FAB$M_BRO 0x40u
#define FAB$M_EXE 0x80u
#define FAB$M_PUT 0x1
#define FAB$M_GET 0x2
#define FAB$M_DEL 0x4
#define FAB$M_UPD 0x8
#define FAB$M_TRN 0x10
#define FAB$M_BIO 0x20
#define FAB$M_BRO 0x40
#define FAB$M_EXE 0x80
#define FAB$C_UDF 0
#define FAB$C_FIX 1
#define FAB$C_VAR 2
#define FAB$C_VFC 3
#define FAB$C_STM 4
#define FAB$C_STMLF 5
#define FAB$C_STMCR 6
/* FAB$B_RFM */
#define FAB$C_UDF 0u
#define FAB$C_FIX 1u
#define FAB$C_VAR 2u
#define FAB$C_VFC 3u
#define FAB$C_STM 4u
#define FAB$C_STMLF 5u
#define FAB$C_STMCR 6u
/* 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
#define FAB$M_ASY UINT32_C(1)
#define FAB$M_MXV UINT32_C(2)
#define FAB$M_SUP UINT32_C(4)
#define FAB$M_TMP UINT32_C(8)
#define FAB$M_TMD UINT32_C(16)
#define FAB$M_DFW UINT32_C(32)
#define FAB$M_SQO UINT32_C(64)
#define FAB$M_RWO UINT32_C(128)
#define FAB$M_POS UINT32_C(256)
#define FAB$M_WCK UINT32_C(512)
#define FAB$M_NEF UINT32_C(1024)
#define FAB$M_RWC UINT32_C(2048)
#define FAB$M_DMO UINT32_C(4096)
#define FAB$M_SPL UINT32_C(8192)
#define FAB$M_SCF UINT32_C(16384)
#define FAB$M_DLT UINT32_C(32768)
#define FAB$M_NFS UINT32_C(65536)
#define FAB$M_UFO UINT32_C(131072)
#define FAB$M_PPF UINT32_C(262144)
#define FAB$M_INP UINT32_C(524288)
#define FAB$M_CTG UINT32_C(1048576)
#define FAB$M_CBT UINT32_C(2097152)
#define FAB$M_SYNCSTS UINT32_C(4194304)
#define FAB$M_RCK UINT32_C(8388608)
#define FAB$M_NAM UINT32_C(16777216)
#define FAB$M_CIF UINT32_C(33554432)
#define FAB$M_ESC UINT32_C(134217728)
#define FAB$M_TEF UINT32_C(268435456)
#define FAB$M_OFP UINT32_C(536870912)
#define FAB$M_KFO UINT32_C(1073741824)
struct FAB {
char *fab$l_fna;
char *fab$l_dna;
struct NAM *fab$l_nam;
int fab$w_ifi;
char *fab$l_fna;
char *fab$l_dna;
int fab$b_fns;
int fab$b_dns;
int fab$l_alq;
int fab$b_bks;
int fab$w_deq;
unsigned int fab$b_fsz;
int fab$w_gbc;
unsigned int fab$w_mrs;
int fab$l_fop;
int fab$b_org;
int fab$b_rat;
int fab$b_rfm;
int fab$b_fac;
void *fab$l_xab;
unsigned short fab__w_verlimit;
void *fab$l_xab;
struct RAB *fab$a__rab;
uint32_t fab$l_isi;
uint32_t fab$l_alq;
uint32_t fab$l_fop;
uint32_t fab$l_openfop;
uint16_t fab$w_deq;
uint16_t fab$w_ifi;
uint16_t fab$w_gbc;
uint16_t fab$w_mrs;
uint8_t fab$b_fns;
uint8_t fab$b_dns;
uint8_t fab$b_bks;
uint8_t fab$b_fsz;
uint8_t fab$b_org;
uint8_t fab$b_rat;
uint8_t fab$b_rfm;
uint8_t fab$b_fac;
uint16_t fab__w_verlimit;
};
#ifdef RMS$INITIALIZE
struct FAB cc$rms_fab = {NULL,0,NULL,NULL,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL,0};
struct FAB cc$rms_fab = {NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0};
#else
extern struct FAB cc$rms_fab;
#endif
@@ -304,23 +373,26 @@ extern struct FAB cc$rms_fab;
#define sys$open sys_open
#define sys$create sys_create
#define sys$erase sys_erase
#define sys$rename sys_rename
#define sys$extend sys_extend
#endif
unsigned sys_search(struct FAB *fab);
unsigned sys_parse(struct FAB *fab);
unsigned sys_connect(struct RAB *rab);
unsigned sys_disconnect(struct RAB *rab);
unsigned sys_get(struct RAB *rab);
unsigned sys_put(struct RAB *rab);
unsigned sys_display(struct FAB *fab);
unsigned sys_close(struct FAB *fab);
unsigned sys_open(struct FAB *fab);
unsigned sys_create(struct FAB *fab);
unsigned sys_erase(struct FAB *fab);
unsigned sys_extend(struct FAB *fab);
unsigned sys_setddir(struct dsc_descriptor *newdir,unsigned short *oldlen,
struct dsc_descriptor *olddir);
unsigned sys_initialize(void);
vmscond_t sys_close( struct FAB *fab );
vmscond_t sys_connect( struct RAB *rab );
vmscond_t sys_create( struct FAB *fab );
vmscond_t sys_disconnect( struct RAB *rab );
vmscond_t sys_display( struct FAB *fab );
vmscond_t sys_erase( struct FAB *fab );
vmscond_t sys_extend( struct FAB *fab );
vmscond_t sys_get( struct RAB *rab );
vmscond_t sys_initialize(void);
vmscond_t sys_open( struct FAB *fab );
vmscond_t sys_parse( struct FAB *fab );
vmscond_t sys_put( struct RAB *rab );
vmscond_t sys_rename( struct FAB *oldfab,
void *astrtn, void *astprm, struct FAB *newfab );
vmscond_t sys_search( struct FAB *fab );
vmscond_t sys_setddir( struct dsc_descriptor *newdir, uint16_t *oldlen,
struct dsc_descriptor *olddir );
#endif /* #ifndef _RMS_H */

View File

@@ -1,3 +1,16 @@
/*
* This is distributed as part of ODS2, originally 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
//***************************************************************************
//
// Name: SCSIDEFS.H

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_SEARCHCMD )
@@ -15,139 +18,621 @@
#endif
#endif
#include <ctype.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cmddef.h"
#define CSI "\033["
static const char *const C0[32] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
"BS" , "TAB", "LF" , "VT" , "FF" , "CR" , "SO" , "SI" ,
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
"CAN", "EM" , "SUB", "ESC", "FS" , "GS" , "RS" , "US" };
static const char *const C1[33] = { /* 0x80 - 0xA0 */
"80" , "81" , "BPH", "NBH", "IND", "NEL", "SSA", "ESA",
"HTS", "HTJ", "VTS", "PLD", "PLU", "RI" , "SS2", "SS3",
"DCS", "PU1", "PU2", "STS", "CCH", "MW" , "SPA", "EPA",
"SOS", "SGCI","DECID","CSI", "ST" , "OSC", "PM" , "APC",
"NSP" };
static uint8_t CW[256], CWS;
#if MAXREC <= INT8_MAX
typedef int8_t mpos_t;
#elif MAXREC <= INT16_MAX
typedef int16_t mpos_t;
#else /* MAXREC <= INT32_MAX */
typedef int32_t mpos_t;
#endif
static int prep( int fc, char *pattern, int plen, void **ctx );
static int match( int fc, char *pattern, int plen,
char *data, int dlen, mpos_t *mpos, void *ctx );
/***************************************************************** dosearch() */
/* dosearch: a simple file search routine */
#define search_exact OPT_GENERIC_1
#define search_number OPT_GENERIC_2
#define search_confirm OPT_GENERIC_3
#define search_heading OPT_GENERIC_4
#define search_nohead OPT_GENERIC_5
#define search_log OPT_GENERIC_6
#define search_highlight OPT_GENERIC_7
#define search_nowindow OPT_GENERIC_8
#define search_page OPT_GENERIC_9
#define search_blink OPT_SHARED_1
#define search_bold OPT_SHARED_2
#define search_reverse OPT_SHARED_3
#define search_underline OPT_SHARED_4
#define search_hardcopy OPT_SHARED_5
param_t 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 }
#define search_match (OPT_SHARED_7|OPT_SHARED_6)
#define search_v_match (OPT_V_SHARED + 5)
#define MAT_AND 0
#define MAT_OR 1
#define MAT_NAND 2
#define MAT_NOR 3
#define search_mat_and (MAT_AND << search_v_match)
#define search_mat_or (MAT_OR << search_v_match)
#define search_mat_nand (MAT_NAND << search_v_match)
#define search_mat_nor (MAT_NOR << search_v_match)
static qual_t
matchkwds[] = { {"and", search_mat_and, search_match, NV,
"commands search qual_match match_and"},
{"or", search_mat_or, search_match, NV,
"commands search qual_match match_or"},
{"nand", search_mat_nand, search_match, NV,
"commands search qual_match match_nand"},
{"nor", search_mat_nor, search_match, NV,
"commands search qual_match match_nor"},
{NULL, 0, 0, NV, NULL}
};
static qual_t
highkwds[] = { {"blink", search_blink, 0, NV,
"commands search qual_highlight highlight_blink"},
{"bold", search_bold, 0, NV,
"commands search qual_highlight highlight_bold"},
{"hardcopy", search_hardcopy, 0, NV,
"commands search qual_highlight highlight_hardcopy"},
{"reverse", search_reverse, 0, NV,
"commands search qual_highlight highlight_reverse"},
{"underline", search_underline, 0, NV,
"commands search qual_highlight highlight_underline"},
{NULL, 0, 0, NV, NULL}
};
static uint32_t height;
const int search_defaults = search_highlight | search_mat_or;
defqualsp_t search_defopt = NULL;
qual_t
searchquals[] = { {"confirm", search_confirm, 0, NV,
"-commands search qual_confirm"},
{"noconfirm", 0, search_confirm, NV, NULL},
{"exact", search_exact, 0, NV,
"-commands search qual_exact"},
{"noexact", 0, search_exact, NV, NULL},
{"log", search_log, 0, NV,
"-commands search qual_log"},
{"nolog", 0, search_log, NV, NULL},
{"heading", search_heading, search_nohead, NV,
"-commands search qual_heading"},
{"noheading", search_nohead, search_heading, NV, NULL},
{"highlight", search_highlight, 0, VOPT(KV(highkwds)),
"-commands search qual_highlight"},
{"nohighlight", 0, search_highlight, NV, NULL},
{"match_type", 0, 0, KV(&matchkwds),
"commands search qual_match"},
{"nowindow", search_nowindow|search_heading, /* ~~/WINDOW=0 */
search_nohead, NV,
"commands search qual_nowindow"},
{"numbers", search_number, 0, NV,
"-commands search qual_numbers"},
{"nonumbers", 0, search_number, NV, NULL},
{"page", search_page, 0, VOPT(DV(&height)),
"-commands search qual_page"},
{"nopage", 0, search_page, NV, NULL},
{NULL, 0, 0, NV, NULL}
};
param_t
searchpars[] = { {"filespec", REQ, FSPEC, NOPA, "commands search filespec"},
{"string", REQ|NOLIM, STRING, NOPA, "commands search string"},
{ NULL, 0, 0, NOPA, NULL }
};
DECL_CMD(search) {
int sts = 0;
int filecount = 0;
int findcount = 0;
vmscond_t sts = 0;
vmscond_t confirm = ODS2_CONFIRM_ALL;
options_t options;
uint32_t filecount = 0;
uint32_t findcount = 0;
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
register char firstch, *searstr, *searend, *s;
struct NAM nam = cc$rms_nam;
struct FAB fab = cc$rms_fab;
struct RAB rab = cc$rms_rab;
char *rec = NULL;
mpos_t *mpos = NULL;
uint32_t *mind = NULL;
int theight;
pause_t *pause = NULL, pausectl;
char highlight[sizeof(CSI ";1;4;5;7m")];
struct sstr {
void *ctx;
int slen;
char *string;
} *sstr, *ss;
int nstrings;
uint32_t match_type;
struct NAM nam;
struct FAB fab;
struct RAB rab;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
memset( res, 0, sizeof(res) );
memset( rsa, 0, sizeof(rsa) );
memset( &pausectl, 0, sizeof(pausectl) );
searstr = argv[2]; /* unquote( argv[2] ); */
if( !CWS ) {
unsigned int i;
searend = searstr + strlen( searstr );
for ( s = searstr; s < searend; s++ ) {
*s = tolower( *s );
for( i = 0; i < 256; i++ ) {
if( isprint( i ) )
CW[i] = 1;
else if( i < 32 )
CW[i] = 2 + (unsigned char)strlen( C0[i] );
else if( i == '\177' )
CW[i] = sizeof( "<DEL>" ) -1;
else if( i >= 0x80ul && i <= 0xA0ul )
CW[i] = 2 + (unsigned char)strlen( C1[i - 0x80ul] );
else
CW[i] = sizeof( "<xx>" ) -1;
}
CWS = TRUE;
}
firstch = *searstr++;
filecount = 0;
findcount = 0;
(void) termchar( NULL, &theight );
height = theight-1;
if( search_defopt != NULL ) {
if( $FAILS(sts = checkquals( &options, search_defaults, searchquals,
search_defopt->qualc, search_defopt->qualv )) ) {
return sts;
}
}
else
options = search_defaults;
if( $FAILS(sts = checkquals( &options, options,
searchquals, qualc, qualv )) )
return sts;
match_type = (options & search_match) >> search_v_match;
if( options & search_page ) {
pausectl.interval = height;
pausectl.lineno = 0;
pausectl.prompt = SEARCH_CONTINUE;
pause = &pausectl;
}
if( options & search_highlight ) {
if( !(options &
(search_bold|search_blink|search_underline|search_reverse|search_hardcopy)) )
memcpy( highlight, CSI "1m", sizeof( CSI "1m" ) );
else if( options & (search_bold|search_blink|search_underline|search_reverse) ) {
memcpy( highlight, CSI, sizeof( CSI ) );
if( options & search_bold )
memcpy( highlight+strlen(highlight), ";1", sizeof( ";1" ) );
if( options & search_blink )
memcpy( highlight+strlen(highlight), ";5", sizeof( ";5" ) );
if( options & search_reverse )
memcpy( highlight+strlen(highlight), ";7", sizeof( ";7" ) );
if( options & search_underline )
memcpy( highlight+strlen(highlight), ";4", sizeof( ";4" ) );
memcpy( highlight+strlen(highlight), "m", sizeof( "m" ) );
} else
highlight[0] = '\0';
}
nstrings = argc - 2;
if( (sstr = calloc( nstrings, sizeof( struct sstr ) )) == NULL ) {
return printmsg( SS$_INSFMEM, 0 );
}
if( options & search_confirm )
confirm = SEARCH_CONFIRM;
nam = cc$rms_nam;
fab = cc$rms_fab;
rab = cc$rms_rab;
rab.rab$l_fab = &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 & STS$M_SUCCESS ) {
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = FAB$M_NAM;
while ( ( sts = sys_search( &fab ) ) & STS$M_SUCCESS ) {
sts = sys_open(&fab);
if ( !( sts & STS$M_SUCCESS ) ) {
printf("%%SEARCH-F-OPENFAIL, Open error: %s\n",getmsg(sts, MSG_TEXT));
} else {
rab.rab$l_fab = &fab;
sts = sys_connect( &rab );
if ( sts & STS$M_SUCCESS ) {
int printname = 1;
char *rec;
if( (rec = malloc( MAXREC + 2 )) == NULL )
sts = SS$_INSFMEM;
else {
filecount++;
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while( (sts = sys_get( &rab )) & STS$M_SUCCESS ) {
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"
);
printf( "%s\n\n", rsa );
printname = 0;
}
fputs( rec, stdout );
if( fab.fab$b_rat & PRINT_ATTR ) {
fputc( '\n', stdout );
}
break;
}
}
}
}
free( rec );
rec = NULL;
}
sys_disconnect(&rab);
}
if (sts == SS$_NOTINSTALL) {
printf(
"%%SEARCH-W-NOIMPLEM, file operation not implemented\n"
);
sts = SS$_NORMAL;
}
sys_close(&fab);
fab.fab$l_nam = &nam;
fab.fab$b_fac = FAB$M_GET;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = (uint8_t)strlen(fab.fab$l_fna);
do {
int i;
if( (mind = malloc( (size_t)4u * ((MAXREC + 2u + 31u) / 32u) )) == NULL ) {
sts = printmsg( SS$_INSFMEM, 0 );
break;
}
for( ss = sstr, i = 0; i < nstrings; ss++, i++ ) {
ss->string = argv[2 + i];
ss->slen = (int)strlen( ss->string);
if( ss->slen < 1 ) {
sts = printmsg( SEARCH_BADSTRING, 0, i + 1 );
break;
}
if( !prep( !(options & search_exact),
ss->string, ss->slen, &ss->ctx ) ) {
sts = printmsg( SS$_INSFMEM, 0 );
break;
}
}
if (sts == RMS$_NMF || sts == RMS$_FNF) sts = SS$_NORMAL;
}
if ( sts & STS$M_SUCCESS ) {
if (filecount < 1) {
printf("%%SEARCH-W-NOFILES, no files found\n");
if( $FAILS(sts = sys_parse(&fab)) ) {
printmsg( SEARCH_PARSEFAIL, 0, fab.fab$l_fna );
sts = printmsg( sts, MSG_CONTINUE, SEARCH_PARSEFAIL );
break;
}
nam.nam$l_esa[nam.nam$b_esl] = '\0';
nam.nam$l_rsa = rsa;
nam.nam$b_rss = NAM$C_MAXRSS;
fab.fab$l_fop = 0;
if( (rec = malloc( MAXREC + 2 )) == NULL ) {
sts = printmsg( SS$_INSFMEM, 0 );
break;
}
if( (mpos = malloc( MAXREC * sizeof( mpos_t ) )) == NULL ) {
sts = printmsg( SS$_INSFMEM, 0 );
break;
}
while( TRUE ) {
int32_t lineno, filefind;
int first = TRUE;
if( $FAILS(sts = sys_search( &fab )) ) {
if( $MATCHCOND(sts, RMS$_NMF) ) {
sts = SS$_NORMAL;
break;
}
printmsg( SEARCH_SEARCHFAIL, 0, nam.nam$l_esa );
sts = printmsg( sts, MSG_CONTINUE, SEARCH_SEARCHFAIL );
break;
}
nam.nam$l_rsa[ nam.nam$b_rsl ] = '\0';
if( $FAILS(sts = sys_open(&fab)) ) {
printmsg( SEARCH_OPENIN, 0, nam.nam$l_rsa );
sts = printmsg( sts, MSG_CONTINUE, SEARCH_OPENIN );
continue;
}
if( $MATCHCOND( confirm, SEARCH_CONFIRM) )
confirm = confirm_cmd( confirm, nam.nam$l_rsa);
if( !$MATCHCOND( confirm, ODS2_CONFIRM_ALL ) ) {
if( $MATCHCOND( confirm, ODS2_CONFIRM_YES ) ) {
confirm = SEARCH_CONFIRM;
} else if( $MATCHCOND( confirm, ODS2_CONFIRM_NO ) ) {
confirm = SEARCH_CONFIRM;
sys_close( &fab );
continue;
} else { /* ODS2_CONFIRM_QUIT */
sys_close( &fab );
sts = confirm;
break;
}
}
if( $FAILS(sts = sys_connect( &rab )) ) {
printmsg( sts, 0 );
sys_close( &fab );
continue;
}
filecount++;
lineno = 0;
filefind = 0;
rab.rab$l_ubf = rec;
rab.rab$w_usz = MAXREC;
while( $SUCCESSFUL(sts = sys_get( &rab )) ) {
int indent = 0, matched = 0, hl = FALSE;
unsigned m;
char *p;
++lineno;
for( ss = sstr; ss < sstr + nstrings; ss++ ) {
int nmat;
nmat = match( !(options & search_exact),
ss->string, ss->slen,
rec, rab.rab$w_rsz, mpos, ss->ctx );
if( nmat <= 0 )
continue;
if( !matched++ )
memset( mind, 0, 4u * (((size_t)rab.rab$w_rsz + 31u) / 32u) );
for( i = 0; i < nmat; i++ )
for( m = mpos[i]; m < (unsigned)(mpos[i] + ss->slen); m++ )
mind[ m >> 5 ] |= UINT32_C(1) << (m & 31u);
}
if( match_type == MAT_OR ) {
if( !(matched > 0) )
continue;
} else if( match_type == MAT_AND ) {
if( !(matched == nstrings) )
continue;
} else if( match_type == MAT_NOR ) {
if( !!(matched > 0) )
continue;
} else { /* MAT_NAND */
if( !!(matched == nstrings) )
continue;
}
findcount++;
filefind++;
if( first && !(options & search_nohead) &&
((options & search_heading) ||
(nam.nam$l_fnb & NAM$M_WILDCARD)) ) {
first = FALSE;
if( options & search_nowindow ) {
printf( "%.*s", nam.nam$b_rsl, nam.nam$l_rsa );
if( $FAILS(sts = put_c( '\n', stdout, pause )) )
break;
continue;
} else {
if( $FAILS(sts = put_str( "\n******************************\n",
stdout, pause )) )
break;
printf( "%.*s", nam.nam$b_rsl, nam.nam$l_rsa );
if( $FAILS(sts = put_strn( "\n\n", 2, stdout, pause )) )
break;
}
} else if( options & search_nowindow )
continue;
if( options & search_number )
indent = printf( "%u: ", lineno );
for( m = 0, p = rec; p < rec + rab.rab$w_rsz; m++, p++ ) {
if( matched && (options & search_highlight) ) {
if( mind[ m >> 5 ] & (UINT32_C(1) << (m & 31u)) ) {
if( !hl && highlight[0] )
fputs( highlight, stdout );
hl = TRUE;
} else {
if( hl && highlight[0] )
fputs( CSI "m", stdout );
hl = FALSE;
}
}
if( isprint( *p & 0xFFul ) ) {
putc( (*p & 0xFFul), stdout );
} else if( (*p & 0xFFul) < 32 ) {
printf( "<%s>", C0[*p & 0x1Ful] );
} else if( *p == '\177' ) {
printf( "<DEL>" );
} else if( (*p & 0xFFul) >= 0x80ul &&
(*p & 0xFFul) <= 0xA0ul ) { /* Special case A0 for code analysis */
printf( "<%s>", C1[ ((*p & 0xFFul) == 0xA0ul)? 0x20ul :
(((*p & 0xFFul) - 0x80ul) & 0x1Ful) ] );
} else
printf( "<%02lX>", (*p & 0xFFul) );
}
if( hl && highlight[0] )
fputs( CSI "m", stdout );
hl = FALSE;
if( $FAILS(sts = put_c( '\n', stdout, pause )) )
break;
if( matched && (options & search_hardcopy) ) {
unsigned e;
for( e = rab.rab$w_rsz; e > 0; --e )
if( mind[ (e - 1) >> 5 ] & (UINT32_C(1) << ((e -1) & 31u)) )
break;
if( e > 0 ) {
printf( "%*s", indent, "" );
for( m = 0, p = rec; m < e; m++, p++ ) {
int i;
for( i = 0; i < CW[*p & 0xFFul]; i++ )
fputc( (mind[ m >> 5] & (UINT32_C(1) << (m & 31u)))?
'^': ' ', stdout );
}
if( $FAILS(sts = put_c( '\n', stdout, pause)) )
break;
}
}
}
sys_disconnect( &rab );
sys_close( &fab );
if( options & search_log ) {
if( filefind > 0 ) {
printmsg( SEARCH_MATCHED, 0,
nam.nam$l_rsa, lineno, filefind );
} else {
printmsg( SEARCH_FILE, 0, nam.nam$l_rsa, lineno );
}
}
if( $MATCHCOND(sts, SS$_ABORT) )
break;
}
} while( 0 );
for( ss = sstr; ss < sstr + nstrings; ss++ )
free( ss->ctx );
free( sstr );
free( mind );
free( rec );
free( mpos );
fab.fab$b_fns =
nam.nam$b_ess =
fab.fab$b_dns = 0;
nam.nam$l_rlf = NULL;
nam.nam$b_nop = NAM$M_SYNCHK;
(void) sys_parse( &fab ); /* Release context */
if( $SUCCESSFUL(sts) ||
$MATCHCOND(sts, SS$_ABORT) || $MATCHCOND(sts, ODS2_CONFIRM_QUIT) ) {
if( filecount < 1 ) {
sts = printmsg( SEARCH_NOFILES, 0 );
} else {
if (findcount < 1) {
printf("%%SEARCH-I-NOMATCHES, no strings matched\n");
if( findcount < 1 ) {
sts = printmsg( SEARCH_NOMATCH, 0 );
}
}
} else {
printf("%%SEARCH-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
sts = printmsg(sts, 0 );
}
return sts;
}
/***************************************************************** prep() */
static int prep( int fc, char *pattern, int plen, void **ctx ) {
int i, j, k = 0;
int *bm, *gm, *sx;
/* BM1977 */
*ctx = NULL;
#define AS (UCHAR_MAX+1)
#define ALLOC(plen) ( (AS + plen) * sizeof( int ) )
if( (bm = (int *)malloc( ALLOC((size_t)plen) )) == NULL ) {
return FALSE;
}
if( (sx = (int *)malloc( plen * sizeof( int ) )) == NULL ) {
free( bm );
return FALSE;
}
*ctx = bm;
gm = bm + AS;
for( i = 0; i < AS; i++ ) {
bm[i] = (int)plen;
}
j = plen - 1;
if( fc ) {
for( i = 0; i < j; i++ ) {
pattern[i] = tolower( pattern[i] );
bm[ (unsigned)(pattern[i] & 0xFFul) ] = j - i;
}
pattern[i] = tolower( pattern[i] & 0xFFul );
} else
for( i = 0; i < j; i++ ) {
bm[ (unsigned)(pattern[i] & 0xFFul) ] = j - i;
}
sx[j] = plen;
for( i = plen - 2; i >= 0; i-- ) {
if( i > j && sx[ i + plen -1 - k ] < i - j ) {
sx[i] = sx[ i + plen - 1 -k ];
} else {
if( i < j ) {
j = i;
}
k = i;
while( j >= 0 && pattern[j] == pattern[ j + plen - 1 - k ] ) {
--j;
}
sx[i] = k - j;
}
}
for( i = 0; i < plen; i++ ) {
gm[i] = plen;
}
k = plen - 1;
for( j = 0, i = k; i >= 0; i-- ) {
if( sx[i] == i + 1 ) {
for( ; j < k - i; j++ ) {
if( gm[j] == plen ) {
gm[j] = k - i;
}
}
}
}
for( i = 0; i <= plen - 2; i++ ) {
gm[ k - sx[i] ] = k - i;
}
free( sx );
return TRUE;
}
/***************************************************************** match() */
static int match( int fc, char *pattern, int plen,
char *data, int dlen, mpos_t *mpos, void *ctx ) {
int i, j, n = 0;
int *bm, *gm;
bm = ctx;
gm = bm + AS;
if( fc ) {
for( j = 0; j <= dlen - plen; ) {
for( i = plen -1;
i >= 0 && pattern[i] == tolower( data[i + j] & 0xFFul ); i-- )
;
if( i < 0 ) {
if( mpos != NULL )
mpos[ n ] = j;
++n;
j += gm[0];
} else {
int g, b;
g = gm[i];
b = bm[ (unsigned)(tolower( data[i + j] & 0xFFul )
& 0xFFul) ] - plen + 1 + i;
j += (g > b)? g: b;
}
}
return n;
}
for( j = 0; j <= dlen - plen; ) {
for( i = plen -1; i >= 0 && pattern[i] == data[i + j]; i-- )
;
if( i < 0 ) {
if( mpos != NULL )
mpos[ n ] = j;
++n;
j += gm[0];
} else {
int g, b;
g = gm[i];
b = bm[ (unsigned)(data[i + j] & 0xFFul) ] - plen + 1 + i;
j += (g > b)? g: b;
}
}
return n;
}

View File

@@ -4,7 +4,10 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_SETCMD )
@@ -17,89 +20,271 @@
#include "cmddef.h"
#ifdef USE_LIBEDIT
#include <histedit.h>
extern EditLine *editline;
extern History *edithist;
#endif
static hlpfunc_t sethelp;
static unsigned setcwd( char *newdef );
static unsigned setdef( char *newdef );
static vmscond_t setcwd( char *newdef );
static vmscond_t setdef( char *newdef );
static vmscond_t savequals( options_t defval, qual_t *qp,
int qualc, char **qualv,
defqualsp_t *saveloc );
static void set_exit( void );
/******************************************************************* doset() */
static qual_t setkwds[] = { {"cwd", 0, 0, NV, "Working directory on local system"},
{"directory_qualifiers", 1, 0, NV, "Default qualifiers for DIRECTORY command" },
{"default", 2, 0, NV, "Default directory on VMS volume"},
{"qualifier_style", 3, 0, NV, "Qualifier style (Unix, VMS)"},
{"verify", 4, 0, NV, "-Display commands in indirect files"},
{"noverify", 5, 0, NV, NULL },
{NULL, 0, 0, NV, NULL }
#define set_msgdef OPT_GENERIC_1
/* Indexes must match in doset() & sethelp() */
static uint32_t histmax;
static
qual_t setkwds[] = { {"cwd", 0, 0, NV,
"commands set item_name item_cwd"},
{"directory_qualifiers", 1, 0, NV,
"commands set item_name item_dirquals"},
{"copy_qualifiers", 2, 0, NV,
"commands set item_name item_copyquals" },
{"default", 3, 0, NV,
"commands set item_name item_setdef"},
{"error_exit", 4, 0, NV,
"-commands set item_name item_seterrxit"},
{"noerror_exit", 5, 0, NV, NULL },
{"message", 6, 0, NV,
"commands set item_name item_setmsg"},
{"qualifier_style", 7, 0, NV,
"commands set item_name item_qualstyle"},
{"search_qualifiers", 8, 0, NV,
"commands set item_name item_searchquals"},
{"verify", 9, 0, NV,
"-commands set item_name item_verify"},
{"noverify", 10, 0, NV, NULL },
#ifdef USE_LIBEDIT
{"key_bindings", 11, 0, NV,
"commands set item_name item_key_bindings"},
#endif
{"history_limit", 12, 0, DV(&histmax),
"commands set item_name item_history_limit"},
{"help_file", 13, 0, NV,
"commands set item_name item_helpfile"},
{NULL, 0, 0, NV, NULL }
};
static qual_t setqskwds[] = {{"unix", 1, 0, NV, "Unix style options, '-option'"},
{"vms", 2, 0, NV, "VMS style qualifiers, '/qualifier'"},
{NULL, 0, 0, NV, NULL }
static
qual_t setmsgkwdsp[] = {{"facility", MSG_FACILITY, 0, NV,
"commands set item_name item_msgfac"},
{"nofacility", 0, MSG_FACILITY, NV, NULL},
{"severity", MSG_SEVERITY, 0, NV,
"commands set item_name item_msgsev"},
{"noseverity", 0, MSG_SEVERITY, NV, NULL},
{"identification", MSG_NAME, 0, NV,
"commands set item_name item_msgid"},
{"noidentification", 0, MSG_NAME, NV, NULL},
{"text", MSG_TEXT, 0, NV,
"commands set item_name item_msgtext"},
{"notext", 0, MSG_TEXT, NV, NULL},
{"default", set_msgdef, 0, NV,
"commands set item_name item_default"},
{NULL, 0, 0, NV, NULL }
};
static
qual_t setqskwds[] = {{"unix", 1, 0, NV, "commands set value value_unix"},
{"dcl", 2, 0, NV, "commands set value value_dcl"},
{"vms", 2, 0, NV, NULL },
{NULL, 0, 0, NV, NULL }
};
param_t setpars[] = { {"item_name", REQ, KEYWD, PA(setkwds), "" },
{"value" , CND, KEYWD, sethelp, setqskwds, "" },
{NULL, 0, 0, NOPA, NULL },
};
/*********************************************************** doset() */
extern qual_t copyquals[];
extern const int copy_defaults;
extern defqualsp_t copy_defopt;
extern qual_t dirquals[];
extern const int dir_defaults;
extern int dir_defopt;
extern defqualsp_t dir_defopt;
extern qual_t searchquals[];
extern const int search_defaults;
extern defqualsp_t search_defopt;
extern uint32_t cmd_histsize;
DECL_CMD(set) {
int parnum;
options_t parnum;
vmscond_t sts;
UNUSED(argc);
parnum = checkquals( 0, setkwds, -1, argv+1 );
if( $FAILS(sts = checkquals( &parnum, 0, setkwds, -1, argv+1 )) ) {
return sts;
}
switch( parnum ) {
default:
return SS$_BADPARAM;
case 0: /* default */
case 2: /* current working directory */
if( qualc ) {
printf( "%%ODS2-E-NOQUAL, No qualifiers are permitted\n" );
return 0;
}
case 3: /* current working directory */
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
return (parnum == 0)? setcwd( argv[2] ) : setdef( argv[2] );
case 1:{ /* directory_qualifiers */
int options = checkquals(dir_defaults,dirquals,qualc,qualv);
if( options == -1 )
return SS$_BADPARAM;
dir_defopt = options;
return 1;
if( qualc == 0 )
return printmsg( ODS2_NOQUALS, 0 );
return savequals( dir_defaults, dirquals,
qualc, qualv, &dir_defopt );
}
case 3: { /* qualifier_style */
int par = checkquals (0,setqskwds,1,argv+2);
if( par == -1 )
return SS$_BADPARAM;
case 2:{ /* copy_qualifiers */
if( qualc == 0 )
return printmsg( ODS2_NOQUALS, 0 );
return savequals( copy_defaults, copyquals,
qualc, qualv, &copy_defopt );
}
case 4:
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
error_exit = TRUE;
return SS$_NORMAL;
case 5:
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
error_exit = FALSE;
return SS$_NORMAL;
case 6: { /* message file */
options_t options;
if( qualc != 0 ) {
if( $FAILS(sts = checkquals( &options, get_message_format(),
setmsgkwdsp, qualc, qualv )) )
return sts;
if( argc > 2 )
return printmsg( ODS2_NOPAROK, 0 );
if( options & set_msgdef ) {
if( (options & ~set_msgdef) != get_message_format() )
return printmsg( ODS2_INCONQUAL, 0 );
return set_message_file( NULL );
}
if( $FAILS(sts = set_message_format( options )) )
return printmsg( sts, 0 );
return SS$_NORMAL;
}
if( argc > 3 )
return printmsg( ODS2_TOOMANY, 0, "parameters" );
if( argc < 3 )
return printmsg( ODS2_TOOFEW, 0, "parameters" );
if( $FAILS(sts = set_message_file( argv[2] )) )
return printmsg(sts, 0 );
return SS$_NORMAL;
}
case 7: { /* qualifier_style */
options_t par;
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
if( $FAILS(sts = checkquals( &par, 0, setqskwds, 1, argv+2 )) ) {
return sts;
}
switch(par) {
default:
abort();
case 2:
vms_qual = 1;
qstyle_s = "/";
break;
case 1:
vms_qual = 0;
qstyle_s = "-";
break;
}
return 1;
return SS$_NORMAL;
}
case 4:
verify_cmd = 1;
return 1;
case 5:
verify_cmd = 0;
return 1;
case 8:{ /* search_qualifiers */
if( qualc == 0 )
return printmsg( ODS2_NOQUALS, 0 );
return savequals( search_defaults, searchquals,
qualc, qualv, &search_defopt );
}
case 9:
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
verify_cmd = TRUE;
return SS$_NORMAL;
case 10:
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
verify_cmd = FALSE;
return SS$_NORMAL;
#ifdef USE_LIBEDIT
case 11: {
char *av[20];
int i, ac;
ac = argc -2;
for( i = 0; i < 20; i++ ) {
if( i < ac )
av[i] = argv[i+2];
else
av[i] = NULL;
}
el_set( editline, EL_BIND,
av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7],
av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15],
av[16], av[17], av[18], NULL );
return SS$_NORMAL;
}
#endif
case 12: {
#ifdef USE_LIBEDIT
HistEvent ev;
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
if( histmax < 1 )
return printmsg( HELP_SETCMDHISTVAL, 0 );
if( history( edithist, &ev, H_SETSIZE, histmax ) >= 0 ) {
cmd_histsize = histmax;
}
#else
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
if( histmax < 1 )
return printmsg( HELP_SETCMDHISTVAL, 0 );
cmd_histsize = histmax;
#endif
return SS$_NORMAL;
}
case 13:
if( qualc )
return printmsg( ODS2_NOQUALSOK, 0 );
if( argc > 3 )
return printmsg( ODS2_TOOMANY, 0, "parameters" );
if( argc < 3 )
return printmsg( ODS2_TOOFEW, 0, "parameters" );
if( $FAILS(sts = sethelpfile( argv[2], NULL, NULL )) )
return printmsg( sts, 0 );
return sts;
} /* switch */
}
/************************************************************ sethelp() */
static const char * sethelp( CMDSETp_t cmd, paramp_t p, int argc, char **argv ) {
int par;
static const char *sethelp( CMDSETp_t cmd, paramp_t p,
int argc, char **argv ) {
options_t par;
vmscond_t sts;
UNUSED( cmd );
UNUSED( argc );
@@ -108,37 +293,73 @@ static const char * sethelp( CMDSETp_t cmd, paramp_t p, int argc, char **argv )
p->helpstr = "";
p->ptype = KEYWD;
p->arg = setkwds;
return "Type 'help set value ITEM' for item details\n";
return getmsg( HELP_SETVALUE, MSG_TEXT );
}
par = checkquals( 0, setkwds, -1, argv+1 );
if( par == -1 )
if( $FAILS(sts = checkquals( &par, 0, setkwds, -1, argv+1 )) ) {
return NULL;
}
switch( par ) {
case 0:
p->helpstr = "working directory for local files";
p->helpstr = "commands set item_name type_cwd";
p->ptype = STRING;
break;
case 1:
p->helpstr = "default directory on volume";
p->ptype = VMSFS;
break;
case 2:
p->helpstr = "directory qualifier name ";
p->ptype = KEYWD;
p->helpstr = "commands set item_name type_dirquals";
p->ptype = QUALS;
p->arg = dirquals;
break;
case 2:
p->helpstr = "commands set item_name type_copyquals";
p->ptype = QUALS;
p->arg = copyquals;
break;
case 3:
p->helpstr = "style ";
p->ptype = KEYWD;
p->arg = setqskwds;
p->helpstr = "commands set item_name type_setdef";
p->ptype = FSPEC;
break;
case 4:
case 5:
p->helpstr = "commands set item_name type_seterrxit";
p->ptype = NONE;
break;
case 6:
p->helpstr = "commands set item_name type_setmsg";
p->ptype = QUALS;
p->arg = setmsgkwdsp;
break;
case 7:
p->helpstr = "commands set item_name type_qualstyle";
p->ptype = KEYWD;
p->arg = setqskwds;
break;
case 8:
p->helpstr = "commands set item_name type_searchquals";
p->ptype = QUALS;
p->arg = searchquals;
break;
case 9:
case 10:
p->helpstr = "commands set item_name item_verify";
p->ptype = NONE;
break;
#ifdef USE_LIBEDIT
case 11:
p->helpstr = "commands set item_name item_key_bindings";
p->ptype = STRING;
break;
#endif
case 12:
p->helpstr = "commands set item_name item_history_limit";
p->ptype = STRING;
break;
case 13:
p->helpstr = "commands set item_name item_helpfile";
p->ptype = NONE;
break;
default:
fprintf( stderr, "Missing help key for param %d\n", par );
abort();
}
return NULL;
@@ -146,37 +367,39 @@ static const char * sethelp( CMDSETp_t cmd, paramp_t p, int argc, char **argv )
/*********************************************************** setcwd() */
static unsigned setcwd( char *newdef ) {
static vmscond_t setcwd( char *newdef ) {
if( chdir( newdef ) != 0 ) {
printf( "%%ODS2-W-SETDEF, Error %s setting cwd to %s\n",
strerror( errno ), newdef );
return SS$_BADPARAM;
}
return SS$_NORMAL;
int err;
err = errno;
printmsg( ODS2_SETCWD, 0 );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, ODS2_SETCWD,
strerror( err ) );
}
return SS$_NORMAL;
}
/*********************************************************** setdef() */
static int default_set = FALSE;
static unsigned setdef( char *newdef ) {
register unsigned sts;
struct dsc_descriptor defdsc;
static vmscond_t setdef( char *newdef ) {
register vmscond_t sts;
struct dsc_descriptor defdsc = { 0, 0, 0, NULL };
defdsc.dsc_a_pointer = (char *) newdef;
defdsc.dsc_w_length = (unsigned short)strlen( defdsc.dsc_a_pointer );
sts = sys_setddir( &defdsc, NULL, NULL );
if ( sts & STS$M_SUCCESS ) {
if( $SUCCESSFUL(sts = sys_setddir( &defdsc, NULL, NULL )) ) {
default_set = TRUE;
} else {
printf( "%%ODS2-E-SETDEF, Error %s setting default to %s\n", getmsg(sts, MSG_TEXT), newdef );
sts = printmsg( sts, 0 );
}
return sts;
}
/*********************************************************** mountdef() */
int mountdef( const char *devnam ) {
vmscond_t mountdef( const char *devnam ) {
char *colon, *buf;
size_t len;
@@ -184,10 +407,9 @@ int mountdef( const char *devnam ) {
return SS$_NORMAL;
len = strlen( devnam );
buf = (char *) malloc( len + sizeof( ":[000000]" ));
buf = (char *) malloc( len + sizeof( ":[000000]" ) );
if( buf == NULL ) {
perror( "malloc" );
return SS$_INSFMEM;
return printmsg( ODS2_OSERROR, 0, strerror( errno ) );
}
colon = strchr( devnam, ':' );
@@ -195,8 +417,82 @@ int mountdef( const char *devnam ) {
len = (size_t)(colon - devnam);
memcpy( buf, devnam, len );
memcpy( buf+len, ":[000000]", sizeof( ":[000000]" ) );
setdef(buf);
setdef( buf );
free( buf );
return SS$_NORMAL;
}
/************************************************************ savequals() */
static defqualsp_t savedquals = NULL;
static vmscond_t savequals( options_t defval, qual_t *qp,
int qualc, char **qualv,
defqualsp_t *saveloc ) {
vmscond_t sts;
int i;
size_t len;
defqualsp_t newq, *old;
char *dp;
len = ( offsetof( defquals_t, data ) +
( sizeof( char** ) * ((size_t)qualc +1) ) );
for( i = 0; i < qualc; i++ )
len += strlen( qualv[i] ) + 1;
if( (newq = (defqualsp_t) malloc( len )) == NULL )
return SS$_INSFMEM;
newq->qualc = qualc;
newq->qualv = newq->data;
dp = (char *)(newq->data + qualc + 1);
for( i = 0; i < qualc; i++ ) {
newq->qualv[i] = dp;
len = strlen( qualv[i] ) +1;
memcpy( dp, qualv[i], len );
dp += len;
}
newq->qualv[i] = NULL;
if( $FAILS(sts = checkquals( &defval, defval, qp, qualc, qualv )) ) {
free( newq );
return sts;
}
for( old = &savedquals; *old != NULL; old = &(*old)->next ) {
defqualsp_t t;
if( (t = *old) == *saveloc ) {
*old = t->next;
free( t );
break;
}
}
newq->next = savedquals;
if( savedquals == NULL )
atexit( set_exit );
*saveloc =
savedquals = newq;
return SS$_NORMAL;
}
/************************************************************ set_exit() */
static void set_exit( void ) {
defqualsp_t sq;
while( (sq = savedquals) != NULL ) {
savedquals = sq->next;
free( sq );
}
return;
}

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_SHOWCMD )
@@ -17,16 +20,16 @@
#include "cmddef.h"
#ifdef USE_READLINE
#ifndef _GNU_SOURCE
#define _XOPEN_SOURCE
#endif
#include <readline/readline.h>
#ifdef USE_LIBEDIT
#include <histedit.h>
#else
extern FILE *histfile;
#endif
#include "access.h"
#include "cache.h"
#include "direct.h"
#include "f11def.h"
#include "phyio.h"
#ifdef USE_VHD
#include "phyvhd.h"
@@ -34,40 +37,95 @@
#include "phyvirt.h"
#include "version.h"
extern defqualsp_t copy_defopt;
extern qual_t copyquals[];
extern defqualsp_t dir_defopt;
extern qual_t dirquals[];
extern defqualsp_t search_defopt;
extern qual_t searchquals[];
static unsigned show_defq( defqualsp_t defs,
qualp_t qualset, const char *name );
static unsigned show_stats( void );
void show_version( void );
static vmscond_t show_history( int qualc, char **qualv );
void show_version( int full );
static char *get_cwd( void );
/******************************************************************* doshow() */
static qual_t showkwds[] = { {"cwd", 0, 0, NV, "Working directory on local system"},
{"default", 1, 0, NV, "Default directory on VMS volume"},
{"devices", 2, 0, NV, "Devices"},
{"qualifier_style", 3, 0, NV, "Qualifier style (Unix, VMS)" },
{"statistics", 4, 0, NV, "Debugging statistics"},
{"time", 5, 0, NV, "Time"},
{"verify", 6, 0, NV, "Command file echo" },
{"version", 7, 0, NV, "Version"},
{"volumes", 8, 0, NV, "Mounted volume information" },
{NULL, 0, 0, NV, NULL }
#define hist_max OPT_SHARED_20
static uint32_t histmax;
static
qual_t histquals[] = { {"max-entries", hist_max, 0, DV(&histmax),
"commands history qual_maxent"},
{NULL, 0, 0, NV, NULL }
};
static
qual_t showkwds[] = { {"cwd", 0, ~0u, NV,
"commands show copy"},
{"default", 1, ~0u, NV,
"commands show default"},
{"devices", 2, ~0u, NV,
"commands show devices"},
{"qualifier_style", 3, ~0u, NV,
"commands show qstyle" },
{"statistics", 4, ~0u, NV,
"commands show statistics"},
{"terminal", 5, ~0u, NV,
"commands show terminal"},
{"time", 6, ~0u, NV,
"commands show time"},
{"verify", 7, ~0u, NV,
"commands show verify" },
{"version", 8, ~0u, NV,
"commands show version"},
{"volumes", 9, ~0u, NV,
"commands show volumes"},
{"directory_qualifiers",
10, ~0u, NV,
"commands show directory"},
{"copy_qualifiers",
11, ~0u, NV,
"commands show copy"},
{"message", 12, ~0u, NV,
"commands show message"},
{"search_qualifiers",
13, ~0u, NV,
"commands show search"},
{"history", 14, ~0u, NV,
"commands show history"},
{"help_file", 15, ~0u, NV,
"commands show helpfile"},
{NULL, 0, 0, NV, NULL }
};
param_t showpars[] = { {"item_name", REQ, KEYWD, PA(showkwds), "" },
{"selector", OPT|NOLIM, STRING, NOPA, NULL},
{NULL, 0, 0, NOPA, NULL }
};
/*********************************************************** doshow() */
DECL_CMD(show) {
int parnum;
options_t parnum;
vmscond_t sts;
UNUSED(argc);
UNUSED(qualc);
UNUSED(qualv);
parnum = checkquals( 0, showkwds, -1, argv+1 );
if( $FAILS(sts = checkquals( &parnum, 0, showkwds, -1, argv+1 )) ) {
return sts;
}
switch( parnum ) {
default:
return SS$_BADPARAM;
@@ -78,72 +136,151 @@ DECL_CMD(show) {
if( cwd == NULL ) {
return SS$_BADPARAM;
}
printf( " Current working directory is %s\n", cwd );
printmsg( HELP_SHOWCWD, MSG_TEXT, cwd );
free( cwd );
return SS$_NORMAL;
}
case 1: {
int sts;
unsigned short curlen;
char curdir[NAM$C_MAXRSS + 1];
char curdir[NAM$C_MAXRSS + 1] = { "" };
struct dsc_descriptor curdsc;
struct FAB fab;
struct NAM nam;
memset( &curdsc, 0, sizeof( curdsc ) );
curdsc.dsc_w_length = NAM$C_MAXRSS;
curdsc.dsc_a_pointer = curdir;
sts = sys_setddir( NULL, &curlen, &curdsc );
if ( sts & STS$M_SUCCESS ) {
curdir[curlen] = '\0';
puts( curdir );
} else {
printf("%%ODS2-E-GETDEF, Error %s getting default\n",getmsg(sts, MSG_TEXT));
if( $FAILS(sts = sys_setddir( NULL, &curlen, &curdsc )) ) {
return printmsg( sts, 0 );
}
fab = cc$rms_fab;
nam = cc$rms_nam;
nam.nam$b_ess = sizeof(curdir) -1;
nam.nam$l_esa = curdir;
fab.fab$l_nam = &nam;
fab.fab$l_fna = curdir;
fab.fab$b_fns = (uint8_t)curlen;
if( $FAILS(sts = sys_parse(&fab)) ) {
curdir[curlen] = '\0';
sts = printmsg( ODS2_INVDEF, 0, curdir );
} else {
curdir[nam.nam$b_dev+nam.nam$b_dir] = '\0';
printf( "%s\n", curdir );
}
fab.fab$b_fns =
nam.nam$b_ess =
fab.fab$b_dns = 0;
nam.nam$b_nop = NAM$M_SYNCHK;
nam.nam$l_rlf = NULL;
(void) sys_parse( &fab ); /* Release context */
return sts;
}
case 2:
phyio_show( SHOW_DEVICES );
virt_show( NULL );
virt_show();
return SS$_NORMAL;
case 3:
printf ( " Qualifier style: %s\n", vms_qual? "/VMS": "-unix" );
return SS$_NORMAL;
return printmsg( HELP_SHOWQSTYLE, MSG_TEXT, (qstyle_c == '/')? "/DCL": "-unix" );
case 4:
return show_stats();
case 5: {
unsigned sts;
char timstr[24];
int twid, th;
termchar( &twid, &th );
return printmsg( HELP_TERMSIZE, MSG_TEXT, twid, th );
}
case 6: {
char timstr[24] = { "" };
unsigned short timlen;
struct dsc_descriptor timdsc;
memset( &timdsc, 0, sizeof( timdsc ) );
timdsc.dsc_w_length = 20;
timdsc.dsc_a_pointer = timstr;
sts = sys$asctim( &timlen, &timdsc, NULL, 0 );
if ( sts & STS$M_SUCCESS ) {
timstr[timlen] = '\0';
printf(" %s\n",timstr);
} else {
printf("%%SHOW-W-TIMERR error %s\n",getmsg(sts, MSG_TEXT));
if( $FAILS(sts = sys_asctim( &timlen, &timdsc, NULL, 0 )) ) {
printmsg(ODS2_VMSTIME, 0 );
return printmsg( sts, MSG_CONTINUE, ODS2_VMSTIME );
}
timstr[timlen] = '\0';
printf(" %s\n",timstr);
return SS$_NORMAL;
}
return SS$_NORMAL;
case 6:
printf( "Command file verification is %s\n", (verify_cmd? "on": "off") );
return SS$_NORMAL;
case 7:
show_version();
return SS$_NORMAL;
return printmsg( verify_cmd? HELP_SHOWVERON: HELP_SHOWVEROFF, MSG_TEXT );
case 8:
show_version( 1 );
return SS$_NORMAL;
case 9:
show_volumes();
return SS$_NORMAL;
case 10:
return show_defq( dir_defopt, dirquals,
"directory" );
case 11:
return show_defq( copy_defopt, copyquals, "copy" );
case 12:
return show_message( argc, argv );
case 13:
return show_defq( search_defopt, searchquals, "search" );
case 14:
return show_history( qualc, qualv );
case 15:
return showhelpfile();
}
return SS$_NORMAL;
}
/************************************************************ show_defq() */
static unsigned show_defq( defqualsp_t defs,
qualp_t qualset, const char *name ) {
int i;
printmsg( HELP_SHOWDEFQ, MSG_TEXT, name );
if( defs == NULL || defs->qualc == 0 ) {
printmsg( HELP_SHOWNODEFQ, MSG_TEXT );
return SS$_NORMAL;
}
for( i = 0; i < defs->qualc; i++ ) {
qualp_t qp;
char *qk, *qv;
size_t len;
len = strlen( defs->qualv[i] ) +1;
if( (qk = malloc( len )) == NULL )
return SS$_INSFMEM;
memcpy( qk, defs->qualv[i], len );
if( (qv = strchr( qk, '=' )) == NULL )
qv = strchr( qk, ':');
if( qv != NULL )
*qv++ = '\0';
for( qp = qualset; qp->name != NULL; qp++ ) {
if( keycomp( qk, qp->name ) ) {
printf( " %c%s", qstyle_c, qp->name );
if( qp->qtype != NOVAL && qv != NULL && *qv )
printf( "=%s", qv );
putchar( '\n' );
break;
}
}
free( qk );
}
return SS$_NORMAL;
}
/****************************************************************** show_stats() */
/* dostats: print some simple statistics */
static unsigned show_stats( void ) {
printf("Statistics:-\n");
printmsg( HELP_SHOWSTATS, MSG_TEXT );
direct_show();
cache_show();
phyio_show(SHOW_STATS);
@@ -151,33 +288,489 @@ static unsigned show_stats( void ) {
return SS$_NORMAL;
}
/*********************************************************** show_history() */
static vmscond_t show_history( int qualc, char **qualv ) {
vmscond_t sts;
options_t options;
#ifdef USE_LIBEDIT
extern History *edithist;
HistEvent ev;
#else
extern uint32_t cmd_histsize;
uint32_t excess = 0;
char *buf = NULL;
size_t bufsize = 80;
#endif
int nent;
if( $FAILS(sts = checkquals( &options, 0, histquals, qualc, qualv )) ) {
return sts;
}
sts = SS$_NORMAL;
#ifdef USE_LIBEDIT
history( edithist, &ev, H_GETSIZE );
nent = ev.num;
if( nent < 0 ) {
fprintf( stderr, "GETSIZE error (%d) %s\n", ev.num, ev.str );
return sts;
}
if( !(options & hist_max) || histmax > (uint32_t)nent ) {
histmax = nent;
}
if( histmax == 0 )
return printmsg( HELP_SHOWNOCMDHIST, 0 );
if( history( edithist, &ev, H_FIRST ) < 0 ) { /* Most recent cmd */
fprintf( stderr, "FIRST error (%d) %s\n", ev.num, ev.str );
return sts;
}
for( nent = 1; (uint32_t)nent < histmax; nent++ ) { /* Find MAXth older cmd */
if( history( edithist, &ev, H_NEXT ) < 0 ) {
fprintf( stderr, "NEXT error (%d) %s\n", ev.num, ev.str );
return sts;
}
}
for( nent = 0; (uint32_t)nent < histmax; nent++ ) {
printmsg( HELP_SHOWCMDHISTLN, MSG_TEXT, ev.num, ev.str );
history( edithist, &ev, H_PREV );
}
return sts;
#else
if( histfile == NULL ) {
printmsg( HELP_SHOWNOCMDHIST, 0 );
return sts;
}
fseek( histfile, 0, SEEK_SET );
for( nent = 0; ; ) { /* Count history lines */
int c;
c = getc( histfile );
if( c == EOF ) break;
if( c == '\n' ) ++nent;
}
if( !(options & hist_max) || histmax > (uint32_t)nent ) {
histmax = nent;
}
if( histmax == 0 )
return printmsg( HELP_SHOWNOCMDHIST, 0 );
if( (uint32_t)nent > cmd_histsize ) /* Hide excess file lines if size reduced */
excess = nent - cmd_histsize;
if( histmax > (uint32_t)nent - excess )
histmax = (uint32_t)nent - excess; /* Reduce request to visible window */
histmax = nent - histmax;
fseek( histfile, 0, SEEK_SET );
for( nent = 0; (uint32_t)nent < histmax; ) { /* Skip old lines */
int c;
c = getc( histfile );
if( c == EOF ) break;
if( c == '\n' ) ++nent;
}
for( ; ; nent++ ) { /* Get full lines for display */
char *line;
if( (line = fgetline( histfile, FALSE, &buf, &bufsize )) == NULL )
break;
printmsg( HELP_SHOWCMDHISTLN, MSG_TEXT, nent + 1 - excess, line );
}
if( buf != NULL ) free( buf );
fseek( histfile, 0, SEEK_END );
return sts;
#endif
}
/*********************************************************** show_version() */
void show_version( int full ) {
char *detail, *version;
#ifdef DEBUG_BUILD
extern int vld_present;
#endif
void show_version( void ) {
printf(" %s %s", MNAME(MODULE_NAME), MODULE_IDENT );
printf( " built %s %s", __DATE__, __TIME__ );
#ifdef USE_READLINE
printf(" with readline version %s", rl_library_version );
#ifdef USE_LIBEDIT
printmsg( HELP_SHOWVERSRL, MSG_TEXT, MNAME(MODULE_NAME), MODULE_IDENT,
__DATE__, __TIME__, LIBEDIT_MAJOR, LIBEDIT_MINOR );
#else
printmsg( HELP_SHOWVERS, MSG_TEXT, MNAME(MODULE_NAME), MODULE_IDENT,
__DATE__, __TIME__ );
#endif
if( !full ) return;
/* Determine what platform and compiler were targeted for this image */
#ifdef _MSC_VER
#define strcat( _dst, _src ) strcat_s( (_dst), MAXSTRL, (_src) )
#endif
#define MAXSTRL 512
if( (detail = malloc( MAXSTRL * 2 )) == NULL ) {
return;
}
detail[0] = '\0';
version = detail + MAXSTRL;
version[0] = '\0';
/* N.B. The order of detection is intended to deal with ambiguities,
* and does not inidcate any particular preference or judgement.
*
* The detection scheme is an amalgam of tests from various sources.
* It has not been run in all these environments by the author,
* (or perhaps by anyone), so errors may exist and should be reported.
* Additions are also welcome.
*/
#if defined __ANDROID__
strcat( detail, "Android" );
#elif defined __linux__
strcat( detail, "Linux" );
#elif defined __APPLE__
#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
strcat( detail, "iOS Simulator" );
#elif TARGET_OS_IPHONE
strcat( detail, "iOS device" );
#elif TARGET_OS_MAC
strcat( detail, "OS X" );
#else
strcat( detail, "Unknown Apple platform" );
#endif
#elif defined __CYGWIN__ && !defined _WIN32
strcat( detail, "Cygwin" );
#elif defined _WIN64
strcat( detail, "Windows (64-bit)" );
#elif defined _WIN32
strcat( detail, "Windows (32-bit)" );
#elif defined VMS || defined __VMS
#if defined __ia64__ || defined __ia64 || defined _M_IA64
strcat( detail, "VMS (Itanium)" );
#elif defined __ALPHA || defined __ALPHA_AXP
strcat( detail, "VMS (Alpha)" );
#elif defined VAX || defined __VAX
strcat( detail, "VMS (VAX)" );
#else
strcat( detail, "VMS" );
#endif
#if defined __VMS_VER
snprintf( detail + strlen( detail ), MAXSTRL - strlen( detail ),
"%c%u.%u-%u%c",
(__VMS_VER % 100u),
(__VMS_VER / 10000000u),
(__VMS_VER / 100000u) % 100u,
(__VMS_VER / 10000u) % 10u,
(__VMS_VER / 100u) % 100u );
#endif
#elif defined __osf__
strcat( detail, "DEC OSF/1 (Tru64)" );
#elif defined ultrix || defined __ultrix || defined __ultrix__
strcat( detail, "Ultrix" );
#elif defined UNICOS
strcat( detail, "UNICOS" );
#elif defined _CRAY || defined __crayx1
strcat( detail, "UNICOSD/mp" );
#elif defined _AIX
#if defined __64BIT__
strcat( detail, "AIX (64-bit)" );
#else
strcat( detail, "AIX" );
#endif
#elif defined(__sun) && defined(__SVR4)
strcat( detail, "Solaris" );
#elif defined __hpux
strcat( detail, "HP-UX" );
#elif defined __NetBSD__
strcat( detail, "NetBSD" );
#elif defined __OpenBSD__
strcat( detail, "OpenBSD" );
/* Generic */
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
strcat( detail, "BSD Unix" );
#endif
#elif defined_POSIX_VERSION
strcat( detail, "POSIX" );
#if( _POSIX_VERSION >= 200809L )
strcat( detail, ".1-2008" );
#elif( _POSIX_VERSION >= 200112L )
strcat( detail, ".1-2001" );
#elif( _POSIX_VERSION >= 199506L )
strcat( detail, ".1-1995" );
#elif( _POSIX_VERSION >= 199309L )
strcat( detail, ".1-1993" );
#elif( _POSIX_VERSION >= 199009L )
strcat( detail,".1-1990" );
#elif( _POSIX_VERSION >= 198808L )
strcat( detail,".1-1988" );
#endif
#else
strcat( detail, "Unknown platform" );
#endif
/* Hardware */
#if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
defined(__64BIT__) || defined(_LP64) || defined(__LP64__)
strcat( detail, " PowerPC (64-bit)" );
#else
strcat( detail, " PowerPC (32-bit)" );
#endif
#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64)
#if !defined VMS && !defined __VMS
strcat( detail, " Itanium " );
#endif
#elif defined(__sparc)
strcat( detail, " SPARC" );
#elif defined(__x86_64__) || defined(_M_X64)
strcat( detail, " x86-64" );
#elif defined(__i386) || defined(_M_IX86)
strcat( detail, " x86-32" );
#elif defined __alpha || defined __alpha || defined _M_ALPHA
#if !defined VMS
strcat( detail, " Alpha" );
#endif
#elif defined VAX || defined __VAX
strcat( detail, " VAX" );
#elif defined __aarch64__
strcat( detail, " ARM64" );
#elif defined __thumb__
strcat( detail, " ARM (Thumb)" );
#elif defined __arm__
strcat( detail, " ARM " )
#elif defined __hppa__ || defined __HPPA__ || defined _hppa
strcat( detail, " HP/PA RISC" );
#elif defined __m68k__ || defined M68000 || defined __MC68K__
strcat( detail, " Motorola 68000" );
#elif defined __mips__ || defined __mips
strcat( detail, " MIPS" );
#elif defined __THW_RS6000__
strcat( detail, " RS6000" );
#elif defined __370__ || defined __THW_370__ || defined __s390__ || defined __s390x || \
defined __zarch__ || defined __SYSC_ZARCH__
strcat( detail, " System Z (370)" );
#endif
#if defined __STDC_VERSION__
#if( __STDC_VERSION__ >= 201112L )
strcat( detail, " C11" );
#elif( __STDC_VERSION__ >= 199901L )
strcat( detail, " C99" );
#elif( __STDC_VERSION__ >= 199409L )
strcat( detail, " C94" );
#else
strcat( detail, " C89/90" );
#endif
#elif defined __STDC__
strcat( detail, " C89/90" );
#else
strcat( detail, " C" );
#endif
#if defined __LSB_VERSION__
snprintf( detail + strlen( detail ), MAXSTRL - strlen( detail ),
" LSB V%u.%u",
(__LSB_VERSION__ / 10), (__LSB_VERSION__%10) );
#endif
#if ODS2_BIG_ENDIAN
strcat( detail, " Big-Endian" );
#endif
printmsg( HELP_SHOWVERPLATFM, MSG_TEXT, detail );
/* Compiler */
detail[0] = '\0';
#if defined __clang__
strcat( detail, "Clang/LLVM" );
snprintf( version, MAXSTRL, "%d.%d.%d",
__clang_major__, __clang_minor__, __clang_patchlevel__ );
#elif defined(__ICC) || defined(__INTEL_COMPILER)
strcat( detail, "ICC" );
#if defined __VERSION__
strcat( version, __VERSION__ );
#endif
#elif defined(__HP_cc) || defined(__HP_aCC)
strcat( detail, "HP C" );
#if defined __HP_aCC && __HP_aCC > 1
snprintf( version, MAXSTRL, "%02u.%02u.%02u",
(__HP_aCC / 10000u ),
(__HP_aCC / 100u ) % 100u,
(__HP_aCC % 100u ) % 100u );
#elif defined __HP_cc && __HP_cc > 1
snprintf( version, MAXSTRL, "%02u.%02u.%02u",
(__HP_cc / 10000u ),
(__HP_cc / 100u ) % 100u,
(__HP_cc % 100u ) % 100u );
#endif
#elif defined(__IBMC__) || defined(__IBMCPP__)
strcat( detail, "IBM XL C" );
#if defined __COMPILER_VER__
strcat( version, __COMPILER_VER__ );
#elif defined __xlxc__
strcat( version, __xlc__ );
#else
strcat( version, __IBMC__ );
#endif
#elif defined __LCC__
strcat( detail, "LCC" );
#elif defined ___llvm
strcat( detail, "LLVM" );
#elif defined __MINGW64__
strcat( detail, "MinGW-w64" );
#if defined __MINGW64_VERSION_MAJOR
snprintf( version, MAXSTRL, "%u.%u",
__MINGW64_VERSION_MAJOR, __MINGW64_VERSION_MINOR );
#endif
#elif defined __MINGW32__
strcat( detail, "MinGW" );
#if defined __MINGW32_MAJOR_VERSIONR
snprintf( version, MAXSTRL, "%u.%u",
__MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION );
#endif
#elif defined(__PGI)
strcat( detail, "PGCC" );
snprintf( version, MAXSTRL, "%u.%u.%u",
__PGIC__, __PGIC_MINOR, __PGIC_PATCHLEVEL__ );
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
strcat( detail, "Solaris Studio" );
#if defined __SUNPRO_C
snprintf( version, MAXSTRL, "%u.%u.%u",
(__SUNPRO_C / 0x100 ),
(__SUNPRO_C / 0x10 ) % 0x100,
(__SUNPRO_C % 0x10 ) );
#elif defined __SUNPRO_CC
snprintf( version, MAXSTRL, "%u.%u.%u",
(__SUNPRO_CC / 0x100 ),
(__SUNPRO_CC / 0x10 ) % 0x100,
(__SUNPRO_CC % 0x10 ) );
#endif
#elif defined __sgi || defined sgi
strcat( detail, "MIPSpro" );
#if defined _SGI_COMPILER_VERSION
snprintf( version, MAXSTRL, "%u.%u.%u",
(_SGI_COMPILER_VERSION / 100u),
(_SGI_COMPILER_VERSION / 10u) % 10u,
(_SGI_COMPILER_VERSION % 10u) );
#elif defined _COMPILER_VERSION
snprintf( version, MAXSTRL, "%u.%u.%u",
(_COMPILER_VERSION / 100u),
(_COMPILER_VERSION / 10u) % 10u,
(_COMPILER_VERSION % 10u) );
#endif
#elif defined _MSC_FULL_VER
strcat( detail, "Visual C++" );
snprintf( version, MAXSTRL, "%d.%02d.%05d.%02d",
(_MSC_FULL_VER / 10000000u),
(_MSC_FULL_VER / 100000u ) % 100u,
(_MSC_FULL_VER % 100000u ),
_MSC_BUILD);
#ifdef _MSC_VER
{ /* https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros */
struct {
char *ide; unsigned ver; } ides[] = {
{"Visual Studio 6.0", 1200},
{"Visual Studio .NET 2002 (7.0)", 1300},
{"Visual Studio .NET 2003 (7.1)", 1310},
{"Visual Studio 2005 (8.0)", 1400},
{"Visual Studio 2008 (9.0)", 1500},
{"Visual Studio 2010 (10.0)", 1600},
{"Visual Studio 2012 (11.0)", 1700},
{"Visual Studio 2013 (12.0)", 1800},
{"Visual Studio 2015 (14.0)", 1900},
{"Visual Studio 2017 RTW (15.0)", 1910},
{"Visual Studio 2017 version 15.3", 1911},
{"Visual Studio 2017 version 15.5", 1912},
{"Visual Studio 2017 version 15.6", 1913},
{"Visual Studio 2017 version 15.7", 1914},
{"Visual Studio 2017 version 15.8", 1915},
{"Visual Studio 2017 version 15.9", 1916},
{"Visual Studio 2019 RTW (16.0)", 1920},
{"Visual Studio 2019 version 16.1", 1921},
{"Visual Studio 2019 version 16.2", 1922},
{"Visual Studio 2019 version 16.3", 1923},
{"Visual Studio 2019 version 16.4", 1924},
{"Visual Studio 2019 version 16.5", 1925},
{"Visual Studio 2019 version 16.6", 1926},
{"Visual Studio 2019 version 16.7", 1927},
{"Visual Studio 2019 version 16.8, 16.9", 1928},
{"Visual Studio 2019 version 16.10, 16.11", 1929},
{"Visual Studio 2022 RTW (17.0)", 1930},
{"Visual Studio 2022 version 17.1", 1931},
{"Visual Studio 2022 version 17.2", 1932},
{"Visual Studio 2022 version 17.3", 1933},
{"Visual Studio 2022+", 100000}, }, *ip;
for( ip = ides; ip->ver < _MSC_VER; ip++ )
;
strcat( version, ", " );
strcat( version, ip->ide );
}
#endif
#elif defined _MSC_VER
strcat( detail, "Visual Studio" );
snprintf( version, MAXSTRL, "%d", _MSC_VER );
#elif defined __CC_ARM
strcat( version, "ARM Compiler" );
snprintf( version, MAXSTRL, "%u.%u.%u build %u",
(__ARMCC_VERSION / 100000u ),
(__ARMCC_VERSION / 10000u ) % 10u,
(__ARMCC_VERSION / 1000u ) % 10u,
(__ARMCC_VERSION % 1000u ) );
#elif defined __GNUC__
strcat( detail, "gcc" );
#if defined __VERSION__
strcat( version, __VERSION__ );
#else
snprintf( version, MAXSTRL, "%d.%d", __GNUC__, __GNUC_MINOR__ );
#endif
#elif defined __DECC__ || defined _DECC
strcat( detail, "DEC C" );
{
char ct;
switch( (__DECC_VER / 10000u) % 10u ) {
case 6:
ct = 'T'; break;
case 8:
ct = 'S'; break;
case 9:
ct = 'V'; break;
default:
ct = 'X'; break;
}
snprintf( version, MAXSTRL, "%c%u.%u-%03u", ct,
(__DECC_VER / 10000000u),
(__DECC_VER / 100000u) % 100u,
(__DECC_VER % 10000u) );
}
#elif defined VAXC || defined VAX11C || defined __VAXC || defined __VAX11C
strcat( detail, "VAX C" );
#endif
if( !version[0] )
strcat( version, "unknown" );
#undef strcat
#undef MAXSTRL
printmsg( HELP_SHOWVERCOMPLR, MSG_TEXT, detail, version );
free( detail ); /* includes version */
detail = version = NULL;
#ifdef DEBUG_BUILD
if( vld_present )
printmsg( HELP_SHOWVLD, MSG_TEXT );
#endif
#ifdef USE_WNASPI32
# ifdef USE_READLINE
printf( " and" );
# else
printf( " with" );
# endif
printf( " direct SCSI access support");
printmsg( HELP_SHOWVERSCSI, MSG_TEXT );
#endif
printf( "\n " );
putchar( ' ');
phyio_show( SHOW_FILE64 );
#ifdef USE_VHD
putchar( ' ');
(void) phyvhd_available( TRUE );
#else
printf( " VHD format image files are not supported\n" );
printmsg( HELP_SHOWVERNOVHD, MSG_TEXT );
#endif
putchar( '\n' );
return;
}
@@ -197,7 +790,7 @@ static char *get_cwd( void ) {
if( getcwd( buf, size ) != NULL )
break;
if( errno != ERANGE ) {
perror( "getcwd" );
printmsg( ODS2_OSERROR, 0, strerror( errno ) );
return NULL;
}
size *= 2;

View File

@@ -1,10 +1,13 @@
/* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
#if !defined( DEBUG ) && defined( DEBUG_SPAWNCMD )
@@ -31,30 +34,48 @@
/******************************************************************* dospawn() */
DECL_CMD(spawn) {
#ifdef VMS
unsigned sts;
char spawnhelp[] = { "commands spawnvms" };
DECL_CMD(spawn) {
vmscond_t sts;
UNUSED( argc );
UNUSED( argv );
UNUSED( qualc );
UNUSED( qualv );
sts = lib$spawn( 0,0,0,0,0,0,0,0,0,0,0,0,0 );
/* command, input, output, flags, process_name, pid, exit_sts, efn,
* astaddr, astprm, prompt, cli, table
*/
if( $FAILS(sts = lib$spawn( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 )) ) {
printmsg( ODS2_NOSHELL, 0, "command interpreter" );
sts = printmsg( sts, MSG_CONTINUE, ODS2_NOSHELL );
}
return sts;
#else
# ifdef _WIN32
}
#elif defined( _WIN32 )
char spawnhelp[] = { "commands spawnnt" };
DECL_CMD(spawn) {
UNUSED( argc );
UNUSED( argv );
UNUSED( qualc );
UNUSED( qualv );
if( system( "cmd" ) == -1 ) {
perror( "cmd" );
return SS$_NOSUCHFILE;
int err;
err = errno;
printmsg( ODS2_NOSHELL, 0, "cmd" );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, strerror( err ) );
}
return SS$_NORMAL;
# else
}
#else
char spawnhelp[] = { "commands spawnunix" };
DECL_CMD(spawn) {
char *shell, *p;
pid_t pid;
@@ -71,19 +92,24 @@ DECL_CMD(spawn) {
p++;
if( (pid = fork()) == 0 ) {
int err;
execlp( shell, p, (char *)NULL );
perror( "%s" );
err = errno;
printmsg( ODS2_NOSHELL, 0, shell );
printmsg( ODS2_OSERROR, MSG_CONTINUE, strerror( err ) );
exit(EXIT_FAILURE);
}
if( pid == -1 ) {
perror( shell );
return SS$_NOSUCHFILE;
int err = errno;
printmsg( ODS2_NOSHELL, 0, shell );
return printmsg( ODS2_OSERROR, MSG_CONTINUE, strerror( err ) );
}
waitpid( pid, NULL, 0 );
return SS$_NORMAL;
# endif
}
#endif
}

File diff suppressed because it is too large Load Diff

1806
extracters/ods2/ssdef.msg Normal file

File diff suppressed because it is too large Load Diff

18
extracters/ods2/strictmake Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
# This is how I validate that everything compiles with GCC warnings enabled.
# ./strictmake -g -DDEBUG (or any other CCFLAGS)
# If the first argument does not begin with '-', it's the target of the build
#
# Exception reasons:
# $ in identifier - VMS compatible code
# object to function pointer - dlsym requires this to work; it's in the
# OpenGroup standard's notes on this (standard) function.
# VHD uses long long - but is optional
if [[ "$1" =~ ^- ]]; then
TGT=
else
TGT="$1"
shift
fi
LANG=C 2>&1 make -f makefile.unix $TGT "CCFLAGS=-O4 $* -DUSE_LIBEDIT -Wall -pedantic -Wextra" | grep -vP "(warning: '\\\$' in identifier or number)|\`arg[cv]|(In file included from)|(phyvhd.c:\\d+:\\d+: warning: ISO C forbids conversion of object pointer to function pointer)|(use of C99 long long integer constant)"

View File

@@ -12,10 +12,13 @@
* 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 contributions of the original author and
* subsequent contributors. This is free software; no
* warranty is offered, and while we believe it to be useful,
* you use it at your own risk.
*/
/* Message code translations for non-VMS systems */
/* VMS-ish message code translations */
#if !defined( DEBUG ) && defined( DEBUG_SYSMSG )
#define DEBUG DEBUG_SYSMSG
@@ -25,147 +28,245 @@
#endif
#endif
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
/* Should replace with lib$sys_getmsg under VMS
#ifndef VMS
*/
/* This is similar to, but not quite $PUTMSG. We don't have VMS signals...
*/
#define SYSMSG_INTERNAL
#include "ods2.h"
#include "ssdef.h"
#include "rms.h"
#include "compat.h"
#include "stsdef.h"
#include "sysmsg.h"
#define MSG(code,text) { $VMS_STATUS_COND_ID(code), #code, text },
static
const struct VMSFAC {
unsigned int code;
const char *const text;
} fac2text[] = {
{ SYSTEM$_FACILITY, "SYSTEM" },
{ RMS$_FACILITY, "RMS" },
{ COPY$_FACILITY, "COPY" },
{ DELETE$_FACILITY, "DELETE" },
{ 0, NULL },
{ 0, "NONAME" }
};
static const char sev2text[(STS$M_SEVERITY>>STS$V_SEVERITY)+1] =
{ 'W', 'S', 'E', 'I', 'F', '?', '?', '?', };
/* Unknown facility or message code */
#ifndef SS$_NOMSG
#define SS$_NOMSG 0xFFFFFFFF
#ifdef _WIN32
#undef sscanf
#define sscanf sscanf_s
#undef fscanf
#define fscanf fscanf_s
#endif
static const char nofmt[] = "Message number %08X";
static char notext[sizeof(nofmt)+8];
/* Facility name to text translations
*/
static
const struct VMSMSG {
unsigned int code;
const char *const txtcode;
char *text;
} vms2text[] = {
MSG(DELETE$_DELVER, "explicit version number or wild card required")
struct VMSFAC fac2textdef[] = {
#define GENERATE_FACTAB
#include "default.md"
}, /* Entry for unknown facility */
nofac = { "NONAME", 0 };
MSG(COPY$_OPENIN, " error opening %s as input")
/* Number of entries to search */
static size_t faclen = (sizeof(fac2textdef)/sizeof(fac2textdef[0]));
MSG(RMS$_BUG, "fatal RMS condition detected, process deleted")
MSG(RMS$_DIR, "error in directory name")
MSG(RMS$_DNF, "directory not found")
MSG(RMS$_EOF, "end of file detected")
MSG(RMS$_ESS, "expanded string area too small")
MSG(RMS$_FNF, "file not found")
MSG(RMS$_FNM, "error in file name")
MSG(RMS$_IFI, "invalid internal file identifier (IFI) value")
MSG(RMS$_NAM, "invalid NAM block or NAM block not accessible")
MSG(RMS$_NMF, "no more files found")
MSG(RMS$_RSS, "invalid resultant string size")
MSG(RMS$_RSZ, "invalid record size")
MSG(RMS$_RTB, "%u byte record too large for user's buffer") /* !UL byte */
MSG(RMS$_WCC, "invalid wild card context (WCC) value")
MSG(RMS$_WLD, "invalid wildcard operation")
MSG(SS$_ABORT, "abort")
MSG(SS$_BADFILENAME, "bad file name syntax")
MSG(SS$_BADIRECTORY, "bad directory file format")
MSG(SS$_BADPARAM, "bad parameter value")
MSG(SS$_BUGCHECK, "internal consistency failure")
MSG(SS$_DATACHECK, "write check error")
MSG(SS$_DEVALLOC, "device already allocated to another user")
MSG(SS$_DEVASSIGN, "device has channels assigned" )
MSG(SS$_DEVICEFULL, "device full - allocation failure")
MSG(SS$_DEVMOUNT, "device is already mounted")
MSG(SS$_DEVNOTALLOC, "device not allocated")
MSG(SS$_DEVNOTDISM, "device not dismounted")
MSG(SS$_DEVNOTMOUNT, "device is not mounted")
MSG(SS$_DUPFILENAME, "duplicate file name")
MSG(SS$_DUPLICATE, "duplicate name")
MSG(SS$_ENDOFFILE, "end of file")
MSG(SS$_ILLBLKNUM, "illegal logical block number")
MSG(SS$_FILELOCKED, "file is deaccess locked")
MSG(SS$_FILESEQCHK, "file identification sequence number check")
MSG(SS$_ILLEFC, "illegal event flag cluster")
MSG(SS$_INSFMEM, "insufficient dynamic memory")
MSG(SS$_ITEMNOTFOUND, "requested item cannot be returned")
MSG(SS$_NOMOREDEV, "no more devices")
MSG(SS$_IVCHAN, "invalid I/O channel")
MSG(SS$_DEVOFFLINE, "device is not in configuration or not available")
MSG(SS$_IVDEVNAM, "invalid device name")
MSG(SS$_NOIOCHAN, "no I/O channel available")
MSG(SS$_NOMOREFILES, "no more files")
MSG(SS$_NORMAL, "normal successful completion")
MSG(SS$_NOSUCHDEV, "no such device available")
MSG(SS$_NOSUCHFILE, "no such file")
MSG(SS$_NOSUCHVOL, "No such volume")
MSG(SS$_NOTINSTALL, "writable shareable images must be installed")
MSG(SS$_PARITY, "parity error")
MSG(SS$_UNSUPVOLSET, "Volume set not supported")
MSG(SS$_WASCLR, "normal successful completion")
MSG(SS$_WASSET, "Event flag was set")
MSG(SS$_WRITLCK, "write lock error")
MSG(SS$_OFFSET_TOO_BIG, "Volume is too large for local file system: needs 64-bit I/O" )
{0, NULL, NULL},
{ SS$_NOMSG, "SS$_NOMSG", notext }
};
/* Pointer to active table.
* Special labels for facility code 0.
*/
static
struct VMSFAC *fac2text = fac2textdef,
sysfac = { "SYSTEM", 0 },
shrfac = { "SHR" , 0 };
/* Pointer to memory containing dynamically-loaded message file data.
*/
static char *msgfile;
static char *msgfilename;
static const char sev2text[(STS$M_SEVERITY >> STS$V_SEVERITY)+1] =
{ 'W', 'S', 'E', 'I', 'F', '?', '?', '?', };
/* 0 1 2 3 4 5 6 7 */
/* Unknown facility or message code
*/
static char notext[256];
/* Message data
*/
static
struct VMSMSG vms2textdef[] = {
#define GENERATE_MSGTAB
#include "default.md"
}, /* Special item for Unknown message response */
nomsg = { "NOMSG", notext, ODS2_NOMSG, 1 };
/* Number of messages */
static size_t msglen = sizeof(vms2textdef)/sizeof(vms2textdef[0]);
/* Pointer to active message table */
struct VMSMSG *vms2text = vms2textdef;
/* Default message display options
*/
static options_t message_format = MSG_FULL;
/* Expandable buffer for formatted messages */
static char *buf = NULL;
static size_t bufsize = 0;
/******************************************************************* xpand() */
/* Last few formatted messages for callers that hold
* pointers across calls.
*/
static char *retbuf[10];
static size_t retidx = 0, lastidx = 0;
static int xpand( size_t used, size_t add ) {
char *nbuf;
size_t need;
static int argcount( vmscond_t vmscond );
need = used + add + 1; /* Always allow for \0 */
if( need < bufsize ) {
return 1;
static int xpand( size_t used, size_t add );
static const char *returnbuf( void );
static int decstr( FILE *mf, size_t *len, char **pp, char **sp );
/******************************************************************* printmsg() */
vmscond_t printmsg( vmscond_t vmscond, unsigned int flags, ... ) {
va_list ap;
vmscond_t status;
va_start( ap, flags );
status = vprintmsg( vmscond, flags, ap );
va_end( ap );
return status;
}
/******************************************************************* vprintmsg() */
vmscond_t vprintmsg( vmscond_t vmscond, unsigned int flags, va_list ap ) {
const char *msg, *pfxe;
FILE *of = stdout;
int nargs;
vmscond_t primary;
if( flags & MSG_TOFILE )
of = va_arg( ap, FILE * );
if( flags & MSG_CONTINUE ) {
primary = va_arg( ap, vmscond_t );
vmscond |= primary & STS$M_INHIB_MSG;
} else
primary = vmscond;
if( (vmscond & STS$M_INHIB_MSG) && !(flags & MSG_ALWAYS) )
return primary;
if( (flags & (MSG_WITHARGS | MSG_NOARGS)) == 0 ) {
nargs = argcount( vmscond );
if( nargs > 0 )
flags |= MSG_WITHARGS;
}
nbuf = realloc( buf, need + 16 + 1); /* 16 minimizes reallocs */
if( nbuf == NULL ) {
return 0;
if( !(flags & MSG_FULL) ) {
flags = (flags & ~MSG_FULL) | message_format;
}
buf = nbuf;
bufsize = need + 16 + 1;
return 1;
if( (flags & (MSG_WITHARGS | MSG_TEXT)) != (MSG_WITHARGS | MSG_TEXT) ) {
fprintf( of, "%s", getmsg_string( vmscond, flags ) );
if( !(flags & MSG_NOCRLF) )
fputc( '\n', of );
return primary | STS$M_INHIB_MSG;
}
msg = getmsg_string( vmscond, flags );
if( flags & (MSG_FACILITY | MSG_SEVERITY | MSG_NAME) ) {
pfxe = strchr( msg, ',' );
if( pfxe == NULL ) {
abort();
}
pfxe += 2;
fprintf( of, "%.*s", (int)(pfxe - msg), msg );
} else {
pfxe = msg;
}
vfprintf( of, pfxe, ap );
if( !(flags & MSG_NOCRLF) )
fputc( '\n', of );
return primary | STS$M_INHIB_MSG;
}
/******************************************************************* getmsg() */
const char *getmsg( unsigned int vmscode, unsigned int flags, ... ) {
const struct VMSMSG *mp = NULL;
const char *getmsg( vmscond_t vmscond, unsigned int flags, ... ) {
char *buf, *msg;
va_list ap;
size_t prelen, len, fmtlen;
if( !(flags & MSG_WITHARGS) ) {
return getmsg_string( vmscond, flags );
}
buf = retbuf[ lastidx ];
prelen = 0;
errno = 0;
(void) getmsg_string( vmscond, flags );
if( errno )
return strerror( errno );
fmtlen = strlen( buf );
if( (msg = strchr( buf, ',')) != NULL ) {
prelen = 2 + (size_t)( msg -buf );
}
va_start( ap, flags );
len = vsnprintf( buf+fmtlen+1, 1, buf, ap );
va_end( ap );
if( (buf = realloc( buf, fmtlen + 1 + len + 1 )) == NULL )
return strerror( errno );
retbuf[lastidx] = buf;
va_start( ap, flags );
(void) vsnprintf( buf+fmtlen + 1, len+1, buf + prelen, ap );
va_end( ap );
memmove( buf, buf+fmtlen+1, len + 1 );
return buf;
}
/******************************************************************* argcount() */
static int argcount( vmscond_t vmscond ) {
struct VMSMSG *mp, key;
memset( &key, 0, sizeof( key ) );
key.code = vmscond;
mp = bsearch( &key, vms2text, msglen,
sizeof(vms2text[0]), msgcmp );
if( mp == NULL )
return -1;
return mp->nargs;
}
/******************************************************************* getmsg_string() */
const char *getmsg_string( vmscond_t vmscond, unsigned int flags ) {
const struct VMSFAC *fp = NULL;
const struct VMSMSG *mp = NULL;
struct VMSFAC fackey;
struct VMSMSG msgkey;
memset( &fackey, 0, sizeof( fackey ) );
memset( &msgkey, 0, sizeof( msgkey ) );
if( !(flags & MSG_FULL) )
flags = (flags & ~MSG_FULL) | MSG_FULL;
flags = (flags & ~MSG_FULL) | message_format;
while( 1 ) {
size_t i = 0, len;
@@ -174,14 +275,30 @@ const char *getmsg( unsigned int vmscode, unsigned int flags, ... ) {
if( flags & (MSG_FACILITY|MSG_SEVERITY|MSG_NAME) ) {
if( !xpand( i, 1 ) )
return strerror( errno );
buf[i++] = '%';
buf[i++] = (flags & MSG_CONTINUE)? '-': '%';
if( fp == NULL ) {
for( fp = fac2text; fp->text != NULL; fp++ ) {
if( fp->code == $VMS_STATUS_FAC_NO(vmscode) )
break;
uint32_t facno;
facno = $VMS_STATUS_FAC_NO(vmscond);
if( facno == 0 ) {
fp = &sysfac;
if( !$VMS_STATUS_FAC_SP(vmscond) ) {
uint32_t msgno;
msgno = $VMS_STATUS_CODE(vmscond);
if( msgno >= 4096 && msgno < 8192 )
fp = &shrfac;
}
} else {
fackey.code = facno;
fp = bsearch( &fackey, fac2text, faclen,
sizeof(fac2text[0]), faccmp );
if( fp == NULL ) fp = &nofac;
}
}
if( fp->text == NULL )
break;
if( flags & MSG_FACILITY ) {
@@ -197,28 +314,22 @@ const char *getmsg( unsigned int vmscode, unsigned int flags, ... ) {
if( flags & MSG_SEVERITY ) {
if( !xpand( i, 2 ) )
return strerror( errno );
buf[i++] = sev2text[$VMS_STATUS_SEVERITY(vmscode)];
buf[i++] = sev2text[$VMS_STATUS_SEVERITY(vmscond)];
if( flags & MSG_NAME )
buf[i++] = '-';
}
if( flags & MSG_NAME ) {
char *p;
if( mp == NULL ) {
for( mp = vms2text; mp->text != NULL; mp++ ) {
if( $VMS_STATUS_COND_ID(vmscode) == mp-> code )
break;
}
msgkey.code = vmscond;
mp = bsearch( &msgkey, vms2text, msglen,
sizeof(vms2text[0]), msgcmp );
}
if( mp->text == NULL )
if( mp == NULL )
break;
p = strchr( mp->txtcode, '_' );
if( p == NULL )
abort();
len = strlen( ++p );
len = strlen( mp->ident );
if( !xpand( i, len ) )
return strerror( errno );
memcpy( buf+i, p, len );
memcpy( buf+i, mp->ident, len );
i += len;
}
if( flags & MSG_TEXT ) {
@@ -229,50 +340,398 @@ const char *getmsg( unsigned int vmscode, unsigned int flags, ... ) {
}
}
if( flags & MSG_TEXT ) {
va_list ap;
if( mp == NULL ) {
for( mp = vms2text; mp->text; mp++ ) {
if( $VMS_STATUS_COND_ID(vmscode) == mp-> code )
break;
}
if( mp->text == NULL )
msgkey.code = vmscond;
mp = bsearch( &msgkey, vms2text, msglen,
sizeof(vms2text[0]), msgcmp );
if( mp == NULL )
break;
}
if( flags & MSG_WITHARGS ) {
va_start( ap, flags );
len = vsnprintf( buf+i, 1, mp->text, ap );
va_end( ap );
} else
len = strlen( mp->text );
len = strlen( mp->text );
if( !xpand( i, len ) )
return strerror( errno );
if( flags & MSG_WITHARGS ) {
va_start( ap, flags );
(void) vsnprintf( buf+i, len+1, mp->text, ap );
va_end( ap );
} else
memcpy( buf+i, mp->text, len );
memcpy( buf+i, mp->text, len );
if( !(flags & (MSG_FACILITY|MSG_SEVERITY|MSG_NAME|MSG_NOUC)) )
buf[i] = toupper( buf[i] );
i += len;
}
buf[i] = '\0';
return buf;
return returnbuf();
} while( 0 );
if( fp == NULL || fp->text == NULL )
fp = fac2text + (sizeof(fac2text)/sizeof(fac2text[0])) -1;
fp = &nofac;
mp = vms2text + (sizeof(vms2text)/sizeof(vms2text[0])) -1;
(void) snprintf( notext, sizeof(notext), nofmt, vmscode );
if( mp == NULL || mp->text == NULL ) {
msgkey.code = vmscond;
mp = bsearch( &msgkey, vms2text, msglen,
sizeof(vms2text[0]), msgcmp );
if( mp == NULL || mp->text == NULL ) {
msgkey.code = ODS2_NOMSG;
mp = bsearch( &msgkey, vms2text, msglen,
sizeof(vms2text[0]), msgcmp );
if( mp == NULL || mp->text == NULL ) {
(void) snprintf( notext, sizeof(notext),
"message number %08X", vmscond );
} else {
(void) snprintf( notext, sizeof(notext),
mp->text, vmscond );
notext[sizeof(notext) -1] = '\0';
}
mp = &nomsg;
}
}
}
}
/******************************************************************* xpand() */
static int xpand( size_t used, size_t add ) {
char *nbuf;
size_t need;
need = used + add + 1; /* Always allow for \0 */
if( need < bufsize ) {
return 1;
}
nbuf = realloc( buf, need + 32 + 1); /* 32 minimizes reallocs */
if( nbuf == NULL ) {
return 0;
}
buf = nbuf;
bufsize = need + 32 + 1;
return 1;
}
/******************************************************************* returnbuf() */
static const char *returnbuf( void ) {
const char *rbuf;
lastidx = retidx;
free( retbuf[retidx] );
retbuf[retidx++] = buf;
retidx %= sizeof( retbuf ) / sizeof( retbuf[0] );
rbuf = buf;
buf = NULL;
bufsize = 0;
return rbuf;
}
/***************************************************************** set_message_format */
vmscond_t set_message_format( options_t new ) {
message_format = new & (MSG_FACILITY|MSG_SEVERITY|MSG_NAME|MSG_TEXT);
return SS$_NORMAL;
}
/***************************************************************** set_message_format */
options_t get_message_format( void ) {
return message_format;
}
/******************************************************************* set_message_file */
vmscond_t set_message_file( const char *filename ) {
vmscond_t sts;
char *newmsg = NULL;
char *newfilename = NULL;
FILE *mf = NULL;
if( filename == NULL ) { /* Reset to built-in default tables */
fac2text = fac2textdef;
vms2text = vms2textdef;
faclen = (sizeof(fac2textdef)/sizeof(fac2textdef[0]));
msglen = sizeof(vms2textdef)/sizeof(vms2textdef[0]);
if( msgfile != NULL ) {
free( msgfile );
msgfile = NULL;
}
if( msgfilename ) {
free( msgfilename );
msgfilename = NULL;
}
return SS$_NORMAL;
}
/* Load a file (built by genmsg.c) */
sts = ODS2_OPENIN;
errno = 0;
do {
size_t size, i;
uint32_t facn, msgn;
uint32_t code, nargs;
int c, n;
char *np, *sp;
off_t pos;
if( (newfilename = get_realpath( filename )) == NULL ) {
size = strlen( filename ) +1;
if( (newfilename = malloc( size)) == NULL ) {
sts = SS$_INSFMEM;
break;
}
memcpy( newfilename, filename, size );
}
if( (mf = openf( newfilename, "rb" )) == NULL ) {
break;
}
sts = ODS2_BADMSGFILE;
/* File header record */
n = 0;
if( (c = fscanf( mf, MSG_HEADER_DEC, &facn, &msgn, &n )) == EOF ||
c < 2 ||
n != MSG_HEADER_DECN )
break;
size = ( (facn * sizeof( struct VMSFAC ) ) +
(msgn * sizeof( struct VMSMSG ) ) );
if( (c = getc( mf )) != '\0' )
break;
pos = ftell( mf );
/* Compute string pool size */
/* Facility records */
for( i = 0; i < facn; i++ ) {
n = 0;
if( (c = fscanf( mf, MSG_FAC_DEC, &code, &n )) == EOF ||
c < 1 ||
n != MSG_FAC_DECN )
break;
if( (c = decstr( mf, &size, NULL, NULL )) == EOF )
break;
}
if( c == EOF || i < facn )
break;
/* Message description records */
for( i = 0; i < msgn; i++ ) {
n = 0;
if( (c = fscanf( mf, MSG_MSG_DEC, &code, &nargs, &n )) == EOF ||
c < 2 ||
n != MSG_MSG_DECN )
break;
if( (c = decstr( mf, &size, NULL, NULL )) == EOF )
break;
if( (c = decstr( mf, &size, NULL, NULL )) == EOF )
break;
}
if( c == EOF || i < msgn )
break;
/* Allocate enough memory for the tables and the string pool */
if( fseek( mf, pos, SEEK_SET ) == -1 )
break;
if( (newmsg = malloc( size )) == NULL ) {
sts = SS$_INSFMEM;
break;
}
np = newmsg;
sp = np + ((facn * sizeof( struct VMSFAC )) +
(msgn * sizeof( struct VMSMSG )));
/* Create each structure along with any strings. */
/* Facility records */
for( i = 0; i < facn; i++ ) {
struct VMSFAC *fp = (struct VMSFAC *)np;
np += sizeof( struct VMSFAC );
n = 0;
if( (c = fscanf( mf, MSG_FAC_DEC, &code, &n )) == EOF ||
c < 1 ||
n != MSG_FAC_DECN )
break;
fp->code = code;
if( (c = decstr( mf, &size, &sp, &fp->text )) == EOF )
break;
}
if( c == EOF || i < facn )
break;
/* Message description records */
for( i = 0; i < msgn; i++ ) {
struct VMSMSG *mp = (struct VMSMSG *)np;
np += sizeof( struct VMSMSG );
n = 0;
if( (c = fscanf( mf, MSG_MSG_DEC, &code, &nargs, &n )) == EOF ||
c < 2 ||
n != MSG_MSG_DECN )
break;
mp->code = code;
mp->nargs = nargs;
if( (c = decstr( mf, &size, &sp, &mp->ident )) == EOF )
break;
if( (c = decstr( mf, &size, &sp, &mp->text )) == EOF )
break;
}
if( c == EOF || i < msgn )
break;
/* EOF */
n = 0;
if( (c = fscanf( mf, MSG_EOF_DEC, &n )) == EOF ||
c < 0 ||
n != MSG_EOF_DECN || (c = getc( mf )) != 0 )
break;
/* Success. Install new file. */
free( msgfile );
msgfile = newmsg;
free( msgfilename );
msgfilename = newfilename;
newfilename = NULL;
fac2text = (struct VMSFAC *)newmsg;
vms2text = (struct VMSMSG *)(newmsg +
(facn * sizeof( struct VMSFAC )));
msglen = msgn;
faclen = (size_t)facn;
newmsg = NULL;
sts = SS$_NORMAL;
} while( 0 );
if( mf != NULL ) {
int err;
err = errno;
fclose( mf );
if( err )
errno = err;
}
if( $FAILED(sts) ) {
if( errno ) {
int err;
err = errno;
printmsg( sts, 0, newfilename );
sts = printmsg( ODS2_OSERROR, MSG_CONTINUE, sts,
strerror( err ) );
} else
sts = printmsg( sts, 0, newfilename );
if( newmsg != NULL ) free( newmsg );
if( newfilename != NULL ) free( newfilename );
}
return sts;
}
/********************************************************** showmessagefile() */
vmscond_t show_message( int argc, char **argv ) {
unsigned long n;
if( argc > 2 ) { /* SHOW MESSAGE numeric [numeric...] */
for( ; argc > 2; --argc, ++argv ) {
n = strtoul( argv[2], NULL, 0 );
if( $PRINTED((vmscond_t)n) ){
printmsg( HELP_SHOWMSGPRINTED, MSG_TEXT | MSG_NOCRLF );
printmsg( (vmscond_t)n, MSG_CONTINUE | MSG_ALWAYS, HELP_SHOWMSGPRINTED );
} else
printmsg( (vmscond_t)n, MSG_NOARGS | MSG_ALWAYS );
}
return SS$_NORMAL;
}
return printmsg( ODS2_MSGFILE, 0, (msgfilename? msgfilename: "/DEFAULT") );
}
/******************************************************************* decstr() */
static int decstr( FILE *mf, size_t *size, char **pp, char **sp ) {
int c;
size_t len = 0;
if( sp != NULL )
*sp = NULL;
while( (c = getc( mf )) != EOF && c != '\0' ) {
if( len == 0 ) {
len = 1;
if( sp != NULL )
*sp = *pp;
}
if( c == '\001' ) {
const char *s;
size_t slen;
c = getc( mf );
if( c == EOF )
return c;
if( c < PRI_CODEBASE || c > PRI_CODEEND )
return EOF;
s = pristr[ c - PRI_CODEBASE ];
len +=
slen = strlen( s );
if( sp != NULL ) {
memcpy( *pp, s, slen );
*pp += slen;
}
} else {
if( sp != NULL )
*(*pp)++ = c;
++len;
}
}
if( c == EOF )
return c;
*size += len;
if( sp != NULL && len != 0 )
*(*pp)++ = '\0';
return 0;
}
/******************************************************************* sysmsg_rundown() */
void sysmsg_rundown( void ) {
size_t i;
for( i = 0; i < sizeof( retbuf ) / sizeof( retbuf[0] ); i++ )
if( retbuf[i] != buf ) {
free( retbuf[i] );
retbuf[i] = NULL;
}
free( buf );
buf = NULL;
free( msgfile );
msgfile = NULL;
free( msgfilename );
msgfilename = NULL;
}
/*
#endif
*/

Some files were not shown because too many files have changed in this diff Show More