home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
disk
/
misc
/
pfs
/
programmersinfo
< prev
next >
Wrap
Text File
|
1995-02-27
|
8KB
|
230 lines
/**********************************************************************/
/* This file contains the datastructures used by PFS */
/* */
/* If you have specific programming plans I would like to know about */
/* it. I can help you with any problems and can supply extra */
/* information, if so needed. I can supply you with PFS specific */
/* code too, like allocation or anode routines. */
/* Of course you're free to do whatever you want with the tools you */
/* make, but if you'll allow me, I would like to add them to the PFS */
/* package, or at least refer to it in the documentation. */
/* */
/**********************************************************************/
// max length of filename, diskname and comment
#define FNSIZE 108
#define DNSIZE 32
#define CMSIZE 80
#define ID_PFS_DISK (0x50465300L) //'PFS\0'
/**********************************************************************/
/* Blockformat */
/**********************************************************************/
#define DBLKID 0x4442 //'DB'
#define ABLKID 0x4142 //'AB'
/* Directory blocks
**
** dirblock structure:
**
** This is what a dirblock looks like on disk. Reserved fields are for
** future extension.
**
** DirEntry structure:
**
** The 'type', 'creationtime' and 'protection' are, accept for their
** size, in DOS format.
** The filename and the comment are dynamic: size followed by that
** number of characters (like BSTRs). The comment directly follows the
** filename. The 'next' field contains the size of the direntry. This
** should always be even. The end of the directoryblock is marked by
** next = 0.
**
** The size of a direntry can be calculated by:
** size = (sizeof(struct direntry) + strlen(name) + strlen(comment))&0xfe
*/
#define DB_HEADSPACE (6 + 10)
#define DB_ENTRYSPACE (TD_SECTOR - 16)
struct dirblock // voor disk only (WORD blokno), timestamp later..
{
UWORD id; // 'DB'
ULONG reserved_1[2];
UWORD reserved_2;
UWORD anodenr; // anodenr belonging to this directory (points to FIRST block of dir)
UWORD parent; // parent; ANODE_ROOTDIR = root
UBYTE entries[DB_ENTRYSPACE]; // entries, fini by NULL
};
struct direntry
{
UBYTE next; // sizeof direntry
BYTE type; // dir, file, link etc
UWORD anode; // anode nummer
ULONG size; // sizeof file
UWORD creationday; // days since Jan. 1, 1978 (ala ADOS; WORD ipv LONG)
UWORD creationminute; // minutes past midnight
UWORD creationtick; // ticks past minute
UBYTE protection; // protection bits (ala ADOS)
UBYTE nlength; // length of filename
UBYTE startofname; // filename, followed by commentlen & comment
UBYTE pad; // make size even
};
// comment: de is struct direntry *
#define COMMENT(de) ((UBYTE*)(&((de)->startofname) + (de)->nlength))
#define OBJECTNAME(de) ((UBYTE*)(&(de->startofname)))
// get a pointer to the next direntry; de = struct direntry *
#define NEXTENTRY(de) ((struct direntry*)((UBYTE*)(de) + (de)->next))
// get a pointer to the firste direntry; blok is struct dirblock *
#define FIRSTENTRY(blok) ((struct direntry*)((blok)->blk.entries))
#define ENTRYLEN(de, comment) ((sizeof(struct direntry) + (de)->nlength + strlen(comment))&0xfffe)
/* Anode blocks and Anodes
**
** All space on disk is allocated by anodes. Anodes are runlength
** lists: a blocknr and a number indicating how many blocks are
** allocated by this anode.
**
** The anodes are organized in an array spread over anodeblocks. The
** anodenr is the index in this array. The anodeblock themselves are
** allocated in the rootblock.
**
** The first 6 anodes have a special function, they allocate
** freespace, the rootdirectory and perform system functions
**
** Every anodeblock contains ANODESINBLOCK anodes.
**
** struct anode:
**
** The anode itself. The 'clustersize' is the number of blocks being
** allocated. The allocated blocks are 'blocknr' up to (but not
** including) 'blocknr' + 'clustersize'. The 'next' field is a link
** to another anode where the allocation continues. At the end of the
** anode chain next = 0.
**
** If blocknr = 0 the anode is free, and can be reused. If the anode
** contains { 0, -1, next} the anode is reserved by a file or
** directory but is not yet in use. PS: empty anodes, with clustersize
** 0, are valid.
** Vrijgeven van een anode: clustersize = 0; blocknr = 0; next = 0;
*/
#define ANODESINBLOCK 82
/* anode 0 is reserved; EOF; must be 0, -1, 0 (use for endoflist detection)
** ANODE_FREESPACE MUST have ANODE_RESERVED linked. All reserved blocks
** must be at the end of the chain. There may not be 'mixed' anodes
** anywhere
**
** Anodes < 6 may be {0,0,0} but should NEVER be allocated for other
** purposes.
** ANODE_FREESPACE, ANODE_BADBLOCKS and ANODE_EOF should always be
** reserved {0, -1, 0}.
** ANODE_USERFIRST is the first anode usable for files etc.
*/
#define ANODE_EOF 0
#define ANODE_FREESPACE 1
#define ANODE_RESERVED 2
#define ANODE_TOBEFREED 3
#define ANODE_BADBLOCKS 4
#define ANODE_ROOTDIR 5
#define ANODE_USERFIRST 6
struct anode
{
UWORD clustersize;
UWORD blocknr;
UWORD next;
};
struct anodeblock
{
UWORD id;
ULONG reserved_1[2];
UWORD seqnr; // sequence number of anodeblock (starts with 0)
UWORD next; // chain, 0 = end
UWORD pad;
struct anode nodes[ANODESINBLOCK];
ULONG reserved_2;
};
/* Data blocks
*/
#define DATAINBLOCK 512
struct datablock
{
UBYTE data[DATAINBLOCK]; // only data
};
/* Rootblock and bootblocks
*/
#define BOOTBLOCK1 0
#define BOOTBLOCK2 1
#define ROOTBLOCK 2
struct rootblock
{
LONG disktype; // 'FDOS' same place as AmigaDos puts id
LONG reserved_1[2];
UWORD creationday; // days since Jan. 1, 1978 (ala ADOS; WORD ipv LONG)
UWORD creationminute; // minutes past midnight
UWORD creationtick; // ticks past minute, not really needed
UWORD protection; // protection bits (ala ADOS)
UBYTE diskname[32]; // DSTR of diskname;
UWORD firstreserved; // first reserved block (must be 0)
UWORD lastreserved; // end of reserved area
LONG reserved_2[10];
WORD anodeblocks[42]; // 0->notallocated
UBYTE reserved_3[DATAINBLOCK - 96 - 2*42];
};
struct bootblock
{
LONG disktype;
UBYTE reserved[508];
};
/* Reserved areas and other notes
**
** Anode and directory blocks are allocated in a special reserved area
** at the start of the partition. The reserved area bounderies are defined
** in the rootblock and vary with disksize. The reserved area can
** overflow in the normal area and vice versa.
**
** Directories are allocated by anodes, but they don't support
** clustersizes other than 1.
**
** Allocation strategy
**
** PFS always always writes directory and anodeblocks in a different
** place than they came from. The same for files: overwritten files are
** actually written somewhere else. A kind of 'freed first reused last'
** (FFRL) algorithm is used, so old versions stay on the disk for a long
** time. Sometimes PFS will abandon FFRL if this can prevent fragmentation.
** Recovery tools could make use of this: old versions can be restored
** if the current one is corrupt, and deleted files can be recovered.
**
** Update strategy
**
** Dirty anode and dirblocks are written to disk before the rootblock.
** Because the rootblock allocates the anodeblock which allocate the
** directories, and every anode is written on a new position, all
** changes take effect at the moment the rootblock is written. Before
** that seemingly nothing has changed.
*/