home *** CD-ROM | disk | FTP | other *** search
- /* RecoverRDB ver. 1.11 (27.07.97)
- Copyright (C) 1997 Karol Bryd (kbryd@femina.com.pl)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
- 06.06.98 - added Mac partitions
- 02.01.99 - cleand up the code fo distribution and fixed one bug
- that caused that block number of RDB wasn't remebered...
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef __GNUC__
- #include <inline/dos.h>
- #include <inline/exec.h>
- #else
- #include <proto/dos.h>
- #include <proto/exec.h>
- #endif
-
- #include <exec/memory.h>
- #include <exec/types.h>
- #include <exec/io.h>
- #include <dos/rdargs.h>
- #include <devices/hardblocks.h>
-
- static char verstr[] = "$VER: 2b_RecoverRDB 1.11 (06.06.98) BLABLA PRODUCT";
- static char twistr[] = "THE OWLS ARE NOT WHAT THEY SEEM";
-
- struct IOStdReq *ioreq = NULL;
- struct MsgPort *msgport = NULL;
-
- long unit = 1,
- result,
- totalcyls = 0,
- partnum = 0,
- Unit = 0,
- StartCyl = 0,
- EndCyl = 0,
- Progress = FALSE,
- args[] = {0, 0, 0, 0, 0},
- blockspercyl;
-
- UBYTE *buf;
- UBYTE *smallbuf;
-
- char DevName[50];
-
- /* Partition info structure, it holds informatons about all possible
- ** partitions, I think that 50 partitions will be sufficent...
- */
-
- struct PartInfo
- {
- long startcyl[100];
- long endcyl;
- long startblock[100];
- long endblock;
- } partitions[50];
-
- /* Very simplified structure of root block - the most important are
- ** first and last longwords.
- */
- struct Root
- {
- long id;
- long rubbish[126];
- long secid;
- };
-
- /* Clean up function */
- void
- closeres (char *errorstr)
- {
- if(smallbuf)
- FreeVec (smallbuf);
- if(buf)
- FreeVec (buf);
- if (strlen (errorstr) > 0)
- Printf ("%s\n", errorstr);
- if (ioreq)
- DeleteStdIO (ioreq);
- if (msgport)
- DeletePort (msgport);
- exit (0);
- }
-
- /* read one block from a given offset */
- int
- readscsi (UBYTE * buff, ULONG offset)
- {
- ioreq->io_Command = CMD_READ;
- ioreq->io_Offset = offset * 512;
- ioreq->io_Length = 512;
- ioreq->io_Data = buff;
- ioreq->io_Flags = IOF_QUICK;
- if (DoIO ((struct IORequest *) ioreq))
- {
- Printf ("Error #%ld\n", ioreq->io_Error);
- return (-1);
- }
- return (1);
- }
-
- /* main function */
- int
- doit (void)
- {
- register long blocknum = 0,
- bootblocks = 0,
- a,
- counter = 0,
- memblock;
- long id,
- numblocks,
- lastcounter;
- int blocknumber = 0,
- toprocess = 0;
- struct RigidDiskBlock *rdb;
- struct Root *root;
- BOOL inpart = FALSE;
-
- /* we are going to read 250 blocks at once to speed up the process */
- buf = AllocVec (250 * 512, MEMF_CHIP);
- if(!buf)
- return(-1);
- smallbuf = AllocVec (512, MEMF_CHIP);
- if(!smallbuf)
- return(-1);
-
- /* read RDB block */
- readscsi (buf, 0);
- rdb = (struct RigidDiskBlock *) buf;
-
- /* if RDB isn't at block #0 then search through first 16 blocks */
- if (rdb->rdb_ID != IDNAME_RIGIDDISK)
- {
- for (; rdb->rdb_ID != IDNAME_RIGIDDISK && blocknum <= 16; ++blocknum)
- {
- readscsi (buf, blocknum);
- rdb = (struct RigidDiskBlock *) buf;
- }
- }
- if (rdb->rdb_ID != IDNAME_RIGIDDISK)
- {
- Printf("ALERT! No Rigid Disk Block!!!\n");
- return(-1);
- }
-
- /* get some constants */
- numblocks = rdb->rdb_CylBlocks * rdb->rdb_Cylinders;
- totalcyls = rdb->rdb_Cylinders;
- blockspercyl = rdb->rdb_CylBlocks;
- partnum = 0;
-
- /* and setup IORequest structure */
- ioreq->io_Command = CMD_READ;
- ioreq->io_Length = 250 * 512;
- ioreq->io_Data = buf;
- ioreq->io_Flags = IOF_QUICK;
- if (EndCyl == 0)
- EndCyl = rdb->rdb_Cylinders;
-
- for (lastcounter = counter = blocknum = StartCyl * blockspercyl; blocknum < EndCyl * blockspercyl; blocknum++, counter++)
- {
- again:
- /* a simple progress indicator */
- if (lastcounter < counter - 5000 && Progress)
- {
- Printf ("Blocknum: %ld (of %ld)\r", blocknum, numblocks);
- lastcounter = counter;
- }
-
- ioreq->io_Command = CMD_READ;
- if (blocknum + 250 >= numblocks)
- {
- /* special case for last read (ie. there are less than 250 blocks to read) */
- ioreq->io_Length = (numblocks - blocknum - 1) * 512;
- toprocess = numblocks - blocknum - 1;
- }
- else
- {
- /* or read all of them */
- ioreq->io_Length = 250 * 512;
- toprocess = 250;
- }
- ioreq->io_Data = buf;
- ioreq->io_Flags = IOF_QUICK;
- ioreq->io_Offset = blocknum * 512;
- DoIO ((struct IORequest *) ioreq);
-
- /* now, scan what we have just read */
- for (blocknumber = 0, memblock = 0; memblock < toprocess; memblock++)
- {
- /* get ID of block */
- memcpy (&id, buf + blocknumber, 4);
- root = (struct Root *) (buf + blocknumber);
- id = id & 0xffffff00;
-
- /* and compare it to known constants */
- if (id == (ID_DOS_DISK & 0xffffff00) || id == (ID_NOT_REALLY_DOS & 0xffffff00))
- {
- /* if this is a bootblock of a partition then remember
- the block number
- */
- inpart = TRUE;
- partitions[partnum].startblock[bootblocks++] = blocknum;
- }
- if (CheckSignal (SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
- {
- Printf ("User abort...\n");
- goto end;
- }
- /* in case of root block check which one of before remembered bootblocks
- match this root block, since root block lays right in the middle
- of partition I simply read block with number:
-
- (2 * actual block number) - first block of partition
-
- and check it's ID, if ID of this block will be ID
- of a bootblock then it means that we have found a valid partition
- */
- if (root->id == 2 && root->secid == 1)
- {
- for (a = 0; a < bootblocks; a++)
- {
- readscsi (smallbuf, (blocknum * 2) - partitions[partnum].startblock[a]);
- memcpy (&id, smallbuf, 4);
- id = id & 0xffffff00;
- if (id == (ID_DOS_DISK & 0xffffff00) || id == (ID_NOT_REALLY_DOS & 0xffffff00) || id == 0x4c4b6000)
- {
- /* we have found a valid partition */
- blocknum = (blocknum * 2) - partitions[partnum].startblock[a] - 1;
- Printf ("Partiton found at cylinder:%ld, end cylinder:%ld\n", partitions[partnum].startblock[a] / blockspercyl, (blocknum) / blockspercyl);
- inpart = FALSE;
- partnum++;
- bootblocks = 0;
- blocknumber = 0;
- goto again;
- }
- }
- }
- blocknum++;
- counter = blocknum;
- blocknumber += 512;
- }
- }
- end:
- return(0);
- }
-
- int
- main (int argc, char *argv[])
- {
- struct RDArgs *rdargs;
-
- rdargs = (struct RDArgs *) ReadArgs ("DEVICE/A,UNIT/K/N/A,STARTCYL=SC/K/N,ENDCYL=EC/K/N,PROGRESS/S", args, NULL);
- if (!rdargs)
- {
- PrintFault (IoErr (), argv[0]);
- exit (10);
- }
- if (strlen ((STRPTR) args[0]) > 0)
- strcpy (DevName, (STRPTR) args[0]);
-
- if (args[1])
- Unit = *(LONG *) args[1];
- if (args[2])
- StartCyl = *(LONG *) args[2];
- if (args[3])
- EndCyl = *(LONG *) args[3];
- if (args[4])
- Progress = TRUE;
-
- FreeArgs (rdargs);
-
- printf("RecoverRDB v1.11, Copyright (C) 1997/98/99 Karol Bryd\n"
- "RecoverRDB comes with ABSOLUTELY NO WARRANTY.\n"
- "This is free software, and you are welcome to redistribute\n"
- "it under certain conditions, see COPYING file for details.\n");
-
- if (EndCyl <= StartCyl && EndCyl)
- closeres ("End Cyl MUST BE higher than StartCyl\n");
-
- if (msgport = (struct MsgPort *) CreatePort (NULL, NULL))
- {
- if (ioreq = (struct IOStdReq *) CreateStdIO (msgport))
- {
- if (!(result = OpenDevice (DevName, Unit, (struct IORequest *) ioreq, 0)))
- {
- if(doit () < 0)
- {
- CloseDevice ((struct IORequest *) ioreq);
- closeres ("Aborting...\n");
- }
- else
- {
- CloseDevice ((struct IORequest *) ioreq);
- closeres ("All done...\n");
- }
- }
- else
- {
- Printf ("Error while opening device:#%ld", result);
- closeres (" ");
- }
- }
- else
- closeres ("Could not create stdio\n");
- }
- else
- closeres ("Could not create port\n");
- }
-