ddscratch/main.c

208 lines
4.4 KiB
C

#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
char devpath[FILENAME_MAX];
char targetpath[FILENAME_MAX];
char mapfile[FILENAME_MAX];
int firstSector = -1;
long offset = -1;
int cntSectors = -1;
int sectSize = 4096;
long devSectorCount = -1;
char *map;
int cntReadSectors = 0;
void printUsage();
int loadScratchMap(char *filename, int size, char *map);
int saveScratchMap(char *filename, int size, char *map);
int scratch(int dev, int image,int firstSector, int cntSectors, int sectSize);
int main(int argc, char **argv) {
int ch;
while ((ch = getopt(argc, argv, "o:c:s:h")) != -1){
switch (ch){
case 'o':
offset = strtol(optarg, NULL, 0);
break;
case 'b':
firstSector = strtol(optarg, NULL, 0);
break;
case 'c':
cntSectors = strtol(optarg, NULL, 0);
break;
case 's':
sectSize = strtol(optarg, NULL, 0);
break;
case 'm':
strncpy(mapfile, optarg, sizeof(mapfile));
break;
case 'h':
printUsage();
return 0;
}
}
if (optind != (argc-2)){
printUsage();
printf("need device and target!\n");
return -1;
}
strncpy(devpath, argv[optind], sizeof(devpath));
strncpy(targetpath, argv[optind+1], sizeof(targetpath));
if (!mapfile[0])
snprintf(mapfile, sizeof(mapfile), "%s.scratchmap", targetpath);
if ((offset != -1) && (firstSector != -1)){
printUsage();
printf("only first sector OR offset may be given!\n");
}
if (offset != -1)
firstSector = (int)(offset / sectSize);
if (firstSector == -1)
firstSector = 0;
int dev = open(devpath, O_RDONLY | O_SYNC);
if (dev == -1){
printf("could not open device %s\n", devpath);
return -2;
}
long devsize = lseek(dev, 0, SEEK_END);
devSectorCount = (devsize / sectSize);
if (cntSectors == -1)
cntSectors = (int)(devsize / sectSize);
int target = open(targetpath, O_RDWR | O_CREAT);
if (target == -1){
printf("could not open target image %s\n", targetpath);
close(dev);
return -3;
}
map = malloc(devSectorCount);
if (!map){
printf("failed to allocate in memory map\n");
close(target);
close(dev);
return -4;
}
printf("target (image file): %s\n", targetpath);
printf("device: %s\n", devpath);
printf("sector size: %i\n", sectSize);
printf("offset: 0x%08lx\n", ((long)firstSector * sectSize));
printf("first sector: %i\n", firstSector);
printf("sectors: %i\n", cntSectors);
memset( map, 0x00, devSectorCount );
loadScratchMap( mapfile, devSectorCount, map);
scratch(dev, target, firstSector, cntSectors, sectSize );
saveScratchMap( mapfile, devSectorCount, map);
close(target);
close(dev);
return 0;
}
int scratch(int dev, int image,int firstSector, int cntSectors, int sectSize){
char p[sectSize];
for (int try = 0; try < 16; try ++){
for (int sect = firstSector; sect < (firstSector + cntSectors); sect++){
long offset = (long)sect * sectSize;
printf("\r#%08i 0x%08lX %i (%i rescued / %i to go)", sect, offset, try, cntReadSectors, (cntSectors - cntReadSectors));
fflush(stdout);
if (map[sect])
continue;
if (lseek(dev, offset, SEEK_SET) != offset){
printf("\ncould not seek (dev).\n");
return -1;
}
if (lseek(image, offset, SEEK_SET) != offset){
printf("\ncould not seek (image).\n");
return -1;
}
int nread = read(dev, p, sectSize);
if (nread == -1){
continue;
} else {
if (nread < sectSize) {
printf("\nshort read!\n");
}
write(image, p, nread);
fsync(image);
map[sect] = 0x01;
cntReadSectors++;
}
}
}
return 0;
}
int loadScratchMap(char *filename, int size, char *map){
int scratchmap = open(filename, O_RDONLY);
if (scratchmap != -1){
int nread = read(scratchmap, map, size);
}
close(scratchmap);
return 0;
}
int saveScratchMap(char *filename, int size, char *map){
int nwritten = -1;
int scratchmap = open(filename, O_WRONLY | O_TRUNC);
if (scratchmap != -1){
nwritten = write(scratchmap, map, size);
}
close(scratchmap);
return nwritten;
}
void printUsage(){
printf("usage: ddscratch ( [-b <firstsector> ] | [-o <offset>] ) [-c <sectorcount>] [-s <sectorsize>] <path> <target>\n");
}