123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- * tarsplit [-d] [-p pfx] [-s size] - split a tar archive into independent
- * tar archives under some size
- */
- #include <u.h>
- #include <libc.h>
- #include <ctype.h>
- #include "tar.h"
- enum {
- Stdin,
- Endsize = 2 * Tblock, /* size of zero blocks at archive end */
- };
- /* private data */
- static char *filenm;
- static char *prefix = "ts.";
- static vlong size = 512*1024*1024; /* fits on a CD with room to spare */
- static int
- opennext(int out, char *prefix)
- {
- static int filenum = 0;
- if (out >= 0) {
- fprint(2, "%s: opennext called with file open\n", argv0);
- exits("open botch");
- }
- free(filenm);
- filenm = smprint("%s%.5d", prefix, filenum++);
- fprint(2, "%s: %s ...", filenm, thisnm);
- out = create(filenm, OWRITE, 0666);
- if (out < 0)
- sysfatal("%s: %r", filenm);
- newarch();
- return out;
- }
- static int
- split(int in, int out, char * /* inname */)
- {
- vlong len, membsz;
- uvlong outoff = 0;
- static Hblock hdr;
- Hblock *hp = &hdr;
- while (getdir(hp, in, &len)) {
- membsz = Tblock + ROUNDUP((uvlong)len, Tblock);
- if (outoff + membsz + Endsize > size) { /* won't fit? */
- out = closeout(out, filenm, 1);
- if (membsz + Endsize > size)
- sysfatal("archive member %s (%,lld) + overhead "
- "exceeds size limit %,lld", hp->name,
- len, size);
- }
- if (out < 0)
- out = opennext(out, prefix);
- /* write directory block */
- writetar(out, (char *)hp, Tblock);
- outoff = passtar(hp, in, out, len);
- }
- return out;
- }
- void
- usage(void)
- {
- fprint(2, "usage: %s [-p pfx] [-s size] [file]...\n", argv0);
- exits("usage");
- }
- void
- main(int argc, char **argv)
- {
- int out = -1;
- ARGBEGIN {
- case 'p':
- prefix = EARGF(usage());
- break;
- case 's':
- size = atoll(EARGF(usage()));
- if (size < Tblock + Endsize)
- sysfatal("implausible max size of %lld bytes", size);
- break;
- default:
- usage();
- } ARGEND
- if (argc <= 0)
- out = split(Stdin, out, "/fd/0");
- else
- for (; argc-- > 0; argv++) {
- int in = open(argv[0], OREAD);
- if (in < 0)
- sysfatal("%s: %r", argv[0]);
- out = split(in, out, argv[0]);
- close(in);
- }
- closeout(out, filenm, 1);
- exits(0);
- }
|