Skip to content

Instantly share code, notes, and snippets.

@xkikeg
Created January 27, 2013 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xkikeg/4645399 to your computer and use it in GitHub Desktop.
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.
#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