16f5889c28
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21897 a95241bf-73f2-0310-859d-f6bbb57e9c96
182 lines
3.3 KiB
C
182 lines
3.3 KiB
C
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|
//
|
|
// Copyright (c) 2001-2003, OpenBeOS
|
|
//
|
|
// This software is part of the OpenBeOS distribution and is covered
|
|
// by the OpenBeOS license.
|
|
//
|
|
//
|
|
// File: unchop.c
|
|
// Author: Daniel Reinhold (danielre@users.sf.net)
|
|
// Description: recreates a file previously split with chop
|
|
//
|
|
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|
|
|
#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 *);
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// globals
|
|
|
|
#define BLOCKSIZE 64 * 1024 // file data is read in BLOCKSIZE blocks
|
|
static char Block[BLOCKSIZE]; // and stored in the global Block array
|
|
|
|
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)) {
|
|
// output file already exists -- write to temp file
|
|
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)
|
|
{
|
|
// appends the entire contents of the input file
|
|
// to the output file
|
|
|
|
ssize_t got;
|
|
|
|
for (;;) {
|
|
got = read(fdin, Block, BLOCKSIZE);
|
|
if (got <= 0)
|
|
break;
|
|
|
|
write(fdout, Block, got);
|
|
}
|
|
}
|
|
|
|
|
|
bool
|
|
valid_file(char *fname)
|
|
{
|
|
// for this program, a valid file is one that:
|
|
// a) exists (that always helps)
|
|
// b) is a regular file (not a directory, link, etc.)
|
|
|
|
struct stat e;
|
|
|
|
if (stat(fname, &e) == -1) {
|
|
// no such file
|
|
return false;
|
|
}
|
|
|
|
return (S_ISREG(e.st_mode));
|
|
}
|
|
|
|
|
|
void
|
|
replace(char *origfile, char *newfile)
|
|
{
|
|
// replace the contents of the original file
|
|
// with the contents of the new file
|
|
|
|
char buf[1000];
|
|
|
|
// delete the original file
|
|
remove(origfile);
|
|
|
|
// rename the new file to the original file name
|
|
sprintf(buf, "mv \"%s\" \"%s\"", newfile, origfile);
|
|
system(buf);
|
|
}
|
|
|
|
|
|
char *
|
|
temp_file(void)
|
|
{
|
|
// creates a new, temporary file and returns its name
|
|
|
|
char *tmp = tmpnam(NULL);
|
|
|
|
FILE *fp = fopen(tmp, "w");
|
|
fclose(fp);
|
|
|
|
return tmp;
|
|
}
|