sparse-tools/src/mksparse.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);
}