home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / 2b_recoverrdb_src / recoverrdb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-13  |  9.3 KB  |  330 lines

  1. /*  RecoverRDB ver. 1.11 (27.07.97)
  2.     Copyright (C) 1997  Karol Bryd (kbryd@femina.com.pl)
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*
  20.  06.06.98 - added Mac partitions
  21.  02.01.99 - cleand up the code fo distribution and fixed one bug
  22.             that caused that block number of RDB wasn't remebered...
  23. */
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28.  
  29. #ifdef __GNUC__
  30. #include <inline/dos.h>
  31. #include <inline/exec.h>
  32. #else
  33. #include <proto/dos.h>
  34. #include <proto/exec.h>
  35. #endif
  36.  
  37. #include <exec/memory.h>
  38. #include <exec/types.h>
  39. #include <exec/io.h>
  40. #include <dos/rdargs.h>
  41. #include <devices/hardblocks.h>
  42.  
  43. static char verstr[] = "$VER: 2b_RecoverRDB 1.11 (06.06.98) BLABLA PRODUCT";
  44. static char twistr[] = "THE OWLS ARE NOT WHAT THEY SEEM";
  45.  
  46. struct IOStdReq *ioreq = NULL;
  47. struct MsgPort *msgport = NULL;
  48.  
  49. long unit = 1,
  50.   result,
  51.   totalcyls = 0,
  52.   partnum = 0,
  53.   Unit = 0,
  54.   StartCyl = 0,
  55.   EndCyl = 0,
  56.   Progress = FALSE,
  57.   args[] = {0, 0, 0, 0, 0},
  58.   blockspercyl;
  59.  
  60. UBYTE *buf;
  61. UBYTE *smallbuf;
  62.  
  63. char DevName[50];
  64.  
  65. /* Partition info structure, it holds informatons about all possible
  66. ** partitions, I think that 50 partitions will be sufficent...
  67. */
  68.  
  69. struct PartInfo
  70. {
  71.     long startcyl[100];
  72.     long endcyl;
  73.     long startblock[100];
  74.     long endblock;
  75. } partitions[50];
  76.  
  77. /* Very simplified structure of root block - the most important are
  78. ** first and last longwords.
  79. */
  80. struct Root
  81. {
  82.     long id;
  83.     long rubbish[126];
  84.     long secid;
  85. };
  86.  
  87. /* Clean up function */
  88. void
  89. closeres (char *errorstr)
  90. {
  91.     if(smallbuf)
  92.         FreeVec (smallbuf);
  93.     if(buf)
  94.         FreeVec (buf);
  95.     if (strlen (errorstr) > 0)
  96.         Printf ("%s\n", errorstr);
  97.     if (ioreq)
  98.         DeleteStdIO (ioreq);
  99.     if (msgport)
  100.         DeletePort (msgport);
  101.     exit (0);
  102. }
  103.  
  104. /* read one block from a given offset */
  105. int
  106. readscsi (UBYTE * buff, ULONG offset)
  107. {
  108.     ioreq->io_Command = CMD_READ;
  109.     ioreq->io_Offset = offset * 512;
  110.     ioreq->io_Length = 512;
  111.     ioreq->io_Data = buff;
  112.     ioreq->io_Flags = IOF_QUICK;
  113.     if (DoIO ((struct IORequest *) ioreq))
  114.     {
  115.         Printf ("Error #%ld\n", ioreq->io_Error);
  116.         return (-1);
  117.     }
  118.     return (1);
  119. }
  120.  
  121. /* main function */
  122. int
  123. doit (void)
  124. {
  125.     register long blocknum = 0,
  126.       bootblocks = 0,
  127.       a,
  128.       counter = 0,
  129.       memblock;
  130.     long id,
  131.       numblocks,
  132.       lastcounter;
  133.     int blocknumber = 0,
  134.       toprocess = 0;
  135.     struct RigidDiskBlock *rdb;
  136.     struct Root *root;
  137.     BOOL inpart = FALSE;
  138.  
  139.     /* we are going to read 250 blocks at once to speed up the process */
  140.     buf = AllocVec (250 * 512, MEMF_CHIP);
  141.     if(!buf)
  142.         return(-1);
  143.     smallbuf = AllocVec (512, MEMF_CHIP);
  144.     if(!smallbuf)
  145.         return(-1);
  146.  
  147.     /* read RDB block */
  148.     readscsi (buf, 0);
  149.     rdb = (struct RigidDiskBlock *) buf;
  150.  
  151.     /* if RDB isn't at block #0 then search through first 16 blocks */
  152.     if (rdb->rdb_ID != IDNAME_RIGIDDISK)
  153.     {
  154.         for (; rdb->rdb_ID != IDNAME_RIGIDDISK && blocknum <= 16; ++blocknum)
  155.         {
  156.             readscsi (buf, blocknum);
  157.             rdb = (struct RigidDiskBlock *) buf;
  158.         }
  159.     }
  160.     if (rdb->rdb_ID != IDNAME_RIGIDDISK)
  161.     {
  162.         Printf("ALERT! No Rigid Disk Block!!!\n");
  163.         return(-1);
  164.     }
  165.  
  166.     /* get some constants */
  167.     numblocks = rdb->rdb_CylBlocks * rdb->rdb_Cylinders;
  168.     totalcyls = rdb->rdb_Cylinders;
  169.     blockspercyl = rdb->rdb_CylBlocks;
  170.     partnum = 0;
  171.  
  172.     /* and setup IORequest structure */
  173.     ioreq->io_Command = CMD_READ;
  174.     ioreq->io_Length = 250 * 512;
  175.     ioreq->io_Data = buf;
  176.     ioreq->io_Flags = IOF_QUICK;
  177.     if (EndCyl == 0)
  178.         EndCyl = rdb->rdb_Cylinders;
  179.  
  180.     for (lastcounter = counter = blocknum = StartCyl * blockspercyl; blocknum < EndCyl * blockspercyl; blocknum++, counter++)
  181.     {
  182.       again:
  183.         /* a simple progress indicator */
  184.         if (lastcounter < counter - 5000 && Progress)
  185.         {
  186.             Printf ("Blocknum: %ld (of %ld)\r", blocknum, numblocks);
  187.             lastcounter = counter;
  188.         }
  189.  
  190.         ioreq->io_Command = CMD_READ;
  191.         if (blocknum + 250 >= numblocks)
  192.         {
  193.             /* special case for last read (ie. there are less than 250 blocks to read) */
  194.             ioreq->io_Length = (numblocks - blocknum - 1) * 512;
  195.             toprocess = numblocks - blocknum - 1;
  196.         }
  197.         else
  198.         {
  199.             /* or read all of them */
  200.             ioreq->io_Length = 250 * 512;
  201.             toprocess = 250;
  202.         }
  203.         ioreq->io_Data = buf;
  204.         ioreq->io_Flags = IOF_QUICK;
  205.         ioreq->io_Offset = blocknum * 512;
  206.         DoIO ((struct IORequest *) ioreq);
  207.  
  208.         /* now, scan what we have just read */
  209.         for (blocknumber = 0, memblock = 0; memblock < toprocess; memblock++)
  210.         {
  211.             /* get ID of block */
  212.             memcpy (&id, buf + blocknumber, 4);
  213.             root = (struct Root *) (buf + blocknumber);
  214.             id = id & 0xffffff00;
  215.  
  216.             /* and compare it to known constants */
  217.             if (id == (ID_DOS_DISK & 0xffffff00) || id == (ID_NOT_REALLY_DOS & 0xffffff00))
  218.             {
  219.                 /* if this is a bootblock of a partition then remember
  220.                    the block number
  221.                 */
  222.                 inpart = TRUE;
  223.                 partitions[partnum].startblock[bootblocks++] = blocknum;
  224.             }
  225.             if (CheckSignal (SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  226.             {
  227.                 Printf ("User abort...\n");
  228.                 goto end;
  229.             }
  230.             /* in case of root block check which one of before remembered bootblocks
  231.                match this root block, since root block lays right in the middle
  232.                of partition I simply read block with number:
  233.  
  234.                (2 * actual block number) - first block of partition
  235.  
  236.                and check it's ID, if ID of this block will be ID
  237.                of a bootblock then it means that we have found a valid partition
  238.             */
  239.             if (root->id == 2 && root->secid == 1)
  240.             {
  241.                 for (a = 0; a < bootblocks; a++)
  242.                 {
  243.                     readscsi (smallbuf, (blocknum * 2) - partitions[partnum].startblock[a]);
  244.                     memcpy (&id, smallbuf, 4);
  245.                     id = id & 0xffffff00;
  246.                     if (id == (ID_DOS_DISK & 0xffffff00) || id == (ID_NOT_REALLY_DOS & 0xffffff00) || id == 0x4c4b6000)
  247.                     {
  248.                         /* we have found a valid partition */
  249.                         blocknum = (blocknum * 2) - partitions[partnum].startblock[a] - 1;
  250.                         Printf ("Partiton found at cylinder:%ld, end cylinder:%ld\n", partitions[partnum].startblock[a] / blockspercyl, (blocknum) / blockspercyl);
  251.                         inpart = FALSE;
  252.                         partnum++;
  253.                         bootblocks = 0;
  254.                         blocknumber = 0;
  255.                         goto again;
  256.                     }
  257.                 }
  258.             }
  259.             blocknum++;
  260.             counter = blocknum;
  261.             blocknumber += 512;
  262.         }
  263.     }
  264.   end:
  265.   return(0);
  266. }
  267.  
  268. int
  269. main (int argc, char *argv[])
  270. {
  271.     struct RDArgs *rdargs;
  272.  
  273.     rdargs = (struct RDArgs *) ReadArgs ("DEVICE/A,UNIT/K/N/A,STARTCYL=SC/K/N,ENDCYL=EC/K/N,PROGRESS/S", args, NULL);
  274.     if (!rdargs)
  275.     {
  276.         PrintFault (IoErr (), argv[0]);
  277.         exit (10);
  278.     }
  279.     if (strlen ((STRPTR) args[0]) > 0)
  280.         strcpy (DevName, (STRPTR) args[0]);
  281.  
  282.     if (args[1])
  283.         Unit = *(LONG *) args[1];
  284.     if (args[2])
  285.         StartCyl = *(LONG *) args[2];
  286.     if (args[3])
  287.         EndCyl = *(LONG *) args[3];
  288.     if (args[4])
  289.         Progress = TRUE;
  290.  
  291.     FreeArgs (rdargs);
  292.  
  293.     printf("RecoverRDB v1.11, Copyright (C) 1997/98/99 Karol Bryd\n"
  294.      "RecoverRDB comes with ABSOLUTELY NO WARRANTY.\n"
  295.      "This is free software, and you are welcome to redistribute\n"
  296.      "it under certain conditions, see COPYING file for details.\n");
  297.  
  298.     if (EndCyl <= StartCyl && EndCyl)
  299.         closeres ("End Cyl MUST BE higher than StartCyl\n");
  300.  
  301.     if (msgport = (struct MsgPort *) CreatePort (NULL, NULL))
  302.     {
  303.         if (ioreq = (struct IOStdReq *) CreateStdIO (msgport))
  304.         {
  305.             if (!(result = OpenDevice (DevName, Unit, (struct IORequest *) ioreq, 0)))
  306.             {
  307.                 if(doit () < 0)
  308.                 {
  309.                     CloseDevice ((struct IORequest *) ioreq);
  310.                     closeres ("Aborting...\n");
  311.                 }
  312.                 else
  313.                 {
  314.                     CloseDevice ((struct IORequest *) ioreq);
  315.                     closeres ("All done...\n");
  316.                 }
  317.             }
  318.             else
  319.             {
  320.                 Printf ("Error while opening device:#%ld", result);
  321.                 closeres (" ");
  322.             }
  323.         }
  324.         else
  325.             closeres ("Could not create stdio\n");
  326.     }
  327.     else
  328.         closeres ("Could not create port\n");
  329. }
  330.