Thursday, December 21, 2017

VMS Binary File Editor

A long long time ago, when the Earth was young, and we rode our 
dinosaurs to work every morning, I worked as a system manager at a large 
VAX site. It was around 1986 and we had a pretty large cluster, that we
used, along with some other local VAXes, to support around 8,000 engineers
and office workers all over the world. 

  One day, I got a call form the folks that managed the accounts on the
system. They allowed as to how they were getting errors when they tried to
add any new accounts to the UAF. Next, the Help Desk called to relate that
lots of people couldn't log in anymore. I found this...alarming. A little
checking soon revealed that the UAF was corrupt. It apparently had a bad
block in the middle of it, and RMS was not well pleased when it tried to
read it. 

  I tried the usual RMS fixes. First, on the theory that maybe the bad
block was in the middle of a secondary index, I tried to convert the file
to a sequential file, and, if that had worked with no errors, I could have
then converted it back to an indexed file, with no loss of data. No soap -
it couldn't successfully convert to a sequential file. 

  I thought about the old RMS trick of "patching" around the bad bucket.
That can make an RMS file readable again, but, had a pretty good chance of
losing some records. Losing random records out of the UAF did not appeal
to me as a solution.

  I considered restoring from backup, but, the backup had been done 
Friday, and it was Monday afternoon now - it was a busy place and a lot
of work had been done since then (at the time, the sun never set on this 
engineering firm). Accounts had been added and deleted, Identifiers had
been granted  and revoked, last login times updated, passwords changed -
well, you know how it is - lots of changes. 

  Using the backup would have been a very large pain in the sitz-platz. 
But I got to thinking - a lot of the UAF doesn't change all that much from 
day to day - the odds were good that the bad block, be it a user record or 
a piece of metadata,  had occurred in a spot that hadn't changed since
the last backup. Finding what block was bad was trivial - I DUMPed the
file and it keeled over and told me when it hit the bad block. Then I used
DUMP to DUMP all the rest of the file starting after that block, to make
sure only one block was bad. All I needed then was a program to read that
block out of the UAF from the Friday backup, and update it into the current
production one, writing over the bad one (well, bad block relocation would
take place, but I wasn't worried about that low level for this problem -
functionally, the bad block got overwritten). 

  So....that's what I did. I wrote a block IO program that read block
number X out of the good backup file, and updated it into block X of the
bad production file. I held my breath and did a CONVERT...it succeeded. A
little testing with UAF showed it was all good to go now - the failures
the accounts folks were seeing didn't happen anymore. All of the hard 
working engineers and office workers could log in again. The phones didn't 
ring off the wall with people asking what happened to the changes from the
last three days. All was well again in Whoville and the phone stopped
ringing. 

  But the whole mess made me think that I ought to have a utility on hand 
and ready to go that could easily read, write, edit and block copy data
around for any future situations such as the above - something a little
more general purpose than the fixup program I used that time. I also had
need of a utility that could do binary edits on files, that was easier to
use than PATCH/ABSOLUTE. 

  ZAP was that program. I named it after the famous RSX11 ZAP program, 
that was a brilliant hack that turned ODT in RSX into a file editor with 
the addition of just a few lines of code.

  ZAP will let you edit files character by character, in hex or ASCII. It 
will allow you to copy blocks around inside a file, as well as copy a 
block or blocks from one file and write them into another file. ZAP is one 
of a very few programs I wrote in Fortran instead of Mcaro-32, so, by 
happy coincidence, it is also one of the very few programs I have written 
that will fork on Alphas (and likely Itaniums, although I haven't tested it 
one one) as well as VAXes.

  Here's the sources for ZAP

build.txt

zap.for

screen_init

ufo.for

read.for

write.for

format_line

fresh.for

  To build...

Rename build.txt to build.com (Google sites won't let me upload a file
with the extension of ".com"...) and the execute it.

$ rename build.txt build.com
$ @build

  To use

$ zap :== $disk:[directory]zap.exe
$ zap somefiletozap.ext

   Or, just run zap

$ run zap
  And you will be prompted for what file you want to edit.


  The leftmost panel in ZAP has a command summary. Here's what a ZAP
session looks like. 





And here it is in ASCII mode






  Basically, in any block, use the cursor keys to move around. When you
reach the bottom or top of the screen, the block will scroll up or down as
needed within the current block. It will not scroll into next block. To
change a value, position on it, then enter the new value. If you are in
HEX mode, and want to enter a new value, entry must be two digits (leading
zeros are required. To write any changes you make to the file, press the
DO key or GOLD-W before leaving the block (several functions have two key
sequences that can perform them, since not all keyboards have DO, Select,
and other DEC terminal specific keys). Note that the hex mode display is formatted
like a VMS dump  - the lower addresses are on the right, increasing as you go
to the left. ASCII mode is like text, it goes from left to right.  Blocks that are copied
go into a temporary file, so you can copy blocks from a file, close that session,
start ZAP on another file, and past those blocks into it.

No comments:

Post a Comment

Comments?