Skip to content

Instantly share code, notes, and snippets.

@syhpoon
Created December 21, 2016 18:40
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 syhpoon/90ef24fa5aa2f065e4b82d2ed04182ce to your computer and use it in GitHub Desktop.
Save syhpoon/90ef24fa5aa2f065e4b82d2ed04182ce to your computer and use it in GitHub Desktop.
Clone two block devices on a block level
#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <malloc.h>
#include <string.h>
#define BUFSIZE 512
int main(int argc, char *argv[]) {
if(argc != 3) {
printf("Usage: clone original-drive copy-drive\n");
return 1;
}
char *orig = argv[1];
char *copy = argv[2];
int orig_fd = open(orig, O_RDONLY | O_LARGEFILE);
if(orig_fd == -1) {
perror("Opening original drive");
exit(1);
}
int copy_fd = open(copy, O_RDWR | O_LARGEFILE);
if(copy_fd == -1) {
perror("Opening copy drive");
exit(1);
}
posix_fadvise(orig_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
posix_fadvise(copy_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
void *orig_buf = memalign(512, BUFSIZE);
void *copy_buf = memalign(512, BUFSIZE);
if(orig_buf == NULL || copy_buf == NULL) {
perror("Allocating memory");
exit(1);
}
size_t orig_read, copy_read;
long block = 0;
while(true) {
orig_read = read(orig_fd, orig_buf, BUFSIZE);
copy_read = read(copy_fd, copy_buf, BUFSIZE);
if(orig_read == -1 || copy_read == -1) {
perror("Reading");
exit(-1);
}
if(orig_read == 0) {
break;
}
if(orig_read != copy_read) {
printf("Read size mismatch, orig=%d, copy=%d\n", orig_read, copy_read);
exit(-1);
}
if(memcmp(orig_buf, copy_buf, orig_read) != 0) {
printf("Found mismatching block %ld, updating\n", block);
// Rewind offset
if(lseek(copy_fd, -copy_read, SEEK_CUR) == -1) {
perror("Seeking");
exit(-1);
}
if(write(copy_fd, orig_buf, orig_read) == -1) {
perror("Writing");
exit(-1);
}
}
block++;
}
printf("Done\n");
fsync(copy_fd);
close(orig_fd);
close(copy_fd);
free(orig_buf);
free(copy_buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment