Created
January 27, 2013 00:04
-
-
Save xkikeg/4645399 to your computer and use it in GitHub Desktop.
Copy from source to destination only if position is recorded in input & source is nonzero and destination is zero.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _FILE_OFFSET_BITS 64 | |
#include <vector> | |
#include <fstream> | |
#include <iostream> | |
#include <cstdio> | |
#include <cstdlib> | |
#include <cassert> | |
#include <cstring> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#define BUFSIZE 512 | |
bool allzero(const char * buf, size_t len) { | |
size_t i; | |
for(i = 0; i < len; ++i) { | |
if(buf[i] != '\0') { return false; } | |
} | |
return true; | |
} | |
const char destination[] = "/media/extDisk/hddimage"; | |
const char source[] = "hddimage2"; | |
const char input[] = "hddimage2.hexmap"; | |
void copy_nonzero(int sfd, int dfd, off_t pos, off_t size) { | |
char sbuf[BUFSIZE]; | |
char dbuf[BUFSIZE]; | |
fprintf(stderr, "begin 0x%llx 0x%llx\n", | |
(unsigned long long)pos, | |
(unsigned long long)size); | |
lseek(sfd, pos, SEEK_SET); | |
off_t current_length = 0; | |
for(off_t i = 0; i < size; ++i) { | |
ssize_t ret; | |
ret = read(sfd, sbuf, BUFSIZE); | |
if(ret != BUFSIZE) { | |
fprintf(stderr, "Error: different size %d %d\n", BUFSIZE, ret); | |
exit(EXIT_FAILURE); | |
} | |
lseek(dfd, pos + i*BUFSIZE, SEEK_SET); | |
ret = read(dfd, dbuf, BUFSIZE); | |
if(ret != BUFSIZE) { | |
fprintf(stderr, "Error: different size %d %d\n", BUFSIZE, ret); | |
exit(EXIT_FAILURE); | |
} | |
if(!allzero(sbuf, BUFSIZE)) { | |
if(current_length == 0) { printf("0x%llx", pos + i*BUFSIZE); } | |
current_length += BUFSIZE; | |
if(!allzero(dbuf, BUFSIZE)) { | |
fprintf(stderr, "destination dirty pos=0x%llx\n", (unsigned long long)(pos + i*BUFSIZE)); | |
} else { | |
lseek(dfd, pos + i*BUFSIZE, SEEK_SET); | |
ret = write(dfd, sbuf, BUFSIZE); | |
if(ret != BUFSIZE) { | |
fprintf(stderr, "partial write\n"); | |
} | |
} | |
} else { | |
if(current_length != 0) { printf(" 0x%llx\n", current_length); } | |
current_length = 0; | |
} | |
} | |
if(current_length != 0) { | |
printf(" 0x%llx\n", current_length); | |
current_length = 0; | |
} | |
} | |
int main() { | |
char buf[65536]; | |
memset(buf, 0, 65536); | |
assert(allzero(buf, 65536)); | |
buf[10000] = 4; | |
assert(!allzero(buf, 65536)); | |
std::ifstream ifs; | |
ifs.open(input); | |
if(ifs.fail()) { | |
std::cerr << "Error: input file open failed\n"; | |
exit(EXIT_FAILURE); | |
} | |
std::vector<off_t> vec_pos, vec_len; | |
do { | |
off_t pos, len; | |
ifs >> std::hex >> pos >> len; | |
vec_pos.push_back(pos); | |
vec_len.push_back(len); | |
// std::cerr << "i=" << vec_pos.size() | |
// << " pos=" << pos | |
// << " len=" << len << "\n"; | |
} while (!ifs.eof()); | |
int sfd = open(source, O_RDONLY); | |
int dfd = open(destination, O_RDWR); | |
if(sfd == -1) { | |
perror("Error: source open failed\n"); | |
} | |
if(dfd == -1) { | |
perror("Error: destionation open failed\n"); | |
} | |
struct stat status; | |
fstat(sfd, &status); | |
for(size_t i=0, s=vec_pos.size(); i < s; ++i) { | |
off_t pos=vec_pos[i], len=vec_len[i]; | |
assert(pos + len < status.st_size); | |
off_t buflen = len / BUFSIZE; | |
assert(buflen * BUFSIZE == len); | |
copy_nonzero(sfd, dfd, pos, buflen); | |
} | |
close(sfd); | |
close(dfd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment