Subject: kern/17345: Apple UFS filesystem support, patches included
To: None <gnats-bugs@gnats.netbsd.org>
From: Darrin B.Jewell <dbj@netbsd.org>
List: netbsd-bugs
Date: 06/21/2002 01:52:52
>Number:         17345
>Category:       kern
>Synopsis:       Apple UFS filesystem support, patches included
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 20 20:12:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Darrin B. Jewell
>Release:        NetBSD 1.6_BETA2, cvs branch netbsd-1-6 ~20020616T2139Z
>Organization:
>Environment:
System: NetBSD quiteria 1.6_BETA2 NetBSD 1.6_BETA2 (QUITERIA) #13: Thu Jun 20 17:05:07 EDT 2002 dbj@quiteria:/usr/src/sys/arch/macppc/compile/QUITERIA macppc
Architecture: powerpc
Machine: macppc
>Description:

The included patches add support for Apple UFS filesystems to NetBSD.
This should also support NeXTstep filesystems on disks that use 512
byte sector sizes.  The primary difference is to support an alternate
value of 1024 for DIRBLKSIZ, although there are a couple of other
minor differences.  My original analsys of these differences can be
found in a post to port-macppc:
  http://mail-index.netbsd.org/port-macppc/2001/12/13/0012.html
 
The general approach is to use a run time deteriminable value
for DIRBLKSIZ.  Additional allowances are included for using
MAXSYMLINKLEN with FS_42INODEFMT and a shift in the cylinder group
cluster summary count array.  Support is added for managing
the Apple UFS volume label.

Either the apple UFS volume label or the new disklabel fstype
FS_APPLEUFS are used as hints that the filesystem is to be
treated as an Apple UFS filesystem.

These changes are enabled with the APPLE_UFS kernel option.
In combination with FFS_EI, they should work with i386 Darwin
filesystems, but this has not been extensively tested.  The
userland utilities that manage filesystems have also been updated.

PR bin/15449 is also needed for use with NeXTstep filesystems.
Additionally the next68k disklabel will need to be updated to
use FS_APPLEUFS since the apple UFS volume label is not present
on NeXTstep disks.

I have been using these changes since January without problem.
They have recently been updated in my tree to the netbsd-1-6 branch,
and minor tweaks have been performed to ready them for general
submission.  I plan to pursue discussion of this PR on tech-kern.
and will merge them to the cvs trunk and commit upon approval.

I also recommend that we import the pdisk utility.  This is
the same utility as MacOS X ships. The current version can
be found at
  http://cantaforda.com/cfcl/eryk/linux/pdisk
it ports trivially to NetBSD and has an MIT style license.

Darrin

>How-To-Repeat:

>Fix:

cvs -f -d cvs.netbsd.org:/cvsroot diff -uN
Index: sbin/disklabel/disklabel.5
===================================================================
RCS file: /cvsroot/basesrc/sbin/disklabel/disklabel.5,v
retrieving revision 1.15
diff -u -r1.15 disklabel.5
--- sbin/disklabel/disklabel.5	2002/02/08 01:30:43	1.15
+++ sbin/disklabel/disklabel.5	2002/06/20 22:40:03
@@ -307,6 +307,7 @@
 #define	FS_NTFS		18	/* Windows/NT file system */
 #define	FS_RAID		19	/* RAIDframe component */
 #define	FS_CCD		20	/* concatenated disk component */
+#define	FS_APPLEUFS	21	/* Apple UFS */
 
 #ifdef	FSTYPENAMES
 static const char *const fstypenames[] = {
@@ -331,6 +332,7 @@
 	"NTFS",
 	"RAID",
 	"ccd",
+	"Apple UFS",
 	NULL
 };
 #define FSMAXTYPES	(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
Index: sbin/disklabel/disklabel.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/disklabel/disklabel.c,v
retrieving revision 1.104
diff -u -r1.104 disklabel.c
--- sbin/disklabel/disklabel.c	2002/05/14 21:27:05	1.104
+++ sbin/disklabel/disklabel.c	2002/06/20 22:40:03
@@ -1151,6 +1151,7 @@
 			case FS_BSDLFS:
 			case FS_EX2FS:
 			case FS_ADOS:
+			case FS_APPLEUFS:
 				(void) fprintf(f, "b%c#%d:", c,
 				    pp->p_fsize * pp->p_frag);
 				(void) fprintf(f, "f%c#%d:", c, pp->p_fsize);
@@ -1603,6 +1604,7 @@
 
 			case FS_BSDFFS:
 			case FS_ADOS:
+			case FS_APPLEUFS:
 				NXTNUM(pp->p_fsize);
 				if (pp->p_fsize == 0)
 					break;
Index: sbin/disklabel/printlabel.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/disklabel/printlabel.c,v
retrieving revision 1.3
diff -u -r1.3 printlabel.c
--- sbin/disklabel/printlabel.c	2001/10/19 01:16:38	1.3
+++ sbin/disklabel/printlabel.c	2002/06/20 22:40:03
@@ -140,6 +140,7 @@
 
 	case FS_BSDFFS:
 	case FS_ADOS:
+	case FS_APPLEUFS:
 		(void)fprintf(f, "  %5d %5d %5d ",
 		    pp->p_fsize, pp->p_fsize * pp->p_frag, pp->p_cpg);
 		break;
Index: sbin/fdisk/fdisk.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fdisk/fdisk.c,v
retrieving revision 1.52
diff -u -r1.52 fdisk.c
--- sbin/fdisk/fdisk.c	2002/04/03 03:17:36	1.52
+++ sbin/fdisk/fdisk.c	2002/06/20 22:40:04
@@ -232,6 +232,7 @@
 	{0xa8, "Apple UFS"},
 	{0xa9, "NetBSD"},
 	{0xab, "Apple Boot"},
+	{0xaf, "Apple HFS"},
 	{0xb1, reserved},
 	{0xb3, reserved},
 	{0xb4, reserved},
Index: sbin/fsck_ffs/Makefile
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/Makefile,v
retrieving revision 1.22
diff -u -r1.22 Makefile
--- sbin/fsck_ffs/Makefile	1999/01/15 13:32:06	1.22
+++ sbin/fsck_ffs/Makefile	2002/06/20 22:40:04
@@ -4,7 +4,8 @@
 PROG=	fsck_ffs
 MAN=	fsck_ffs.8
 SRCS=	dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
-	pass5.c fsutil.c setup.c utilities.c ffs_bswap.c ffs_subr.c ffs_tables.c
+	pass5.c fsutil.c setup.c utilities.c ffs_bswap.c ffs_subr.c \
+	ffs_tables.c ffs_appleufs.c
 FSCK=	${.CURDIR}/../fsck
 CPPFLAGS+=-I${FSCK}
 .PATH:	${.CURDIR}/../../sys/ufs/ffs ${FSCK}
Index: sbin/fsck_ffs/dir.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/dir.c,v
retrieving revision 1.33
diff -u -r1.33 dir.c
--- sbin/fsck_ffs/dir.c	2002/05/09 02:55:50	1.33
+++ sbin/fsck_ffs/dir.c	2002/06/20 22:40:04
@@ -145,13 +145,17 @@
 	struct bufarea *bp;
 	int dsize, n;
 	long blksiz;
+#if DIRBLKSIZ > APPLEUFS_DIRBLKSIZ
 	char dbuf[DIRBLKSIZ];
+#else
+	char dbuf[APPLEUFS_DIRBLKSIZ];
+#endif
 
 	if (idesc->id_type != DATA)
 		errx(EEXIT, "wrong type to dirscan %d", idesc->id_type);
 	if (idesc->id_entryno == 0 &&
-	    (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0)
-		idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ);
+	    (idesc->id_filesize & (dirblksiz - 1)) != 0)
+		idesc->id_filesize = roundup(idesc->id_filesize, dirblksiz);
 	blksiz = idesc->id_numfrags * sblock->fs_fsize;
 	if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
 		idesc->id_filesize -= blksiz;
@@ -238,7 +242,7 @@
 
 	blksiz = idesc->id_numfrags * sblock->fs_fsize;
 	bp = getdirblk(idesc->id_blkno, blksiz);
-	if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
+	if (idesc->id_loc % dirblksiz == 0 && idesc->id_filesize > 0 &&
 	    idesc->id_loc < blksiz) {
 		dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
 		if (dircheck(idesc, dp))
@@ -248,7 +252,7 @@
 		fix = dofix(idesc, "DIRECTORY CORRUPTED");
 		bp = getdirblk(idesc->id_blkno, blksiz);
 		dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
-		dp->d_reclen = iswap16(DIRBLKSIZ);
+		dp->d_reclen = iswap16(dirblksiz);
 		dp->d_ino = 0;
 		dp->d_type = 0;
 		dp->d_namlen = 0;
@@ -257,8 +261,8 @@
 			dirty(bp);
 		else 
 			markclean=  0;
-		idesc->id_loc += DIRBLKSIZ;
-		idesc->id_filesize -= DIRBLKSIZ;
+		idesc->id_loc += dirblksiz;
+		idesc->id_filesize -= dirblksiz;
 		return (dp);
 	}
 dpok:
@@ -268,12 +272,12 @@
 	dp = (struct direct *)(bp->b_un.b_buf + dploc);
 	idesc->id_loc += iswap16(dp->d_reclen);
 	idesc->id_filesize -= iswap16(dp->d_reclen);
-	if ((idesc->id_loc % DIRBLKSIZ) == 0)
+	if ((idesc->id_loc % dirblksiz) == 0)
 		return (dp);
 	ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
 	if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
 	    dircheck(idesc, ndp) == 0) {
-		size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
+		size = dirblksiz - (idesc->id_loc % dirblksiz);
 		idesc->id_loc += size;
 		idesc->id_filesize -= size;
 		if (idesc->id_fix == IGNORE)
@@ -304,11 +308,11 @@
 	u_char namlen, type;
 	int spaceleft;
 
-	spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
+	spaceleft = dirblksiz - (idesc->id_loc % dirblksiz);
 	if (iswap32(dp->d_ino) >= maxino ||
 	    dp->d_reclen == 0 ||
 	    iswap16(dp->d_reclen) > spaceleft ||
-	    (iswap16(dp->d_reclen) & 0x3) != 0)
+	    (iswap16(dp->d_reclen) & 0x3) != 0) 
 		return (0);
 	if (dp->d_ino == 0)
 		return (1);
@@ -629,8 +633,8 @@
 	idesc.id_fix = DONTKNOW;
 	idesc.id_name = name;
 	dp = ginode(parent);
-	if (iswap64(dp->di_size) % DIRBLKSIZ) {
-		dp->di_size = iswap64(roundup(iswap64(dp->di_size), DIRBLKSIZ));
+	if (iswap64(dp->di_size) % dirblksiz) {
+		dp->di_size = iswap64(roundup(iswap64(dp->di_size), dirblksiz));
 		inodirty();
 	}
 	if ((ckinode(dp, &idesc) & ALTERED) != 0)
@@ -652,7 +656,12 @@
 {
 	ufs_daddr_t lastbn, newblk;
 	struct bufarea *bp;
-	char *cp, firstblk[DIRBLKSIZ];
+	char *cp;
+#if DIRBLKSIZ > APPLEUFS_DIRBLKSIZ
+	char firstblk[DIRBLKSIZ];
+#else
+	char firstblk[APPLEUFS_DIRBLKSIZ];
+#endif
 
 	lastbn = lblkno(sblock, iswap64(dp->di_size));
 	if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
@@ -667,15 +676,15 @@
 		(long)dblksize(sblock, dp, lastbn + 1));
 	if (bp->b_errs)
 		goto bad;
-	memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
+	memmove(firstblk, bp->b_un.b_buf, dirblksiz);
 	bp = getdirblk(newblk, sblock->fs_bsize);
 	if (bp->b_errs)
 		goto bad;
-	memmove(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
-	emptydir.dot_reclen = iswap16(DIRBLKSIZ);
-	for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
+	memmove(bp->b_un.b_buf, firstblk, dirblksiz);
+	emptydir.dot_reclen = iswap16(dirblksiz);
+	for (cp = &bp->b_un.b_buf[dirblksiz];
 	     cp < &bp->b_un.b_buf[sblock->fs_bsize];
-	     cp += DIRBLKSIZ)
+	     cp += dirblksiz)
 		memmove(cp, &emptydir, sizeof emptydir);
 	dirty(bp);
 	bp = getdirblk(iswap32(dp->di_db[lastbn + 1]),
@@ -717,9 +726,9 @@
 
 	ino = allocino(request, IFDIR|mode);
 	dirhead.dot_reclen = iswap16(12);
-	dirhead.dotdot_reclen = iswap16(DIRBLKSIZ - 12);
+	dirhead.dotdot_reclen = iswap16(dirblksiz - 12);
 	odirhead.dot_reclen = iswap16(12);
-	odirhead.dotdot_reclen = iswap16(DIRBLKSIZ - 12);
+	odirhead.dotdot_reclen = iswap16(dirblksiz - 12);
 	odirhead.dot_namlen = iswap16(1);
 	odirhead.dotdot_namlen = iswap16(2);
 	if (newinofmt)
@@ -735,10 +744,10 @@
 		return (0);
 	}
 	memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate));
-	emptydir.dot_reclen = iswap16(DIRBLKSIZ);
-	for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
+	emptydir.dot_reclen = iswap16(dirblksiz);
+	for (cp = &bp->b_un.b_buf[dirblksiz];
 	     cp < &bp->b_un.b_buf[sblock->fs_fsize];
-	     cp += DIRBLKSIZ)
+	     cp += dirblksiz)
 		memmove(cp, &emptydir, sizeof emptydir);
 	dirty(bp);
 	dp->di_nlink = iswap16(2);
Index: sbin/fsck_ffs/fsck.h
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/fsck.h,v
retrieving revision 1.28
diff -u -r1.28 fsck.h
--- sbin/fsck_ffs/fsck.h	2002/05/06 03:17:43	1.28
+++ sbin/fsck_ffs/fsck.h	2002/06/20 22:40:04
@@ -70,6 +70,7 @@
 		ufs_daddr_t *b_indir;		/* indirect block */
 		struct fs *b_fs;		/* super block */
 		struct cg *b_cg;		/* cylinder group */
+		struct appleufslabel *b_appleufs;		/* Apple UFS volume label */
 	} b_un;
 	char b_dirty;
 };
@@ -81,6 +82,7 @@
 struct bufarea sblk;		/* file system superblock */
 struct bufarea asblk;		/* file system superblock */
 struct bufarea cgblk;		/* cylinder group blocks */
+struct bufarea appleufsblk;		/* Apple UFS volume label */
 struct bufarea *pdirbp;		/* current directory contents */
 struct bufarea *pbp;		/* current inode block */
 
@@ -102,6 +104,14 @@
 	} while (0)
 #define	cgdirty()	do {copyback_cg(&cgblk); cgblk.b_dirty = 1;} while (0)
 
+#define appleufsdirty() \
+	do { \
+		appleufsblk.b_un.b_appleufs->ul_checksum = 0; \
+		appleufsblk.b_un.b_appleufs->ul_checksum =  \
+			ffs_appleufs_cksum(appleufsblk.b_un.b_appleufs); \
+		appleufsblk.b_dirty = 1; \
+	} while (0)
+
 enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
 
 struct inodesc {
@@ -201,6 +211,7 @@
 int	fswritefd;		/* file descriptor for writing file system */
 int	rerun;			/* rerun fsck.  Only used in non-preen mode */
 char	resolved;		/* cleared if unresolved changes => not clean */
+int isappleufs;		/* filesystem is Apple UFS */
 
 ufs_daddr_t maxfsblock;		/* number of blocks in the file system */
 char	*blockmap;		/* ptr to primary blk allocation map */
@@ -210,6 +221,8 @@
 u_char	*typemap;		/* ptr to inode type table */
 int16_t	*lncntp;		/* ptr to link count table */
 
+int	dirblksiz;
+
 extern ino_t	lfdir;		/* lost & found directory inode number */
 extern char	*lfname;	/* lost & found directory name */
 extern int	lfmode;		/* lost & found directory creation mode */
@@ -262,3 +275,5 @@
 		return bswap64(x);
 	else return x;
 }
+
+
Index: sbin/fsck_ffs/fsck_ffs.8
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/fsck_ffs.8,v
retrieving revision 1.29
diff -u -r1.29 fsck_ffs.8
--- sbin/fsck_ffs/fsck_ffs.8	2002/05/06 03:17:43	1.29
+++ sbin/fsck_ffs/fsck_ffs.8	2002/06/20 22:40:04
@@ -145,6 +145,9 @@
 The following flags are interpreted by
 .Nm "" .
 .Bl -tag -width indent
+.It Fl a
+Interpret the filesystem as an Apple UFS filesystem, even if
+there is no Apple UFS volume label present.
 .It Fl B
 Convert the file system metadata to the specified byte order if needed.
 Valid byte order are `be' and `le'. If
Index: sbin/fsck_ffs/inode.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/inode.c,v
retrieving revision 1.34
diff -u -r1.34 inode.c
--- sbin/fsck_ffs/inode.c	2001/01/05 02:02:57	1.34
+++ sbin/fsck_ffs/inode.c	2002/06/20 22:40:04
@@ -88,6 +88,7 @@
 	mode = iswap16(dp->di_mode) & IFMT;
 	if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
 	    (idesc->id_filesize < sblock->fs_maxsymlinklen ||
+	    (isappleufs && (idesc->id_filesize < APPLEUFS_MAXSYMLINKLEN)) ||
 	     (sblock->fs_maxsymlinklen == 0 && dp->di_blocks == 0))))
 		return (KEEPON);
 	dino = *dp;
@@ -351,6 +352,7 @@
 				ffs_dinode_swap(dp, dp);
 				/* ffs_dinode_swap() doesn't swap blocks addrs */
 				if ((iswap16(dp->di_mode) & IFMT) != IFLNK ||
+					(isappleufs && (iswap64(dp->di_size) > APPLEUFS_MAXSYMLINKLEN)) ||
 					iswap64(dp->di_size) > sblock->fs_maxsymlinklen) {
 					for (j=0; j<NDADDR + NIADDR; j++)
 						dp->di_db[j] = bswap32(dp->di_db[j]);
Index: sbin/fsck_ffs/main.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/main.c,v
retrieving revision 1.41
diff -u -r1.41 main.c
--- sbin/fsck_ffs/main.c	2002/05/06 03:17:43	1.41
+++ sbin/fsck_ffs/main.c	2002/06/20 22:40:04
@@ -97,7 +97,8 @@
 	markclean = 1;
 	forceimage = 0;
 	endian = 0;
-	while ((ch = getopt(argc, argv, "B:b:c:dFfm:npy")) != -1) {
+	isappleufs = 0;
+	while ((ch = getopt(argc, argv, "B:b:c:dFfm:npya")) != -1) {
 		switch (ch) {
 		case 'B':
 			if (strcmp(optarg, "be") == 0)
@@ -149,6 +150,10 @@
 		case 'y':
 			yflag++;
 			nflag = 0;
+			break;
+
+		case 'a':
+			isappleufs = 1;
 			break;
 
 		default:
Index: sbin/fsck_ffs/pass1.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/pass1.c,v
retrieving revision 1.24
diff -u -r1.24 pass1.c
--- sbin/fsck_ffs/pass1.c	2002/05/06 03:17:43	1.24
+++ sbin/fsck_ffs/pass1.c	2002/06/20 22:40:04
@@ -199,6 +199,7 @@
 		 * will detect any garbage after symlink string.
 		 */
 		if (size < sblock->fs_maxsymlinklen ||
+		    (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) ||
 		    (sblock->fs_maxsymlinklen == 0 && dp->di_blocks == 0)) {
 			ndb = howmany(size, sizeof(daddr_t));
 			if (ndb > NDADDR) {
Index: sbin/fsck_ffs/pass2.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/pass2.c,v
retrieving revision 1.31
diff -u -r1.31 pass2.c
--- sbin/fsck_ffs/pass2.c	2002/05/06 19:37:51	1.31
+++ sbin/fsck_ffs/pass2.c	2002/06/20 22:40:04
@@ -154,26 +154,26 @@
 			continue;
 		if (inp->i_isize < MINDIRSIZE) {
 			direrror(inp->i_number, "DIRECTORY TOO SHORT");
-			inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);
+			inp->i_isize = roundup(MINDIRSIZE, dirblksiz);
 			if (reply("FIX") == 1) {
 				dp = ginode(inp->i_number);
 				dp->di_size = iswap64(inp->i_isize);
 				inodirty();
 			} else
 				markclean = 0;
-		} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
+		} else if ((inp->i_isize & (dirblksiz - 1)) != 0) {
 			getpathname(pathbuf, inp->i_number, inp->i_number);
 			if (usedsoftdep)
 				pfatal("%s %s: LENGTH %lld NOT MULTIPLE OF %d",
 					"DIRECTORY", pathbuf,
-					(long long)inp->i_isize, DIRBLKSIZ);
+					(long long)inp->i_isize, dirblksiz);
 			else
 				pwarn("%s %s: LENGTH %lld NOT MULTIPLE OF %d",
 					"DIRECTORY", pathbuf,
-					(long long)inp->i_isize, DIRBLKSIZ);
+					(long long)inp->i_isize, dirblksiz);
 			if (preen)
 				printf(" (ADJUSTED)\n");
-			inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
+			inp->i_isize = roundup(inp->i_isize, dirblksiz);
 			if (preen || reply("ADJUST") == 1) {
 				dp = ginode(inp->i_number);
 				dp->di_size = iswap64(inp->i_isize);
Index: sbin/fsck_ffs/pass5.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/pass5.c,v
retrieving revision 1.29
diff -u -r1.29 pass5.c
--- sbin/fsck_ffs/pass5.c	2002/05/06 03:17:43	1.29
+++ sbin/fsck_ffs/pass5.c	2002/06/20 22:40:05
@@ -155,6 +155,13 @@
 		if (fs->fs_contigsumsize > 0) {
 			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
 			    sizeof(int32_t);
+			if (isappleufs) {
+				/* Apple PR2216969 gives rationale for this change.
+				 * I believe they were mistaken, but we need to
+				 * duplicate it for compatibility.  -- dbj@netbsd.org
+				 */
+				newcg->cg_clustersumoff += sizeof(int32_t);
+			}
 			newcg->cg_clustersumoff =
 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
 			newcg->cg_clusteroff = newcg->cg_clustersumoff +
Index: sbin/fsck_ffs/setup.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/setup.c,v
retrieving revision 1.52
diff -u -r1.52 setup.c
--- sbin/fsck_ffs/setup.c	2001/12/19 10:05:20	1.52
+++ sbin/fsck_ffs/setup.c	2002/06/20 22:40:05
@@ -51,6 +51,7 @@
 #include <sys/file.h>
 
 #include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
 #include <ufs/ufs/ufs_bswap.h>
 #include <ufs/ffs/fs.h>
 #include <ufs/ffs/ffs_extern.h>
@@ -71,7 +72,9 @@
 static void badsb __P((int, char *));
 static int calcsb __P((const char *, int, struct fs *));
 static struct disklabel *getdisklabel __P((const char *, int));
+static struct partition *getdisklabelpart __P((const char *, struct disklabel *));
 static int readsb __P((int));
+static int readappleufs __P((void));
 
 /*
  * Read in a superblock finding an alternate if necessary.
@@ -431,6 +434,26 @@
 		usedsoftdep = 1;
 	else
 		usedsoftdep = 0;
+
+	{
+		struct partition *pp = 0;
+		if (!forceimage) 
+			pp = getdisklabelpart(dev,lp);
+		if (pp && (pp->p_fstype == FS_APPLEUFS)) {
+			isappleufs = 1;
+		}
+	}
+	if (readappleufs()) {
+		isappleufs = 1;
+	}
+
+	dirblksiz = DIRBLKSIZ;
+	if (isappleufs)
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+
+	if (debug)
+		printf("isappleufs = %d, dirblksiz = %d\n", isappleufs, dirblksiz);
+
 	return (1);
 
 badsblabel:
@@ -439,6 +462,107 @@
 	return (0);
 }
 
+static int
+readappleufs()
+{
+	ufs_daddr_t label = APPLEUFS_LABEL_OFFSET / dev_bsize;
+	struct appleufslabel *appleufs;
+	int i;
+
+	/* @@@ deal with APPLEUFS_LABEL_OFFSET not being block aligned (CD's?) */
+	/* @@@ also, we should use getblk here instead of bread */
+	if (bread(fsreadfd, (char *)appleufsblk.b_un.b_fs, label, (long)APPLEUFS_LABEL_SIZE) != 0)
+		return 0;
+	appleufsblk.b_bno = label;
+	appleufsblk.b_size = APPLEUFS_LABEL_SIZE;
+
+	appleufs = appleufsblk.b_un.b_appleufs;
+
+	if (ntohl(appleufs->ul_magic) != APPLEUFS_LABEL_MAGIC) {
+		if (!isappleufs) {
+			return 0;
+		} else {
+			pfatal("MISSING APPLEUFS VOLUME LABEL\n");
+			if (reply("FIX") == 0) {
+				return 1;
+			}
+			ffs_appleufs_set(appleufs,NULL,-1);
+			appleufsdirty();
+		}
+	}
+
+	if (ntohl(appleufs->ul_version) != APPLEUFS_LABEL_VERSION) {
+		pwarn("INCORRECT APPLE UFS VERSION NUMBER (%d should be %d)",
+			ntohl(appleufs->ul_version),APPLEUFS_LABEL_VERSION);
+		if (preen) {
+			printf(" (CORRECTED)\n");
+		}
+		if (preen || reply("CORRECT")) {
+			appleufs->ul_version = htonl(APPLEUFS_LABEL_VERSION);
+			appleufsdirty();
+		}
+	}
+
+	if (ntohs(appleufs->ul_namelen) > APPLEUFS_MAX_LABEL_NAME) {
+		pwarn("APPLE UFS LABEL NAME TOO LONG");
+		if (preen) {
+			printf(" (TRUNCATED)\n");
+		}
+		if (preen || reply("TRUNCATE")) {
+			appleufs->ul_namelen = htons(APPLEUFS_MAX_LABEL_NAME);
+			appleufsdirty();
+		}
+	}
+
+	if (ntohs(appleufs->ul_namelen) == 0) {
+		pwarn("MISSING APPLE UFS LABEL NAME");
+		if (preen) {
+			printf(" (FIXED)\n");
+		}
+		if (preen || reply("FIX")) {
+			ffs_appleufs_set(appleufs,NULL,-1);
+			appleufsdirty();
+		}
+	}
+
+	/* Scan name for first illegal character */
+	for (i=0;i<ntohs(appleufs->ul_namelen);i++) {
+		if ((appleufs->ul_name[i] == '\0') ||
+			(appleufs->ul_name[i] == ':') ||
+			(appleufs->ul_name[i] == '/')) {
+			pwarn("APPLE UFS LABEL NAME CONTAINS ILLEGAL CHARACTER");
+			if (preen) {
+				printf(" (TRUNCATED)\n");
+			}
+			if (preen || reply("TRUNCATE")) {
+				appleufs->ul_namelen = i+1;
+				appleufsdirty();
+			}
+			break;
+		}
+	}
+
+	/* Check the checksum last, because if anything else was wrong,
+	 * then the checksum gets reset anyway.
+	 */
+	appleufs->ul_checksum = 0;
+	appleufs->ul_checksum = ffs_appleufs_cksum(appleufs);
+	if (appleufsblk.b_un.b_appleufs->ul_checksum != appleufs->ul_checksum) {
+		pwarn("INVALID APPLE UFS CHECKSUM (%#04x should be %#04x)",
+			appleufsblk.b_un.b_appleufs->ul_checksum, appleufs->ul_checksum);
+		if (preen) {
+			printf(" (CORRECTED)\n");
+		}
+		if (preen || reply("CORRECT")) {
+			appleufsdirty();
+		} else {
+			/* put the incorrect checksum back in place */
+			appleufs->ul_checksum = appleufsblk.b_un.b_appleufs->ul_checksum;
+		}
+	}
+	return 1;
+}
+
 /*
  * Read in the super block and its summary info.
  */
@@ -652,20 +776,15 @@
 {
 	struct disklabel *lp;
 	struct partition *pp;
-	char *cp;
 	int i;
 
-	cp = strchr(dev, '\0') - 1;
-	if ((cp == (char *)-1 || (*cp < 'a' || *cp > 'p')) && !isdigit(*cp)) {
+	lp = getdisklabel(dev, devfd);
+	pp = getdisklabelpart(dev,lp);
+	if (pp == 0) {
 		pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
 		return (0);
 	}
-	lp = getdisklabel(dev, devfd);
-	if (isdigit(*cp))
-		pp = &lp->d_partitions[0];
-	else
-		pp = &lp->d_partitions[*cp - 'a'];
-	if (pp->p_fstype != FS_BSDFFS) {
+	if ((pp->p_fstype != FS_BSDFFS) && (pp->p_fstype != FS_APPLEUFS)) {
 		pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n",
 			dev, pp->p_fstype < FSMAXTYPES ?
 			fstypenames[pp->p_fstype] : "unknown");
@@ -716,3 +835,21 @@
 	}
 	return (&lab);
 }
+
+static struct partition *
+getdisklabelpart(dev, lp)
+	const char *dev;
+	struct disklabel *lp;
+{
+	char *cp;
+
+	cp = strchr(dev, '\0') - 1;
+	if ((cp == (char *)-1 || (*cp < 'a' || *cp > 'p')) && !isdigit(*cp)) {
+		return 0;
+	}
+	if (isdigit(*cp))
+		return &lp->d_partitions[0];
+	else
+		return &lp->d_partitions[*cp - 'a'];
+}
+  
Index: sbin/fsck_ffs/utilities.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsck_ffs/utilities.c,v
retrieving revision 1.33
diff -u -r1.33 utilities.c
--- sbin/fsck_ffs/utilities.c	2002/05/06 03:17:43	1.33
+++ sbin/fsck_ffs/utilities.c	2002/06/20 22:40:05
@@ -144,6 +144,11 @@
 		errx(EEXIT, "cannot allocate buffer pool");
 	cgblk.b_un.b_buf = bufp;
 	initbarea(&cgblk);
+	bufp = malloc((unsigned int)APPLEUFS_LABEL_SIZE);
+	if (bufp == 0)
+		errx(EEXIT, "cannot allocate buffer pool");
+	appleufsblk.b_un.b_buf = bufp;
+	initbarea(&appleufsblk);
 	bufhead.b_next = bufhead.b_prev = &bufhead;
 	bufcnt = MAXBUFSPACE / sblock->fs_bsize;
 	if (bufcnt < MINBUFS)
@@ -279,6 +284,8 @@
 		sbdirty();
 		flush(fswritefd, &sblk);
 	}
+	flush(fswritefd, &appleufsblk);
+	free(appleufsblk.b_un.b_buf);
 	flush(fswritefd, &cgblk);
 	free(cgblk.b_un.b_buf);
 	for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
Index: sbin/fsdb/Makefile
===================================================================
RCS file: /cvsroot/basesrc/sbin/fsdb/Makefile,v
retrieving revision 1.12
diff -u -r1.12 Makefile
--- sbin/fsdb/Makefile	1999/01/15 13:32:06	1.12
+++ sbin/fsdb/Makefile	2002/06/20 22:40:05
@@ -6,7 +6,7 @@
 SRCS=	fsdb.c fsdbutil.c
 SRCS+=	dir.c inode.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
 	pass5.c setup.c utilities.c
-SRCS+=	ffs_bswap.c ffs_subr.c ffs_tables.c
+SRCS+=	ffs_bswap.c ffs_subr.c ffs_tables.c ffs_appleufs.c
 SRCS+=	fsutil.c 
 
 FSCK=	${.CURDIR}/../fsck
Index: sbin/mbrlabel/mbrlabel.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/mbrlabel/mbrlabel.c,v
retrieving revision 1.20
diff -u -r1.20 mbrlabel.c
--- sbin/mbrlabel/mbrlabel.c	2002/05/21 01:39:56	1.20
+++ sbin/mbrlabel/mbrlabel.c	2002/06/20 22:40:05
@@ -106,6 +106,7 @@
 	{ MBR_PTYPE_LNXSWAP,	FS_SWAP },
 	{ MBR_PTYPE_NETBSD,	FS_BSDFFS },
 	{ MBR_PTYPE_NTFS,	FS_NTFS },
+	{ MBR_PTYPE_APPLEUFS,	FS_APPLEUFS },
 	{ 0, 0 }
 };
 
@@ -223,6 +224,7 @@
 			    fstypenames[npe.p_fstype], unused + 'a');
 		switch (npe.p_fstype) {
 		case FS_BSDFFS:
+		case FS_APPLEUFS:
 			npe.p_size = 16384;	/* XXX */
 			npe.p_fsize = 1024;
 			npe.p_frag = 8;
Index: sbin/newfs/Makefile
===================================================================
RCS file: /cvsroot/basesrc/sbin/newfs/Makefile,v
retrieving revision 1.22
diff -u -r1.22 Makefile
--- sbin/newfs/Makefile	2002/01/08 20:54:49	1.22
+++ sbin/newfs/Makefile	2002/06/20 22:40:05
@@ -2,7 +2,7 @@
 #	@(#)Makefile	8.2 (Berkeley) 3/27/94
 
 PROG=	newfs
-SRCS=	dkcksum.c getmntopts.c newfs.c mkfs.c ffs_bswap.c
+SRCS=	dkcksum.c getmntopts.c newfs.c mkfs.c ffs_bswap.c ffs_appleufs.c
 MAN=	newfs.8 mount_mfs.8
 
 WARNS=	2
Index: sbin/newfs/extern.h
===================================================================
RCS file: /cvsroot/basesrc/sbin/newfs/extern.h,v
retrieving revision 1.7
diff -u -r1.7 extern.h
--- sbin/newfs/extern.h	2002/01/07 12:00:09	1.7
+++ sbin/newfs/extern.h	2002/06/20 22:40:05
@@ -63,3 +63,5 @@
 extern u_long	memleft;	/* virtual memory available */
 extern caddr_t	membase;	/* start address of memory based filesystem */
 extern int	needswap;	/* Filesystem not in native byte order */
+extern int	isappleufs; /* Filesystem is Apple UFS */
+extern char	*appleufs_volname;	/* Apple UFS volume name */
Index: sbin/newfs/mkfs.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/newfs/mkfs.c,v
retrieving revision 1.64
diff -u -r1.64 mkfs.c
--- sbin/newfs/mkfs.c	2002/04/10 17:28:13	1.64
+++ sbin/newfs/mkfs.c	2002/06/20 22:40:05
@@ -164,6 +164,12 @@
 		printf("preposterous size %d\n", fssize), exit(13);
 	wtfs(fssize - 1, sectorsize, (char *)&sblock);
 
+	if (isappleufs) {
+		struct appleufslabel appleufs;
+		ffs_appleufs_set(&appleufs,appleufs_volname,utime);
+		wtfs(APPLEUFS_LABEL_OFFSET/sectorsize,APPLEUFS_LABEL_SIZE,&appleufs);
+	}
+
 	/*
 	 * collect and verify the sector and track info
 	 */
@@ -658,7 +664,10 @@
 	 * Update information about this partion in pack
 	 * label, to that it may be updated on disk.
 	 */
-	pp->p_fstype = FS_BSDFFS;
+	if (isappleufs)
+		pp->p_fstype = FS_APPLEUFS;
+	else
+		pp->p_fstype = FS_BSDFFS;
 	pp->p_fsize = sblock.fs_fsize;
 	pp->p_frag = sblock.fs_frag;
 	pp->p_cpg = sblock.fs_cpg;
@@ -712,6 +721,13 @@
 	} else {
 		acg.cg_clustersumoff = acg.cg_freeoff +
 		    howmany(sblock.fs_fpg, NBBY) - sizeof(int32_t);
+		if (isappleufs) {
+			/* Apple PR2216969 gives rationale for this change.
+			 * I believe they were mistaken, but we need to
+			 * duplicate it for compatibility.  -- dbj@netbsd.org
+			 */
+			acg.cg_clustersumoff += sizeof(int32_t);
+		}
 		acg.cg_clustersumoff =
 		    roundup(acg.cg_clustersumoff, sizeof(int32_t));
 		acg.cg_clusteroff = acg.cg_clustersumoff +
@@ -868,6 +884,9 @@
 {
 #ifdef LOSTDIR
 	int i;
+	int dirblksiz = DIRBLKSIZ;
+	if (isappleufs)
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
 #endif
 
 	/*
@@ -884,12 +903,12 @@
 	 */
 	if (Oflag) {
 		(void)makedir((struct direct *)olost_found_dir, 2);
-		for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
+		for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz)
 			copy_dir((struct direct*)&olost_found_dir[2],
 				(struct direct*)&buf[i]);
 	} else {
 		(void)makedir(lost_found_dir, 2);
-		for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
+		for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz)
 			copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]);
 	}
 	node.di_mode = IFDIR | UMASK;
@@ -937,8 +956,11 @@
 {
 	char *cp;
 	int i, spcleft;
+	int dirblksiz = DIRBLKSIZ;
+	if (isappleufs)
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
 
-	spcleft = DIRBLKSIZ;
+	spcleft = dirblksiz;
 	for (cp = buf, i = 0; i < entries - 1; i++) {
 		protodir[i].d_reclen = DIRSIZ(Oflag, &protodir[i], 0);
 		copy_dir(&protodir[i], (struct direct*)cp);
@@ -947,7 +969,7 @@
 	}
 	protodir[i].d_reclen = spcleft;
 	copy_dir(&protodir[i], (struct direct*)cp);
-	return (DIRBLKSIZ);
+	return (dirblksiz);
 }
 
 /*
Index: sbin/newfs/newfs.8
===================================================================
RCS file: /cvsroot/basesrc/sbin/newfs/newfs.8,v
retrieving revision 1.42
diff -u -r1.42 newfs.8
--- sbin/newfs/newfs.8	2002/04/06 05:57:17	1.42
+++ sbin/newfs/newfs.8	2002/06/20 22:40:05
@@ -64,6 +64,7 @@
 .Op Fl s Ar size
 .Op Fl t Ar ntracks
 .Op Fl u Ar nsectors
+.Op Fl v Ar volname
 .Op Fl x Ar sectors
 .Ar special
 .Sh DESCRIPTION
@@ -108,7 +109,9 @@
 No attempts to use or update the disk label will be made.
 .It Fl I
 Do not require that the file system type listed in the disk label is
-.Ql 4.2BSD .
+.Ql 4.2BSD
+or
+.Ql Apple UFS .
 .It Fl N
 Causes the file system parameters to be printed out
 without really creating the file system.
@@ -254,6 +257,9 @@
 sector size (as specified by
 .Fl S Ar secsize )
 after suffix interpretation.
+.It Fl v Ar volname
+This specifies that a Apple UFS filesystem should be created
+with the given volume name.
 .El
 .Pp
 The following options override the standard sizes for the disk geometry.
@@ -330,7 +336,9 @@
 command to succeed,
 the disk label should first be updated such that the fstype field for the
 partition is set to
-.Ql 4.2BSD ,
+.Ql 4.2BSD
+or
+.Ql Apple UFS ,
 unless
 .Fl F
 or
Index: sbin/newfs/newfs.c
===================================================================
RCS file: /cvsroot/basesrc/sbin/newfs/newfs.c,v
retrieving revision 1.58
diff -u -r1.58 newfs.c
--- sbin/newfs/newfs.c	2002/02/20 04:04:39	1.58
+++ sbin/newfs/newfs.c	2002/06/20 22:40:06
@@ -205,6 +205,8 @@
 char	*disktype;
 int	unlabeled;
 #endif
+char *appleufs_volname = 0; /* Apple UFS volume name */
+int isappleufs = 0;
 
 char	device[MAXPATHLEN];
 
@@ -248,7 +250,7 @@
 
 	opstring = mfs ?
 	    "NT:a:b:c:d:e:f:g:h:i:m:o:p:s:u:" :
-	    "B:FINOS:T:Za:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:x:";
+	    "B:FINOS:T:Za:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:v:x:";
 	while ((ch = getopt(argc, argv, opstring)) != -1)
 		switch (ch) {
 		case 'B':
@@ -422,6 +424,14 @@
 				    optarg, 1, INT_MAX);
 			}
 			break;
+		case 'v':
+			appleufs_volname = optarg;
+			if (strchr(appleufs_volname, ':') || strchr(appleufs_volname, '/'))
+				errx(1,"Apple UFS volume name cannot contain ':' or '/'");
+			if (appleufs_volname[0] == '\0')
+				errx(1,"Apple UFS volume name cannot be zero length");
+			isappleufs = 1;
+			break;
 		case 'x':
 			cylspares = strsuftoi("spare sectors per cylinder",
 			    optarg, 0, INT_MAX);
@@ -558,8 +568,15 @@
 			pp = &lp->d_partitions[*cp - 'a'];
 		if (pp->p_size == 0)
 			errx(1, "`%c' partition is unavailable", *cp);
-		if (!Iflag && pp->p_fstype != FS_BSDFFS)
-			errx(1, "`%c' partition type is not `4.2BSD'", *cp);
+		if (pp->p_fstype == FS_APPLEUFS)
+			isappleufs = 1;
+		if (isappleufs) {
+			if (!Iflag && (pp->p_fstype != FS_APPLEUFS))
+				errx(1, "`%c' partition type is not `Apple UFS'", *cp);
+		} else {
+			if (!Iflag && (pp->p_fstype != FS_BSDFFS))
+				errx(1, "`%c' partition type is not `4.2BSD'", *cp);
+		}
 	}	/* !Fflag && !mfs */
 
 	if (fssize == 0)
@@ -918,6 +935,7 @@
 	{ NEWFS,	"-t ntracks\ttracks/cylinder" },
 	{ NEWFS,	"-u nsectors\tsectors/track" },
 	{ MFS_MOUNT,	"-u username\tuser name of mount point" },
+	{ NEWFS,	"-v volname\tApple UFS volume name" },
 	{ NEWFS,	"-x cylspares\tspare sectors per cylinder" },
 	{ 0, NULL }
 };
Index: sys/arch/i386/i386/disksubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/i386/disksubr.c,v
retrieving revision 1.45
diff -u -r1.45 disksubr.c
--- sys/arch/i386/i386/disksubr.c	2002/02/19 17:09:44	1.45
+++ sys/arch/i386/i386/disksubr.c	2002/06/20 22:40:33
@@ -208,6 +208,11 @@
 			if (dp->mbrp_typ == MBR_PTYPE_NTFS)
 				pp->p_fstype = FS_NTFS;
 
+#ifdef APPLE_UFS
+			if (dp->mbrp_typ == MBR_PTYPE_APPLEUFS)
+				pp->p_fstype = FS_APPLEUFS;
+#endif
+
 			/* is this ours? */
 			if (dp == ourdp) {
 				/* need sector address for SCSI/IDE,
Index: sys/arch/macppc/include/disklabel.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/include/disklabel.h,v
retrieving revision 1.8
diff -u -r1.8 disklabel.h
--- sys/arch/macppc/include/disklabel.h	2002/03/23 01:29:35	1.8
+++ sys/arch/macppc/include/disklabel.h	2002/06/20 22:40:37
@@ -178,6 +178,7 @@
 #define PART_TYPE_FWB_COMPONENT	"FWB DRIVER COMPONENTS"
 #define PART_TYPE_FREE		"APPLE_FREE"
 #define PART_TYPE_MAC		"APPLE_HFS"
+#define PART_TYPE_APPLEUFS	"APPLE_UFS"
 #define PART_TYPE_NETBSD	"NETBSD"
 #define PART_TYPE_NBSD_PPCBOOT	"NETBSD/MACPPC"
 #define PART_TYPE_NBSD_68KBOOT	"NETBSD/MAC68K"
Index: sys/arch/macppc/macppc/disksubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/macppc/macppc/disksubr.c,v
retrieving revision 1.20
diff -u -r1.20 disksubr.c
--- sys/arch/macppc/macppc/disksubr.c	2002/03/27 20:23:11	1.20
+++ sys/arch/macppc/macppc/disksubr.c	2002/06/20 22:40:37
@@ -126,6 +126,7 @@
 #define SWAP_PART 3
 #define HFS_PART 4
 #define SCRATCH_PART 5
+#define APPLEUFS_PART 6
 
 int fat_types[] = { MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S,
 		    MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32,
@@ -226,6 +227,9 @@
 			type = SCRATCH_PART;
 	} else if (strcmp(PART_TYPE_MAC, typestr) == 0)
 		type = HFS_PART;
+	else if (strcmp(PART_TYPE_APPLEUFS, typestr) == 0) {
+		type = APPLEUFS_PART;
+	}
 	else
 		type = SCRATCH_PART;	/* no known type */
 
@@ -378,6 +382,9 @@
 			break;
 		case SCRATCH_PART:
 			setpartition(part + i, pp, FS_OTHER);
+			break;
+		case APPLEUFS_PART:
+			setpartition(part + i, pp, FS_APPLEUFS);
 			break;
 		default:
 			slot = 0;
Index: sys/sys/disklabel.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/disklabel.h,v
retrieving revision 1.70
diff -u -r1.70 disklabel.h
--- sys/sys/disklabel.h	2002/03/27 19:07:32	1.70
+++ sys/sys/disklabel.h	2002/06/20 22:41:08
@@ -323,8 +323,9 @@
 #define	FS_NTFS		18		/* Windows/NT file system */
 #define	FS_RAID		19		/* RAIDframe component */
 #define	FS_CCD		20		/* concatenated disk component */
+#define	FS_APPLEUFS	21		/* Apple UFS */
 
-/* Adjust the FSMAXTYPES def below if you add something after CCD */
+/* Adjust the FSMAXTYPES def below if you add something after APPLEUFS */
 
 #ifdef	FSTYPENAMES
 static const char *const fstypenames[] = {
@@ -349,11 +350,12 @@
 	"NTFS",
 	"RAID",
 	"ccd",
+	"Apple UFS",
 	NULL
 };
 #define FSMAXTYPES	(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
 #else
-#define FSMAXTYPES	(FS_CCD + 1)
+#define FSMAXTYPES	(FS_APPLEUFS + 1)
 #endif
 
 #ifdef FSCKNAMES
@@ -380,6 +382,7 @@
 	NULL,		/* Windows/NT */
 	NULL,		/* RAID Component */
 	NULL,		/* concatenated disk component */
+	"ffs",		/* Apple UFS */
 	NULL		/* NULL */
 };
 #define FSMAXNAMES	(sizeof(fscknames) / sizeof(fscknames[0]) - 1)
@@ -410,6 +413,7 @@
 	"ntfs",		/* Windows/NT */
 	NULL,		/* RAID Component */
 	NULL,		/* concatenated disk component */
+	"ffs",		/* Apple UFS */
 	NULL		/* NULL */
 };
 #define FSMAXMOUNTNAMES	(sizeof(mountnames) / sizeof(mountnames[0]) - 1)
Index: sys/sys/disklabel_mbr.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/disklabel_mbr.h,v
retrieving revision 1.7
diff -u -r1.7 disklabel_mbr.h
--- sys/sys/disklabel_mbr.h	2002/03/02 07:04:31	1.7
+++ sys/sys/disklabel_mbr.h	2002/06/20 22:41:08
@@ -82,6 +82,7 @@
 #define	MBR_PTYPE_EXT_LNX	0x85	/* Linux extended partition */
 #define MBR_PTYPE_NTFSVOL	0x87	/* NTFS volume set or HPFS mirrored */
 #define	MBR_PTYPE_PREP		0x41	/* PReP */
+#define MBR_PTYPE_APPLEUFS  0xa8	/* Apple UFS */
 
 /* Isolate the relevant bits to get sector and cylinder. */
 #define	MBR_PSECT(s)	((s) & 0x3f)
Index: sys/ufs/files.ufs
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/files.ufs,v
retrieving revision 1.1
diff -u -r1.1 files.ufs
--- sys/ufs/files.ufs	2002/04/16 23:14:10	1.1
+++ sys/ufs/files.ufs	2002/06/20 22:41:08
@@ -5,7 +5,7 @@
 deffs	fs_mfs.h			MFS		# XXX
 deffs	fs_lfs.h			LFS		# XXX
 
-defflag	opt_ffs.h			FFS_EI
+defflag	opt_ffs.h			FFS_EI	APPLE_UFS
 
 file	ufs/ext2fs/ext2fs_alloc.c	ext2fs
 file	ufs/ext2fs/ext2fs_balloc.c	ext2fs
@@ -29,6 +29,7 @@
 file	ufs/ffs/ffs_tables.c		ffs | mfs
 file	ufs/ffs/ffs_vfsops.c		ffs | mfs
 file	ufs/ffs/ffs_vnops.c		ffs | mfs
+file	ufs/ffs/ffs_appleufs.c		ffs & apple_ufs
 
 file	ufs/lfs/lfs_alloc.c		lfs  
 file	ufs/lfs/lfs_balloc.c		lfs
Index: sys/ufs/ffs/ffs_appleufs.c
===================================================================
RCS file: ffs_appleufs.c
diff -N ffs_appleufs.c
--- /dev/null	Fri Jun 21 01:55:31 2002
+++ ffs_appleufs.c	Fri Jun 21 01:41:08 2002
@@ -0,0 +1,155 @@
+/* $NetBSD: $ */
+/*
+ * Copyright (c) 2002 Darrin B. Jewell
+ * 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. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Darrin B. Jewell
+ * 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.
+ */
+
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: $");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#if defined(_KERNEL)
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#endif
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/ufs_bswap.h>
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
+
+#if !defined(_KERNEL) && !defined(STANDALONE)
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#define KASSERT(x) assert(x)
+#endif
+
+/*
+ * this is the same calculation as in_cksum
+ */
+u_int16_t
+ffs_appleufs_cksum(appleufs)
+	const struct appleufslabel *appleufs;
+{
+	const u_int16_t *p = (const u_int16_t *)appleufs;
+	int len = sizeof(struct appleufslabel);
+	long res = 0;
+	while (len > 1)  {
+		res += *p++;
+		len -= 2;
+	}
+#if 0 /* sizeof(struct appleufslabel) is guaranteed to be even */
+	if (len == 1)
+		res += htons(*(u_char *)p<<8);
+#endif
+	res = (res >> 16) + (res & 0xffff);
+	res += (res >> 16);
+	return (~res);
+}
+
+/* copies o to n, validating and byteswapping along the way
+ * returns 0 if ok, EINVAL if not valid
+ */
+int
+ffs_appleufs_validate(name,o,n)
+	const char *name;
+	const struct appleufslabel *o;
+	struct appleufslabel *n;
+{
+	struct appleufslabel tmp;
+	if (!n) n = &tmp;
+
+	if (o->ul_magic != ntohl(APPLEUFS_LABEL_MAGIC)) {
+		return EINVAL;
+	}
+	*n = *o;
+	n->ul_checksum = 0;
+	n->ul_checksum = ffs_appleufs_cksum(n);
+	if (n->ul_checksum != o->ul_checksum) {
+#if defined(DIAGNOSTIC) || !defined(_KERNEL)
+		printf("%s: invalid APPLE UFS checksum. found 0x%x, expecting 0x%x",
+			name,o->ul_checksum,n->ul_checksum);
+#endif
+		return EINVAL;
+	}
+	n->ul_magic = ntohl(o->ul_magic);
+	n->ul_version = ntohl(o->ul_version);
+	n->ul_time = ntohl(o->ul_time);
+	n->ul_namelen = ntohs(o->ul_namelen);
+
+	if (n->ul_namelen > APPLEUFS_MAX_LABEL_NAME) {
+#if defined(DIAGNOSTIC) || !defined(_KERNEL)
+		printf("%s: APPLE UFS label name too long, truncated.\n",
+				name);
+#endif
+		n->ul_namelen = APPLEUFS_MAX_LABEL_NAME;
+	}
+	/* if len is max, will set ul_reserved[0] */
+	n->ul_name[n->ul_namelen] = '\0';	
+#ifdef DEBUG
+	printf("%s: found APPLE UFS label v%d: \"%s\"\n",
+			name,n->ul_version,n->ul_name);
+#endif
+	
+	return 0;
+}
+
+void
+ffs_appleufs_set(appleufs,name,t)
+	struct appleufslabel *appleufs;
+	const char *name;
+	time_t t;
+{
+	size_t namelen;
+	if (!name) name = "untitled";
+	if (t == ((time_t)-1)) {
+#if defined(_KERNEL)
+		t = time.tv_sec;
+#elif defined(STANDALONE)
+		t = 0;
+#else
+		(void)time(&t);
+#endif
+	}
+	namelen = strlen(name);
+	if (namelen > APPLEUFS_MAX_LABEL_NAME)
+		namelen = APPLEUFS_MAX_LABEL_NAME;
+	memset(appleufs, 0, sizeof(*appleufs));
+	appleufs->ul_magic   = htonl(APPLEUFS_LABEL_MAGIC);
+	appleufs->ul_version = htonl(APPLEUFS_LABEL_VERSION);
+	appleufs->ul_time    = htonl((u_int32_t)t);
+	appleufs->ul_namelen = htons(namelen);
+	strncpy(appleufs->ul_name,name,namelen);
+	appleufs->ul_checksum = ffs_appleufs_cksum(appleufs);
+}
Index: sys/ufs/ffs/ffs_extern.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/ffs_extern.h,v
retrieving revision 1.22
diff -u -r1.22 ffs_extern.h
--- sys/ufs/ffs/ffs_extern.h	2002/05/05 17:00:06	1.22
+++ sys/ufs/ffs/ffs_extern.h	2002/06/20 22:41:08
@@ -134,6 +134,12 @@
 int ffs_sbupdate __P((struct ufsmount *, int));
 int ffs_cgupdate __P((struct ufsmount *, int));
 
+/* ffs_appleufs.c */
+u_int16_t ffs_appleufs_cksum __P((const struct appleufslabel *));
+int ffs_appleufs_validate __P((const char*,const struct appleufslabel *,struct appleufslabel *));
+void ffs_appleufs_set __P((struct appleufslabel *, const char *, time_t));
+
+
 /* ffs_vnops.c */
 int ffs_read __P((void *));
 int ffs_write __P((void *));
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.98.4.1
diff -u -r1.98.4.1 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c	2002/06/10 16:46:17	1.98.4.1
+++ sys/ufs/ffs/ffs_vfsops.c	2002/06/20 22:41:09
@@ -498,7 +498,42 @@
 		bp->b_flags |= B_INVAL;
 	brelse(bp);
 	free(newfs, M_UFSMNT);
+
+#ifdef APPLE_UFS
+	/* Recheck for apple UFS filesystem */
+	VFSTOUFS(mountp)->um_flags &= ~UFS_ISAPPLEUFS;
+	/* First check to see if this is tagged as an Apple UFS filesystem
+	 * in the disklabel
+	 */
+	if ((VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) == 0) &&
+		(dpart.part->p_fstype == FS_APPLEUFS)) {
+		VFSTOUFS(mountp)->um_flags |= UFS_ISAPPLEUFS;
+
+	} else {
+		/* Manually look for an apple ufs label, and if a valid one
+		 * is found, then treat it like an Apple UFS filesystem anyway
+		 */
+		error = bread(devvp, (ufs_daddr_t)(APPLEUFS_LABEL_OFFSET / size),
+			APPLEUFS_LABEL_SIZE, cred, &bp);
+		if (error) {
+			brelse(bp);
+			return (error);
+		}
+		error = ffs_appleufs_validate(fs->fs_fsmnt,
+			(struct appleufslabel *)bp->b_data,NULL);
+		if (error == 0) {
+			VFSTOUFS(mountp)->um_flags |= UFS_ISAPPLEUFS;
+		}
+		brelse(bp);
+		bp = NULL;
+	}
+#endif
+
 	mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+	if (UFS_MPISAPPLEUFS(mountp)) {
+		/* see comment about NeXT below */
+		mountp->mnt_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
+	}
 	ffs_oldfscompat(fs);
 		/* An old fsck may have zeroed these fields, so recheck them. */
 	if (fs->fs_avgfilesize <= 0)
@@ -511,6 +546,7 @@
 	}
 
 	ffs_statfs(mountp, &mountp->mnt_stat, p);
+
 	/*
 	 * Step 3: re-read summary information from disk.
 	 */
@@ -714,6 +750,32 @@
 	brelse(bp);
 	bp = NULL;
 
+#ifdef APPLE_UFS
+	/* First check to see if this is tagged as an Apple UFS filesystem
+	 * in the disklabel
+	 */
+	if ((VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) == 0) &&
+		(dpart.part->p_fstype == FS_APPLEUFS)) {
+		ump->um_flags |= UFS_ISAPPLEUFS;
+
+	} else {
+		/* Manually look for an apple ufs label, and if a valid one
+		 * is found, then treat it like an Apple UFS filesystem anyway
+		 */
+		error = bread(devvp, (ufs_daddr_t)(APPLEUFS_LABEL_OFFSET / size),
+			APPLEUFS_LABEL_SIZE, cred, &bp);
+		if (error)
+			goto out;
+		error = ffs_appleufs_validate(fs->fs_fsmnt,
+			(struct appleufslabel *)bp->b_data,NULL);
+		if (error == 0) {
+			ump->um_flags |= UFS_ISAPPLEUFS;
+		}
+		brelse(bp);
+		bp = NULL;
+	}
+#endif
+
 	/*
 	 * verify that we can access the last block in the fs
 	 * if we're mounting read/write.
@@ -784,6 +846,14 @@
 	mp->mnt_stat.f_fsid.val[0] = (long)dev;
 	mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FFS);
 	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+	if (UFS_MPISAPPLEUFS(mp)) {
+		/* NeXT used to keep short symlinks in the inode even
+		 * when using FS_42INODEFMT.  In that case fs->fs_maxsymlinklen
+		 * is probably -1, but we still need to be able to identify
+		 * short symlinks.
+		 */
+		mp->mnt_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
+	}
 	mp->mnt_fs_bshift = fs->fs_bshift;
 	mp->mnt_dev_bshift = DEV_BSHIFT;	/* XXX */
 	mp->mnt_flag |= MNT_LOCAL;
Index: sys/ufs/ffs/fs.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/fs.h,v
retrieving revision 1.25
diff -u -r1.25 fs.h
--- sys/ufs/ffs/fs.h	2002/04/10 14:31:07	1.25
+++ sys/ufs/ffs/fs.h	2002/06/20 22:41:09
@@ -549,4 +549,26 @@
  */
 #define	NINDIR(fs)	((fs)->fs_nindir)
 
+/*
+ * Apple UFS Label:
+ *  We check for this to decide to use APPLEUFS_DIRBLKSIZ
+ */
+#define APPLEUFS_LABEL_MAGIC		0x4c41424c /* LABL */
+#define APPLEUFS_LABEL_SIZE		1024
+#define APPLEUFS_LABEL_OFFSET	(BBSIZE - APPLEUFS_LABEL_SIZE) /* located at 7k */
+#define APPLEUFS_LABEL_VERSION	1
+#define APPLEUFS_MAX_LABEL_NAME	512
+
+struct appleufslabel {
+	u_int32_t	ul_magic;
+	u_int16_t	ul_checksum;
+	u_int32_t	ul_version;
+	u_int32_t	ul_time;
+	u_int16_t	ul_namelen;
+	u_char	ul_name[APPLEUFS_MAX_LABEL_NAME];
+	u_char	ul_reserved[32];
+	u_char	ul_unused[460];
+};
+
+
 #endif /* !_UFS_FFS_FS_H_ */
Index: sys/ufs/ufs/dinode.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/dinode.h,v
retrieving revision 1.13
diff -u -r1.13 dinode.h
--- sys/ufs/ufs/dinode.h	2001/07/27 01:24:54	1.13
+++ sys/ufs/ufs/dinode.h	2002/06/20 22:41:09
@@ -110,6 +110,12 @@
 #define	di_shortlink	di_db
 #define	MAXSYMLINKLEN	((NDADDR + NIADDR) * sizeof(ufs_daddr_t))
 
+/* NeXT used to keep short symlinks in the inode even when using
+ * FS_42INODEFMT.  In that case fs->fs_maxsymlinklen is probably -1,
+ * but short symlinks were stored in inodes shorter than this:
+ */
+#define	APPLEUFS_MAXSYMLINKLEN 60
+
 /* File permissions. */
 #define	IEXEC		0000100		/* Executable. */
 #define	IWRITE		0000200		/* Writeable. */
Index: sys/ufs/ufs/dir.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/dir.h,v
retrieving revision 1.13
diff -u -r1.13 dir.h
--- sys/ufs/ufs/dir.h	2002/02/06 15:44:49	1.13
+++ sys/ufs/ufs/dir.h	2002/06/20 22:41:09
@@ -80,6 +80,7 @@
 #define	DIRBLKSIZ	DEV_BSIZE
 #undef	MAXNAMLEN
 #define	MAXNAMLEN	255
+#define APPLEUFS_DIRBLKSIZ 1024
 
 struct	direct {
 	u_int32_t d_ino;		/* inode number of entry */
Index: sys/ufs/ufs/ufs_lookup.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/ufs_lookup.c,v
retrieving revision 1.39
diff -u -r1.39 ufs_lookup.c
--- sys/ufs/ufs/ufs_lookup.c	2002/05/12 23:06:30	1.39
+++ sys/ufs/ufs/ufs_lookup.c	2002/06/20 22:41:10
@@ -135,6 +135,10 @@
 	int flags;
 	int nameiop = cnp->cn_nameiop;
 	const int needswap = UFS_MPNEEDSWAP(ap->a_dvp->v_mount);
+	int dirblksiz = DIRBLKSIZ;
+	if (UFS_MPISAPPLEUFS(ap->a_dvp->v_mount)) {
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+	}
 
 	cnp->cn_flags &= ~PDIRUNLOCK;
 	flags = cnp->cn_flags;
@@ -209,7 +213,7 @@
 		nchstats.ncs_2passes++;
 	}
 	prevoff = dp->i_offset;
-	endsearch = roundup(dp->i_ffs_size, DIRBLKSIZ);
+	endsearch = roundup(dp->i_ffs_size, dirblksiz);
 	enduseful = 0;
 
 searchloop:
@@ -231,7 +235,7 @@
 		 * boundary, have to start looking for free space again.
 		 */
 		if (slotstatus == NONE &&
-		    (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) {
+		    (entryoffsetinblock & (dirblksiz - 1)) == 0) {
 			slotoffset = -1;
 			slotfreespace = 0;
 		}
@@ -248,7 +252,7 @@
 			int i;
 
 			ufs_dirbad(dp, dp->i_offset, "mangled entry");
-			i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1));
+			i = dirblksiz - (entryoffsetinblock & (dirblksiz - 1));
 			dp->i_offset += i;
 			entryoffsetinblock += i;
 			continue;
@@ -390,12 +394,12 @@
 		 * dp->i_offset + dp->i_count.
 		 */
 		if (slotstatus == NONE) {
-			dp->i_offset = roundup(dp->i_ffs_size, DIRBLKSIZ);
+			dp->i_offset = roundup(dp->i_ffs_size, dirblksiz);
 			dp->i_count = 0;
 			enduseful = dp->i_offset;
 		} else if (nameiop == DELETE) {
 			dp->i_offset = slotoffset;
-			if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0)
+			if ((dp->i_offset & (dirblksiz - 1)) == 0)
 				dp->i_count = 0;
 			else
 				dp->i_count = dp->i_offset - prevoff;
@@ -405,7 +409,7 @@
 			if (enduseful < slotoffset + slotsize)
 				enduseful = slotoffset + slotsize;
 		}
-		dp->i_endoff = roundup(enduseful, DIRBLKSIZ);
+		dp->i_endoff = roundup(enduseful, dirblksiz);
 		dp->i_flag |= IN_CHANGE | IN_UPDATE;
 		/*
 		 * We return with the directory locked, so that
@@ -456,7 +460,7 @@
 	 * in the cache as to where the entry was found.
 	 */
 	if ((flags & ISLASTCN) && nameiop == LOOKUP)
-		dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1);
+		dp->i_diroff = dp->i_offset &~ (dirblksiz - 1);
 
 	/*
 	 * If deleting, and at end of pathname, return
@@ -478,7 +482,7 @@
 		 * is a previous entry in this block) in dp->i_count.
 		 * Save directory inode pointer in ndp->ni_dvp for dirremove().
 		 */
-		if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0)
+		if ((dp->i_offset & (dirblksiz - 1)) == 0)
 			dp->i_count = 0;
 		else
 			dp->i_count = dp->i_offset - prevoff;
@@ -638,6 +642,10 @@
 	int i;
 	int namlen;
 	const int needswap = UFS_MPNEEDSWAP(dp->v_mount);
+	int dirblksiz = DIRBLKSIZ;
+	if (UFS_MPISAPPLEUFS(dp->v_mount)) {
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+	}
 
 #if (BYTE_ORDER == LITTLE_ENDIAN)
 	if (dp->v_mount->mnt_maxsymlinklen > 0 || needswap != 0)
@@ -652,16 +660,16 @@
 #endif
 	if ((ufs_rw16(ep->d_reclen, needswap) & 0x3) != 0 ||
 	    ufs_rw16(ep->d_reclen, needswap) >
-		DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
+		dirblksiz - (entryoffsetinblock & (dirblksiz - 1)) ||
 	    ufs_rw16(ep->d_reclen, needswap) <
 		DIRSIZ(FSFMT(dp), ep, needswap) ||
 	    namlen > MAXNAMLEN) {
 		/*return (1); */
 		printf("First bad, reclen=%x, DIRSIZ=%lu, namlen=%d, flags=%x "
-			"entryoffsetinblock=%d\n",
+			"entryoffsetinblock=%d, dirblksiz = %d\n",
 			ufs_rw16(ep->d_reclen, needswap),
 			(u_long)DIRSIZ(FSFMT(dp), ep, needswap),
-			namlen, dp->v_mount->mnt_flag, entryoffsetinblock);
+			namlen, dp->v_mount->mnt_flag, entryoffsetinblock,dirblksiz);
 		goto bad;
 	}
 	if (ep->d_ino == 0)
@@ -732,6 +740,10 @@
 	char *dirbuf;
 	struct timespec ts;
 	const int needswap = UFS_MPNEEDSWAP(dvp->v_mount);
+	int dirblksiz = DIRBLKSIZ;
+	if (UFS_MPISAPPLEUFS(dvp->v_mount)) {
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+	}
 
 	error = 0;
 	cr = cnp->cn_cred;
@@ -747,21 +759,21 @@
 		 * be on a directory block boundary and we will write the
 		 * new entry into a fresh block.
 		 */
-		if (dp->i_offset & (DIRBLKSIZ - 1))
+		if (dp->i_offset & (dirblksiz - 1))
 			panic("ufs_direnter: newblk");
 		flags = B_CLRBUF;
 		if (!DOINGSOFTDEP(dvp))
 			flags |= B_SYNC;
-		if ((error = VOP_BALLOC(dvp, (off_t)dp->i_offset, DIRBLKSIZ,
+		if ((error = VOP_BALLOC(dvp, (off_t)dp->i_offset, dirblksiz,
 		    cr, flags, &bp)) != 0) {
 			if (DOINGSOFTDEP(dvp) && newdirbp != NULL)
 				bdwrite(newdirbp);
 			return (error);
 		}
-		dp->i_ffs_size = dp->i_offset + DIRBLKSIZ;
+		dp->i_ffs_size = dp->i_offset + dirblksiz;
 		dp->i_flag |= IN_CHANGE | IN_UPDATE;
 		uvm_vnp_setsize(dvp, dp->i_ffs_size);
-		dirp->d_reclen = ufs_rw16(DIRBLKSIZ, needswap);
+		dirp->d_reclen = ufs_rw16(dirblksiz, needswap);
 		dirp->d_ino = ufs_rw32(dirp->d_ino, needswap);
 		if (dvp->v_mount->mnt_maxsymlinklen <= 0) {
 #if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -785,11 +797,11 @@
 			 * block does not have to ensure that the block is
 			 * written before the inode.
 			 */
-			blkoff += DIRBLKSIZ;
+			blkoff += dirblksiz;
 			while (blkoff < bp->b_bcount) {
 				((struct direct *)
-				   (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
-				blkoff += DIRBLKSIZ;
+				   (bp->b_data + blkoff))->d_reclen = dirblksiz;
+				blkoff += dirblksiz;
 			}
 			if (softdep_setup_directory_add(bp, dp, dp->i_offset,
 			    ufs_rw32(dirp->d_ino, needswap), newdirbp, 1) == 0) {
Index: sys/ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.86
diff -u -r1.86 ufs_vnops.c
--- sys/ufs/ufs/ufs_vnops.c	2002/05/14 17:37:52	1.86
+++ sys/ufs/ufs/ufs_vnops.c	2002/06/20 22:41:10
@@ -1178,6 +1178,10 @@
 	struct dirtemplate	dirtemplate;
 	struct direct		newdir;
 	int			error, dmode, blkoff;
+	int dirblksiz = DIRBLKSIZ;
+	if (UFS_MPISAPPLEUFS(ap->a_dvp->v_mount)) {
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+	}
 
 	dvp = ap->a_dvp;
 	vap = ap->a_vap;
@@ -1240,6 +1244,7 @@
 	 * Initialize directory with "." and ".." from static template.
 	 */
 	dirtemplate = mastertemplate;
+	dirtemplate.dotdot_reclen = dirblksiz - dirtemplate.dot_reclen;
 	dirtemplate.dot_ino = ufs_rw32(ip->i_number,
 	    UFS_MPNEEDSWAP(dvp->v_mount));
 	dirtemplate.dotdot_ino = ufs_rw32(dp->i_number,
@@ -1261,10 +1266,10 @@
 		} else
 			dirtemplate.dot_type = dirtemplate.dotdot_type = 0;
 	}
-	if ((error = VOP_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
+	if ((error = VOP_BALLOC(tvp, (off_t)0, dirblksiz, cnp->cn_cred,
 	    B_CLRBUF, &bp)) != 0)
 		goto bad;
-	ip->i_ffs_size = DIRBLKSIZ;
+	ip->i_ffs_size = dirblksiz;
 	ip->i_flag |= IN_CHANGE | IN_UPDATE;
 	uvm_vnp_setsize(tvp, ip->i_ffs_size);
 	memcpy((caddr_t)bp->b_data, (caddr_t)&dirtemplate, sizeof dirtemplate);
@@ -1275,11 +1280,11 @@
 		 * block does not have to ensure that the block is
 		 * written before the inode.
 		 */
-		blkoff = DIRBLKSIZ;
+		blkoff = dirblksiz;
 		while (blkoff < bp->b_bcount) {
 			((struct direct *)
-			  (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
-			blkoff += DIRBLKSIZ;
+			  (bp->b_data + blkoff))->d_reclen = dirblksiz;
+			blkoff += dirblksiz;
 		}
 	}
 	/*
@@ -1491,12 +1496,16 @@
 	int		error;
 	size_t		count, lost;
 	off_t		off;
+	int dirblksiz = DIRBLKSIZ;
+	if (UFS_MPISAPPLEUFS(ap->a_vp->v_mount)) {
+		dirblksiz = APPLEUFS_DIRBLKSIZ;
+	}
 
 	uio = ap->a_uio;
 	off = uio->uio_offset;
 	count = uio->uio_resid;
 	/* Make sure we don't return partial entries. */
-	count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
+	count -= (uio->uio_offset + count) & (dirblksiz -1);
 	if (count <= 0)
 		return (EINVAL);
 	lost = uio->uio_resid - count;
Index: sys/ufs/ufs/ufsmount.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ufs/ufsmount.h,v
retrieving revision 1.8
diff -u -r1.8 ufsmount.h
--- sys/ufs/ufs/ufsmount.h	2000/11/27 08:40:02	1.8
+++ sys/ufs/ufs/ufsmount.h	2002/06/20 22:41:10
@@ -54,6 +54,11 @@
 };
 
 #ifdef _KERNEL
+
+#if defined(_KERNEL_OPT)
+#include "opt_ffs.h"
+#endif
+
 struct buf;
 struct inode;
 struct nameidata;
@@ -94,6 +99,7 @@
 
 /* UFS-specific flags */
 #define UFS_NEEDSWAP	0x01	/* filesystem metadata need byte-swapping */
+#define UFS_ISAPPLEUFS	0x02	/* filesystem is Apple UFS */
 
 /*
  * Flags describing the state of quotas.
@@ -103,6 +109,12 @@
 
 /* Convert mount ptr to ufsmount ptr. */
 #define VFSTOUFS(mp)	((struct ufsmount *)((mp)->mnt_data))
+
+#ifdef APPLE_UFS
+#define UFS_MPISAPPLEUFS(mp)	(VFSTOUFS(mp)->um_flags & UFS_ISAPPLEUFS)
+#else
+#define UFS_MPISAPPLEUFS(mp)	(0)
+#endif
 
 /*
  * Macros to access file system parameters in the ufsmount structure.
Index: usr.bin/file/magdir/filesystems
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/file/magdir/filesystems,v
retrieving revision 1.11
diff -u -r1.11 filesystems
--- usr.bin/file/magdir/filesystems	2002/05/18 07:00:49	1.11
+++ usr.bin/file/magdir/filesystems	2002/06/20 22:41:14
@@ -89,6 +89,10 @@
 >8320	lelong		1		SPACE optimization
 
 9564	belong		0x00011954	Unix Fast File system (big-endian),
+>7168   long		0x4c41424c	Apple UFS Volume
+>>7186  string		x		named %s,
+>>7176  belong		x		volume label version %d,
+>>7180  bedate		x		created on %s,
 >8404	string		x		last mounted on %s,
 #>9504	bedate		x		last checked at %s,
 >8224	bedate		x		last written at %s,

>Release-Note:
>Audit-Trail:
>Unformatted: