home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 408.lha / DeadAlloc / Deadalloc.c < prev    next >
C/C++ Source or Header  |  1990-09-02  |  11KB  |  435 lines

  1. /*
  2.  *  deadalloc.c   Dead track allocator.
  3.  *  (c)Tim MacKenzie .
  4.  *
  5.  *  This program is freely redistributable. It may be modified, hacked and
  6.  *  mutilated as long as this is not for profit, this message must also
  7.  *  remain with it.
  8.  *
  9.  *  Begun:  17/6/90
  10.  *  History:
  11.  *              v1.0: Allocates dead blocks only.
  12.  *              v1.1: Creates file with dead blocks in it.
  13.  *              v1.2: Checks every block instead of just the first on a track
  14.  *              v1.21: Repaired some bugs in 1.2.
  15.  *              v1.22: Doesnt include blocks 0 and 1 in file list.
  16.  *                v1.23: Now doesn't write new bitmap if reallocating blocks.
  17.  */
  18.  
  19. #define REV "v1.23"
  20. #define DATE "13/8/90"
  21.  
  22. #include <devices/trackdisk.h>
  23. /* This should include lots of things with it (I hope) */
  24. #include <exec/memory.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <proto/exec.h>
  28. #include <proto/dos.h>
  29. /* Works with DICE */
  30. /* Need open_lib's with Aztec or Lattice */
  31.  
  32. struct Task *my_task;
  33. struct MsgPort port;
  34. struct IOStdReq req;
  35. UBYTE *m_data;  /* Sector buffer */
  36. char drive=1; /* Which drive to access */
  37. char error_list[160];
  38. long bitblock;
  39. char n_opt;
  40. char doubly_alloc=0;
  41. /* This flag gets set if a track is already allocated and is dead */
  42.  
  43. struct file_head {
  44.     long type;
  45.     long key;
  46.     long num_block;
  47.     long dat_size;
  48.     long first;
  49.     long sum;
  50.     long blocks[72];
  51.     long res[2];
  52.     long prot;
  53.     long size;
  54.     char comment[92];
  55.     long date[3];
  56.     char name[64];
  57.     long hash;
  58.     long parent;
  59.     long extens;
  60.     long sec;
  61. } head;
  62.  
  63. close_all()
  64. {/* Closes anything that was opened in open_all()
  65.   */
  66.     printf("\x9b\x20\x70\x9b0;31\x6d");
  67.      /* Back to normal */
  68.     read_track(0);
  69.     FreeMem(m_data,512);
  70.     CloseDevice(&req);
  71.     RemPort(&port);
  72.     exit(0);
  73. }
  74.  
  75. chkabort()
  76. {/*  Dont let anyone take control away from me!*/
  77. }
  78.  
  79. open_all()
  80. {/* This opens the trackdisk device and assoc stuff.
  81.   */
  82.     m_data=AllocMem(512,MEMF_CHIP);
  83.     if (!m_data) {
  84.         printf("Cant get 512 bytes (What is happening to my world?)\n");
  85.         exit();
  86.     }
  87.     my_task=FindTask(0L);  /* Find my task! */
  88.     port.mp_SigTask=my_task;
  89.     AddPort(&port);
  90.     if(OpenDevice(TD_NAME,(long)drive,&req,0L)) {
  91.         printf("Couldn't open %s. exiting.\n",TD_NAME);
  92.         exit();
  93.     }
  94.     req.io_Message.mn_ReplyPort=&port;
  95.     req.io_Command=CMD_READ;
  96.     req.io_Data=m_data;
  97.     req.io_Length=TD_SECTOR;
  98. }
  99.  
  100.  
  101. read_track(track)
  102. int track;
  103. {/* Reads the track specified into the buffer.
  104.   */
  105.     int error;
  106.     req.io_Command=CMD_READ;
  107.     req.io_Length=TD_SECTOR;
  108.     req.io_Offset= track *512;
  109.     req.io_Data=m_data;
  110.     error=DoIO(&req);
  111.     req.io_Command=TD_MOTOR;
  112.     req.io_Length=0;
  113.     DoIO(&req); /* Turn motor off */
  114.     return(error);
  115. }
  116.  
  117. write_track(track)
  118. long track;
  119. {/* Writes the track specified into the buffer.
  120.   */
  121.     long error;
  122.     req.io_Command=CMD_WRITE;
  123.     req.io_Length=TD_SECTOR;
  124.     req.io_Offset= track *512;
  125.     req.io_Data=m_data;
  126.     error=DoIO(&req);
  127.     req.io_Command=TD_MOTOR;
  128.     req.io_Length=0;
  129.     DoIO(&req); /* Turn motor off */
  130.     return(error);
  131. }
  132.  
  133. display_err(err)
  134. int err;
  135. {/* Displays the error number and interpretation.
  136.   */
  137.     static char *msgs[]={
  138.         "Not Specified",
  139.         "No sector header",
  140.         "Bad Sector Preamble",
  141.         "Bad Sector ID",
  142.         "Bad Header sum",
  143.         "Bad Sector sum",
  144.         "Too Few Sectors",
  145.         "Bad Sector Header",
  146.         "Write Protected",
  147.         "Disk Changed",
  148.         "Seek error",
  149.         "No Memory",
  150.         "Bad Unit Number",
  151.         "Bad Drive Type",
  152.         "Drive in use",
  153.         "Post Reset"
  154.     };
  155.     printf("Error %ld: %s\n",err,msgs[err-20]);
  156. }
  157.  
  158. check_disk()
  159. {/* This routine checks the disk for errors and fills up the error_list array
  160.   */
  161.     long i;
  162.     long err;
  163.     int count;
  164.     req.io_Command=CMD_READ;
  165.     req.io_Length=512;
  166.     count=0;
  167.     printf("\x9b\x30\x20\x70");
  168.     for (i=0;i<160;i++) {
  169.         long j;
  170.         printf("Track %d.\n",i);
  171.         printf("\x9b\x41");
  172.         for (j=0;j<11;j++) {
  173.             req.io_Offset=(i*11 +j)*512;
  174.             err=DoIO(&req);
  175.             if (err) {
  176.                 printf("Track %d: ",i);
  177.                 display_err(err);
  178.                 error_list[i]=1;
  179.                 count++;
  180.                 break;
  181.             }
  182.         }
  183.     }
  184.     printf("\x9b\x20\x70");
  185.     printf("Check complete. %d errors.\n",count);
  186.     req.io_Command=TD_MOTOR;
  187.     req.io_Length=0;
  188.     DoIO(&req);
  189.     return(count);
  190. }
  191.  
  192. warn(bit)
  193. int bit;
  194. {
  195.     ULONG *dat;
  196.     ULONG block;
  197.     long err;
  198.     printf("Warning: block %d is allocated\n",bit);
  199.      doubly_alloc=1;
  200. }
  201.  
  202.  
  203. dead_alloc()
  204. {/* This is the bit that allocates the dead blocks.
  205.   */
  206.     int i,j;
  207.     ULONG sum;
  208.     long bit,err;
  209.     err=read_track(bitblock);
  210.     if (err) {
  211.         display_err(err);
  212.         printf("The bitmap block has an error... quitting \n");
  213.         return;
  214.     }
  215.     for (i=0;i<160;i++) {
  216.         if (error_list[i]) {
  217.             for (j=0;j<11;j++) {
  218.                bit=32+ i*11 +j -2;
  219.                if (bit>=32) {
  220.                    if (!(((ULONG *)m_data)[bit/32] & (1<<(bit%32)))) warn(bit);
  221.                    ((ULONG *)m_data)[bit/32] = (((ULONG *)m_data)[bit/32]) & ~((ULONG)1 << (bit%32));
  222.                 }
  223.             }
  224.         }
  225.     }
  226.     fix_bit_sum(m_data);
  227.     do {
  228.         err=write_track(bitblock);
  229.         if (err) {
  230.             char c;
  231.             printf("Error writing bitblock: ");
  232.             display_err(err);
  233.             printf("Retry? ");
  234.             fflush(stdout);
  235.             scanf("%c",&c);
  236.             if (!(c=='y' || c=='Y')) err=0;
  237.         }
  238.     } while (err);
  239. }
  240.  
  241. fix_bit_sum(dat)
  242. ULONG *dat;
  243. {
  244.     ULONG sum,i;
  245.     sum=0;
  246.     for (i=1;i<128;i++)
  247.         sum= sum+((ULONG *)dat)[i];
  248.     ((ULONG *)dat)[0] = -sum;
  249. }
  250.  
  251. fix_block_sum(dat)
  252. ULONG *dat;
  253. {
  254.     ULONG sum,i;
  255.     sum=0;
  256.     for (i=0;i<128;i++)
  257.         if (i!=5)
  258.             sum= sum+((ULONG *)dat)[i];
  259.     ((ULONG *)dat)[5] = -sum;
  260. }
  261.  
  262. long
  263. find_free()
  264. {/* Finds a free block, allocates it and returns it's address.
  265.   */
  266.     long i,j,i1,j1;
  267.     long err;
  268.     err=read_track(bitblock);
  269.     if (err) return(0);
  270.     for (i1=880;i1<1760;i1++) {
  271.         j1=1760-i1;
  272.         i=i1+30;
  273.         j=j1+30;
  274.         if (((ULONG *)m_data)[i/32] & (1 << (i%32))) {
  275.             ((ULONG *)m_data)[i/32] = (((ULONG *)m_data)[i/32]) & ~((ULONG)1 << (i%32));
  276.             fix_bit_sum(m_data);
  277.             write_track(bitblock);
  278.             return(i1);
  279.         }
  280.         else if ((((ULONG *)m_data)[j/32] & (1 << (j%32))&&j>31)) {
  281.             ((ULONG *)m_data)[j/32] = (((ULONG *)m_data)[j/32]) & ~((ULONG)1 << (j%32));
  282.             fix_bit_sum(m_data);
  283.             write_track(bitblock);
  284.             return(j1);
  285.         }
  286.     }
  287. }
  288.  
  289. dead_file(count)
  290. long count;
  291. {/* This creates the file "...dead" in the root directory of the disk
  292.   * with the dead blocks in it.
  293.   */
  294.     long upto,err,which,howmany,next,i;
  295.         int lower;
  296.         if (error_list[0]==1) lower=2;
  297.         else lower=0;
  298.     if(!(which=find_free())) {
  299.         printf("Error allocating block for ...Dead file\n");
  300.         return;
  301.     }
  302.     head.type=2;
  303.     head.key=which;
  304.     head.prot=0x007;
  305.     strcpy(head.comment,"\x21 File for holding dead tracks in.");
  306.     strcpy(head.name,"\7...Dead");
  307.     head.parent=880;
  308.     head.sec=-3;
  309.     for (upto=0,howmany=0;upto<1760 && howmany<72;upto++)
  310.         if (error_list[upto/11] && upto>=2) {
  311.             head.blocks[71-howmany]=upto;
  312.             howmany++;
  313.         }
  314.     head.num_block=howmany-lower;
  315.     head.size=(count*11-lower)*488;
  316.     head.first=head.blocks[71];
  317.     read_track(880);
  318.     head.hash=((ULONG *)m_data)[61];
  319.     ((ULONG *)m_data)[61]=which;
  320.     /*                ^^  61 is the hash value for ...Dead . If you change
  321.      *  the name then you have to change the hash value.
  322.      */
  323.     fix_block_sum(m_data);
  324.     write_track(880);
  325.     next=0;
  326.     if (howmany==72) {
  327.         if(!(next=find_free())) {
  328.             printf("Error allocating block for ...Dead file\n");
  329.             return;
  330.         }
  331.         head.extens=next;
  332.     }
  333.     for (i=0;i<128;i++)
  334.         ((ULONG *)m_data)[i]=((ULONG *)&head)[i];
  335.     fix_block_sum(m_data);
  336.     write_track(which);
  337.     /* Here make extension blocks if number of blocks > 72 */
  338.     while (upto<1760) {
  339.         long next_ext;
  340.         next_ext=0;
  341.         head.type=0x10;
  342.         for (howmany=0;upto<1760 && howmany<72;upto++)
  343.             if (error_list[upto/11]) {
  344.                 head.blocks[71-howmany]=upto;
  345.                 howmany++;
  346.             }
  347.         for (i=howmany;i<72;i++)
  348.             head.blocks[71-i]=0;
  349.         head.num_block=howmany;
  350.         head.hash=0;
  351.         for (i=0;i<92;i++) head.comment[i]=0;
  352.         for (i=0;i<64;i++) head.name[i]=0;
  353.         head.prot=0;
  354.         head.size=0;
  355.         head.parent=which;
  356.         head.key=next;
  357.         head.first=0;
  358.         head.extens=0;
  359.         if (howmany==72) {
  360.             next_ext=find_free();
  361.             head.extens=next_ext;
  362.         }
  363.         for (i=0;i<128;i++)
  364.             ((ULONG *)m_data)[i]=((ULONG *)&head)[i];
  365.         fix_block_sum(m_data);
  366.         write_track(next);
  367.         next=next_ext;
  368.     }
  369. }
  370.  
  371. main(argc,argv)
  372. int argc;
  373. char *argv[];
  374. {
  375.     BPTR in;
  376.     int i,count;
  377.     int err,nofile;
  378.     nofile=0;
  379.     printf("\x9b33;4mDead track allocator %s.\x9b0;33m ) Tim MacKenzie %s.\x9b31m\n",REV,DATE);
  380.     for (i=1;i<argc;i++) {
  381.         if (argv[i][0]!='-' && argv[i][0]!='d') {
  382.             printf("Usage: %s [-m] [-n] [df?:] \n",argv[0]);
  383.             printf("    -m : Modify bitmap only. Dont add file\n");
  384.             printf("    -n : Allow reallocation of blocks\n");
  385.             printf("    df?: Set drive number (default is drive 1)\n");
  386.             exit(1);
  387.         }
  388.         if (argv[i][1]=='m') {nofile=1; continue;}
  389.         if (argv[i][1]=='n') {n_opt=1; continue;}
  390.         if (argv[i][1]=='f') {
  391.             drive=argv[i][2]-'0';
  392.             if (drive <0 || drive >4) {
  393.                 argv[i][0]='0';
  394.                 i--;
  395.                 continue;
  396.             }
  397.             continue;
  398.         }
  399.     }
  400.     if (!nofile) {
  401.         char name[12];
  402.         strcpy(name,"df1:...Dead");
  403.         name[2]='0'+drive;
  404.         in = Open(name,MODE_OLDFILE);
  405.         if (in) {
  406.             printf("File \"...Dead\" already exists on drive df%1d:.\n",drive);
  407.             printf("Change it's protection and delete it. Then retry\n");
  408.             Close(in);
  409.             exit();
  410.         }
  411.     }
  412.     open_all();
  413.     err=read_track(880);
  414.     if(err) {
  415.        display_err(err);
  416.        printf("Error reading root block. Quitting.\n");
  417.        close_all();
  418.     }
  419.     bitblock=((long *)m_data)[79];
  420.     printf("Volume: %s. Bitmap on %d.\n",&m_data[(108<<2)+1],bitblock);
  421.     count=check_disk();
  422.     if (count) {
  423.         dead_alloc();
  424.         if (!n_opt && doubly_alloc) {
  425.               printf("Some dead tracks are allocated to existing files.\n");
  426.               printf("Delete offending file/s or use -n option (dangerous!)\n");
  427.               close_all();
  428.         }
  429.         if (!nofile)
  430.             dead_file(count);
  431.         printf("Now remove the disk and reinsert it before using.\n");
  432.     }
  433.     close_all();
  434. }
  435.