Index: uspace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision ce13577fe1bbc2e3cc10732baad6a223d0f5a27b)
+++ uspace/app/ext2info/ext2info.c	(revision 5352d72a1c169f0bcb66fde90819e94f703d561a)
@@ -56,4 +56,14 @@
 static void print_block_groups(ext2_filesystem_t *);
 static void print_block_group(ext2_block_group_t *);
+static void print_inode_by_number(ext2_filesystem_t *, uint32_t);
+static void print_inode(ext2_inode_t *);
+
+#define ARG_SUPERBLOCK 1
+#define ARG_BLOCK_GROUPS 2
+#define ARG_INODE 4
+#define ARG_STRICT_CHECK 8
+#define ARG_COMMON (ARG_SUPERBLOCK | ARG_BLOCK_GROUPS)
+#define ARG_ALL (ARG_COMMON | ARG_INODE)
+
 
 int main(int argc, char **argv)
@@ -61,8 +71,12 @@
 
 	int rc;
+	char *endptr;
 	char *dev_path;
 	devmap_handle_t handle;
 	ext2_filesystem_t filesystem;
-	bool strict_check;
+	int arg_flags;
+	uint32_t inode = 0;
+	
+	arg_flags = 0;
 	
 	if (argc < 2) {
@@ -72,11 +86,39 @@
 	}
 	
-	strict_check = false;
+	// Skip program name
+	--argc; ++argv;
+	
 	if (str_cmp(*argv, "--strict-check") == 0) {
 		--argc; ++argv;
-		strict_check = true;
-	}
-
-	--argc; ++argv;
+		arg_flags |= ARG_STRICT_CHECK;
+	}
+	
+	if (str_cmp(*argv, "--superblock") == 0) {
+		--argc; ++argv;
+		arg_flags |= ARG_SUPERBLOCK;
+	}
+	
+	if (str_cmp(*argv, "--block-groups") == 0) {
+		--argc; ++argv;
+		arg_flags |= ARG_BLOCK_GROUPS;
+	}
+	
+	if (str_cmp(*argv, "--inode") == 0) {
+		--argc; ++argv;
+		if (argc == 0) {
+			printf(NAME ": Argument expected for --inode\n");
+			return 2;
+		}
+		
+		inode = strtol(*argv, &endptr, 10);
+		if (*endptr != '\0') {
+			printf(NAME ": Error, invalid argument for --inode.\n");
+			syntax_print();
+			return 1;
+		}
+		
+		arg_flags |= ARG_INODE;
+		--argc; ++argv;
+	}
 
 	if (argc != 1) {
@@ -85,4 +127,9 @@
 		return 1;
 	}
+	
+	// Display common things by default
+	if ((arg_flags & ARG_ALL) == 0) {
+		arg_flags = ARG_COMMON;
+	}
 
 	dev_path = *argv;
@@ -103,11 +150,20 @@
 	if (rc != EOK) {
 		printf(NAME ": Filesystem did not pass sanity check.\n");
-		if (strict_check) {
+		if (arg_flags & ARG_STRICT_CHECK) {
 			return 3;
 		}
 	}
 	
-	print_superblock(filesystem.superblock);
-	print_block_groups(&filesystem);
+	if (arg_flags & ARG_SUPERBLOCK) {
+		print_superblock(filesystem.superblock);
+	}
+	
+	if (arg_flags & ARG_BLOCK_GROUPS) {
+		print_block_groups(&filesystem);
+	}
+	
+	if (arg_flags & ARG_INODE) {
+		print_inode_by_number(&filesystem, inode);
+	}
 
 	ext2_filesystem_fini(&filesystem);
@@ -119,5 +175,5 @@
 static void syntax_print(void)
 {
-	printf("syntax: ext2info <device_name>\n");
+	printf("syntax: ext2info --strict-check --superblock --block-groups --inode <i-number> <device_name>\n");
 }
 
@@ -212,5 +268,6 @@
 }
 
-void print_block_groups(ext2_filesystem_t *filesystem) {
+void print_block_groups(ext2_filesystem_t *filesystem)
+{
 	uint32_t block_group_count;
 	uint32_t i;
@@ -241,5 +298,6 @@
 }
 
-void print_block_group(ext2_block_group_t *bg) {
+void print_block_group(ext2_block_group_t *bg)
+{
 	uint32_t block_bitmap_block;
 	uint32_t inode_bitmap_block;
@@ -264,4 +322,92 @@
 }
 
+void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode)
+{
+	int rc;
+	ext2_inode_ref_t *inode_ref;
+	
+	printf("Inode %u\n", inode);
+	
+	rc = ext2_filesystem_get_inode_ref(fs, inode, &inode_ref);
+	if (rc != EOK) {
+		printf("  Failed getting inode ref\n");
+		return;
+	}
+	
+	print_inode(inode_ref->inode);
+	
+	rc = ext2_filesystem_put_inode_ref(inode_ref);
+	if (rc != EOK) {
+		printf("  Failed putting inode ref\n");
+	}
+}
+
+void print_inode(ext2_inode_t *inode)
+{
+	uint16_t mode;
+	uint32_t user_id;
+	uint32_t group_id;
+	uint32_t size;
+	uint16_t usage_count;
+	uint32_t flags;
+	uint16_t access;
+	const char *type;
+	uint32_t block;
+	int i;
+	bool all_blocks = false;
+	
+	mode = ext2_inode_get_mode(inode);
+	user_id = ext2_inode_get_user_id(inode);
+	group_id = ext2_inode_get_group_id(inode);
+	size = ext2_inode_get_size(inode);
+	usage_count = ext2_inode_get_usage_count(inode);
+	flags = ext2_inode_get_flags(inode);
+	
+	type = "Unknown";
+	if ((mode & EXT2_INODE_MODE_BLOCKDEV) == EXT2_INODE_MODE_BLOCKDEV) {
+		type = "Block device";
+	}
+	else if (mode & EXT2_INODE_MODE_FIFO) {
+		type = "Fifo (pipe)";
+	}
+	else if (mode & EXT2_INODE_MODE_CHARDEV) {
+		type = "Character device";
+	}
+	else if (mode & EXT2_INODE_MODE_DIRECTORY) {
+		type = "Directory";
+	}
+	else if (mode & EXT2_INODE_MODE_FILE) {
+		type = "File";
+	}
+	else if (mode & EXT2_INODE_MODE_SOFTLINK) {
+		type = "Soft link";
+	}
+	else if (mode & EXT2_INODE_MODE_SOCKET) {
+		type = "Socket";
+	}
+	
+	access = mode & EXT2_INODE_MODE_ACCESS_MASK;
+	
+	printf("  Mode: %04x (Type: %s, Access bits: %04ho)\n", mode, type, access);
+	printf("  User ID: %u\n", user_id);
+	printf("  Group ID: %u\n", group_id);
+	printf("  Size: %u\n", size);
+	printf("  Usage (link) count: %u\n", usage_count);
+	printf("  Flags: %u\n", flags);
+	printf("  Block list: ");
+	for (i = 0; i < 12; i++) {
+		block = ext2_inode_get_direct_block(inode, i);
+		if (block == 0) {
+			all_blocks = true;
+			break;
+		}
+		printf("%u ", block);
+	}
+	if (!all_blocks) {
+		printf(" and more...");
+	}
+	printf("\n");
+}
+
 /**
  * @}
Index: uspace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision ce13577fe1bbc2e3cc10732baad6a223d0f5a27b)
+++ uspace/lib/ext2/libext2_filesystem.c	(revision 5352d72a1c169f0bcb66fde90819e94f703d561a)
@@ -225,5 +225,5 @@
 	}
 	
-	newref->inode = newref->block->data + offset_in_group;
+	newref->inode = newref->block->data + (offset_in_group*inode_size);
 	
 	*ref = newref;
Index: uspace/lib/ext2/libext2_inode.c
===================================================================
--- uspace/lib/ext2/libext2_inode.c	(revision ce13577fe1bbc2e3cc10732baad6a223d0f5a27b)
+++ uspace/lib/ext2/libext2_inode.c	(revision 5352d72a1c169f0bcb66fde90819e94f703d561a)
@@ -38,4 +38,119 @@
 #include <byteorder.h>
 
+/**
+ * Get mode stored in the inode
+ * 
+ * @param inode pointer to inode
+ */
+inline uint16_t ext2_inode_get_mode(ext2_inode_t *inode)
+{
+	return uint16_t_le2host(inode->mode);
+}
+
+/**
+ * Get uid this inode is belonging to
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_user_id(ext2_inode_t *inode)
+{
+	// TODO: use additional OS specific bits
+	return uint16_t_le2host(inode->user_id);
+}
+
+/**
+ * Get size of file
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_size(ext2_inode_t *inode)
+{
+	// TODO: Directory ACLS!
+	return uint16_t_le2host(inode->size);
+}
+
+/**
+ * Get gid this inode belongs to
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_group_id(ext2_inode_t *inode)
+{
+	// TODO: use additional OS specific bits
+	return uint16_t_le2host(inode->group_id);
+}
+
+/**
+ * Get usage count (i.e. hard link count)
+ * A value of 1 is common, while 0 means that the inode should be freed
+ * 
+ * @param inode pointer to inode
+ */
+inline uint16_t ext2_inode_get_usage_count(ext2_inode_t *inode)
+{
+	return uint16_t_le2host(inode->usage_count);
+}
+
+/**
+ * Get size of inode in 512 byte blocks
+ * TODO: clarify this
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *inode)
+{
+	return uint32_t_le2host(inode->reserved_512_blocks);
+}
+
+/**
+ * Get inode flags
+ * 
+ * @param inode pointer to inode
+ */
+
+inline uint32_t ext2_inode_get_flags(ext2_inode_t *inode) {
+	return uint32_t_le2host(inode->flags);
+}
+
+/**
+ * Get direct block ID
+ * 
+ * @param inode pointer to inode
+ * @param idx Index to block. Valid values are 0 <= idx < 12
+ */
+inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *inode, uint8_t idx)
+{
+	return uint32_t_le2host(inode->direct_blocks[idx]);
+}
+
+/**
+ * Get indirect block ID
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *inode)
+{
+	return uint32_t_le2host(inode->single_indirect_block);
+}
+
+/**
+ * Get double indirect block ID
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *inode)
+{
+	return uint32_t_le2host(inode->double_indirect_block);
+}
+
+/**
+ * Get triple indirect block ID
+ * 
+ * @param inode pointer to inode
+ */
+inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *inode)
+{
+	return uint32_t_le2host(inode->triple_indirect_block);
+}
 
 
Index: uspace/lib/ext2/libext2_inode.h
===================================================================
--- uspace/lib/ext2/libext2_inode.h	(revision ce13577fe1bbc2e3cc10732baad6a223d0f5a27b)
+++ uspace/lib/ext2/libext2_inode.h	(revision 5352d72a1c169f0bcb66fde90819e94f703d561a)
@@ -55,8 +55,29 @@
 } ext2_inode_t;
 
+#define EXT2_INODE_MODE_FIFO		0x1000
+#define EXT2_INODE_MODE_CHARDEV		0x2000
+#define EXT2_INODE_MODE_DIRECTORY	0x4000
+#define EXT2_INODE_MODE_BLOCKDEV	0x6000
+#define EXT2_INODE_MODE_FILE		0x8000
+#define EXT2_INODE_MODE_SOFTLINK	0xA000
+#define EXT2_INODE_MODE_SOCKET		0xC000
+#define EXT2_INODE_MODE_ACCESS_MASK	0x0FFF
+
 typedef struct ext2_inode_ref {
 	block_t *block; // Reference to a block containing this inode
 	ext2_inode_t *inode;
 } ext2_inode_ref_t;
+
+inline uint16_t ext2_inode_get_mode(ext2_inode_t *);
+inline uint32_t ext2_inode_get_user_id(ext2_inode_t *);
+inline uint32_t ext2_inode_get_size(ext2_inode_t *);
+inline uint32_t ext2_inode_get_group_id(ext2_inode_t *);
+inline uint16_t ext2_inode_get_usage_count(ext2_inode_t *);
+inline uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *);
+inline uint32_t ext2_inode_get_flags(ext2_inode_t *);
+inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *, uint8_t);
+inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *);
+inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *);
+inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *);
 
 
