summaryrefslogtreecommitdiff
path: root/sys/src/cmd/bzfs/mkext.c
diff options
context:
space:
mode:
authoriru <devnull@localhost>2011-04-14 00:35:48 -0300
committeriru <devnull@localhost>2011-04-14 00:35:48 -0300
commitfd8d404d520a3f10c143f5cbe7c170606fffc75c (patch)
treefbc8bf7218eca7d6290ffb1109fcc73b5b5cda33 /sys/src/cmd/bzfs/mkext.c
parentdd468419f2fbaa2c3fec570a88d13e8eae8f3faf (diff)
Promote the old installer/livecd specific tools to normal tools under /sys/src/cmd. Where similar common tools already existed, I kept them.
Diffstat (limited to 'sys/src/cmd/bzfs/mkext.c')
-rw-r--r--sys/src/cmd/bzfs/mkext.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/sys/src/cmd/bzfs/mkext.c b/sys/src/cmd/bzfs/mkext.c
new file mode 100644
index 000000000..1fedd62cc
--- /dev/null
+++ b/sys/src/cmd/bzfs/mkext.c
@@ -0,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;
+}