2 * bzip2-based file system.
3 * the file system itself is just a bzipped2 xzipped mkfs archive
4 * prefixed with "bzfilesystem\n" and suffixed with
7 * changes to the file system are only kept in
8 * memory, not written back to the disk.
10 * this is intended for use on a floppy boot disk.
11 * we assume the file is in the dos file system and
12 * contiguous on the disk: finding it amounts to
13 * looking at the beginning of each sector for
14 * "bzfilesystem\n". then we pipe it through
15 * bunzip2 and store the files in a file tree in memory.
16 * things are slightly complicated by the fact that
17 * devfloppy requires reads to be on a 512-byte
18 * boundary and be a multiple of 512 bytes; we
19 * fork a process to relieve bunzip2 of this restriction.
31 NFLDS = 6, /* filename, modes, uid, gid, mtime, bytes */
34 void mkdirs(char*, char*);
35 void mkdir(char*, ulong, ulong, char*, char*);
36 void extract(char*, ulong, ulong, char*, char*, ulong);
38 void error(char*, ...);
39 void warn(char*, ...);
48 fprint(2, "usage: bzfs [-m mtpt] [-s] [-f file] [-h]\n");
53 * floppy disks can only be read on 512-byte
54 * boundaries and in 512 byte multiples.
55 * feed one over a pipe to allow arbitrary reading.
59 blockread(int in, char *first, int nfirst)
68 switch(rfork(RFPROC|RFNOTEG|RFFDG)){
80 write(out, first, nfirst);
82 while((n=read(in, blk, sizeof blk)) > 0){
83 if(write(out, blk, n) != n)
85 if(n == sizeof(blk) && memcmp(zero, blk, n) == n)
92 enum { NAMELEN = 28 };
95 main(int argc, char **argv)
99 char *fields[NFLDS], name[2*LEN], *p, *namep;
100 char uid[NAMELEN], gid[NAMELEN];
101 ulong mode, bytes, mtime;
103 int i, n, stdin, fd, chatty;
106 if(argc>1 && strcmp(argv[1], "RAMFS") == 0){
108 ramfsmain(argc-1, argv+1);
111 if(argc>1 && strcmp(argv[1], "BUNZIP") == 0){
143 fprint(2, "must specify -f file\n");
147 if((fd = open(file, OREAD)) < 0) {
148 fprint(2, "cannot open \"%s\": %r\n", file);
155 rargv[rargc++] = "-i";
156 rargv[rargc++] = "-m";
157 rargv[rargc++] = mtpt;
159 ramfsmain(rargc, rargv);
161 if(1 || strstr(file, "disk")) { /* search for archive on block boundary */
162 if(chatty) fprint(2, "searching for bz\n");
164 if((n = readn(fd, blk, sizeof blk)) != sizeof blk)
165 sysfatal("read %d gets %d: %r\n", i, n);
166 if(strncmp(blk, "bzfilesystem\n", 13) == 0)
169 if(chatty) fprint(2, "found at %d\n", i);
173 error("chdir %s: %r", mtpt);
175 fd = unbflz(unbzip(blockread(fd, blk+13, sizeof(blk)-13)));
177 Binits(&bin, fd, OREAD, binbuf, sizeof binbuf);
178 while(p = Brdline(&bin, '\n')){
179 p[Blinelen(&bin)-1] = '\0';
180 if(chatty) fprint(2, "%s\n", p);
181 if(strcmp(p, "end of archive") == 0){
184 if(getfields(p, fields, NFLDS, 0, " \t") != NFLDS){
185 warn("too few fields in file header");
188 strcpy(namep, fields[0]);
189 mode = strtoul(fields[1], 0, 8);
190 mtime = strtoul(fields[4], 0, 10);
191 bytes = strtoul(fields[5], 0, 10);
192 strncpy(uid, fields[2], NAMELEN);
193 strncpy(gid, fields[3], NAMELEN);
195 mkdir(name, mode, mtime, uid, gid);
197 extract(name, mode, mtime, uid, gid, bytes);
199 fprint(2, "premature end of archive\n");
200 exits("premature end of archive");
206 ffcreate(char *name, ulong mode, char *uid, char *gid, ulong mtime, int length)
211 sprint(buf, "%s/%s", mtpt, name);
215 if((fd = create(buf, om, (mode&DMDIR)|0666)) < 0)
216 error("create %s: %r", buf);
225 if(dirfwstat(fd, &nd) < 0)
226 error("fwstat %s: %r", buf);
232 mkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid)
234 close(ffcreate(name, mode, uid, gid, mtime, 0));
238 extract(char *name, ulong mode, ulong mtime, char *uid, char *gid, ulong bytes)
242 fd = ffcreate(name, mode, uid, gid, mtime, bytes);
244 for(tot = 0; tot < bytes; tot += n){
248 n = Bread(&bin, buf, n);
250 error("premature eof reading %s", name);
251 if(write(fd, buf, n) != n)
252 error("short write writing %s", name);
258 error(char *fmt, ...)
263 sprint(buf, "%s: ", argv0);
265 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
267 fprint(2, "%s\n", buf);
277 sprint(buf, "%s: ", argv0);
279 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
281 fprint(2, "%s\n", buf);