#include #include #include #include "cram.h" uint getle(uchar *buf, int n) { uint x; x = 0; while(--n >= 0) x = x<<8 | buf[n]; return x; } u8int get8(uchar *buf) { return getle(buf, 1); } u16int get16(uchar *buf) { return getle(buf, 2); } u32int get24(uchar *buf) { return getle(buf, 3); } u32int get32(uchar *buf) { return getle(buf, 4); } long Bpread(Biobuf *b, void *buf, long n, vlong o) { if(Bseek(b, o, 0) < 0) return -1; return Bread(b, buf, n); } int readdentry(Biobuf *disk, Dentry *dentry, vlong offset) { uchar buf[12]; int n, mode; if((n = Bpread(disk, buf, sizeof buf, offset)) < 0) return -1; if(n < sizeof buf) { werrstr("short read: %d/%d", n, sizeof buf); return -1; } dentry->offset = offset; dentry->mode = (mode = get16(buf+0)) & 0777; if(mode & 040000) dentry->mode |= DMDIR; dentry->uid = get16(buf+2); dentry->length = get24(buf+4); dentry->gid = get8(buf+7); dentry->index = (get24(buf+9)<<2 | *(buf+8)>>6) << 2; if(~dentry->mode & DMDIR) dentry->data = dentry->index + (dentry->length + Blocksz-1)/Blocksz * 4; else dentry->data = dentry->index; dentry->namelen = (get8(buf+8) & 0x3F) << 2; if((n = Bpread(disk, dentry->name, dentry->namelen, offset+12)) < 0) { werrstr("name: %r"); return -1; } dentry->name[n] = '\0'; while(dentry->namelen > 0 && dentry->name[dentry->namelen-1] == '\0') dentry->namelen--; return 12+n; } void printdentry(char *pfx, Dentry *d) { print("%s%#llx %#.4uo %d %d %d %#llx %#llx %d %s\n", pfx, d->offset, d->mode, d->uid, d->gid, d->length, d->index, d->data, d->namelen, d->name ); } void readsuper(Biobuf *disk, Super *super) { uchar buf[64]; int n; if((n = Bread(disk, buf, sizeof buf)) < 0) sysfatal("read header: %r"); if(n < sizeof buf) sysfatal("short header: %d/%d", n, sizeof buf); if(get32(buf+0) != 0x28cd3d45) sysfatal("bad magic: %#.8ux", get32(buf+0)); super->size = get32(buf+4); super->flags = get32(buf+8); if(strncmp((char *)buf+16, "Compressed ROMFS", 16) != 0) sysfatal("bad signature: %.16s", (char *)buf+16); super->crc = get32(buf+32); super->edition = get32(buf+36); super->nblocks = get32(buf+40); super->nfiles = get32(buf+44); if(readdentry(disk, &super->root, 64) < 0) sysfatal("read root dentry: %r"); }