Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * bsplit - split big binaries (copy-less plan 9 version)
3
 */
4
 
5
#include <u.h>
6
#include <libc.h>
7
#include <authsrv.h>		/* for ANAMELEN */
8
 
9
enum {
10
	Stdin,
11
	Sectsiz = 512,
12
	Bufsiz = 256*Sectsiz,
13
};
14
 
15
/* disk address (in bytes or sectors), also type of 2nd arg. to seek */
16
typedef uvlong Daddr;
17
 
18
#define BLEN(s)	((s)->wp - (s)->rp)
19
#define BALLOC(s) ((s)->lim - (s)->base)
20
 
21
typedef struct {
22
	uchar*	rp;		/* first unconsumed byte */
23
	uchar*	wp;		/* first empty byte */
24
	uchar*	lim;		/* 1 past the end of the buffer */
25
	uchar*	base;		/* start of the buffer */
26
} Buffer;
27
 
28
typedef struct {
29
	/* parameters */
30
	Daddr	maxoutsz;	/* maximum size of output file(s) */
31
 
32
	Daddr	fileout;	/* bytes written to the current output file */
33
	char	*filenm;
34
	int	filesz;		/* size of filenm */
35
	char	*prefix;
36
	long	filenum;
37
	int	outf;		/* open output file */
38
 
39
	Buffer	buff;
40
} Copy;
41
 
42
/* global data */
43
char *argv0;
44
 
45
/* private data */
46
static Copy cp = { 512*1024*1024 };	/* default maximum size */
47
static int debug;
48
 
49
static void
50
bufreset(Buffer *bp)
51
{
52
	bp->rp = bp->wp = bp->base;
53
}
54
 
55
static void
56
bufinit(Buffer *bp, uchar *block, unsigned size)
57
{
58
	bp->base = block;
59
	bp->lim = bp->base + size;
60
	bufreset(bp);
61
}
62
 
63
static int 
64
eopen(char *file, int mode)
65
{
66
	int fd = open(file, mode);
67
 
68
	if (fd < 0)
69
		sysfatal("can't open %s: %r", file);
70
	return fd;
71
}
72
 
73
static int 
74
ecreate(char *file, int mode)
75
{
76
	int fd = create(file, mode, 0666);
77
 
78
	if (fd < 0)
79
		sysfatal("can't create %s: %r", file);
80
	return fd;
81
}
82
 
83
static char *
84
filename(Copy *cp)
85
{
86
	return cp->filenm;
87
}
88
 
89
static int 
90
opennext(Copy *cp)
91
{
92
	if (cp->outf >= 0)
93
		sysfatal("opennext called with file open");
94
	snprint(cp->filenm, cp->filesz, "%s%5.5ld", cp->prefix, cp->filenum++);
95
	cp->outf = ecreate(cp->filenm, OWRITE);
96
	cp->fileout = 0;
97
	return cp->outf;
98
}
99
 
100
static int 
101
closeout(Copy *cp)
102
{
103
	if (cp->outf >= 0) {
104
		if (close(cp->outf) < 0)
105
			sysfatal("error writing %s: %r", filename(cp));
106
		cp->outf = -1;
107
		cp->fileout = 0;
108
	}
109
	return cp->outf;
110
}
111
 
112
/*
113
 * process - process input file
114
 */
115
static void
116
process(int in, char *inname)
117
{
118
	int n = 1;
119
	unsigned avail, tolim, wsz;
120
	Buffer *bp = &cp.buff;
121
 
122
	USED(inname);
123
	do {
124
		if (BLEN(bp) == 0) {
125
			if (bp->lim == bp->wp)
126
				bufreset(bp);
127
			n = read(in, bp->wp, bp->lim - bp->wp);
128
			if (n <= 0)
129
				break;
130
			bp->wp += n;
131
		}
132
		if (cp.outf < 0)
133
			opennext(&cp);
134
 
135
		/*
136
		 * write from buffer's current point to end or enough bytes to
137
		 * reach file-size limit.
138
		 */
139
		avail = BLEN(bp);
140
		tolim = cp.maxoutsz - cp.fileout;
141
		wsz = (tolim < avail? tolim: avail);
142
 
143
		/* try to write full sectors */
144
		if (tolim >= avail && n > 0 && wsz >= Sectsiz)
145
			wsz = (wsz / Sectsiz) * Sectsiz;
146
		if (write(cp.outf, bp->rp, wsz) != wsz)
147
			sysfatal("error writing %s: %r", filename(&cp));
148
		bp->rp += wsz;
149
 
150
		cp.fileout += wsz;
151
		if (cp.fileout >= cp.maxoutsz)
152
			closeout(&cp);
153
	} while (n > 0 || BLEN(bp) != 0);
154
}
155
 
156
static void
157
usage(void)
158
{
159
	fprint(2, "usage: %s [-d][-p pfx][-s size] [file...]\n", argv0);
160
	exits("usage");
161
}
162
 
163
void
164
main(int argc, char **argv)
165
{
166
	int i, errflg = 0;
167
	uchar block[Bufsiz];
168
 
169
	cp.prefix = "bs.";
170
	ARGBEGIN {
171
	case 'd':
172
		debug++;
173
		break;
174
	case 'p':
175
		cp.prefix = EARGF(usage());
176
		break;
177
	case 's':
178
		cp.maxoutsz = atoll(EARGF(usage()));
179
		if (cp.maxoutsz < 1)
180
			errflg++;
181
		break;
182
	default:
183
		errflg++;
184
		break;
185
	} ARGEND
186
	if (errflg || argc < 0)
187
		usage();
188
 
189
	bufinit(&cp.buff, block, sizeof block);
190
	cp.outf = -1;
191
	cp.filesz = strlen(cp.prefix) + 2*ANAMELEN;	/* 2* is slop */
192
	cp.filenm = malloc(cp.filesz + 1);
193
	if (cp.filenm == nil)
194
		sysfatal("no memory: %r");
195
 
196
	if (argc == 0)
197
		process(Stdin, "/fd/0");
198
	else
199
		for (i = 0; i < argc; i++) {
200
			int in = eopen(argv[i], OREAD);
201
 
202
			process(in, argv[i]);
203
			close(in);
204
		}
205
	closeout(&cp);
206
	exits(0);
207
}