Merge with git+ssh://hera.kernel.org/pub/scm/libs/klibc/klibc.git
diff --git a/klibc/arch/parisc/crt0.S b/klibc/arch/parisc/crt0.S
index 7adc6c4..7428443 100644
--- a/klibc/arch/parisc/crt0.S
+++ b/klibc/arch/parisc/crt0.S
@@ -1,34 +1,37 @@
-        .align 4
+	.align 4
 
-        .import $global$, data
-        .import __libc_init, code
+	.import $global$, data
+	.import __libc_init, code
  
-        .global _start
-        .export _start, ENTRY
-        .type _start,@function
+	.global _start
+	.export _start, ENTRY
+	.type _start,@function
 
-        .proc
-        .callinfo
+	.proc
+	.callinfo
 
 _start: 
 /* extend the stack by 64-bytes */
-        ldo     64(%sp), %sp
+	ldo	64(%sp), %sp
 	
 /* %r25 = argc
  * %r24 = argv
- * envp = argv + (argc + 1)        
+ * envp = argv + (argc + 1)	   
  * elfdata = (argv - 4)
  */
-        ldo     -4(%r24), %r26
+	ldo	-4(%r24), %r26
 
 /* load global data */
-        ldil	L%$global$, %dp
-        ldo	R%$global$(%dp), %dp
+	ldil	L%$global$, %dp
+	ldo	R%$global$(%dp), %dp
+
+/* Indicate that we don't need no stinkin' atexit callback */
+	ldi	0,%r25
 
 /* branch to __libc_init */
-        bl	__libc_init,%r2
-        nop
+	bl	__libc_init,%r2
+	nop
 /* break miserably if we ever return */
-        iitlbp	%r0,(%sr0,%r0) /* illegal instruction */
-        nop
-        .procend
+	iitlbp	%r0,(%sr0,%r0) /* illegal instruction */
+	nop
+	.procend
diff --git a/utils/fstype.c b/utils/fstype.c
index c7efbfe..e9cdf28 100644
--- a/utils/fstype.c
+++ b/utils/fstype.c
@@ -7,7 +7,7 @@
  *  FSSIZE - filesystem size (if known)
  *
  * We currently detect (in order):
- *  gzip, cramfs, romfs, xfs, minix, ext3, ext2, reiserfs
+ *  gzip, cramfs, romfs, xfs, minix, ext3, ext2, reiserfs, jfs
  *
  * MINIX, ext3 and Reiserfs bits are currently untested.
  */
@@ -16,8 +16,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <endian.h>
 #include <netinet/in.h>
+#include <sys/vfs.h>
 
 #define cpu_to_be32(x) __cpu_to_be32(x)	/* Needed by romfs_fs.h */
 
@@ -29,6 +31,12 @@
 #include "xfs_sb.h"
 
 /*
+ * Slightly cleaned up version of jfs_superblock to
+ * avoid pulling in other kernel header files.
+ */
+#include "jfs_superblock.h"
+
+/*
  * reiserfs_fs.h is too sick to include directly.
  * Use a cleaned up version.
  */
@@ -174,6 +182,19 @@
 	return 0;
 }
 
+static int jfs_image(const unsigned char *buf, unsigned long *blocks)
+{
+	const struct jfs_superblock *sb =
+		(const struct jfs_superblock *)buf;
+
+	if (!memcmp(sb->s_magic, JFS_MAGIC, 4)) {
+		/* 512 is the VFS Block size */
+		*blocks = __le32_to_cpu(sb->s_size) * 512;;
+		return 1;
+	}
+	return 0;
+}
+
 struct imagetype {
 	off_t		block;
 	const char	name[12];
@@ -189,7 +210,8 @@
 	{ 1,	"ext3",		ext3_image	},
 	{ 1,	"ext2",		ext2_image	},
 	{ 8,	"reiserfs",	reiserfs_image	},
-	{ 64,	"reiserfs",	reiserfs_image	}
+	{ 64,	"reiserfs",	reiserfs_image	},
+	{ 32,	"jfs",		jfs_image	}
 };
 
 int main(int argc, char *argv[])
@@ -199,21 +221,30 @@
 	off_t cur_block = (off_t)-1;
 	unsigned int i;
 	int ret;
+	int fd = 0;
 
 	progname = argv[0];
 
-	if (argc != 1) {
-		fprintf(stderr, "Usage: %s < file\n", progname);
+	if (argc >= 2) {
+		fprintf(stderr, "Usage: %s [file]\n", progname);
 		return 1;
 	}
 
+	if (argc >= 1 && strcmp(argv[1], "-")) {
+		fd = open(argv[1], O_RDONLY);
+		if ( fd < 0 ) {
+			perror(argv[1]);
+			return 1;
+		}
+	}
+
 	for (i = 0; i < ARRAY_SIZE(images); i++) {
 		if (cur_block != images[i].block) {
 			/*
 			 * Read block.
 			 */
 			cur_block = images[i].block;
-			ret = readfile(0, cur_block * BLOCK_SIZE, buf,
+			ret = readfile(fd, cur_block * BLOCK_SIZE, buf,
 				       BLOCK_SIZE);
 			if (ret != 0)
 				return ret;
diff --git a/utils/jfs_superblock.h b/utils/jfs_superblock.h
new file mode 100644
index 0000000..7f60a8c
--- /dev/null
+++ b/utils/jfs_superblock.h
@@ -0,0 +1,114 @@
+/*
+ *   Copyright (C) International Business Machines Corp., 2000-2003
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef	_H_JFS_SUPERBLOCK
+#define _H_JFS_SUPERBLOCK
+
+struct timestruc_t {
+	__le32 tv_sec;
+	__le32 tv_nsec;
+};
+
+/*
+ * make the magic number something a human could read
+ */
+#define JFS_MAGIC 	"JFS1"	/* Magic word */
+
+#define JFS_VERSION	2	/* Version number: Version 2 */
+
+#define LV_NAME_SIZE	11	/* MUST BE 11 for OS/2 boot sector */
+
+/* 
+ *	aggregate superblock 
+ *
+ * The name superblock is too close to super_block, so the name has been
+ * changed to jfs_superblock.  The utilities are still using the old name.
+ */
+struct jfs_superblock {
+	char s_magic[4];	/* 4: magic number */
+	__le32 s_version;	/* 4: version number */
+
+	__le64 s_size;		/* 8: aggregate size in hardware/LVM blocks;
+				 * VFS: number of blocks
+				 */
+	__le32 s_bsize;		/* 4: aggregate block size in bytes; 
+				 * VFS: fragment size
+				 */
+	__le16 s_l2bsize;	/* 2: log2 of s_bsize */
+	__le16 s_l2bfactor;	/* 2: log2(s_bsize/hardware block size) */
+	__le32 s_pbsize;	/* 4: hardware/LVM block size in bytes */
+	__le16 s_l2pbsize;	/* 2: log2 of s_pbsize */
+	__le16 pad;		/* 2: padding necessary for alignment */
+
+	__le32 s_agsize;	/* 4: allocation group size in aggr. blocks */
+
+	__le32 s_flag;		/* 4: aggregate attributes:
+				 *    see jfs_filsys.h
+				 */
+	__le32 s_state;		/* 4: mount/unmount/recovery state: 
+				 *    see jfs_filsys.h
+				 */
+	__le32 s_compress;		/* 4: > 0 if data compression */
+
+	__le64 s_ait2;		/* 8: first extent of secondary
+				 *    aggregate inode table
+				 */
+
+	__le64 s_aim2;		/* 8: first extent of secondary
+				 *    aggregate inode map
+				 */
+	__le32 s_logdev;		/* 4: device address of log */
+	__le32 s_logserial;	/* 4: log serial number at aggregate mount */
+	__le64 s_logpxd;		/* 8: inline log extent */
+
+	__le64 s_fsckpxd;	/* 8: inline fsck work space extent */
+
+	struct timestruc_t s_time;	/* 8: time last updated */
+
+	__le32 s_fsckloglen;	/* 4: Number of filesystem blocks reserved for
+				 *    the fsck service log.  
+				 *    N.B. These blocks are divided among the
+				 *         versions kept.  This is not a per
+				 *         version size.
+				 *    N.B. These blocks are included in the 
+				 *         length field of s_fsckpxd.
+				 */
+	char s_fscklog;		/* 1: which fsck service log is most recent
+				 *    0 => no service log data yet
+				 *    1 => the first one
+				 *    2 => the 2nd one
+				 */
+	char s_fpack[11];	/* 11: file system volume name 
+				 *     N.B. This must be 11 bytes to
+				 *          conform with the OS/2 BootSector
+				 *          requirements
+				 *          Only used when s_version is 1
+				 */
+
+	/* extendfs() parameter under s_state & FM_EXTENDFS */
+	__le64 s_xsize;		/* 8: extendfs s_size */
+	__le64 s_xfsckpxd;	/* 8: extendfs fsckpxd */
+	__le64 s_xlogpxd;	/* 8: extendfs logpxd */
+	/* - 128 byte boundary - */
+
+	char s_uuid[16];	/* 16: 128-bit uuid for volume */
+	char s_label[16];	/* 16: volume label */
+	char s_loguuid[16];	/* 16: 128-bit uuid for log device */
+
+};
+
+#endif /*_H_JFS_SUPERBLOCK */