Commit Diff


commit - 8ecefa411d235498ed036c6e173f62547a2e5dd4
commit + e060bc52275a6d7eff5238fba5ba592004da3eb3
blob - d26d0ff3ac595a3dea42a957fe5ad5d162e64d18
blob + f6a87883df7d20efe4bf8c0d41d48aebb00eeca1
--- src/libdiskfs/ffs.c
+++ src/libdiskfs/ffs.c
@@ -6,6 +6,8 @@
 #include <diskfs.h>
 #include "ffs.h"
 
+#define BADBNO	((u64int)~0ULL)
+
 #define checkcg 0
 #define debug 0
 
@@ -57,7 +59,7 @@ error:
 }
 
 static Cgblk*
-ffscylgrp(Ffs *fs, int i, Block **pb)
+ffscylgrp(Ffs *fs, u32int i, Block **pb)
 {
 	Block *b;
 	Cgblk *cg;
@@ -82,6 +84,7 @@ static int
 ffssync(Fsys *fsys)
 {
 	int i;
+	int off[] = { SBOFF, SBOFF2, SBOFFPIGGY };
 	Block *b, *cgb;
 	Cgblk *cgblk;
 	Cylgrp *cg;
@@ -95,12 +98,18 @@ ffssync(Fsys *fsys)
 	/*
 	 * Read super block.
 	 */
-	if((b = diskread(disk, SBSIZE, SBOFF)) == nil)
-		goto error;
-	fsblk = (Fsblk*)b->data;
-	if(checkfsblk(fsblk) < 0)
-		goto error;
+	for(i=0; i<nelem(off); i++){
+		if((b = diskread(disk, SBSIZE, off[i])) == nil)
+			goto error;
+		fsblk = (Fsblk*)b->data;
+		fprint(2, "offset of magic: %d\n", offsetof(Fsblk, magic));
+		if((fs->ufs = checkfsblk(fsblk)) > 0)
+			goto okay;
+		blockput(b);
+	}
+	goto error;
 
+okay:
 	fs->blocksize = fsblk->blocksize;
 	fs->nblock = (fsblk->nfrag+fsblk->fragsperblock-1) / fsblk->fragsperblock;
 	fs->fragsize = fsblk->fragsize;
@@ -111,21 +120,31 @@ ffssync(Fsys *fsys)
 
 	fs->nfrag = fsblk->nfrag;
 	fs->ndfrag = fsblk->ndfrag;
-	fs->blockspergroup = (u64int)fsblk->cylspergroup * 
-		fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize;
+	/*
+	 * used to use 
+	 *	fs->blockspergroup = (u64int)fsblk->_cylspergroup * 
+	 *		fsblk->secspercyl * BYTESPERSEC / fsblk->blocksize;
+	 * for UFS1, but this should work for both UFS1 and UFS2
+	 */
+	fs->blockspergroup = (u64int)fsblk->fragspergroup / fsblk->fragsperblock;
 	fs->ncg = fsblk->ncg;
 
 	fsys->blocksize = fs->blocksize;
 	fsys->nblock = fs->nblock;
 
-	if(0) fprint(2, "ffs %d %d-byte blocks, %d cylinder groups\n",
+	if(debug) fprint(2, "ffs %lld %d-byte blocks, %d cylinder groups\n",
 		fs->nblock, fs->blocksize, fs->ncg);
+	if(debug) fprint(2, "\tinospergroup %d perblock %d blockspergroup %lld\n",
+		fs->inospergroup, fs->inosperblock, fs->blockspergroup);
 
 	if(fs->cg == nil)
 		fs->cg = emalloc(fs->ncg*sizeof(Cylgrp));
 	for(i=0; i<fs->ncg; i++){
 		cg = &fs->cg[i];
-		cg->bno = fs->blockspergroup*i + fsblk->cgoffset * (i & ~fsblk->cgmask);
+		if(fs->ufs == 2)
+			cg->bno = (u64int)fs->blockspergroup*i;
+		else
+			cg->bno = fs->blockspergroup*i + fsblk->_cgoffset * (i & ~fsblk->_cgmask);
 		cg->cgblkno = cg->bno + fsblk->cfragno/fs->fragsperblock;
 		cg->ibno = cg->bno + fsblk->ifragno/fs->fragsperblock;
 		cg->dbno = cg->bno + fsblk->dfragno/fs->fragsperblock;
@@ -172,12 +191,20 @@ ffsclose(Fsys *fsys)
 static int
 checkfsblk(Fsblk *super)
 {
-	if(super->magic != FSMAGIC){
-		werrstr("bad super block");
-		return -1;
+fprint(2, "ffs magic 0x%ux\n", super->magic);
+	if(super->magic == FSMAGIC){
+		super->time = super->_time;
+		super->nfrag = super->_nfrag;
+		super->ndfrag = super->_ndfrag;
+		super->flags = super->_flags;
+		return 1;
 	}
+	if(super->magic == FSMAGIC2){
+		return 2;
+	}
 
-	return 0;
+	werrstr("bad super block");
+	return -1;
 }
 
 static int
@@ -198,11 +225,10 @@ int nskipx;
 static Block*
 ffsblockread(Fsys *fsys, u64int bno)
 {
-	u32int i, o;
+	int i, o;
 	u8int *fmap;
 	int frag, fsize, avail;
 	Block *b;
-//	Cylgrp *cg;
 	Cgblk *cgblk;
 	Ffs *fs;
 
@@ -211,11 +237,7 @@ ffsblockread(Fsys *fsys, u64int bno)
 	o = bno % fs->blockspergroup;
 	if(i >= fs->ncg)
 		return nil;
-//	cg = &fs->cg[i];
 
-//	if(o >= cg->nblock)
-//		return nil;
-
 	if((cgblk = ffscylgrp(fs, i, &b)) == nil)
 		return nil;
 
@@ -257,7 +279,7 @@ nskipx++;
 }
 
 static Block*
-ffsdatablock(Ffs *fs, u32int bno, int size)
+ffsdatablock(Ffs *fs, u64int bno, int size)
 {
 	int fsize;
 	u64int diskaddr;
@@ -290,25 +312,26 @@ ffsdatablock(Ffs *fs, u32int bno, int size)
 	return b;
 }
 
-static u32int
-ifetch(Ffs *fs, u32int bno, u32int off)
+static u64int
+ifetch(Ffs *fs, u64int bno, u32int off)
 {
-	u32int *a;
 	Block *b;
 	
-	if(bno == ~0)
-		return ~0;
+	if(bno == BADBNO)
+		return BADBNO;
 	b = ffsdatablock(fs, bno, fs->blocksize);
 	if(b == nil)
-		return ~0;
-	a = (u32int*)b->data;
-	bno = a[off];
+		return BADBNO;
+	if(fs->ufs == 2)
+		bno = ((u64int*)b->data)[off];
+	else
+		bno = ((u32int*)b->data)[off];
 	blockput(b);
 	return bno;
 }
 
-static u32int
-ffsfileblockno(Ffs *fs, Inode *ino, u32int bno)
+static u64int
+ffsfileblockno(Ffs *fs, Inode *ino, u64int bno)
 {
 	int ppb;
 
@@ -329,16 +352,15 @@ ffsfileblockno(Ffs *fs, Inode *ino, u32int bno)
 	
 	if(bno/ppb/ppb/ppb == 0)	/* bno < ppb*ppb*ppb w/o overflow */
 		return ifetch(fs, ifetch(fs, ifetch(fs, ino->ib[2], bno/ppb/ppb), (bno/ppb)%ppb), bno%ppb);
-	bno -= ppb*ppb*ppb;
 	
-	fprint(2, "ffsfileblock %lud: way too big\n", (ulong)bno+NDADDR);
-	return ~0;
+	fprint(2, "ffsfileblock %llud: way too big\n", bno+NDADDR+ppb+ppb*ppb);
+	return BADBNO;
 }
 
 static Block*
-ffsfileblock(Ffs *fs, Inode *ino, u32int bno, int size)
+ffsfileblock(Ffs *fs, Inode *ino, u64int bno, int size)
 {
-	u32int b;
+	u64int b;
 	
 	b = ffsfileblockno(fs, ino, bno);
 	if(b == ~0)
@@ -365,16 +387,44 @@ byte2u32(uchar *p)
 	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 }
 
-static u64int iaddr;
+static u64int lastiaddr;	/* debugging */
 
+static void
+inode1to2(Inode1 *i1, Inode *i2)
+{
+	int i;
+	
+	memset(i2, 0, sizeof *i2);
+	i2->mode = i1->mode;
+	i2->nlink = i1->nlink;
+	i2->size = i1->size;
+	i2->atime = i1->atime;
+	i2->atimensec = i1->atimensec;
+	i2->mtime = i1->mtime;
+	i2->mtimensec = i1->mtimensec;
+	i2->ctime = i1->ctime;
+	i2->ctimensec = i1->ctimensec;
+	for(i=0; i<NDADDR; i++)
+		i2->db[i] = i1->db[i];
+	for(i=0; i<NIADDR; i++)
+		i2->ib[i] = i1->ib[i];
+	i2->flags = i1->flags;
+	i2->nblock = i1->nblock;
+	i2->gen = i1->gen;
+	i2->uid = i1->uid;
+	i2->gid = i1->gid;
+}
+
 static Nfs3Status
 handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inode *ino)
 {
 	int i;
 	u32int ioff;
 	u32int inum;
+	u64int iaddr;
 	Block *b;
 	Cylgrp *cg;
+	Inode1 ino1;
 
 	if(h->len != 4)
 		return Nfs3ErrBadHandle;
@@ -390,20 +440,21 @@ handle2ino(Ffs *fs, Nfs3Handle *h, u32int *pinum, Inod
 	if(i >= fs->ncg)
 		return Nfs3ErrBadHandle;
 	cg = &fs->cg[i];
-/*
-	if(ioff >= cg->nino)
-		return Nfs3ErrBadHandle;
-*/
 
-	if(debug) print("cg->ibno %d...", cg->ibno);
-	if((b = diskread(fs->disk, fs->blocksize,
-		(cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize)) == nil)
+	if(debug) print("cg->ibno %lld ufs %d...", cg->ibno, fs->ufs);
+	iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize;
+	ioff = ioff%fs->inosperblock;
+	if((b = diskread(fs->disk, fs->blocksize, iaddr)) == nil)
 		return Nfs3ErrIo;
-	iaddr = (cg->ibno+ioff/fs->inosperblock)*(vlong)fs->blocksize
-		+ (ioff%fs->inosperblock)*sizeof(Inode);
-	*ino = ((Inode*)b->data)[ioff%fs->inosperblock];
+	if(fs->ufs == 2){
+		*ino = ((Inode*)b->data)[ioff];
+		lastiaddr = iaddr+ioff*sizeof(Inode);
+	}else{
+		ino1 = ((Inode1*)b->data)[ioff];
+		inode1to2(&ino1, ino);
+		lastiaddr = iaddr+ioff*sizeof(Inode1);
+	}
 	blockput(b);
-
 	return Nfs3Ok;
 }
 
@@ -717,7 +768,7 @@ ffsreaddir(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h,
 static u64int
 ffsxfileblock(Fsys *fsys, Nfs3Handle *h, u64int offset)
 {
-	u32int bno;
+	u64int bno;
 	Inode ino;
 	Nfs3Status ok;
 	Ffs *fs;
@@ -727,8 +778,8 @@ ffsxfileblock(Fsys *fsys, Nfs3Handle *h, u64int offset
 		nfs3errstr(ok);
 		return 0;
 	}
-	if(offset == 1)
-		return iaddr;
+	if(offset == 1)	/* clumsy hack for debugging */
+		return lastiaddr;
 	if(offset >= ino.size){
 		werrstr("beyond end of file");
 		return 0;
@@ -820,7 +871,7 @@ ffsreadlink(Fsys *fsys, SunAuthUnix *au, Nfs3Handle *h
 	len = ino.size;
 
 	if(ino.nblock != 0){
-		/* BUG: assumes symlink fits in one block */
+		/* assumes symlink fits in one block */
 		b = ffsfileblock(fs, &ino, 0, len);
 		if(b == nil)
 			return Nfs3ErrIo;
blob - 479ff65f71bd28b3bcf35e83edde26c111893d3a
blob + 4a90aef248a482c9355cd8ae1cc8a2d3fb0e0eda
--- src/libdiskfs/ffs.h
+++ src/libdiskfs/ffs.h
@@ -19,8 +19,10 @@
 typedef struct Cgblk Cgblk;
 typedef struct Cylgrp Cylgrp;
 typedef struct Cylsum Cylsum;
+typedef struct Cylsumtotal Cylsumtotal;
 typedef struct Ffs Ffs;
 typedef struct Fsblk Fsblk;
+typedef struct Inode1 Inode1;
 typedef struct Inode Inode;
 typedef struct Dirent Dirent;
 
@@ -30,9 +32,13 @@ enum
 
 	/* constants for Fsblk */
 	FSMAXMNTLEN = 512,
-	FSNOCSPTRS = 128 / sizeof(void*) - 3,
+	FSMAXMNTLEN2 = 468,
+	FSMAXVOLLEN = 32,				/* UFS2 */
+	FSNOCSPTRSLEN = 128-12,
+	FSNOCSPTRSLEN2 = 128-16,	/* UFS2 */
 	FSMAXSNAP = 20,
 	FSMAGIC = 0x011954,
+	FSMAGIC2 = 0x19540119,
 	FSCHECKSUM = 0x7c269d38,
 	
 	/* Fsblk.inodefmt */
@@ -45,6 +51,8 @@ enum
 
 	/* offset and size of first super block */
 	SBOFF = BBOFF+BBSIZE,
+	SBOFF2 = BBOFF+65536,			/* UFS2 */
+	SBOFFPIGGY = BBOFF+262144,		/* UFS2 */
 	SBSIZE = 8192,
 
 	/* minimum block size */
@@ -60,6 +68,7 @@ enum
 	ROOTINODE = 2,
 	WHITEOUT = 1,
 
+	NXADDR = 2,	/* UFS2 */
 	NDADDR = 12,
 	NIADDR = 3,
 
@@ -102,6 +111,17 @@ struct Cylsum
 	u32int	nffree;
 };
 
+struct Cylsumtotal
+{
+	u64int	ndir;
+	u64int	nbfree;
+	u64int	nifree;
+	u64int	nffree;
+	u64int	numclusters;
+	u64int	unused[3];
+};
+
+/* Fields beginning with underscore are deprecated in UFS2 */
 struct Fsblk
 {
 	u32int	unused0;
@@ -110,11 +130,11 @@ struct Fsblk
 	daddr_t	cfragno;		/* fragment address if cylinder block in file system */
 	daddr_t	ifragno;		/* fragment offset of inode blocks in file system */
 	daddr_t	dfragno;		/* fragment offset of data blocks in cg */
-	u32int	cgoffset;		/* block (maybe fragment?) offset of Cgblk in cylinder */
-	u32int	cgmask;
-	time_t	time;
-	u32int	nfrag;		/* number of blocks in fs * fragsperblock */
-	u32int	ndfrag;
+	u32int	_cgoffset;		/* block (maybe fragment?) offset of Cgblk in cylinder */
+	u32int	_cgmask;
+	time_t	_time;
+	u32int	_nfrag;			/* number of blocks in fs * fragsperblock */
+	u32int	_ndfrag;
 	u32int	ncg;			/* number of cylinder groups in fs */
 	u32int	blocksize;		/* block size in fs */
 	u32int	fragsize;		/* frag size in fs */
@@ -130,58 +150,73 @@ struct Fsblk
 	u32int	maxbpg;
 	u32int	fragshift;
 	u32int	fsbtodbshift;
-	u32int	sbsize;		/* size of super block */
+	u32int	sbsize;			/* size of super block */
 	u32int	unused2;		/* more stuff we don't use ... */
 	u32int	unused3;
 	u32int	nindir;
 	u32int	inosperblock;	/* inodes per block */
-	u32int	nspf;
+	u32int	_nspf;
 	u32int	optim;
-	u32int	npsect;
-	u32int	interleave;
-	u32int	trackskew;
+	u32int	_npsect;
+	u32int	_interleave;
+	u32int	_trackskew;
 	u32int	id[2];
-	daddr_t	csaddr;		/* blk addr of cyl grp summary area */
-	u32int	cssize;		/* size of cyl grp summary area */
-	u32int	cgsize;		/* cylinder group size */
-	u32int	trackspercyl;	/* tracks per cylinder */
-	u32int	secspertrack;	/* sectors per track */
-	u32int	secspercyl;	/* sectors per cylinder */
-	u32int	ncyl;			/* cylinders in fs */
-	u32int	cylspergroup;	/* cylinders per group */
+	daddr_t	_csaddr;		/* blk addr of cyl grp summary area */
+	u32int	cssize;			/* size of cyl grp summary area */
+	u32int	cgsize;			/* cylinder group size */
+	u32int	_trackspercyl;	/* tracks per cylinder */
+	u32int	_secspertrack;	/* sectors per track */
+	u32int	_secspercyl;	/* sectors per cylinder */
+	u32int	_ncyl;			/* cylinders in fs */
+	u32int	_cylspergroup;	/* cylinders per group */
 	u32int	inospergroup;	/* inodes per group */
 	u32int	fragspergroup;	/* data blocks per group * fragperblock */
-	Cylsum	cstotal;		/* more unused... */
+	Cylsum	_cstotal;		/* more unused... */
 	u8int	fmod;
 	u8int	clean;
 	u8int	ronly;
-	u8int	flags;
-	char		fsmnt[FSMAXMNTLEN];
+	u8int	_flags;
+	/* char fsmnt[512]; in UFS1 */
+		char	fsmnt[FSMAXMNTLEN2];
+		char	volname[FSMAXVOLLEN];
+		u64int	swuid;
+		u32int	pad;
 	u32int	cgrotor;
-	void*	ocsp[FSNOCSPTRS];
-	u8int*	contigdirs;
-	Cylsum*	csp;
-	u32int*	maxcluster;
-	u32int	cpc;
-	u16int	opostbl[16][8];
+	uchar	ocsp[FSNOCSPTRSLEN]; /* last 4 bytes is contigdirs in UFS2 */
+	u32int	contigdirs;		/* csp in UFS2 */
+	u32int	csp;			/* maxcluster in UFS2 */
+	u32int	maxcluster;		/* active in UFS2 */
+	u32int	_cpc;
+	/* u16int	opostbl[16][8]; in UFS1 */
+		u32int	maxbsize;
+		u64int	spare64[17];
+		u64int	sblockloc;
+		Cylsumtotal	cstotal;
+		u64int	time;
+		u64int	nfrag;
+		u64int	ndfrag;
+		u64int	csaddr;
+		u64int	pendingblocks;
+		u32int	pendinginodes;
 	u32int	snapinum[FSMAXSNAP];
 	u32int	avgfilesize;
 	u32int	avgfpdir;
-	u32int	sparecon[26];
-	u32int	pendingblocks;
-	u32int	pendinginodes;
+	/* u32int sparecon[26], pendingblocks, pendinginodes; in UFS1 */
+		u32int	savecgsize;
+		u32int	sparecon[26];
+		u32int	flags;
 	u32int	contigsumsize;
 	u32int	maxsymlinklen;
-	u32int	inodefmt;		/* format of on-disk inodes */
+	u32int	_inodefmt;		/* format of on-disk inodes */
 	u64int	maxfilesize;	/* maximum representable file size */
 	u64int	qbmask;
 	u64int	qfmask;
 	u32int	state;
-	u32int	postblformat;
-	u32int	nrpos;
-	u32int	postbloff;
-	u32int	rotbloff;
-	u32int	magic;		/* FS_MAGIC */
+	u32int	_postblformat;
+	u32int	_nrpos;
+	u32int	_postbloff;
+	u32int	_rotbloff;
+	u32int	magic;			/* FSMAGIC or FSMAGIC2 */
 };
 
 /*
@@ -190,12 +225,12 @@ struct Fsblk
 struct Cgblk
 {
 	u32int	unused0;
-	u32int	magic;		/* CGMAGIC */
+	u32int	magic;			/* CGMAGIC */
 	u32int	time;			/* time last written */
-	u32int	num;		/* we are cg #cgnum */
+	u32int	num;			/* we are cg #cgnum */
 	u16int	ncyl;			/* number of cylinders in gp */
-	u16int	nino;		/* number of inodes */
-	u32int	nfrag;		/* number of fragments  */
+	u16int	nino;			/* number of inodes */
+	u32int	nfrag;			/* number of fragments  */
 	Cylsum	csum;
 	u32int	rotor;
 	u32int	frotor;
@@ -215,16 +250,16 @@ struct Cgblk
 struct Cylgrp
 {
 	/* these are block numbers not fragment numbers */
-	u32int	bno;			/* disk block address of start of cg */
-	u32int	ibno;			/* disk block address of first inode */
-	u32int	dbno;		/* disk block address of first data */
-	u32int	cgblkno;
+	u64int	bno;			/* disk block address of start of cg */
+	u64int	ibno;			/* disk block address of first inode */
+	u64int	dbno;			/* disk block address of first data */
+	u64int	cgblkno;
 };
 
 /*
  * this is the on-disk structure
  */
-struct Inode
+struct Inode1
 {
 	u16int	mode;
 	u16int	nlink;
@@ -247,6 +282,33 @@ struct Inode
 	u32int	spare[2];
 };
 
+struct Inode
+{
+	u16int	mode;
+	u16int	nlink;
+	u32int	uid;
+	u32int	gid;
+	u32int	blksize;
+	u64int	size;
+	u64int	nblock;
+	u64int	atime;
+	u64int	mtime;
+	u64int	ctime;
+	u64int	btime;
+	u32int	atimensec;
+	u32int	mtimensec;
+	u32int	ctimensec;
+	u32int	btimensec;
+	u32int	gen;
+	u32int	kernflags;
+	u32int	flags;
+	u32int	extsize;
+	u64int	ext[NXADDR];
+	u64int	db[NDADDR];
+	u64int	ib[NIADDR];
+	u64int	spare[3];
+};
+
 struct Dirent
 {
 	u32int	ino;
@@ -261,17 +323,18 @@ struct Dirent
  */
 struct Ffs
 {
+	int		ufs;
 	int		blocksize;
-	int		nblock;
+	u64int	nblock;
 	int		fragsize;
 	int		fragsperblock;
 	int		inosperblock;
-	int		blockspergroup;
-	int		fragspergroup;
+	u64int	blockspergroup;
+	u64int	fragspergroup;
 	int		inospergroup;
 
-	u32int	nfrag;
-	u32int	ndfrag;
+	u64int	nfrag;
+	u64int	ndfrag;
 
 	int		ncg;
 	Cylgrp	*cg;
blob - 61538da1bcc56a69bc02c7aa2e81eae96c220842
blob + cade26625e3bf6d3ab7dd6c92d8b8a0162a60efd
--- src/libdiskfs/mkfile
+++ src/libdiskfs/mkfile
@@ -29,3 +29,5 @@ CFLAGS=$CFLAGS
 
 %.acid: %.$O %.c
 	$CC $CFLAGS -a $stem.c >$stem.acid
+
+ffs.$O: ffs.h