V10/cmd/worm/wcopy.c

Compare this file to the similar file:
Show the results in this format:

#include	<libc.h>
#include	<fio.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<signal.h>
#include	"worm.h"

long minfree = 40000;
int verbose = 0;

main(argc, argv)
	char **argv;
{
	Superblock in, out;
	char *e;
	char buf[4096];
	int n;
	long lineno;
	int c;
	char *dev = "/dev/worm0";
	long tfiles, tbytes;
	int eof;
	char first[4096];
	extern char *optarg;
	extern int optind;

	argout = argv[0];
	while((c = getopt(argc, argv, "vm:f:")) != -1)
		switch(c)
		{
		case 'f':	dev = optarg; break;
		case 'm':	minfree = atol(optarg); break;
		case 'v':	verbose = 1; break;
		case '?':	usage();
		}

	if(optind+3 != argc)
		usage();
	e = mapdev(argv[optind+1]);
	if((out.fd = open(e, 2)) < 0){
		perror(e);
		exit(1);
	}
	if(e = openinode(&out, SPIN_DOWN)){
		fprint(2, "%s: %s\n", *argv, e);
		exit(1);
	}
	if(strcmp(out.vol_id, argv[optind+2])){
		fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind+2], out.vol_id);
		exit(1);
	}
	if(out.version != VLINK){
		fprint(2, "%s: can't write on a b-tree disk\n", out.vol_id);
		exit(1);
	}
	dev = mapdev(dev);
	if((in.fd = open(dev, 2)) < 0){
		perror(*argv);
		exit(1);
	}
	if(e = openinode(&in, DO_INODE|SPIN_DOWN)){
		fprint(2, "%s: %s\n", *argv, e);
		exit(1);
	}
	if(strcmp(in.vol_id, argv[optind])){
		fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], in.vol_id);
		exit(1);
	}
	for(n = 1; n <= NSIG; n++)
		signal(n, SIG_IGN);
	eof = 0;
	tfiles = tbytes = 0;
	lineno = 0;
	while(!eof){
		/* flush seperater lines */
		while(e = Frdline(0)){
			lineno++;
			if(*e)
				break;
		}
		if(e == 0)
			break;
		ininit();
		proc(&out, e);
		strncpy(first, e, sizeof first);
		if(out.nfree < minfree){
			fprint(2, "wcopy: disk %s full before copying group '%s' line %d\n",
				out.vol_id, first, lineno);
			exit(1);
		}
		while(e = Frdline(0)){
			lineno++;
			if(*e == 0)
				break;
			proc(&out, e);
		}
		if(e == 0)
			eof = 1;
		if(bad)
			exit(1);
		nfiles = nbytes = 0;
		blkdone = 0;
		inwrite(&out, &in);
		if(bad)
			exit(1);
		if(verbose)
			fprint(1, "%s group('%s' %d files, %.6fMB) done\n",
				timenow(), first, nfiles, nbytes/1e6);
		tfiles += nfiles;
		tbytes += nbytes;
	}
	if(verbose)
		fprint(1, "%s total: %d files, %.6fMB\n", timenow(), tfiles, tbytes/1e6);
	exit(0);
}

usage()
{
	fprint(2, "Usage: worm copy [-v] [-m minfree] [-f src_dev] src_id dest_dev dest_id < files\n");
	exit(1);
}

proc(s, file)
	Superblock *s;
	char *file;
{
	struct stat sbuf;
	unsigned short mode;
	Inode i;
	Inode *srci;

	if((srci = inodeof(file)) == 0){
		fprint(2, "can't find file '%s'\n", file);
		return;
	}
	memset((char *)&i, 0, sizeof(i));
	i = *srci;
	i.block = 0;
	nbytes += i.nbytes;
	if(inadd(s, &i))
		bad = 1;
}

writeout(dest, i, blk, src)
	Superblock *dest, *src;
	Inode *i;
	long *blk;
{
	char b[BIGBLOCK];
	Inode *srci;
	long n, len, blen;
	char *name;

	n = (i->nbytes+dest->blocksize-1)/dest->blocksize;
	*blk += n;
	blkdone += n;
	blen = sizeof b/dest->blocksize;
	len = blen*dest->blocksize;
	nbytes += i->nbytes;
	nfiles++;
	name = i->name.n;
	srci = inodeof(name);
	Seek(src, srci->block);
	for(n = i->nbytes; n > len; n -= len){
		if(Read(src, b, blen)){
	out:
			fprint(2, "read problem: seek=%d n=%d blen=%d len=%d; ",
				srci->block, n, blen, len);
			perror(name);
			bad = 1;
			return;
		}
		if(Write(dest, b, blen)){
fprint(2, "nb=%d, n=%d len=%d blen=%d\n", i->nbytes, n, len, blen);
			perror("data write");
			exit(1);
		}
	}
	if(n){
		n += dest->blocksize-1;
		n /= dest->blocksize;
		if(Read(src, b, n))
			goto out;
		if(Write(dest, b, n)){
			perror("data write");
			exit(1);
		}
	}
}