Spójrz na
- ntfsclone (kopiuje tylko używane sektory)
- fixntfs.c, aby naprawić przesunięcia informacji o rozruchu
IIRC, Trinity Rescue Kit zawiera niezbędne oprogramowanie, a także wiele innych (ssh, partimage, fdisk, fdisk, cfdisk, parted, gparted, testdisk, ntfsfix; montowanie ntfs-3g, rsync itp.).
/*
* fixntfs: change some attributes of an NTFS bootsector
*
* brought to you by Phoenix
* url: www.grhack.gr/phoenix
* mail: phoenix@grhack.gr
* irc: phoenix -> #grhack -> undernet
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *fd;
FILE *idfd;
struct stat fst;
unsigned char cab[32];
unsigned short log_heads;
unsigned short ntfs_heads;
unsigned short force_heads;
unsigned short ntfs_cab;
unsigned long long sectors;
unsigned long long new_sectors;
log_heads = 0;
ntfs_heads = 0;
force_heads = 0;
ntfs_cab = 0;
if(argc < 2)
{
fprintf(stderr, "Usage:\n\t%s <device> <total_sectors> <force_heads>\n", argv[0]);
exit(0);
}
fprintf(stderr, "Stating file %s... ", argv[1]);
stat(argv[1], &fst);
if(!S_ISBLK(fst.st_mode))
{
fprintf(stderr, "not a block device\n");
exit(-1);
}
fprintf(stderr, "a block device\n");
fprintf(stderr, "Opening device %s rw... ", argv[1]);
fd = fopen(argv[1], "r+");
if(!fd)
{
perror("open device");
exit(-1);
}
fprintf(stderr, "ok\n");
fprintf(stderr, "Checking partition... ");
fseek(fd, 3, SEEK_SET);
if(fread(cab, 1, 4, fd) != 4)
{
perror("read system_id");
exit(-1);
}
cab[5] = 0;
if(strncmp(cab, "NTFS", 4))
{
fprintf(stderr, "%s\n", cab);
exit(-1);
}
fprintf(stderr, "%s\n", cab);
fprintf(stderr, "Reading NTFS bootsector heads... ");
fseek(fd, 0x1a, SEEK_SET);
ntfs_heads = 0;
fread(&ntfs_heads, 1, 2, fd);
fprintf(stderr, "%u\n", ntfs_heads);
fprintf(stderr, "Reading NTFS bootsector sectors... ");
fseek(fd, 0x18, SEEK_SET);
ntfs_cab = 0;
fread(&ntfs_cab, 1, 2, fd);
fprintf(stderr, "%u\n", ntfs_cab);
fprintf(stderr, "Reading NTFS bootsector sectors_per_cluster... ");
fseek(fd, 0x0d, SEEK_SET);
ntfs_cab = 0;
fread(&ntfs_cab, 1, 1, fd);
fprintf(stderr, "%u\n", ntfs_cab);
fprintf(stderr, "Reading NTFS bootsector sectors_size... ");
fseek(fd, 0x0b, SEEK_SET);
ntfs_cab = 0;
fread(&ntfs_cab, 1, 2, fd);
fprintf(stderr, "%u\n", ntfs_cab);
fprintf(stderr, "Reading NTFS bootsector boot_loader_routine_jump... ");
fseek(fd, 0, SEEK_SET);
bzero(cab, sizeof(cab));
fread(cab, 1, 3, fd);
fprintf(stderr, "0x%x 0x%x 0x%x\n", cab[0], cab[1], cab[2]);
fprintf(stderr, "Reading NTFS bootsector total_sectors... ");
fseek(fd, 0x28, SEEK_SET);
sectors = 0;
fread(§ors, 1, 8, fd);
fprintf(stderr, "%Lu\n", sectors);
fprintf(stderr, "Reading device logical heads... ");
sprintf(cab, "/proc/ide/hd%c/geometry", *(strrchr(argv[1],'/') + 3));
idfd = fopen(cab, "r");
if(!idfd)
{
perror(cab);
exit(-1);
}
fscanf(idfd, "%*s %*s\n");
fscanf(idfd, "%*s %s\n", cab);
*(strrchr(cab, '/')) = 0;
log_heads = (unsigned short) atoi(strchr(cab, '/') + 1);
fprintf(stderr, "%u\n", log_heads);
if(argc == 4)
{
force_heads=atoi(argv[3]);
fprintf(stderr, "Forcing heads to %u\n", force_heads);
log_heads=force_heads;
}
if(fclose(fd) == EOF)
{
perror("close device");
exit(-1);
}
if(log_heads != ntfs_heads)
{
fprintf(stderr, "Heads are different... Logical=%u NTFS=%u\n\n"
"Update NTFS bootsector? (y/n) ",
log_heads, ntfs_heads);
if(getc(stdin) == 'y')
{
fd = fopen(argv[1], "r+");
if(!fd)
{
perror("open device");
exit(-1);
}
ntfs_heads = log_heads;
fseek(fd, 0x1a, SEEK_SET);
fwrite(&ntfs_heads, 1, 2, fd);
fprintf(stderr, "\nBootsector updated... Verifying... ");
fclose(fd);
fd = fopen(argv[1], "r");
if(!fd)
{
perror("open device");
exit(-1);
}
fseek(fd, 0x1a, SEEK_SET);
ntfs_heads = 0;
fread(&ntfs_heads, 1, 2, fd);
if(ntfs_heads == log_heads)
{
fprintf(stderr, "ok\n\n");
}
else
{
fprintf(stderr, "error [%u]\n", ntfs_heads);
exit(-1);
}
fclose(fd);
}
else
{
fprintf(stderr, "\nHeads update cancelled...\n");
}
getc(stdin);
}
if(argc >= 3 && atoll(argv[2]))
{
fprintf(stderr, "Update NTFS bootsector total_sectors from %Lu to %Lu? (y/n) ",
sectors, atoll(argv[2]));
if(getc(stdin) == 'y')
{
fd = fopen(argv[1], "r+");
if(!fd)
{
perror("open device");
exit(-1);
}
new_sectors = atoll(argv[2]);
fseek(fd, 0x28, SEEK_SET);
fwrite(&new_sectors, 1, 8, fd);
fprintf(stderr, "\nBootsector updated... Verifying... ");
fclose(fd);
fd = fopen(argv[1], "r");
if(!fd)
{
perror("open device");
exit(-1);
}
fseek(fd, 0x28, SEEK_SET);
sectors = 0;
fread(§ors, 1, 8, fd);
if(sectors == new_sectors)
{
fprintf(stderr, "ok\n\n");
}
else
{
fprintf(stderr, "error [%Lu]\n", sectors);
exit(-1);
}
fclose(fd);
}
else
{
fprintf(stderr, "\nTotal_sectors update cancelled...\n");
}
getc(stdin);
}
return(1);
}