home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 316.lha / DF / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-05  |  8.1 KB  |  361 lines

  1. /*
  2.  
  3.     FILE.C - file creation and maintainance module for df.c
  4.  
  5. */
  6.  
  7.  
  8. #include    <exec/io.h>
  9. #include    <exec/devices.h>
  10. #include    <devices/trackdisk.h>
  11. #include    <devices/bootblock.h>
  12. #include    "df.h"
  13.  
  14.  
  15. char    bb_name[] = "bad.blocks";
  16.  
  17. extern    void    df_exit();        /* exit routine            */
  18. extern    char    *calloc();        /* clear & alloc function    */
  19.  
  20. extern    char    *dsk_buf;        /* buffer for disk writes    */
  21. extern    BYTE    write_blocks();        /* write blocks to the disk    */
  22.  
  23. extern    struct    RootBlock    rb;    /* structure for root block    */
  24. struct    FileHeaderBlock        fb;    /* structure for file header    */
  25. extern    struct    disk_parm    dp;    /* structure for disk_parms    */
  26. struct    extension_block        *extb;    /* ptr to extension block list    */
  27. struct    bitmap_block        *bmb;    /* ptr to bitmap block list    */
  28. ULONG    next_avail_block;        /* next block to write to    */
  29. ULONG    fh_key;                /* file header key        */
  30.  
  31. extern    struct    bad_block    *bad_block_list;
  32. extern    int            bad_blocks;
  33. struct    file_ext_block        *fextb; /* ptr to file ext block list    */
  34.  
  35.  
  36.  
  37. /*-----------------------------------------------------------------------------
  38. ------------------------------------------------------------------------------*/
  39. void    add_bad_block( block )
  40. ULONG    block;
  41.     {
  42.     /*
  43.       Allocate and add the block to the bad_block_list. Make sure the
  44.       block is in range for this disk as well...
  45.     */
  46.     struct    bad_block    *p, *q;
  47.  
  48.     if ( block > dp.upper_key )
  49.         df_exit( EBADBLK );
  50.  
  51.     if ( !(p = (struct bad_block *) calloc( sizeof( struct bad_block ), 1 )) )
  52.         {
  53.         df_exit( ENOBLKS );
  54.         }
  55.  
  56.     q = bad_block_list;
  57.     p->key  = block;
  58.  
  59.     bad_block_list = p;
  60.     p->next = q;
  61.     }
  62.  
  63.  
  64. /*-----------------------------------------------------------------------------
  65. ------------------------------------------------------------------------------*/
  66. int    block_already_bad( block )
  67. ULONG    block;
  68.     {
  69.     /*
  70.       Check the supplied block against the list of bad blocks
  71.       If it is in there, return true, else return false...
  72.     */
  73.     struct    bad_block    *p;
  74.  
  75.     for( p = bad_block_list; p; p = p->next )
  76.         {
  77.         if ( p->key == block )
  78.             return( 1 );
  79.         }
  80.     return( 0 );
  81.     }
  82.  
  83.  
  84.  
  85. /*-----------------------------------------------------------------------------
  86. ------------------------------------------------------------------------------*/
  87. ULONG    get_next_avail_block()
  88.     {
  89.     /*
  90.       Just set next_avail_block to its successor unless we happen
  91.        to find it in the used block list. In that case, keep going
  92.       till we find a good/free block. 
  93.     */
  94.  
  95.     while ( block_already_bad( next_avail_block ) )
  96.         {
  97.         next_avail_block++;
  98.         } 
  99.  
  100.     return( next_avail_block++ );
  101.     }
  102.  
  103.  
  104. /*-----------------------------------------------------------------------------
  105. ------------------------------------------------------------------------------*/
  106. void    create_file_extension_block_list( blocks )
  107. int    blocks;
  108.     {
  109.     /* 
  110.       Create a linked list of file extension blocks...
  111.     */
  112.     int    i, blocks_left;
  113.     struct    file_ext_block    *p, *q;
  114.  
  115.     /*
  116.       calculate blocks_left for filling in the HighSeq field.
  117.     */
  118.     blocks_left = bad_blocks;
  119.  
  120.     for( i = 0, q = 0L; i < blocks; i++ )
  121.         {
  122.         blocks_left -= 72;
  123.  
  124.         if ( !(p = (struct file_ext_block *) calloc( sizeof( struct file_ext_block ), 1 ) ) )
  125.             {
  126.             df_exit( ENOMEM );
  127.             }
  128.  
  129.         if ( !fextb )
  130.             {
  131.             fextb     = p;
  132.             }
  133.         else    
  134.             {
  135.             q->next = p;
  136.             }
  137.  
  138.         p->next         = 0L;
  139.             p->key             = get_next_avail_block();
  140.         p->fhb.Type         = 16L;
  141.         p->fhb.OwnKey         = p->key;
  142.         p->fhb.SecondaryType     = -3L;
  143.         p->fhb.Parent          = (q) ? q->fhb.OwnKey : fh_key;
  144.         p->fhb.HighSeq         = (blocks_left > 72) ? 72 : blocks_left;
  145.         q            = p;
  146.         }
  147.     }
  148.  
  149.  
  150.  
  151. /*-----------------------------------------------------------------------------
  152. ------------------------------------------------------------------------------*/
  153. void    get_next_block_ptr( key )
  154. ULONG    key;
  155.     {
  156.     /*
  157.       Stick the key in the next slot we have in the header or
  158.       extension block, and update our next slot pointer.
  159.     */
  160.     static    int    fh_ptr = 71, eblock_ptr = 71;
  161.     static    struct    file_ext_block    *p = 0L;
  162.  
  163.     if ( !p )
  164.         {
  165.         fb.DataBlocks[fh_ptr--] = key;
  166.         if ( fh_ptr < 0 )
  167.             {
  168.             p = fextb;
  169.             fb.Extension = p->key;
  170.             }
  171.         }
  172.     else
  173.         {
  174.         p->fhb.DataBlocks[eblock_ptr--] = key;
  175.         if ( eblock_ptr < 0 )
  176.             {
  177.             p->fhb.Extension = p->next->key;
  178.             p = p->next;
  179.             eblock_ptr = 71;
  180.             }
  181.         }
  182.     }
  183.  
  184.  
  185.  
  186. /*-----------------------------------------------------------------------------
  187. ------------------------------------------------------------------------------*/
  188. int    hash_file_name( name )
  189. char    *name;
  190.     {
  191.     /*
  192.       Hash the file name to an address suitable for the root block.
  193.       I got this out of a CATs newsletter on the FFS. It does not
  194.       work, so I fudge the hash value for bad.blocks later...
  195.     */
  196.     int     i, val;
  197.  
  198.     val = sizeof( name ) - 1;
  199.     for( i = 0; *name; i++ )
  200.         val = (( val * 13 ) + toupper( *name++ )) & 0x7ff;
  201.  
  202.     return( val % 72 );
  203.     }
  204.  
  205. /*-----------------------------------------------------------------------------
  206. ------------------------------------------------------------------------------*/
  207. void    initialize_header_block( my_key )
  208. ULONG    my_key;
  209.     {
  210.     /*
  211.       Initialize the needed fields in the file header block prior to
  212.       writing it to the disk.
  213.     */
  214.     int    i;
  215.     ULONG    chksum;
  216.     long    *p;
  217.     
  218.     fb.Type        = 2L;
  219.     fb.OwnKey    = my_key;
  220.     fb.Parent    = dp.root_key;
  221.     fb.Protect    = 15L;
  222.  
  223.     /*
  224.         If we have extension blocks, set fb.HighSeq to 72, else
  225.       set it to bad_blocks;
  226.     */
  227.     fb.HighSeq    = (fextb) ? 72 : bad_blocks;
  228.  
  229.     fb.FirstBlock    = bad_block_list->key;
  230.     movmem( (char *) &rb.DiskMade, (char *) &fb.Date, 12);
  231.  
  232.     fb.FileName[0] = sizeof( bb_name ) - 1;
  233.     strcpy( &fb.FileName[1], bb_name );
  234.     fb.SecondaryType = -3L;
  235.  
  236.     /*
  237.        Calculate the checksum for this block.
  238.     */
  239.     for( i = 0, chksum = 0, p = (long *) &fb; i < (sizeof( fb )/4); i++ )
  240.         {
  241.         chksum += *p++;
  242.         }
  243.     fb.Checksum = -chksum;
  244.     }
  245.  
  246.  
  247. /*-----------------------------------------------------------------------------
  248. ------------------------------------------------------------------------------*/
  249. void    update_bad_blocks()
  250.     {
  251.     printf( "Sorry, not implemented yet...\n" );
  252.     }
  253.  
  254.  
  255. /*-----------------------------------------------------------------------------
  256. ------------------------------------------------------------------------------*/
  257. void    print_bad_blocks()
  258.     {
  259.     printf( "Sorry, not implemented yet...\n" );
  260.     }
  261.  
  262. /*-----------------------------------------------------------------------------
  263. ------------------------------------------------------------------------------*/
  264. void    create_bad_block_file()
  265.     {
  266.     /*
  267.       Create the header and attach the blocks to the bad.block file.
  268.     */
  269.     int    ext_blocks_needed, i;
  270.     struct    bad_block    *p;
  271.     struct    file_ext_block    *q;
  272.     long            chksum, *tmp;
  273.  
  274.  
  275.     /*
  276.        Set next_avail block to dp.lower_key, because this is where
  277.       we are going to write the file header.
  278.     */
  279.     next_avail_block = dp.lower_key;
  280.  
  281.  
  282.     /*
  283.       Use the first available block for the File header...
  284.     */
  285.     fh_key = get_next_avail_block();
  286.  
  287.  
  288.     /*
  289.       Calculate number of extension blocks needed for bad block file.
  290.       bad_blocks contains the number of blocks in the bad_block_list,
  291.       and since a FileHeaderBlock can only hold 72 entries, we will 
  292.       need bad_blocks / 72 extension blocks.
  293.     */
  294.     ext_blocks_needed = (bad_blocks / 72) - 1;
  295.     if ( (bad_blocks % 72) != 0 )
  296.         ext_blocks_needed++;
  297.  
  298.  
  299.     /*
  300.       Create the extension block list if we need it.
  301.     */
  302.     if ( ext_blocks_needed )
  303.         create_file_extension_block_list( ext_blocks_needed );
  304.  
  305.  
  306.     /*
  307.       For every block in the used block list, stick its key
  308.       in either the fileheader or extension block.
  309.     */
  310.     for( p = bad_block_list; p; p = p->next )
  311.         {
  312.         get_next_block_ptr( p->key );
  313.         }
  314.  
  315.  
  316.     /*
  317.       Initialize the rest of the fields in the FileHeader block,
  318.       then write this baby to the disk!
  319.     */
  320.     initialize_header_block( fh_key );
  321.  
  322.     movmem( (char *) &fb, dsk_buf, sizeof( fb ) );
  323.     if ( !write_blocks( fh_key, 1 ) )
  324.         {
  325.         df_exit( ENOHDR );
  326.         }
  327.  
  328.     /*
  329.       Update the root block with the address of this file header
  330.       block. We would normally hash it, but our hash function does
  331.       not work. Once again, we will cheat!!!
  332.     */
  333.     rb.HashTable[21] = fh_key;
  334.  
  335.  
  336.     /*
  337.       Complete and write the file extension blocks to the disk.
  338.     */
  339.     for ( q = fextb; q; q = q->next )
  340.         {
  341.         /*
  342.            Calculate the checksum for this block.
  343.         */
  344.         for( i = 0, chksum = 0, tmp = (long *) &(q->fhb); i < 128; i++ )
  345.             {
  346.             chksum += *tmp++;
  347.             }
  348.         q->fhb.Checksum = -chksum;
  349.     
  350.         movmem( (char *) &(q->fhb), dsk_buf, 512);
  351.  
  352.         if ( !write_blocks( q->key, 1 ) )
  353.             {
  354.             df_exit( ENEXTB );
  355.             }
  356.  
  357.  
  358.         }
  359.     
  360.     }
  361.