From: Martin Mares Date: Sat, 29 Jan 2022 20:13:03 +0000 (+0100) Subject: verbose-copy X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=225457f513c3f7fa66c8b494adbdd2d498e0f0f3;p=misc.git verbose-copy --- diff --git a/verbose-copy.c b/verbose-copy.c new file mode 100644 index 0000000..6b7c136 --- /dev/null +++ b/verbose-copy.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// XXX: Assuming block size == 512 + +int main(int argc, char **argv) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + int fi = open(argv[1], O_RDONLY); + if (fi < 0) { + fprintf(stderr, "Cannot open source %s: %m\n", argv[1]); + return 1; + } + + int fo = open(argv[2], O_WRONLY); + if (fo < 0) { + fprintf(stderr, "Cannot open destination %s: %m\n", argv[1]); + return 1; + } + + struct stat sti, sto; + if (fstat(fi, &sti) < 0 || fstat(fo, &sto) < 0) { + fprintf(stderr, "Stat failed: %m\n"); + return 1; + } + if (!S_ISBLK(sti.st_mode)) { + fprintf(stderr, "Input is not a block device\n"); + return 1; + } + if (!S_ISBLK(sto.st_mode)) { + fprintf(stderr, "Output is not a block device\n"); + return 1; + } + + unsigned long leni, leno; + if (ioctl(fi, BLKGETSIZE, &leni) < 0 || + ioctl(fo, BLKGETSIZE, &leno) < 0) { + fprintf(stderr, "Cannot get device size: %m\n"); + return 1; + } + if (leni > leno) { + fprintf(stderr, "Will not fit: %ld > %ld\n", leni, leno); + return 1; + } + +#define BUFSIZE 65536 + char *buf = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) { + fprintf(stderr, "Cannot mmap buffer: %m\n"); + return 1; + } + + unsigned int remi = leni; + int verb = 1; + while (remi) { + int s = (remi < BUFSIZE/512) ? remi : BUFSIZE/512; + int l = read(fi, buf, s*512); + if (l < 0) { + fprintf(stderr, "Read error: %m\n"); + return 1; + } + if (l != s*512) { + fprintf(stderr, "Short read: %d of %d. Recovering.\n", l, s*512); + } + int w = write(fo, buf, l); + if (w < 0) { + fprintf(stderr, "Write error: %m\n"); + return 1; + } + if (w != l) { + fprintf(stderr, "Short write: %d of %d\n", w, l); + return 1; + } + remi -= s; + if (!--verb) { + printf("\rCopied %d of %d MB (%d%%)...", (int)((leni-remi)/2048), (int)((leni+2047)/2048), + (int)((double)(leni-remi) / leni * 100)); + verb = 64; + } + } + + printf("Copied %d MB \n", (int)((leni+2047)/2048)); + close(fo); + close(fi); + return 0; +}