ref: fd8d404d520a3f10c143f5cbe7c170606fffc75c
parent: dd468419f2fbaa2c3fec570a88d13e8eae8f3faf
author: iru <devnull@localhost>
date: Wed Apr 13 20:35:48 EDT 2011
Promote the old installer/livecd specific tools to normal tools under /sys/src/cmd. Where similar common tools already existed, I kept them.
--- a/sys/lib/dist.old/cmd/bflz.c
+++ /dev/null
@@ -1,374 +1,0 @@
-/*
- * Extraordinarily brute force Lempel & Ziv-like
- * compressor. The input file must fit in memory
- * during compression, and the output file will
- * be reconstructed in memory during decompression.
- * We search for large common sequences and use a
- * greedy algorithm to choose which sequence gets
- * compressed first.
- *
- * Files begin with "BLZ\n" and a 32-bit uncompressed file length.
- *
- * Output format is a series of blocks followed by
- * a raw data section. Each block begins with a 32-bit big-endian
- * number. The top bit is type and the next 31 bits
- * are uncompressed size. Type is one of
- * 0 - use raw data for this length
- * 1 - a 32-bit offset follows
- * After the blocks come the raw data. (The end of the blocks can be
- * noted by summing block lengths until you reach the file length.)
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-#define malloc sbrk
-
-int minrun = 16;
-int win = 16;
-ulong outn;
-int verbose;
-int mindist;
-
-enum { Prime = 16777213 }; /* smallest prime < 2^24 (so p*256+256 < 2^32) */
-enum { NOFF = 3 };
-
-Biobuf bout;
-ulong length;
-uchar *data;
-ulong sum32(ulong, void*, long);
-uchar *odat;
-int nodat;
-int nraw;
-int rawstart;
-int acct;
-int zlength;
-int maxchain;
-int maxrle[256];
-int nnew;
-
-typedef struct Node Node;
-struct Node {
- Node *link;
- ulong key;
- ulong offset[NOFF];
-};
-
-Node *nodepool;
-int nnodepool;
-
-Node **hash;
-uint nhash;
-
-uint maxlen;
-uint maxsame;
-uint replacesame = 8*1024*1024;
-
-Node *freelist, **freeend;
-uint nalloc;
-
-Node*
-allocnode(void)
-{
- int i;
- Node *n;
-
- if(nnodepool == 0){
- nnodepool = 256*1024;
- nodepool = malloc(sizeof(Node)*nnodepool);
- }
- if(freelist){
- n = freelist;
- freelist = n->link;
- return n;
- }
- assert(nnodepool > 0);
- nalloc++;
- n = &nodepool[--nnodepool];
- for(i=0; i<NOFF; i++)
- n->offset[i] = -1;
-
- return n;
-}
-
-void
-freenode(Node *n)
-{
- if(freelist == nil)
- freelist = n;
- else
- *freeend = n;
- freeend = &n->link;
- n->link = nil;
-}
-
-Node**
-llookup(ulong key)
-{
- uint c;
- Node **l, **top, *n;
-
- if(nhash == 0){
- uint x;
-
- x = length/8;
- for(nhash=1; nhash<x; nhash<<=1)
- ;
- hash = sbrk(sizeof(Node*)*nhash);
- }
-
- top = &hash[key&(nhash-1)];
- c = 0;
- for(l=top; *l; l=&(*l)->link){
- c++;
- if((*l)->key == key){
- /* move to front */
- n = *l;
- *l = n->link;
- n->link = *top;
- *top = n;
- return top;
- }
- }
- if(c > maxlen)
- maxlen = c;
- return l;
-}
-
-Node*
-lookup(ulong key)
-{
- return *llookup(key);
-}
-
-void
-insertnode(ulong key, ulong offset)
-{
- int i;
- Node *n, **l;
-
- l = llookup(key);
- if(*l == nil){
- if(l==&hash[key&(nhash-1)])
- nnew++;
- *l = allocnode();
- (*l)->key = key;
- }
- n = *l;
-
- /* add or replace last */
- for(i=0; i<NOFF-1 && n->offset[i]!=-1; i++)
- ;
- n->offset[i] = offset;
-}
-
-void
-Bputint(Biobufhdr *b, int n)
-{
- uchar p[4];
-
- p[0] = n>>24;
- p[1] = n>>16;
- p[2] = n>>8;
- p[3] = n;
- Bwrite(b, p, 4);
-}
-
-void
-flushraw(void)
-{
- if(nraw){
- if(verbose)
- fprint(2, "Raw %d+%d\n", rawstart, nraw);
- zlength += 4+nraw;
- Bputint(&bout, (1<<31)|nraw);
- memmove(odat+nodat, data+rawstart, nraw);
- nodat += nraw;
- nraw = 0;
- }
-}
-
-int
-rawbyte(int i)
-{
- assert(acct == i);
- if(nraw == 0)
- rawstart = i;
- acct++;
- nraw++;
- return 1;
-}
-
-int
-refblock(int i, int len, int off)
-{
- assert(acct == i);
- acct += len;
- if(nraw)
- flushraw();
- if(verbose)
- fprint(2, "Copy %d+%d from %d\n", i, len, off);
- Bputint(&bout, len);
- Bputint(&bout, off);
- zlength += 4+4;
- return len;
-}
-
-int
-cmprun(uchar *a, uchar *b, int len)
-{
- int i;
-
- if(a==b)
- return 0;
- for(i=0; i<len && a[i]==b[i]; i++)
- ;
- return i;
-}
-
-int
-countrle(uchar *a)
-{
- int i;
-
- for(i=0; a[i]==a[0]; i++)
- ;
- return i;
-}
-
-void
-compress(void)
-{
- int best, i, j, o, rle, run, maxrun, maxoff;
- ulong sum;
- Node *n;
-
- sum = 0;
- for(i=0; i<win && i<length; i++)
- sum = (sum*256+data[i])%Prime;
- for(i=0; i<length-win; ){
- maxrun = 0;
- maxoff = 0;
- if(verbose)
- fprint(2, "look %.6lux\n", sum);
- n = lookup(sum);
- if(n){
- best = -1;
- for(o=0; o<NOFF; o++){
- if(n->offset[o] == -1)
- break;
- run = cmprun(data+i, data+n->offset[o], length-i);
- if(run > maxrun && n->offset[o]+mindist < i){
- maxrun = run;
- maxoff = n->offset[o];
- best = o;
- }
- }
- if(best > 0){
- o = n->offset[best];
- for(j=best; j>0; j--)
- n->offset[j] = n->offset[j-1];
- n->offset[0] = o;
- }
- }
-
- if(maxrun >= minrun)
- j = i+refblock(i, maxrun, maxoff);
- else
- j = i+rawbyte(i);
- for(; i<j; i++){
- /* avoid huge chains from large runs of same byte */
- rle = countrle(data+i);
- if(rle<4)
- insertnode(sum, i);
- else if(rle>maxrle[data[i]]){
- maxrle[data[i]] = rle;
- insertnode(sum, i);
- }
- sum = (sum*256+data[i+win]) % Prime;
- sum = (sum + data[i]*outn) % Prime;
- }
- }
- /* could do better here */
- for(; i<length; i++)
- rawbyte(i);
- flushraw();
-}
-
-void
-usage(void)
-{
- fprint(2, "usage: bflz [-n winsize] [file]\n");
- exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
- int fd, i, n;
- char buf[10485760];
-
- ARGBEGIN{
- case 'd':
- verbose = 1;
- break;
- case 's':
- replacesame = atoi(EARGF(usage()));
- break;
- case 'm':
- mindist = atoi(EARGF(usage()));
- break;
- case 'n':
- win = atoi(EARGF(usage()));
- minrun = win;
- break;
- default:
- usage();
- }ARGEND
-
- switch(argc){
- default:
- usage();
- case 0:
- fd = 0;
- break;
- case 1:
- if((fd = open(argv[0], OREAD)) < 0)
- sysfatal("open %s: %r", argv[0]);
- break;
- }
-
- while((n = readn(fd, buf, sizeof buf)) > 0){
- data = realloc(data, length+n);
- if(data == nil)
- sysfatal("realloc: %r");
- memmove(data+length, buf, n);
- length += n;
- if(n < sizeof buf)
- break;
- }
- odat = malloc(length);
- if(odat == nil)
- sysfatal("malloc: %r");
-
- Binit(&bout, 1, OWRITE);
- Bprint(&bout, "BLZ\n");
- Bputint(&bout, length);
- outn = 1;
- for(i=0; i<win; i++)
- outn = (outn * 256) % Prime;
-
- if(verbose)
- fprint(2, "256^%d = %.6lux\n", win, outn);
- outn = Prime - outn;
- if(verbose)
- fprint(2, "outn = %.6lux\n", outn);
-
- compress();
- Bwrite(&bout, odat, nodat);
- Bterm(&bout);
- fprint(2, "brk %p\n", sbrk(1));
- fprint(2, "%d nodes used; %d of %d hash slots used\n", nalloc, nnew, nhash);
- exits(nil);
-}
--- a/sys/lib/dist.old/cmd/bzfs/bzfs.h
+++ /dev/null
@@ -1,11 +1,0 @@
-int unbzip(int);
-void _unbzip(int, int);
-int unbflz(int);
-int xexpand(int);
-void *emalloc(ulong);
-void *erealloc(void*, ulong);
-char *estrdup(char*);
-
-void ramfsmain(int, char**);
-extern int chatty;
-void error(char*, ...);
--- a/sys/lib/dist.old/cmd/bzfs/mkext.c
+++ /dev/null
@@ -1,288 +1,0 @@
-/*
- * bzip2-based file system.
- * the file system itself is just a bzipped2 xzipped mkfs archive
- * prefixed with "bzfilesystem\n" and suffixed with
- * a kilobyte of zeros.
- *
- * changes to the file system are only kept in
- * memory, not written back to the disk.
- *
- * this is intended for use on a floppy boot disk.
- * we assume the file is in the dos file system and
- * contiguous on the disk: finding it amounts to
- * looking at the beginning of each sector for
- * "bzfilesystem\n". then we pipe it through
- * bunzip2 and store the files in a file tree in memory.
- * things are slightly complicated by the fact that
- * devfloppy requires reads to be on a 512-byte
- * boundary and be a multiple of 512 bytes; we
- * fork a process to relieve bunzip2 of this restriction.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <auth.h>
-#include <fcall.h>
-#include "bzfs.h"
-
-enum{
- LEN = 8*1024,
- NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
-};
-
-void mkdirs(char*, char*);
-void mkdir(char*, ulong, ulong, char*, char*);
-void extract(char*, ulong, ulong, char*, char*, ulong);
-void seekpast(ulong);
-void error(char*, ...);
-void warn(char*, ...);
-void usage(void);
-char *mtpt;
-Biobufhdr bin;
-uchar binbuf[2*LEN];
-
-void
-usage(void)
-{
- fprint(2, "usage: bzfs [-m mtpt] [-s] [-f file] [-h]\n");
- exits("usage");
-}
-
-/*
- * floppy disks can only be read on 512-byte
- * boundaries and in 512 byte multiples.
- * feed one over a pipe to allow arbitrary reading.
- */
-char zero[512];
-int
-blockread(int in, char *first, int nfirst)
-{
- int p[2], out, n, rv;
- char blk[512];
-
- if(pipe(p) < 0)
- sysfatal("pipe: %r");
- rv = p[0];
- out = p[1];
- switch(rfork(RFPROC|RFNOTEG|RFFDG)){
- case -1:
- sysfatal("fork: %r");
- case 0:
- close(rv);
- break;
- default:
- close(in);
- close(out);
- return rv;
- }
-
- write(out, first, nfirst);
-
- while((n=read(in, blk, sizeof blk)) > 0){
- if(write(out, blk, n) != n)
- break;
- if(n == sizeof(blk) && memcmp(zero, blk, n) == n)
- break;
- }
- _exits(0);
- return -1;
-}
-
-enum { NAMELEN = 28 };
-
-void
-main(int argc, char **argv)
-{
- char *rargv[10];
- int rargc;
- char *fields[NFLDS], name[2*LEN], *p, *namep;
- char uid[NAMELEN], gid[NAMELEN];
- ulong mode, bytes, mtime;
- char *file;
- int i, n, stdin, fd, chatty;
- char blk[512];
-
- if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
- argv[1] = argv[0];
- ramfsmain(argc-1, argv+1);
- exits(nil);
- }
- if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
- _unbzip(0, 1);
- exits(nil);
- }
-
- rfork(RFNOTEG);
- stdin = 0;
- file = nil;
- namep = name;
- mtpt = "/root";
- chatty = 0;
- ARGBEGIN{
- case 'd':
- chatty = !chatty;
- break;
- case 'f':
- file = ARGF();
- break;
- case 's':
- stdin++;
- break;
- case 'm':
- mtpt = ARGF();
- break;
- default:
- usage();
- }ARGEND
-
- if(argc != 0)
- usage();
-
- if(file == nil) {
- fprint(2, "must specify -f file\n");
- usage();
- }
-
- if((fd = open(file, OREAD)) < 0) {
- fprint(2, "cannot open \"%s\": %r\n", file);
- exits("open");
- }
-
- rargv[0] = "ramfs";
- rargc = 1;
- if(stdin)
- rargv[rargc++] = "-i";
- rargv[rargc++] = "-m";
- rargv[rargc++] = mtpt;
- rargv[rargc] = nil;
- ramfsmain(rargc, rargv);
-
- if(1 || strstr(file, "disk")) { /* search for archive on block boundary */
-if(chatty) fprint(2, "searching for bz\n");
- for(i=0;; i++){
- if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
- sysfatal("read %d gets %d: %r\n", i, n);
- if(strncmp(blk, "bzfilesystem\n", 13) == 0)
- break;
- }
-if(chatty) fprint(2, "found at %d\n", i);
- }
-
- if(chdir(mtpt) < 0)
- error("chdir %s: %r", mtpt);
-
- fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));
-
- Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
- while(p = Brdline(&bin, '\n')){
- p[Blinelen(&bin)-1] = '\0';
-if(chatty) fprint(2, "%s\n", p);
- if(strcmp(p, "end of archive") == 0){
- _exits(0);
- }
- if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
- warn("too few fields in file header");
- continue;
- }
- strcpy(namep, fields[0]);
- mode = strtoul(fields[1], 0, 8);
- mtime = strtoul(fields[4], 0, 10);
- bytes = strtoul(fields[5], 0, 10);
- strncpy(uid, fields[2], NAMELEN);
- strncpy(gid, fields[3], NAMELEN);
- if(mode & DMDIR)
- mkdir(name, mode, mtime, uid, gid);
- else
- extract(name, mode, mtime, uid, gid, bytes);
- }
- fprint(2, "premature end of archive\n");
- exits("premature end of archive");
-}
-
-char buf[8192];
-
-int
-ffcreate(char *name, ulong mode, char *uid, char *gid, ulong mtime, int length)
-{
- int fd, om;
- Dir nd;
-
- sprint(buf, "%s/%s", mtpt, name);
- om = ORDWR;
- if(mode&DMDIR)
- om = OREAD;
- if((fd = create(buf, om, (mode&DMDIR)|0666)) < 0)
- error("create %s: %r", buf);
-
- nulldir(&nd);
- nd.mode = mode;
- nd.uid = uid;
- nd.gid = gid;
- nd.mtime = mtime;
- if(length)
- nd.length = length;
- if(dirfwstat(fd, &nd) < 0)
- error("fwstat %s: %r", buf);
-
- return fd;
-}
-
-void
-mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
-{
- close(ffcreate(name, mode, uid, gid, mtime, 0));
-}
-
-void
-extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, ulong bytes)
-{
- int fd, tot, n;
-
- fd = ffcreate(name, mode, uid, gid, mtime, bytes);
-
- for(tot = 0; tot < bytes; tot += n){
- n = sizeof buf;
- if(tot + n > bytes)
- n = bytes - tot;
- n = Bread(&bin, buf, n);
- if(n <= 0)
- error("premature eof reading %s", name);
- if(write(fd, buf, n) != n)
- error("short write writing %s", name);
- }
- close(fd);
-}
-
-void
-error(char *fmt, ...)
-{
- char buf[1024];
- va_list arg;
-
- sprint(buf, "%s: ", argv0);
- va_start(arg, fmt);
- vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%s\n", buf);
- exits(0);
-}
-
-void
-warn(char *fmt, ...)
-{
- char buf[1024];
- va_list arg;
-
- sprint(buf, "%s: ", argv0);
- va_start(arg, fmt);
- vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%s\n", buf);
-}
-
-int
-_efgfmt(Fmt*)
-{
- return -1;
-}
--- a/sys/lib/dist.old/cmd/bzfs/mkfile
+++ /dev/null
@@ -1,20 +1,0 @@
-</$objtype/mkfile
-
-TARG=bzfs
-
-OFILES=\
- mkext.$O\
- oramfs.$O\
- unbflz.$O\
- unbzip.$O\
-
-HFILES=bzfs.h
-
-BIN=/sys/lib/dist/bin/$objtype
-LIB=/sys/src/cmd/bzip2/lib/libbzip2.a$O
-</sys/src/cmd/mkone
-
-CFLAGS=$CFLAGS -p -I/sys/src/cmd/bzip2/lib
-
-/sys/src/cmd/bzip2/lib/libbzip2.a$O:
- @{cd /sys/src/cmd/bzip2/lib && mk}
--- a/sys/lib/dist.old/cmd/bzfs/oramfs.c
+++ /dev/null
@@ -1,927 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "bzfs.h"
-
-/*
- * Rather than reading /adm/users, which is a lot of work for
- * a toy program, we assume all groups have the form
- * NNN:user:user:
- * meaning that each user is the leader of his own group.
- */
-
-enum
-{
- OPERM = 0x3, /* mask of all permission types in open mode */
- Nram = 512,
- Maxsize = 512*1024*1024,
- Maxfdata = 8192,
-};
-
-typedef struct Fid Fid;
-typedef struct Ram Ram;
-
-struct Fid
-{
- short busy;
- short open;
- short rclose;
- int fid;
- Fid *next;
- char *user;
- Ram *ram;
-};
-
-struct Ram
-{
- short busy;
- short open;
- long parent; /* index in Ram array */
- Qid qid;
- long perm;
- char *name;
- ulong atime;
- ulong mtime;
- char *user;
- char *group;
- char *muid;
- char *data;
- long ndata;
-};
-
-enum
-{
- Pexec = 1,
- Pwrite = 2,
- Pread = 4,
- Pother = 1,
- Pgroup = 8,
- Powner = 64,
-};
-
-ulong path; /* incremented for each new file */
-Fid *fids;
-Ram ram[Nram];
-int nram;
-int mfd[2];
-char *user;
-uchar mdata[IOHDRSZ+Maxfdata];
-uchar rdata[Maxfdata]; /* buffer for data in reply */
-uchar statbuf[STATMAX];
-Fcall thdr;
-Fcall rhdr;
-int messagesize = sizeof mdata;
-
-Fid * newfid(int);
-uint ramstat(Ram*, uchar*, uint);
-void io(void);
-void *erealloc(void*, ulong);
-void *emalloc(ulong);
-char *estrdup(char*);
-void ramfsusage(void);
-int perm(Fid*, Ram*, int);
-char *atom(char*);
-
-char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
- *rattach(Fid*), *rwalk(Fid*),
- *ropen(Fid*), *rcreate(Fid*),
- *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
- *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
-
-char *(*fcalls[])(Fid*) = {
- [Tversion] rversion,
- [Tflush] rflush,
- [Tauth] rauth,
- [Tattach] rattach,
- [Twalk] rwalk,
- [Topen] ropen,
- [Tcreate] rcreate,
- [Tread] rread,
- [Twrite] rwrite,
- [Tclunk] rclunk,
- [Tremove] rremove,
- [Tstat] rstat,
- [Twstat] rwstat,
-};
-
-char Eperm[] = "permission denied";
-char Enotdir[] = "not a directory";
-char Enoauth[] = "no authentication in ramfs";
-char Enotexist[] = "file does not exist";
-char Einuse[] = "file in use";
-char Eexist[] = "file exists";
-char Eisdir[] = "file is a directory";
-char Enotowner[] = "not owner";
-char Eisopen[] = "file already open for I/O";
-char Excl[] = "exclusive use file already open";
-char Ename[] = "illegal name";
-char Eversion[] = "unknown 9P version";
-
-int debug;
-
-void
-notifyf(void *a, char *s)
-{
- USED(a);
- if(strncmp(s, "interrupt", 9) == 0)
- noted(NCONT);
- noted(NDFLT);
-}
-
-void
-ramfsmain(int argc, char *argv[])
-{
- Ram *r;
- char *defmnt;
- int p[2];
- char buf[32];
- int fd, srvfd;
- int stdio = 0;
-
- srvfd = -1;
- defmnt = "/tmp";
- ARGBEGIN{
- case 'D':
- debug = 1;
- break;
- case 'i': /* this is DIFFERENT from normal ramfs; use 1 for both for kernel */
- defmnt = 0;
- stdio = 1;
- srvfd = 0;
- mfd[0] = 1;
- mfd[1] = 1;
- break;
- case 's':
- defmnt = 0;
- break;
- case 'm':
- defmnt = ARGF();
- break;
- default:
- ramfsusage();
- }ARGEND
-
- if(!stdio){
- if(pipe(p) < 0)
- error("pipe failed");
- srvfd = p[1];
- mfd[0] = p[0];
- mfd[1] = p[0];
- if(defmnt == 0){
- fd = create("#s/ramfs", OWRITE, 0666);
- if(fd < 0)
- error("create of /srv/ramfs failed");
- sprint(buf, "%d", p[1]);
- if(write(fd, buf, strlen(buf)) < 0)
- error("writing /srv/ramfs");
- }
- }
-
- user = atom(getuser());
- notify(notifyf);
- nram = 1;
- r = &ram[0];
- r->busy = 1;
- r->data = 0;
- r->ndata = 0;
- r->perm = DMDIR | 0775;
- r->qid.type = QTDIR;
- r->qid.path = 0LL;
- r->qid.vers = 0;
- r->parent = 0;
- r->user = user;
- r->group = user;
- r->muid = user;
- r->atime = time(0);
- r->mtime = r->atime;
- r->name = estrdup(".");
-
- if(debug)
- fmtinstall('F', fcallfmt);
- switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
- case -1:
- error("fork");
- case 0:
- close(srvfd);
- io();
- break;
- default:
- close(mfd[0]); /* don't deadlock if child fails */
- if(defmnt && mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
- error("mount failed: %r");
- }
-}
-
-char*
-rversion(Fid*)
-{
- Fid *f;
-
- for(f = fids; f; f = f->next)
- if(f->busy)
- rclunk(f);
- if(thdr.msize > sizeof mdata)
- rhdr.msize = sizeof mdata;
- else
- rhdr.msize = thdr.msize;
- messagesize = rhdr.msize;
- if(strncmp(thdr.version, "9P2000", 6) != 0)
- return Eversion;
- rhdr.version = "9P2000";
- return 0;
-}
-
-char*
-rauth(Fid*)
-{
- return "ramfs: no authentication required";
-}
-
-char*
-rflush(Fid *f)
-{
- USED(f);
- return 0;
-}
-
-char*
-rattach(Fid *f)
-{
- /* no authentication! */
- f->busy = 1;
- f->rclose = 0;
- f->ram = &ram[0];
- rhdr.qid = f->ram->qid;
- if(thdr.uname[0])
- f->user = atom(thdr.uname);
- else
- f->user = atom("none");
- if(strcmp(user, "none") == 0)
- user = f->user;
- return 0;
-}
-
-char*
-clone(Fid *f, Fid **nf)
-{
- if(f->open)
- return Eisopen;
- if(f->ram->busy == 0)
- return Enotexist;
- *nf = newfid(thdr.newfid);
- (*nf)->busy = 1;
- (*nf)->open = 0;
- (*nf)->rclose = 0;
- (*nf)->ram = f->ram;
- (*nf)->user = f->user; /* no ref count; the leakage is minor */
- return 0;
-}
-
-char*
-rwalk(Fid *f)
-{
- Ram *r, *fram;
- char *name;
- Ram *parent;
- Fid *nf;
- char *err;
- ulong t;
- int i;
-
- err = nil;
- nf = nil;
- rhdr.nwqid = 0;
- if(rhdr.newfid != rhdr.fid){
- err = clone(f, &nf);
- if(err)
- return err;
- f = nf; /* walk the new fid */
- }
- fram = f->ram;
- if(thdr.nwname > 0){
- t = time(0);
- for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
- if((fram->qid.type & QTDIR) == 0){
- err = Enotdir;
- break;
- }
- if(fram->busy == 0){
- err = Enotexist;
- break;
- }
- fram->atime = t;
- name = thdr.wname[i];
- if(strcmp(name, ".") == 0){
- Found:
- rhdr.nwqid++;
- rhdr.wqid[i] = fram->qid;
- continue;
- }
- parent = &ram[fram->parent];
-#ifdef CHECKS
- if(!perm(f, parent, Pexec)){
- err = Eperm;
- break;
- }
-#endif
- if(strcmp(name, "..") == 0){
- fram = parent;
- goto Found;
- }
- for(r=ram; r < &ram[nram]; r++)
- if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){
- fram = r;
- goto Found;
- }
- break;
- }
- if(i==0 && err == nil)
- err = Enotexist;
- }
- if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
- /* clunk the new fid, which is the one we walked */
- f->busy = 0;
- f->ram = nil;
- }
- if(rhdr.nwqid == thdr.nwname) /* update the fid after a successful walk */
- f->ram = fram;
- return err;
-}
-
-char *
-ropen(Fid *f)
-{
- Ram *r;
- int mode, trunc;
-
- if(f->open)
- return Eisopen;
- r = f->ram;
- if(r->busy == 0)
- return Enotexist;
- if(r->perm & DMEXCL)
- if(r->open)
- return Excl;
- mode = thdr.mode;
- if(r->qid.type & QTDIR){
- if(mode != OREAD)
- return Eperm;
- rhdr.qid = r->qid;
- return 0;
- }
- if(mode & ORCLOSE){
- /* can't remove root; must be able to write parent */
- if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))
- return Eperm;
- f->rclose = 1;
- }
- trunc = mode & OTRUNC;
- mode &= OPERM;
- if(mode==OWRITE || mode==ORDWR || trunc)
- if(!perm(f, r, Pwrite))
- return Eperm;
- if(mode==OREAD || mode==ORDWR)
- if(!perm(f, r, Pread))
- return Eperm;
- if(mode==OEXEC)
- if(!perm(f, r, Pexec))
- return Eperm;
- if(trunc && (r->perm&DMAPPEND)==0){
- r->ndata = 0;
- if(r->data)
- free(r->data);
- r->data = 0;
- r->qid.vers++;
- }
- rhdr.qid = r->qid;
- rhdr.iounit = messagesize-IOHDRSZ;
- f->open = 1;
- r->open++;
- return 0;
-}
-
-char *
-rcreate(Fid *f)
-{
- Ram *r;
- char *name;
- long parent, prm;
-
- if(f->open)
- return Eisopen;
- if(f->ram->busy == 0)
- return Enotexist;
- parent = f->ram - ram;
- if((f->ram->qid.type&QTDIR) == 0)
- return Enotdir;
- /* must be able to write parent */
-#ifdef CHECKS
- if(!perm(f, f->ram, Pwrite))
- return Eperm;
-#endif
- prm = thdr.perm;
- name = thdr.name;
- if(strcmp(name, ".")==0 || strcmp(name, "..")==0)
- return Ename;
- for(r=ram; r<&ram[nram]; r++)
- if(r->busy && parent==r->parent)
- if(strcmp((char*)name, r->name)==0)
- return Einuse;
- for(r=ram; r->busy; r++)
- if(r == &ram[Nram-1])
- return "no free ram resources";
- r->busy = 1;
- r->qid.path = ++path;
- r->qid.vers = 0;
- if(prm & DMDIR)
- r->qid.type |= QTDIR;
- r->parent = parent;
- free(r->name);
- r->name = estrdup(name);
- r->user = f->user;
- r->group = f->ram->group;
- r->muid = f->ram->muid;
- if(prm & DMDIR)
- prm = (prm&~0777) | (f->ram->perm&prm&0777);
- else
- prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);
- r->perm = prm;
- r->ndata = 0;
- if(r-ram >= nram)
- nram = r - ram + 1;
- r->atime = time(0);
- r->mtime = r->atime;
- f->ram->mtime = r->atime;
- f->ram = r;
- rhdr.qid = r->qid;
- rhdr.iounit = messagesize-IOHDRSZ;
- f->open = 1;
- if(thdr.mode & ORCLOSE)
- f->rclose = 1;
- r->open++;
- return 0;
-}
-
-char*
-rread(Fid *f)
-{
- Ram *r;
- uchar *buf;
- long off;
- int n, m, cnt;
-
- if(f->ram->busy == 0)
- return Enotexist;
- n = 0;
- rhdr.count = 0;
- off = thdr.offset;
- buf = rdata;
- cnt = thdr.count;
- if(cnt > messagesize) /* shouldn't happen, anyway */
- cnt = messagesize;
- if(f->ram->qid.type & QTDIR){
- for(r=ram+1; off > 0; r++){
- if(r->busy && r->parent==f->ram-ram)
- off -= ramstat(r, statbuf, sizeof statbuf);
- if(r == &ram[nram-1])
- return 0;
- }
- for(; r<&ram[nram] && n < cnt; r++){
- if(!r->busy || r->parent!=f->ram-ram)
- continue;
- m = ramstat(r, buf+n, cnt-n);
- if(m == 0)
- break;
- n += m;
- }
- rhdr.data = (char*)rdata;
- rhdr.count = n;
- return 0;
- }
- r = f->ram;
- if(off >= r->ndata)
- return 0;
- r->atime = time(0);
- n = cnt;
- if(off+n > r->ndata)
- n = r->ndata - off;
- rhdr.data = r->data+off;
- rhdr.count = n;
- return 0;
-}
-
-char*
-rwrite(Fid *f)
-{
- Ram *r;
- ulong off;
- int cnt;
-
- r = f->ram;
- if(r->busy == 0)
- return Enotexist;
- off = thdr.offset;
- if(r->perm & DMAPPEND)
- off = r->ndata;
- cnt = thdr.count;
- if(r->qid.type & QTDIR)
- return Eisdir;
- if(off+cnt >= Maxsize) /* sanity check */
- return "write too big";
- if(off+cnt > r->ndata)
- r->data = erealloc(r->data, off+cnt);
- if(off > r->ndata)
- memset(r->data+r->ndata, 0, off-r->ndata);
- if(off+cnt > r->ndata)
- r->ndata = off+cnt;
- memmove(r->data+off, thdr.data, cnt);
- r->qid.vers++;
- r->mtime = time(0);
- rhdr.count = cnt;
- return 0;
-}
-
-void
-realremove(Ram *r)
-{
- r->ndata = 0;
- if(r->data)
- free(r->data);
- r->data = 0;
- r->parent = 0;
- memset(&r->qid, 0, sizeof r->qid);
- free(r->name);
- r->name = nil;
- r->busy = 0;
-}
-
-char *
-rclunk(Fid *f)
-{
- if(f->open)
- f->ram->open--;
- if(f->rclose)
- realremove(f->ram);
- f->busy = 0;
- f->open = 0;
- f->ram = 0;
- return 0;
-}
-
-char *
-rremove(Fid *f)
-{
- Ram *r;
-
- if(f->open)
- f->ram->open--;
- f->busy = 0;
- f->open = 0;
- r = f->ram;
- f->ram = 0;
-#ifdef CHECKS
- if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))
- return Eperm;
-#endif
- ram[r->parent].mtime = time(0);
- realremove(r);
- return 0;
-}
-
-char *
-rstat(Fid *f)
-{
- if(f->ram->busy == 0)
- return Enotexist;
- rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);
- rhdr.stat = statbuf;
- return 0;
-}
-
-char *
-rwstat(Fid *f)
-{
- Ram *r, *s;
- Dir dir;
-
- if(f->ram->busy == 0)
- return Enotexist;
- convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);
- r = f->ram;
-
- /*
- * To change length, must have write permission on file.
- */
-#ifdef CHECKS
- if(dir.length!=~0 && dir.length!=r->ndata){
- if(!perm(f, r, Pwrite))
- return Eperm;
- }
-#endif
-
- /*
- * To change name, must have write permission in parent
- * and name must be unique.
- */
- if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){
-#ifdef CHECKS
- if(!perm(f, &ram[r->parent], Pwrite))
- return Eperm;
-#endif
- for(s=ram; s<&ram[nram]; s++)
- if(s->busy && s->parent==r->parent)
- if(strcmp(dir.name, s->name)==0)
- return Eexist;
- }
-
-#ifdef OWNERS
- /*
- * To change mode, must be owner or group leader.
- * Because of lack of users file, leader=>group itself.
- */
- if(dir.mode!=~0 && r->perm!=dir.mode){
- if(strcmp(f->user, r->user) != 0)
- if(strcmp(f->user, r->group) != 0)
- return Enotowner;
- }
-
- /*
- * To change group, must be owner and member of new group,
- * or leader of current group and leader of new group.
- * Second case cannot happen, but we check anyway.
- */
- if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){
- if(strcmp(f->user, r->user) == 0)
- if(strcmp(f->user, dir.gid) == 0)
- goto ok;
- if(strcmp(f->user, r->group) == 0)
- if(strcmp(f->user, dir.gid) == 0)
- goto ok;
- return Enotowner;
- ok:;
- }
-#endif
-
- /* all ok; do it */
- if(dir.mode != ~0){
- dir.mode &= ~DMDIR; /* cannot change dir bit */
- dir.mode |= r->perm&DMDIR;
- r->perm = dir.mode;
- }
- if(dir.name[0] != '\0'){
- free(r->name);
- r->name = estrdup(dir.name);
- }
- if(dir.gid[0] != '\0')
- r->group = atom(dir.gid);
-
- if(dir.uid[0] != '\0')
- r->user = atom(dir.uid);
-
- if(dir.length!=~0 && dir.length!=r->ndata){
- r->data = erealloc(r->data, dir.length);
- if(r->ndata < dir.length)
- memset(r->data+r->ndata, 0, dir.length-r->ndata);
- r->ndata = dir.length;
- }
-
- if(dir.mtime != ~0)
- r->mtime = dir.mtime;
-
- ram[r->parent].mtime = time(0);
- return 0;
-}
-
-uint
-ramstat(Ram *r, uchar *buf, uint nbuf)
-{
- Dir dir;
-
- dir.name = r->name;
- dir.qid = r->qid;
- dir.mode = r->perm;
- dir.length = r->ndata;
- dir.uid = r->user;
- dir.gid = r->group;
- dir.muid = r->muid;
- dir.atime = r->atime;
- dir.mtime = r->mtime;
- return convD2M(&dir, buf, nbuf);
-}
-
-Fid *
-newfid(int fid)
-{
- Fid *f, *ff;
-
- ff = 0;
- for(f = fids; f; f = f->next)
- if(f->fid == fid)
- return f;
- else if(!ff && !f->busy)
- ff = f;
- if(ff){
- ff->fid = fid;
- return ff;
- }
- f = emalloc(sizeof *f);
- f->ram = nil;
- f->fid = fid;
- f->next = fids;
- fids = f;
- return f;
-}
-
-void
-io(void)
-{
- char *err;
- int n, pid;
-
- pid = getpid();
-
- for(;;){
- /*
- * reading from a pipe or a network device
- * will give an error after a few eof reads.
- * however, we cannot tell the difference
- * between a zero-length read and an interrupt
- * on the processes writing to us,
- * so we wait for the error.
- */
- n = read9pmsg(mfd[0], mdata, messagesize);
- if(n < 0)
- error("mount read: %r");
- if(n == 0)
- continue;
- if(convM2S(mdata, n, &thdr) == 0)
- continue;
-
- if(debug)
- fprint(2, "ramfs %d:<-%F\n", pid, &thdr);
-
- if(!fcalls[thdr.type])
- err = "bad fcall type";
- else
- err = (*fcalls[thdr.type])(newfid(thdr.fid));
- if(err){
- rhdr.type = Rerror;
- rhdr.ename = err;
- }else{
- rhdr.type = thdr.type + 1;
- rhdr.fid = thdr.fid;
- }
- rhdr.tag = thdr.tag;
- if(debug)
- fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/
- n = convS2M(&rhdr, mdata, messagesize);
- if(n == 0)
- error("convS2M error on write");
- if(write(mfd[1], mdata, n) != n)
- error("mount write");
- }
-}
-
-int
-perm(Fid *f, Ram *r, int p)
-{
- if((p*Pother) & r->perm)
- return 1;
- if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
- return 1;
- if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
- return 1;
- return 0;
-}
-
-void *
-emalloc(ulong n)
-{
- void *p;
-
- p = malloc(n);
- if(!p)
- error("out of memory");
- memset(p, 0, n);
- return p;
-}
-
-void *
-erealloc(void *p, ulong n)
-{
- p = realloc(p, n);
- if(!p)
- error("out of memory");
- return p;
-}
-
-char *
-estrdup(char *q)
-{
- char *p;
- int n;
-
- n = strlen(q)+1;
- p = malloc(n);
- if(!p)
- error("out of memory");
- memmove(p, q, n);
- return p;
-}
-
-void
-ramfsusage(void)
-{
- fprint(2, "usage: %s [-is] [-m mountpoint]\n", argv0);
- exits("usage");
-}
-
-/*
- * Custom allocators to avoid malloc overheads on small objects.
- * We never free these. (See below.)
- */
-typedef struct Stringtab Stringtab;
-struct Stringtab {
- Stringtab *link;
- char *str;
-};
-static Stringtab*
-taballoc(void)
-{
- static Stringtab *t;
- static uint nt;
-
- if(nt == 0){
- t = malloc(64*sizeof(Stringtab));
- if(t == 0)
- sysfatal("out of memory");
- nt = 64;
- }
- nt--;
- return t++;
-}
-
-static char*
-xstrdup(char *s)
-{
- char *r;
- int len;
- static char *t;
- static int nt;
-
- len = strlen(s)+1;
- if(len >= 8192)
- sysfatal("strdup big string");
-
- if(nt < len){
- t = malloc(8192);
- if(t == 0)
- sysfatal("out of memory");
- nt = 8192;
- }
- r = t;
- t += len;
- nt -= len;
- strcpy(r, s);
- return r;
-}
-
-/*
- * Return a uniquely allocated copy of a string.
- * Don't free these -- they stay in the table for the
- * next caller who wants that particular string.
- * String comparison can be done with pointer comparison
- * if you know both strings are atoms.
- */
-static Stringtab *stab[1024];
-
-static uint
-hash(char *s)
-{
- uint h;
- uchar *p;
-
- h = 0;
- for(p=(uchar*)s; *p; p++)
- h = h*37 + *p;
- return h;
-}
-
-char*
-atom(char *str)
-{
- uint h;
- Stringtab *tab;
-
- h = hash(str) % nelem(stab);
- for(tab=stab[h]; tab; tab=tab->link)
- if(strcmp(str, tab->str) == 0)
- return tab->str;
-
- tab = taballoc();
- tab->str = xstrdup(str);
- tab->link = stab[h];
- stab[h] = tab;
- return tab->str;
-}
--- a/sys/lib/dist.old/cmd/bzfs/unbflz.c
+++ /dev/null
@@ -1,108 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "bzfs.h"
-
-int
-Bgetint(Biobuf *b)
-{
- uchar p[4];
-
- if(Bread(b, p, 4) != 4)
- sysfatal("short read");
- return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-}
-
-/*
- * memmove but make sure overlap works properly.
- */
-void
-copy(uchar *dst, uchar *src, int n)
-{
- while(n-- > 0)
- *dst++ = *src++;
-}
-
-int
-unbflz(int in)
-{
- int rv, out, p[2];
- Biobuf *b, bin;
- char buf[5];
- uchar *data;
- int i, j, length, n, m, o, sum;
- ulong *blk;
- int nblk, mblk;
-
- if(pipe(p) < 0)
- sysfatal("pipe: %r");
-
- rv = p[0];
- out = p[1];
- switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
- case -1:
- sysfatal("fork: %r");
- case 0:
- close(rv);
- break;
- default:
- close(in);
- close(out);
- return rv;
- }
-
- Binit(&bin, in, OREAD);
- b = &bin;
-
- if(Bread(b, buf, 4) != 4)
- sysfatal("short read");
-
- if(memcmp(buf, "BLZ\n", 4) != 0)
- sysfatal("bad header");
-
- length = Bgetint(b);
- data = malloc(length);
- if(data == nil)
- sysfatal("out of memory");
- sum = 0;
- nblk = 0;
- mblk = 0;
- blk = nil;
- while(sum < length){
- if(nblk>=mblk){
- mblk += 16384;
- blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
- if(blk == nil)
- sysfatal("out of memory");
- }
- n = Bgetint(b);
- blk[nblk++] = n;
- if(n&(1<<31))
- n &= ~(1<<31);
- else
- blk[nblk++] = Bgetint(b);
- sum += n;
- }
- if(sum != length)
- sysfatal("bad compressed data %d %d", sum, length);
- i = 0;
- j = 0;
- while(i < length){
- assert(j < nblk);
- n = blk[j++];
- if(n&(1<<31)){
- n &= ~(1<<31);
- if((m=Bread(b, data+i, n)) != n)
- sysfatal("short read %d %d", n, m);
- }else{
- o = blk[j++];
- copy(data+i, data+o, n);
- }
- i += n;
- }
- write(out, data, length);
- close(in);
- close(out);
- _exits(0);
- return -1;
-}
--- a/sys/lib/dist.old/cmd/bzfs/unbzip.c
+++ /dev/null
@@ -1,861 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include "bzfs.h"
-
-/*
- * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
- * FROM THE BZIP2 DISTRIBUTION.
- *
- * It has been modified, mainly to break the library
- * into smaller pieces.
- *
- * Russ Cox
- * [email protected]
- * July 2000
- */
-
-/*---------------------------------------------*/
-/*--
- Place a 1 beside your platform, and 0 elsewhere.
- Attempts to autosniff this even if you don't.
---*/
-
-
-/*--
- Plan 9 from Bell Labs
---*/
-#define BZ_PLAN9 1
-#define BZ_UNIX 0
-
-#define exit(x) exits((x) ? "whoops" : nil)
-#define size_t ulong
-
-#ifdef __GNUC__
-# define NORETURN __attribute__ ((noreturn))
-#else
-# define NORETURN /**/
-#endif
-
-/*--
- Some more stuff for all platforms :-)
- This might have to get moved into the platform-specific
- header files if we encounter a machine with different sizes.
---*/
-
-typedef char Char;
-typedef unsigned char Bool;
-typedef unsigned char UChar;
-typedef int Int32;
-typedef unsigned int UInt32;
-typedef short Int16;
-typedef unsigned short UInt16;
-
-#define True ((Bool)1)
-#define False ((Bool)0)
-
-/*--
- IntNative is your platform's `native' int size.
- Only here to avoid probs with 64-bit platforms.
---*/
-typedef int IntNative;
-
-#include "bzfs.h"
-#include "bzlib.h"
-#include "bzlib_private.h"
-
-static int
-bunzip(int ofd, char *ofile, Biobuf *bin)
-{
- int e, n, done, onemore;
- char buf[8192];
- char obuf[8192];
- Biobuf bout;
- bz_stream strm;
-
- USED(ofile);
-
- memset(&strm, 0, sizeof strm);
- BZ2_bzDecompressInit(&strm, 0, 0);
-
- strm.next_in = buf;
- strm.avail_in = 0;
- strm.next_out = obuf;
- strm.avail_out = sizeof obuf;
-
- done = 0;
- Binit(&bout, ofd, OWRITE);
-
- /*
- * onemore is a crummy hack to go 'round the loop
- * once after we finish, to flush the output buffer.
- */
- onemore = 1;
- SET(e);
- do {
- if(!done && strm.avail_in < sizeof buf) {
- if(strm.avail_in)
- memmove(buf, strm.next_in, strm.avail_in);
-
- n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
- if(n <= 0)
- done = 1;
- else
- strm.avail_in += n;
- strm.next_in = buf;
- }
- if(strm.avail_out < sizeof obuf) {
- Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
- strm.next_out = obuf;
- strm.avail_out = sizeof obuf;
- }
-
- if(onemore == 0)
- break;
- } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
-
- if(e != BZ_STREAM_END) {
- fprint(2, "bunzip2: decompress failed\n");
- return 0;
- }
-
- if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
- fprint(2, "bunzip2: decompress end failed (can't happen)\n");
- return 0;
- }
-
- Bterm(&bout);
-
- return 1;
-}
-
-void
-_unbzip(int in, int out)
-{
- Biobuf bin;
-
- Binit(&bin, in, OREAD);
- if(bunzip(out, nil, &bin) != 1) {
- fprint(2, "bunzip2 failed\n");
- _exits("bunzip2");
- }
-}
-
-int
-unbzip(int in)
-{
- int rv, out, p[2];
-
- if(pipe(p) < 0)
- sysfatal("pipe: %r");
-
- rv = p[0];
- out = p[1];
- switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
- case -1:
- sysfatal("fork: %r");
- case 0:
- close(rv);
- break;
- default:
- close(in);
- close(out);
- return rv;
- }
-
- _unbzip(in, out);
- _exits(0);
- return -1; /* not reached */
-}
-
-int bz_config_ok ( void )
-{
- if (sizeof(int) != 4) return 0;
- if (sizeof(short) != 2) return 0;
- if (sizeof(char) != 1) return 0;
- return 1;
-}
-
-void* default_bzalloc(void *o, int items, int size)
-{
- USED(o);
- return sbrk(items*size);
-}
-
-void default_bzfree(void*, void*)
-{
-}
-
-void
-bz_internal_error(int)
-{
- abort();
-}
-
-/*-------------------------------------------------------------*/
-/*--- Decompression machinery ---*/
-/*--- decompress.c ---*/
-/*-------------------------------------------------------------*/
-
-/*--
- This file is a part of bzip2 and/or libbzip2, a program and
- library for lossless, block-sorting data compression.
-
- Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Julian Seward, Cambridge, UK.
- [email protected]
- bzip2/libbzip2 version 1.0 of 21 March 2000
-
- This program is based on (at least) the work of:
- Mike Burrows
- David Wheeler
- Peter Fenwick
- Alistair Moffat
- Radford Neal
- Ian H. Witten
- Robert Sedgewick
- Jon L. Bentley
-
- For more information on these sources, see the manual.
---*/
-
-
-
-/*---------------------------------------------------*/
-static
-void makeMaps_d ( DState* s )
-{
- Int32 i;
- s->nInUse = 0;
- for (i = 0; i < 256; i++)
- if (s->inUse[i]) {
- s->seqToUnseq[s->nInUse] = i;
- s->nInUse++;
- }
-}
-
-
-/*---------------------------------------------------*/
-#define RETURN(rrr) \
- { retVal = rrr; goto save_state_and_return; };
-
-#define GET_BITS(lll,vvv,nnn) \
- case lll: \
- { int x; if((retVal = getbits(s, lll, &x, nnn)) != 99) \
- goto save_state_and_return; vvv=x; }\
-
-int
-getbits(DState *s, int lll, int *vvv, int nnn)
-{
- s->state = lll;
-
- for(;;) {
- if (s->bsLive >= nnn) {
- UInt32 v;
- v = (s->bsBuff >>
- (s->bsLive-nnn)) & ((1 << nnn)-1);
- s->bsLive -= nnn;
- *vvv = v;
- return 99;
- }
- if (s->strm->avail_in == 0) return BZ_OK;
- s->bsBuff
- = (s->bsBuff << 8) |
- ((UInt32)
- (*((UChar*)(s->strm->next_in))));
- s->bsLive += 8;
- s->strm->next_in++;
- s->strm->avail_in--;
- s->strm->total_in_lo32++;
- if (s->strm->total_in_lo32 == 0)
- s->strm->total_in_hi32++;
- }
- return -1; /* KEN */
-}
-
-#define GET_UCHAR(lll,uuu) \
- GET_BITS(lll,uuu,8)
-
-#define GET_BIT(lll,uuu) \
- GET_BITS(lll,uuu,1)
-
-/*---------------------------------------------------*/
-#define GET_MTF_VAL(label1,label2,lval) \
-{ \
- if (groupPos == 0) { \
- groupNo++; \
- if (groupNo >= nSelectors) \
- RETURN(BZ_DATA_ERROR); \
- groupPos = BZ_G_SIZE; \
- gSel = s->selector[groupNo]; \
- gMinlen = s->minLens[gSel]; \
- gLimit = &(s->limit[gSel][0]); \
- gPerm = &(s->perm[gSel][0]); \
- gBase = &(s->base[gSel][0]); \
- } \
- groupPos--; \
- zn = gMinlen; \
- GET_BITS(label1, zvec, zn); \
- while (1) { \
- if (zn > 20 /* the longest code */) \
- RETURN(BZ_DATA_ERROR); \
- if (zvec <= gLimit[zn]) break; \
- zn++; \
- GET_BIT(label2, zj); \
- zvec = (zvec << 1) | zj; \
- }; \
- if (zvec - gBase[zn] < 0 \
- || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
- RETURN(BZ_DATA_ERROR); \
- lval = gPerm[zvec - gBase[zn]]; \
-}
-
-
-/*---------------------------------------------------*/
-Int32 BZ2_decompress ( DState* s )
-{
- UChar uc;
- Int32 retVal;
- Int32 minLen, maxLen;
- bz_stream* strm = s->strm;
-
- /* stuff that needs to be saved/restored */
- Int32 i;
- Int32 j;
- Int32 t;
- Int32 alphaSize;
- Int32 nGroups;
- Int32 nSelectors;
- Int32 EOB;
- Int32 groupNo;
- Int32 groupPos;
- Int32 nextSym;
- Int32 nblockMAX;
- Int32 nblock;
- Int32 es;
- Int32 N;
- Int32 curr;
- Int32 zt;
- Int32 zn;
- Int32 zvec;
- Int32 zj;
- Int32 gSel;
- Int32 gMinlen;
- Int32* gLimit;
- Int32* gBase;
- Int32* gPerm;
-
- if (s->state == BZ_X_MAGIC_1) {
- /*initialise the save area*/
- s->save_i = 0;
- s->save_j = 0;
- s->save_t = 0;
- s->save_alphaSize = 0;
- s->save_nGroups = 0;
- s->save_nSelectors = 0;
- s->save_EOB = 0;
- s->save_groupNo = 0;
- s->save_groupPos = 0;
- s->save_nextSym = 0;
- s->save_nblockMAX = 0;
- s->save_nblock = 0;
- s->save_es = 0;
- s->save_N = 0;
- s->save_curr = 0;
- s->save_zt = 0;
- s->save_zn = 0;
- s->save_zvec = 0;
- s->save_zj = 0;
- s->save_gSel = 0;
- s->save_gMinlen = 0;
- s->save_gLimit = NULL;
- s->save_gBase = NULL;
- s->save_gPerm = NULL;
- }
-
- /*restore from the save area*/
- i = s->save_i;
- j = s->save_j;
- t = s->save_t;
- alphaSize = s->save_alphaSize;
- nGroups = s->save_nGroups;
- nSelectors = s->save_nSelectors;
- EOB = s->save_EOB;
- groupNo = s->save_groupNo;
- groupPos = s->save_groupPos;
- nextSym = s->save_nextSym;
- nblockMAX = s->save_nblockMAX;
- nblock = s->save_nblock;
- es = s->save_es;
- N = s->save_N;
- curr = s->save_curr;
- zt = s->save_zt;
- zn = s->save_zn;
- zvec = s->save_zvec;
- zj = s->save_zj;
- gSel = s->save_gSel;
- gMinlen = s->save_gMinlen;
- gLimit = s->save_gLimit;
- gBase = s->save_gBase;
- gPerm = s->save_gPerm;
-
- retVal = BZ_OK;
-
- switch (s->state) {
-
- GET_UCHAR(BZ_X_MAGIC_1, uc);
- if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
-
- GET_UCHAR(BZ_X_MAGIC_2, uc);
- if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
-
- GET_UCHAR(BZ_X_MAGIC_3, uc)
- if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
-
- GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
- if (s->blockSize100k < '1' ||
- s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
- s->blockSize100k -= '0';
-
- if (0 && s->smallDecompress) {
- s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
- s->ll4 = BZALLOC(
- ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
- );
- if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
- } else {
- s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
- if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
- }
-
- GET_UCHAR(BZ_X_BLKHDR_1, uc);
-
- if (uc == 0x17) goto endhdr_2;
- if (uc != 0x31) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_BLKHDR_2, uc);
- if (uc != 0x41) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_BLKHDR_3, uc);
- if (uc != 0x59) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_BLKHDR_4, uc);
- if (uc != 0x26) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_BLKHDR_5, uc);
- if (uc != 0x53) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_BLKHDR_6, uc);
- if (uc != 0x59) RETURN(BZ_DATA_ERROR);
-
- s->currBlockNo++;
- // if (s->verbosity >= 2)
- // VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
-
- s->storedBlockCRC = 0;
- GET_UCHAR(BZ_X_BCRC_1, uc);
- s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_BCRC_2, uc);
- s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_BCRC_3, uc);
- s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_BCRC_4, uc);
- s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
-
- GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
-
- s->origPtr = 0;
- GET_UCHAR(BZ_X_ORIGPTR_1, uc);
- s->origPtr = (s->origPtr << 8) | ((Int32)uc);
- GET_UCHAR(BZ_X_ORIGPTR_2, uc);
- s->origPtr = (s->origPtr << 8) | ((Int32)uc);
- GET_UCHAR(BZ_X_ORIGPTR_3, uc);
- s->origPtr = (s->origPtr << 8) | ((Int32)uc);
-
- if (s->origPtr < 0)
- RETURN(BZ_DATA_ERROR);
- if (s->origPtr > 10 + 100000*s->blockSize100k)
- RETURN(BZ_DATA_ERROR);
-
- /*--- Receive the mapping table ---*/
- for (i = 0; i < 16; i++) {
- GET_BIT(BZ_X_MAPPING_1, uc);
- if (uc == 1)
- s->inUse16[i] = True; else
- s->inUse16[i] = False;
- }
-
- for (i = 0; i < 256; i++) s->inUse[i] = False;
-
- for (i = 0; i < 16; i++)
- if (s->inUse16[i])
- for (j = 0; j < 16; j++) {
- GET_BIT(BZ_X_MAPPING_2, uc);
- if (uc == 1) s->inUse[i * 16 + j] = True;
- }
- makeMaps_d ( s );
- if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
- alphaSize = s->nInUse+2;
-
- /*--- Now the selectors ---*/
- GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
- if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
- GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
- if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
- for (i = 0; i < nSelectors; i++) {
- j = 0;
- while (True) {
- GET_BIT(BZ_X_SELECTOR_3, uc);
- if (uc == 0) break;
- j++;
- if (j >= nGroups) RETURN(BZ_DATA_ERROR);
- }
- s->selectorMtf[i] = j;
- }
-
- /*--- Undo the MTF values for the selectors. ---*/
- {
- UChar pos[BZ_N_GROUPS], tmp, v;
- for (v = 0; v < nGroups; v++) pos[v] = v;
-
- for (i = 0; i < nSelectors; i++) {
- v = s->selectorMtf[i];
- tmp = pos[v];
- while (v > 0) { pos[v] = pos[v-1]; v--; }
- pos[0] = tmp;
- s->selector[i] = tmp;
- }
- }
-
- /*--- Now the coding tables ---*/
- for (t = 0; t < nGroups; t++) {
- GET_BITS(BZ_X_CODING_1, curr, 5);
- for (i = 0; i < alphaSize; i++) {
- while (True) {
- if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
- GET_BIT(BZ_X_CODING_2, uc);
- if (uc == 0) break;
- GET_BIT(BZ_X_CODING_3, uc);
- if (uc == 0) curr++; else curr--;
- }
- s->len[t][i] = curr;
- }
- }
-
- /*--- Create the Huffman decoding tables ---*/
- for (t = 0; t < nGroups; t++) {
- minLen = 32;
- maxLen = 0;
- for (i = 0; i < alphaSize; i++) {
- if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
- if (s->len[t][i] < minLen) minLen = s->len[t][i];
- }
- BZ2_hbCreateDecodeTables (
- &(s->limit[t][0]),
- &(s->base[t][0]),
- &(s->perm[t][0]),
- &(s->len[t][0]),
- minLen, maxLen, alphaSize
- );
- s->minLens[t] = minLen;
- }
-
- /*--- Now the MTF values ---*/
-
- EOB = s->nInUse+1;
- nblockMAX = 100000 * s->blockSize100k;
- groupNo = -1;
- groupPos = 0;
-
- for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
-
- /*-- MTF init --*/
- {
- Int32 ii, jj, kk;
- kk = MTFA_SIZE-1;
- for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
- for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
- s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
- kk--;
- }
- s->mtfbase[ii] = kk + 1;
- }
- }
- /*-- end MTF init --*/
-
- nblock = 0;
- GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
-
- while (True) {
-
- if (nextSym == EOB) break;
-
- if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
-
- es = -1;
- N = 1;
- do {
- if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
- if (nextSym == BZ_RUNB) es = es + (1+1) * N;
- N = N * 2;
- GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
- }
- while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
-
- es++;
- uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
- s->unzftab[uc] += es;
-
- if (0 && s->smallDecompress)
- while (es > 0) {
- if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
- s->ll16[nblock] = (UInt16)uc;
- nblock++;
- es--;
- }
- else
- while (es > 0) {
- if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
- s->tt[nblock] = (UInt32)uc;
- nblock++;
- es--;
- };
-
- continue;
-
- } else {
-
- if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
-
- /*-- uc = MTF ( nextSym-1 ) --*/
- {
- Int32 ii, jj, kk, pp, lno, off;
- UInt32 nn;
- nn = (UInt32)(nextSym - 1);
-
- if (nn < MTFL_SIZE) {
- /* avoid general-case expense */
- pp = s->mtfbase[0];
- uc = s->mtfa[pp+nn];
- while (nn > 3) {
- Int32 z = pp+nn;
- s->mtfa[(z) ] = s->mtfa[(z)-1];
- s->mtfa[(z)-1] = s->mtfa[(z)-2];
- s->mtfa[(z)-2] = s->mtfa[(z)-3];
- s->mtfa[(z)-3] = s->mtfa[(z)-4];
- nn -= 4;
- }
- while (nn > 0) {
- s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
- };
- s->mtfa[pp] = uc;
- } else {
- /* general case */
- lno = nn / MTFL_SIZE;
- off = nn % MTFL_SIZE;
- pp = s->mtfbase[lno] + off;
- uc = s->mtfa[pp];
- while (pp > s->mtfbase[lno]) {
- s->mtfa[pp] = s->mtfa[pp-1]; pp--;
- };
- s->mtfbase[lno]++;
- while (lno > 0) {
- s->mtfbase[lno]--;
- s->mtfa[s->mtfbase[lno]]
- = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
- lno--;
- }
- s->mtfbase[0]--;
- s->mtfa[s->mtfbase[0]] = uc;
- if (s->mtfbase[0] == 0) {
- kk = MTFA_SIZE-1;
- for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
- for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
- s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
- kk--;
- }
- s->mtfbase[ii] = kk + 1;
- }
- }
- }
- }
- /*-- end uc = MTF ( nextSym-1 ) --*/
-
- s->unzftab[s->seqToUnseq[uc]]++;
- if (0 && s->smallDecompress)
- s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
- s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
- nblock++;
-
- GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
- continue;
- }
- }
-
- /* Now we know what nblock is, we can do a better sanity
- check on s->origPtr.
- */
- if (s->origPtr < 0 || s->origPtr >= nblock)
- RETURN(BZ_DATA_ERROR);
-
- s->state_out_len = 0;
- s->state_out_ch = 0;
- BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
- s->state = BZ_X_OUTPUT;
- // if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
-
- /*-- Set up cftab to facilitate generation of T^(-1) --*/
- s->cftab[0] = 0;
- for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
- for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
-
- if (0 && s->smallDecompress) {
-
- /*-- Make a copy of cftab, used in generation of T --*/
- for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
-
- /*-- compute the T vector --*/
- for (i = 0; i < nblock; i++) {
- uc = (UChar)(s->ll16[i]);
- SET_LL(i, s->cftabCopy[uc]);
- s->cftabCopy[uc]++;
- }
-
- /*-- Compute T^(-1) by pointer reversal on T --*/
- i = s->origPtr;
- j = GET_LL(i);
- do {
- Int32 tmp = GET_LL(j);
- SET_LL(j, i);
- i = j;
- j = tmp;
- }
- while (i != s->origPtr);
-
- s->tPos = s->origPtr;
- s->nblock_used = 0;
- if (s->blockRandomised) {
- BZ_RAND_INIT_MASK;
- BZ_GET_SMALL(s->k0); s->nblock_used++;
- BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
- } else {
- BZ_GET_SMALL(s->k0); s->nblock_used++;
- }
-
- } else {
-
- /*-- compute the T^(-1) vector --*/
- for (i = 0; i < nblock; i++) {
- uc = (UChar)(s->tt[i] & 0xff);
- s->tt[s->cftab[uc]] |= (i << 8);
- s->cftab[uc]++;
- }
-
- s->tPos = s->tt[s->origPtr] >> 8;
- s->nblock_used = 0;
- if (s->blockRandomised) {
- BZ_RAND_INIT_MASK;
- BZ_GET_FAST(s->k0); s->nblock_used++;
- BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
- } else {
- BZ_GET_FAST(s->k0); s->nblock_used++;
- }
-
- }
-
- RETURN(BZ_OK);
-
-
-
- endhdr_2:
-
- GET_UCHAR(BZ_X_ENDHDR_2, uc);
- if (uc != 0x72) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_ENDHDR_3, uc);
- if (uc != 0x45) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_ENDHDR_4, uc);
- if (uc != 0x38) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_ENDHDR_5, uc);
- if (uc != 0x50) RETURN(BZ_DATA_ERROR);
- GET_UCHAR(BZ_X_ENDHDR_6, uc);
- if (uc != 0x90) RETURN(BZ_DATA_ERROR);
-
- s->storedCombinedCRC = 0;
- GET_UCHAR(BZ_X_CCRC_1, uc);
- s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_CCRC_2, uc);
- s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_CCRC_3, uc);
- s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
- GET_UCHAR(BZ_X_CCRC_4, uc);
- s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
-
- s->state = BZ_X_IDLE;
- RETURN(BZ_STREAM_END);
-
- default: AssertH ( False, 4001 );
- }
-
- AssertH ( False, 4002 );
-
- save_state_and_return:
-
- s->save_i = i;
- s->save_j = j;
- s->save_t = t;
- s->save_alphaSize = alphaSize;
- s->save_nGroups = nGroups;
- s->save_nSelectors = nSelectors;
- s->save_EOB = EOB;
- s->save_groupNo = groupNo;
- s->save_groupPos = groupPos;
- s->save_nextSym = nextSym;
- s->save_nblockMAX = nblockMAX;
- s->save_nblock = nblock;
- s->save_es = es;
- s->save_N = N;
- s->save_curr = curr;
- s->save_zt = zt;
- s->save_zn = zn;
- s->save_zvec = zvec;
- s->save_zj = zj;
- s->save_gSel = gSel;
- s->save_gMinlen = gMinlen;
- s->save_gLimit = gLimit;
- s->save_gBase = gBase;
- s->save_gPerm = gPerm;
-
- return retVal;
-}
-
-
-/*-------------------------------------------------------------*/
-/*--- end decompress.c ---*/
-/*-------------------------------------------------------------*/
--- a/sys/lib/dist.old/cmd/cdsh.c
+++ /dev/null
@@ -1,133 +1,0 @@
-/*
- * The `cd' shell.
- * Just has cd and lc.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-char *pwd;
-char *root = "/";
-
-void
-usage(void)
-{
- fprint(2, "usage: cdsh [-r root]\n");
- exits("usage");
-}
-
-int
-system(char *cmd)
-{
- int pid;
- if((pid = fork()) < 0)
- return -1;
-
- if(pid == 0) {
- dup(2, 1);
- execl("/bin/rc", "rc", "-c", cmd, nil);
- exits("exec");
- }
- waitpid();
- return 0;
-}
-
-int
-cd(char *s)
-{
- char *newpwd;
- int l;
-
- if(s[0] == '/') {
- cleanname(s);
- newpwd = strdup(s);
- } else {
- l = strlen(pwd)+1+strlen(s)+1+50; /* 50 = crud for unicode mistakes */
- newpwd = malloc(l);
- snprint(newpwd, l, "%s/%s", pwd, s);
- cleanname(newpwd);
- assert(newpwd[0] == '/');
- }
-
- if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
- chdir(root);
- chdir(pwd+1);
- free(newpwd);
- return -1;
- } else {
- free(pwd);
- pwd = newpwd;
- return 0;
- }
-}
-
-void
-main(int argc, char **argv)
-{
- char *p;
- Biobuf bin;
- char *f[2];
- int nf;
-
- ARGBEGIN{
- case 'r':
- root = ARGF();
- if(root == nil)
- usage();
- if(root[0] != '/') {
- fprint(2, "root must be rooted\n");
- exits("root");
- }
- break;
- default:
- usage();
- }ARGEND;
-
- if(argc != 0)
- usage();
-
- cleanname(root);
- if(cd("/") < 0) {
- fprint(2, "cannot cd %s: %r\n", root);
- exits("root");
- }
-
- Binit(&bin, 0, OREAD);
- while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
- p[Blinelen(&bin)-1] = '\0';
- nf = tokenize(p, f, nelem(f));
- if(nf < 1)
- continue;
- if(strcmp(f[0], "exit") == 0)
- break;
- if(strcmp(f[0], "lc") == 0) {
- if(nf == 1) {
- if(system("/bin/lc") < 0)
- fprint(2, "lc: %r\n");
- } else if(nf == 2) {
- if(strpbrk(p, "'`{}^@$#&()|\\;><"))
- fprint(2, "no shell characters allowed\n");
- else {
- p = f[1];
- *--p = ' ';
- *--p = 'c';
- *--p = 'l';
- if(system(p) < 0)
- fprint(2, "lc: %r\n");
- }
- }
- continue;
- }
- if(strcmp(f[0], "cd") == 0) {
- if(nf < 2)
- fprint(2, "usage: cd dir\n");
- else if(cd(f[1]) < 0)
- fprint(2, "cd: %r\n");
- continue;
- }
- fprint(2, "commands are cd, lc, and exit\n");
- }
-
- print("%s\n", pwd);
-}
--- a/sys/lib/dist.old/cmd/clog.c
+++ /dev/null
@@ -1,59 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-char *argv0;
-
-int
-openlog(char *name)
-{
- int fd;
-
- fd = open(name, OWRITE);
- if(fd < 0){
- fprint(2, "%s: can't open %s: %r\n", argv0, name);
- return -1;
- }
- seek(fd, 0, 2);
- return fd;
-}
-
-void
-main(int argc, char **argv)
-{
- Biobuf in;
- int fd;
- char *p, *t;
- char buf[8192];
-
- argv0 = argv[0];
- if(argc != 4){
- fprint(2, "usage: %s console logfile prefix\n", argv0);
- exits("usage");
- }
-
- fd = open(argv[1], OREAD);
- if(fd < 0){
- fprint(2, "%s: can't open %s: %r\n", argv0, argv[1]);
- exits("open");
- }
- Binit(&in, fd, OREAD);
-
- fd = openlog(argv[2]);
-
- for(;;){
- if(p = Brdline(&in, '\n')){
- p[Blinelen(&in)-1] = 0;
- if(fprint(fd, "%s: %s\n", argv[3], p) < 0){
- close(fd);
- fd = openlog(argv[2]);
- fprint(fd, "%s: %s\n", t, p);
- }
- } else if(Blinelen(&in) == 0) // true eof
- break;
- else {
- Bread(&in, buf, sizeof buf);
- }
- }
- exits(0);
-}
--- a/sys/lib/dist.old/cmd/multi/mkfile
+++ /dev/null
@@ -1,76 +1,0 @@
-objtype=386
-</$objtype/mkfile
-
-TARG=multi
-
-PIECES=\
- aux/mouse\
- aux/pcmcia\
- aux/vga\
- aux/zerotrunc\
- disk/fdisk\
- disk/format\
- disk/mbr\
- disk/prep\
-# fossil/fossil\
-# fossil/flfmt\
- ip/ipconfig\
- ip/ppp\
- ndb/cs\
- ndb/dns\
-# replica/applylog\
- 9660srv\
-# awk\
- basename\
- cat\
- chgrp\
- chmod\
- cleanname\
- cmp\
- cp\
- date\
- dd\
- dossrv\
- echo\
- ed\
- ext2srv\
-# fcp\
- grep\
- hget\
- hoc\
- ls\
- mc\
- mount\
- mv\
- ps\
- read\
-# rio\
- rm\
- sed\
- sort\
- srv\
-# stats\
- syscall\
- tail\
- tee\
- test\
- wc\
- xd\
-
-8.multi:V: mkmulti mkfile
- mkmulti $PIECES
- ls -l 8.multi
- ls -l /386/bin/$PIECES | awk '{s += $6} END{print s}'
-
-scripts:V:
- rm -rf ../../pc/multi
- mkdir ../../pc/multi
- for(i in $PIECES){
- b=`{basename $i}
- echo '#!/bin/multi' >>../../pc/multi/$b
- chmod +x ../../pc/multi/$b
- }
-
-BIN=/sys/lib/dist/bin/$objtype
-</sys/src/cmd/mkmany
-
--- a/sys/lib/dist.old/cmd/multi/mkmulti
+++ /dev/null
@@ -1,70 +1,0 @@
-#!/bin/rc
-
-targ=multi
-
-n=0
-dir=`{pwd}
-
-fn grab {
- echo using $*
- for(i){
- n=`{echo 1+$n|hoc}
- mv $i $dir/a.$n.8
- }
-}
-
-fn getfiles {
- sed -n 's/^(pcc|8\^l|8l) +(-o [^ ]* +)?([^\-].*)/ \3/p' | sed 's/ -[^ ]*//g' |
- sed 's/ [^ ]*\.a//g'
-}
-
-rm a.*.8
->multi.h
->multiproto.h
-
-for(i){
-echo $i...
- b=`{basename $i}
- p=$b
- if(~ $b [0-9]*)
- p=_$b
- echo void $p^_main'(int, char**);' >>$dir/multiproto.h
- echo "$b", $p^_main, >>$dir/multi.h
- d=`{basename -d $i}
- if(~ $i disk/prep disk/fdisk){
- cd /sys/src/cmd/disk/prep
- rm 8.$b
- files=`{mk 8.$b | getfiles}
- }
- if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.out}){
- cd /sys/src/cmd/$i
- rm 8.out
- files=`{mk 8.out | getfiles}
- }
- if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.$b}){
- cd /sys/src/cmd/$i
- rm 8.out
- files=`{mk 8.$b | getfiles}
- }
- if not if(test -d /sys/src/cmd/$d && @{cd /sys/src/cmd/$d && mk 8.$b}){
- cd /sys/src/cmd/$d
- rm 8.$b
- files=`{mk 8.$b | getfiles}
- }
- if not{
- echo do not know how to make $i
- exit oops
- }
- aux/8prefix $p^_ $files
- grab $files
- switch(`{pwd}){
- case /sys/src/cmd /sys/src/cmd/aux /sys/src/cmd/ip
- rm 8.$b
- case *
- mk clean
- }
-}
-cd $dir
-8c -FVw multi.c
-8l -o 8.$targ multi.8 a.*.8
-# rm a.*.8
--- a/sys/lib/dist.old/cmd/multi/multi.c
+++ /dev/null
@@ -1,38 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-#include "multiproto.h"
-struct {
- char *name;
- void (*fn)(int, char**);
-} mains[] =
-{
-#include "multi.h"
-};
-
-void
-main(int argc, char **argv)
-{
- int i;
- char *cmd, *p;
-
- if(argc == 1){
- fprint(2, "usage: multi cmd args...\n");
- exits("usage");
- }
-
- cmd = argv[1];
- if(p = strrchr(cmd, '/'))
- cmd = p+1;
- argv++;
- argc--;
-
- for(i=0; i<nelem(mains); i++){
- if(strcmp(cmd, mains[i].name) == 0){
- mains[i].fn(argc, argv);
- return;
- }
- }
- fprint(2, "multi: no such cmd %s\n", cmd);
- exits("no cmd");
-}
--- a/sys/lib/dist.old/cmd/tailfsrv.c
+++ /dev/null
@@ -1,17 +1,0 @@
-#include <u.h>
-#include <libc.h>
-
-void
-main(void)
-{
- int fd, p[2];
- char buf[8192], n;
-
- pipe(p);
- fd = create("/srv/log", OWRITE, 0666);
- fprint(fd, "%d", p[0]);
- close(fd);
- close(p[0]);
- while((n = read(p[1], buf, sizeof buf)) >= 0)
- write(1, buf, n);
-}
--- a/sys/lib/dist.old/cmd/touchfs.c
+++ /dev/null
@@ -1,66 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-void
-Bpass(Biobuf *bin, Biobuf *bout, int n)
-{
- char buf[8192];
- int m;
-
- while(n > 0) {
- m = sizeof buf;
- if(m > n)
- m = n;
- m = Bread(bin, buf, m);
- if(m <= 0) {
- fprint(2, "corrupt archive\n");
- exits("notdone");
- }
- Bwrite(bout, buf, m);
- n -= m;
- }
- assert(n == 0);
-}
-
-void
-main(int argc, char **argv)
-{
- char *p, *f[10];
- Biobuf bin, bout;
- int nf;
- ulong d, size;
-
- if(argc != 2) {
- fprint(2, "usage: cat mkfs-archive | touchfs date (in seconds)\n");
- exits("usage");
- }
-
- d = strtoul(argv[1], 0, 0);
-
- quotefmtinstall();
- Binit(&bin, 0, OREAD);
- Binit(&bout, 1, OWRITE);
-
- while(p = Brdline(&bin, '\n')) {
- p[Blinelen(&bin)-1] = '\0';
- if(strcmp(p, "end of archive") == 0) {
- Bprint(&bout, "end of archive\n");
- exits(0);
- }
-
- nf = tokenize(p, f, nelem(f));
- if(nf != 6) {
- fprint(2, "corrupt archive\n");
- exits("notdone");
- }
-
- Bprint(&bout, "%q %q %q %q %lud %q\n",
- f[0], f[1], f[2], f[3], d, f[5]);
-
- size = strtoul(f[5], 0, 0);
- Bpass(&bin, &bout, size);
- }
- fprint(2, "premature end of archive\n");
- exits("notdone");
-}
--- a/sys/lib/dist.old/cmd/unbflz.c
+++ /dev/null
@@ -1,109 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-
-void
-usage(void)
-{
- fprint(2, "usage: unbflz [file]\n");
- exits("usage");
-}
-
-int
-Bgetint(Biobuf *b)
-{
- uchar p[4];
-
- if(Bread(b, p, 4) != 4)
- sysfatal("short read");
- return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
-}
-
-/*
- * memmove but make sure overlap works properly.
- */
-void
-copy(uchar *dst, uchar *src, int n)
-{
- while(n-- > 0)
- *dst++ = *src++;
-}
-
-void
-main(int argc, char **argv)
-{
- Biobuf *b, bin;
- char buf[5];
- uchar *data;
- ulong *blk, l;
- int nblk, mblk;
- int sum;
- int i, j, length, m, n, o;
-
- ARGBEGIN{
- default:
- usage();
- }ARGEND
-
- switch(argc){
- default:
- usage();
- case 0:
- Binit(&bin, 0, OREAD);
- b = &bin;
- break;
- case 1:
- if((b = Bopen(argv[0], OREAD)) == nil)
- sysfatal("open %s: %r", argv[0]);
- break;
- }
-
- if(Bread(b, buf, 4) != 4)
- sysfatal("short read");
-
- if(memcmp(buf, "BLZ\n", 4) != 0)
- sysfatal("bad header");
-
- length = Bgetint(b);
- data = malloc(length);
- if(data == nil)
- sysfatal("out of memory");
- sum = 0;
- nblk = 0;
- mblk = 0;
- blk = nil;
- while(sum < length){
- if(nblk>=mblk){
- mblk += 16384;
- blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
- if(blk == nil)
- sysfatal("out of memory");
- }
- l = Bgetint(b);
- blk[nblk++] = l;
- if(l&(1<<31))
- l &= ~(1<<31);
- else
- blk[nblk++] = Bgetint(b);
- sum += l;
- }
- if(sum != length)
- sysfatal("bad compressed data %d %d", sum, length);
- i = 0;
- j = 0;
- while(i < length){
- assert(j < nblk);
- n = blk[j++];
- if(n&(1<<31)){
- n &= ~(1<<31);
- if((m=Bread(b, data+i, n)) != n)
- sysfatal("short read %d %d", n, m);
- }else{
- o = blk[j++];
- copy(data+i, data+o, n);
- }
- i += n;
- }
- write(1, data, length);
- exits(nil);
-}
--- /dev/null
+++ b/sys/src/cmd/aux/bflz.c
@@ -1,0 +1,374 @@
+/*
+ * Extraordinarily brute force Lempel & Ziv-like
+ * compressor. The input file must fit in memory
+ * during compression, and the output file will
+ * be reconstructed in memory during decompression.
+ * We search for large common sequences and use a
+ * greedy algorithm to choose which sequence gets
+ * compressed first.
+ *
+ * Files begin with "BLZ\n" and a 32-bit uncompressed file length.
+ *
+ * Output format is a series of blocks followed by
+ * a raw data section. Each block begins with a 32-bit big-endian
+ * number. The top bit is type and the next 31 bits
+ * are uncompressed size. Type is one of
+ * 0 - use raw data for this length
+ * 1 - a 32-bit offset follows
+ * After the blocks come the raw data. (The end of the blocks can be
+ * noted by summing block lengths until you reach the file length.)
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+#define malloc sbrk
+
+int minrun = 16;
+int win = 16;
+ulong outn;
+int verbose;
+int mindist;
+
+enum { Prime = 16777213 }; /* smallest prime < 2^24 (so p*256+256 < 2^32) */
+enum { NOFF = 3 };
+
+Biobuf bout;
+ulong length;
+uchar *data;
+ulong sum32(ulong, void*, long);
+uchar *odat;
+int nodat;
+int nraw;
+int rawstart;
+int acct;
+int zlength;
+int maxchain;
+int maxrle[256];
+int nnew;
+
+typedef struct Node Node;
+struct Node {
+ Node *link;
+ ulong key;
+ ulong offset[NOFF];
+};
+
+Node *nodepool;
+int nnodepool;
+
+Node **hash;
+uint nhash;
+
+uint maxlen;
+uint maxsame;
+uint replacesame = 8*1024*1024;
+
+Node *freelist, **freeend;
+uint nalloc;
+
+Node*
+allocnode(void)
+{
+ int i;
+ Node *n;
+
+ if(nnodepool == 0){
+ nnodepool = 256*1024;
+ nodepool = malloc(sizeof(Node)*nnodepool);
+ }
+ if(freelist){
+ n = freelist;
+ freelist = n->link;
+ return n;
+ }
+ assert(nnodepool > 0);
+ nalloc++;
+ n = &nodepool[--nnodepool];
+ for(i=0; i<NOFF; i++)
+ n->offset[i] = -1;
+
+ return n;
+}
+
+void
+freenode(Node *n)
+{
+ if(freelist == nil)
+ freelist = n;
+ else
+ *freeend = n;
+ freeend = &n->link;
+ n->link = nil;
+}
+
+Node**
+llookup(ulong key)
+{
+ uint c;
+ Node **l, **top, *n;
+
+ if(nhash == 0){
+ uint x;
+
+ x = length/8;
+ for(nhash=1; nhash<x; nhash<<=1)
+ ;
+ hash = sbrk(sizeof(Node*)*nhash);
+ }
+
+ top = &hash[key&(nhash-1)];
+ c = 0;
+ for(l=top; *l; l=&(*l)->link){
+ c++;
+ if((*l)->key == key){
+ /* move to front */
+ n = *l;
+ *l = n->link;
+ n->link = *top;
+ *top = n;
+ return top;
+ }
+ }
+ if(c > maxlen)
+ maxlen = c;
+ return l;
+}
+
+Node*
+lookup(ulong key)
+{
+ return *llookup(key);
+}
+
+void
+insertnode(ulong key, ulong offset)
+{
+ int i;
+ Node *n, **l;
+
+ l = llookup(key);
+ if(*l == nil){
+ if(l==&hash[key&(nhash-1)])
+ nnew++;
+ *l = allocnode();
+ (*l)->key = key;
+ }
+ n = *l;
+
+ /* add or replace last */
+ for(i=0; i<NOFF-1 && n->offset[i]!=-1; i++)
+ ;
+ n->offset[i] = offset;
+}
+
+void
+Bputint(Biobufhdr *b, int n)
+{
+ uchar p[4];
+
+ p[0] = n>>24;
+ p[1] = n>>16;
+ p[2] = n>>8;
+ p[3] = n;
+ Bwrite(b, p, 4);
+}
+
+void
+flushraw(void)
+{
+ if(nraw){
+ if(verbose)
+ fprint(2, "Raw %d+%d\n", rawstart, nraw);
+ zlength += 4+nraw;
+ Bputint(&bout, (1<<31)|nraw);
+ memmove(odat+nodat, data+rawstart, nraw);
+ nodat += nraw;
+ nraw = 0;
+ }
+}
+
+int
+rawbyte(int i)
+{
+ assert(acct == i);
+ if(nraw == 0)
+ rawstart = i;
+ acct++;
+ nraw++;
+ return 1;
+}
+
+int
+refblock(int i, int len, int off)
+{
+ assert(acct == i);
+ acct += len;
+ if(nraw)
+ flushraw();
+ if(verbose)
+ fprint(2, "Copy %d+%d from %d\n", i, len, off);
+ Bputint(&bout, len);
+ Bputint(&bout, off);
+ zlength += 4+4;
+ return len;
+}
+
+int
+cmprun(uchar *a, uchar *b, int len)
+{
+ int i;
+
+ if(a==b)
+ return 0;
+ for(i=0; i<len && a[i]==b[i]; i++)
+ ;
+ return i;
+}
+
+int
+countrle(uchar *a)
+{
+ int i;
+
+ for(i=0; a[i]==a[0]; i++)
+ ;
+ return i;
+}
+
+void
+compress(void)
+{
+ int best, i, j, o, rle, run, maxrun, maxoff;
+ ulong sum;
+ Node *n;
+
+ sum = 0;
+ for(i=0; i<win && i<length; i++)
+ sum = (sum*256+data[i])%Prime;
+ for(i=0; i<length-win; ){
+ maxrun = 0;
+ maxoff = 0;
+ if(verbose)
+ fprint(2, "look %.6lux\n", sum);
+ n = lookup(sum);
+ if(n){
+ best = -1;
+ for(o=0; o<NOFF; o++){
+ if(n->offset[o] == -1)
+ break;
+ run = cmprun(data+i, data+n->offset[o], length-i);
+ if(run > maxrun && n->offset[o]+mindist < i){
+ maxrun = run;
+ maxoff = n->offset[o];
+ best = o;
+ }
+ }
+ if(best > 0){
+ o = n->offset[best];
+ for(j=best; j>0; j--)
+ n->offset[j] = n->offset[j-1];
+ n->offset[0] = o;
+ }
+ }
+
+ if(maxrun >= minrun)
+ j = i+refblock(i, maxrun, maxoff);
+ else
+ j = i+rawbyte(i);
+ for(; i<j; i++){
+ /* avoid huge chains from large runs of same byte */
+ rle = countrle(data+i);
+ if(rle<4)
+ insertnode(sum, i);
+ else if(rle>maxrle[data[i]]){
+ maxrle[data[i]] = rle;
+ insertnode(sum, i);
+ }
+ sum = (sum*256+data[i+win]) % Prime;
+ sum = (sum + data[i]*outn) % Prime;
+ }
+ }
+ /* could do better here */
+ for(; i<length; i++)
+ rawbyte(i);
+ flushraw();
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: bflz [-n winsize] [file]\n");
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ int fd, i, n;
+ char buf[10485760];
+
+ ARGBEGIN{
+ case 'd':
+ verbose = 1;
+ break;
+ case 's':
+ replacesame = atoi(EARGF(usage()));
+ break;
+ case 'm':
+ mindist = atoi(EARGF(usage()));
+ break;
+ case 'n':
+ win = atoi(EARGF(usage()));
+ minrun = win;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ switch(argc){
+ default:
+ usage();
+ case 0:
+ fd = 0;
+ break;
+ case 1:
+ if((fd = open(argv[0], OREAD)) < 0)
+ sysfatal("open %s: %r", argv[0]);
+ break;
+ }
+
+ while((n = readn(fd, buf, sizeof buf)) > 0){
+ data = realloc(data, length+n);
+ if(data == nil)
+ sysfatal("realloc: %r");
+ memmove(data+length, buf, n);
+ length += n;
+ if(n < sizeof buf)
+ break;
+ }
+ odat = malloc(length);
+ if(odat == nil)
+ sysfatal("malloc: %r");
+
+ Binit(&bout, 1, OWRITE);
+ Bprint(&bout, "BLZ\n");
+ Bputint(&bout, length);
+ outn = 1;
+ for(i=0; i<win; i++)
+ outn = (outn * 256) % Prime;
+
+ if(verbose)
+ fprint(2, "256^%d = %.6lux\n", win, outn);
+ outn = Prime - outn;
+ if(verbose)
+ fprint(2, "outn = %.6lux\n", outn);
+
+ compress();
+ Bwrite(&bout, odat, nodat);
+ Bterm(&bout);
+ fprint(2, "brk %p\n", sbrk(1));
+ fprint(2, "%d nodes used; %d of %d hash slots used\n", nalloc, nnew, nhash);
+ exits(nil);
+}
--- /dev/null
+++ b/sys/src/cmd/aux/cdsh.c
@@ -1,0 +1,133 @@
+/*
+ * The `cd' shell.
+ * Just has cd and lc.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+char *pwd;
+char *root = "/";
+
+void
+usage(void)
+{
+ fprint(2, "usage: cdsh [-r root]\n");
+ exits("usage");
+}
+
+int
+system(char *cmd)
+{
+ int pid;
+ if((pid = fork()) < 0)
+ return -1;
+
+ if(pid == 0) {
+ dup(2, 1);
+ execl("/bin/rc", "rc", "-c", cmd, nil);
+ exits("exec");
+ }
+ waitpid();
+ return 0;
+}
+
+int
+cd(char *s)
+{
+ char *newpwd;
+ int l;
+
+ if(s[0] == '/') {
+ cleanname(s);
+ newpwd = strdup(s);
+ } else {
+ l = strlen(pwd)+1+strlen(s)+1+50; /* 50 = crud for unicode mistakes */
+ newpwd = malloc(l);
+ snprint(newpwd, l, "%s/%s", pwd, s);
+ cleanname(newpwd);
+ assert(newpwd[0] == '/');
+ }
+
+ if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
+ chdir(root);
+ chdir(pwd+1);
+ free(newpwd);
+ return -1;
+ } else {
+ free(pwd);
+ pwd = newpwd;
+ return 0;
+ }
+}
+
+void
+main(int argc, char **argv)
+{
+ char *p;
+ Biobuf bin;
+ char *f[2];
+ int nf;
+
+ ARGBEGIN{
+ case 'r':
+ root = ARGF();
+ if(root == nil)
+ usage();
+ if(root[0] != '/') {
+ fprint(2, "root must be rooted\n");
+ exits("root");
+ }
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ if(argc != 0)
+ usage();
+
+ cleanname(root);
+ if(cd("/") < 0) {
+ fprint(2, "cannot cd %s: %r\n", root);
+ exits("root");
+ }
+
+ Binit(&bin, 0, OREAD);
+ while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
+ p[Blinelen(&bin)-1] = '\0';
+ nf = tokenize(p, f, nelem(f));
+ if(nf < 1)
+ continue;
+ if(strcmp(f[0], "exit") == 0)
+ break;
+ if(strcmp(f[0], "lc") == 0) {
+ if(nf == 1) {
+ if(system("/bin/lc") < 0)
+ fprint(2, "lc: %r\n");
+ } else if(nf == 2) {
+ if(strpbrk(p, "'`{}^@$#&()|\\;><"))
+ fprint(2, "no shell characters allowed\n");
+ else {
+ p = f[1];
+ *--p = ' ';
+ *--p = 'c';
+ *--p = 'l';
+ if(system(p) < 0)
+ fprint(2, "lc: %r\n");
+ }
+ }
+ continue;
+ }
+ if(strcmp(f[0], "cd") == 0) {
+ if(nf < 2)
+ fprint(2, "usage: cd dir\n");
+ else if(cd(f[1]) < 0)
+ fprint(2, "cd: %r\n");
+ continue;
+ }
+ fprint(2, "commands are cd, lc, and exit\n");
+ }
+
+ print("%s\n", pwd);
+}
--- /dev/null
+++ b/sys/src/cmd/aux/multi/mkfile
@@ -1,0 +1,76 @@
+objtype=386
+</$objtype/mkfile
+
+TARG=multi
+
+PIECES=\
+ aux/mouse\
+ aux/pcmcia\
+ aux/vga\
+ aux/zerotrunc\
+ disk/fdisk\
+ disk/format\
+ disk/mbr\
+ disk/prep\
+# fossil/fossil\
+# fossil/flfmt\
+ ip/ipconfig\
+ ip/ppp\
+ ndb/cs\
+ ndb/dns\
+# replica/applylog\
+ 9660srv\
+# awk\
+ basename\
+ cat\
+ chgrp\
+ chmod\
+ cleanname\
+ cmp\
+ cp\
+ date\
+ dd\
+ dossrv\
+ echo\
+ ed\
+ ext2srv\
+# fcp\
+ grep\
+ hget\
+ hoc\
+ ls\
+ mc\
+ mount\
+ mv\
+ ps\
+ read\
+# rio\
+ rm\
+ sed\
+ sort\
+ srv\
+# stats\
+ syscall\
+ tail\
+ tee\
+ test\
+ wc\
+ xd\
+
+8.multi:V: mkmulti mkfile
+ mkmulti $PIECES
+ ls -l 8.multi
+ ls -l /386/bin/$PIECES | awk '{s += $6} END{print s}'
+
+scripts:V:
+ rm -rf ../../pc/multi
+ mkdir ../../pc/multi
+ for(i in $PIECES){
+ b=`{basename $i}
+ echo '#!/bin/multi' >>../../pc/multi/$b
+ chmod +x ../../pc/multi/$b
+ }
+
+BIN=/sys/lib/dist/bin/$objtype
+</sys/src/cmd/mkmany
+
--- /dev/null
+++ b/sys/src/cmd/aux/multi/mkmulti
@@ -1,0 +1,70 @@
+#!/bin/rc
+
+targ=multi
+
+n=0
+dir=`{pwd}
+
+fn grab {
+ echo using $*
+ for(i){
+ n=`{echo 1+$n|hoc}
+ mv $i $dir/a.$n.8
+ }
+}
+
+fn getfiles {
+ sed -n 's/^(pcc|8\^l|8l) +(-o [^ ]* +)?([^\-].*)/ \3/p' | sed 's/ -[^ ]*//g' |
+ sed 's/ [^ ]*\.a//g'
+}
+
+rm a.*.8
+>multi.h
+>multiproto.h
+
+for(i){
+echo $i...
+ b=`{basename $i}
+ p=$b
+ if(~ $b [0-9]*)
+ p=_$b
+ echo void $p^_main'(int, char**);' >>$dir/multiproto.h
+ echo "$b", $p^_main, >>$dir/multi.h
+ d=`{basename -d $i}
+ if(~ $i disk/prep disk/fdisk){
+ cd /sys/src/cmd/disk/prep
+ rm 8.$b
+ files=`{mk 8.$b | getfiles}
+ }
+ if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.out}){
+ cd /sys/src/cmd/$i
+ rm 8.out
+ files=`{mk 8.out | getfiles}
+ }
+ if not if(test -d /sys/src/cmd/$i && @{cd /sys/src/cmd/$i && mk 8.$b}){
+ cd /sys/src/cmd/$i
+ rm 8.out
+ files=`{mk 8.$b | getfiles}
+ }
+ if not if(test -d /sys/src/cmd/$d && @{cd /sys/src/cmd/$d && mk 8.$b}){
+ cd /sys/src/cmd/$d
+ rm 8.$b
+ files=`{mk 8.$b | getfiles}
+ }
+ if not{
+ echo do not know how to make $i
+ exit oops
+ }
+ aux/8prefix $p^_ $files
+ grab $files
+ switch(`{pwd}){
+ case /sys/src/cmd /sys/src/cmd/aux /sys/src/cmd/ip
+ rm 8.$b
+ case *
+ mk clean
+ }
+}
+cd $dir
+8c -FVw multi.c
+8l -o 8.$targ multi.8 a.*.8
+# rm a.*.8
--- /dev/null
+++ b/sys/src/cmd/aux/multi/multi.c
@@ -1,0 +1,38 @@
+#include <u.h>
+#include <libc.h>
+
+#include "multiproto.h"
+struct {
+ char *name;
+ void (*fn)(int, char**);
+} mains[] =
+{
+#include "multi.h"
+};
+
+void
+main(int argc, char **argv)
+{
+ int i;
+ char *cmd, *p;
+
+ if(argc == 1){
+ fprint(2, "usage: multi cmd args...\n");
+ exits("usage");
+ }
+
+ cmd = argv[1];
+ if(p = strrchr(cmd, '/'))
+ cmd = p+1;
+ argv++;
+ argc--;
+
+ for(i=0; i<nelem(mains); i++){
+ if(strcmp(cmd, mains[i].name) == 0){
+ mains[i].fn(argc, argv);
+ return;
+ }
+ }
+ fprint(2, "multi: no such cmd %s\n", cmd);
+ exits("no cmd");
+}
--- /dev/null
+++ b/sys/src/cmd/aux/tailfsrv.c
@@ -1,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+
+void
+main(void)
+{
+ int fd, p[2];
+ char buf[8192], n;
+
+ pipe(p);
+ fd = create("/srv/log", OWRITE, 0666);
+ fprint(fd, "%d", p[0]);
+ close(fd);
+ close(p[0]);
+ while((n = read(p[1], buf, sizeof buf)) >= 0)
+ write(1, buf, n);
+}
--- /dev/null
+++ b/sys/src/cmd/aux/unbflz.c
@@ -1,0 +1,109 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void
+usage(void)
+{
+ fprint(2, "usage: unbflz [file]\n");
+ exits("usage");
+}
+
+int
+Bgetint(Biobuf *b)
+{
+ uchar p[4];
+
+ if(Bread(b, p, 4) != 4)
+ sysfatal("short read");
+ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+/*
+ * memmove but make sure overlap works properly.
+ */
+void
+copy(uchar *dst, uchar *src, int n)
+{
+ while(n-- > 0)
+ *dst++ = *src++;
+}
+
+void
+main(int argc, char **argv)
+{
+ Biobuf *b, bin;
+ char buf[5];
+ uchar *data;
+ ulong *blk, l;
+ int nblk, mblk;
+ int sum;
+ int i, j, length, m, n, o;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND
+
+ switch(argc){
+ default:
+ usage();
+ case 0:
+ Binit(&bin, 0, OREAD);
+ b = &bin;
+ break;
+ case 1:
+ if((b = Bopen(argv[0], OREAD)) == nil)
+ sysfatal("open %s: %r", argv[0]);
+ break;
+ }
+
+ if(Bread(b, buf, 4) != 4)
+ sysfatal("short read");
+
+ if(memcmp(buf, "BLZ\n", 4) != 0)
+ sysfatal("bad header");
+
+ length = Bgetint(b);
+ data = malloc(length);
+ if(data == nil)
+ sysfatal("out of memory");
+ sum = 0;
+ nblk = 0;
+ mblk = 0;
+ blk = nil;
+ while(sum < length){
+ if(nblk>=mblk){
+ mblk += 16384;
+ blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
+ if(blk == nil)
+ sysfatal("out of memory");
+ }
+ l = Bgetint(b);
+ blk[nblk++] = l;
+ if(l&(1<<31))
+ l &= ~(1<<31);
+ else
+ blk[nblk++] = Bgetint(b);
+ sum += l;
+ }
+ if(sum != length)
+ sysfatal("bad compressed data %d %d", sum, length);
+ i = 0;
+ j = 0;
+ while(i < length){
+ assert(j < nblk);
+ n = blk[j++];
+ if(n&(1<<31)){
+ n &= ~(1<<31);
+ if((m=Bread(b, data+i, n)) != n)
+ sysfatal("short read %d %d", n, m);
+ }else{
+ o = blk[j++];
+ copy(data+i, data+o, n);
+ }
+ i += n;
+ }
+ write(1, data, length);
+ exits(nil);
+}
--- /dev/null
+++ b/sys/src/cmd/bzfs/bzfs.h
@@ -1,0 +1,11 @@
+int unbzip(int);
+void _unbzip(int, int);
+int unbflz(int);
+int xexpand(int);
+void *emalloc(ulong);
+void *erealloc(void*, ulong);
+char *estrdup(char*);
+
+void ramfsmain(int, char**);
+extern int chatty;
+void error(char*, ...);
--- /dev/null
+++ b/sys/src/cmd/bzfs/mkext.c
@@ -1,0 +1,288 @@
+/*
+ * bzip2-based file system.
+ * the file system itself is just a bzipped2 xzipped mkfs archive
+ * prefixed with "bzfilesystem\n" and suffixed with
+ * a kilobyte of zeros.
+ *
+ * changes to the file system are only kept in
+ * memory, not written back to the disk.
+ *
+ * this is intended for use on a floppy boot disk.
+ * we assume the file is in the dos file system and
+ * contiguous on the disk: finding it amounts to
+ * looking at the beginning of each sector for
+ * "bzfilesystem\n". then we pipe it through
+ * bunzip2 and store the files in a file tree in memory.
+ * things are slightly complicated by the fact that
+ * devfloppy requires reads to be on a 512-byte
+ * boundary and be a multiple of 512 bytes; we
+ * fork a process to relieve bunzip2 of this restriction.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <auth.h>
+#include <fcall.h>
+#include "bzfs.h"
+
+enum{
+ LEN = 8*1024,
+ NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
+};
+
+void mkdirs(char*, char*);
+void mkdir(char*, ulong, ulong, char*, char*);
+void extract(char*, ulong, ulong, char*, char*, ulong);
+void seekpast(ulong);
+void error(char*, ...);
+void warn(char*, ...);
+void usage(void);
+char *mtpt;
+Biobufhdr bin;
+uchar binbuf[2*LEN];
+
+void
+usage(void)
+{
+ fprint(2, "usage: bzfs [-m mtpt] [-s] [-f file] [-h]\n");
+ exits("usage");
+}
+
+/*
+ * floppy disks can only be read on 512-byte
+ * boundaries and in 512 byte multiples.
+ * feed one over a pipe to allow arbitrary reading.
+ */
+char zero[512];
+int
+blockread(int in, char *first, int nfirst)
+{
+ int p[2], out, n, rv;
+ char blk[512];
+
+ if(pipe(p) < 0)
+ sysfatal("pipe: %r");
+ rv = p[0];
+ out = p[1];
+ switch(rfork(RFPROC|RFNOTEG|RFFDG)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ close(rv);
+ break;
+ default:
+ close(in);
+ close(out);
+ return rv;
+ }
+
+ write(out, first, nfirst);
+
+ while((n=read(in, blk, sizeof blk)) > 0){
+ if(write(out, blk, n) != n)
+ break;
+ if(n == sizeof(blk) && memcmp(zero, blk, n) == n)
+ break;
+ }
+ _exits(0);
+ return -1;
+}
+
+enum { NAMELEN = 28 };
+
+void
+main(int argc, char **argv)
+{
+ char *rargv[10];
+ int rargc;
+ char *fields[NFLDS], name[2*LEN], *p, *namep;
+ char uid[NAMELEN], gid[NAMELEN];
+ ulong mode, bytes, mtime;
+ char *file;
+ int i, n, stdin, fd, chatty;
+ char blk[512];
+
+ if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
+ argv[1] = argv[0];
+ ramfsmain(argc-1, argv+1);
+ exits(nil);
+ }
+ if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
+ _unbzip(0, 1);
+ exits(nil);
+ }
+
+ rfork(RFNOTEG);
+ stdin = 0;
+ file = nil;
+ namep = name;
+ mtpt = "/root";
+ chatty = 0;
+ ARGBEGIN{
+ case 'd':
+ chatty = !chatty;
+ break;
+ case 'f':
+ file = ARGF();
+ break;
+ case 's':
+ stdin++;
+ break;
+ case 'm':
+ mtpt = ARGF();
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 0)
+ usage();
+
+ if(file == nil) {
+ fprint(2, "must specify -f file\n");
+ usage();
+ }
+
+ if((fd = open(file, OREAD)) < 0) {
+ fprint(2, "cannot open \"%s\": %r\n", file);
+ exits("open");
+ }
+
+ rargv[0] = "ramfs";
+ rargc = 1;
+ if(stdin)
+ rargv[rargc++] = "-i";
+ rargv[rargc++] = "-m";
+ rargv[rargc++] = mtpt;
+ rargv[rargc] = nil;
+ ramfsmain(rargc, rargv);
+
+ if(1 || strstr(file, "disk")) { /* search for archive on block boundary */
+if(chatty) fprint(2, "searching for bz\n");
+ for(i=0;; i++){
+ if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
+ sysfatal("read %d gets %d: %r\n", i, n);
+ if(strncmp(blk, "bzfilesystem\n", 13) == 0)
+ break;
+ }
+if(chatty) fprint(2, "found at %d\n", i);
+ }
+
+ if(chdir(mtpt) < 0)
+ error("chdir %s: %r", mtpt);
+
+ fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));
+
+ Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
+ while(p = Brdline(&bin, '\n')){
+ p[Blinelen(&bin)-1] = '\0';
+if(chatty) fprint(2, "%s\n", p);
+ if(strcmp(p, "end of archive") == 0){
+ _exits(0);
+ }
+ if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
+ warn("too few fields in file header");
+ continue;
+ }
+ strcpy(namep, fields[0]);
+ mode = strtoul(fields[1], 0, 8);
+ mtime = strtoul(fields[4], 0, 10);
+ bytes = strtoul(fields[5], 0, 10);
+ strncpy(uid, fields[2], NAMELEN);
+ strncpy(gid, fields[3], NAMELEN);
+ if(mode & DMDIR)
+ mkdir(name, mode, mtime, uid, gid);
+ else
+ extract(name, mode, mtime, uid, gid, bytes);
+ }
+ fprint(2, "premature end of archive\n");
+ exits("premature end of archive");
+}
+
+char buf[8192];
+
+int
+ffcreate(char *name, ulong mode, char *uid, char *gid, ulong mtime, int length)
+{
+ int fd, om;
+ Dir nd;
+
+ sprint(buf, "%s/%s", mtpt, name);
+ om = ORDWR;
+ if(mode&DMDIR)
+ om = OREAD;
+ if((fd = create(buf, om, (mode&DMDIR)|0666)) < 0)
+ error("create %s: %r", buf);
+
+ nulldir(&nd);
+ nd.mode = mode;
+ nd.uid = uid;
+ nd.gid = gid;
+ nd.mtime = mtime;
+ if(length)
+ nd.length = length;
+ if(dirfwstat(fd, &nd) < 0)
+ error("fwstat %s: %r", buf);
+
+ return fd;
+}
+
+void
+mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
+{
+ close(ffcreate(name, mode, uid, gid, mtime, 0));
+}
+
+void
+extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, ulong bytes)
+{
+ int fd, tot, n;
+
+ fd = ffcreate(name, mode, uid, gid, mtime, bytes);
+
+ for(tot = 0; tot < bytes; tot += n){
+ n = sizeof buf;
+ if(tot + n > bytes)
+ n = bytes - tot;
+ n = Bread(&bin, buf, n);
+ if(n <= 0)
+ error("premature eof reading %s", name);
+ if(write(fd, buf, n) != n)
+ error("short write writing %s", name);
+ }
+ close(fd);
+}
+
+void
+error(char *fmt, ...)
+{
+ char buf[1024];
+ va_list arg;
+
+ sprint(buf, "%s: ", argv0);
+ va_start(arg, fmt);
+ vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
+ va_end(arg);
+ fprint(2, "%s\n", buf);
+ exits(0);
+}
+
+void
+warn(char *fmt, ...)
+{
+ char buf[1024];
+ va_list arg;
+
+ sprint(buf, "%s: ", argv0);
+ va_start(arg, fmt);
+ vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
+ va_end(arg);
+ fprint(2, "%s\n", buf);
+}
+
+int
+_efgfmt(Fmt*)
+{
+ return -1;
+}
--- /dev/null
+++ b/sys/src/cmd/bzfs/mkfile
@@ -1,0 +1,20 @@
+</$objtype/mkfile
+
+TARG=bzfs
+
+OFILES=\
+ mkext.$O\
+ oramfs.$O\
+ unbflz.$O\
+ unbzip.$O\
+
+HFILES=bzfs.h
+
+BIN=/sys/lib/dist/bin/$objtype
+LIB=/sys/src/cmd/bzip2/lib/libbzip2.a$O
+</sys/src/cmd/mkone
+
+CFLAGS=$CFLAGS -p -I/sys/src/cmd/bzip2/lib
+
+/sys/src/cmd/bzip2/lib/libbzip2.a$O:
+ @{cd /sys/src/cmd/bzip2/lib && mk}
--- /dev/null
+++ b/sys/src/cmd/bzfs/oramfs.c
@@ -1,0 +1,927 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include "bzfs.h"
+
+/*
+ * Rather than reading /adm/users, which is a lot of work for
+ * a toy program, we assume all groups have the form
+ * NNN:user:user:
+ * meaning that each user is the leader of his own group.
+ */
+
+enum
+{
+ OPERM = 0x3, /* mask of all permission types in open mode */
+ Nram = 512,
+ Maxsize = 512*1024*1024,
+ Maxfdata = 8192,
+};
+
+typedef struct Fid Fid;
+typedef struct Ram Ram;
+
+struct Fid
+{
+ short busy;
+ short open;
+ short rclose;
+ int fid;
+ Fid *next;
+ char *user;
+ Ram *ram;
+};
+
+struct Ram
+{
+ short busy;
+ short open;
+ long parent; /* index in Ram array */
+ Qid qid;
+ long perm;
+ char *name;
+ ulong atime;
+ ulong mtime;
+ char *user;
+ char *group;
+ char *muid;
+ char *data;
+ long ndata;
+};
+
+enum
+{
+ Pexec = 1,
+ Pwrite = 2,
+ Pread = 4,
+ Pother = 1,
+ Pgroup = 8,
+ Powner = 64,
+};
+
+ulong path; /* incremented for each new file */
+Fid *fids;
+Ram ram[Nram];
+int nram;
+int mfd[2];
+char *user;
+uchar mdata[IOHDRSZ+Maxfdata];
+uchar rdata[Maxfdata]; /* buffer for data in reply */
+uchar statbuf[STATMAX];
+Fcall thdr;
+Fcall rhdr;
+int messagesize = sizeof mdata;
+
+Fid * newfid(int);
+uint ramstat(Ram*, uchar*, uint);
+void io(void);
+void *erealloc(void*, ulong);
+void *emalloc(ulong);
+char *estrdup(char*);
+void ramfsusage(void);
+int perm(Fid*, Ram*, int);
+char *atom(char*);
+
+char *rflush(Fid*), *rversion(Fid*), *rauth(Fid*),
+ *rattach(Fid*), *rwalk(Fid*),
+ *ropen(Fid*), *rcreate(Fid*),
+ *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
+ *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
+
+char *(*fcalls[])(Fid*) = {
+ [Tversion] rversion,
+ [Tflush] rflush,
+ [Tauth] rauth,
+ [Tattach] rattach,
+ [Twalk] rwalk,
+ [Topen] ropen,
+ [Tcreate] rcreate,
+ [Tread] rread,
+ [Twrite] rwrite,
+ [Tclunk] rclunk,
+ [Tremove] rremove,
+ [Tstat] rstat,
+ [Twstat] rwstat,
+};
+
+char Eperm[] = "permission denied";
+char Enotdir[] = "not a directory";
+char Enoauth[] = "no authentication in ramfs";
+char Enotexist[] = "file does not exist";
+char Einuse[] = "file in use";
+char Eexist[] = "file exists";
+char Eisdir[] = "file is a directory";
+char Enotowner[] = "not owner";
+char Eisopen[] = "file already open for I/O";
+char Excl[] = "exclusive use file already open";
+char Ename[] = "illegal name";
+char Eversion[] = "unknown 9P version";
+
+int debug;
+
+void
+notifyf(void *a, char *s)
+{
+ USED(a);
+ if(strncmp(s, "interrupt", 9) == 0)
+ noted(NCONT);
+ noted(NDFLT);
+}
+
+void
+ramfsmain(int argc, char *argv[])
+{
+ Ram *r;
+ char *defmnt;
+ int p[2];
+ char buf[32];
+ int fd, srvfd;
+ int stdio = 0;
+
+ srvfd = -1;
+ defmnt = "/tmp";
+ ARGBEGIN{
+ case 'D':
+ debug = 1;
+ break;
+ case 'i': /* this is DIFFERENT from normal ramfs; use 1 for both for kernel */
+ defmnt = 0;
+ stdio = 1;
+ srvfd = 0;
+ mfd[0] = 1;
+ mfd[1] = 1;
+ break;
+ case 's':
+ defmnt = 0;
+ break;
+ case 'm':
+ defmnt = ARGF();
+ break;
+ default:
+ ramfsusage();
+ }ARGEND
+
+ if(!stdio){
+ if(pipe(p) < 0)
+ error("pipe failed");
+ srvfd = p[1];
+ mfd[0] = p[0];
+ mfd[1] = p[0];
+ if(defmnt == 0){
+ fd = create("#s/ramfs", OWRITE, 0666);
+ if(fd < 0)
+ error("create of /srv/ramfs failed");
+ sprint(buf, "%d", p[1]);
+ if(write(fd, buf, strlen(buf)) < 0)
+ error("writing /srv/ramfs");
+ }
+ }
+
+ user = atom(getuser());
+ notify(notifyf);
+ nram = 1;
+ r = &ram[0];
+ r->busy = 1;
+ r->data = 0;
+ r->ndata = 0;
+ r->perm = DMDIR | 0775;
+ r->qid.type = QTDIR;
+ r->qid.path = 0LL;
+ r->qid.vers = 0;
+ r->parent = 0;
+ r->user = user;
+ r->group = user;
+ r->muid = user;
+ r->atime = time(0);
+ r->mtime = r->atime;
+ r->name = estrdup(".");
+
+ if(debug)
+ fmtinstall('F', fcallfmt);
+ switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
+ case -1:
+ error("fork");
+ case 0:
+ close(srvfd);
+ io();
+ break;
+ default:
+ close(mfd[0]); /* don't deadlock if child fails */
+ if(defmnt && mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0)
+ error("mount failed: %r");
+ }
+}
+
+char*
+rversion(Fid*)
+{
+ Fid *f;
+
+ for(f = fids; f; f = f->next)
+ if(f->busy)
+ rclunk(f);
+ if(thdr.msize > sizeof mdata)
+ rhdr.msize = sizeof mdata;
+ else
+ rhdr.msize = thdr.msize;
+ messagesize = rhdr.msize;
+ if(strncmp(thdr.version, "9P2000", 6) != 0)
+ return Eversion;
+ rhdr.version = "9P2000";
+ return 0;
+}
+
+char*
+rauth(Fid*)
+{
+ return "ramfs: no authentication required";
+}
+
+char*
+rflush(Fid *f)
+{
+ USED(f);
+ return 0;
+}
+
+char*
+rattach(Fid *f)
+{
+ /* no authentication! */
+ f->busy = 1;
+ f->rclose = 0;
+ f->ram = &ram[0];
+ rhdr.qid = f->ram->qid;
+ if(thdr.uname[0])
+ f->user = atom(thdr.uname);
+ else
+ f->user = atom("none");
+ if(strcmp(user, "none") == 0)
+ user = f->user;
+ return 0;
+}
+
+char*
+clone(Fid *f, Fid **nf)
+{
+ if(f->open)
+ return Eisopen;
+ if(f->ram->busy == 0)
+ return Enotexist;
+ *nf = newfid(thdr.newfid);
+ (*nf)->busy = 1;
+ (*nf)->open = 0;
+ (*nf)->rclose = 0;
+ (*nf)->ram = f->ram;
+ (*nf)->user = f->user; /* no ref count; the leakage is minor */
+ return 0;
+}
+
+char*
+rwalk(Fid *f)
+{
+ Ram *r, *fram;
+ char *name;
+ Ram *parent;
+ Fid *nf;
+ char *err;
+ ulong t;
+ int i;
+
+ err = nil;
+ nf = nil;
+ rhdr.nwqid = 0;
+ if(rhdr.newfid != rhdr.fid){
+ err = clone(f, &nf);
+ if(err)
+ return err;
+ f = nf; /* walk the new fid */
+ }
+ fram = f->ram;
+ if(thdr.nwname > 0){
+ t = time(0);
+ for(i=0; i<thdr.nwname && i<MAXWELEM; i++){
+ if((fram->qid.type & QTDIR) == 0){
+ err = Enotdir;
+ break;
+ }
+ if(fram->busy == 0){
+ err = Enotexist;
+ break;
+ }
+ fram->atime = t;
+ name = thdr.wname[i];
+ if(strcmp(name, ".") == 0){
+ Found:
+ rhdr.nwqid++;
+ rhdr.wqid[i] = fram->qid;
+ continue;
+ }
+ parent = &ram[fram->parent];
+#ifdef CHECKS
+ if(!perm(f, parent, Pexec)){
+ err = Eperm;
+ break;
+ }
+#endif
+ if(strcmp(name, "..") == 0){
+ fram = parent;
+ goto Found;
+ }
+ for(r=ram; r < &ram[nram]; r++)
+ if(r->busy && r->parent==fram-ram && strcmp(name, r->name)==0){
+ fram = r;
+ goto Found;
+ }
+ break;
+ }
+ if(i==0 && err == nil)
+ err = Enotexist;
+ }
+ if(nf != nil && (err!=nil || rhdr.nwqid<thdr.nwname)){
+ /* clunk the new fid, which is the one we walked */
+ f->busy = 0;
+ f->ram = nil;
+ }
+ if(rhdr.nwqid == thdr.nwname) /* update the fid after a successful walk */
+ f->ram = fram;
+ return err;
+}
+
+char *
+ropen(Fid *f)
+{
+ Ram *r;
+ int mode, trunc;
+
+ if(f->open)
+ return Eisopen;
+ r = f->ram;
+ if(r->busy == 0)
+ return Enotexist;
+ if(r->perm & DMEXCL)
+ if(r->open)
+ return Excl;
+ mode = thdr.mode;
+ if(r->qid.type & QTDIR){
+ if(mode != OREAD)
+ return Eperm;
+ rhdr.qid = r->qid;
+ return 0;
+ }
+ if(mode & ORCLOSE){
+ /* can't remove root; must be able to write parent */
+ if(r->qid.path==0 || !perm(f, &ram[r->parent], Pwrite))
+ return Eperm;
+ f->rclose = 1;
+ }
+ trunc = mode & OTRUNC;
+ mode &= OPERM;
+ if(mode==OWRITE || mode==ORDWR || trunc)
+ if(!perm(f, r, Pwrite))
+ return Eperm;
+ if(mode==OREAD || mode==ORDWR)
+ if(!perm(f, r, Pread))
+ return Eperm;
+ if(mode==OEXEC)
+ if(!perm(f, r, Pexec))
+ return Eperm;
+ if(trunc && (r->perm&DMAPPEND)==0){
+ r->ndata = 0;
+ if(r->data)
+ free(r->data);
+ r->data = 0;
+ r->qid.vers++;
+ }
+ rhdr.qid = r->qid;
+ rhdr.iounit = messagesize-IOHDRSZ;
+ f->open = 1;
+ r->open++;
+ return 0;
+}
+
+char *
+rcreate(Fid *f)
+{
+ Ram *r;
+ char *name;
+ long parent, prm;
+
+ if(f->open)
+ return Eisopen;
+ if(f->ram->busy == 0)
+ return Enotexist;
+ parent = f->ram - ram;
+ if((f->ram->qid.type&QTDIR) == 0)
+ return Enotdir;
+ /* must be able to write parent */
+#ifdef CHECKS
+ if(!perm(f, f->ram, Pwrite))
+ return Eperm;
+#endif
+ prm = thdr.perm;
+ name = thdr.name;
+ if(strcmp(name, ".")==0 || strcmp(name, "..")==0)
+ return Ename;
+ for(r=ram; r<&ram[nram]; r++)
+ if(r->busy && parent==r->parent)
+ if(strcmp((char*)name, r->name)==0)
+ return Einuse;
+ for(r=ram; r->busy; r++)
+ if(r == &ram[Nram-1])
+ return "no free ram resources";
+ r->busy = 1;
+ r->qid.path = ++path;
+ r->qid.vers = 0;
+ if(prm & DMDIR)
+ r->qid.type |= QTDIR;
+ r->parent = parent;
+ free(r->name);
+ r->name = estrdup(name);
+ r->user = f->user;
+ r->group = f->ram->group;
+ r->muid = f->ram->muid;
+ if(prm & DMDIR)
+ prm = (prm&~0777) | (f->ram->perm&prm&0777);
+ else
+ prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);
+ r->perm = prm;
+ r->ndata = 0;
+ if(r-ram >= nram)
+ nram = r - ram + 1;
+ r->atime = time(0);
+ r->mtime = r->atime;
+ f->ram->mtime = r->atime;
+ f->ram = r;
+ rhdr.qid = r->qid;
+ rhdr.iounit = messagesize-IOHDRSZ;
+ f->open = 1;
+ if(thdr.mode & ORCLOSE)
+ f->rclose = 1;
+ r->open++;
+ return 0;
+}
+
+char*
+rread(Fid *f)
+{
+ Ram *r;
+ uchar *buf;
+ long off;
+ int n, m, cnt;
+
+ if(f->ram->busy == 0)
+ return Enotexist;
+ n = 0;
+ rhdr.count = 0;
+ off = thdr.offset;
+ buf = rdata;
+ cnt = thdr.count;
+ if(cnt > messagesize) /* shouldn't happen, anyway */
+ cnt = messagesize;
+ if(f->ram->qid.type & QTDIR){
+ for(r=ram+1; off > 0; r++){
+ if(r->busy && r->parent==f->ram-ram)
+ off -= ramstat(r, statbuf, sizeof statbuf);
+ if(r == &ram[nram-1])
+ return 0;
+ }
+ for(; r<&ram[nram] && n < cnt; r++){
+ if(!r->busy || r->parent!=f->ram-ram)
+ continue;
+ m = ramstat(r, buf+n, cnt-n);
+ if(m == 0)
+ break;
+ n += m;
+ }
+ rhdr.data = (char*)rdata;
+ rhdr.count = n;
+ return 0;
+ }
+ r = f->ram;
+ if(off >= r->ndata)
+ return 0;
+ r->atime = time(0);
+ n = cnt;
+ if(off+n > r->ndata)
+ n = r->ndata - off;
+ rhdr.data = r->data+off;
+ rhdr.count = n;
+ return 0;
+}
+
+char*
+rwrite(Fid *f)
+{
+ Ram *r;
+ ulong off;
+ int cnt;
+
+ r = f->ram;
+ if(r->busy == 0)
+ return Enotexist;
+ off = thdr.offset;
+ if(r->perm & DMAPPEND)
+ off = r->ndata;
+ cnt = thdr.count;
+ if(r->qid.type & QTDIR)
+ return Eisdir;
+ if(off+cnt >= Maxsize) /* sanity check */
+ return "write too big";
+ if(off+cnt > r->ndata)
+ r->data = erealloc(r->data, off+cnt);
+ if(off > r->ndata)
+ memset(r->data+r->ndata, 0, off-r->ndata);
+ if(off+cnt > r->ndata)
+ r->ndata = off+cnt;
+ memmove(r->data+off, thdr.data, cnt);
+ r->qid.vers++;
+ r->mtime = time(0);
+ rhdr.count = cnt;
+ return 0;
+}
+
+void
+realremove(Ram *r)
+{
+ r->ndata = 0;
+ if(r->data)
+ free(r->data);
+ r->data = 0;
+ r->parent = 0;
+ memset(&r->qid, 0, sizeof r->qid);
+ free(r->name);
+ r->name = nil;
+ r->busy = 0;
+}
+
+char *
+rclunk(Fid *f)
+{
+ if(f->open)
+ f->ram->open--;
+ if(f->rclose)
+ realremove(f->ram);
+ f->busy = 0;
+ f->open = 0;
+ f->ram = 0;
+ return 0;
+}
+
+char *
+rremove(Fid *f)
+{
+ Ram *r;
+
+ if(f->open)
+ f->ram->open--;
+ f->busy = 0;
+ f->open = 0;
+ r = f->ram;
+ f->ram = 0;
+#ifdef CHECKS
+ if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))
+ return Eperm;
+#endif
+ ram[r->parent].mtime = time(0);
+ realremove(r);
+ return 0;
+}
+
+char *
+rstat(Fid *f)
+{
+ if(f->ram->busy == 0)
+ return Enotexist;
+ rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);
+ rhdr.stat = statbuf;
+ return 0;
+}
+
+char *
+rwstat(Fid *f)
+{
+ Ram *r, *s;
+ Dir dir;
+
+ if(f->ram->busy == 0)
+ return Enotexist;
+ convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);
+ r = f->ram;
+
+ /*
+ * To change length, must have write permission on file.
+ */
+#ifdef CHECKS
+ if(dir.length!=~0 && dir.length!=r->ndata){
+ if(!perm(f, r, Pwrite))
+ return Eperm;
+ }
+#endif
+
+ /*
+ * To change name, must have write permission in parent
+ * and name must be unique.
+ */
+ if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){
+#ifdef CHECKS
+ if(!perm(f, &ram[r->parent], Pwrite))
+ return Eperm;
+#endif
+ for(s=ram; s<&ram[nram]; s++)
+ if(s->busy && s->parent==r->parent)
+ if(strcmp(dir.name, s->name)==0)
+ return Eexist;
+ }
+
+#ifdef OWNERS
+ /*
+ * To change mode, must be owner or group leader.
+ * Because of lack of users file, leader=>group itself.
+ */
+ if(dir.mode!=~0 && r->perm!=dir.mode){
+ if(strcmp(f->user, r->user) != 0)
+ if(strcmp(f->user, r->group) != 0)
+ return Enotowner;
+ }
+
+ /*
+ * To change group, must be owner and member of new group,
+ * or leader of current group and leader of new group.
+ * Second case cannot happen, but we check anyway.
+ */
+ if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){
+ if(strcmp(f->user, r->user) == 0)
+ if(strcmp(f->user, dir.gid) == 0)
+ goto ok;
+ if(strcmp(f->user, r->group) == 0)
+ if(strcmp(f->user, dir.gid) == 0)
+ goto ok;
+ return Enotowner;
+ ok:;
+ }
+#endif
+
+ /* all ok; do it */
+ if(dir.mode != ~0){
+ dir.mode &= ~DMDIR; /* cannot change dir bit */
+ dir.mode |= r->perm&DMDIR;
+ r->perm = dir.mode;
+ }
+ if(dir.name[0] != '\0'){
+ free(r->name);
+ r->name = estrdup(dir.name);
+ }
+ if(dir.gid[0] != '\0')
+ r->group = atom(dir.gid);
+
+ if(dir.uid[0] != '\0')
+ r->user = atom(dir.uid);
+
+ if(dir.length!=~0 && dir.length!=r->ndata){
+ r->data = erealloc(r->data, dir.length);
+ if(r->ndata < dir.length)
+ memset(r->data+r->ndata, 0, dir.length-r->ndata);
+ r->ndata = dir.length;
+ }
+
+ if(dir.mtime != ~0)
+ r->mtime = dir.mtime;
+
+ ram[r->parent].mtime = time(0);
+ return 0;
+}
+
+uint
+ramstat(Ram *r, uchar *buf, uint nbuf)
+{
+ Dir dir;
+
+ dir.name = r->name;
+ dir.qid = r->qid;
+ dir.mode = r->perm;
+ dir.length = r->ndata;
+ dir.uid = r->user;
+ dir.gid = r->group;
+ dir.muid = r->muid;
+ dir.atime = r->atime;
+ dir.mtime = r->mtime;
+ return convD2M(&dir, buf, nbuf);
+}
+
+Fid *
+newfid(int fid)
+{
+ Fid *f, *ff;
+
+ ff = 0;
+ for(f = fids; f; f = f->next)
+ if(f->fid == fid)
+ return f;
+ else if(!ff && !f->busy)
+ ff = f;
+ if(ff){
+ ff->fid = fid;
+ return ff;
+ }
+ f = emalloc(sizeof *f);
+ f->ram = nil;
+ f->fid = fid;
+ f->next = fids;
+ fids = f;
+ return f;
+}
+
+void
+io(void)
+{
+ char *err;
+ int n, pid;
+
+ pid = getpid();
+
+ for(;;){
+ /*
+ * reading from a pipe or a network device
+ * will give an error after a few eof reads.
+ * however, we cannot tell the difference
+ * between a zero-length read and an interrupt
+ * on the processes writing to us,
+ * so we wait for the error.
+ */
+ n = read9pmsg(mfd[0], mdata, messagesize);
+ if(n < 0)
+ error("mount read: %r");
+ if(n == 0)
+ continue;
+ if(convM2S(mdata, n, &thdr) == 0)
+ continue;
+
+ if(debug)
+ fprint(2, "ramfs %d:<-%F\n", pid, &thdr);
+
+ if(!fcalls[thdr.type])
+ err = "bad fcall type";
+ else
+ err = (*fcalls[thdr.type])(newfid(thdr.fid));
+ if(err){
+ rhdr.type = Rerror;
+ rhdr.ename = err;
+ }else{
+ rhdr.type = thdr.type + 1;
+ rhdr.fid = thdr.fid;
+ }
+ rhdr.tag = thdr.tag;
+ if(debug)
+ fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/
+ n = convS2M(&rhdr, mdata, messagesize);
+ if(n == 0)
+ error("convS2M error on write");
+ if(write(mfd[1], mdata, n) != n)
+ error("mount write");
+ }
+}
+
+int
+perm(Fid *f, Ram *r, int p)
+{
+ if((p*Pother) & r->perm)
+ return 1;
+ if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))
+ return 1;
+ if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))
+ return 1;
+ return 0;
+}
+
+void *
+emalloc(ulong n)
+{
+ void *p;
+
+ p = malloc(n);
+ if(!p)
+ error("out of memory");
+ memset(p, 0, n);
+ return p;
+}
+
+void *
+erealloc(void *p, ulong n)
+{
+ p = realloc(p, n);
+ if(!p)
+ error("out of memory");
+ return p;
+}
+
+char *
+estrdup(char *q)
+{
+ char *p;
+ int n;
+
+ n = strlen(q)+1;
+ p = malloc(n);
+ if(!p)
+ error("out of memory");
+ memmove(p, q, n);
+ return p;
+}
+
+void
+ramfsusage(void)
+{
+ fprint(2, "usage: %s [-is] [-m mountpoint]\n", argv0);
+ exits("usage");
+}
+
+/*
+ * Custom allocators to avoid malloc overheads on small objects.
+ * We never free these. (See below.)
+ */
+typedef struct Stringtab Stringtab;
+struct Stringtab {
+ Stringtab *link;
+ char *str;
+};
+static Stringtab*
+taballoc(void)
+{
+ static Stringtab *t;
+ static uint nt;
+
+ if(nt == 0){
+ t = malloc(64*sizeof(Stringtab));
+ if(t == 0)
+ sysfatal("out of memory");
+ nt = 64;
+ }
+ nt--;
+ return t++;
+}
+
+static char*
+xstrdup(char *s)
+{
+ char *r;
+ int len;
+ static char *t;
+ static int nt;
+
+ len = strlen(s)+1;
+ if(len >= 8192)
+ sysfatal("strdup big string");
+
+ if(nt < len){
+ t = malloc(8192);
+ if(t == 0)
+ sysfatal("out of memory");
+ nt = 8192;
+ }
+ r = t;
+ t += len;
+ nt -= len;
+ strcpy(r, s);
+ return r;
+}
+
+/*
+ * Return a uniquely allocated copy of a string.
+ * Don't free these -- they stay in the table for the
+ * next caller who wants that particular string.
+ * String comparison can be done with pointer comparison
+ * if you know both strings are atoms.
+ */
+static Stringtab *stab[1024];
+
+static uint
+hash(char *s)
+{
+ uint h;
+ uchar *p;
+
+ h = 0;
+ for(p=(uchar*)s; *p; p++)
+ h = h*37 + *p;
+ return h;
+}
+
+char*
+atom(char *str)
+{
+ uint h;
+ Stringtab *tab;
+
+ h = hash(str) % nelem(stab);
+ for(tab=stab[h]; tab; tab=tab->link)
+ if(strcmp(str, tab->str) == 0)
+ return tab->str;
+
+ tab = taballoc();
+ tab->str = xstrdup(str);
+ tab->link = stab[h];
+ stab[h] = tab;
+ return tab->str;
+}
--- /dev/null
+++ b/sys/src/cmd/bzfs/unbflz.c
@@ -1,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "bzfs.h"
+
+int
+Bgetint(Biobuf *b)
+{
+ uchar p[4];
+
+ if(Bread(b, p, 4) != 4)
+ sysfatal("short read");
+ return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+/*
+ * memmove but make sure overlap works properly.
+ */
+void
+copy(uchar *dst, uchar *src, int n)
+{
+ while(n-- > 0)
+ *dst++ = *src++;
+}
+
+int
+unbflz(int in)
+{
+ int rv, out, p[2];
+ Biobuf *b, bin;
+ char buf[5];
+ uchar *data;
+ int i, j, length, n, m, o, sum;
+ ulong *blk;
+ int nblk, mblk;
+
+ if(pipe(p) < 0)
+ sysfatal("pipe: %r");
+
+ rv = p[0];
+ out = p[1];
+ switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ close(rv);
+ break;
+ default:
+ close(in);
+ close(out);
+ return rv;
+ }
+
+ Binit(&bin, in, OREAD);
+ b = &bin;
+
+ if(Bread(b, buf, 4) != 4)
+ sysfatal("short read");
+
+ if(memcmp(buf, "BLZ\n", 4) != 0)
+ sysfatal("bad header");
+
+ length = Bgetint(b);
+ data = malloc(length);
+ if(data == nil)
+ sysfatal("out of memory");
+ sum = 0;
+ nblk = 0;
+ mblk = 0;
+ blk = nil;
+ while(sum < length){
+ if(nblk>=mblk){
+ mblk += 16384;
+ blk = realloc(blk, (mblk+1)*sizeof(blk[0]));
+ if(blk == nil)
+ sysfatal("out of memory");
+ }
+ n = Bgetint(b);
+ blk[nblk++] = n;
+ if(n&(1<<31))
+ n &= ~(1<<31);
+ else
+ blk[nblk++] = Bgetint(b);
+ sum += n;
+ }
+ if(sum != length)
+ sysfatal("bad compressed data %d %d", sum, length);
+ i = 0;
+ j = 0;
+ while(i < length){
+ assert(j < nblk);
+ n = blk[j++];
+ if(n&(1<<31)){
+ n &= ~(1<<31);
+ if((m=Bread(b, data+i, n)) != n)
+ sysfatal("short read %d %d", n, m);
+ }else{
+ o = blk[j++];
+ copy(data+i, data+o, n);
+ }
+ i += n;
+ }
+ write(out, data, length);
+ close(in);
+ close(out);
+ _exits(0);
+ return -1;
+}
--- /dev/null
+++ b/sys/src/cmd/bzfs/unbzip.c
@@ -1,0 +1,861 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "bzfs.h"
+
+/*
+ * THIS FILE IS NOT IDENTICAL TO THE ORIGINAL
+ * FROM THE BZIP2 DISTRIBUTION.
+ *
+ * It has been modified, mainly to break the library
+ * into smaller pieces.
+ *
+ * Russ Cox
+ * [email protected]
+ * July 2000
+ */
+
+/*---------------------------------------------*/
+/*--
+ Place a 1 beside your platform, and 0 elsewhere.
+ Attempts to autosniff this even if you don't.
+--*/
+
+
+/*--
+ Plan 9 from Bell Labs
+--*/
+#define BZ_PLAN9 1
+#define BZ_UNIX 0
+
+#define exit(x) exits((x) ? "whoops" : nil)
+#define size_t ulong
+
+#ifdef __GNUC__
+# define NORETURN __attribute__ ((noreturn))
+#else
+# define NORETURN /**/
+#endif
+
+/*--
+ Some more stuff for all platforms :-)
+ This might have to get moved into the platform-specific
+ header files if we encounter a machine with different sizes.
+--*/
+
+typedef char Char;
+typedef unsigned char Bool;
+typedef unsigned char UChar;
+typedef int Int32;
+typedef unsigned int UInt32;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#define True ((Bool)1)
+#define False ((Bool)0)
+
+/*--
+ IntNative is your platform's `native' int size.
+ Only here to avoid probs with 64-bit platforms.
+--*/
+typedef int IntNative;
+
+#include "bzfs.h"
+#include "bzlib.h"
+#include "bzlib_private.h"
+
+static int
+bunzip(int ofd, char *ofile, Biobuf *bin)
+{
+ int e, n, done, onemore;
+ char buf[8192];
+ char obuf[8192];
+ Biobuf bout;
+ bz_stream strm;
+
+ USED(ofile);
+
+ memset(&strm, 0, sizeof strm);
+ BZ2_bzDecompressInit(&strm, 0, 0);
+
+ strm.next_in = buf;
+ strm.avail_in = 0;
+ strm.next_out = obuf;
+ strm.avail_out = sizeof obuf;
+
+ done = 0;
+ Binit(&bout, ofd, OWRITE);
+
+ /*
+ * onemore is a crummy hack to go 'round the loop
+ * once after we finish, to flush the output buffer.
+ */
+ onemore = 1;
+ SET(e);
+ do {
+ if(!done && strm.avail_in < sizeof buf) {
+ if(strm.avail_in)
+ memmove(buf, strm.next_in, strm.avail_in);
+
+ n = Bread(bin, buf+strm.avail_in, sizeof(buf)-strm.avail_in);
+ if(n <= 0)
+ done = 1;
+ else
+ strm.avail_in += n;
+ strm.next_in = buf;
+ }
+ if(strm.avail_out < sizeof obuf) {
+ Bwrite(&bout, obuf, sizeof(obuf)-strm.avail_out);
+ strm.next_out = obuf;
+ strm.avail_out = sizeof obuf;
+ }
+
+ if(onemore == 0)
+ break;
+ } while((e=BZ2_bzDecompress(&strm)) == BZ_OK || onemore--);
+
+ if(e != BZ_STREAM_END) {
+ fprint(2, "bunzip2: decompress failed\n");
+ return 0;
+ }
+
+ if(BZ2_bzDecompressEnd(&strm) != BZ_OK) {
+ fprint(2, "bunzip2: decompress end failed (can't happen)\n");
+ return 0;
+ }
+
+ Bterm(&bout);
+
+ return 1;
+}
+
+void
+_unbzip(int in, int out)
+{
+ Biobuf bin;
+
+ Binit(&bin, in, OREAD);
+ if(bunzip(out, nil, &bin) != 1) {
+ fprint(2, "bunzip2 failed\n");
+ _exits("bunzip2");
+ }
+}
+
+int
+unbzip(int in)
+{
+ int rv, out, p[2];
+
+ if(pipe(p) < 0)
+ sysfatal("pipe: %r");
+
+ rv = p[0];
+ out = p[1];
+ switch(rfork(RFPROC|RFFDG|RFNOTEG|RFMEM)){
+ case -1:
+ sysfatal("fork: %r");
+ case 0:
+ close(rv);
+ break;
+ default:
+ close(in);
+ close(out);
+ return rv;
+ }
+
+ _unbzip(in, out);
+ _exits(0);
+ return -1; /* not reached */
+}
+
+int bz_config_ok ( void )
+{
+ if (sizeof(int) != 4) return 0;
+ if (sizeof(short) != 2) return 0;
+ if (sizeof(char) != 1) return 0;
+ return 1;
+}
+
+void* default_bzalloc(void *o, int items, int size)
+{
+ USED(o);
+ return sbrk(items*size);
+}
+
+void default_bzfree(void*, void*)
+{
+}
+
+void
+bz_internal_error(int)
+{
+ abort();
+}
+
+/*-------------------------------------------------------------*/
+/*--- Decompression machinery ---*/
+/*--- decompress.c ---*/
+/*-------------------------------------------------------------*/
+
+/*--
+ This file is a part of bzip2 and/or libbzip2, a program and
+ library for lossless, block-sorting data compression.
+
+ Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Julian Seward, Cambridge, UK.
+ [email protected]
+ bzip2/libbzip2 version 1.0 of 21 March 2000
+
+ This program is based on (at least) the work of:
+ Mike Burrows
+ David Wheeler
+ Peter Fenwick
+ Alistair Moffat
+ Radford Neal
+ Ian H. Witten
+ Robert Sedgewick
+ Jon L. Bentley
+
+ For more information on these sources, see the manual.
+--*/
+
+
+
+/*---------------------------------------------------*/
+static
+void makeMaps_d ( DState* s )
+{
+ Int32 i;
+ s->nInUse = 0;
+ for (i = 0; i < 256; i++)
+ if (s->inUse[i]) {
+ s->seqToUnseq[s->nInUse] = i;
+ s->nInUse++;
+ }
+}
+
+
+/*---------------------------------------------------*/
+#define RETURN(rrr) \
+ { retVal = rrr; goto save_state_and_return; };
+
+#define GET_BITS(lll,vvv,nnn) \
+ case lll: \
+ { int x; if((retVal = getbits(s, lll, &x, nnn)) != 99) \
+ goto save_state_and_return; vvv=x; }\
+
+int
+getbits(DState *s, int lll, int *vvv, int nnn)
+{
+ s->state = lll;
+
+ for(;;) {
+ if (s->bsLive >= nnn) {
+ UInt32 v;
+ v = (s->bsBuff >>
+ (s->bsLive-nnn)) & ((1 << nnn)-1);
+ s->bsLive -= nnn;
+ *vvv = v;
+ return 99;
+ }
+ if (s->strm->avail_in == 0) return BZ_OK;
+ s->bsBuff
+ = (s->bsBuff << 8) |
+ ((UInt32)
+ (*((UChar*)(s->strm->next_in))));
+ s->bsLive += 8;
+ s->strm->next_in++;
+ s->strm->avail_in--;
+ s->strm->total_in_lo32++;
+ if (s->strm->total_in_lo32 == 0)
+ s->strm->total_in_hi32++;
+ }
+ return -1; /* KEN */
+}
+
+#define GET_UCHAR(lll,uuu) \
+ GET_BITS(lll,uuu,8)
+
+#define GET_BIT(lll,uuu) \
+ GET_BITS(lll,uuu,1)
+
+/*---------------------------------------------------*/
+#define GET_MTF_VAL(label1,label2,lval) \
+{ \
+ if (groupPos == 0) { \
+ groupNo++; \
+ if (groupNo >= nSelectors) \
+ RETURN(BZ_DATA_ERROR); \
+ groupPos = BZ_G_SIZE; \
+ gSel = s->selector[groupNo]; \
+ gMinlen = s->minLens[gSel]; \
+ gLimit = &(s->limit[gSel][0]); \
+ gPerm = &(s->perm[gSel][0]); \
+ gBase = &(s->base[gSel][0]); \
+ } \
+ groupPos--; \
+ zn = gMinlen; \
+ GET_BITS(label1, zvec, zn); \
+ while (1) { \
+ if (zn > 20 /* the longest code */) \
+ RETURN(BZ_DATA_ERROR); \
+ if (zvec <= gLimit[zn]) break; \
+ zn++; \
+ GET_BIT(label2, zj); \
+ zvec = (zvec << 1) | zj; \
+ }; \
+ if (zvec - gBase[zn] < 0 \
+ || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
+ RETURN(BZ_DATA_ERROR); \
+ lval = gPerm[zvec - gBase[zn]]; \
+}
+
+
+/*---------------------------------------------------*/
+Int32 BZ2_decompress ( DState* s )
+{
+ UChar uc;
+ Int32 retVal;
+ Int32 minLen, maxLen;
+ bz_stream* strm = s->strm;
+
+ /* stuff that needs to be saved/restored */
+ Int32 i;
+ Int32 j;
+ Int32 t;
+ Int32 alphaSize;
+ Int32 nGroups;
+ Int32 nSelectors;
+ Int32 EOB;
+ Int32 groupNo;
+ Int32 groupPos;
+ Int32 nextSym;
+ Int32 nblockMAX;
+ Int32 nblock;
+ Int32 es;
+ Int32 N;
+ Int32 curr;
+ Int32 zt;
+ Int32 zn;
+ Int32 zvec;
+ Int32 zj;
+ Int32 gSel;
+ Int32 gMinlen;
+ Int32* gLimit;
+ Int32* gBase;
+ Int32* gPerm;
+
+ if (s->state == BZ_X_MAGIC_1) {
+ /*initialise the save area*/
+ s->save_i = 0;
+ s->save_j = 0;
+ s->save_t = 0;
+ s->save_alphaSize = 0;
+ s->save_nGroups = 0;
+ s->save_nSelectors = 0;
+ s->save_EOB = 0;
+ s->save_groupNo = 0;
+ s->save_groupPos = 0;
+ s->save_nextSym = 0;
+ s->save_nblockMAX = 0;
+ s->save_nblock = 0;
+ s->save_es = 0;
+ s->save_N = 0;
+ s->save_curr = 0;
+ s->save_zt = 0;
+ s->save_zn = 0;
+ s->save_zvec = 0;
+ s->save_zj = 0;
+ s->save_gSel = 0;
+ s->save_gMinlen = 0;
+ s->save_gLimit = NULL;
+ s->save_gBase = NULL;
+ s->save_gPerm = NULL;
+ }
+
+ /*restore from the save area*/
+ i = s->save_i;
+ j = s->save_j;
+ t = s->save_t;
+ alphaSize = s->save_alphaSize;
+ nGroups = s->save_nGroups;
+ nSelectors = s->save_nSelectors;
+ EOB = s->save_EOB;
+ groupNo = s->save_groupNo;
+ groupPos = s->save_groupPos;
+ nextSym = s->save_nextSym;
+ nblockMAX = s->save_nblockMAX;
+ nblock = s->save_nblock;
+ es = s->save_es;
+ N = s->save_N;
+ curr = s->save_curr;
+ zt = s->save_zt;
+ zn = s->save_zn;
+ zvec = s->save_zvec;
+ zj = s->save_zj;
+ gSel = s->save_gSel;
+ gMinlen = s->save_gMinlen;
+ gLimit = s->save_gLimit;
+ gBase = s->save_gBase;
+ gPerm = s->save_gPerm;
+
+ retVal = BZ_OK;
+
+ switch (s->state) {
+
+ GET_UCHAR(BZ_X_MAGIC_1, uc);
+ if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_2, uc);
+ if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_UCHAR(BZ_X_MAGIC_3, uc)
+ if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC);
+
+ GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
+ if (s->blockSize100k < '1' ||
+ s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC);
+ s->blockSize100k -= '0';
+
+ if (0 && s->smallDecompress) {
+ s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
+ s->ll4 = BZALLOC(
+ ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
+ );
+ if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
+ } else {
+ s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
+ if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
+ }
+
+ GET_UCHAR(BZ_X_BLKHDR_1, uc);
+
+ if (uc == 0x17) goto endhdr_2;
+ if (uc != 0x31) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_2, uc);
+ if (uc != 0x41) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_3, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_4, uc);
+ if (uc != 0x26) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_5, uc);
+ if (uc != 0x53) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_BLKHDR_6, uc);
+ if (uc != 0x59) RETURN(BZ_DATA_ERROR);
+
+ s->currBlockNo++;
+ // if (s->verbosity >= 2)
+ // VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
+
+ s->storedBlockCRC = 0;
+ GET_UCHAR(BZ_X_BCRC_1, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_2, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_3, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_BCRC_4, uc);
+ s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
+
+ GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
+
+ s->origPtr = 0;
+ GET_UCHAR(BZ_X_ORIGPTR_1, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_2, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+ GET_UCHAR(BZ_X_ORIGPTR_3, uc);
+ s->origPtr = (s->origPtr << 8) | ((Int32)uc);
+
+ if (s->origPtr < 0)
+ RETURN(BZ_DATA_ERROR);
+ if (s->origPtr > 10 + 100000*s->blockSize100k)
+ RETURN(BZ_DATA_ERROR);
+
+ /*--- Receive the mapping table ---*/
+ for (i = 0; i < 16; i++) {
+ GET_BIT(BZ_X_MAPPING_1, uc);
+ if (uc == 1)
+ s->inUse16[i] = True; else
+ s->inUse16[i] = False;
+ }
+
+ for (i = 0; i < 256; i++) s->inUse[i] = False;
+
+ for (i = 0; i < 16; i++)
+ if (s->inUse16[i])
+ for (j = 0; j < 16; j++) {
+ GET_BIT(BZ_X_MAPPING_2, uc);
+ if (uc == 1) s->inUse[i * 16 + j] = True;
+ }
+ makeMaps_d ( s );
+ if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
+ alphaSize = s->nInUse+2;
+
+ /*--- Now the selectors ---*/
+ GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
+ if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
+ GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
+ if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
+ for (i = 0; i < nSelectors; i++) {
+ j = 0;
+ while (True) {
+ GET_BIT(BZ_X_SELECTOR_3, uc);
+ if (uc == 0) break;
+ j++;
+ if (j >= nGroups) RETURN(BZ_DATA_ERROR);
+ }
+ s->selectorMtf[i] = j;
+ }
+
+ /*--- Undo the MTF values for the selectors. ---*/
+ {
+ UChar pos[BZ_N_GROUPS], tmp, v;
+ for (v = 0; v < nGroups; v++) pos[v] = v;
+
+ for (i = 0; i < nSelectors; i++) {
+ v = s->selectorMtf[i];
+ tmp = pos[v];
+ while (v > 0) { pos[v] = pos[v-1]; v--; }
+ pos[0] = tmp;
+ s->selector[i] = tmp;
+ }
+ }
+
+ /*--- Now the coding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ GET_BITS(BZ_X_CODING_1, curr, 5);
+ for (i = 0; i < alphaSize; i++) {
+ while (True) {
+ if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
+ GET_BIT(BZ_X_CODING_2, uc);
+ if (uc == 0) break;
+ GET_BIT(BZ_X_CODING_3, uc);
+ if (uc == 0) curr++; else curr--;
+ }
+ s->len[t][i] = curr;
+ }
+ }
+
+ /*--- Create the Huffman decoding tables ---*/
+ for (t = 0; t < nGroups; t++) {
+ minLen = 32;
+ maxLen = 0;
+ for (i = 0; i < alphaSize; i++) {
+ if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
+ if (s->len[t][i] < minLen) minLen = s->len[t][i];
+ }
+ BZ2_hbCreateDecodeTables (
+ &(s->limit[t][0]),
+ &(s->base[t][0]),
+ &(s->perm[t][0]),
+ &(s->len[t][0]),
+ minLen, maxLen, alphaSize
+ );
+ s->minLens[t] = minLen;
+ }
+
+ /*--- Now the MTF values ---*/
+
+ EOB = s->nInUse+1;
+ nblockMAX = 100000 * s->blockSize100k;
+ groupNo = -1;
+ groupPos = 0;
+
+ for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
+
+ /*-- MTF init --*/
+ {
+ Int32 ii, jj, kk;
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ /*-- end MTF init --*/
+
+ nblock = 0;
+ GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
+
+ while (True) {
+
+ if (nextSym == EOB) break;
+
+ if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
+
+ es = -1;
+ N = 1;
+ do {
+ if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
+ if (nextSym == BZ_RUNB) es = es + (1+1) * N;
+ N = N * 2;
+ GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
+ }
+ while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
+
+ es++;
+ uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
+ s->unzftab[uc] += es;
+
+ if (0 && s->smallDecompress)
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->ll16[nblock] = (UInt16)uc;
+ nblock++;
+ es--;
+ }
+ else
+ while (es > 0) {
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+ s->tt[nblock] = (UInt32)uc;
+ nblock++;
+ es--;
+ };
+
+ continue;
+
+ } else {
+
+ if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
+
+ /*-- uc = MTF ( nextSym-1 ) --*/
+ {
+ Int32 ii, jj, kk, pp, lno, off;
+ UInt32 nn;
+ nn = (UInt32)(nextSym - 1);
+
+ if (nn < MTFL_SIZE) {
+ /* avoid general-case expense */
+ pp = s->mtfbase[0];
+ uc = s->mtfa[pp+nn];
+ while (nn > 3) {
+ Int32 z = pp+nn;
+ s->mtfa[(z) ] = s->mtfa[(z)-1];
+ s->mtfa[(z)-1] = s->mtfa[(z)-2];
+ s->mtfa[(z)-2] = s->mtfa[(z)-3];
+ s->mtfa[(z)-3] = s->mtfa[(z)-4];
+ nn -= 4;
+ }
+ while (nn > 0) {
+ s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
+ };
+ s->mtfa[pp] = uc;
+ } else {
+ /* general case */
+ lno = nn / MTFL_SIZE;
+ off = nn % MTFL_SIZE;
+ pp = s->mtfbase[lno] + off;
+ uc = s->mtfa[pp];
+ while (pp > s->mtfbase[lno]) {
+ s->mtfa[pp] = s->mtfa[pp-1]; pp--;
+ };
+ s->mtfbase[lno]++;
+ while (lno > 0) {
+ s->mtfbase[lno]--;
+ s->mtfa[s->mtfbase[lno]]
+ = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
+ lno--;
+ }
+ s->mtfbase[0]--;
+ s->mtfa[s->mtfbase[0]] = uc;
+ if (s->mtfbase[0] == 0) {
+ kk = MTFA_SIZE-1;
+ for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
+ for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
+ s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
+ kk--;
+ }
+ s->mtfbase[ii] = kk + 1;
+ }
+ }
+ }
+ }
+ /*-- end uc = MTF ( nextSym-1 ) --*/
+
+ s->unzftab[s->seqToUnseq[uc]]++;
+ if (0 && s->smallDecompress)
+ s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
+ s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
+ nblock++;
+
+ GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
+ continue;
+ }
+ }
+
+ /* Now we know what nblock is, we can do a better sanity
+ check on s->origPtr.
+ */
+ if (s->origPtr < 0 || s->origPtr >= nblock)
+ RETURN(BZ_DATA_ERROR);
+
+ s->state_out_len = 0;
+ s->state_out_ch = 0;
+ BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
+ s->state = BZ_X_OUTPUT;
+ // if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
+
+ /*-- Set up cftab to facilitate generation of T^(-1) --*/
+ s->cftab[0] = 0;
+ for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
+ for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
+
+ if (0 && s->smallDecompress) {
+
+ /*-- Make a copy of cftab, used in generation of T --*/
+ for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
+
+ /*-- compute the T vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->ll16[i]);
+ SET_LL(i, s->cftabCopy[uc]);
+ s->cftabCopy[uc]++;
+ }
+
+ /*-- Compute T^(-1) by pointer reversal on T --*/
+ i = s->origPtr;
+ j = GET_LL(i);
+ do {
+ Int32 tmp = GET_LL(j);
+ SET_LL(j, i);
+ i = j;
+ j = tmp;
+ }
+ while (i != s->origPtr);
+
+ s->tPos = s->origPtr;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_SMALL(s->k0); s->nblock_used++;
+ }
+
+ } else {
+
+ /*-- compute the T^(-1) vector --*/
+ for (i = 0; i < nblock; i++) {
+ uc = (UChar)(s->tt[i] & 0xff);
+ s->tt[s->cftab[uc]] |= (i << 8);
+ s->cftab[uc]++;
+ }
+
+ s->tPos = s->tt[s->origPtr] >> 8;
+ s->nblock_used = 0;
+ if (s->blockRandomised) {
+ BZ_RAND_INIT_MASK;
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
+ } else {
+ BZ_GET_FAST(s->k0); s->nblock_used++;
+ }
+
+ }
+
+ RETURN(BZ_OK);
+
+
+
+ endhdr_2:
+
+ GET_UCHAR(BZ_X_ENDHDR_2, uc);
+ if (uc != 0x72) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_3, uc);
+ if (uc != 0x45) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_4, uc);
+ if (uc != 0x38) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_5, uc);
+ if (uc != 0x50) RETURN(BZ_DATA_ERROR);
+ GET_UCHAR(BZ_X_ENDHDR_6, uc);
+ if (uc != 0x90) RETURN(BZ_DATA_ERROR);
+
+ s->storedCombinedCRC = 0;
+ GET_UCHAR(BZ_X_CCRC_1, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_2, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_3, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+ GET_UCHAR(BZ_X_CCRC_4, uc);
+ s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
+
+ s->state = BZ_X_IDLE;
+ RETURN(BZ_STREAM_END);
+
+ default: AssertH ( False, 4001 );
+ }
+
+ AssertH ( False, 4002 );
+
+ save_state_and_return:
+
+ s->save_i = i;
+ s->save_j = j;
+ s->save_t = t;
+ s->save_alphaSize = alphaSize;
+ s->save_nGroups = nGroups;
+ s->save_nSelectors = nSelectors;
+ s->save_EOB = EOB;
+ s->save_groupNo = groupNo;
+ s->save_groupPos = groupPos;
+ s->save_nextSym = nextSym;
+ s->save_nblockMAX = nblockMAX;
+ s->save_nblock = nblock;
+ s->save_es = es;
+ s->save_N = N;
+ s->save_curr = curr;
+ s->save_zt = zt;
+ s->save_zn = zn;
+ s->save_zvec = zvec;
+ s->save_zj = zj;
+ s->save_gSel = gSel;
+ s->save_gMinlen = gMinlen;
+ s->save_gLimit = gLimit;
+ s->save_gBase = gBase;
+ s->save_gPerm = gPerm;
+
+ return retVal;
+}
+
+
+/*-------------------------------------------------------------*/
+/*--- end decompress.c ---*/
+/*-------------------------------------------------------------*/
--- /dev/null
+++ b/sys/src/cmd/touchfs.c
@@ -1,0 +1,66 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void
+Bpass(Biobuf *bin, Biobuf *bout, int n)
+{
+ char buf[8192];
+ int m;
+
+ while(n > 0) {
+ m = sizeof buf;
+ if(m > n)
+ m = n;
+ m = Bread(bin, buf, m);
+ if(m <= 0) {
+ fprint(2, "corrupt archive\n");
+ exits("notdone");
+ }
+ Bwrite(bout, buf, m);
+ n -= m;
+ }
+ assert(n == 0);
+}
+
+void
+main(int argc, char **argv)
+{
+ char *p, *f[10];
+ Biobuf bin, bout;
+ int nf;
+ ulong d, size;
+
+ if(argc != 2) {
+ fprint(2, "usage: cat mkfs-archive | touchfs date (in seconds)\n");
+ exits("usage");
+ }
+
+ d = strtoul(argv[1], 0, 0);
+
+ quotefmtinstall();
+ Binit(&bin, 0, OREAD);
+ Binit(&bout, 1, OWRITE);
+
+ while(p = Brdline(&bin, '\n')) {
+ p[Blinelen(&bin)-1] = '\0';
+ if(strcmp(p, "end of archive") == 0) {
+ Bprint(&bout, "end of archive\n");
+ exits(0);
+ }
+
+ nf = tokenize(p, f, nelem(f));
+ if(nf != 6) {
+ fprint(2, "corrupt archive\n");
+ exits("notdone");
+ }
+
+ Bprint(&bout, "%q %q %q %q %lud %q\n",
+ f[0], f[1], f[2], f[3], d, f[5]);
+
+ size = strtoul(f[5], 0, 0);
+ Bpass(&bin, &bout, size);
+ }
+ fprint(2, "premature end of archive\n");
+ exits("notdone");
+}