Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * tarsplit [-d] [-p pfx] [-s size] - split a tar archive into independent
3
 *	tar archives under some size
4
 */
5
 
6
#include <u.h>
7
#include <libc.h>
8
#include <ctype.h>
9
#include "tar.h"
10
 
11
enum {
12
	Stdin,
13
	Endsize	= 2 * Tblock,		/* size of zero blocks at archive end */
14
};
15
 
16
/* private data */
17
static char *filenm;
18
static char *prefix = "ts.";
19
static vlong size = 512*1024*1024;	/* fits on a CD with room to spare */
20
 
21
static int
22
opennext(int out, char *prefix)
23
{
24
	static int filenum = 0;
25
 
26
	if (out >= 0) {
27
		fprint(2, "%s: opennext called with file open\n", argv0);
28
		exits("open botch");
29
	}
30
	free(filenm);
31
	filenm = smprint("%s%.5d", prefix, filenum++);
32
	fprint(2, "%s: %s ...", filenm, thisnm);
33
	out = create(filenm, OWRITE, 0666);
34
	if (out < 0)
35
		sysfatal("%s: %r", filenm);
36
	newarch();
37
	return out;
38
}
39
 
40
static int
41
split(int in, int out, char * /* inname */)
42
{
43
	vlong len, membsz;
44
	uvlong outoff = 0;
45
	static Hblock hdr;
46
	Hblock *hp = &hdr;
47
 
48
	while (getdir(hp, in, &len)) {
49
		membsz = Tblock + ROUNDUP((uvlong)len, Tblock);
50
		if (outoff + membsz + Endsize > size) {	/* won't fit? */
51
			out = closeout(out, filenm, 1);
52
			if (membsz + Endsize > size)
53
				sysfatal("archive member %s (%,lld) + overhead "
54
					"exceeds size limit %,lld", hp->name,
55
					len, size);
56
		}
57
		if (out < 0)
58
			out = opennext(out, prefix);
59
		/* write directory block */
60
		writetar(out, (char *)hp, Tblock);
61
		outoff = passtar(hp, in, out, len);
62
	}
63
	return out;
64
}
65
 
66
void
67
usage(void)
68
{
69
	fprint(2, "usage: %s [-p pfx] [-s size] [file]...\n", argv0);
70
	exits("usage");
71
}
72
 
73
void
74
main(int argc, char **argv)
75
{
76
	int out = -1;
77
 
78
	ARGBEGIN {
79
	case 'p':
80
		prefix = EARGF(usage());
81
		break;
82
	case 's':
83
		size = atoll(EARGF(usage()));
84
		if (size < Tblock + Endsize)
85
			sysfatal("implausible max size of %lld bytes", size);
86
		break;
87
	default:
88
		usage();
89
	} ARGEND
90
 
91
	if (argc <= 0)
92
		out = split(Stdin, out, "/fd/0");
93
	else
94
		for (; argc-- > 0; argv++) {
95
			int in = open(argv[0], OREAD);
96
 
97
			if (in < 0)
98
				sysfatal("%s: %r", argv[0]);
99
			out = split(in, out, argv[0]);
100
			close(in);
101
		}
102
	closeout(out, filenm, 1);
103
	exits(0);
104
}