home *** CD-ROM | disk | FTP | other *** search
- /*
-
- FILE.C - file creation and maintainance module for df.c
-
- */
-
-
- #include <exec/io.h>
- #include <exec/devices.h>
- #include <devices/trackdisk.h>
- #include <devices/bootblock.h>
- #include "df.h"
-
-
- char bb_name[] = "bad.blocks";
-
- extern void df_exit(); /* exit routine */
- extern char *calloc(); /* clear & alloc function */
-
- extern char *dsk_buf; /* buffer for disk writes */
- extern BYTE write_blocks(); /* write blocks to the disk */
-
- extern struct RootBlock rb; /* structure for root block */
- struct FileHeaderBlock fb; /* structure for file header */
- extern struct disk_parm dp; /* structure for disk_parms */
- struct extension_block *extb; /* ptr to extension block list */
- struct bitmap_block *bmb; /* ptr to bitmap block list */
- ULONG next_avail_block; /* next block to write to */
- ULONG fh_key; /* file header key */
-
- extern struct bad_block *bad_block_list;
- extern int bad_blocks;
- struct file_ext_block *fextb; /* ptr to file ext block list */
-
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void add_bad_block( block )
- ULONG block;
- {
- /*
- Allocate and add the block to the bad_block_list. Make sure the
- block is in range for this disk as well...
- */
- struct bad_block *p, *q;
-
- if ( block > dp.upper_key )
- df_exit( EBADBLK );
-
- if ( !(p = (struct bad_block *) calloc( sizeof( struct bad_block ), 1 )) )
- {
- df_exit( ENOBLKS );
- }
-
- q = bad_block_list;
- p->key = block;
-
- bad_block_list = p;
- p->next = q;
- }
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- int block_already_bad( block )
- ULONG block;
- {
- /*
- Check the supplied block against the list of bad blocks
- If it is in there, return true, else return false...
- */
- struct bad_block *p;
-
- for( p = bad_block_list; p; p = p->next )
- {
- if ( p->key == block )
- return( 1 );
- }
- return( 0 );
- }
-
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- ULONG get_next_avail_block()
- {
- /*
- Just set next_avail_block to its successor unless we happen
- to find it in the used block list. In that case, keep going
- till we find a good/free block.
- */
-
- while ( block_already_bad( next_avail_block ) )
- {
- next_avail_block++;
- }
-
- return( next_avail_block++ );
- }
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void create_file_extension_block_list( blocks )
- int blocks;
- {
- /*
- Create a linked list of file extension blocks...
- */
- int i, blocks_left;
- struct file_ext_block *p, *q;
-
- /*
- calculate blocks_left for filling in the HighSeq field.
- */
- blocks_left = bad_blocks;
-
- for( i = 0, q = 0L; i < blocks; i++ )
- {
- blocks_left -= 72;
-
- if ( !(p = (struct file_ext_block *) calloc( sizeof( struct file_ext_block ), 1 ) ) )
- {
- df_exit( ENOMEM );
- }
-
- if ( !fextb )
- {
- fextb = p;
- }
- else
- {
- q->next = p;
- }
-
- p->next = 0L;
- p->key = get_next_avail_block();
- p->fhb.Type = 16L;
- p->fhb.OwnKey = p->key;
- p->fhb.SecondaryType = -3L;
- p->fhb.Parent = (q) ? q->fhb.OwnKey : fh_key;
- p->fhb.HighSeq = (blocks_left > 72) ? 72 : blocks_left;
- q = p;
- }
- }
-
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void get_next_block_ptr( key )
- ULONG key;
- {
- /*
- Stick the key in the next slot we have in the header or
- extension block, and update our next slot pointer.
- */
- static int fh_ptr = 71, eblock_ptr = 71;
- static struct file_ext_block *p = 0L;
-
- if ( !p )
- {
- fb.DataBlocks[fh_ptr--] = key;
- if ( fh_ptr < 0 )
- {
- p = fextb;
- fb.Extension = p->key;
- }
- }
- else
- {
- p->fhb.DataBlocks[eblock_ptr--] = key;
- if ( eblock_ptr < 0 )
- {
- p->fhb.Extension = p->next->key;
- p = p->next;
- eblock_ptr = 71;
- }
- }
- }
-
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- int hash_file_name( name )
- char *name;
- {
- /*
- Hash the file name to an address suitable for the root block.
- I got this out of a CATs newsletter on the FFS. It does not
- work, so I fudge the hash value for bad.blocks later...
- */
- int i, val;
-
- val = sizeof( name ) - 1;
- for( i = 0; *name; i++ )
- val = (( val * 13 ) + toupper( *name++ )) & 0x7ff;
-
- return( val % 72 );
- }
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void initialize_header_block( my_key )
- ULONG my_key;
- {
- /*
- Initialize the needed fields in the file header block prior to
- writing it to the disk.
- */
- int i;
- ULONG chksum;
- long *p;
-
- fb.Type = 2L;
- fb.OwnKey = my_key;
- fb.Parent = dp.root_key;
- fb.Protect = 15L;
-
- /*
- If we have extension blocks, set fb.HighSeq to 72, else
- set it to bad_blocks;
- */
- fb.HighSeq = (fextb) ? 72 : bad_blocks;
-
- fb.FirstBlock = bad_block_list->key;
- movmem( (char *) &rb.DiskMade, (char *) &fb.Date, 12);
-
- fb.FileName[0] = sizeof( bb_name ) - 1;
- strcpy( &fb.FileName[1], bb_name );
- fb.SecondaryType = -3L;
-
- /*
- Calculate the checksum for this block.
- */
- for( i = 0, chksum = 0, p = (long *) &fb; i < (sizeof( fb )/4); i++ )
- {
- chksum += *p++;
- }
- fb.Checksum = -chksum;
- }
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void update_bad_blocks()
- {
- printf( "Sorry, not implemented yet...\n" );
- }
-
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void print_bad_blocks()
- {
- printf( "Sorry, not implemented yet...\n" );
- }
-
- /*-----------------------------------------------------------------------------
- ------------------------------------------------------------------------------*/
- void create_bad_block_file()
- {
- /*
- Create the header and attach the blocks to the bad.block file.
- */
- int ext_blocks_needed, i;
- struct bad_block *p;
- struct file_ext_block *q;
- long chksum, *tmp;
-
-
- /*
- Set next_avail block to dp.lower_key, because this is where
- we are going to write the file header.
- */
- next_avail_block = dp.lower_key;
-
-
- /*
- Use the first available block for the File header...
- */
- fh_key = get_next_avail_block();
-
-
- /*
- Calculate number of extension blocks needed for bad block file.
- bad_blocks contains the number of blocks in the bad_block_list,
- and since a FileHeaderBlock can only hold 72 entries, we will
- need bad_blocks / 72 extension blocks.
- */
- ext_blocks_needed = (bad_blocks / 72) - 1;
- if ( (bad_blocks % 72) != 0 )
- ext_blocks_needed++;
-
-
- /*
- Create the extension block list if we need it.
- */
- if ( ext_blocks_needed )
- create_file_extension_block_list( ext_blocks_needed );
-
-
- /*
- For every block in the used block list, stick its key
- in either the fileheader or extension block.
- */
- for( p = bad_block_list; p; p = p->next )
- {
- get_next_block_ptr( p->key );
- }
-
-
- /*
- Initialize the rest of the fields in the FileHeader block,
- then write this baby to the disk!
- */
- initialize_header_block( fh_key );
-
- movmem( (char *) &fb, dsk_buf, sizeof( fb ) );
- if ( !write_blocks( fh_key, 1 ) )
- {
- df_exit( ENOHDR );
- }
-
- /*
- Update the root block with the address of this file header
- block. We would normally hash it, but our hash function does
- not work. Once again, we will cheat!!!
- */
- rb.HashTable[21] = fh_key;
-
-
- /*
- Complete and write the file extension blocks to the disk.
- */
- for ( q = fextb; q; q = q->next )
- {
- /*
- Calculate the checksum for this block.
- */
- for( i = 0, chksum = 0, tmp = (long *) &(q->fhb); i < 128; i++ )
- {
- chksum += *tmp++;
- }
- q->fhb.Checksum = -chksum;
-
- movmem( (char *) &(q->fhb), dsk_buf, 512);
-
- if ( !write_blocks( q->key, 1 ) )
- {
- df_exit( ENEXTB );
- }
-
-
- }
-
- }
-