/*
gcc -Wall -D_XOPEN_SOURCE=0600 -D_LARGEFILE64_SOURCE hddread.c

mknod /dev/rawctl c 162 0
mkdir /dev/raw
mknod /dev/raw/raw1 c 162 1


raw /dev/raw1 /dev/mojevadnapartition
*/
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//#define O_LARGEFILE    0100000 
#include <stdio.h>                   
#include <unistd.h>
#include <errno.h>
#include <linux/major.h> 
#include <string.h>
#include <stdlib.h>
    
#define SEC_SIZE 512
#define SEC_SKIP 5


int check_device(int fd,char *raw_name) {
int err;
struct stat statbuf;

	err = fstat(fd, &statbuf);
	if (err) {
		fprintf (stderr, "Cannot locate raw device '%s' (%s)\n",
			 raw_name, strerror(errno));
		return 1;
	}
	
	if (!S_ISCHR(statbuf.st_mode)) {
		fprintf (stderr, "raw device '%s' is not a character dev\n",
			 raw_name);
		return 1;
	}
	if (major(statbuf.st_rdev) != RAW_MAJOR) {
		fprintf (stderr, "Device '%s' is not a raw dev\n",
			 raw_name);
		return 1;
	}

return 0;
}

int do_copy(int from, int where) {
 
 char sec2[SEC_SIZE+1];
 char *sec;
 int count;
 int i;


sec = (char*)((((long)malloc(SEC_SIZE+SEC_SIZE-1))+SEC_SIZE-1)&~(SEC_SIZE-1));

// if ((posix_memalign(&sec, SEC_SIZE,SEC_SIZE+1))!=0) return 1;
 if (sec == NULL) return 1;
 memset(sec2,0x0,sizeof(sec2)); /* do blank sector */

    while(1) {

	if ((count=read(from,sec,SEC_SIZE))==SEC_SIZE) {
		printf("O"); /*sector we just read is OK*/
		write(where,sec,SEC_SIZE); /* write it*/
		fflush(stdout); /*make sure user get this */
	} else
	{
        if  (count==-1) 
	    { 
	    //printf ("%d\n",errno);
	    if (errno!=5) return errno;
	    }
	
	printf("F"); /* we failed to read the sector */
	fflush(stdout); /*make sure user get this */
	lseek(from,SEC_SKIP*SEC_SIZE,SEEK_CUR); /*skip SEC_SKIP sectors */
	for (i=0;i<SEC_SKIP;i++) write(where,sec2,SEC_SIZE);
	}

    }
 }
 
 int main (int argc,char **argv) {
 
 int from,where;
 
// char iq[] = "/dev/raw2";
// char oq[] = "data_home";


 if (argc>2) {
    
    from = open(argv[1], O_RDONLY|O_LARGEFILE);
    where = open(argv[2], O_RDWR|O_LARGEFILE|O_CREAT);
    
    if (check_device(from,argv[1])) exit(2);
    if (where<0) {
	fprintf(stderr,"Unable to create '%s' destination file\nGiving up.\n",argv[2]);
	exit(2);
    }
    printf ("Ret: %d\n",do_copy(from,where));
 } else
 {
 fprintf(stderr,"\nThis program will copy sectors from raw device and skip bad ones(zero fill)\n\n");
 fprintf(stderr,"Usage:   %s source destination\n",argv[0]);
 fprintf(stderr,"	  source must be raw device, destination can be file or device\n");
 fprintf(stderr,"Example: %s /dev/raw/raw2 my_rescued_data_file \n\n",argv[0]);
 fprintf(stderr,"See README for details\n"); 
 return 1;
 }
return 0; 
 }

 
