/* Comile with -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 */ #ifdef LINUXSTATIC #include "lib.h" #else #include #include #include #include #include #include #include #include #include #endif #include "util.h" #define MAXDISKS 12 #define DEFWINDOW 128 const char *diskname[MAXDISKS], *progname="xor"; unsigned char *window[MAXDISKS][2]; int windowalt=1; int diskfd[MAXDISKS], request[MAXDISKS], reply[MAXDISKS]; off_t windowstart, windowend, datastart, datalen=0; int disks=0, datasize=0, windowsize=DEFWINDOW*1024; void usage(int status) { fprintf(status? stderr:stdout, "Usage: %s [options] disks...\n" " --window " " Set I/O window size in K (default: %i)\n" " --start " " Skip to given position in bytes (default: 0)\n" " --length " " Length of data (no default)\n", progname, DEFWINDOW); exit(status); } void diskhelper(int i, int rd, int wr) { int bytes, dummy, datalen; while (1) { char *ptr; int len=windowsize; windowalt=!windowalt; ptr=window[i][windowalt]; while (len) { bytes=read(diskfd[i], ptr, windowsize); if (bytes==-1 && errno==EINTR) continue; if (bytes==-1) die("read (child %i, file %s): %s\n", i, diskname[i], strerror(errno)); if (bytes==0) break; ptr+=bytes; len-=bytes; } datalen=windowsize-len; msync(window[i][windowalt], windowsize, MS_SYNC | MS_INVALIDATE); len=sizeof(datalen); ptr=(char *)&datalen; while (len) { bytes=write(wr, ptr, len); if (bytes==-1 && errno==EINTR) continue; if (bytes==-1) die("write (child %i): %s\n", i, strerror(errno)); len-=bytes; ptr+=bytes; } while ((bytes=read(rd, &dummy, 1))!=1) { if (bytes==-1 && errno==EINTR) continue; if (bytes==-1) die("read (child %i): %s\n", i, strerror(errno)); if (bytes==0) exit(0); } } } void parseopts(int argc, char *argv[]) { int i, optparsing=1; if (argc) setprogname(argv[0]); if (argc<=1) usage(1); for (i=1; i returned) ret=returned; while ((bytes=write(request[i], &dummy, 1))!=1) { if (bytes==-1 && errno==EINTR) continue; die("write: %s\n", strerror(errno)); } } windowstart += datasize; datasize = ret; windowend = windowstart + ret-1; windowalt = !windowalt; return ret; } void verifychecksum(void) { int i, a; return; for (a=0; adatalen) len=datalen; if (winoffset+len > datasize) len=datasize-winoffset; if (!len) die("Input ended with %llu output bytes unwritten\n", datalen); datastart+=len; datalen-=len; ptr=window[disk][windowalt]+winoffset; while (len) { bytes=write(STDOUT_FILENO, ptr, len); if (bytes==-1 && errno==EINTR) continue; if (bytes==-1) die("write: %s\n", strerror(errno)); len-=bytes; ptr+=bytes; } } #endif void printpartial(void) { off_t offset = datastart - windowstart; int len=windowsize-offset; if (len>datalen) len=datalen; if (offset+len > datasize) len=datasize-offset; if (!len) die("Input ended with %llu bytes early\n", datalen); datastart+=len; datalen-=len; while (len--) { unsigned char xor=0; int i; for (i=0; i