home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
144.lha
/
disk.tutor
< prev
next >
Wrap
Text File
|
1986-11-21
|
47KB
|
969 lines
An Explanation of AmigaDOS Storage Device Structure
In order for you to use a disk editor to its full disk-saving/disk-altering
potential, you must first understand the structure of an AmigaDOS device.
References will be made to a P.D. disk editor called 'Sectorama', though the
basic information and principals presented in this doc will be applicable to
all disk editors. Note that to avoid confusion and to provide immediately
applicable info, the block formats presented in this doc are specifically for
512 byte blocks. For larger blocks, the size of the Hash Table will vary and
all info after the hash table will be displaced ahead of the hash table so
the secondary-type word is at the end of the block. All devices I know of to
this point use a 512 byte block.
This document is basically written in two parts. The first part is an
explanation of what each word in each type of block, how various types
of blocks are structured, and how all these blocks relate to one another on
an AmigaDOS storage device. The second part is an explanation of how to do
things with a disk editor such as sectorama.
I) BLOCK BASICS
============
Generally, each block on an AmigaDOS device contains a checksum, a header
key whose value is the disk address of the block, and a block type which tells
you what type of block this is so you know what format that particular block
uses. Note that when I use the term, 'block', I am referring to a 512 byte
chunk of storage space on an AmigaDOS device. For example, on a floppy or
hard drive, a block refers to a 512 byte sector. In VDO: and RAM:, a block
refers to 512 contiguous bytes somewhere in memory. Also note that the size
of each datum in a block is a 32 bit word. For all blocks, the first
six words are as follows:
+--------------------+
0 | Block Type |
+--------------------+
1 | Header Key |
+--------------------+
2 | Number or count |
+--------------------+
3 | Table or Data size |
+--------------------+
4 | First or next data |
+--------------------+
5 | Checksum |
+--------------------+
: :
Block Type - This identifies the general size and structure of this block.
It currently has one of three values:
T.SHORT = 00000002 This indicates the block is at the head of
a list (i.e. a HEADER BLOCK).
T.LIST = 00000010 This indicates the block is a LIST BLOCK.
A list block is a member of a linked list
list blocks and contains a table of pointers
to data blocks.
T.DATA = 00000008 This indicates the block is a DATA BLOCK.
A data block is simply a block that contains
data and will be described later in this
doc.
Header Key - This 32-bit word is the device's address for this block. It
is a pointer to this block.
Number or Count - If this not a data block, this is a total count of data
blocks (and, hence, the highest sequence number of any
data block) pointed-to by this block.
- If this block is a data block, this number is the sequence
number of this data block. That is, it tells us this data
block is the n'th member of a list of data blocks.
Table or Data Size - This is a count of how many 32-bit words there are in
the table or data starting at word # 6 in this block.
First or Next Data - This is a pointer to the data block following this block.
If this block is a header or a list block, then this
pointer will point to the first data block in a list
of data blocks.
Checksum - When this number and the values of all other words in this block
are added up, the sum must be zero. This is how bad blocks are
detected by AmigaDOS.
For all types of blocks excepting data blocks, the last four words have the
following format:
: :
+----------------+
7C | Hashchain |
+----------------+
7D | Parent |
+----------------+
7E | Extension |
+----------------+
7F | Secondary Type |
+----------------+
Hashchain - points to the next entry on this hash chain.
Parent - pointer to the parent directory. The parent directory is the
directory block which either points to this block or points to a
linked list (i.e. hash chain) of which this block is a member.
Extension - pointer to the next extension block which essentially extends the
table which starts at word # 6 of this block.
Secondary Type - This exactly identifies what kind of block this is. This
tells us exactly what function and structure this block has.
The possible codes in this word are:
ST.ROOT = 00000001 This identifies the ROOT BLOCK, which
is the device's 'root directory'.
This block ultimately points to all
the files and directories on the
storage device.
ST.USERDIR = 00000002 This identifies a USER DIRECTORY BLOCK
which points to all the files and
directories which have been defined
for this directory.
ST.FILE = FFFFFFFD This identifies either a FILE HEADER
BLOCK, if the block type at word # 1
is T.SHORT, or a FILE LIST BLOCK if
the block type is T.LIST.
A FILE HEADER BLOCK points to all the
data blocks that make up the file. If
there are too many data blocks to be
pointed to by this block, a list of
FILE LIST BLOCKS is pointed-to by the
extension pointer at word # 7E. A
FILE LIST BLOCK simply extends the
table and points to the next FILE LIST
BLOCK if more data block pointers are
required.
Note that the above-mentioned word definitions are not applicable to some
block types and functions. Where their function is non-applicable, their
value is usually set at zero.
II) THE ROOT BLOCK
==============
The block that ultimately points to everything on the disk is called the
'Root Block'. This block usually resides in the exact center of a storage
device to minimize the distance a read/write head of a floppy or hard disk
must move when travelling from an outer cylinder to the Root Block. The
format of the Root Block is as follows:
symbolic usual
value value
+----------------------+
0 | T.SHORT = 00000002 | Indicates this is a 512 byte header block
+----------------------+
1 | 0 = 00000000 | Header Key (Always zero in a root block)
+----------------------+
2 | 0 = 00000000 | Highest sequence number in chain (0 for root)
+----------------------+
3 | HT SIZE = 00000048 | Hashtable size (=blocksize-56 = 512/4-56 words)
+----------------------+
4 | 0 = 00000000 |
+----------------------+
5 | CHECKSUM = ? | Checksum for this block
----+----------------------+
{ 6 | |
{ | Hash Table |
{ to : :
{ : :
{ 4D | |
----+----------------------+
4E | BMFLAG = FFFFFFFF | True (all F's) if device or disk bitmap valid
----+----------------------+
{ 4F | |
{ | Bitmap Pages |
{ to : :
{ : :
{ 68 | |
----+----------------------+
69 | DAYS = ? | Volume last altered date and time.
+----------------------+ Date is in packed format.
6A | MINS = ? | Time is rated in minutes and ticks.
+----------------------+ One tick is 1/60th of a second.
6B | TICKS = ? |
----+----------------------+
{ 6C | | Volume name as a BCPL string of 30 characters
{ | Disk Name | or less, though the amount of space to store
{ to : : this string always remains the same size.
{ : :
{ 78 | |
----+----------------------+
79 |CREATEDAYS = ? | Date and time when this volume was created.
+----------------------+ Format here, as well as all date/time data
7A |CREATEMINS = ? | presented in other types of blocks are in the
+----------------------+ format shown for the above volume last altered
7B |CREATETICKS= ? | date and time.
+----------------------+
7C | 0 = 00000000 | Next entry on this hash chain (0 for root)
+----------------------+
7D | 0 = 00000000 | Parent directory (always 0 for root)
+----------------------+
7E | 0 = 00000000 | Extension (always 0 for root)
+----------------------+
7F | ST.ROOT = 00000001 | Secondary type indicates this is a Root Block
+----------------------+
-> What the heck is a HASH TABLE?
A HASH TABLE is a table of pointers to files and to lists of files. To
locate a particular file in the table, the name of the file is used to
calculate where in the table it is to be located. This location may not be
unique to the name of this file. In this case, the pointer will point to a
linked list of file headers which must be traversed until the file header for
the file we're searching for is found. This linked list is referred to as a
HASH CHAIN.
The actual searching-out of files will be discussed in more practical terms
in the practical portion of this document.
-> What things are pointed-to by pointers in a HASH TABLE?
Each non-zero pointers in the hash table points to either a FILE HEADER
BLOCK or a USER DIRECTORY BLOCK which, in turn, may have a hash chain pointer
which will point to the next file header block or user directory block in
the hash chain.
-> What are bitmap pages?
The words in the list of bitmap pages point to 512 byte blocks which
simply map-out which blocks on the device are used, and which are free for
usage. I don't yet understand how the bitmaps are set-up or maintained,
but as soon as I find out, I'll slip the info into this document.
-> What is a BCPL string?
This is a string of bytes where the first byte indicates the number of
characters in the string (say, 'n' characters), the next 'n' characters
contain the ASCII values for the string, and the rest of the string is
ignored. For example, on my Workbench disk, a hex dump of the string looks
like this:
09576F72 6B62656E 63686F72 6B62656E .Workbenchorkben
63680000 00000000 00000000 00000000 ch..............
00000000 00000000 ........
Where the 09 at the beginning specifies that only the next nine characters
are valid characters of the string and the rest are ignored.
Note that for the root block, zeros are always in the Header Key, Sequence
Number, Hash cain, Parent, and Extension fields. This is because a ROOT BLOCK
is always at a specific spot on the device (for a disk, it is exactly
cenetered between the outer- and inner-most cylinders), it never require hash
table extensions, it is not pointed-to by a hash table and is not part of a
hash list, and it does not have a parent directory.
III) USER DIRECTORY BLOCKS
=====================
A user directory block is created when a new directory is made in a storage
device. It contains its own name and protection status, its parent directory,
as well as a hash table pointing to files and user directories that have been
placed into this directory. The hash table functions exactly the same way as
that in the ROOT BLOCK. The format of a USER DIRECTORY BLOCK is as follows:
symbolic usual
value value
+----------------------+
0 | T.SHORT = 00000002 | Indicates this is a 512 byte header block
+----------------------+
1 | OWN KEY = ? | Header Key (pointer to this very block)
+----------------------+
2 | 0 = 00000000 | Highest sequence number in chain (always zero)
+----------------------+
3 | 0 = 00000000 |
+----------------------+
4 | 0 = 00000000 |
+----------------------+
5 | CHECKSUM = ? | Checksum for this block
----+----------------------+
{ 6 | |
{ | Hash Table |
{ to : :
{ : :
{ 4D | |
----+----------------------+
4E | SPARE = 00000000 |
4F | SPARE = 00000000 |
+----------------------+
50 | PROTECT = ? | Protection bits (Read/Write/Execute/Delete)
+----------------------+
51 | 0 = 00000000 | Unused (always zero)
----+----------------------+
{ 52 | |
{ | COMMENT | Stored as a BCPL string
{ to : : (up to 90 characters)
{ : :
{ 68 | |
----+----------------------+
69 | DAYS = ? | Directory creation date and time.
+----------------------+
6A | MINS = ? |
+----------------------+
6B | TICKS = ? |
----+----------------------+
{ 6C | |
{ | Directory Name | Directory name as a BCPL
{ to : : (up to 30 characters)
{ : :
{ 7B | |
----+----------------------+
7C |HASHCHAIN = ? | Next entry with same hash value
+----------------------+
7D | PARENT = ? | Back pointer to parent directory
+----------------------+
7E | 0 = 00000000 | Extension
+----------------------+
7F | ST.ROOT = 00000002 | Secondary type (user directory block)
+----------------------+
IV) FILE HEADER BLOCK
=================
This block is the first block of any given file. It contains file
information such as the name, size, protection status, creation date, and a
pointer to the parent directory block of the file. It also contains a table
of pointers to all the data blocks that make up the file. If there are more
data blocks than there are pointers in the table of data block pointers (at
words # 6 to 4D), an extension pointer is provided to a FILE LIST BLOCK which
contains a similar table of data block pointers. If the file list block
still doesn't provide enough pointers, it will provide yet another extension
pointer to another FILE LIST BLOCK. This list of FILE LIST BLOCKS extends
until enough pointers are provided to point to all the data blocks of the
file.
symbolic usual
value value
+----------------------+
0 | T.SHORT = 00000002 | Indicates this is a 512 byte header block
+----------------------+
1 | OWN KEY = ? | Header Key (pointer to this very block)
+----------------------+
2 |HIGHEST SEQ= ? | Number of data blocks pointed-to by this block
+----------------------+
3 |DATA SIZE = ? |
+----------------------+
4 |FIRST DATA = ? | Pointer to the first data block of the file
+----------------------+
5 | CHECKSUM = ? | Checksum for this block
----+----------------------+
{ 6 | : |
{ : : : List of pointers to data blocks
{ to : : : (i.e. Data block keys)
{ | DATA BLOCK 3 |
{ | DATA BLOCK 2 |
{ 4D | DATA BLOCK 1 |
----+----------------------+
4E | SPARE = 00000000 |
4F | SPARE = 00000000 |
+----------------------+
50 | PROTECT = ? | Protection bits (Read/Write/Execute/Delete)
+----------------------+
51 | BYTESIZE = ? | Total size of file in bytes
----+----------------------+
{ 52 | |
{ | COMMENT | Stored as a BCPL string
{ to : : (up to 90 characters)
{ : :
{ 68 | |
----+----------------------+
69 | DAYS = ? | File creation date and time.
+----------------------+
6A | MINS = ? |
+----------------------+
6B | TICKS = ? |
----+----------------------+
{ 6C | |
{ | File Name | File name as a BCPL string
{ to : : (up to 30 characters)
{ : :
{ 7B | |
----+----------------------+
7C |HASHCHAIN = ? | Next entry with same hash value
+----------------------+
7D | PARENT = ? | Back pointer to parent directory
+----------------------+
7E |EXTENSION = ? | Pointer to a FILE LIST BLOCK (if required)
+----------------------+
7F | ST.ROOT = FFFFFFFD | Secondary type (file header block)
+----------------------+
V) FILE LIST BLOCK
===============
This type of block is used to extend the table of data block keys
(pointers) of a FILE HEADER BLOCK when the table in the FILE HEADER BLOCK
hasn't enough pointers to point to all the file's data blocks. If a FILE
LIST BLOCK doesn't have enough pointers to point to the rest of the file's
data blocks, the EXTENSION pointer of the block will point to yet another
FILE LIST BLOCK. The extension list continues until enough pointers are
provided for all the data blocks in the file.
symbolic usual
value value
+----------------------+
0 | T.LIST = 00000010 | Indicates this is a file list block
+----------------------+
1 | OWN KEY = ? | Header Key (pointer to this very block)
+----------------------+
2 |BLOCK COUNT= ? | Number of data blocks pointed-to by this block
+----------------------+
3 |DATA SIZE = 00000000 |
+----------------------+
4 |FIRST DATA = 00000000 |
+----------------------+
5 | CHECKSUM = ? | Checksum for this block
----+----------------------+
{ 6 | : |
{ : : : Extended list of pointers to data blocks
{ to : : : (i.e. Data block keys)
{ | DATA BLOCK 3 |
{ | DATA BLOCK 2 |
{ 4D | DATA BLOCK 1 |
----+----------------------+
{ 4E | |
{ | unused | unused (all zeros)
{ to : :
{ : :
{ 7B | |
----+----------------------+
7C | 0 = 00000000 | Next in hash list (always zero for list block)
+----------------------+
7D | PARENT = ? | Points to the file header block of this file
+----------------------+
7E |EXTENSION = ? | Points to the next FILE LIST BLOCK (if required)
+----------------------+
7F | ST.ROOT = FFFFFFFD | Secondary type (file header block)
+----------------------+
VI) DATA BLOCK
==========
A data block contains data from a file and is pointed-to by preceding
data blocks and by a pointer in a table in either a FILE HEADER BLOCK or a
FILE LIST BLOCK. Thus, the data block can be accessed directly from a header
or list block of a file, or sequentially by following the linked list of data
blocks. Each data block also points to the FILE HEADER BLOCK which describes
the file which contains this data block. A sequence number is also present
in a data block, and indicates that this data block is the n'th data block
in the list of the file's data blocks.
symbolic usual
value value
+----------------------+
0 | T.DATA = 00000008 | Indicates this is a data block
+----------------------+
1 | HEADER = ? | Header key pointing to the file header block.
+----------------------+
2 | SEQ NUM = ? | Sequence number
+----------------------+
3 | DATA SIZE = 00000000 | Number of words of data in this block
+----------------------+
4 | NEXT DATA = ? | Pointer to the next data block
+----------------------+
5 | CHECKSUM = ? | Checksum for this block
----+----------------------+
{ 6 | |
{ | DATA |
{ to : :
{ : :
{ 7F | |
+----------------------+
VII) HOW DO THE BLOCKS FIT TOGETHER?
===============================
The ROOT BLOCK is located at a fixed location, exactly between the highest
and lowest addresses available on a storage device. The ROOT BLOCK contains
a table of pointers (the hash table) to linked lists (hash chains) of USER
DIRECTORY BLOCKS and FILE HEADER BLOCKS which describe user directories and
files accessible from the root directory.
A USER DIRECTORY BLOCK contains the name and protection status of a user
directory, as well as a hash table containing pointers to hash chains of
USER DIRECTORY BLOCKS and FILE HEADER BLOCKS which describe user directories
and files accessible from that user directory. Since the USER DIRECTORY
itself is a member of a hash chain, it also contains pointers to its parent
directory block and to the next USER DIRECTORY BLOCK or FILE HEADER BLOCK in
the header chain.
A FILE HEADER BLOCK contains information describing the file it represents,
as well as a table of pointers to DATA BLOCKS that make up the file. If
there aren't enough pointers in this table to point to all the file's DATA
BLOCKS, an EXTENSION pointer points to a list of FILE LIST BLOCKS which
extend the table. Since the FILE HEADER BLOCK is a member of a hash chain,
it contains pointers to its parent directory and to the next USER DIRECTORY
BLOCK or FILE HEADER BLOCK in the header chain.
A FILE LIST BLOCK contains a table of pointers to DATA BLOCKS and extends
the table of the FILE HEADER BLOCK or FILE LIST BLOCK which points to this
FILE LIST BLOCK. If there aren't enough pointers in this table to point to
the remainder of the file's DATA BLOCKS, an EXTENSION pointer in the FILE
LIST BLOCK points to the next FILE LIST BLOCK to extend its data block table.
A DATA BLOCK's main content is data. It is part of a linked list of DATA
BLOCKS and includes a pointer to the next DATA BLOCK in the list. It also
includes a sequence number indicating that this DATA BLOCK is the n'th DATA
BLOCK in the list. Each DATA BLOCK is pointed-to both by the preceding DATA
BLOCK in the list, and by a pointer in a data block table in either a FILE
HEADER BLOCK or a FILE LIST BLOCK. Each DATA BLOCK also contains a pointer
to the FILE HEADER BLOCK which describes the file which the DATA BLOCK is a
member of.
Confused? Don't worry, practical stuff is coming up next...
VIII) UNDERSTANDING YOUR DISK EDITOR
==============================
Before we begin playing with a disk editor, I recommend that you create a
backup of a densely populated disk, like your workbench, so that if a wrong
key is pressed while looking through the backup, you haven't done damage to
your one and only copy.
a) A Look at Sectorama
===================
For those of you lucky enough to have a copy of sectorama handy, fire it
up and I can explain what all those obscure thingies on the right side and
of the top line of the screen mean and where, from the block you are
looking at, the information was taken.
The lower right hand portion of the display identifies the storage
device currently being examined by this sectorama display. It gives us
the device name (as a volume name), the device unit number, and the
filename of the device driver that communicates with the device.
The display section immediately above this info contains hardware-
dependant information. The middle column shows us the the sector, track
cylinder, surface, and block numbers of the block currently being
displayed. This information is all given in decimal values. All these
statistics are all determined by a set of info used by the device driver.
For a floppy, for example, these tell us on which cylinder the read/write
head is currently positioned, which sector on which surface (top or bottom)
is being read by the read/write head, and the hardware-specific track and
block numbers for that sector. The rightmost column are device statistics.
These tell us how many of each category there are on this device.
Note that by pointing at any of the figures in the center column of this
section, you can change the current values. By changing sector, surface,
or block number, you can examine any sector of the device immediately.
The section immediately above the hardware information contains
information about (and from) the block currently being displayed:
Date -refers to the creation date which is taken from word # 69.
Time -is calculated from words # 6A (to get hours and minutes) and
# 6B (to get seconds).
Highest Seq # -is taken from word # 2 and refers to the number of
words used in the table starting at word # 6.
Data Size -refers to the size of the table at word # 6.
Protect -refers to the protection status of a user directory block or
a file header block and is taken from the value at word # 50
File Bytes -refers to the size of a file in kilobytes. This value is
1/1000'th the value of word # 51.
The section at the upper right corner of the display is a list of
keyboard commands with current values beside them. All except the
checksum are pointers to other blocks in the device. The checksum is the
current block's checksum value taken from word # 5. This value must be
recalculated every time you make an alteration to a block. The pointers
shown beside each command are as follows:
R-Go Root -points to the root directory of this disk. This pointer
is a constant value which has been calculate for this
storage device.
P-Go Parent -points to a FILE HEADER BLOCK's or USER DIRECTORY BLOCK's
parent directory block. This pointer is taken from
word # 7D.
C-Go Hash Chain -points to the next FILE HEADER BLOCK or USER
DIRECTORY BLOCK in this blocks hash chain. This
pointer is taken from word # 7C.
X-Go Extension -points to the next FILE LIST BLOCK in an extension
chain. This pointer is taken from word # 7E.
H-Go Header -for DATA BLOCKS, this points to the FILE HEADER BLOCK
to which this DATA BLOCK belongs.
-for other blocks, this points to the block currently
being examined.
-in both cases, this pointer is taken from word # 1.
For all the above commands, if you type the letter to initiate the
command, sectorama will jump to the block corresponding to the pointer
displayed beside the command.
At the top of the display are three more information displays. On the
left is the block number of the block currently being displayed. Next to
that is the Type of the block being displayed. The block type is
determined by word # 0, which contains the block type, and word # 7F,
which contains the secondary type.
Next to the block type is the Name of the block. This name may be a
volume name or a directory name or a file name, depending on if this block
is a ROOT BLOCK, a USER DIRECTORY BLOCK, or a FILE HEADER BLOCK,
respectively.
b) Sectorama commands
==================
All the sectorama commands are adequately described in the documentation
file that accompanies it.
c) A Practical Session
===================
i) Touring a floppy, a summary
---------------------------
I suggest that as you progress through this little step-by-step
blathering that each time you come across a new type of block, you
compare the data being displayed by sectorama to the block
descriptions shown above so that you become more familiar about where
things are located in each type of block.
The steps for performing the operations summarized below with
Sectorama are described in detail, with a running commentary, in
section ii) Touring a floppy with Sectorama. For following these
steps with any other disk editor, I suggest that you quickly read
through the Sectorama tour to familiarize yourself with what is
being attempted, then attempt the summarized steps below to familiarize
yourself with your disk editor and AmigaDOS.
Steps 1 thru 8 will guide you from a disk's ROOT BLOCK, into a file
and through all the data blocks in that file. A quick summary of
these steps is as follows:
Steps 9 thru 14 show you how to alter a block and write it to disk.
_A step-by-step of the tour, in summary is as follows:
/ 1. Run the disk editor.
|
| 1a. (Load the root block. This is done automatically by Sectorama.)
|
| 2. Locate the 'c' directory by using the hash function.
Part< 3. Load the USER DIRECTORY BLOCK for the c directory.
1a | 4. Locate the 'dir' command file by using the hash function.
| 5. Load the FILE HEADER BLOCK for the 'dir' file.
| 6. Load the first DATA BLOCK of the 'dir' file.
| 7. Load and examine each consecutive DATA BLOCK of the 'dir' file until
| the last DATA BLOCK in the file has been loaded and examined.
\_8. Load the FILE HEADER BLOCK pointed-to by the final DATA BLOCK.
_
/ 9. Locate and select the first word in the comment filed of the FILE
| HEADER BLOCK for the 'dir' file.
| 10. Edit the ASCII values of the comment field.
Part< 11. Edit the hexadecimal value of the first byte of the first word of
1b | the comment field to insert the string length of the comment
| created in step 10.
| 12. Re-calculate the checksum for this block.
| 13. Write the altered block to disk.
\_14. Quit the disk editor.
ii) Touring a floppy with Sectorama...
----------------------------------
1. O.K., get your disk editor up and running (if it isn't already)
and begin examining a back-up copy of your workbench disk. For
sectorama, the CLI command line for this if the disk was in df0:
would look like:
1> run sec df0:
What you will see on your display (in neato-keen hi-res) is data
of the ROOT BLOCK of df0:. On top of the display is 'Type=ROOT DIR'
which indicates that the block currently being displayed is a
ROOT BLOCK.
2. Now that we are at the ROOT BLOCK, lets find the c directory. The
first step for this is to find out what value we get when we use the
hash function on the string 'c'. To do this you must envoke the hash
function by picking 'COMPUTE HASH VALUE' under the SEARCH menu, then
typing the file or directory name, in this case the letter c followed
by a <RETURN>. This highlights the block address of the hash chain
which contains the c directory.
3. Now that you've found the possible whereabouts of the c directory
jump to it by hitting the j key. If (more likely than not) on top of
the display is 'Name=c' then the display is currently displaying the
contents of the c directory and the top of the display has
'Type=DIRECTORY' indicating that what is being displayed is a USER
DIRECTORY BLOCK, which is essentially the c directory of df0:.
4. Now that we're at the c directory, let's look at a file containing
loadable/executable code for a well-known function... say, the file
called 'dir'. Envoke the hash function as before using the string
dir. The block address of the hash chain that contains the dir file
will be highlighted.
5. Press the j key to jump to the beginning of the hash chain which
will have (again, more likely than not) 'Type=FILE Name=dir'
displayed above the table of block data. The Type=FILE indicates that
this is the header block for the file indicated by Name=dir. This is a
fairly short file, so that all the block addresses for the DATA BLOCKS
for this file are included in this block and that no extension blocks
are required for this file, which is why the block address beside
'X-Go Extension=' is 00000000.
Also notice that the block address beside 'D-Go Next Data' is the
same as the last entry in the data table of this block (at word # 4D
according to my version of dir). This is because data blocks are
arranged in this table starting at the end of the table and working
towards the beginning.
6. Let's take a look at the first DATA BLOCK, then, by hitting the
d key to 'Go Next Data'. What will be displayed is the first DATA
BLOCK of the dir file. On top of the display will be 'Type=DATA BLOCK'
confirming that fact. Note that word # 04, which has the same value as
is displayed beside D-Go Next Data =, points to the next DATA BLOCK for
this file.
7. Let's traverse the entire list of DATA BLOCKS to see what the last
one in the list looks like. You can do this by hitting the D key
about 16 times or so. While you do this, note that the value beside
H-Go Header = stays constant for each data block while all the other
values remain constant. The value beside H-Go Header = points to
the FILE HEADER BLOCK which owns the DATA BLOCK. If this ever changes
as you are traversing a list of DATA BLOCKS, you KNOW there is a
problem with the file. Also note that as you jump from block to block,
the HISTORY list at the bottom of the display keeps track of your last
eight jumps. This is a valuable feature when you overshoot a problem
area and need to know where you've been in previous jumps. Also note
that for each successive DATA BLOCK that you display, the sequence
number displayed in the middle of the right part of the screen is
incremented by one. This helps you figure out exactly where you are in
the file you are looking through. If ever this sequence number jumps
up or down by more that one, you know the DATA BLOCK is out of its
proper sequence.
8. Once you've reach the end of the DATA BLOCK list, you will find that
hitting the D key will now only cause the display to flash, indicating
that this is indeed the end of the DATA BLOCK list for this file. Lets
jump back to the FILE HEADER BLOCK for the 'dir' file by hitting the
h key (for H-Go Header).
9. Now that we've jumped around the disk doing some block reading,
let's get more adventurous. Let's modify a block on the disk. By
comparing the FILE HEADER BLOCK description above, we note that the
comment field in this block begins at word # 52 and ends at word # 68.
Move your pointer to word # 52 and click your left mouse button to
highlight it.
10. Next, press the A key to enter ASCII edit mode (the command list on
the right of the display describes it as Edir ASCII). Now type a space
and then some sort of short comment, being careful not to type past
word #68. For example, I typed the comment ' dir, oh dir' beginning
in word #52. Note that the delete key and backspace key do not work
normally in this mode, and actually produce their own special ascii
values. To re-type something, you must either move your pointer to the
desired location and click, or use your cursor keys to move the
highlighter to the desired character, then type your correction.
To exit this edit mode, simply hit <RETURN>.
11. To make our comment a proper BCPL string, we must put a character
count at word # 52. Count how many characters there are in your string
and convert this number to hexadecimal. Next, enter the hexadecimal
edit mode by hitting the e key (for Edit), type your two-digit
hexadecimal value and hit return. For example, in my 'dir, oh dir'
comment there are eleven characters. Eleven converts to 0B in
hexadecimal, so I edit word #52, type 0B, and hit return.
12. Since we've altered the contents of this block, the checksum for
this block is no longer valid. We must hit the k key to calculate a
new checksum. When you have done this, you will note that the value
beside K-Checksum = and at word # 05 have changed to the newly
calculated checksum.
13. Note that any changes you have made so far haven't been written to
disk at all. Nothing is ever written to disk until you actually write
it by hitting the u key to 'Update block'. To incorporate your new
file comment for the file called 'dir', hit the u key.
14. Then quit Sectorama, and list df0:c/dir to see the
change that you've just made. Note that you may have to list the whole
c directory to see the change since AmigaDOS keeps track of which
sectors of which device it currently has in buffers, and will avoid
fetching your modified sector if it is currently in df0:'s buffer.
What we've just done is to examine a disk, seek-out a specific file,
look through the file's data, then modify the FILE HEADER BLOCK of
that file. What we haven't seen yet are two important data
structures which we will look for now. Specifically, these structures
are the hash chain, and the file list.
1. to 3. Same as steps 1. to 3. above. (Locate & load the c directory)
4. Now calculate the hash value for Echo using the Calculate Hash Value
function. Write the highlighted number down.
5. Calculate the hash value for Quit using the same hash function used
in step 4.
6. Calculate the hash value for Why using the hash function. You will
find that the value you have written down for the value calculated for
Why, Quit, and Echo are all identical, implying that if you jump to
this number, you will have access to all three files.
What this really means is that the FILE HEADER BLOCKS of these three
files are members of the same hash chain.
7. Jump to the first file in the hash chain by hitting the j key. I
cannot say exactly which FILE HEADER BLOCK you will be shown, since
that depends on in what order the files in the chain were created on
this disk. Note that the value beside P-Go Parent = is that of the
USER DIRECTORY BLOCK of the directory containing this file, namely the
c directory.
8. Note that the block address beside C-Go Hash Chain = is non-zero.
At least, if the files Echo, Quit, and Why are in the c directory on
this disk, the value will be non-zero. Otherwise, this demonstration
will not be successful. To display the header of the next file or
directory in this hash chain, hit the c key (indicated by C-Go Hash
Chain).
9. Note that the value beside P-Go Parent hasn't changed. This is
because all members of a hash chain always belong to the same
directory. To traverse the hash chain and find the last FILE HEADER
BLOCK or USER DIRECTORY BLOCK in the chain, keep hitting the c key
until the value beside C-Go Hash Chain becomes zero. When this
happens, further presses of the c key will merely cause the display
to flash, indicating you are at the end of the hash chain.
10. Jump back to the ROOT BLOCK by hitting the r key.
To find what an extension file looks like, we must look for a large
file... one where the amount of data is large enough that more pointers
are available in a FILE HEADER BLOCK's DATA BLOCK pointer table. A
DATA BLOCK pointer table usually has 72 available entries. Since each
BLOCK is 512 bytes long, we need a file that is over 72 x 512 = 36864
bytes long. The Preferences file is about twice that length, so let's
take a look at it.
11. Calculate the hash value for Preferences using the hash function.
12. Jump to the FILE HEADER BLOCK for the Preferences file by hitting
the j key. You will note that all the entries in the DATA BLOCK
pointer table in this FILE HEADER BLOCK are used-up. You will find
the rest of the pointers required to point to the rest of the DATA
BLOCKS for this file in the file list. The block number of the first
FILE LIST BLOCK in the file list is shown beside X-Go Extension.
13. Hit the x key to jump to the first FILE LIST BLOCK. Note that the
block number displayed beside P-Go Parent is the same as the block
number of the FILE HEADER BLOCK to which this FILE LIST BLOCK belongs.
Also note that the value beside X-Go Extension is now zero. If the
required even more DATA BLOCKS, that is, if the file was longer than
about 73kbytes, the value beside X-Go Extension would point to the next
FILE LIST BLOCK in the file list.
So, that pretty well wraps-up the tour. We've seen all the data
structures used by AmigaDOS and have had a chance to modify a block.
There are a number of implications of AmigaDOS structure that this
document hasn't covered, but these things will become apparent as you
are given the opportunity to apply the disk editor.
I hope the information forwarded by this document will help you solve
or at least understand problems that may occur from time to time when
storing things on AmigaDOS compatible devices.
A Trouble-shooting Example
--------------------------
This information was recently invaluable to me as I discovered a
problem with my hard drive recently that could have blossomed into a
fairly major disaster. A file was written on top of another file.
I kept getting a read/write error when I tried to copy the
over-written file to another device. So, I examined the hard drive
with Sectorama. I used the hash function to locate which hash chain
the file was stored under, traversed the hash chain until I found the
file header block of the file in question. I then traversed the list
of data blocks for the file by hitting the d key repeatedly. The
list seemed to be intact since I was able to follow the list to its
last block.
I then hit the h key to display the file header block again. It
was the file header block of an entirely different file! So, I jump
back to the root, jumped to the file I was originally investigating,
and again traversed the data block list while watching the value
beside H-Go Header for any changes. About half-way through the file
the value changed. I noted the block number of that data block,
hit the h key to jump to the wrong file header block again, and noted
that the block number of the erroneous data block was listed. I went
back to the root block and back to the original file header block and
found that the same erroneous data block was listed here, too.
I checked all the files on the hard disk, and found that only one
file was unreadable. Thus, that file had been overwritten. This
implied that somehow the bitmap of the disk was erroneous since the
data block used by the file was claimed by another file. I had to
backup-up new files, format the hard drive to prevent further calamity,
and copy back all the files. That cured the whole problem.
I had a directory problem a while ago that I now know how to fix
recover from with a disk editor. The directory of a device wrapped
around so that when I executed a list command, I got an endless
repetition of the same files, while other files on the disk would
never be listed. When I listed the ignored files by naming them
directly, they would show up. If I executed a dir command, the
storage device was searched and searched and searched until the
computer crashed. I believe that is due to dir's method of collecting
all files in a directory for sorting until the end of the directory
is reached, which, in this case, it never did.
Solving this is a matter of copying all files possible to another
device. This means individually copying all the files since wildcards
cause a directory search which, in this case, would never end. The
files you cannot see can be searched-out with Sectorama using wildcards
since Sectorama provides full-disk searches without consulting a
directory. After finding and copying all your files to another device,
I'd recommend formatting the device to remove anything that might cause
a relapse of the problem.
If you have any corrections, comments, or suggestions about the above
document, please send them to me or tell me about them. You can reach me at:
//
\X/ Tesseract BBS
(306)757-5699
(24 hours, 8N1, 300 or 1200 baud)
address: Dwayne Miller
770 Robinson Street
Regina, Saskatchewan, Canada (Yup, way up there!)
S4T 2M1
voice: (306)525-1652
P.S. Sectorama was written by David Joiner of MicroIllusions and is commonly
available, often named 'sec.arc' or 'sector.arc' or 'sectoram.arc' etc.