#include <OS.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
void append_file (int, int);
void do_unchop (char *, char *);
void replace (char *, char *);
char *temp_file (void);
void usage (void);
bool valid_file (char *);
#define BLOCKSIZE 64 * 1024 // file data is read in BLOCKSIZE blocks
static char Block[BLOCKSIZE];
static int Errors = 0;
void
usage()
{
printf("Usage: unchop file\n");
printf("Concatenates files named file00, file01... into file\n");
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
usage();
return 0;
}
else {
char *origfile = argv[1];
char *tmpfile = origfile;
bool needs_replace = false;
if (valid_file(origfile)) {
tmpfile = temp_file();
needs_replace = true;
}
do_unchop(tmpfile, origfile);
if (needs_replace) {
if (Errors == 0)
replace(origfile, tmpfile);
else
remove(tmpfile);
}
}
return Errors;
}
void
do_unchop(char *outfile, char *basename)
{
int fdout = open(outfile, O_WRONLY|O_CREAT|O_APPEND);
if (fdout < 0)
fprintf(stderr, "can't open '%s': %s\n", outfile, strerror(errno));
else {
int i;
char fnameN[256];
for (i = 0; i < 999999; ++i) {
sprintf(fnameN, "%s%02d", basename, i);
if (valid_file(fnameN)) {
int fdin = open(fnameN, O_RDONLY);
if (fdin < 0) {
fprintf(stderr, "can't open '%s': %s\n", fnameN, strerror(errno));
++Errors;
} else {
append_file(fdin, fdout);
close(fdin);
}
} else {
if (i == 0)
printf("No chunk files present (%s)", fnameN);
break;
}
}
close(fdout);
}
}
void
append_file(int fdin, int fdout)
{
ssize_t got;
for (;;) {
got = read(fdin, Block, BLOCKSIZE);
if (got <= 0)
break;
write(fdout, Block, got);
}
}
bool
valid_file(char *fname)
{
struct stat e;
if (stat(fname, &e) == -1) {
return false;
}
return (S_ISREG(e.st_mode));
}
void
replace(char *origfile, char *newfile)
{
char buf[1000];
remove(origfile);
sprintf(buf, "mv \"%s\" \"%s\"", newfile, origfile);
system(buf);
}
char *
temp_file(void)
{
char *tmp = tmpnam(NULL);
FILE *fp = fopen(tmp, "w");
fclose(fp);
return tmp;
}