194 lines
3.4 KiB
C
194 lines
3.4 KiB
C
|
#include <stdlib.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <signal.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
char *units[] =
|
||
|
{
|
||
|
"Bytes",
|
||
|
"kBytes",
|
||
|
"MBytes",
|
||
|
"GBytes"
|
||
|
};
|
||
|
|
||
|
int mode = 0; // 0 = stdin -> stdout
|
||
|
// 1 = enocde
|
||
|
// 2 = decode
|
||
|
|
||
|
int arg_verbose = 0;
|
||
|
|
||
|
long filesize = 0;
|
||
|
long netsize = 0;
|
||
|
|
||
|
long transferred = 0;
|
||
|
long nettransferred = 0;
|
||
|
|
||
|
long transfersum = 0;
|
||
|
long nettransfersum = 0;
|
||
|
|
||
|
|
||
|
char status[1024];
|
||
|
|
||
|
void (*restore_sig_alrm)(int sig);
|
||
|
void sig_alrm(int sig)
|
||
|
{
|
||
|
long transfer = filesize - transferred;
|
||
|
transferred += transfer;
|
||
|
|
||
|
transfersum += transfer;
|
||
|
transfer = transfersum >> 2;
|
||
|
transfersum -= transfer;
|
||
|
|
||
|
long t = transferred;
|
||
|
|
||
|
int nu = 0;
|
||
|
int nt = 0;
|
||
|
|
||
|
while ((transfer > 1024))
|
||
|
{
|
||
|
transfer >>= 10;
|
||
|
nu++;
|
||
|
if (nu == 3)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while ((t > 1024))
|
||
|
{
|
||
|
t >>= 10;
|
||
|
nt++;
|
||
|
if (nt == 3)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
sprintf(status, "sparse-tools: %li %s seen, current speed is %li %s/s \r", t, units[nt], transfer, units[nu]);
|
||
|
write(2, status, strlen(status));
|
||
|
fsync(2);
|
||
|
|
||
|
alarm( 1 );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int sparse_copy(int in, int out, int blocksize)
|
||
|
{
|
||
|
int nread = 0, i;
|
||
|
char block[blocksize];
|
||
|
|
||
|
while ((nread = read( in, block, blocksize))>0)
|
||
|
{
|
||
|
for (i=0; (i<blocksize) && (block[i] == 0) ; i++) { }
|
||
|
if (i != nread)
|
||
|
write( out, block, nread );
|
||
|
else
|
||
|
lseek( out, blocksize, SEEK_CUR );
|
||
|
|
||
|
filesize += nread;
|
||
|
}
|
||
|
|
||
|
ftruncate( out, filesize );
|
||
|
|
||
|
return nread;
|
||
|
}
|
||
|
|
||
|
int sparse_encode(int in, int out, int blocksize)
|
||
|
{
|
||
|
int nread = 0, i;
|
||
|
char block[blocksize];
|
||
|
|
||
|
while ((nread = read( in, block, blocksize))>0)
|
||
|
{
|
||
|
for (i=0; (i<blocksize) && (block[i] == 0) ; i++) { }
|
||
|
|
||
|
if (i != nread)
|
||
|
{
|
||
|
write( out, "D", 1 );
|
||
|
write( out, block, nread );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
write( out, "S", 1 );
|
||
|
}
|
||
|
|
||
|
filesize += nread;
|
||
|
}
|
||
|
|
||
|
return nread;
|
||
|
|
||
|
}
|
||
|
int sparse_decode(int in, int out, int blocksize)
|
||
|
{
|
||
|
int nread = 0, i;
|
||
|
char m;
|
||
|
char block[blocksize];
|
||
|
|
||
|
while (read(in, &m, 1 ) > 0)
|
||
|
{
|
||
|
switch (m)
|
||
|
{
|
||
|
case 'S':
|
||
|
lseek( out, blocksize, SEEK_CUR );
|
||
|
filesize += blocksize;
|
||
|
break;
|
||
|
case 'D':
|
||
|
nread = read( in, block, blocksize);
|
||
|
write( out, block, nread );
|
||
|
filesize += nread;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ftruncate( out, filesize );
|
||
|
|
||
|
return nread;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int ch;
|
||
|
|
||
|
while ((ch = getopt(argc, argv, "edv"))!=-1)
|
||
|
{
|
||
|
switch (ch)
|
||
|
{
|
||
|
case 'd':
|
||
|
mode = 2;
|
||
|
break;
|
||
|
case 'e':
|
||
|
mode = 1;
|
||
|
break;
|
||
|
case 'v':
|
||
|
arg_verbose = 1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (arg_verbose)
|
||
|
{
|
||
|
restore_sig_alrm = signal( SIGALRM, sig_alrm);
|
||
|
alarm( 1 );
|
||
|
}
|
||
|
|
||
|
switch (mode)
|
||
|
{
|
||
|
case 0:
|
||
|
return sparse_copy( 0, 1, 4096 );
|
||
|
case 1:
|
||
|
return sparse_encode( 0, 1, 4096 );
|
||
|
case 2:
|
||
|
return sparse_decode( 0, 1, 4096 );
|
||
|
}
|
||
|
|
||
|
if (arg_verbose)
|
||
|
{
|
||
|
alarm( 0 );
|
||
|
signal( SIGALRM, restore_sig_alrm );
|
||
|
write( 2, "\n", 1 );
|
||
|
}
|
||
|
|
||
|
close(0);
|
||
|
close(1);
|
||
|
}
|