Index: abi/include/mm/as.h
===================================================================
--- abi/include/mm/as.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ abi/include/mm/as.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -37,8 +37,10 @@
 
 /** Address space area flags. */
-#define AS_AREA_READ       1
-#define AS_AREA_WRITE      2
-#define AS_AREA_EXEC       4
-#define AS_AREA_CACHEABLE  8
+#define AS_AREA_READ         0x01
+#define AS_AREA_WRITE        0x02
+#define AS_AREA_EXEC         0x04
+#define AS_AREA_CACHEABLE    0x08
+#define AS_AREA_GUARD        0x10
+#define AS_AREA_LATE_RESERVE 0x20
 
 /** Address space area info exported to uspace. */
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ boot/Makefile.common	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -109,5 +109,4 @@
 	$(USPACE_PATH)/srv/fs/exfat/exfat \
 	$(USPACE_PATH)/srv/fs/udf/udf \
-	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
 	$(USPACE_PATH)/srv/fs/ext4fs/ext4fs \
 	$(USPACE_PATH)/srv/hid/remcons/remcons \
@@ -167,5 +166,4 @@
 	$(USPACE_PATH)/app/dload/dload \
 	$(USPACE_PATH)/app/edit/edit \
-	$(USPACE_PATH)/app/ext2info/ext2info \
 	$(USPACE_PATH)/app/inet/inet \
 	$(USPACE_PATH)/app/kill/kill \
Index: boot/arch/ia64/src/main.c
===================================================================
--- boot/arch/ia64/src/main.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ boot/arch/ia64/src/main.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -48,5 +48,5 @@
 
 #define DEFAULT_MEMORY_BASE		0x4000000ULL
-#define DEFAULT_MEMORY_SIZE		0x4000000ULL
+#define DEFAULT_MEMORY_SIZE		(256 * 1024 * 1024)
 #define DEFAULT_LEGACY_IO_BASE		0x00000FFFFC000000ULL
 #define DEFAULT_LEGACY_IO_SIZE		0x4000000ULL
Index: contrib/conf/ski.conf
===================================================================
--- contrib/conf/ski.conf	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ contrib/conf/ski.conf	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,1 +1,1 @@
-load HelenOS/image.boot
+load image.boot
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/arch/amd64/Makefile.inc	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -33,24 +33,5 @@
 
 FPU_NO_CFLAGS = -mno-sse -mno-sse2
-
-#
-# FIXME:
-#
-# The -fno-optimize-sibling-calls should be removed as soon as a bug
-# in GCC concerning the "large" memory model and tail call optimization
-# is fixed.
-#
-# When GCC generates a code for tail call, instead of generating ..
-#
-#   jmp *fnc
-#
-# it generates an assembly code with an illegal immediate prefix:
-#
-#   jmp *$fnc
-#
-# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48385 for reference.
-#
-
-CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls
+CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer
 GCC_CFLAGS += $(CMN1)
 ICC_CFLAGS += $(CMN1)
Index: kernel/arch/ia64/include/mm/as.h
===================================================================
--- kernel/arch/ia64/include/mm/as.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/arch/ia64/include/mm/as.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -43,6 +43,4 @@
 #define USER_ADDRESS_SPACE_END_ARCH      UINT64_C(0xdfffffffffffffff)
 
-#define USTACK_ADDRESS_ARCH  UINT64_C(0x0000000ff0000000)
-
 typedef struct {
 } as_arch_t;
Index: kernel/arch/ia64/src/mm/tlb.c
===================================================================
--- kernel/arch/ia64/src/mm/tlb.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/arch/ia64/src/mm/tlb.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -113,6 +113,6 @@
 	va = page;
 	
-	rr.word = rr_read(VA2VRN(va));
-	if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
+	rr.word = rr_read(VA2VRN(page));
+	if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(page))))) {
 		/*
 		 * The selected region register does not contain required RID.
@@ -122,6 +122,6 @@
 		
 		rr0 = rr;
-		rr0.map.rid = ASID2RID(asid, VA2VRN(va));
-		rr_write(VA2VRN(va), rr0.word);
+		rr0.map.rid = ASID2RID(asid, VA2VRN(page));
+		rr_write(VA2VRN(page), rr0.word);
 		srlz_d();
 		srlz_i();
@@ -139,38 +139,38 @@
 	case 1: /* cnt 4 - 15 */
 		ps = PAGE_WIDTH + 2;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 2: /* cnt 16 - 63 */
 		ps = PAGE_WIDTH + 4;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 3: /* cnt 64 - 255 */
 		ps = PAGE_WIDTH + 6;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 4: /* cnt 256 - 1023 */
 		ps = PAGE_WIDTH + 8;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 5: /* cnt 1024 - 4095 */
 		ps = PAGE_WIDTH + 10;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 6: /* cnt 4096 - 16383 */
 		ps = PAGE_WIDTH + 12;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	case 7: /* cnt 16384 - 65535 */
 	case 8: /* cnt 65536 - (256K - 1) */
 		ps = PAGE_WIDTH + 14;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	default:
 		ps = PAGE_WIDTH + 18;
-		va &= ~((1 << ps) - 1);
+		va &= ~((1UL << ps) - 1);
 		break;
 	}
 	
-	for (; va < (page + cnt * PAGE_SIZE); va += (1 << ps))
+	for (; va < (page + cnt * PAGE_SIZE); va += (1UL << ps))
 		asm volatile (
 			"ptc.l %[va], %[ps] ;;"
@@ -183,5 +183,5 @@
 	
 	if (restore_rr) {
-		rr_write(VA2VRN(va), rr.word);
+		rr_write(VA2VRN(page), rr.word);
 		srlz_d();
 		srlz_i();
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/arch/ppc32/src/ppc32.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -103,4 +103,5 @@
 }
 
+#ifdef CONFIG_FB
 static bool display_register(ofw_tree_node_t *node, void *arg)
 {
@@ -169,4 +170,5 @@
 	return true;
 }
+#endif
 
 void arch_post_mm_init(void)
Index: kernel/genarch/src/mm/page_ht.c
===================================================================
--- kernel/genarch/src/mm/page_ht.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/genarch/src/mm/page_ht.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -209,4 +209,8 @@
 		pte->frame = ALIGN_DOWN(frame, FRAME_SIZE);
 
+		/*
+		 * Make sure that a concurrent ht_mapping_find() will see the
+		 * new entry only after it is fully initialized.
+		 */
 		write_barrier();
 		
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/genarch/src/mm/page_pt.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -89,4 +89,9 @@
 		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		/*
+		 * Make sure that a concurrent hardware page table walk or
+		 * pt_mapping_find() will see the new PTL1 only after it is
+		 * fully initialized.
+		 */
 		write_barrier();
 		SET_PTL1_PRESENT(ptl0, PTL0_INDEX(page));
@@ -103,4 +108,7 @@
 		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		/*
+		 * Make the new PTL2 visible only after it is fully initialized.
+		 */
 		write_barrier();
 		SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page));	
@@ -117,4 +125,7 @@
 		    PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
 		    PAGE_WRITE);
+		/*
+		 * Make the new PTL3 visible only after it is fully initialized.
+		 */
 		write_barrier();
 		SET_PTL3_PRESENT(ptl2, PTL2_INDEX(page));
@@ -125,4 +136,7 @@
 	SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
 	SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags | PAGE_NOT_PRESENT);
+	/*
+	 * Make the new mapping visible only after it is fully initialized.
+	 */
 	write_barrier();
 	SET_FRAME_PRESENT(ptl3, PTL3_INDEX(page));
@@ -296,4 +310,7 @@
 
 #if (PTL1_ENTRIES != 0)
+	/*
+	 * Always read ptl2 only after we are sure it is present.
+	 */
 	read_barrier();
 #endif
@@ -304,4 +321,7 @@
 
 #if (PTL2_ENTRIES != 0)
+	/*
+	 * Always read ptl3 only after we are sure it is present.
+	 */
 	read_barrier();
 #endif
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/include/config.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -44,4 +44,6 @@
 #define STACK_FRAMES  TWO_FRAMES
 #define STACK_SIZE    ((1 << STACK_FRAMES) << PAGE_WIDTH)
+
+#define STACK_SIZE_USER	(1 * 1024 * 1024)
 
 #define CONFIG_INIT_TASKS        32
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/include/macros.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -52,8 +52,19 @@
     uint64_t sz2)
 {
-	uint64_t e1 = s1 + sz1;
-	uint64_t e2 = s2 + sz2;
-	
-	return ((s1 < e2) && (s2 < e1));
+	uint64_t e1 = s1 + sz1 - 1;
+	uint64_t e2 = s2 + sz2 - 1;
+
+	/* both sizes are non-zero */
+	if (sz1 && sz2)
+		return ((s1 <= e2) && (s2 <= e1));
+
+	/* one size is non-zero */
+	if (sz2)
+		return ((s1 >= s2) && (s1 <= e2));
+	if (sz1)
+		return ((s2 >= s1) && (s2 <= e1));
+
+	/* both are zero */
+	return (s1 == s2);
 }
 
@@ -119,4 +130,12 @@
 	    | ((((uint64_t) (up)) & UINT32_C(0xffffffff)) << 32))
 
+/* Test for sum overflow. */
+#define overflows(a, b) \
+	((a) + (b) < (a))
+
+/* Test for sum overflow into positive numbers. */
+#define overflows_into_positive(a, b)	\
+	(overflows((a), (b)) && ((a) + (b) > 0))
+
 /** Pseudorandom generator
  *
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/include/mm/as.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -61,10 +61,4 @@
 #define USER_ADDRESS_SPACE_END      USER_ADDRESS_SPACE_END_ARCH
 
-#ifdef USTACK_ADDRESS_ARCH
-	#define USTACK_ADDRESS  USTACK_ADDRESS_ARCH
-#else
-	#define USTACK_ADDRESS  (USER_ADDRESS_SPACE_END - (STACK_SIZE - 1))
-#endif
-
 /** Kernel address space. */
 #define FLAG_AS_KERNEL  (1 << 0)
@@ -224,4 +218,7 @@
 	void (* destroy)(as_area_t *);
 
+	bool (* is_resizable)(as_area_t *);
+	bool (* is_shareable)(as_area_t *);
+
 	int (* page_fault)(as_area_t *, uintptr_t, pf_access_t);
 	void (* frame_free)(as_area_t *, uintptr_t, uintptr_t);
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/include/proc/task.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -134,4 +134,7 @@
 	uint64_t ucycles;
 	uint64_t kcycles;
+
+	/** If true, do not attempt to print a verbose kill message. */ 
+	bool silent_kill;
 } task_t;
 
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/interrupt/interrupt.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -168,14 +168,16 @@
 static NO_TRACE void fault_from_uspace_core(istate_t *istate, const char *fmt, va_list args)
 {
-	printf("Task %s (%" PRIu64 ") killed due to an exception at "
-	    "program counter %p.\n", TASK->name, TASK->taskid,
-	    (void *) istate_get_pc(istate));
-	
-	istate_decode(istate);
-	stack_trace_istate(istate);
-	
-	printf("Kill message: ");
-	vprintf(fmt, args);
-	printf("\n");
+	if (!TASK->silent_kill) {
+		printf("Task %s (%" PRIu64 ") killed due to an exception at "
+		    "program counter %p.\n", TASK->name, TASK->taskid,
+		    (void *) istate_get_pc(istate));
+	
+		istate_decode(istate);
+		stack_trace_istate(istate);
+	
+		printf("Kill message: ");
+		vprintf(fmt, args);
+		printf("\n");
+	}
 	
 	task_kill_self(true);
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/main/kinit.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -172,4 +172,10 @@
 #endif /* CONFIG_KCONSOLE */
 	
+	/*
+	 * Store the default stack size in sysinfo so that uspace can create
+	 * stack with this default size.
+	 */
+	sysinfo_set_item_val("default.stack_size", NULL, STACK_SIZE_USER);
+	
 	interrupts_enable();
 	
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/mm/as.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -285,8 +285,9 @@
 /** Check area conflicts with other areas.
  *
- * @param as    Address space.
- * @param addr  Starting virtual address of the area being tested.
- * @param count Number of pages in the area being tested.
- * @param avoid Do not touch this area.
+ * @param as      Address space.
+ * @param addr    Starting virtual address of the area being tested.
+ * @param count   Number of pages in the area being tested.
+ * @param guarded True if the area being tested is protected by guard pages.
+ * @param avoid   Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
@@ -294,8 +295,15 @@
  */
 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
-    size_t count, as_area_t *avoid)
+    size_t count, bool guarded, as_area_t *avoid)
 {
 	ASSERT((addr % PAGE_SIZE) == 0);
 	ASSERT(mutex_locked(&as->lock));
+
+	/*
+	 * If the addition of the supposed area address and size overflows,
+	 * report conflict.
+	 */
+	if (overflows_into_positive(addr, P2SZ(count)))
+		return false;
 	
 	/*
@@ -304,5 +312,5 @@
 	if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
 		return false;
-	
+
 	/*
 	 * The leaf node is found in O(log n), where n is proportional to
@@ -328,6 +336,51 @@
 		if (area != avoid) {
 			mutex_lock(&area->lock);
-			
+
+			/*
+			 * If at least one of the two areas are protected
+			 * by the AS_AREA_GUARD flag then we must be sure
+			 * that they are separated by at least one unmapped
+			 * page.
+			 */
+			int const gp = (guarded || 
+			    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+			
+			/*
+			 * The area comes from the left neighbour node, which
+			 * means that there already are some areas in the leaf
+			 * node, which in turn means that adding gp is safe and
+			 * will not cause an integer overflow.
+			 */
 			if (overlaps(addr, P2SZ(count), area->base,
+			    P2SZ(area->pages + gp))) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
+	if (node) {
+		area = (as_area_t *) node->value[0];
+		
+		if (area != avoid) {
+			int gp;
+
+			mutex_lock(&area->lock);
+
+			gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+			if (gp && overflows(addr, P2SZ(count))) {
+				/*
+				 * Guard page not needed if the supposed area
+				 * is adjacent to the end of the address space.
+				 * We already know that the following test is
+				 * going to fail...
+				 */
+				gp--;
+			}
+			
+			if (overlaps(addr, P2SZ(count + gp), area->base,
 			    P2SZ(area->pages))) {
 				mutex_unlock(&area->lock);
@@ -339,25 +392,10 @@
 	}
 	
-	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
-	if (node) {
-		area = (as_area_t *) node->value[0];
-		
-		if (area != avoid) {
-			mutex_lock(&area->lock);
-			
-			if (overlaps(addr, P2SZ(count), area->base,
-			    P2SZ(area->pages))) {
-				mutex_unlock(&area->lock);
-				return false;
-			}
-			
-			mutex_unlock(&area->lock);
-		}
-	}
-	
 	/* Second, check the leaf node. */
 	btree_key_t i;
 	for (i = 0; i < leaf->keys; i++) {
 		area = (as_area_t *) leaf->value[i];
+		int agp;
+		int gp;
 		
 		if (area == avoid)
@@ -365,7 +403,18 @@
 		
 		mutex_lock(&area->lock);
-		
-		if (overlaps(addr, P2SZ(count), area->base,
-		    P2SZ(area->pages))) {
+
+		gp = (guarded || (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+		agp = gp;
+
+		/*
+		 * Sanitize the two possible unsigned integer overflows.
+		 */
+		if (gp && overflows(addr, P2SZ(count)))
+			gp--;
+		if (agp && overflows(area->base, P2SZ(area->pages)))
+			agp--;
+
+		if (overlaps(addr, P2SZ(count + gp), area->base,
+		    P2SZ(area->pages + agp))) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -377,9 +426,10 @@
 	/*
 	 * So far, the area does not conflict with other areas.
-	 * Check if it doesn't conflict with kernel address space.
+	 * Check if it is contained in the user address space.
 	 */
 	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
-		return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
-		    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
+		return iswithin(USER_ADDRESS_SPACE_START,
+		    (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1,
+		    addr, P2SZ(count));
 	}
 	
@@ -392,7 +442,8 @@
  * this function.
  *
- * @param as    Address space.
- * @param bound Lowest address bound.
- * @param size  Requested size of the allocation.
+ * @param as      Address space.
+ * @param bound   Lowest address bound.
+ * @param size    Requested size of the allocation.
+ * @param guarded True if the allocation must be protected by guard pages.
  *
  * @return Address of the beginning of unmapped address space area.
@@ -401,5 +452,5 @@
  */
 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
-    size_t size)
+    size_t size, bool guarded)
 {
 	ASSERT(mutex_locked(&as->lock));
@@ -423,7 +474,15 @@
 	/* First check the bound address itself */
 	uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
-	if ((addr >= bound) &&
-	    (check_area_conflicts(as, addr, pages, NULL)))
-		return addr;
+	if (addr >= bound) {
+		if (guarded) {
+			/* Leave an unmapped page between the lower
+			 * bound and the area's start address.
+			 */
+			addr += P2SZ(1);
+		}
+
+		if (check_area_conflicts(as, addr, pages, guarded, NULL))
+			return addr;
+	}
 	
 	/* Eventually check the addresses behind each area */
@@ -439,7 +498,15 @@
 			addr =
 			    ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
+
+			if (guarded || area->flags & AS_AREA_GUARD) {
+				/* We must leave an unmapped page
+				 * between the two areas.
+				 */
+				addr += P2SZ(1);
+			}
+
 			bool avail =
 			    ((addr >= bound) && (addr >= area->base) &&
-			    (check_area_conflicts(as, addr, pages, area)));
+			    (check_area_conflicts(as, addr, pages, guarded, area)));
 			
 			mutex_unlock(&area->lock);
@@ -481,5 +548,5 @@
 	if (size == 0)
 		return NULL;
-	
+
 	size_t pages = SIZE2FRAMES(size);
 	
@@ -487,9 +554,11 @@
 	if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
 		return NULL;
+
+	bool const guarded = flags & AS_AREA_GUARD;
 	
 	mutex_lock(&as->lock);
 	
 	if (*base == (uintptr_t) -1) {
-		*base = as_get_unmapped_area(as, bound, size);
+		*base = as_get_unmapped_area(as, bound, size, guarded);
 		if (*base == (uintptr_t) -1) {
 			mutex_unlock(&as->lock);
@@ -497,6 +566,9 @@
 		}
 	}
-	
-	if (!check_area_conflicts(as, *base, pages, NULL)) {
+
+	if (overflows_into_positive(*base, size))
+		return NULL;
+
+	if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -625,9 +697,8 @@
 		return ENOENT;
 	}
-	
-	if (area->backend == &phys_backend) {
-		/*
-		 * Remapping of address space areas associated
-		 * with memory mapped devices is not supported.
+
+	if (!area->backend->is_resizable(area)) {
+		/*
+		 * The backend does not support resizing for this area.
 		 */
 		mutex_unlock(&area->lock);
@@ -776,7 +847,14 @@
 		/*
 		 * Growing the area.
+		 */
+
+		if (overflows_into_positive(address, P2SZ(pages)))
+			return EINVAL;
+
+		/*
 		 * Check for overlaps with other address space areas.
 		 */
-		if (!check_area_conflicts(as, address, pages, area)) {
+		bool const guarded = area->flags & AS_AREA_GUARD;
+		if (!check_area_conflicts(as, address, pages, guarded, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
@@ -979,8 +1057,7 @@
 	}
 	
-	if ((!src_area->backend) || (!src_area->backend->share)) {
-		/*
-		 * There is no backend or the backend does not
-		 * know how to share the area.
+	if (!src_area->backend->is_shareable(src_area)) {
+		/*
+		 * The backend does not permit sharing of this area.
 		 */
 		mutex_unlock(&src_area->lock);
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/mm/backend_anon.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -59,4 +59,7 @@
 static void anon_destroy(as_area_t *);
 
+static bool anon_is_resizable(as_area_t *);
+static bool anon_is_shareable(as_area_t *);
+
 static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t);
 static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t);
@@ -68,4 +71,7 @@
 	.destroy = anon_destroy,
 
+	.is_resizable = anon_is_resizable,
+	.is_shareable = anon_is_shareable,
+
 	.page_fault = anon_page_fault,
 	.frame_free = anon_frame_free,
@@ -74,4 +80,7 @@
 bool anon_create(as_area_t *area)
 {
+	if (area->flags & AS_AREA_LATE_RESERVE)
+		return true;
+
 	return reserve_try_alloc(area->pages);
 }
@@ -79,4 +88,7 @@
 bool anon_resize(as_area_t *area, size_t new_pages)
 {
+	if (area->flags & AS_AREA_LATE_RESERVE)
+		return true;
+
 	if (new_pages > area->pages)
 		return reserve_try_alloc(new_pages - area->pages);
@@ -100,4 +112,5 @@
 	ASSERT(mutex_locked(&area->as->lock));
 	ASSERT(mutex_locked(&area->lock));
+	ASSERT(!(area->flags & AS_AREA_LATE_RESERVE));
 
 	/*
@@ -139,7 +152,19 @@
 void anon_destroy(as_area_t *area)
 {
+	if (area->flags & AS_AREA_LATE_RESERVE)
+		return;
+
 	reserve_free(area->pages);
 }
 
+bool anon_is_resizable(as_area_t *area)
+{
+	return true;
+}
+
+bool anon_is_shareable(as_area_t *area)
+{
+	return !(area->flags & AS_AREA_LATE_RESERVE);
+}
 
 /** Service a page fault in the anonymous memory address space area.
@@ -225,4 +250,18 @@
 		 *   the different causes
 		 */
+
+		if (area->flags & AS_AREA_LATE_RESERVE) {
+			/*
+			 * Reserve the memory for this page now.
+			 */
+			if (!reserve_try_alloc(1)) {
+				printf("Killing task %" PRIu64 " due to a "
+				    "failed late reservation request.\n",
+				    TASK->taskid);
+				TASK->silent_kill = true;
+				return AS_PF_FAULT;
+			}
+		}
+
 		kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE);
 		memsetb((void *) kpage, PAGE_SIZE, 0);
@@ -255,5 +294,19 @@
 	ASSERT(mutex_locked(&area->lock));
 
-	frame_free_noreserve(frame);
+	if (area->flags & AS_AREA_LATE_RESERVE) {
+		/*
+		 * In case of the late reserve areas, physical memory will not
+		 * be unreserved when the area is destroyed so we need to use
+		 * the normal unreserving frame_free().
+		 */
+		frame_free(frame);
+	} else {
+		/*
+		 * The reserve will be given back when the area is destroyed or
+		 * resized, so use the frame_free_noreserve() which does not
+		 * manipulate the reserve or it would be given back twice.
+		 */
+		frame_free_noreserve(frame);
+	}
 }
 
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/mm/backend_elf.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -58,4 +58,7 @@
 static void elf_destroy(as_area_t *);
 
+static bool elf_is_resizable(as_area_t *);
+static bool elf_is_shareable(as_area_t *);
+
 static int elf_page_fault(as_area_t *, uintptr_t, pf_access_t);
 static void elf_frame_free(as_area_t *, uintptr_t, uintptr_t);
@@ -66,4 +69,7 @@
 	.share = elf_share,
 	.destroy = elf_destroy,
+
+	.is_resizable = elf_is_resizable,
+	.is_shareable = elf_is_shareable,
 
 	.page_fault = elf_page_fault,
@@ -213,4 +219,15 @@
 }
 
+bool elf_is_resizable(as_area_t *area)
+{
+	return true;
+}
+
+bool elf_is_shareable(as_area_t *area)
+{
+	return true;
+}
+
+
 /** Service a page fault in the ELF backend address space area.
  *
Index: kernel/generic/src/mm/backend_phys.c
===================================================================
--- kernel/generic/src/mm/backend_phys.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/mm/backend_phys.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -52,4 +52,8 @@
 static void phys_destroy(as_area_t *);
 
+static bool phys_is_resizable(as_area_t *);
+static bool phys_is_shareable(as_area_t *);
+
+
 static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t);
 
@@ -59,4 +63,7 @@
 	.share = phys_share,
 	.destroy = phys_destroy,
+
+	.is_resizable = phys_is_resizable,
+	.is_shareable = phys_is_shareable,
 
 	.page_fault = phys_page_fault,
@@ -87,4 +94,15 @@
 	/* Nothing to do. */
 }
+
+bool phys_is_resizable(as_area_t *area)
+{
+	return false;
+}
+
+bool phys_is_shareable(as_area_t *area)
+{
+	return true;
+}
+
 
 /** Service a page fault in the address space area backed by physical memory.
Index: kernel/generic/src/mm/km.c
===================================================================
--- kernel/generic/src/mm/km.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/mm/km.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -233,5 +233,6 @@
  * @param[inout] framep	Pointer to a variable which will receive the physical
  *			address of the allocated frame.
- * @param[in] flags	Frame allocation flags. FRAME_NONE or FRAME_NO_RESERVE.
+ * @param[in] flags	Frame allocation flags. FRAME_NONE, FRAME_NO_RESERVE
+ *			and FRAME_ATOMIC bits are allowed.
  * @return		Virtual address of the allocated frame.
  */
@@ -243,5 +244,5 @@
 	ASSERT(THREAD);
 	ASSERT(framep);
-	ASSERT(!(flags & ~FRAME_NO_RESERVE));
+	ASSERT(!(flags & ~(FRAME_NO_RESERVE | FRAME_ATOMIC)));
 
 	/*
@@ -255,6 +256,8 @@
 		ASSERT(page);	// FIXME
 	} else {
-		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME,
-		    FRAME_LOWMEM);
+		frame = (uintptr_t) frame_alloc(ONE_FRAME,
+		    FRAME_LOWMEM | flags);
+		if (!frame)
+			return (uintptr_t) NULL;
 		page = PA2KA(frame);
 	}
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/proc/program.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -79,8 +79,14 @@
 	 * Create the stack address space area.
 	 */
-	uintptr_t virt = USTACK_ADDRESS;
+	uintptr_t virt = (uintptr_t) -1;
+	uintptr_t bound = USER_ADDRESS_SPACE_END - (STACK_SIZE_USER - 1);
+
+	/* Adjust bound to create space for the desired guard page. */
+	bound -= PAGE_SIZE;
+
 	as_area_t *area = as_area_create(as,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
-	    STACK_SIZE, AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, 0);
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD |
+	    AS_AREA_LATE_RESERVE, STACK_SIZE_USER, AS_AREA_ATTR_NONE,
+	    &anon_backend, NULL, &virt, bound);
 	if (!area) {
 		task_destroy(prg->task);
@@ -93,5 +99,5 @@
 	kernel_uarg->uspace_entry = (void *) entry_addr;
 	kernel_uarg->uspace_stack = (void *) virt;
-	kernel_uarg->uspace_stack_size = STACK_SIZE;
+	kernel_uarg->uspace_stack_size = STACK_SIZE_USER;
 	kernel_uarg->uspace_thread_function = NULL;
 	kernel_uarg->uspace_thread_arg = NULL;
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ kernel/generic/src/proc/task.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -196,4 +196,6 @@
 	task->ucycles = 0;
 	task->kcycles = 0;
+
+	task->silent_kill = false;
 	
 	task->ipc_info.call_sent = 0;
Index: tools/autotool.py
===================================================================
--- tools/autotool.py	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ tools/autotool.py	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -563,4 +563,5 @@
 	outmk.write('#########################################\n')
 	outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
+	outmk.write('## Generated by: tools/autotool.py     ##\n')
 	outmk.write('#########################################\n\n')
 	
@@ -580,4 +581,5 @@
 	outhd.write('/***************************************\n')
 	outhd.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	outhd.write(' * Generated by: tools/autotool.py     *\n')
 	outhd.write(' ***************************************/\n\n')
 	
Index: tools/config.py
===================================================================
--- tools/config.py	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ tools/config.py	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -388,8 +388,10 @@
 	outmk.write('#########################################\n')
 	outmk.write('## AUTO-GENERATED FILE, DO NOT EDIT!!! ##\n')
+	outmk.write('## Generated by: tools/config.py       ##\n')
 	outmk.write('#########################################\n\n')
 	
 	outmc.write('/***************************************\n')
 	outmc.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	outmc.write(' * Generated by: tools/config.py       *\n')
 	outmc.write(' ***************************************/\n\n')
 	
Index: tools/mkarray.py
===================================================================
--- tools/mkarray.py	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ tools/mkarray.py	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -95,4 +95,5 @@
 	header.write('/***************************************\n')
 	header.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	header.write(' * Generated by: tools/mkarray.py      *\n')
 	header.write(' ***************************************/\n\n')
 	header.write("#ifndef %s_H_\n" % label)
@@ -109,4 +110,5 @@
 	data.write('/***************************************\n')
 	data.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	data.write(' * Generated by: tools/mkarray.py      *\n')
 	data.write(' ***************************************/\n\n')
 	data.write("#include \"%s.h\"\n\n" % dest)
Index: tools/pack.py
===================================================================
--- tools/pack.py	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ tools/pack.py	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -155,4 +155,5 @@
 	header.write('/***************************************\n')
 	header.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	header.write(' * Generated by: tools/pack.py         *\n')
 	header.write(' ***************************************/\n\n')
 	header.write("#ifndef BOOT_COMPONENTS_H_\n")
@@ -177,4 +178,5 @@
 	data.write('/***************************************\n')
 	data.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	data.write(' * Generated by: tools/pack.py         *\n')
 	data.write(' ***************************************/\n\n')
 	data.write("#include <typedefs.h>\n")
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ tools/toolchain.sh	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -43,6 +43,6 @@
 MPFR_MAIN=<<EOF
 #if MPFR_VERSION < MPFR_VERSION_NUM(2, 4, 2)
-choke me
-	#endif
+	choke me
+#endif
 EOF
 
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/Makefile	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -40,5 +40,4 @@
 	app/devctl \
 	app/edit \
-	app/ext2info \
 	app/getterm \
 	app/init \
@@ -105,5 +104,4 @@
 	srv/fs/mfs \
 	srv/fs/locfs \
-	srv/fs/ext2fs \
 	srv/fs/ext4fs \
 	srv/hid/compositor \
@@ -218,5 +216,4 @@
 	lib/net \
 	lib/nic \
-	lib/ext2 \
 	lib/ext4 \
 	lib/usb \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/Makefile.common	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -118,5 +118,4 @@
 LIBGUI_PREFIX = $(LIB_PREFIX)/gui
 
-LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
 LIBEXT4_PREFIX = $(LIB_PREFIX)/ext4
 
Index: uspace/app/bdsh/config.h
===================================================================
--- uspace/app/bdsh/config.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/bdsh/config.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -55,6 +55,3 @@
 #define PACKAGE_STRING "The brain dead shell"
 #define PACKAGE_TARNAME "bdsh"
-#define PACKAGE_VERSION "0.0.1"
-
-
-
+#define PACKAGE_VERSION "0.1.0"
Index: pace/app/ext2info/Makefile
===================================================================
--- uspace/app/ext2info/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - 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.
-# - 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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBEXT2_PREFIX)/libext2.a
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX)
-BINARY = ext2info
-
-SOURCES = \
-	ext2info.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,624 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-/**
- * @file	ext2info.c
- * @brief	Tool for displaying information about ext2 filesystem
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <block.h>
-#include <mem.h>
-#include <loc.h>
-#include <byteorder.h>
-#include <sys/types.h>
-#include <sys/typefmt.h>
-#include <inttypes.h>
-#include <errno.h>
-#include <libext2.h>
-#include <assert.h>
-
-#define NAME	"ext2info"
-
-static void syntax_print(void);
-static void print_superblock(ext2_superblock_t *);
-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, bool, uint32_t,
-    bool, bool);
-static void print_data(unsigned char *, size_t);
-static void print_inode(ext2_filesystem_t *, ext2_inode_t *, bool);
-static void print_inode_data(ext2_filesystem_t *, ext2_inode_t *, uint32_t);
-static void print_directory_contents(ext2_filesystem_t *, ext2_inode_ref_t *);
-
-#define ARG_SUPERBLOCK 1
-#define ARG_BLOCK_GROUPS 2
-#define ARG_INODE 4
-#define ARG_NO_CHECK 8
-#define ARG_INODE_DATA 16
-#define ARG_INODE_LIST 32
-#define ARG_INODE_BLOCKS 64
-#define ARG_COMMON (ARG_SUPERBLOCK)
-#define ARG_ALL 127
-
-
-int main(int argc, char **argv)
-{
-
-	int rc;
-	char *endptr;
-	char *dev_path;
-	service_id_t service_id;
-	ext2_filesystem_t filesystem;
-	int arg_flags;
-	uint32_t inode = 0;
-	uint32_t inode_data = 0;
-	
-	arg_flags = 0;
-	
-	if (argc < 2) {
-		printf(NAME ": Error, argument missing.\n");
-		syntax_print();
-		return 1;
-	}
-	
-	/* Skip program name */
-	--argc; ++argv;
-	
-	if (argc > 0 && str_cmp(*argv, "--no-check") == 0) {
-		--argc; ++argv;
-		arg_flags |= ARG_NO_CHECK;
-	}
-	
-	if (argc > 0 && str_cmp(*argv, "--superblock") == 0) {
-		--argc; ++argv;
-		arg_flags |= ARG_SUPERBLOCK;
-	}
-	
-	if (argc > 0 && str_cmp(*argv, "--block-groups") == 0) {
-		--argc; ++argv;
-		arg_flags |= ARG_BLOCK_GROUPS;
-	}
-	
-	if (argc > 0 && 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 > 0 && str_cmp(*argv, "--blocks") == 0) {
-			--argc; ++argv;
-			arg_flags |= ARG_INODE_BLOCKS;
-		}
-		
-		if (argc > 0 && str_cmp(*argv, "--data") == 0) {
-			--argc; ++argv;
-			if (argc == 0) {
-				printf(NAME ": Argument expected for --data\n");
-				return 2;
-			}
-			
-			inode_data = strtol(*argv, &endptr, 10);
-			if (*endptr != '\0') {
-				printf(NAME ": Error, invalid argument for --data.\n");
-				syntax_print();
-				return 1;
-			}
-			
-			arg_flags |= ARG_INODE_DATA;
-			--argc; ++argv;
-		}
-		
-		if (argc > 0 && str_cmp(*argv, "--list") == 0) {
-			--argc; ++argv;
-			arg_flags |= ARG_INODE_LIST;
-		}
-	}
-
-	if (argc < 1) {
-		printf(NAME ": Error, argument missing.\n");
-		syntax_print();
-		return 1;
-	}
-	else if (argc > 1) {
-		printf(NAME ": Error, unexpected argument.\n");
-		syntax_print();
-		return 1;
-	}
-	assert(argc == 1);
-	
-	/* Display common things by default */
-	if ((arg_flags & ARG_ALL) == 0) {
-		arg_flags = ARG_COMMON;
-	}
-
-	dev_path = *argv;
-
-	rc = loc_service_get_id(dev_path, &service_id, 0);
-	if (rc != EOK) {
-		printf(NAME ": Error resolving device `%s'.\n", dev_path);
-		return 2;
-	}
-
-	rc = ext2_filesystem_init(&filesystem, service_id);
-	if (rc != EOK)  {
-		printf(NAME ": Error initializing libext2.\n");
-		return 3;
-	}
-	
-	rc = ext2_filesystem_check_sanity(&filesystem);
-	if (rc != EOK) {
-		printf(NAME ": Filesystem did not pass sanity check.\n");
-		if (!(arg_flags & ARG_NO_CHECK)) {
-			return 3;
-		}
-	}
-	
-	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, arg_flags & ARG_INODE_DATA,
-		    inode_data, arg_flags & ARG_INODE_LIST,
-		    arg_flags & ARG_INODE_BLOCKS);
-	}
-
-	ext2_filesystem_fini(&filesystem);
-
-	return 0;
-}
-
-
-static void syntax_print(void)
-{
-	printf("syntax: ext2info [--no-check] [--superblock] [--block-groups] "
-	    "[--inode <i-number> [--blocks] [--data <block-number>] [--list]] "
-	    "<device_name>\n");
-}
-
-static void print_superblock(ext2_superblock_t *superblock)
-{
-	uint16_t magic;
-	uint32_t first_block;
-	uint32_t block_size;
-	uint32_t fragment_size;
-	uint32_t blocks_per_group;
-	uint32_t fragments_per_group;
-	uint32_t rev_major;
-	uint16_t rev_minor;
-	uint16_t state;
-	uint32_t first_inode;
-	uint16_t inode_size;
-	uint32_t total_blocks;
-	uint32_t reserved_blocks;
-	uint32_t free_blocks;
-	uint32_t total_inodes;
-	uint32_t free_inodes;	
-	uint32_t os;
-	
-	int pos;
-	unsigned char c;
-	
-	magic = ext2_superblock_get_magic(superblock);
-	first_block = ext2_superblock_get_first_block(superblock);
-	block_size = ext2_superblock_get_block_size(superblock);
-	fragment_size = ext2_superblock_get_fragment_size(superblock);
-	blocks_per_group = ext2_superblock_get_blocks_per_group(superblock);
-	fragments_per_group = ext2_superblock_get_fragments_per_group(superblock);
-	rev_major = ext2_superblock_get_rev_major(superblock);
-	rev_minor = ext2_superblock_get_rev_minor(superblock);
-	state = ext2_superblock_get_state(superblock);
-	first_inode = ext2_superblock_get_first_inode(superblock);
-	inode_size = ext2_superblock_get_inode_size(superblock);
-	total_blocks = ext2_superblock_get_total_block_count(superblock);
-	reserved_blocks = ext2_superblock_get_reserved_block_count(superblock);
-	free_blocks = ext2_superblock_get_free_block_count(superblock);
-	total_inodes = ext2_superblock_get_total_inode_count(superblock);
-	free_inodes = ext2_superblock_get_free_inode_count(superblock);
-	os = ext2_superblock_get_os(superblock);
-	
-	printf("Superblock:\n");
-	
-	if (magic == EXT2_SUPERBLOCK_MAGIC) {
-		printf("  Magic value: %X (correct)\n", magic);
-	}
-	else {
-		printf("  Magic value: %X (incorrect)\n", magic);
-	}
-	
-	printf("  Revision: %u.%hu\n", rev_major, rev_minor);
-	printf("  State: %hu\n", state);
-	printf("  Creator OS: %u\n", os);
-	printf("  First block: %u\n", first_block);
-	printf("  Block size: %u bytes (%u KiB)\n", block_size, block_size/1024);
-	printf("  Blocks per group: %u\n", blocks_per_group);
-	printf("  Total blocks: %u\n", total_blocks);
-	printf("  Reserved blocks: %u\n", reserved_blocks);
-	printf("  Free blocks: %u\n", free_blocks);
-	printf("  Fragment size: %u bytes (%u KiB)\n", fragment_size,
-	    fragment_size/1024);
-	printf("  Fragments per group: %u\n", fragments_per_group);
-	printf("  First inode: %u\n", first_inode);
-	printf("  Inode size: %hu bytes\n", inode_size);
-	printf("  Total inodes: %u\n", total_inodes);
-	printf("  Free inodes: %u\n", free_inodes);
-	
-	
-	if (rev_major == 1) {
-		printf("  UUID: ");
-		for (pos = 0; pos < 16; pos++) {
-			printf("%02x", superblock->uuid[pos]);
-		}
-		printf("\n");
-		
-		printf("  Volume label: ");
-		for (pos = 0; pos < 16; pos++) {
-			c = superblock->volume_name[pos];
-			if (c >= 32 && c < 128) {
-				putchar(c);
-			}
-			else {
-				putchar(' ');
-			}
-		}
-		printf("\n");
-	}
-	
-}
-
-void print_block_groups(ext2_filesystem_t *filesystem)
-{
-	uint32_t block_group_count;
-	uint32_t i;
-	ext2_block_group_ref_t *block_group_ref;
-	int rc;
-	
-	printf("Block groups:\n");
-	
-	block_group_count = ext2_superblock_get_block_group_count(
-	    filesystem->superblock);
-	
-	for (i = 0; i < block_group_count; i++) {
-		printf("  Block group %u\n", i);
-		rc = ext2_filesystem_get_block_group_ref(filesystem, i, &block_group_ref);
-		if (rc != EOK) {
-			printf("    Failed reading block group\n");
-			continue;
-		}
-		
-		print_block_group(block_group_ref->block_group);
-		
-		rc = ext2_filesystem_put_block_group_ref(block_group_ref);
-		if (rc != EOK) {
-			printf("    Failed freeing block group\n");
-		}
-	}
-	
-}
-
-void print_block_group(ext2_block_group_t *bg)
-{
-	uint32_t block_bitmap_block;
-	uint32_t inode_bitmap_block;
-	uint32_t inode_table_first_block;
-	uint16_t free_block_count;
-	uint16_t free_inode_count;
-	uint16_t directory_inode_count;
-	
-	block_bitmap_block = ext2_block_group_get_block_bitmap_block(bg);
-	inode_bitmap_block = ext2_block_group_get_inode_bitmap_block(bg);
-	inode_table_first_block = ext2_block_group_get_inode_table_first_block(bg);
-	free_block_count = ext2_block_group_get_free_block_count(bg);
-	free_inode_count = ext2_block_group_get_free_inode_count(bg);
-	directory_inode_count = ext2_block_group_get_directory_inode_count(bg);
-	
-	printf("    Block bitmap block: %u\n", block_bitmap_block);
-	printf("    Inode bitmap block: %u\n", inode_bitmap_block);
-	printf("    Inode table's first block: %u\n", inode_table_first_block);
-	printf("    Free blocks: %u\n", free_block_count);
-	printf("    Free inodes: %u\n", free_inode_count);
-	printf("    Directory inodes: %u\n", directory_inode_count);
-}
-
-void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode, 
-    bool print_data, uint32_t data, bool list, bool blocks)
-{
-	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(fs, inode_ref->inode, blocks);
-	if (print_data) {
-		print_inode_data(fs, inode_ref->inode, data);
-	}
-	
-	if (list && ext2_inode_is_type(fs->superblock, inode_ref->inode,
-	    EXT2_INODE_MODE_DIRECTORY)) {
-		print_directory_contents(fs, inode_ref);
-	}
-	
-	rc = ext2_filesystem_put_inode_ref(inode_ref);
-	if (rc != EOK) {
-		printf("  Failed putting inode ref\n");
-	}
-}
-
-void print_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, bool blocks)
-{
-	uint32_t mode;
-	uint32_t mode_type;
-	uint32_t user_id;
-	uint32_t group_id;
-	uint64_t size;
-	uint16_t usage_count;
-	uint32_t flags;
-	uint16_t access;
-	const char *type;
-	uint32_t total_blocks;
-	uint32_t i;
-	uint32_t range_start;
-	uint32_t range_last;
-	uint32_t range_start_file;
-	uint32_t range_last_file;
-	uint32_t range_current;
-	uint32_t range_expected;
-	uint32_t block_size;
-	uint64_t file_blocks;
-	bool printed_range;
-	int rc;
-	
-	block_size = ext2_superblock_get_block_size(fs->superblock);
-	mode = ext2_inode_get_mode(fs->superblock, inode);
-	mode_type = mode & EXT2_INODE_MODE_TYPE_MASK;
-	user_id = ext2_inode_get_user_id(fs->superblock, inode);
-	group_id = ext2_inode_get_group_id(fs->superblock, inode);
-	size = ext2_inode_get_size(fs->superblock, inode);
-	usage_count = ext2_inode_get_usage_count(inode);
-	flags = ext2_inode_get_flags(inode);
-	total_blocks = ext2_inode_get_reserved_blocks(fs->superblock, inode);
-	file_blocks = 0;
-	if (size > 0) {
-		file_blocks = ((size-1)/block_size)+1;
-	}
-	
-	type = "Unknown";
-	if (mode_type == EXT2_INODE_MODE_BLOCKDEV) {
-		type = "Block device";
-	}
-	else if (mode_type == EXT2_INODE_MODE_FIFO) {
-		type = "Fifo (pipe)";
-	}
-	else if (mode_type == EXT2_INODE_MODE_CHARDEV) {
-		type = "Character device";
-	}
-	else if (mode_type == EXT2_INODE_MODE_DIRECTORY) {
-		type = "Directory";
-	}
-	else if (mode_type == EXT2_INODE_MODE_FILE) {
-		type = "File";
-	}
-	else if (mode_type == EXT2_INODE_MODE_SOFTLINK) {
-		type = "Soft link";
-	}
-	else if (mode_type == EXT2_INODE_MODE_SOCKET) {
-		type = "Socket";
-	}
-	
-	access = mode & EXT2_INODE_MODE_ACCESS_MASK;
-	
-	
-	printf("  Mode: %08x (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: %" PRIu64 "\n", size);
-	printf("  Usage (link) count: %u\n", usage_count);
-	printf("  Flags: %u\n", flags);
-	printf("  Total allocated blocks: %u\n", total_blocks);
-	
-	if (blocks) {
-		printf("  Block list: ");
-		
-		range_start = 0;
-		range_current = 0;
-		range_last = 0;
-		
-		printed_range = false;
-		
-		for (i = 0; i <= file_blocks; i++) {
-			if (i < file_blocks) {
-				rc = ext2_filesystem_get_inode_data_block_index(fs, inode, i, &range_current);
-				if (rc != EOK) {
-					printf("Error reading data block indexes\n");
-					return;
-				}
-			}
-			if (range_last == 0) {
-				range_expected = 0;
-			}
-			else {
-				range_expected = range_last + 1;
-			}
-			if (range_current != range_expected) {
-				if (i > 0) {
-					if (printed_range) {
-						printf(", ");
-					}
-					if (range_start == 0 && range_last == 0) {
-						if (range_start_file == range_last_file) {
-							printf("%u N/A", range_start_file);
-						}
-						else {
-							printf("[%u, %u] N/A", range_start_file,
-								range_last_file);
-						}
-					}
-					else {
-						if (range_start_file == range_last_file) {
-							printf("%u -> %u", range_start_file, range_start);
-						}
-						else {
-							printf("[%u, %u] -> [%u, %u]", range_start_file,
-								range_last_file, range_start, range_last);
-						}
-					}
-					printed_range = true;
-				}
-				range_start = range_current;
-				range_start_file = i;
-			}
-			range_last = range_current;
-			range_last_file = i;
-		}
-		printf("\n");
-	}
-}
-
-void print_data(unsigned char *data, size_t size)
-{
-	unsigned char c;
-	size_t i;
-	
-	for (i = 0; i < size; i++) {
-		c = data[i];
-		if (c >= 32 && c < 127) {
-			putchar(c);
-		}
-		else {
-			putchar('.');
-		}
-	}
-}
-
-void print_inode_data(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t data)
-{
-	int rc;
-	uint32_t data_block_index;
-	block_t *block;
-	
-	rc = ext2_filesystem_get_inode_data_block_index(fs, inode, data,
-	    &data_block_index);
-	
-	if (rc != EOK) {
-		printf("Failed getting data block #%u\n", data);
-		return;
-	}
-	
-	printf("Data for inode contents block #%u is located in filesystem "
-	    "block %u\n", data, data_block_index);
-	
-	printf("Data preview (only printable characters):\n");
-	
-	rc = block_get(&block, fs->device, data_block_index, 0);
-	if (rc != EOK) {
-		printf("Failed reading filesystem block %u\n", data_block_index);
-		return;
-	}
-	
-	print_data(block->data, block->size);
-	printf("\n");	
-	
-	rc = block_put(block);
-	if (rc != EOK) {
-		printf("Failed putting filesystem block\n");
-	}
-	
-}
-
-void print_directory_contents(ext2_filesystem_t *fs,
-    ext2_inode_ref_t *inode_ref)
-{
-	int rc;
-	ext2_directory_iterator_t it;
-	size_t name_size;
-	uint32_t inode;
-	
-	printf("  Directory contents:\n");
-	
-	rc = ext2_directory_iterator_init(&it, fs, inode_ref, 0);
-	if (rc != EOK) {
-		printf("Failed initializing directory iterator\n");
-		return;
-	}
-	
-	while (it.current != NULL) {
-		name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
-		    it.current);
-		printf("    ");
-		print_data(&it.current->name, name_size);
-		
-		inode = ext2_directory_entry_ll_get_inode(it.current);
-		printf(" --> %u\n", inode);
-		
-		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			printf("Failed reading directory contents\n");
-			goto cleanup;
-		}
-	}
-
-cleanup:
-	rc = ext2_directory_iterator_fini(&it);
-	if (rc != EOK) {
-		printf("Failed cleaning-up directory iterator\n");
-	}
-	
-}
-
-/**
- * @}
- */
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/tester/Makefile	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -29,6 +29,6 @@
 
 USPACE_PREFIX = ../..
-LIBS = $(LIBEXT2_PREFIX)/libext2.a $(LIBBLOCK_PREFIX)/libblock.a $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX) -I$(LIBSOFTFLOAT_PREFIX)
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBSOFTFLOAT_PREFIX)/libsoftfloat.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBSOFTFLOAT_PREFIX)
 BINARY = tester
 
@@ -42,4 +42,5 @@
 	print/print4.c \
 	print/print5.c \
+	print/print6.c \
 	console/console1.c \
 	stdio/stdio1.c \
@@ -62,6 +63,5 @@
 	mm/mapping1.c \
 	hw/misc/virtchar1.c \
-	hw/serial/serial1.c \
-	ext2/ext2_1.c
+	hw/serial/serial1.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/tester/ext2/ext2_1.c
===================================================================
--- uspace/app/tester/ext2/ext2_1.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,106 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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 <stdio.h>
-#include <unistd.h>
-#include "../tester.h"
-#include "../util.h"
-#include <libext2.h>
-#include <malloc.h>
-
-static ext2_superblock_t *fake_superblock1()
-{
-	uint8_t *buf;
-	int i;
-	
-	buf = malloc(EXT2_SUPERBLOCK_SIZE);
-	if (buf == NULL) {
-		return NULL;
-	}
-	
-	for (i = 0; i < EXT2_SUPERBLOCK_SIZE; i++) {
-		buf[i] = i % 256;
-	}
-	
-	return (ext2_superblock_t *) buf;
-}
-
-const char *test_ext2_1(void)
-{
-	ext2_superblock_t *fake1;
-	
-	TPRINTF("Testing ext2 superblock getters...\n");
-	TPRINTF("Simple test for correct position and byte order\n");
-	
-	fake1 = fake_superblock1();
-	if (fake1 == NULL) {
-		return "Failed allocating memory for test superblock 1";
-	}
-	
-	ASSERT_EQ_32(0x03020100, ext2_superblock_get_total_inode_count(fake1),
-	    "Failed getting total inode count");
-	ASSERT_EQ_32(0x07060504, ext2_superblock_get_total_block_count(fake1),
-	    "Failed getting total block count");
-	ASSERT_EQ_32(0x0B0A0908, ext2_superblock_get_reserved_block_count(fake1),
-	    "Failed getting reserved block count");
-	ASSERT_EQ_32(0x0F0E0D0C, ext2_superblock_get_free_block_count(fake1),
-	    "Failed getting free block count");
-	ASSERT_EQ_32(0x13121110, ext2_superblock_get_free_inode_count(fake1),
-	    "Failed getting free inode count");
-	ASSERT_EQ_32(0x17161514, ext2_superblock_get_first_block(fake1),
-	    "Failed getting first block number");
-	ASSERT_EQ_32(0x1B1A1918, ext2_superblock_get_block_size_log2(fake1),
-	    "Failed getting log block size");
-	ASSERT_EQ_32(0x1F1E1D1C, ext2_superblock_get_fragment_size_log2(fake1),
-	    "Failed getting log fragment size");
-	ASSERT_EQ_32(0x23222120, ext2_superblock_get_blocks_per_group(fake1),
-	    "Failed getting blocks per group");
-	ASSERT_EQ_32(0x27262524, ext2_superblock_get_fragments_per_group(fake1),
-	    "Failed getting fragments per group");
-	ASSERT_EQ_32(0x2B2A2928, ext2_superblock_get_inodes_per_group(fake1),
-	    "Failed getting inodes per group");
-	ASSERT_EQ_16(0x3938, ext2_superblock_get_magic(fake1),
-	    "Failed getting magic number");
-	ASSERT_EQ_16(0x3B3A, ext2_superblock_get_state(fake1),
-	    "Failed getting state");
-	ASSERT_EQ_16(0x3F3E, ext2_superblock_get_rev_minor(fake1),
-	    "Failed getting minor revision number");
-	ASSERT_EQ_32(0x4B4A4948, ext2_superblock_get_os(fake1),
-	    "Failed getting OS");
-	ASSERT_EQ_32(0x4F4E4D4C, ext2_superblock_get_rev_major(fake1),
-	    "Failed getting major revision number");
-	ASSERT_EQ_32(0x57565554, ext2_superblock_get_first_inode(fake1),
-	    "Failed getting first inode number");
-	ASSERT_EQ_16(0x5958, ext2_superblock_get_inode_size(fake1),
-	    "Failed getting size");
-	ASSERT_EQ_8(0x68, fake1->uuid[0], "UUID position is incorrect");
-	ASSERT_EQ_8(0x78, fake1->volume_name[0],
-	    "Volume name position is incorrect");
-	
-	return NULL;
-}
Index: pace/app/tester/ext2/ext2_1.def
===================================================================
--- uspace/app/tester/ext2/ext2_1.def	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"ext2_1",
-	"Superblock getters test",
-	&test_ext2_1,
-	true
-},
Index: uspace/app/tester/float/softfloat1.c
===================================================================
--- uspace/app/tester/float/softfloat1.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/tester/float/softfloat1.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -34,4 +34,5 @@
 #include <mul.h>
 #include <div.h>
+#include <comparison.h>
 #include <bool.h>
 #include "../tester.h"
@@ -45,4 +46,5 @@
 typedef void (* float_op_t)(float, float, float *, float_t *);
 typedef void (* double_op_t)(double, double, double *, double_t *);
+typedef void (* double_cmp_op_t)(double, double, cmptype_t *, cmptype_t *);
 typedef void (* template_t)(void *, unsigned, unsigned, cmptype_t *,
     cmptype_t *);
@@ -66,4 +68,14 @@
 	
 	return -a;
+}
+
+static int dcmp(double a, double b)
+{
+	if (a < b)
+		return -1;
+	else if (a > b)
+		return 1;
+
+	return 0;
 }
 
@@ -96,4 +108,13 @@
 	*pic = (cmptype_t) (c * PRECISION);
 	*pisc = (cmptype_t) (sc.val * PRECISION);
+}
+
+static void
+double_compare_template(void *f, unsigned i, unsigned j, cmptype_t *pis,
+    cmptype_t *piss)
+{
+	double_cmp_op_t op = (double_cmp_op_t) f;
+	
+	op(dop_a[i], dop_b[j], pis, piss);
 }
 
@@ -221,4 +242,25 @@
 }
 
+static void
+double_cmp_operator(double a, double b, cmptype_t *pis, cmptype_t *piss)
+{
+	*pis = dcmp(a, b);
+
+	double_t sa;
+	double_t sb;
+
+	sa.val = a;
+	sb.val = b;
+
+	if (is_double_lt(sa.data, sb.data))
+		*piss = -1;
+	else if (is_double_gt(sa.data, sb.data))
+		*piss = 1;
+	else if (is_double_eq(sa.data, sb.data))
+		*piss = 0;
+	else
+		*piss = 42;
+}
+
 const char *test_softfloat1(void)
 {
@@ -249,4 +291,8 @@
 		TPRINTF("%s\n", err);
 	}
+	if (!test_template(double_compare_template, double_cmp_operator)) {
+		err = "Double comparison failed";
+		TPRINTF("%s\n", err);
+	}
 	
 	return err;
Index: uspace/app/tester/print/print5.def
===================================================================
--- uspace/app/tester/print/print5.def	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/tester/print/print5.def	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,6 +1,6 @@
 {
-	"print1",
-	"String printf test",
-	&test_print1,
+	"print5",
+	"Char printf test",
+	&test_print5,
 	true
 },
Index: uspace/app/tester/print/print6.c
===================================================================
--- uspace/app/tester/print/print6.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/app/tester/print/print6.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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 <stdio.h>
+#include <unistd.h>
+#include "../tester.h"
+
+#include <str.h>
+
+const char *test_print6(void)
+{
+	struct {
+		double val;
+		const char *fmt;
+		const char *exp_str;
+		const char *warn_str;
+	} pat[] = {
+		/* 
+		 * Generic 
+		 */
+		{ 2.0,         "%g",       "2", 0 },
+		{ 0,           "%g",       "0", 0 },
+		{ 0.1,         "%g",     "0.1", 0 },
+		{ 9e59,        "%g",   "9e+59", 0 },
+		{ -9e-59,      "%g",  "-9e-59", 0 },
+		{ 1e307,       "%g",  "1e+307", 0 },   
+		{ 0.09999999999999999, "%g",  "9.999999999999999e-02", 0 },   
+		{ 0.099999999999999999, "%g",  "0.1", 0 },   
+
+		/*
+		 * gcc and msvc convert "3.4567e-317" to different binary
+		 * doubles.
+		 */
+		{ 3.4567e-317, "%g",  "3.4567e-317", "3.456998e-317" },   
+		{ 3.4567e-318, "%g",  "3.4567e-318", 0 },   
+		{ 123456789012345.0, "%g",  "123456789012345", 0 },   
+		{ -123456789012345.0, "%g",  "-123456789012345", 0 },   
+
+		/* Special */
+		{ 1e300 * 1e300, "%g",  "inf", 0 },   
+		{ -1.0 /(1e300 * 1e300), "%g",  "-0", 0 },   
+
+		{ 1234567.8901, "%g",  "1234567.8901", 0 },   
+		{ 1234567.80012, "%g",  "1234567.80012", 0 },   
+		{ 112e-32, "%g",  "1.12e-30", 0 },   
+		{ 10.0e45, "%g",  "1e+46", 0 },   
+
+		/* rounding w/ trailing zero removal */
+		{ 0.01, "%10.6g",      "      0.01", 0 },   
+		{ 9.495, "%10.2g",     "       9.5", 0 },   
+		{ 9.495e30, "%10.2g",  "   9.5e+30", 0 },   
+		{ 9.495e30, "%10g",  " 9.495e+30", 0 },   
+		{ 9.495e30, "%10.6g",  " 9.495e+30", 0 },   
+
+		/*
+		 * Scientific 
+		 */
+		{ 1e05, "%e",  "1.000000e+05", 0 },   
+
+		/* full padding */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%+010.3e",  "+1.000e-01", 0 },
+		{ 1e-1, "%+10.3e",  "+1.000e-01", 0 },   
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_LEFTALIGNED */
+		{ 1e-1, "%+-10.3e",  "+1.000e-01", 0 },
+
+		/* padding */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%+010.2e",  "+01.00e-01", 0 },
+		{ 1e-1, "%+10.2e",  " +1.00e-01", 0 },   
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_LEFTALIGNED */
+		{ 1e-1, "%+-10.2e",  "+1.00e-01 ", 0 },
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.2e",  " 01.00e-01", 0 },
+		/* __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "%010.2e",  "001.00e-01", 0 },
+		/* __PRINTF_FLAG_SPACESIGN */
+		{ 1e-1, "% 10.2e",  "  1.00e-01", 0 },
+		{ 1e-1, "%10.2e",  "  1.00e-01", 0 },   
+
+		/* padding fractionals */
+
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1.08e29, "%+010.3e",  "+1.080e+29", 0 },
+		{ 1.08e29, "%+10.3e",  "+1.080e+29", 0 },  
+		/* __PRINTF_FLAG_SHOWPLUS | __PRINTF_FLAG_ZEROPADDED */
+		{ 1.08e29, "%+011.2e",  "+001.08e+29", 0 },
+		{ 1.085e29, "%11.2e", "   1.09e+29", 0 },   
+
+		/* rounding */
+
+		{ 1.345e2, "%+10.2e",  " +1.35e+02", 0 }, 
+		{ 9.995e2, "%+10.2e",  " +1.00e+03", 0 }, 
+		{ -9.99499999e2, "%10.2e",  " -9.99e+02", 0 },   
+		{ -9.99499999e2, "%10.0e",  "    -1e+03", 0 },   
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -9.99499999e2, "%#10.0e",  "   -1.e+03", 0 },
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -1.2345006789e+231, "%#10.10e",   "-1.2345006789e+231", 0 },
+		/* __PRINTF_FLAG_DECIMALPT */
+		{ -1.23450067995e+231, "%#10.10e",  "-1.2345006800e+231", 0 },
+			
+		/* special */
+
+		{ 1e300 * 1e300, "%10.5e",  "       inf", 0 },   
+		{ -1.0 /(1e300 * 1e300), "%10.2e",  " -0.00e+00", 0 },   
+		/* __PRINTF_FLAG_BIGCHARS */
+		{ 1e300 * 1e300, "%10.5E",  "       INF", 0 },
+		/* __PRINTF_FLAG_BIGCHARS */
+		{ -1.0 /(1e300 * 1e300), "%10.2E",  " -0.00E+00", 0 },
+
+		/*
+		 * Fixed
+		 */
+		 
+		/* padding */
+
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.3f",  " 00000.100", 0 },
+		/*
+		 * __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED |
+		 * __PRINTF_FLAG_LEFTALIGNED
+		 */
+		{ 1e-1, "% 0-10.3f",  " 0.100    ", 0 },
+		/* __PRINTF_FLAG_SPACESIGN | __PRINTF_FLAG_ZEROPADDED */
+		{ 1e-1, "% 010.3f",  " 00000.100", 0 },
+		{ 1e-1, "%10.3f",  "     0.100", 0 },   
+
+		/* rounding */
+
+		{ -0.0, "%10.0f",     "        -0", 0 },   
+		{ -0.099, "%+10.3f",   "    -0.099", 0 }, 
+		{ -0.0995, "%+10.3f",  "    -0.100", 0 }, 
+		{ -0.0994, "%+10.3f",  "    -0.099", 0 }, 
+		{ -99.995, "%+10.0f",  "      -100", 0 }, 
+		{ 3.5, "%+10.30f",  "+3.500000000000000000000000000000", 0 }, 
+		{ 3.5, "%+10.0f",      "        +4", 0 }, 
+		{ 0.1, "%+10.6f",      " +0.100000", 0 }, 
+
+		/*
+		 * The compiler will go for closer 0.10..055 instead of
+		 * 0.09..917
+		 */
+		{ 0.1, "%+10.20f",  "+0.10000000000000000550", 0 },  
+		/* Next closest to 0.1 */
+		{ 0.0999999999999999917, "%+10.20f", "+0.09999999999999999170",
+		    0 }, 
+		{ 0.0999999999999999917, "%+10f",    " +0.100000", 0 },
+		{ 0.0999999999999998945, "%10.20f",  "0.09999999999999989450",
+		    0 },   
+	};
+
+	int patterns_len = (int)(sizeof(pat) / sizeof(pat[0]));
+	int failed = 0;
+	const int buf_size = 256;
+	char buf[256 + 1] = { 0 };
+	
+	TPRINTF("Test printing of floating point numbers via "
+	    "printf(\"%%f\"):\n");
+	
+	for (int i = 0; i < patterns_len; ++i) {
+		
+		snprintf(buf, buf_size, pat[i].fmt, pat[i].val);
+		
+		if (!str_cmp(buf, pat[i].exp_str)) {
+			TPRINTF("ok:  %s |%s| == |%s|\n",
+			    pat[i].fmt, buf, pat[i].exp_str);
+		} else {
+			if (pat[i].warn_str && !str_cmp(buf, pat[i].warn_str)) {
+				TPRINTF("warn: %s |%s| != |%s|\n",
+				    pat[i].fmt, buf, pat[i].exp_str);
+			} else {
+				++failed;
+				TPRINTF("ERR: %s |%s| != |%s|\n",
+				    pat[i].fmt, buf, pat[i].exp_str);
+			}
+		}
+	}
+	
+	if (failed) {
+		return "Unexpectedly misprinted floating point numbers.";
+	} else {
+		return 0;
+	}
+}
+
Index: uspace/app/tester/print/print6.def
===================================================================
--- uspace/app/tester/print/print6.def	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/app/tester/print/print6.def	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,6 @@
+{
+	"print6",
+	"Floating point printf test",
+	&test_print6,
+	true
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/tester/tester.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -53,4 +53,5 @@
 #include "print/print4.def"
 #include "print/print5.def"
+#include "print/print6.def"
 #include "console/console1.def"
 #include "stdio/stdio1.def"
@@ -73,5 +74,4 @@
 #include "hw/serial/serial1.def"
 #include "hw/misc/virtchar1.def"
-#include "ext2/ext2_1.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/app/tester/tester.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -85,4 +85,5 @@
 extern const char *test_print4(void);
 extern const char *test_print5(void);
+extern const char *test_print6(void);
 extern const char *test_console1(void);
 extern const char *test_stdio1(void);
@@ -105,5 +106,4 @@
 extern const char *test_serial1(void);
 extern const char *test_virtchar1(void);
-extern const char *test_ext2_1(void);
 extern const char *test_devman1(void);
 extern const char *test_devman2(void);
Index: uspace/drv/time/cmos-rtc/cmos-rtc.c
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -99,4 +99,6 @@
 static time_t uptime_get(void);
 static bool is_battery_ok(rtc_t *rtc);
+static int  rtc_fun_online(ddf_fun_t *fun);
+static int  rtc_fun_offline(ddf_fun_t *fun);
 
 static ddf_dev_ops_t rtc_dev_ops;
@@ -106,4 +108,6 @@
 	.dev_add = rtc_dev_add,
 	.dev_remove = rtc_dev_remove,
+	.fun_online = rtc_fun_online,
+	.fun_offline = rtc_fun_offline,
 };
 
@@ -405,10 +409,16 @@
 	/* Try to normalize the content of the tm structure */
 	time_t r = mktime(t);
-
-	rtc->boottime = r - uptime_get();
+	int result;
+
+	if (r < 0)
+		result = EINVAL;
+	else {
+		rtc->boottime = r - uptime_get();
+		result = EOK;
+	}
 
 	fibril_mutex_unlock(&rtc->mutex);
 
-	return r < 0 ? EINVAL : EOK;
+	return result;
 }
 
@@ -637,4 +647,10 @@
 	fibril_mutex_unlock(&rtc->mutex);
 
+	rc = rtc_fun_offline(rtc->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to offline function");
+		return rc;
+	}
+
 	rc = ddf_fun_unbind(rtc->fun);
 	if (rc != EOK) {
@@ -725,4 +741,25 @@
 }
 
+static int
+rtc_fun_online(ddf_fun_t *fun)
+{
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "rtc_fun_online()");
+
+	rc = ddf_fun_online(fun);
+	if (rc == EOK)
+		ddf_fun_add_to_category(fun, "clock");
+
+	return rc;
+}
+
+static int
+rtc_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "rtc_fun_offline()");
+	return ddf_fun_offline(fun);
+}
+
 int
 main(int argc, char **argv)
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/Makefile	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -77,4 +77,5 @@
 	generic/device/pci.c \
 	generic/device/ahci.c \
+	generic/dlfcn.c \
 	generic/elf/elf_load.c \
 	generic/event.c \
@@ -115,4 +116,7 @@
 	generic/iplink.c \
 	generic/iplink_srv.c \
+	generic/ieee_double.c \
+	generic/power_of_ten.c \
+	generic/double_to_str.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
@@ -136,4 +140,5 @@
 	generic/net/socket_client.c \
 	generic/net/socket_parse.c \
+	generic/stack.c \
 	generic/stacktrace.c \
 	generic/arg_parse.c \
@@ -145,5 +150,4 @@
 ifeq ($(CONFIG_RTLD),y)
 	GENERIC_SOURCES += \
-		generic/dlfcn.c \
 		generic/rtld/rtld.c \
 		generic/rtld/dynamic.c \
Index: uspace/lib/c/generic/dlfcn.c
===================================================================
--- uspace/lib/c/generic/dlfcn.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/generic/dlfcn.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -38,4 +38,6 @@
 #include <stdlib.h>
 #include <dlfcn.h>
+
+#ifdef CONFIG_RTLD
 
 #include <rtld/module.h>
@@ -87,4 +89,18 @@
 }
 
+#else /* CONFIG_RTLD not defined */
+
+void *dlopen(const char *path, int flag)
+{
+	return NULL;
+}
+
+void *dlsym(void *mod, const char *sym_name)
+{
+	return NULL;
+}
+
+#endif
+
 /** @}
  */
Index: uspace/lib/c/generic/double_to_str.c
===================================================================
--- uspace/lib/c/generic/double_to_str.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/generic/double_to_str.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,785 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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 <double_to_str.h>
+
+#include "private/power_of_ten.h"
+#include <ieee_double.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <bool.h>
+
+/*
+ * Floating point numbers are converted from their binary representation
+ * into a decimal string using the algorithm described in:
+ *   Printing floating-point numbers quickly and accurately with integers
+ *   Loitsch, 2010
+ */
+
+/** The computation assumes a significand of 64 bits. */
+static const int significand_width = 64;
+
+/* Scale exponents to interval [alpha, gamma] to simplify conversion. */
+static const int alpha = -59;
+static const int gamma = -32;
+
+
+/** Returns true if the most-significant bit of num.significand is set. */
+static bool is_normalized(fp_num_t num)
+{
+	assert(8*sizeof(num.significand) == significand_width);
+
+	/* Normalized == most significant bit of the significand is set. */
+	return (num.significand & (1ULL << (significand_width - 1))) != 0;
+}
+
+/** Returns a normalized num with the MSbit set. */
+static fp_num_t normalize(fp_num_t num)
+{
+	const uint64_t top10bits = 0xffc0000000000000ULL;
+
+	/* num usually comes from ieee_double with top 10 bits zero. */
+	while (0 == (num.significand & top10bits)) {
+		num.significand <<= 10;
+		num.exponent -= 10;
+	}
+
+	while (!is_normalized(num)) {
+		num.significand <<= 1;
+		--num.exponent;
+	}
+
+	return num;
+}
+
+
+/** Returns x * y with an error of less than 0.5 ulp. */
+static fp_num_t multiply(fp_num_t x, fp_num_t y)
+{
+	assert(/* is_normalized(x) && */ is_normalized(y));
+	
+	const uint32_t low_bits = -1;
+
+	uint64_t a, b, c, d;
+	a = x.significand >> 32;
+	b = x.significand & low_bits;
+	c = y.significand >> 32;
+	d = y.significand & low_bits;
+
+	uint64_t bd, ad, bc, ac;
+	bd = b * d;
+	ad = a * d;
+	
+	bc = b * c;
+	ac = a * c;
+
+	/* Denote 32 bit parts of x a y as: x == a b, y == c d. Then:
+	 *        a  b    
+	 *  *     c  d
+	 *  ----------
+	 *       ad bd .. multiplication of 32bit parts results in 64bit parts
+	 *  + ac bc
+	 *  ----------
+	 *       [b|d] .. Depicts 64 bit intermediate results and how
+	 *     [a|d]      the 32 bit parts of these results overlap and
+	 *     [b|c]      contribute to the final result.
+	 *  +[a|c]
+	 *  ----------
+	 *   [ret]
+	 *  [tmp]
+	 */
+	uint64_t tmp = (bd >> 32) + (ad & low_bits) + (bc & low_bits);
+
+	/* Round upwards. */
+	tmp += 1U << 31;
+
+	fp_num_t ret;
+	ret.significand = ac + (bc >> 32) + (ad >> 32) + (tmp >> 32);
+	ret.exponent = x.exponent + y.exponent + significand_width;
+	
+	return ret;			
+}
+
+
+/** Returns a - b. Both must have the same exponent. */
+static fp_num_t subtract(fp_num_t a, fp_num_t b)
+{
+	assert(a.exponent == b.exponent);
+	assert(a.significand >= b.significand);
+
+	fp_num_t result;
+	
+	result.significand = a.significand - b.significand;
+	result.exponent = a.exponent;
+
+	return result;
+}
+
+
+/** Returns the interval [low, high] of numbers that convert to binary val. */
+static void get_normalized_bounds(ieee_double_t val, fp_num_t *high, 
+	fp_num_t *low, fp_num_t *val_dist)
+{
+	/* 
+	 * Only works if val comes directly from extract_ieee_double without
+	 * being manipulated in any way (eg it must not be normalized). 
+	 */
+	assert(!is_normalized(val.pos_val));
+
+	high->significand = (val.pos_val.significand << 1) + 1;
+	high->exponent = val.pos_val.exponent - 1;
+
+	/* val_dist = high - val */
+	val_dist->significand = 1;
+	val_dist->exponent = val.pos_val.exponent - 1;
+
+	/* Distance from both lower and upper bound is the same. */
+	if (!val.is_accuracy_step) {
+		low->significand = (val.pos_val.significand << 1) - 1;
+		low->exponent = val.pos_val.exponent - 1;
+	} else {
+		low->significand = (val.pos_val.significand << 2) - 1;
+		low->exponent = val.pos_val.exponent - 2;
+	}
+
+	*high = normalize(*high);
+
+	/* 
+	 * Lower bound may not be normalized if subtracting 1 unit
+	 * reset the most-significant bit to 0. 
+	 */
+	low->significand = low->significand << (low->exponent - high->exponent);
+	low->exponent = high->exponent;
+
+	val_dist->significand = 
+		val_dist->significand << (val_dist->exponent - high->exponent);
+	val_dist->exponent = high->exponent;
+}
+
+/** Determines the interval of numbers that have the binary representation 
+ *  of val.
+ * 
+ * Numbers in the range [scaled_upper_bound - bounds_delta, scaled_upper_bound]
+ * have the same double binary representation as val. 
+ *
+ * Bounds are scaled by 10^scale so that alpha <= exponent <= gamma.
+ * Moreover, scaled_upper_bound is normalized.
+ *
+ * val_dist is the scaled distance from val to the upper bound, ie
+ * val_dist == (upper_bound - val) * 10^scale
+ */
+static void calc_scaled_bounds(ieee_double_t val, fp_num_t *scaled_upper_bound, 
+	fp_num_t *bounds_delta, fp_num_t *val_dist, int *scale)
+{
+	fp_num_t upper_bound, lower_bound;
+
+	get_normalized_bounds(val, &upper_bound, &lower_bound, val_dist);
+
+	assert(upper_bound.exponent == lower_bound.exponent);
+	assert(is_normalized(upper_bound));
+	assert(normalize(val.pos_val).exponent == upper_bound.exponent);
+
+	/* 
+	 * Find such a cached normalized power of 10 that if multiplied
+	 * by upper_bound the binary exponent of upper_bound almost vanishes, 
+	 * ie:
+	 *   upper_scaled := upper_bound * 10^scale
+	 *   alpha <= upper_scaled.exponent <= gamma
+	 *   alpha <= upper_bound.exponent + pow_10.exponent + 64 <= gamma
+	 */
+	fp_num_t scaling_power_of_10;
+	int lower_bin_exp = alpha - upper_bound.exponent - significand_width;
+
+	get_power_of_ten(lower_bin_exp, &scaling_power_of_10, scale);
+
+	int scale_exp = scaling_power_of_10.exponent;
+	assert(alpha <= upper_bound.exponent + scale_exp + significand_width);
+	assert(upper_bound.exponent + scale_exp + significand_width <= gamma);
+
+	fp_num_t upper_scaled = multiply(upper_bound, scaling_power_of_10);
+	fp_num_t lower_scaled = multiply(lower_bound, scaling_power_of_10);
+	*val_dist = multiply(*val_dist, scaling_power_of_10);
+
+	assert(alpha <= upper_scaled.exponent && upper_scaled.exponent <= gamma);
+
+	/* 
+	 * Any value between lower and upper bound would be represented
+	 * in binary as the double val originated from. The bounds were
+	 * however scaled by an imprecise power of 10 (error less than 
+	 * 1 ulp) so the scaled bounds have an error of less than 1 ulp. 
+	 * Conservatively round the lower bound up and the upper bound 
+	 * down by 1 ulp just to be on the safe side. It avoids pronouncing
+	 * produced decimal digits as correct if such a decimal number
+	 * is close to the bounds to within 1 ulp. 
+	 */
+	upper_scaled.significand -= 1;
+	lower_scaled.significand += 1;
+
+	*bounds_delta = subtract(upper_scaled, lower_scaled);
+	*scaled_upper_bound = upper_scaled;
+}
+
+
+/** Rounds the last digit of buf so that it is closest to the converted number.*/
+static void round_last_digit(uint64_t rest, uint64_t w_dist, uint64_t delta,
+	uint64_t digit_val_diff, char *buf, int len)
+{
+	/*
+	 *  | <------- delta -------> |
+	 *  |    | <---- w_dist ----> |
+	 *  |    |       | <- rest -> |
+	 *  |    |       |            |
+	 *  |    |       ` buffer     |
+	 *  |    ` w                  ` upper
+	 *  ` lower
+	 *
+	 * delta = upper - lower .. conservative/safe interval
+	 * w_dist = upper - w    
+	 * upper = "number represented by digits in buf" + rest
+	 * 
+	 * Changing buf[len - 1] changes the value represented by buf 
+	 * by digit_val_diff * scaling, where scaling is shared by
+	 * all parameters. 
+	 *
+	 */
+
+	/* Current number in buf is greater than the double being converted */
+	bool cur_greater_w = rest < w_dist;
+	/* Rounding down by one would keep buf in between bounds (in safe rng). */
+	bool next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta);
+	/* Rounding down by one would bring buf closer to the processed number. */
+	bool next_closer = next_in_val_rng 
+		&& (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest);
+
+	/* Of the shortest strings pick the one that is closest to the actual 
+	   floating point number. */
+	while (next_closer) {
+		assert('0' < buf[len - 1]);
+		assert(0 < digit_val_diff);
+
+		--buf[len - 1];
+		rest += digit_val_diff;
+
+		cur_greater_w = rest < w_dist;
+		next_in_val_rng = cur_greater_w && (rest + digit_val_diff < delta);
+		next_closer = next_in_val_rng 
+			&& (rest + digit_val_diff < w_dist || rest - w_dist < w_dist - rest);
+	}
+}
+
+
+/** Generates the shortest accurate decimal string representation.
+ *
+ * Outputs (mostly) the shortest accurate string representation 
+ * for the number scaled_upper - val_dist. Numbers in the interval
+ * [scaled_upper - delta, scaled_upper] have the same binary
+ * floating point representation and will therefore share the
+ * shortest string representation (up to the rounding of the last
+ * digit to bring the shortest string also the closest to the
+ * actual number). 
+ *
+ * @param scaled_upper Scaled upper bound of numbers that have the
+ *              same binary representation as the converted number.
+ *              Scaled by 10^-scale so that alpha <= exponent <= gamma.
+ * @param delta scaled_upper - delta is the lower bound of numbers
+ *              that share the same binary representation in double.
+ * @param val_dist scaled_upper - val_dist is the number whose
+ *              decimal string we're generating.
+ * @param scale Decimal scaling of the value to convert (ie scaled_upper).
+ * @param buf   Buffer to store the string representation. Must be large 
+ *              enough to store all digits and a null terminator. At most
+ *              MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *              the null terminator).
+ * @param buf_size Size of buf in bytes. 
+ * @param dec_exponent Will be set to the decimal exponent of the number 
+ *              string in buf.
+ *
+ * @return Number of digits; negative on failure (eg buffer too small).
+ */
+static int gen_dec_digits(fp_num_t scaled_upper, fp_num_t delta, 
+	fp_num_t val_dist, int scale, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* 
+	 * The integral part of scaled_upper is 5 to 32 bits long while 
+	 * the remaining fractional part is 59 to 32 bits long because:
+	 * -59 == alpha <= scaled_upper.e <= gamma == -32
+	 *
+	 *  | <------- delta -------> |
+	 *  |    | <--- val_dist ---> |
+	 *  |    |    |<- remainder ->|
+	 *  |    |    |               |
+	 *  |    |    ` buffer        |
+	 *  |    ` val                ` upper
+	 *  ` lower
+	 *
+	 */ 
+	assert(scaled_upper.significand != 0);
+	assert(alpha <= scaled_upper.exponent && scaled_upper.exponent <= gamma);
+	assert(scaled_upper.exponent == delta.exponent);
+	assert(scaled_upper.exponent == val_dist.exponent);
+	assert(val_dist.significand <= delta.significand);
+
+	/* We'll produce at least one digit and a null terminator. */
+	if (buf_size < 2) {
+		return -1;
+	}
+
+	/* one is number 1 encoded with the same exponent as scaled_upper */
+	fp_num_t one;
+	one.significand = ((uint64_t) 1) << (-scaled_upper.exponent);
+	one.exponent = scaled_upper.exponent;
+
+	/*
+	 * Extract the integral part of scaled_upper. 
+	 *  upper / one == upper >> -one.e 
+	 */
+	uint32_t int_part = (uint32_t)(scaled_upper.significand >> (-one.exponent));
+	
+	/* 
+	 * Fractional part of scaled_upper.
+	 *  upper % one == upper & (one.f - 1) 
+	 */
+	uint64_t frac_part = scaled_upper.significand & (one.significand - 1);
+
+	/*
+	 * The integral part of upper has at least 5 bits (64 + alpha) and 
+	 * at most 32 bits (64 + gamma). The integral part has at most 10 
+	 * decimal digits, so kappa <= 10. 
+	 */
+	int kappa = 10;
+	uint32_t div = 1000000000;
+	size_t len = 0;
+
+	/* Produce decimal digits for the integral part of upper. */
+	while (kappa > 0) {
+		int digit = int_part / div;
+		int_part %= div;
+
+		--kappa;
+
+		/* Skip leading zeros. */
+		if (digit != 0 || len != 0) {
+			/* Current length + new digit + null terminator <= buf_size */
+			if (len + 2 <= buf_size) {
+				buf[len] = '0' + digit;
+				++len;
+			} else {
+				return -1;
+			}
+		}
+
+		/* 
+		 * Difference between the so far produced decimal number and upper
+		 * is calculated as: remaining_int_part * one + frac_part 
+		 */
+		uint64_t remainder = (((uint64_t)int_part) << -one.exponent) + frac_part;
+
+		/* The produced decimal number would convert back to upper. */
+		if (remainder <= delta.significand) {
+			assert(0 < len && len < buf_size);
+			*dec_exponent = kappa - scale;
+			buf[len] = '\0';
+
+			/* Of the shortest representations choose the numerically closest. */
+			round_last_digit(remainder, val_dist.significand, delta.significand,
+				(uint64_t)div << (-one.exponent), buf, len);
+			return len;
+		}
+
+		div /= 10;
+	}
+
+	/* Generate decimal digits for the fractional part of upper. */
+	do {
+		/*
+		 * Does not overflow because at least 5 upper bits were
+		 * taken by the integral part and are now unused in frac_part. 
+		 */
+		frac_part *= 10;
+		delta.significand *= 10;
+		val_dist.significand *= 10;
+
+		/* frac_part / one */
+		int digit = (int)(frac_part >> (-one.exponent));
+		
+		/* frac_part %= one */
+		frac_part &= one.significand - 1;
+
+		--kappa;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+		} else {
+			return -1;
+		}
+	} while (frac_part > delta.significand);
+
+	assert(0 < len && len < buf_size);
+
+	*dec_exponent = kappa - scale;
+	buf[len] = '\0';
+
+	/* Of the shortest representations choose the numerically closest one. */
+	round_last_digit(frac_part, val_dist.significand, delta.significand, 
+		one.significand, buf, len);
+
+	return len;
+}
+
+/** Produce a string for 0.0 */
+static int zero_to_str(char *buf, size_t buf_size, int *dec_exponent)
+{
+	if (2 <= buf_size) {
+		buf[0] = '0';
+		buf[1] = '\0';
+		*dec_exponent = 0;
+		return 1;
+	} else {
+		return -1;
+	}
+}
+
+
+/** Converts a non-special double into its shortest accurate string 
+ *  representation.
+ *
+ * Produces an accurate string representation, ie the string will 
+ * convert back to the same binary double (eg via strtod). In the
+ * vast majority of cases (99%) the string will be the shortest such
+ * string that is also the closest to the value of any shortest
+ * string representations. Therefore, no trailing zeros are ever
+ * produced.
+ *
+ * Conceptually, the value is: buf * 10^dec_exponent
+ *
+ * Never outputs trailing zeros.
+ *
+ * @param ieee_val Binary double description to convert. Must be the product
+ *                 of extract_ieee_double and it must not be a special number.
+ * @param buf      Buffer to store the string representation. Must be large 
+ *                 enough to store all digits and a null terminator. At most
+ *                 MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *                 the null terminator).
+ * @param buf_size Size of buf in bytes.
+ * @param dec_exponent Will be set to the decimal exponent of the number 
+ *                 string in buf.
+ *
+ * @return The number of printed digits. A negative value indicates
+ *         an error: buf too small (or ieee_val.is_special).
+ */
+int double_to_short_str(ieee_double_t ieee_val, char *buf, size_t buf_size, 
+	int *dec_exponent)
+{
+	/* The whole computation assumes 64bit significand. */
+	assert(sizeof(ieee_val.pos_val.significand) == sizeof(uint64_t));
+
+	if (ieee_val.is_special) {
+		return -1;
+	}
+
+	/* Zero cannot be normalized. Handle it here. */
+	if (0 == ieee_val.pos_val.significand) {
+		return zero_to_str(buf, buf_size, dec_exponent);
+	}
+
+	fp_num_t scaled_upper_bound;
+	fp_num_t delta;
+	fp_num_t val_dist;
+	int scale;
+
+	calc_scaled_bounds(ieee_val, &scaled_upper_bound, 
+		&delta, &val_dist, &scale);
+
+	int len = gen_dec_digits(scaled_upper_bound, delta, val_dist, scale, 
+		buf, buf_size, dec_exponent);
+
+	assert(len <= MAX_DOUBLE_STR_LEN);
+	return len;
+}
+
+/** Generates a fixed number of decimal digits of w_scaled.
+ *
+ * double == w_scaled * 10^-scale, where alpha <= w_scaled.e <= gamma
+ *
+ * @param w_scaled Scaled number by 10^-scale so that
+ *              alpha <= exponent <= gamma
+ * @param scale Decimal scaling of the value to convert (ie w_scaled).
+ * @param signif_d_cnt Maximum number of significant digits to output. 
+ *              Negative if as many as possible are requested.
+ * @param frac_d_cnt   Maximum number of fractional digits to output.
+ *              Negative if as many as possible are requested.
+ *              Eg. if 2 then 1.234 -> "1.23"; if 2 then 3e-9 -> "0".
+ * @param buf   Buffer to store the string representation. Must be large 
+ *              enough to store all digits and a null terminator. At most
+ *              MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *              the null terminator).
+ * @param buf_size Size of buf in bytes. 
+ *
+ * @return Number of digits; negative on failure (eg buffer too small).
+ */
+static int gen_fixed_dec_digits(fp_num_t w_scaled, int scale, int signif_d_cnt, 
+	int frac_d_cnt, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* We'll produce at least one digit and a null terminator. */
+	if (0 == signif_d_cnt || buf_size < 2) {
+		return -1;
+	}
+
+	/* 
+	 * The integral part of w_scaled is 5 to 32 bits long while the 
+	 * remaining fractional part is 59 to 32 bits long because:
+	 * -59 == alpha <= w_scaled.e <= gamma == -32
+	 * 
+	 * Therefore:
+	 *  | 5..32 bits | 32..59 bits | == w_scaled == w * 10^scale
+	 *  |  int_part  |  frac_part  |
+	 *  |0 0  ..  0 1|0 0   ..  0 0| == one == 1.0
+	 *  |      0     |0 0   ..  0 1| == w_err == 1 * 2^w_scaled.e  
+	*/
+	assert(alpha <= w_scaled.exponent && w_scaled.exponent <= gamma);
+	assert(0 != w_scaled.significand);
+
+	/* 
+	 * Scaling the number being converted by 10^scale introduced
+	 * an error of less that 1 ulp. The actual value of w_scaled
+	 * could lie anywhere between w_scaled.signif +/- w_err. 
+	 * Scale the error locally as we scale the fractional part
+	 * of w_scaled.
+	 */
+	uint64_t w_err = 1;
+
+	/* one is number 1.0 encoded with the same exponent as w_scaled */
+	fp_num_t one;
+	one.significand = ((uint64_t) 1) << (-w_scaled.exponent);
+	one.exponent = w_scaled.exponent;
+
+	/* Extract the integral part of w_scaled. 
+	   w_scaled / one == w_scaled >> -one.e */
+	uint32_t int_part = (uint32_t)(w_scaled.significand >> (-one.exponent));
+
+	/* Fractional part of w_scaled.
+	   w_scaled % one == w_scaled & (one.f - 1) */
+	uint64_t frac_part = w_scaled.significand & (one.significand - 1);
+
+	size_t len = 0;
+	/* 
+	 * The integral part of w_scaled has at least 5 bits (64 + alpha = 5) 
+	 * and at most 32 bits (64 + gamma = 32). The integral part has 
+	 * at most 10 decimal digits, so kappa <= 10. 
+	 */
+	int kappa = 10;
+	uint32_t div = 1000000000;
+
+	int rem_signif_d_cnt = signif_d_cnt;
+	int rem_frac_d_cnt = 
+		(frac_d_cnt >= 0) ? (kappa - scale + frac_d_cnt) : INT_MAX;
+
+	/* Produce decimal digits for the integral part of w_scaled. */
+	while (kappa > 0 && rem_signif_d_cnt != 0 && rem_frac_d_cnt > 0) {
+		int digit = int_part / div;
+		int_part %= div;
+
+		div /= 10;
+		--kappa;
+		--rem_frac_d_cnt;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+			--rem_signif_d_cnt;
+		} else {
+			return -1;
+		}
+	}
+
+	/* Generate decimal digits for the fractional part of w_scaled. */
+	while (w_err <= frac_part && rem_signif_d_cnt != 0 && rem_frac_d_cnt > 0) {
+		/*
+		 * Does not overflow because at least 5 upper bits were
+		 * taken by the integral part and are now unused in frac_part. 
+		 */
+		frac_part *= 10;
+		w_err *= 10;
+
+		/* frac_part / one */
+		int digit = (int)(frac_part >> (-one.exponent));
+		
+		/* frac_part %= one */
+		frac_part &= one.significand - 1;
+
+		--kappa;
+		--rem_frac_d_cnt;
+
+		/* Skip leading zeros. */
+		if (digit == 0 && len == 0) {
+			continue;
+		}
+
+		/* Current length + new digit + null terminator <= buf_size */
+		if (len + 2 <= buf_size) {
+			buf[len] = '0' + digit;
+			++len;
+			--rem_signif_d_cnt;
+		} else {
+			return -1;
+		}
+	};
+
+	assert(/* 0 <= len && */ len < buf_size);
+
+	if (0 < len) {
+		*dec_exponent = kappa - scale;
+		assert(frac_d_cnt < 0 || -frac_d_cnt <= *dec_exponent);
+	} else {
+		/* 
+		 * The number of fractional digits was too limiting to produce 
+		 * any digits. 
+		 */
+		assert(rem_frac_d_cnt <= 0 || w_scaled.significand == 0);
+		*dec_exponent = 0;
+		buf[0] = '0';
+		len = 1;
+	}
+
+	if (len < buf_size) {
+		buf[len] = '\0';
+		assert(signif_d_cnt < 0 || (int)len <= signif_d_cnt);
+		return len;
+	} else {
+		return -1;
+	}
+}
+
+
+/** Converts a non-special double into its string representation.
+ *
+ * Conceptually, the truncated double value is: buf * 10^dec_exponent
+ *
+ * Conversion errors are tracked, so all produced digits except the
+ * last one are accurate. Garbage digits are never produced.
+ * If the requested number of digits cannot be produced accurately 
+ * due to conversion errors less digits are produced than requested 
+ * and the last digit has an error of +/- 1 (so if '7' is the last
+ * converted digit it might have been converted to any of '6'..'8'
+ * had the conversion been completely precise). 
+ *
+ * If no error occurs at least one digit is output. 
+ *
+ * The conversion stops once the requested number of significant or 
+ * fractional digits is reached or the conversion error is too large 
+ * to generate any more digits (whichever happens first).
+ *
+ * Any digits following the first (most-significant) digit (this digit
+ * included) are counted as significant digits; eg:
+ *   1.4,    4 signif -> "1400" * 10^-3, ie 1.400
+ *   1000.3, 1 signif -> "1" * 10^3      ie 1000
+ *   0.003,  2 signif -> "30" * 10^-4    ie 0.003
+ *   9.5     1 signif -> "9" * 10^0,     ie 9
+ *
+ * Any digits following the decimal point are counted as fractional digits.
+ * This includes the zeros that would appear between the decimal point
+ * and the first non-zero fractional digit. If fewer fractional digits
+ * are requested than would allow to place the most-significant digit
+ * a "0" is output. Eg:
+ *   1.4,   3 frac -> "1400" * 10^-3,   ie 1.400
+ *   12.34  4 frac -> "123400" * 10^-4, ie 12.3400
+ *   3e-99  4 frac -> "0" * 10^0,       ie 0
+ *   0.009  2 frac -> "0" * 10^-2,      ie 0
+ *
+ * @param ieee_val Binary double description to convert. Must be the product
+ *                 of extract_ieee_double and it must not be a special number.
+ * @param signif_d_cnt Maximum number of significant digits to produce.
+ *                 The output is not rounded. 
+ *                 Set to a negative value to generate as many digits
+ *                 as accurately possible.
+ * @param frac_d_cnt Maximum number of fractional digits to produce including
+ *                 any zeros immediately trailing the decimal point. 
+ *                 The output is not rounded. 
+ *                 Set to a negative value to generate as many digits
+ *                 as accurately possible.
+ * @param buf      Buffer to store the string representation. Must be large 
+ *                 enough to store all digits and a null terminator. At most
+ *                 MAX_DOUBLE_STR_LEN digits will be written (not counting
+ *                 the null terminator).
+ * @param buf_size Size of buf in bytes.
+ * @param dec_exponent Set to the decimal exponent of the number string 
+ *                 in buf.
+ *
+ * @return The number of output digits. A negative value indicates
+ *         an error: buf too small (or ieee_val.is_special, or 
+ *         signif_d_cnt == 0).
+ */
+int double_to_fixed_str(ieee_double_t ieee_val, int signif_d_cnt,
+	int frac_d_cnt, char *buf, size_t buf_size, int *dec_exponent)
+{
+	/* The whole computation assumes 64bit significand. */
+	assert(sizeof(ieee_val.pos_val.significand) == sizeof(uint64_t));
+
+	if (ieee_val.is_special) {
+		return -1;
+	}
+
+	/* Zero cannot be normalized. Handle it here. */
+	if (0 == ieee_val.pos_val.significand) {
+		return zero_to_str(buf, buf_size, dec_exponent);
+	}
+
+	/* Normalize and scale. */
+	fp_num_t w = normalize(ieee_val.pos_val);
+
+	int lower_bin_exp = alpha - w.exponent - significand_width;
+
+	int scale;
+	fp_num_t scaling_power_of_10;
+
+	get_power_of_ten(lower_bin_exp, &scaling_power_of_10, &scale);
+
+	fp_num_t w_scaled = multiply(w, scaling_power_of_10);
+
+	/* Produce decimal digits from the scaled number. */
+	int len = gen_fixed_dec_digits(w_scaled, scale, signif_d_cnt, frac_d_cnt, 
+		buf, buf_size, dec_exponent);
+
+	assert(len <= MAX_DOUBLE_STR_LEN);
+	return len;
+}
+
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/generic/fibril.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -37,6 +37,9 @@
 #include <fibril.h>
 #include <thread.h>
+#include <stack.h>
 #include <tls.h>
 #include <malloc.h>
+#include <abi/mm/as.h>
+#include <as.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -46,8 +49,4 @@
 #include <assert.h>
 #include <async.h>
-
-#ifndef FIBRIL_INITIAL_STACK_PAGES_NO
-	#define FIBRIL_INITIAL_STACK_PAGES_NO  1
-#endif
 
 /**
@@ -195,5 +194,5 @@
 					 * stack member filled.
 					 */
-					free(stack);
+					as_area_destroy(stack);
 				}
 				fibril_teardown(srcf->clean_after_me);
@@ -269,7 +268,9 @@
 		return 0;
 	
-	fibril->stack =
-	    (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize());
-	if (!fibril->stack) {
+	size_t stack_size = stack_size_get();
+	fibril->stack = as_area_create((void *) -1, stack_size,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD |
+	    AS_AREA_LATE_RESERVE);
+	if (fibril->stack == (void *) -1) {
 		fibril_teardown(fibril);
 		return 0;
@@ -281,5 +282,5 @@
 	context_save(&fibril->ctx);
 	context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
-	    FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), fibril->tcb);
+	    stack_size, fibril->tcb);
 
 	return (fid_t) fibril;
@@ -298,5 +299,5 @@
 	fibril_t *fibril = (fibril_t *) fid;
 	
-	free(fibril->stack);
+	as_area_destroy(fibril->stack);
 	fibril_teardown(fibril);
 }
Index: uspace/lib/c/generic/ieee_double.c
===================================================================
--- uspace/lib/c/generic/ieee_double.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/generic/ieee_double.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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 <ieee_double.h>
+
+#include <assert.h>
+
+/** Returns an easily processible description of the double val.
+ */
+ieee_double_t extract_ieee_double(double val)
+{
+	const uint64_t significand_mask = 0xfffffffffffffULL;
+	const uint64_t exponent_mask = 0x7ff0000000000000ULL;
+	const int exponent_shift = 64 - 11 - 1;
+	const uint64_t sign_mask = 0x8000000000000000ULL;
+	
+	const int special_exponent = 0x7ff;
+	const int denormal_exponent = 0;
+	const uint64_t hidden_bit = (1ULL << 52);
+	const int exponent_bias = 1075;
+
+	assert(sizeof(val) == sizeof(uint64_t));
+
+	union {
+		uint64_t num;
+		double val;
+	} bits;
+
+	bits.val = val;
+
+	/* 
+	 * Extract the binary ieee representation of the double. 
+	 * Relies on integers having the same endianness as doubles.
+	 */
+	uint64_t num = bits.num;	
+
+	ieee_double_t ret;
+
+	/* Determine the sign. */
+	ret.is_negative = ((num & sign_mask) != 0);
+
+	/* Extract the exponent. */
+	int raw_exponent = (num & exponent_mask) >> exponent_shift;
+
+	/* The extracted raw significand may not contain the hidden bit */
+	uint64_t raw_significand = num & significand_mask;
+
+	ret.is_special = (raw_exponent == special_exponent);
+
+	/* NaN or infinity */
+	if (ret.is_special) {
+		ret.is_infinity = (raw_significand == 0);
+		ret.is_nan = (raw_significand != 0);
+
+		/* These are not valid for special numbers but init them anyway. */
+		ret.is_denormal = true;
+		ret.is_accuracy_step = false;
+		ret.pos_val.significand = 0;
+		ret.pos_val.exponent = 0;
+	} else {
+		ret.is_infinity = false;
+		ret.is_nan = false;
+
+		ret.is_denormal = (raw_exponent == denormal_exponent);
+
+		/* Denormal or zero. */
+		if (ret.is_denormal) {
+			ret.pos_val.significand = raw_significand;
+			ret.pos_val.exponent = 1 - exponent_bias;
+			ret.is_accuracy_step = false;
+		} else {
+			ret.pos_val.significand = raw_significand + hidden_bit;
+			ret.pos_val.exponent = raw_exponent - exponent_bias;
+
+			/* The predecessor is closer to val than the successor 
+			 * if val is a normal value of the form 2^k (hence
+			 * raw_significand == 0) with the only exception being 
+			 * the smallest normal (raw_exponent == 1). The smallest 
+			 * normal's predecessor is the largest denormal and denormals 
+			 * do not get an extra bit of precision because their exponent 
+			 * stays the same (ie it does not decrease from k to k-1).
+			 */
+			ret.is_accuracy_step = (raw_significand == 0) && (raw_exponent != 1);
+		}
+	}
+
+	return ret;
+}
+
Index: uspace/lib/c/generic/io/log.c
===================================================================
--- uspace/lib/c/generic/io/log.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/generic/io/log.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -239,10 +239,10 @@
 
 	char *message_buffer = malloc(MESSAGE_BUFFER_SIZE);
-	if (message_buffer == NULL) {
+	if (message_buffer == NULL)
 		return;
-	}
 
 	vsnprintf(message_buffer, MESSAGE_BUFFER_SIZE, fmt, args);
 	logger_message(logger_session, ctx, level, message_buffer);
+	free(message_buffer);
 }
 
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/generic/io/printf_core.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -42,8 +42,16 @@
 #include <ctype.h>
 #include <str.h>
+#include <double_to_str.h>
+#include <ieee_double.h>
+#include <assert.h>
+#include <macros.h>
+
 
 /** show prefixes 0x or 0 */
 #define __PRINTF_FLAG_PREFIX       0x00000001
 
+/** show the decimal point even if no fractional digits present */
+#define __PRINTF_FLAG_DECIMALPT    0x00000001
+
 /** signed / unsigned number */
 #define __PRINTF_FLAG_SIGNED       0x00000002
@@ -66,4 +74,8 @@
 /** number has - sign */
 #define __PRINTF_FLAG_NEGATIVE     0x00000100
+
+/** don't print trailing zeros in the fractional part */
+#define __PRINTF_FLAG_NOFRACZEROS  0x00000200
+
 
 /**
@@ -110,4 +122,47 @@
 static const char invalch = U_SPECIAL;
 
+
+
+/** Unformatted double number string representation. */
+typedef struct {
+	/** Buffer with len digits, no sign or leading zeros. */
+	char *str;
+	/** Number of digits in str. */
+	int len;
+	/** Decimal exponent, ie number = str * 10^dec_exp */
+	int dec_exp;
+	/** True if negative. */
+	bool neg;
+} double_str_t;
+
+
+
+/** Returns the sign character or 0 if no sign should be printed. */
+static int get_sign_char(bool negative, uint32_t flags)
+{
+	if (negative) {
+		return '-';
+	} else if (flags & __PRINTF_FLAG_SHOWPLUS) {
+		return '+';
+	} else if (flags & __PRINTF_FLAG_SPACESIGN) {
+		return ' ';
+	} else {
+		return 0;
+	}
+}
+
+/** Prints count times character ch. */
+static int print_padding(char ch, int count, printf_spec_t *ps)
+{
+	for (int i = 0; i < count; ++i) {
+		if (ps->str_write(&ch, 1, ps->data) < 0) {
+			return -1;
+		}
+	}
+
+	return count;
+}
+
+
 /** Print one or more characters without adding newline.
  *
@@ -281,6 +336,7 @@
 		return printf_putstr(nullstr, ps);
 	
-	/* Print leading spaces. */
 	size_t strw = str_length(str);
+
+	/* Precision unspecified - print everything. */
 	if ((precision == 0) || (precision > strw))
 		precision = strw;
@@ -329,6 +385,7 @@
 		return printf_putstr(nullstr, ps);
 	
-	/* Print leading spaces. */
 	size_t strw = wstr_length(str);
+
+	/* Precision not specified - print everything. */
 	if ((precision == 0) || (precision > strw))
 		precision = strw;
@@ -377,4 +434,9 @@
     uint32_t flags, printf_spec_t *ps)
 {
+	/* Precision not specified. */
+	if (precision < 0) {
+		precision = 0;
+	}
+	
 	const char *digits;
 	if (flags & __PRINTF_FLAG_BIGCHARS)
@@ -525,4 +587,656 @@
 	
 	return ((int) counter);
+}
+
+/** Prints a special double (ie NaN, infinity) padded to width characters. */
+static int print_special(ieee_double_t val, int width, uint32_t flags, 
+	printf_spec_t *ps)
+{
+	assert(val.is_special);
+
+	char sign = get_sign_char(val.is_negative, flags);
+
+	const int str_len = 3;
+	const char *str;
+	
+	if (flags & __PRINTF_FLAG_BIGCHARS) {
+		str = val.is_infinity ? "INF" : "NAN";
+	} else {
+		str = val.is_infinity ? "inf" : "nan";
+	}
+
+	int padding_len = max(0, width - ((sign ? 1 : 0) + str_len));
+
+	int counter = 0;
+	int ret;
+
+	/* Leading padding. */
+	if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0)
+			return -1;
+		
+		counter += ret;
+	}
+
+	if ((ret = ps->str_write(str, str_len, ps->data)) < 0)
+		return -1;
+	
+	counter += ret;
+
+
+	/* Trailing padding. */
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+/** Trims trailing zeros but leaves a single "0" intact. */
+static void fp_trim_trailing_zeros(char *buf, int *len, int *dec_exp)
+{
+	/* Cut the zero off by adjusting the exponent. */
+	while (2 <= *len && '0' == buf[*len - 1]) {
+		--*len;
+		++*dec_exp;
+	}
+}
+
+/** Textually round up the last digit thereby eliminating it. */
+static void fp_round_up(char *buf, int *len, int *dec_exp)
+{
+	assert(1 <= *len);
+
+	char *last_digit = &buf[*len - 1];
+
+	int carry = ('5' <= *last_digit);
+
+	/* Cut the digit off by adjusting the exponent. */
+	--*len;
+	++*dec_exp;
+	--last_digit;
+
+	if (carry) {
+		/* Skip all the digits to cut off/round to zero. */
+		while (buf <= last_digit && '9' == *last_digit) {
+			--last_digit;
+		}
+
+		/* last_digit points to the last digit to round but not '9' */
+		if (buf <= last_digit) {
+			*last_digit += 1;
+			int new_len = last_digit - buf + 1;
+			*dec_exp += *len - new_len;
+			*len = new_len;
+		} else {
+			/* All len digits rounded to 0. */
+			buf[0] = '1';
+			*dec_exp += *len;
+			*len = 1;
+		}
+	} else {
+		/* The only digit was rounded to 0. */
+		if (last_digit < buf) {
+			buf[0] = '0';
+			*dec_exp = 0;
+			*len = 1;
+		}
+	}
+}
+
+
+/** Format and print the double string repressentation according 
+ *  to the %f specifier. 
+ */
+static int print_double_str_fixed(double_str_t *val_str, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	int len = val_str->len;
+	char *buf = val_str->str;
+	int dec_exp = val_str->dec_exp;
+
+	assert(0 < len);
+	assert(0 <= precision);
+	assert(0 <= dec_exp || -dec_exp <= precision);
+
+	/* Number of integral digits to print (at least leading zero). */
+	int int_len = max(1, len + dec_exp);
+
+	char sign = get_sign_char(val_str->neg, flags);
+
+	/* Fractional portion lengths. */
+	int last_frac_signif_pos = max(0, -dec_exp);
+	int leading_frac_zeros = max(0, last_frac_signif_pos - len);
+	int signif_frac_figs = min(last_frac_signif_pos, len);
+	int trailing_frac_zeros = precision - last_frac_signif_pos;
+	char *buf_frac = buf + len - signif_frac_figs;
+
+	if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+		trailing_frac_zeros = 0;
+	}
+
+	int frac_len = leading_frac_zeros + signif_frac_figs + trailing_frac_zeros;
+
+	bool has_decimal_pt = (0 < frac_len) || (flags & __PRINTF_FLAG_DECIMALPT);
+
+	/* Number of non-padding chars to print. */
+	int num_len = (sign ? 1 : 0) + int_len + (has_decimal_pt ? 1 : 0) + frac_len;
+
+	int padding_len = max(0, width - num_len);
+	int ret = 0;
+	int counter = 0;
+
+	/* Leading padding and sign. */
+
+	if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+	}
+
+	if (flags & __PRINTF_FLAG_ZEROPADDED) {
+		if ((ret = print_padding('0', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Print the intergral part of the buffer. */
+
+	int buf_int_len = min(len, len + dec_exp);
+
+	if (0 < buf_int_len) {
+		if ((ret = ps->str_write(buf, buf_int_len, ps->data)) < 0) 
+			return -1;
+
+		counter += ret;
+
+		/* Print trailing zeros of the integral part of the number. */
+		if ((ret = print_padding('0', int_len - buf_int_len, ps)) < 0) 
+			return -1;
+	} else {
+		/* Single leading integer 0. */
+		char ch = '0';
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+	}
+
+	counter += ret;
+	
+	/* Print the decimal point and the fractional part. */
+	if (has_decimal_pt) {
+		char ch = '.';
+
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+
+		/* Print leading zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', leading_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+
+		/* Print significant digits of the fractional part of the number. */
+		if (0 < signif_frac_figs) {
+			if ((ret = ps->str_write(buf_frac, signif_frac_figs, ps->data)) < 0) 
+				return -1;
+
+			counter += ret;
+		}
+
+		/* Print trailing zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Trailing padding. */
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+
+/** Convert, format and print a double according to the %f specifier. 
+ *
+ * @param g     Double to print.
+ * @param precision Number of fractional digits to print. If 0 no
+ *              decimal point will be printed unless the flag
+ *              __PRINTF_FLAG_DECIMALPT is specified.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_fixed(double g, int precision, int width, uint32_t flags, 
+	printf_spec_t *ps)
+{
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		flags &= ~__PRINTF_FLAG_ZEROPADDED;
+	}
+
+	if (flags & __PRINTF_FLAG_DECIMALPT) {
+		flags &= ~__PRINTF_FLAG_NOFRACZEROS;
+	}
+
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	double_str_t val_str;
+
+	val_str.str = buf;
+	val_str.neg = val.is_negative;
+
+	if (0 <= precision) {
+		/* 
+		 * Request one more digit so we can round the result. The last
+		 * digit it returns may have an error of at most +/- 1. 
+		 */
+		val_str.len = double_to_fixed_str(val, -1, precision + 1, buf, buf_size, 
+			&val_str.dec_exp);
+
+		/* 
+		 * Round using the last digit to produce precision fractional digits. 
+		 * If less than precision+1 fractional digits were output the last 
+		 * digit is definitely inaccurate so also round to get rid of it. 
+		 */
+		fp_round_up(buf, &val_str.len, &val_str.dec_exp);
+
+		/* Rounding could have introduced trailing zeros. */
+		if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+			fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
+		}
+	} else {
+		/* Let the implementation figure out the proper precision. */
+		val_str.len = double_to_short_str(val, buf, buf_size, &val_str.dec_exp);
+		
+		/* Precision needed for the last significant digit. */
+		precision = max(0, -val_str.dec_exp);
+	}
+
+	return print_double_str_fixed(&val_str, precision, width, flags, ps);
+}
+
+/** Prints the decimal exponent part of a %e specifier formatted number. */
+static int print_exponent(int exp_val, uint32_t flags, printf_spec_t *ps)
+{
+	int counter = 0;
+	int ret;
+
+	char exp_ch = (flags & __PRINTF_FLAG_BIGCHARS) ? 'E' : 'e';
+
+	if ((ret = ps->str_write(&exp_ch, 1, ps->data)) < 0) 
+		return -1;
+	
+	counter += ret;
+
+	char exp_sign = (exp_val < 0) ? '-' : '+';
+
+	if ((ret = ps->str_write(&exp_sign, 1, ps->data)) < 0)
+		return -1;
+
+	counter += ret;
+
+	/* Print the exponent. */
+	exp_val = abs(exp_val);
+	
+	char exp_str[4] = { 0 };
+
+	exp_str[0] = '0' + exp_val / 100;
+	exp_str[1] = '0' + (exp_val % 100) / 10 ;
+	exp_str[2] = '0' + (exp_val % 10);
+	
+	int exp_len = (exp_str[0] == '0') ? 2 : 3;
+	const char *exp_str_start = &exp_str[3] - exp_len;
+
+	if ((ret = ps->str_write(exp_str_start, exp_len, ps->data)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	return counter;
+}
+
+
+/** Format and print the double string repressentation according 
+ *  to the %e specifier. 
+ */
+static int print_double_str_scient(double_str_t *val_str, int precision, 
+	int width, uint32_t flags, printf_spec_t *ps)
+{
+	int len = val_str->len;
+	int dec_exp = val_str->dec_exp;
+	char *buf  = val_str->str;
+
+	assert(0 < len);
+
+	char sign = get_sign_char(val_str->neg, flags);
+	bool has_decimal_pt = (0 < precision) || (flags & __PRINTF_FLAG_DECIMALPT);
+	int dec_pt_len = has_decimal_pt ? 1 : 0;
+
+	/* Fractional part lengths. */
+	int signif_frac_figs = len - 1;
+	int trailing_frac_zeros = precision - signif_frac_figs;
+
+	if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+		trailing_frac_zeros = 0;
+	}
+
+	int frac_len = signif_frac_figs + trailing_frac_zeros;
+
+	int exp_val = dec_exp + len - 1;
+	/* Account for exponent sign and 'e'; minimum 2 digits. */
+	int exp_len = 2 + (abs(exp_val) >= 100 ? 3 : 2);
+
+	/* Number of non-padding chars to print. */
+	int num_len = (sign ? 1 : 0) + 1 + dec_pt_len + frac_len + exp_len;
+
+	int padding_len = max(0, width - num_len);
+	int ret = 0;
+	int counter = 0;
+
+	if (!(flags & (__PRINTF_FLAG_LEFTALIGNED | __PRINTF_FLAG_ZEROPADDED))) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	if (sign) {
+		if ((ret = ps->str_write(&sign, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+	}
+
+	if (flags & __PRINTF_FLAG_ZEROPADDED) {
+		if ((ret = print_padding('0', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Single leading integer. */
+	if ((ret = ps->str_write(buf, 1, ps->data)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	/* Print the decimal point and the fractional part. */
+	if (has_decimal_pt) {
+		char ch = '.';
+
+		if ((ret = ps->str_write(&ch, 1, ps->data)) < 0) 
+			return -1;
+		
+		counter += ret;
+
+		/* Print significant digits of the fractional part of the number. */
+		if (0 < signif_frac_figs) {
+			if ((ret = ps->str_write(buf + 1, signif_frac_figs, ps->data)) < 0) 
+				return -1;
+
+			counter += ret;
+		}
+
+		/* Print trailing zeros of the fractional part of the number. */
+		if ((ret = print_padding('0', trailing_frac_zeros, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	/* Print the exponent. */
+	if ((ret = print_exponent(exp_val, flags, ps)) < 0) 
+		return -1;
+
+	counter += ret;
+
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		if ((ret = print_padding(' ', padding_len, ps)) < 0) 
+			return -1;
+
+		counter += ret;
+	}
+
+	return counter;
+}
+
+
+/** Convert, format and print a double according to the %e specifier. 
+ *
+ * Note that if g is large, the output may be huge (3e100 prints 
+ * with at least 100 digits).
+ *
+ * %e style: [-]d.dddde+dd
+ *  left-justified:  [-]d.dddde+dd[space_pad]
+ *  right-justified: [space_pad][-][zero_pad]d.dddde+dd
+ *
+ * @param g     Double to print.
+ * @param precision Number of fractional digits to print, ie
+ *              precision + 1 significant digits to display. If 0 no
+ *              decimal point will be printed unless the flag
+ *              __PRINTF_FLAG_DECIMALPT is specified. If negative
+ *              the shortest accurate number will be printed.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_scientific(double g, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+		flags &= ~__PRINTF_FLAG_ZEROPADDED;
+	}
+
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	double_str_t val_str;
+
+	val_str.str = buf;
+	val_str.neg = val.is_negative;
+
+	if (0 <= precision) {
+		/* 
+		 * Request one more digit (in addition to the leading integer) 
+		 * so we can round the result. The last digit it returns may 
+		 * have an error of at most +/- 1. 
+		 */
+		val_str.len = double_to_fixed_str(val, precision + 2, -1, buf, buf_size, 
+			&val_str.dec_exp);
+
+		/* 
+		 * Round the extra digit to produce precision+1 significant digits. 
+		 * If less than precision+2 significant digits were returned the last 
+		 * digit is definitely inaccurate so also round to get rid of it. 
+		 */
+		fp_round_up(buf, &val_str.len, &val_str.dec_exp);
+
+		/* Rounding could have introduced trailing zeros. */
+		if (flags & __PRINTF_FLAG_NOFRACZEROS) {
+			fp_trim_trailing_zeros(buf, &val_str.len, &val_str.dec_exp);
+		}
+	} else {
+		/* Let the implementation figure out the proper precision. */
+		val_str.len = double_to_short_str(val, buf, buf_size, &val_str.dec_exp);
+		
+		/* Use all produced digits. */
+		precision = val_str.len - 1;
+	}
+
+	return print_double_str_scient(&val_str, precision, width, flags, ps);
+}
+
+
+/** Convert, format and print a double according to the %g specifier. 
+ *
+ * %g style chooses between %f and %e. 
+ *
+ * @param g     Double to print.
+ * @param precision Number of significant digits to display; excluding
+ *              any leading zeros from this count. If negative
+ *              the shortest accurate number will be printed.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double_generic(double g, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	ieee_double_t val = extract_ieee_double(g);
+
+	if (val.is_special) {
+		return print_special(val, width, flags, ps);
+	} 
+
+	char buf[MAX_DOUBLE_STR_BUF_SIZE];
+	const size_t buf_size = MAX_DOUBLE_STR_BUF_SIZE;
+	int dec_exp;
+	int len;
+
+	/* Honor the user requested number of significant digits. */
+	if (0 <= precision) {
+		/* 
+		 * Do a quick and dirty conversion of a single digit to determine 
+		 * the decimal exponent.
+		 */
+		len = double_to_fixed_str(val, 1, -1, buf, buf_size, &dec_exp);
+		assert(0 < len);
+
+		precision = max(1, precision);
+
+		if (-4 <= dec_exp && dec_exp < precision) {
+			precision = precision - (dec_exp + 1);
+			return print_double_fixed(g, precision, width, 
+				flags | __PRINTF_FLAG_NOFRACZEROS, ps);
+		} else {
+			--precision;
+			return print_double_scientific(g, precision, width, 
+				flags | __PRINTF_FLAG_NOFRACZEROS, ps);
+		}
+	} else {
+		/* Convert to get the decimal exponent and digit count.*/
+		len = double_to_short_str(val, buf, buf_size, &dec_exp);
+		assert(0 < len);
+
+		if (flags & __PRINTF_FLAG_LEFTALIGNED) {
+			flags &= ~__PRINTF_FLAG_ZEROPADDED;
+		}
+
+		double_str_t val_str;
+		val_str.str = buf;
+		val_str.len = len;
+		val_str.neg = val.is_negative;
+		val_str.dec_exp = dec_exp;
+
+		int first_digit_pos = len + dec_exp;
+		int last_digit_pos = dec_exp;
+
+		/* The whole number (15 digits max) fits between dec places 15 .. -6 */
+		if (len <= 15 && -6 <= last_digit_pos && first_digit_pos <= 15) {
+			/* Precision needed for the last significant digit. */
+			precision = max(0, -val_str.dec_exp);
+			return print_double_str_fixed(&val_str, precision, width, flags, ps);
+		} else {
+			/* Use all produced digits. */
+			precision = val_str.len - 1;
+			return print_double_str_scient(&val_str, precision, width, flags, ps);
+		}
+	}
+}
+
+
+/** Convert, format and print a double according to the specifier. 
+ *
+ * Depending on the specifier it prints the double using the styles
+ * %g, %f or %e by means of print_double_generic(), print_double_fixed(),
+ * print_double_scientific().
+ *
+ * @param g     Double to print.
+ * @param spec  Specifier of the style to print in; one of: 'g','G','f','F',
+ *              'e','E'.
+ * @param precision Number of fractional digits to display. If negative
+ *              the shortest accurate number will be printed for style %g;
+ *              negative precision defaults to 6 for styles %f, %e.
+ * @param width Minimum number of characters to display. Pads 
+ *              with '0' or ' ' depending on the set flags;
+ * @param flags Printf flags.
+ * @param ps    Printing functions.
+ *
+ * @return The number of characters printed; negative on failure.
+ */
+static int print_double(double g, char spec, int precision, int width, 
+	uint32_t flags, printf_spec_t *ps)
+{
+	switch (spec) {
+	case 'F':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'f':
+		precision = (precision < 0) ? 6 : precision;
+		return print_double_fixed(g, precision, width, flags, ps);
+
+	case 'E':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'e':
+		precision = (precision < 0) ? 6 : precision;
+		return print_double_scientific(g, precision, width, flags, ps);
+
+	case 'G':
+		flags |= __PRINTF_FLAG_BIGCHARS;
+		/* Fall through.*/
+	case 'g':
+		return print_double_generic(g, precision, width, flags, ps);
+
+	default:
+		assert(false);
+		return -1;
+	}
 }
 
@@ -656,4 +1370,5 @@
 				case '#':
 					flags |= __PRINTF_FLAG_PREFIX;
+					flags |= __PRINTF_FLAG_DECIMALPT;
 					break;
 				case '-':
@@ -701,9 +1416,10 @@
 			
 			/* Precision and '*' operator */
-			int precision = 0;
+			int precision = -1;
 			if (uc == '.') {
 				i = nxt;
 				uc = str_decode(fmt, &nxt, STR_NO_LIMIT);
 				if (isdigit(uc)) {
+					precision = 0;
 					while (true) {
 						precision *= 10;
@@ -723,6 +1439,6 @@
 					precision = (int) va_arg(ap, int);
 					if (precision < 0) {
-						/* Ignore negative precision */
-						precision = 0;
+						/* Ignore negative precision - use default instead */
+						precision = -1;
 					}
 				}
@@ -774,4 +1490,6 @@
 			 */
 			case 's':
+				precision = max(0,  precision);
+				
 				if (qualifier == PrintfQualifierLong)
 					retval = print_wstr(va_arg(ap, wchar_t *), width, precision, flags, ps);
@@ -797,4 +1515,25 @@
 					goto out;
 				};
+				
+				counter += retval;
+				j = nxt;
+				goto next_char;
+				
+			/*
+			 * Floating point values
+			 */
+			case 'G':
+			case 'g':
+			case 'F':
+			case 'f':
+			case 'E':
+			case 'e':
+				retval = print_double(va_arg(ap, double), uc, precision, 
+					width, flags, ps);
+				
+				if (retval < 0) {
+					counter = -counter;
+					goto out;
+				}
 				
 				counter += retval;
Index: uspace/lib/c/generic/power_of_ten.c
===================================================================
--- uspace/lib/c/generic/power_of_ten.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/generic/power_of_ten.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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 "private/power_of_ten.h"
+
+#include <ieee_double.h>
+#include <assert.h>
+
+/** Precomputed normalized rounded-up powers of 10^k.
+ *
+ * The powers were computed using arbitrary precision arithmetic
+ * and rounded up to the top 64 significant bits. Therefore:
+ *   10^dec_exp == significand * 2^bin_exp  +/- 0.5 ulp error
+ *
+ * The smallest interval of binary exponents computed by hand
+ * is [-1083, 987]. Add 200 (exponent change > 3 * 64 bits) 
+ * to both bounds just to be on the safe side; ie [-1283, 1187].
+ */
+static struct {
+	uint64_t significand;
+	int16_t bin_exp;
+	int16_t dec_exp;
+} fp_powers_of_10[] = {
+	{ 0xb8e1cbc28bef0b69ULL, -1286, -368 },
+	{ 0x89bf722840327f82ULL, -1259, -360 },
+	{ 0xcd42a11346f34f7dULL, -1233, -352 },
+	{ 0x98ee4a22ecf3188cULL, -1206, -344 },
+	{ 0xe3e27a444d8d98b8ULL, -1180, -336 },
+	{ 0xa9c98d8ccb009506ULL, -1153, -328 },
+	{ 0xfd00b897478238d1ULL, -1127, -320 },
+	{ 0xbc807527ed3e12bdULL, -1100, -312 },
+	{ 0x8c71dcd9ba0b4926ULL, -1073, -304 },
+	{ 0xd1476e2c07286faaULL, -1047, -296 },
+	{ 0x9becce62836ac577ULL, -1020, -288 },
+	{ 0xe858ad248f5c22caULL, -994, -280 },
+	{ 0xad1c8eab5ee43b67ULL, -967, -272 },
+	{ 0x80fa687f881c7f8eULL, -940, -264 },
+	{ 0xc0314325637a193aULL, -914, -256 },
+	{ 0x8f31cc0937ae58d3ULL, -887, -248 },
+	{ 0xd5605fcdcf32e1d7ULL, -861, -240 },
+	{ 0x9efa548d26e5a6e2ULL, -834, -232 },
+	{ 0xece53cec4a314ebeULL, -808, -224 },
+	{ 0xb080392cc4349dedULL, -781, -216 },
+	{ 0x8380dea93da4bc60ULL, -754, -208 },
+	{ 0xc3f490aa77bd60fdULL, -728, -200 },
+	{ 0x91ff83775423cc06ULL, -701, -192 },
+	{ 0xd98ddaee19068c76ULL, -675, -184 },
+	{ 0xa21727db38cb0030ULL, -648, -176 },
+	{ 0xf18899b1bc3f8ca2ULL, -622, -168 },
+	{ 0xb3f4e093db73a093ULL, -595, -160 },
+	{ 0x8613fd0145877586ULL, -568, -152 },
+	{ 0xc7caba6e7c5382c9ULL, -542, -144 },
+	{ 0x94db483840b717f0ULL, -515, -136 },
+	{ 0xddd0467c64bce4a1ULL, -489, -128 },
+	{ 0xa54394fe1eedb8ffULL, -462, -120 },
+	{ 0xf64335bcf065d37dULL, -436, -112 },
+	{ 0xb77ada0617e3bbcbULL, -409, -104 },
+	{ 0x88b402f7fd75539bULL, -382, -96 },
+	{ 0xcbb41ef979346bcaULL, -356, -88 },
+	{ 0x97c560ba6b0919a6ULL, -329, -80 },
+	{ 0xe2280b6c20dd5232ULL, -303, -72 },
+	{ 0xa87fea27a539e9a5ULL, -276, -64 },
+	{ 0xfb158592be068d2fULL, -250, -56 },
+	{ 0xbb127c53b17ec159ULL, -223, -48 },
+	{ 0x8b61313bbabce2c6ULL, -196, -40 },
+	{ 0xcfb11ead453994baULL, -170, -32 },
+	{ 0x9abe14cd44753b53ULL, -143, -24 },
+	{ 0xe69594bec44de15bULL, -117, -16 },
+	{ 0xabcc77118461cefdULL, -90, -8 },
+	{ 0x8000000000000000ULL, -63, 0 },
+	{ 0xbebc200000000000ULL, -37, 8 },
+	{ 0x8e1bc9bf04000000ULL, -10, 16 },
+	{ 0xd3c21bcecceda100ULL, 16, 24 },
+	{ 0x9dc5ada82b70b59eULL, 43, 32 },
+	{ 0xeb194f8e1ae525fdULL, 69, 40 },
+	{ 0xaf298d050e4395d7ULL, 96, 48 },
+	{ 0x82818f1281ed44a0ULL, 123, 56 },
+	{ 0xc2781f49ffcfa6d5ULL, 149, 64 },
+	{ 0x90e40fbeea1d3a4bULL, 176, 72 },
+	{ 0xd7e77a8f87daf7fcULL, 202, 80 },
+	{ 0xa0dc75f1778e39d6ULL, 229, 88 },
+	{ 0xefb3ab16c59b14a3ULL, 255, 96 },
+	{ 0xb2977ee300c50fe7ULL, 282, 104 },
+	{ 0x850fadc09923329eULL, 309, 112 },
+	{ 0xc646d63501a1511eULL, 335, 120 },
+	{ 0x93ba47c980e98ce0ULL, 362, 128 },
+	{ 0xdc21a1171d42645dULL, 388, 136 },
+	{ 0xa402b9c5a8d3a6e7ULL, 415, 144 },
+	{ 0xf46518c2ef5b8cd1ULL, 441, 152 },
+	{ 0xb616a12b7fe617aaULL, 468, 160 },
+	{ 0x87aa9aff79042287ULL, 495, 168 },
+	{ 0xca28a291859bbf93ULL, 521, 176 },
+	{ 0x969eb7c47859e744ULL, 548, 184 },
+	{ 0xe070f78d3927556bULL, 574, 192 },
+	{ 0xa738c6bebb12d16dULL, 601, 200 },
+	{ 0xf92e0c3537826146ULL, 627, 208 },
+	{ 0xb9a74a0637ce2ee1ULL, 654, 216 },
+	{ 0x8a5296ffe33cc930ULL, 681, 224 },
+	{ 0xce1de40642e3f4b9ULL, 707, 232 },
+	{ 0x9991a6f3d6bf1766ULL, 734, 240 },
+	{ 0xe4d5e82392a40515ULL, 760, 248 },
+	{ 0xaa7eebfb9df9de8eULL, 787, 256 },
+	{ 0xfe0efb53d30dd4d8ULL, 813, 264 },
+	{ 0xbd49d14aa79dbc82ULL, 840, 272 },
+	{ 0x8d07e33455637eb3ULL, 867, 280 },
+	{ 0xd226fc195c6a2f8cULL, 893, 288 },
+	{ 0x9c935e00d4b9d8d2ULL, 920, 296 },
+	{ 0xe950df20247c83fdULL, 946, 304 },
+	{ 0xadd57a27d29339f6ULL, 973, 312 },
+	{ 0x81842f29f2cce376ULL, 1000, 320 },
+	{ 0xc0fe908895cf3b44ULL, 1026, 328 },
+	{ 0x8fcac257558ee4e6ULL, 1053, 336 },
+	{ 0xd6444e39c3db9b0aULL, 1079, 344 },
+	{ 0x9fa42700db900ad2ULL, 1106, 352 },
+	{ 0xede24ae798ec8284ULL, 1132, 360 },
+	{ 0xb13cc3832ef0c9acULL, 1159, 368 },
+	{ 0x840d57e2899d945fULL, 1186, 376 }
+};
+
+
+/** 
+ * Returns the smallest precomputed power of 10 such that 
+ *  binary_exp <= power_of_10.bin_exp
+ * where
+ *  10^decimal_exp = power_of_10.significand * 2^bin_exp 
+ * with an error of 0.5 ulp in the significand.
+ */
+void get_power_of_ten(int binary_exp, fp_num_t *power_of_10, int *decimal_exp)
+{
+	const int powers_count = sizeof(fp_powers_of_10) / sizeof(fp_powers_of_10[0]);
+	const int min_bin_exp = fp_powers_of_10[0].bin_exp;
+	const int max_bin_exp = fp_powers_of_10[powers_count - 1].bin_exp;
+	const int max_bin_exp_diff = 27;
+
+	assert(min_bin_exp <= binary_exp && binary_exp <= max_bin_exp);
+
+	/* 
+	 * Binary exponent difference between adjacent powers of 10 
+	 * is lg(10^8) = 26.575. The starting search index seed_idx
+	 * undershoots the actual position by less than 1.6%, ie it
+	 * skips 26.575/27 = 98.4% of all the smaller powers. This
+	 * translates to at most three extra tests. 
+	 */
+	int seed_idx = (binary_exp - min_bin_exp) / max_bin_exp_diff;
+
+	assert(fp_powers_of_10[seed_idx].bin_exp < binary_exp);
+
+	for (int i = seed_idx; i < powers_count; ++i) {
+		/* Found the smallest power of 10 with bin_exp >= binary_exp. */
+		if (binary_exp <= fp_powers_of_10[i].bin_exp) {
+			assert(fp_powers_of_10[i].bin_exp <= binary_exp + max_bin_exp_diff);
+
+			power_of_10->significand = fp_powers_of_10[i].significand;
+			power_of_10->exponent = fp_powers_of_10[i].bin_exp;
+			*decimal_exp = fp_powers_of_10[i].dec_exp;
+			return;
+		}
+	}
+
+	assert(false);
+}
+
Index: uspace/lib/c/generic/private/power_of_ten.h
===================================================================
--- uspace/lib/c/generic/private/power_of_ten.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/generic/private/power_of_ten.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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.
+ */
+
+#ifndef POWER_OF_TEN_H_
+#define POWER_OF_TEN_H_
+
+/* Fwd decl. */
+struct fp_num_t_tag;
+
+extern void get_power_of_ten(int, struct fp_num_t_tag *, int *);
+
+#endif
Index: uspace/lib/c/generic/stack.c
===================================================================
--- uspace/lib/c/generic/stack.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/generic/stack.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <stack.h>
+#include <sysinfo.h>
+
+size_t stack_size_get(void)
+{
+	static sysarg_t stack_size = 0;
+
+	if (!stack_size)
+		sysinfo_get_value("default.stack_size", &stack_size);
+
+	return (size_t) stack_size;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/thread.c
===================================================================
--- uspace/lib/c/generic/thread.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/generic/thread.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -39,4 +39,5 @@
 #include <abi/proc/uarg.h>
 #include <fibril.h>
+#include <stack.h>
 #include <str.h>
 #include <async.h>
@@ -44,8 +45,4 @@
 #include <as.h>
 #include "private/thread.h"
-
-#ifndef THREAD_INITIAL_STACK_PAGES
-	#define THREAD_INITIAL_STACK_PAGES  2
-#endif
 
 /** Main thread function.
@@ -101,7 +98,8 @@
 		return ENOMEM;
 	
-	size_t stack_size = getpagesize() * THREAD_INITIAL_STACK_PAGES;
+	size_t stack_size = stack_size_get();
 	void *stack = as_area_create(AS_AREA_ANY, stack_size,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD |
+	    AS_AREA_LATE_RESERVE);
 	if (stack == AS_MAP_FAILED) {
 		free(uarg);
Index: uspace/lib/c/include/double_to_str.h
===================================================================
--- uspace/lib/c/include/double_to_str.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/include/double_to_str.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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.
+ */
+
+#ifndef DOUBLE_TO_STR_H_
+#define DOUBLE_TO_STR_H_
+
+#include <unistd.h>
+
+/** Maximum number of digits double_to_*_str conversion functions produce. 
+ *
+ * Both double_to_short_str and double_to_fixed_str generate digits out
+ * of a 64bit unsigned int number representation. The max number of 
+ * of digits is therefore 20. Add 1 to help users who forget to reserve
+ * space for a null terminator.
+ */
+#define MAX_DOUBLE_STR_LEN (20 + 1)
+
+/** Maximum buffer size needed to store the output of double_to_*_str 
+ *  functions. 
+ */
+#define MAX_DOUBLE_STR_BUF_SIZE  21
+
+/* Fwd decl.*/
+struct ieee_double_t_tag;
+
+extern int double_to_short_str(struct ieee_double_t_tag, char *, size_t, int *);
+extern int double_to_fixed_str(struct ieee_double_t_tag, int, int, char *,
+    size_t, int *);
+
+#endif 
Index: uspace/lib/c/include/ieee_double.h
===================================================================
--- uspace/lib/c/include/ieee_double.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/include/ieee_double.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012 Adam Hraska
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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.
+ */
+
+#ifndef IEEE_DOUBLE_H_
+#define IEEE_DOUBLE_H_
+
+#include <stdint.h>
+#include <bool.h>
+
+/** Represents a non-negative floating point number: significand * 2^exponent */
+typedef struct fp_num_t_tag {
+	/** Significand (aka mantissa). */
+	uint64_t significand;
+	/** Binary exponent. */
+	int exponent;
+} fp_num_t;
+
+/** Double number description according to IEEE 754. */
+typedef struct ieee_double_t_tag {
+	/** The number is a NaN or infinity. */
+	bool is_special;
+	/** Not a number. */
+	bool is_nan;
+	bool is_negative;
+	/** The number denoted infinity. */
+	bool is_infinity;
+	/** The number could not be represented as a normalized double. */
+	bool is_denormal;
+	/**
+	 * The predecessor double is closer than the successor. This happens 
+	 * if a normal number is of the form 2^k and it is not the smallest
+	 * normal number. 
+	 */
+	bool is_accuracy_step;
+	/** 
+	 * If !is_special the double's value is:
+	 *   pos_val.significand * 2^pos_val.exponent
+	 */
+	fp_num_t pos_val;
+} ieee_double_t;
+
+extern ieee_double_t extract_ieee_double(double);
+
+#endif
Index: uspace/lib/c/include/macros.h
===================================================================
--- uspace/lib/c/include/macros.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/c/include/macros.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -38,4 +38,6 @@
 #define min(a, b)  ((a) < (b) ? (a) : (b))
 #define max(a, b)  ((a) > (b) ? (a) : (b))
+#define abs(a)     ((a) >= 0 ? (a) : (-a))
+
 
 #define KiB2SIZE(kb)  ((kb) << 10)
Index: uspace/lib/c/include/stack.h
===================================================================
--- uspace/lib/c/include/stack.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
+++ uspace/lib/c/include/stack.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_STACK_H_
+#define LIBC_STACK_H_
+
+#include <libarch/types.h>
+
+extern size_t stack_size_get(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/clui/tinput.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -104,5 +104,7 @@
 static void tinput_display_tail(tinput_t *ti, size_t start, size_t pad)
 {
-	wchar_t dbuf[INPUT_MAX_SIZE + 1];
+	wchar_t *dbuf = malloc((INPUT_MAX_SIZE + 1) * sizeof(wchar_t));
+	if (!dbuf)
+		return;	
 	
 	size_t sa;
@@ -146,4 +148,6 @@
 	
 	console_flush(ti->console);
+
+	free(dbuf);
 }
 
Index: pace/lib/ext2/Makefile
===================================================================
--- uspace/lib/ext2/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,43 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# Copyright (c) 2010 Martin Sucha
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - 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.
-# - 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.
-#
-
-USPACE_PREFIX = ../..
-LIBRARY = libext2
-EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a
-
-SOURCES = \
-	libext2_filesystem.c \
-	libext2_superblock.c \
-	libext2_block_group.c \
-	libext2_inode.c \
-	libext2_directory.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/lib/ext2/libext2.h
===================================================================
--- uspace/lib/ext2/libext2.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_H_
-#define LIBEXT2_LIBEXT2_H_
-
-#include "libext2_superblock.h"
-#include "libext2_block_group.h"
-#include "libext2_inode.h"
-#include "libext2_filesystem.h"
-#include "libext2_directory.h"
-
-#endif
-
-/** @}
- */
Index: pace/lib/ext2/libext2_block_group.c
===================================================================
--- uspace/lib/ext2/libext2_block_group.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#include "libext2.h"
-#include "libext2_block_group.h"
-#include <byteorder.h>
-
-/**
- * Get block ID corresponding to the block bitmap of this block group
- * 
- * @param bg pointer to block group descriptor
- */
-uint32_t ext2_block_group_get_block_bitmap_block(ext2_block_group_t *bg)
-{
-	return uint32_t_le2host(bg->block_bitmap_block);
-}
-
-/**
- * Get block ID corresponding to the inode bitmap of this block group
- * 
- * @param bg pointer to block group descriptor
- */
-uint32_t ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *bg)
-{
-	return uint32_t_le2host(bg->inode_bitmap_block);
-}
-
-/**
- * Get block ID of first block in inode table
- * 
- * @param bg pointer to block group descriptor
- */
-uint32_t ext2_block_group_get_inode_table_first_block(ext2_block_group_t *bg)
-{
-	return uint32_t_le2host(bg->inode_table_first_block);
-}
-
-/**
- * Get amount of free blocks in this block group
- * 
- * @param bg pointer to block group descriptor
- */
-uint16_t ext2_block_group_get_free_block_count(ext2_block_group_t *bg)
-{
-	return uint16_t_le2host(bg->free_block_count);
-}
-
-/**
- * Set amount of free blocks in this block group
- * 
- * @param bg pointer to block group descriptor
- * @param val new value
- */
-void ext2_block_group_set_free_block_count(ext2_block_group_t *bg,
-	uint16_t val)
-{
-	bg->free_block_count = host2uint16_t_le(val);
-}
-
-/**
- * Get amount of free inodes in this block group
- * 
- * @param bg pointer to block group descriptor
- */
-uint16_t ext2_block_group_get_free_inode_count(ext2_block_group_t *bg)
-{
-	return uint16_t_le2host(bg->free_inode_count);
-}
-
-/**
- * Get amount of inodes allocated for directories
- * 
- * @param bg pointer to block group descriptor
- */
-uint16_t ext2_block_group_get_directory_inode_count(ext2_block_group_t *bg)
-{
-	return uint16_t_le2host(bg->directory_inode_count);
-}
-
-
-/** @}
- */
Index: pace/lib/ext2/libext2_block_group.h
===================================================================
--- uspace/lib/ext2/libext2_block_group.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
-#define LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
-
-#include <block.h>
-
-typedef struct ext2_block_group {
-	uint32_t block_bitmap_block; // Block ID for block bitmap
-	uint32_t inode_bitmap_block; // Block ID for inode bitmap
-	uint32_t inode_table_first_block; // Block ID of first block of inode table 
-	uint16_t free_block_count; // Count of free blocks
-	uint16_t free_inode_count; // Count of free inodes
-	uint16_t directory_inode_count; // Number of inodes allocated to directories
-} ext2_block_group_t;
-
-typedef struct ext2_block_group_ref {
-	block_t *block; // Reference to a block containing this block group descr
-	ext2_block_group_t *block_group;
-} ext2_block_group_ref_t;
-
-#define EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE 32
-
-extern uint32_t	ext2_block_group_get_block_bitmap_block(ext2_block_group_t *);
-extern uint32_t	ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *);
-extern uint32_t	ext2_block_group_get_inode_table_first_block(ext2_block_group_t *);
-extern uint16_t	ext2_block_group_get_free_block_count(ext2_block_group_t *);
-extern uint16_t	ext2_block_group_get_free_inode_count(ext2_block_group_t *);
-extern uint16_t	ext2_block_group_get_directory_inode_count(ext2_block_group_t *);
-
-extern void	ext2_block_group_set_free_block_count(ext2_block_group_t *, uint16_t);
-
-#endif
-
-/** @}
- */
Index: pace/lib/ext2/libext2_directory.c
===================================================================
--- uspace/lib/ext2/libext2_directory.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,256 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#include "libext2.h"
-#include "libext2_directory.h"
-#include <byteorder.h>
-#include <errno.h>
-#include <assert.h>
-
-static int ext2_directory_iterator_set(ext2_directory_iterator_t *it,
-    uint32_t block_size);
-
-/**
- * Get inode number for the directory entry
- * 
- * @param de pointer to linked list directory entry
- */
-uint32_t ext2_directory_entry_ll_get_inode(ext2_directory_entry_ll_t *de)
-{
-	return uint32_t_le2host(de->inode);
-}
-
-/**
- * Get length of the directory entry
- * 
- * @param de pointer to linked list directory entry
- */
-uint16_t ext2_directory_entry_ll_get_entry_length(
-    ext2_directory_entry_ll_t *de)
-{
-	return uint16_t_le2host(de->entry_length);
-}
-
-/**
- * Get length of the name stored in the directory entry
- * 
- * @param de pointer to linked list directory entry
- */
-uint16_t ext2_directory_entry_ll_get_name_length(
-    ext2_superblock_t *sb, ext2_directory_entry_ll_t *de)
-{
-	if (ext2_superblock_get_rev_major(sb) == 0 &&
-	    ext2_superblock_get_rev_minor(sb) < 5) {
-		return ((uint16_t)de->name_length_high) << 8 | 
-		    ((uint16_t)de->name_length);
-	}
-	return de->name_length;
-}
-
-/**
- * Initialize a directory iterator
- * 
- * @param it pointer to iterator to initialize
- * @param fs pointer to filesystem structure
- * @param inode pointer to inode reference structure
- * @param pos position within inode to start at, 0 is the first entry
- * @return EOK on success or negative error code on failure
- */
-int ext2_directory_iterator_init(ext2_directory_iterator_t *it,
-    ext2_filesystem_t *fs, ext2_inode_ref_t *inode_ref, aoff64_t pos)
-{	
-	it->inode_ref = inode_ref;
-	it->fs = fs;
-	it->current = NULL;
-	it->current_offset = 0;
-	it->current_block = NULL;
-	
-	return ext2_directory_iterator_seek(it, pos);
-}
-
-/**
- * Advance the directory iterator to the next entry
- * 
- * @param it pointer to iterator to initialize
- * @return EOK on success or negative error code on failure
- */
-int ext2_directory_iterator_next(ext2_directory_iterator_t *it)
-{
-	uint16_t skip;
-	
-	assert(it->current != NULL);
-	
-	skip = ext2_directory_entry_ll_get_entry_length(it->current);
-	
-	return ext2_directory_iterator_seek(it, it->current_offset + skip);
-}
-
-/**
- * Seek the directory iterator to the given byte offset within the inode.
- * 
- * @param it pointer to iterator to initialize
- * @return EOK on success or negative error code on failure
- */
-int ext2_directory_iterator_seek(ext2_directory_iterator_t *it, aoff64_t pos)
-{
-	int rc;
-	
-	uint64_t size;
-	aoff64_t current_block_idx;
-	aoff64_t next_block_idx;
-	uint32_t next_block_phys_idx;
-	uint32_t block_size;
-	
-	size = ext2_inode_get_size(it->fs->superblock, it->inode_ref->inode);
-	
-	/* The iterator is not valid until we seek to the desired position */
-	it->current = NULL;
-	
-	/* Are we at the end? */
-	if (pos >= size) {		
-		if (it->current_block) {
-			rc = block_put(it->current_block);
-			it->current_block = NULL;
-			if (rc != EOK) {
-				return rc;
-			}
-		}
-		
-		it->current_offset = pos;
-		return EOK;
-	}
-	
-	block_size = ext2_superblock_get_block_size(it->fs->superblock);
-	current_block_idx = it->current_offset / block_size;
-	next_block_idx = pos / block_size;
-	
-	/* If we don't have a block or are moving accross block boundary,
-	 * we need to get another block
-	 */
-	if (it->current_block == NULL || current_block_idx != next_block_idx) {		
-		if (it->current_block) {
-			rc = block_put(it->current_block);
-			it->current_block = NULL;
-			if (rc != EOK) {
-				return rc;
-			}
-		}
-		
-		rc = ext2_filesystem_get_inode_data_block_index(it->fs,
-		    it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
-		if (rc != EOK) {
-			return rc;
-		}
-		
-		rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
-		    BLOCK_FLAGS_NONE);
-		if (rc != EOK) {
-			it->current_block = NULL;
-			return rc;
-		}
-	}
-	
-	it->current_offset = pos;
-	return ext2_directory_iterator_set(it, block_size);
-}
-
-/** Setup the entry at the current iterator offset.
- * 
- * This function checks the validity of the directory entry,
- * before setting the data pointer.
- *
- * @return EOK on success or error code on failure 
- */
-static int ext2_directory_iterator_set(ext2_directory_iterator_t *it,
-    uint32_t block_size)
-{
-	uint32_t offset_in_block = it->current_offset % block_size;
-	
-	it->current = NULL;
-	
-	/* Ensure proper alignment */
-	if ((offset_in_block % 4) != 0) {
-		return EIO;
-	}
-	
-	/* Ensure that the core of the entry does not overflow the block */
-	if (offset_in_block > block_size - 8) {
-		return EIO;
-	}
-	
-	ext2_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
-	
-	/* Ensure that the whole entry does not overflow the block */
-	uint16_t length = ext2_directory_entry_ll_get_entry_length(entry);
-	if (offset_in_block + length > block_size) {
-		return EIO;
-	}
-	
-	/* Ensure the name length is not too large */
-	if (ext2_directory_entry_ll_get_name_length(it->fs->superblock, 
-	    entry) > length-8) {
-		return EIO;
-	}
-	
-	it->current = entry;
-	return EOK;
-}
-
-/**
- * Release all resources asociated with the directory iterator
- * 
- * @param it pointer to iterator to initialize
- * @return EOK on success or negative error code on failure
- */
-int ext2_directory_iterator_fini(ext2_directory_iterator_t *it)
-{
-	int rc;
-	
-	it->fs = NULL;
-	it->inode_ref = NULL;
-	it->current = NULL;
-	
-	if (it->current_block) {
-		rc = block_put(it->current_block);
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-	
-	return EOK;
-}
-
-/** @}
- */
Index: pace/lib/ext2/libext2_directory.h
===================================================================
--- uspace/lib/ext2/libext2_directory.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_DIRECTORY_H_
-#define LIBEXT2_LIBEXT2_DIRECTORY_H_
-
-#include <block.h>
-#include "libext2_filesystem.h"
-#include "libext2_inode.h"
-
-/**
- * Linked list directory entry structure
- */
-typedef struct ext2_directory_entry_ll {
-	uint32_t inode; // Inode for the entry
-	uint16_t entry_length; // Distance to the next directory entry
-	uint8_t name_length; // Lower 8 bits of name length
-	union {
-		uint8_t name_length_high; // Higher 8 bits of name length
-		uint8_t inode_type; // Type of referenced inode (in rev >= 0.5)
-	} __attribute__ ((packed));
-	uint8_t name; // First byte of name, if present
-} __attribute__ ((packed)) ext2_directory_entry_ll_t;
-
-typedef struct ext2_directory_iterator {
-	ext2_filesystem_t *fs;
-	ext2_inode_ref_t *inode_ref;
-	block_t *current_block;
-	aoff64_t current_offset;
-	ext2_directory_entry_ll_t *current;
-} ext2_directory_iterator_t;
-
-
-extern uint32_t	ext2_directory_entry_ll_get_inode(ext2_directory_entry_ll_t *);
-extern uint16_t	ext2_directory_entry_ll_get_entry_length(
-    ext2_directory_entry_ll_t *);
-extern uint16_t	ext2_directory_entry_ll_get_name_length(
-    ext2_superblock_t *, ext2_directory_entry_ll_t *);
-
-extern int ext2_directory_iterator_init(ext2_directory_iterator_t *,
-    ext2_filesystem_t *, ext2_inode_ref_t *, aoff64_t);
-extern int ext2_directory_iterator_next(ext2_directory_iterator_t *);
-extern int ext2_directory_iterator_seek(ext2_directory_iterator_t *, aoff64_t pos);
-extern int ext2_directory_iterator_fini(ext2_directory_iterator_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,532 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#include "libext2_filesystem.h"
-#include "libext2_superblock.h"
-#include "libext2_block_group.h"
-#include "libext2_inode.h"
-#include <errno.h>
-#include <block.h>
-#include <malloc.h>
-#include <assert.h>
-#include <byteorder.h>
-
-/**
- * Initialize an instance of filesystem on the device.
- * This function reads superblock from the device and
- * initializes libblock cache with appropriate logical block size.
- * 
- * @param fs			Pointer to ext2_filesystem_t to initialize
- * @param service_id	Service ID of the block device
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_init(ext2_filesystem_t *fs, service_id_t service_id)
-{
-	int rc;
-	ext2_superblock_t *temp_superblock;
-	size_t block_size;
-	
-	fs->device = service_id;
-	
-	rc = block_init(EXCHANGE_SERIALIZE, fs->device, 2048);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	rc = ext2_superblock_read_direct(fs->device, &temp_superblock);
-	if (rc != EOK) {
-		block_fini(fs->device);
-		return rc;
-	}
-	
-	block_size = ext2_superblock_get_block_size(temp_superblock);
-	
-	if (block_size > EXT2_MAX_BLOCK_SIZE) {
-		block_fini(fs->device);
-		return ENOTSUP;
-	}
-	
-	rc = block_cache_init(service_id, block_size, 0, CACHE_MODE_WT);
-	if (rc != EOK) {
-		block_fini(fs->device);
-		return rc;
-	}
-	
-	fs->superblock = temp_superblock;
-	
-	return EOK; 
-}
-
-/**
- * Check filesystem for sanity
- * 
- * @param fs			Pointer to ext2_filesystem_t to check
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_check_sanity(ext2_filesystem_t *fs)
-{
-	int rc;
-	
-	rc = ext2_superblock_check_sanity(fs->superblock);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/**
- * Check feature flags
- * 
- * @param fs Pointer to ext2_filesystem_t to check
- * @param read_only bool to set to true if the fs needs to be read-only
- * @return EOK on success or negative error code on failure
- */
-int ext2_filesystem_check_flags(ext2_filesystem_t *fs, bool *o_read_only)
-{
-	/* feature flags are present in rev 1 and later */
-	if (ext2_superblock_get_rev_major(fs->superblock) == 0) {
-		*o_read_only = false;
-		return EOK;
-	}
-	
-	uint32_t incompatible;
-	uint32_t read_only;
-	
-	incompatible = ext2_superblock_get_features_incompatible(fs->superblock);
-	read_only = ext2_superblock_get_features_read_only(fs->superblock);
-	
-	/* check whether we support all features
-	 * first unset any supported feature flags
-	 * and see whether any unspported feature remains */
-	incompatible &= ~EXT2_SUPPORTED_INCOMPATIBLE_FEATURES;
-	read_only &= ~EXT2_SUPPORTED_READ_ONLY_FEATURES;
-	
-	if (incompatible > 0) {
-		*o_read_only = true;
-		return ENOTSUP;
-	}
-	
-	if (read_only > 0) {
-		*o_read_only = true;
-	}
-	
-	return EOK;
-}
-
-/**
- * Get a reference to block descriptor
- * 
- * @param fs Pointer to filesystem information
- * @param bgid Index of block group to find
- * @param ref Pointer where to store pointer to block group reference
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *fs, uint32_t bgid,
-    ext2_block_group_ref_t **ref)
-{
-	int rc;
-	aoff64_t block_id;
-	uint32_t descriptors_per_block;
-	size_t offset;
-	ext2_block_group_ref_t *newref;
-	
-	newref = malloc(sizeof(ext2_block_group_ref_t));
-	if (newref == NULL) {
-		return ENOMEM;
-	}
-	
-	descriptors_per_block = ext2_superblock_get_block_size(fs->superblock)
-	    / EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
-	
-	/* Block group descriptor table starts at the next block after superblock */
-	block_id = ext2_superblock_get_first_block(fs->superblock) + 1;
-	
-	/* Find the block containing the descriptor we are looking for */
-	block_id += bgid / descriptors_per_block;
-	offset = (bgid % descriptors_per_block) * EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
-	
-	rc = block_get(&newref->block, fs->device, block_id, 0);
-	if (rc != EOK) {
-		free(newref);
-		return rc;
-	}
-	
-	newref->block_group = newref->block->data + offset;
-	
-	*ref = newref;
-	
-	return EOK;
-}
-
-/**
- * Free a reference to block group
- * 
- * @param ref Pointer to block group reference to free
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *ref)
-{
-	int rc;
-	
-	rc = block_put(ref->block);
-	free(ref);
-	
-	return rc;
-}
-
-/**
- * Get a reference to inode
- * 
- * @param fs Pointer to filesystem information
- * @param index The index number of the inode
- * @param ref Pointer where to store pointer to inode reference
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_get_inode_ref(ext2_filesystem_t *fs, uint32_t index,
-    ext2_inode_ref_t **ref)
-{
-	int rc;
-	aoff64_t block_id;
-	uint32_t block_group;
-	uint32_t offset_in_group;
-	uint32_t byte_offset_in_group;
-	size_t offset_in_block;
-	uint32_t inodes_per_group;
-	uint32_t inode_table_start;
-	uint16_t inode_size;
-	uint32_t block_size;
-	ext2_block_group_ref_t *bg_ref;
-	ext2_inode_ref_t *newref;
-	
-	newref = malloc(sizeof(ext2_inode_ref_t));
-	if (newref == NULL) {
-		return ENOMEM;
-	}
-	
-	inodes_per_group = ext2_superblock_get_inodes_per_group(fs->superblock);
-	
-	/* inode numbers are 1-based, but it is simpler to work with 0-based
-	 * when computing indices
-	 */
-	index -= 1;
-	block_group = index / inodes_per_group;
-	offset_in_group = index % inodes_per_group;
-	
-	rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
-	if (rc != EOK) {
-		free(newref);
-		return rc;
-	}
-	
-	inode_table_start = ext2_block_group_get_inode_table_first_block(
-	    bg_ref->block_group);
-	
-	rc = ext2_filesystem_put_block_group_ref(bg_ref);
-	if (rc != EOK) {
-		free(newref);
-		return rc;
-	}
-
-	inode_size = ext2_superblock_get_inode_size(fs->superblock);
-	block_size = ext2_superblock_get_block_size(fs->superblock);
-	
-	byte_offset_in_group = offset_in_group * inode_size;
-	
-	block_id = inode_table_start + (byte_offset_in_group / block_size);
-	offset_in_block = byte_offset_in_group % block_size;
-	
-	rc = block_get(&newref->block, fs->device, block_id, 0);
-	if (rc != EOK) {
-		free(newref);
-		return rc;
-	}
-	
-	newref->inode = newref->block->data + offset_in_block;
-	/* we decremented index above, but need to store the original value
-	 * in the reference
-	 */
-	newref->index = index+1;
-	
-	*ref = newref;
-	
-	return EOK;
-}
-
-/**
- * Free a reference to inode
- * 
- * @param ref Pointer to inode reference to free
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *ref)
-{
-	int rc;
-	
-	rc = block_put(ref->block);
-	free(ref);
-	
-	return rc;
-}
-
-/**
- * Find a filesystem block number where iblock-th data block
- * of the given inode is located.
- * 
- * @param fblock the number of filesystem block, or 0 if no such block is allocated yet
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *fs, ext2_inode_t* inode,
-    aoff64_t iblock, uint32_t* fblock)
-{
-	int rc;
-	aoff64_t limits[4];
-	uint32_t block_ids_per_block;
-	aoff64_t blocks_per_level[4];
-	uint32_t offset_in_block;
-	uint32_t current_block;
-	aoff64_t block_offset_in_level;
-	int i;
-	int level;
-	block_t *block;
-	
-	/* Handle simple case when we are dealing with direct reference */ 
-	if (iblock < EXT2_INODE_DIRECT_BLOCKS) {
-		current_block = ext2_inode_get_direct_block(inode, (uint32_t)iblock);
-		*fblock = current_block;
-		return EOK;
-	}
-	
-	/* Compute limits for indirect block levels
-	 * TODO: compute this once when loading filesystem and store in ext2_filesystem_t
-	 */
-	block_ids_per_block = ext2_superblock_get_block_size(fs->superblock) / sizeof(uint32_t);
-	limits[0] = EXT2_INODE_DIRECT_BLOCKS;
-	blocks_per_level[0] = 1;
-	for (i = 1; i < 4; i++) {
-		blocks_per_level[i]  = blocks_per_level[i-1] *
-		    block_ids_per_block;
-		limits[i] = limits[i-1] + blocks_per_level[i];
-	}
-	
-	/* Determine the indirection level needed to get the desired block */
-	level = -1;
-	for (i = 1; i < 4; i++) {
-		if (iblock < limits[i]) {
-			level = i;
-			break;
-		}
-	}
-	
-	if (level == -1) {
-		return EIO;
-	}
-	
-	/* Compute offsets for the topmost level */
-	block_offset_in_level = iblock - limits[level-1];
-	current_block = ext2_inode_get_indirect_block(inode, level-1);
-	offset_in_block = block_offset_in_level / blocks_per_level[level-1];
-	
-	/* Navigate through other levels, until we find the block number
-	 * or find null reference meaning we are dealing with sparse file
-	 */
-	while (level > 0) {
-		rc = block_get(&block, fs->device, current_block, 0);
-		if (rc != EOK) {
-			return rc;
-		}
-		
-		assert(offset_in_block < block_ids_per_block);
-		current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
-		
-		rc = block_put(block);
-		if (rc != EOK) {
-			return rc;
-		}
-		
-		if (current_block == 0) {
-			/* This is a sparse file */
-			*fblock = 0;
-			return EOK;
-		}
-		
-		level -= 1;
-		
-		/* If we are on the last level, break here as
-		 * there is no next level to visit
-		 */
-		if (level == 0) {
-			break;
-		}
-		
-		/* Visit the next level */
-		block_offset_in_level %= blocks_per_level[level];
-		offset_in_block = block_offset_in_level / blocks_per_level[level-1];
-	}
-	
-	*fblock = current_block;
-	
-	return EOK;
-}
-
-/**
- * Allocate a given number of blocks and store their ids in blocks
- * 
- * @todo TODO: This function is not finished and really has never been
- *             used (and tested) yet
- * 
- * @param fs pointer to filesystem
- * @param blocks array of count uint32_t values where store block ids
- * @param count number of blocks to allocate and elements in blocks array
- * @param preferred_bg preferred block group number
- * 
- * @return 		EOK on success or negative error code on failure
- */
-int ext2_filesystem_allocate_blocks(ext2_filesystem_t *fs, uint32_t *blocks,
-    size_t count, uint32_t preferred_bg)
-{
-	uint32_t bg_count = ext2_superblock_get_block_group_count(fs->superblock);
-	uint32_t bpg = ext2_superblock_get_blocks_per_group(fs->superblock);
-	uint32_t block_size = ext2_superblock_get_block_size(fs->superblock);
-	uint32_t block_group = preferred_bg;
-	uint32_t free_blocks_sb;
-	uint32_t block_groups_left;
-	size_t idx;
-	ext2_block_group_ref_t *bg;
-	int rc;
-	uint32_t bb_block;
-	block_t *block;
-	size_t bb_idx;
-	size_t bb_bit;
-	
-	free_blocks_sb = ext2_superblock_get_free_block_count(fs->superblock);
-	
-	if (count > free_blocks_sb) {
-		return EIO;
-	}
-	
-	block_groups_left = bg_count;
-	
-	idx = 0;
-	
-	/* Read the block group descriptor */
-	rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg);
-	if (rc != EOK) {
-		goto failed;
-	}
-	
-	while (idx < count && block_groups_left > 0) {
-		uint16_t fb = ext2_block_group_get_free_block_count(bg->block_group);
-		if (fb == 0) {
-			block_group = (block_group + 1) % bg_count;
-			block_groups_left -= 1;
-			
-			rc = ext2_filesystem_put_block_group_ref(bg);
-			if (rc != EOK) {
-				goto failed;
-			}
-			
-			rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg);
-			if (rc != EOK) {
-				goto failed;
-			}
-			continue;
-		}
-		
-		/* We found a block group with free block, let's look at the block bitmap */
-		bb_block = ext2_block_group_get_block_bitmap_block(bg->block_group);
-		
-		rc = block_get(&block, fs->device, bb_block, BLOCK_FLAGS_NONE);
-		if (rc != EOK) {
-			goto failed;
-		}
-		
-		/* Use all blocks from this block group */
-		for (bb_idx = 0; bb_idx < block_size && idx < count; bb_idx++) {
-			uint8_t *data = (uint8_t *) block->data;
-			if (data[bb_idx] == 0xff) {
-				continue;
-			}
-			/* find an empty bit */
-			uint8_t mask;
-			for (mask = 1, bb_bit = 0;
-				 bb_bit < 8 && idx < count; 
-				 bb_bit++, mask = mask << 1) {
-				if ((data[bb_idx] & mask) == 0) {
-					// free block found
-					blocks[idx] = block_group * bpg + bb_idx*8 + bb_bit;
-					data[bb_idx] |= mask;
-					idx += 1;
-					fb -= 1;
-					ext2_block_group_set_free_block_count(bg->block_group, fb);
-				}
-			}
-		}
-	}
-	
-	rc = ext2_filesystem_put_block_group_ref(bg);
-	if (rc != EOK) {
-		goto failed;
-	}
-	
-	// TODO update superblock
-	
-	return EOK;
-failed:
-	// TODO deallocate already allocated blocks, if possible
-	
-	return rc;
-}
-
-/**
- * Finalize an instance of filesystem
- * 
- * @param fs Pointer to ext2_filesystem_t to finalize
- */
-void ext2_filesystem_fini(ext2_filesystem_t *fs)
-{
-	free(fs->superblock);
-	block_fini(fs->device);
-}
-
-
-/** @}
- */
Index: pace/lib/ext2/libext2_filesystem.h
===================================================================
--- uspace/lib/ext2/libext2_filesystem.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,78 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_FILESYSTEM_H_
-#define LIBEXT2_LIBEXT2_FILESYSTEM_H_
-
-#include <block.h>
-#include "libext2_superblock.h"
-#include "libext2_block_group.h"
-#include "libext2_inode.h"
-
-typedef struct ext2_filesystem {
-	service_id_t		device;
-	ext2_superblock_t *	superblock;
-} ext2_filesystem_t;
-
-// allow maximum this block size
-#define EXT2_MAX_BLOCK_SIZE			8096
-#define EXT2_REV0_FIRST_INODE		11
-#define EXT2_REV0_INODE_SIZE		128
-
-#define EXT2_FEATURE_RO_SPARSE_SUPERBLOCK	1
-#define EXT2_FEATURE_RO_LARGE_FILE			2
-#define EXT2_FEATURE_I_TYPE_IN_DIR			2
-
-#define EXT2_SUPPORTED_INCOMPATIBLE_FEATURES EXT2_FEATURE_I_TYPE_IN_DIR
-#define EXT2_SUPPORTED_READ_ONLY_FEATURES 0
-
-extern int ext2_filesystem_init(ext2_filesystem_t *, service_id_t);
-extern int ext2_filesystem_check_sanity(ext2_filesystem_t *);
-extern int ext2_filesystem_check_flags(ext2_filesystem_t *, bool *);
-extern int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *, uint32_t, 
-    ext2_block_group_ref_t **);
-extern int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *);
-extern int ext2_filesystem_get_inode_ref(ext2_filesystem_t *, uint32_t,
-    ext2_inode_ref_t **);
-extern int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *);
-extern int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *, ext2_inode_t*,
-    aoff64_t, uint32_t*);
-extern int ext2_filesystem_allocate_blocks(ext2_filesystem_t *, uint32_t *, size_t, uint32_t);
-extern void ext2_filesystem_fini(ext2_filesystem_t *);
-
-#endif
-
-/** @}
- */
Index: pace/lib/ext2/libext2_inode.c
===================================================================
--- uspace/lib/ext2/libext2_inode.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,192 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#include "libext2.h"
-#include "libext2_inode.h"
-#include "libext2_superblock.h"
-#include <byteorder.h>
-#include <assert.h>
-
-/**
- * Get mode stored in the inode
- * 
- * @param inode pointer to inode
- */
-uint32_t ext2_inode_get_mode(ext2_superblock_t *sb, ext2_inode_t *inode)
-{
-	if (ext2_superblock_get_os(sb) == EXT2_SUPERBLOCK_OS_HURD) {
-		return ((uint32_t)uint16_t_le2host(inode->mode_high)) << 16 |
-		    ((uint32_t)uint16_t_le2host(inode->mode));
-	}
-	return uint16_t_le2host(inode->mode);
-}
-
-/**
- * Check whether inode is of given type
- * 
- * @param sb pointer to superblock structure
- * @param inode pointer to inode
- * @param type EXT2_INODE_MODE_TYPE_* constant to check
- */
-bool ext2_inode_is_type(ext2_superblock_t *sb, ext2_inode_t *inode, uint32_t type)
-{
-	uint32_t mode = ext2_inode_get_mode(sb, inode);
-	return (mode & EXT2_INODE_MODE_TYPE_MASK) == type;
-}
-
-/**
- * Get uid this inode is belonging to
- * 
- * @param inode pointer to inode
- */
-uint32_t ext2_inode_get_user_id(ext2_superblock_t *sb, ext2_inode_t *inode)
-{
-	uint32_t os = ext2_superblock_get_os(sb);
-	if (os == EXT2_SUPERBLOCK_OS_LINUX || os == EXT2_SUPERBLOCK_OS_HURD) {
-		return ((uint32_t)uint16_t_le2host(inode->user_id_high)) << 16 |
-		    ((uint32_t)uint16_t_le2host(inode->user_id));
-	}
-	return uint16_t_le2host(inode->user_id);
-}
-
-/**
- * Get size of file
- * 
- * For regular files in revision 1 and later, the high 32 bits of
- * file size are stored in inode->size_high and are 0 otherwise
- * 
- * @param inode pointer to inode
- */
-uint64_t ext2_inode_get_size(ext2_superblock_t *sb, ext2_inode_t *inode)
-{
-	uint32_t major_rev = ext2_superblock_get_rev_major(sb);
-	
-	if (major_rev > 0 && ext2_inode_is_type(sb, inode, EXT2_INODE_MODE_FILE)) {
-		return ((uint64_t)uint32_t_le2host(inode->size_high)) << 32 |
-		    ((uint64_t)uint32_t_le2host(inode->size));
-	}
-	return uint32_t_le2host(inode->size);
-}
-
-/**
- * Get gid this inode belongs to
- * 
- * For Linux and Hurd, the high 16 bits are stored in OS dependent part
- * of inode structure
- * 
- * @param inode pointer to inode
- */
-uint32_t ext2_inode_get_group_id(ext2_superblock_t *sb, ext2_inode_t *inode)
-{
-	uint32_t os = ext2_superblock_get_os(sb);
-	if (os == EXT2_SUPERBLOCK_OS_LINUX || os == EXT2_SUPERBLOCK_OS_HURD) {
-		return ((uint32_t)uint16_t_le2host(inode->group_id_high)) << 16 |
-		    ((uint32_t)uint16_t_le2host(inode->group_id));
-	}
-	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
- */
-uint16_t ext2_inode_get_usage_count(ext2_inode_t *inode)
-{
-	return uint16_t_le2host(inode->usage_count);
-}
-
-/**
- * Get number of 512-byte data blocks allocated for contents of the file
- * represented by this inode.
- * This should be multiple of block size unless fragments are used.
- * 
- * @param inode pointer to inode
- */
-uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *inode)
-{
-	return uint32_t_le2host(inode->reserved_512_blocks);
-}
-
-/**
- * Get number of blocks allocated for contents of the file
- * represented by this inode.
- * 
- * @param inode pointer to inode
- */
-uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *sb,
-    ext2_inode_t *inode)
-{
-	return ext2_inode_get_reserved_512_blocks(inode) /
-	    (ext2_superblock_get_block_size(sb) / 512);
-}
-
-/**
- * Get inode flags
- * 
- * @param inode pointer to inode
- */
-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
- */
-uint32_t ext2_inode_get_direct_block(ext2_inode_t *inode, uint8_t idx)
-{
-	assert(idx < EXT2_INODE_DIRECT_BLOCKS);
-	return uint32_t_le2host(inode->direct_blocks[idx]);
-}
-
-/**
- * Get indirect block ID
- * 
- * @param inode pointer to inode
- * @param idx Indirection level. Valid values are 0 <= idx < 3, where 0 is
- *            singly-indirect block and 2 is triply-indirect-block
- */
-uint32_t ext2_inode_get_indirect_block(ext2_inode_t *inode, uint8_t idx)
-{
-	assert(idx < 3);
-	return uint32_t_le2host(inode->indirect_blocks[idx]);
-}
-
-/** @}
- */
Index: pace/lib/ext2/libext2_inode.h
===================================================================
--- uspace/lib/ext2/libext2_inode.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,103 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_INODE_H_
-#define LIBEXT2_LIBEXT2_INODE_H_
-
-#include <block.h>
-#include "libext2_superblock.h"
-
-typedef struct ext2_inode {
-	uint16_t mode;
-	uint16_t user_id;
-	uint32_t size;
-	uint8_t unused[16];
-	uint16_t group_id;
-	uint16_t usage_count; // Hard link count, when 0 the inode is to be freed
-	uint32_t reserved_512_blocks; // Size of this inode in 512-byte blocks
-	uint32_t flags;
-	uint8_t unused2[4];
-	uint32_t direct_blocks[12]; // Direct block ids stored in this inode
-	uint32_t indirect_blocks[3];
-	uint32_t version;
-	uint32_t file_acl;
-	union {
-		uint32_t dir_acl;
-		uint32_t size_high; // For regular files in version >= 1
-	} __attribute__ ((packed));
-	uint8_t unused3[6];
-	uint16_t mode_high; // Hurd only
-	uint16_t user_id_high; // Linux/Hurd only
-	uint16_t group_id_high; // Linux/Hurd only
-} __attribute__ ((packed)) 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
-#define EXT2_INODE_MODE_TYPE_MASK	0xF000
-#define EXT2_INODE_DIRECT_BLOCKS	12
-
-#define EXT2_INODE_ROOT_INDEX		2
-
-typedef struct ext2_inode_ref {
-	block_t *block; // Reference to a block containing this inode
-	ext2_inode_t *inode;
-	uint32_t index; // Index number of this inode
-} ext2_inode_ref_t;
-
-extern uint32_t ext2_inode_get_mode(ext2_superblock_t *, ext2_inode_t *);
-extern bool ext2_inode_is_type(ext2_superblock_t *, ext2_inode_t *, uint32_t);
-extern uint32_t ext2_inode_get_user_id(ext2_superblock_t *, ext2_inode_t *);
-extern uint64_t ext2_inode_get_size(ext2_superblock_t *, ext2_inode_t *);
-extern uint32_t ext2_inode_get_group_id(ext2_superblock_t *, ext2_inode_t *);
-extern uint16_t ext2_inode_get_usage_count(ext2_inode_t *);
-extern uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *);
-extern uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *, 
-    ext2_inode_t *);
-extern uint32_t ext2_inode_get_flags(ext2_inode_t *);
-extern uint32_t ext2_inode_get_direct_block(ext2_inode_t *, uint8_t);
-extern uint32_t ext2_inode_get_indirect_block(ext2_inode_t *, uint8_t level);
-
-
-
-#endif
-
-/** @}
- */
Index: pace/lib/ext2/libext2_superblock.c
===================================================================
--- uspace/lib/ext2/libext2_superblock.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,409 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#include "libext2.h"
-#include <errno.h>
-#include <malloc.h>
-#include <block.h>
-#include <byteorder.h>
-
-/**
- * Return a magic number from ext2 superblock, this should be equal to
- * EXT_SUPERBLOCK_MAGIC for valid ext2 superblock
- * 
- * @param sb pointer to superblock
- */
-uint16_t ext2_superblock_get_magic(ext2_superblock_t *sb)
-{
-	return uint16_t_le2host(sb->magic);
-}
-
-/**
- * Get the position of first ext2 data block (i.e. the block number
- * containing main superblock)
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_first_block(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->first_block);
-}
-
-/**
- * Get the number of bits to shift a value of 1024 to the left necessary
- * to get the size of a block
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_block_size_log2(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->block_size_log2);
-}
-
-/**
- * Get the size of a block, in bytes 
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_block_size(ext2_superblock_t *sb)
-{
-	return 1024 << ext2_superblock_get_block_size_log2(sb);
-}
-
-/**
- * Get the number of bits to shift a value of 1024 to the left necessary
- * to get the size of a fragment (note that this is a signed integer and
- * if negative, the value should be shifted to the right instead)
- * 
- * @param sb pointer to superblock
- */
-int32_t ext2_superblock_get_fragment_size_log2(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->fragment_size_log2);
-}
-
-/**
- * Get the size of a fragment, in bytes 
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_fragment_size(ext2_superblock_t *sb)
-{
-	int32_t log = ext2_superblock_get_fragment_size_log2(sb);
-	if (log >= 0) {
-		return 1024 << log;
-	}
-	else {
-		return 1024 >> -log;
-	}
-}
-
-/**
- * Get number of blocks per block group
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_blocks_per_group(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->blocks_per_group);
-}
-
-/**
- * Get number of fragments per block group
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_fragments_per_group(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->fragments_per_group);
-}
-
-/**
- * Get filesystem state
- * 
- * @param sb pointer to superblock
- */
-uint16_t ext2_superblock_get_state(ext2_superblock_t *sb)
-{
-	return uint16_t_le2host(sb->state);
-}
-
-/**
- * Get minor revision number
- * 
- * @param sb pointer to superblock
- */
-uint16_t ext2_superblock_get_rev_minor(ext2_superblock_t *sb)
-{
-	return uint16_t_le2host(sb->rev_minor);
-}
-
-/**
- * Get major revision number
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_rev_major(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->rev_major);
-}
-
-/**
- * Get index of first regular inode
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_first_inode(ext2_superblock_t *sb)
-{
-	if (ext2_superblock_get_rev_major(sb) == 0) {
-		return EXT2_REV0_FIRST_INODE;
-	}
-	return uint32_t_le2host(sb->first_inode);
-}
-
-/**
- * Get size of inode
- * 
- * @param sb pointer to superblock
- */
-uint16_t ext2_superblock_get_inode_size(ext2_superblock_t *sb)
-{
-	if (ext2_superblock_get_rev_major(sb) == 0) {
-		return EXT2_REV0_INODE_SIZE;
-	}
-	return uint16_t_le2host(sb->inode_size);
-}
-
-/**
- * Get total inode count
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_total_inode_count(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->total_inode_count);
-}
-
-/**
- * Get total block count
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_total_block_count(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->total_block_count);
-}
-
-/**
- * Get amount of blocks reserved for the superuser
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_reserved_block_count(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->reserved_block_count);
-}
-
-/**
- * Get amount of free blocks
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_free_block_count(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->free_block_count);
-}
-
-/**
- * Get amount of free inodes
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_free_inode_count(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->free_inode_count);
-}
-
-/**
- * Get id of operating system that created the filesystem
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_os(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->os);
-}
-
-/**
- * Get count of inodes per block group
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_inodes_per_group(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->inodes_per_group);
-}
-
-/**
- * Get compatible features flags
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_features_compatible(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->features_compatible);
-}
-
-/**
- * Get incompatible features flags
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_features_incompatible(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->features_incompatible);
-}
-
-/**
- * Get read-only compatible features flags
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_features_read_only(ext2_superblock_t *sb)
-{
-	return uint32_t_le2host(sb->features_read_only);
-}
-
-/**
- * Compute count of block groups present in the filesystem
- * 
- * Note: This function works only for correct filesystem,
- *       i.e. it assumes that total block count > 0 and
- *       blocks per group > 0
- * 
- * Example:
- *   If there are 3 blocks per group, the result should be as follows:
- *   Total blocks	Result
- *   1				1
- *   2				1
- *   3				1
- *   4				2
- * 
- * 
- * @param sb pointer to superblock
- */
-uint32_t ext2_superblock_get_block_group_count(ext2_superblock_t *sb)
-{
-	/* We add one to the result because e.g. 2/3 = 0, while to store
-	 *  2 blocks in 3-block group we need one (1) block group
-	 * 
-	 * We subtract one first because of special case that to store e.g.
-	 *  3 blocks in a 3-block group we need only one group
-	 *  (and 3/3 yields one - this is one more that we want as we
-	 *   already add one at the end)
-	 */ 
-	return ((ext2_superblock_get_total_block_count(sb)-1) / 
-	    ext2_superblock_get_blocks_per_group(sb))+1;
-}
-
-/** Read a superblock directly from device (i.e. no libblock cache)
- * 
- * @param service_id	Service ID of the block device.
- * @param superblock	Pointer where to store pointer to new superblock
- * 
- * @return		EOK on success or negative error code on failure.
- */
-int ext2_superblock_read_direct(service_id_t service_id,
-    ext2_superblock_t **superblock)
-{
-	void *data;
-	int rc;
-	
-	data = malloc(EXT2_SUPERBLOCK_SIZE);
-	if (data == NULL) {
-		return ENOMEM;
-	}
-	
-	rc = block_read_bytes_direct(service_id, EXT2_SUPERBLOCK_OFFSET,
-	    EXT2_SUPERBLOCK_SIZE, data);
-	if (rc != EOK) {
-		free(data);
-		return rc;
-	}
-	
-	(*superblock) = data;
-	return EOK;
-}
-
-/** Check a superblock for sanity
- * 
- * @param sb	Pointer to superblock
- * 
- * @return		EOK on success or negative error code on failure.
- */
-int ext2_superblock_check_sanity(ext2_superblock_t *sb)
-{
-	if (ext2_superblock_get_magic(sb) != EXT2_SUPERBLOCK_MAGIC) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_rev_major(sb) > 1) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_total_inode_count(sb) == 0) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_total_block_count(sb) == 0) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_blocks_per_group(sb) == 0) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_fragments_per_group(sb) == 0) {
-		return ENOTSUP;
-	}
-	
-	/* We don't support fragments smaller than block */
-	if (ext2_superblock_get_block_size(sb) != 
-		    ext2_superblock_get_fragment_size(sb)) {
-		return ENOTSUP;
-	}
-	if (ext2_superblock_get_blocks_per_group(sb) !=
-		    ext2_superblock_get_fragments_per_group(sb)) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_inodes_per_group(sb) == 0) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_inode_size(sb) < 128) {
-		return ENOTSUP;
-	}
-	
-	if (ext2_superblock_get_first_inode(sb) < 11) {
-		return ENOTSUP;
-	}
-	
-	return EOK;
-}
-
-
-/** @}
- */
Index: pace/lib/ext2/libext2_superblock.h
===================================================================
--- uspace/lib/ext2/libext2_superblock.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup libext2
- * @{
- */
-/**
- * @file
- */
-
-#ifndef LIBEXT2_LIBEXT2_SUPERBLOCK_H_
-#define LIBEXT2_LIBEXT2_SUPERBLOCK_H_
-
-#include <block.h>
-
-typedef struct ext2_superblock {
-	uint32_t	total_inode_count; // Total number of inodes
-	uint32_t	total_block_count; // Total number of blocks
-	uint32_t	reserved_block_count; // Total number of reserved blocks
-	uint32_t	free_block_count; // Total number of free blocks
-	uint32_t	free_inode_count; // Total number of free inodes
-	uint32_t	first_block; // Block containing the superblock (either 0 or 1)
-	uint32_t	block_size_log2; // log_2(block_size)
-	int32_t		fragment_size_log2; // log_2(fragment size)
-	uint32_t	blocks_per_group; // Number of blocks in one block group
-	uint32_t	fragments_per_group; // Number of fragments per block group
-	uint32_t	inodes_per_group; // Number of inodes per block group
-	uint8_t		unused2[12];
-	uint16_t	magic; // Magic value
-	uint16_t	state; // State (mounted/unmounted)
-	uint16_t	error_behavior; // What to do when errors are encountered
-	uint16_t	rev_minor; // Minor revision level
-	uint8_t		unused3[8];
-	uint32_t	os; // OS that created the filesystem
-	uint32_t	rev_major; // Major revision level
-	uint8_t		unused4[4];
-	
-	// Following is for ext2 revision 1 only
-	uint32_t	first_inode;
-	uint16_t	inode_size;
-	uint16_t	unused5;
-	uint32_t	features_compatible;
-	uint32_t	features_incompatible;
-	uint32_t	features_read_only;
-	uint8_t		uuid[16]; // UUID TODO: Create a library for UUIDs
-	uint8_t		volume_name[16];
-
-// TODO: add __attribute__((aligned(...)) for better performance?
-//       (it is necessary to ensure the superblock is correctly aligned then
-//        though)
-} __attribute__ ((packed)) ext2_superblock_t;
-
-#define EXT2_SUPERBLOCK_MAGIC		0xEF53
-#define EXT2_SUPERBLOCK_SIZE		1024
-#define EXT2_SUPERBLOCK_OFFSET		1024
-#define EXT2_SUPERBLOCK_LAST_BYTE	(EXT2_SUPERBLOCK_OFFSET + \
-									 EXT2_SUPERBLOCK_SIZE -1)
-#define EXT2_SUPERBLOCK_OS_LINUX	0
-#define EXT2_SUPERBLOCK_OS_HURD		1
-
-
-extern uint16_t	ext2_superblock_get_magic(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_first_block(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_block_size_log2(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_block_size(ext2_superblock_t *);
-extern int32_t	ext2_superblock_get_fragment_size_log2(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_fragment_size(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_blocks_per_group(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_fragments_per_group(ext2_superblock_t *);
-extern uint16_t	ext2_superblock_get_state(ext2_superblock_t *);
-extern uint16_t	ext2_superblock_get_rev_minor(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_rev_major(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_os(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_first_inode(ext2_superblock_t *);
-extern uint16_t	ext2_superblock_get_inode_size(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_total_inode_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_total_block_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_reserved_block_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_free_block_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_free_inode_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_block_group_count(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_inodes_per_group(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_features_compatible(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_features_incompatible(ext2_superblock_t *);
-extern uint32_t	ext2_superblock_get_features_read_only(ext2_superblock_t *);
-
-extern int ext2_superblock_read_direct(service_id_t, ext2_superblock_t **);
-extern int ext2_superblock_check_sanity(ext2_superblock_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/ext4/libext4_block_group.c
===================================================================
--- uspace/lib/ext4/libext4_block_group.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_block_group.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_block_group.h
===================================================================
--- uspace/lib/ext4/libext4_block_group.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_block_group.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_directory.c
===================================================================
--- uspace/lib/ext4/libext4_directory.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_directory.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_directory.h
===================================================================
--- uspace/lib/ext4/libext4_directory.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_directory.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_filesystem.h
===================================================================
--- uspace/lib/ext4/libext4_filesystem.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_filesystem.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_inode.c
===================================================================
--- uspace/lib/ext4/libext4_inode.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_inode.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_inode.h
===================================================================
--- uspace/lib/ext4/libext4_inode.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_inode.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_superblock.c
===================================================================
--- uspace/lib/ext4/libext4_superblock.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_superblock.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_superblock.h
===================================================================
--- uspace/lib/ext4/libext4_superblock.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_superblock.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/lib/ext4/libext4_types.h
===================================================================
--- uspace/lib/ext4/libext4_types.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/lib/ext4/libext4_types.h	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: pace/srv/fs/ext2fs/Makefile
===================================================================
--- uspace/srv/fs/ext2fs/Makefile	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# Copyright (c) 2010 Martin Sucha
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - 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.
-# - 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.
-#
-
-USPACE_PREFIX = ../../..
-LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBEXT2_PREFIX)/libext2.a
-EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBEXT2_PREFIX)
-BINARY = ext2fs
-
-SOURCES = \
-	ext2fs.c \
-	ext2fs_ops.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup fs
- * @{
- */ 
-
-/**
- * @file	ext2.c
- * @brief	EXT2 file system driver for HelenOS.
- */
-
-#include "ext2fs.h"
-#include <ipc/services.h>
-#include <ns.h>
-#include <async.h>
-#include <errno.h>
-#include <unistd.h>
-#include <task.h>
-#include <stdio.h>
-#include <libfs.h>
-#include "../../vfs/vfs.h"
-
-#define NAME	"ext2fs"
-
-vfs_info_t ext2fs_vfs_info = {
-	.name = NAME,
-	.instance = 0,
-};
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": HelenOS EXT2 file system server\n");
-
-	if (argc == 3) {
-		if (!str_cmp(argv[1], "--instance"))
-			ext2fs_vfs_info.instance = strtol(argv[2], NULL, 10);
-		else {
-			printf(NAME " Unrecognized parameters");
-			return -1;
-		}
-	}
-	
-	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
-	    SERVICE_VFS, 0, 0);
-	if (!vfs_sess) {
-		printf(NAME ": failed to connect to VFS\n");
-		return -1;
-	}
-
-	int rc = ext2fs_global_init();
-	if (rc != EOK) {
-		printf(NAME ": Failed global initialization\n");
-		return 1;
-	}	
-		
-	rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
-	    &ext2fs_libfs_ops);
-	if (rc != EOK) {
-		fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
-		return 1;
-	}
-	
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-	/* not reached */
-	return 0;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup fs
- * @{
- */ 
-
-#ifndef EXT2FS_EXT2FS_H_
-#define EXT2FS_EXT2FS_H_
-
-#include <libext2.h>
-#include <libfs.h>
-#include <sys/types.h>
-
-#define min(a, b)		((a) < (b) ? (a) : (b))
-
-extern vfs_out_ops_t ext2fs_ops;
-extern libfs_ops_t ext2fs_libfs_ops;
-
-extern int ext2fs_global_init(void);
-extern int ext2fs_global_fini(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ 	(revision )
@@ -1,976 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Sucha
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - 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.
- * - 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.
- */
-
-/** @addtogroup fs
- * @{
- */ 
-
-/**
- * @file	ext2fs_ops.c
- * @brief	Implementation of VFS operations for the EXT2 file system server.
- */
-
-#include "ext2fs.h"
-#include "../../vfs/vfs.h"
-#include <libfs.h>
-#include <block.h>
-#include <libext2.h>
-#include <ipc/services.h>
-#include <ipc/loc.h>
-#include <macros.h>
-#include <async.h>
-#include <errno.h>
-#include <str.h>
-#include <byteorder.h>
-#include <adt/hash_table.h>
-#include <adt/hash.h>
-#include <adt/list.h>
-#include <assert.h>
-#include <fibril_synch.h>
-#include <sys/mman.h>
-#include <align.h>
-#include <adt/hash_table.h>
-#include <sys/typefmt.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <inttypes.h>
-
-#define EXT2FS_NODE(node)	((node) ? (ext2fs_node_t *) (node)->data : NULL)
-#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
-
-typedef struct ext2fs_instance {
-	link_t link;
-	service_id_t service_id;
-	ext2_filesystem_t *filesystem;
-	unsigned int open_nodes_count;
-} ext2fs_instance_t;
-
-typedef struct ext2fs_node {
-	ext2fs_instance_t *instance;
-	ext2_inode_ref_t *inode_ref;
-	fs_node_t *fs_node;
-	ht_link_t link;
-	unsigned int references;
-} ext2fs_node_t;
-
-/*
- * Forward declarations of auxiliary functions
- */
-static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **);
-static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
-    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
-static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
-    ext2_inode_ref_t *, size_t *);
-static bool ext2fs_is_dots(const uint8_t *, size_t);
-static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
-static int ext2fs_node_put_core(ext2fs_node_t *);
-
-/*
- * Forward declarations of EXT2 libfs operations.
- */
-static int ext2fs_root_get(fs_node_t **, service_id_t);
-static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
-static int ext2fs_node_get(fs_node_t **, service_id_t, fs_index_t);
-static int ext2fs_node_open(fs_node_t *);
-static int ext2fs_node_put(fs_node_t *);
-static int ext2fs_create_node(fs_node_t **, service_id_t, int);
-static int ext2fs_destroy_node(fs_node_t *);
-static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
-static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
-static int ext2fs_has_children(bool *, fs_node_t *);
-static fs_index_t ext2fs_index_get(fs_node_t *);
-static aoff64_t ext2fs_size_get(fs_node_t *);
-static unsigned ext2fs_lnkcnt_get(fs_node_t *);
-static bool ext2fs_is_directory(fs_node_t *);
-static bool ext2fs_is_file(fs_node_t *node);
-static service_id_t ext2fs_service_get(fs_node_t *node);
-
-/*
- * Static variables
- */
-static LIST_INITIALIZE(instance_list);
-static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
-static hash_table_t open_nodes;
-static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
-
-/* 
- * Hash table interface for open nodes hash table 
- */
-
-typedef struct {
-	service_id_t service_id;
-	fs_index_t index;
-} node_key_t;
-
-static size_t open_nodes_key_hash(void *key)
-{
-	node_key_t *node_key = (node_key_t*)key;
-	return hash_combine(node_key->service_id, node_key->index);
-}
-
-static size_t open_nodes_hash(const ht_link_t *item)
-{
-	ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
-
-	assert(enode->instance);
-	assert(enode->inode_ref);
-	
-	return hash_combine(enode->instance->service_id, enode->inode_ref->index);
-}
-
-static bool open_nodes_key_equal(void *key, const ht_link_t *item)
-{
-	node_key_t *node_key = (node_key_t*)key;
-	ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
-	
-	return node_key->service_id == enode->instance->service_id
-		&& node_key->index == enode->inode_ref->index;
-}
-
-static hash_table_ops_t open_nodes_ops = {
-	.hash = open_nodes_hash,
-	.key_hash = open_nodes_key_hash,
-	.key_equal = open_nodes_key_equal,
-	.equal = NULL,
-	.remove_callback = NULL,
-};
-
-/**
- * 
- */
-int ext2fs_global_init(void)
-{
-	if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) {
-		return ENOMEM;
-	}
-	return EOK;
-}
-
-int ext2fs_global_fini(void)
-{
-	hash_table_destroy(&open_nodes);
-	return EOK;
-}
-
-
-/*
- * EXT2 libfs operations.
- */
-
-/**
- * Find an instance of filesystem for the given service_id
- */
-int ext2fs_instance_get(service_id_t service_id, ext2fs_instance_t **inst)
-{
-	EXT2FS_DBG("(%" PRIun ", -)", service_id);
-	ext2fs_instance_t *tmp;
-	
-	fibril_mutex_lock(&instance_list_mutex);
-
-	if (list_empty(&instance_list)) {
-		EXT2FS_DBG("list empty");
-		fibril_mutex_unlock(&instance_list_mutex);
-		return EINVAL;
-	}
-
-	list_foreach(instance_list, link) {
-		tmp = list_get_instance(link, ext2fs_instance_t, link);
-		
-		if (tmp->service_id == service_id) {
-			*inst = tmp;
-			fibril_mutex_unlock(&instance_list_mutex);
-			return EOK;
-		}
-	}
-	
-	EXT2FS_DBG("not found");
-	
-	fibril_mutex_unlock(&instance_list_mutex);
-	return EINVAL;
-}
-
-
-
-int ext2fs_root_get(fs_node_t **rfn, service_id_t service_id)
-{
-	EXT2FS_DBG("(-, %" PRIun ")", service_id);
-	return ext2fs_node_get(rfn, service_id, EXT2_INODE_ROOT_INDEX);
-}
-
-int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
-{
-	EXT2FS_DBG("(-,-,%s)", component);
-	ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
-	ext2_filesystem_t *fs;
-	ext2_directory_iterator_t it;
-	int rc;
-	size_t name_size;
-	size_t component_size;
-	bool found = false;
-	uint32_t inode;
-	
-	fs = eparent->instance->filesystem;
-	
-	if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
-	    EXT2_INODE_MODE_DIRECTORY)) {
-		return ENOTDIR;
-	}
-	
-	rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Find length of component in bytes
-	 * TODO: check for library function call that does this
-	 */
-	component_size = 0;
-	while (*(component+component_size) != 0) {
-		component_size++;
-	}
-	
-	while (it.current != NULL) {
-		inode = ext2_directory_entry_ll_get_inode(it.current);
-		
-		/* ignore empty directory entries */
-		if (inode != 0) {
-			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
-				it.current);
-
-			if (name_size == component_size && bcmp(component, &it.current->name,
-				    name_size) == 0) {
-				rc = ext2fs_node_get_core(rfn, eparent->instance,
-					inode);
-				if (rc != EOK) {
-					ext2_directory_iterator_fini(&it);
-					return rc;
-				}
-				found = true;
-				break;
-			}
-		}
-		
-		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			ext2_directory_iterator_fini(&it);
-			return rc;
-		}
-	}
-	
-	ext2_directory_iterator_fini(&it);
-	
-	if (!found) {
-		return ENOENT;
-	}
-	
-	return EOK;
-}
-
-/** Instantiate a EXT2 in-core node. */
-int ext2fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
-{
-	EXT2FS_DBG("(-,%" PRIun ",%u)", service_id, index);
-	
-	ext2fs_instance_t *inst = NULL;
-	int rc;
-	
-	rc = ext2fs_instance_get(service_id, &inst);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	return ext2fs_node_get_core(rfn, inst, index);
-}
-
-int ext2fs_node_get_core(fs_node_t **rfn, ext2fs_instance_t *inst,
-		fs_index_t index)
-{
-	int rc;
-	fs_node_t *node = NULL;
-	ext2fs_node_t *enode = NULL;
-	
-	ext2_inode_ref_t *inode_ref = NULL;
-
-	fibril_mutex_lock(&open_nodes_lock);
-	
-	/* Check if the node is not already open */
-	node_key_t key = {
-		.service_id = inst->service_id,
-		.index = index
-	};
-	ht_link_t *already_open = hash_table_find(&open_nodes, &key);
-
-	if (already_open) {
-		enode = hash_table_get_inst(already_open, ext2fs_node_t, link);
-		*rfn = enode->fs_node;
-		enode->references++;
-
-		fibril_mutex_unlock(&open_nodes_lock);
-		return EOK;
-	}
-
-	enode = malloc(sizeof(ext2fs_node_t));
-	if (enode == NULL) {
-		fibril_mutex_unlock(&open_nodes_lock);
-		return ENOMEM;
-	}
-
-	node = malloc(sizeof(fs_node_t));
-	if (node == NULL) {
-		free(enode);
-		fibril_mutex_unlock(&open_nodes_lock);
-		return ENOMEM;
-	}	
-	fs_node_initialize(node);
-
-	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
-	if (rc != EOK) {
-		free(enode);
-		free(node);
-		fibril_mutex_unlock(&open_nodes_lock);
-		return rc;
-	}
-	
-	enode->inode_ref = inode_ref;
-	enode->instance = inst;
-	enode->references = 1;
-	enode->fs_node = node;
-	
-	node->data = enode;
-	*rfn = node;
-	
-	hash_table_insert(&open_nodes, &enode->link);
-	inst->open_nodes_count++;
-	
-	EXT2FS_DBG("inode: %u", inode_ref->index);
-	
-	EXT2FS_DBG("EOK");
-
-	fibril_mutex_unlock(&open_nodes_lock);
-	return EOK;
-}
-
-int ext2fs_node_open(fs_node_t *fn)
-{
-	EXT2FS_DBG("");
-	/*
-	 * Opening a file is stateless, nothing
-	 * to be done here.
-	 */
-	return EOK;
-}
-
-int ext2fs_node_put(fs_node_t *fn)
-{
-	EXT2FS_DBG("");
-	int rc;
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	
-	fibril_mutex_lock(&open_nodes_lock);
-
-	assert(enode->references > 0);
-	enode->references--;
-	if (enode->references == 0) {
-		rc = ext2fs_node_put_core(enode);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&open_nodes_lock);
-			return rc;
-		}
-	}
-
-	fibril_mutex_unlock(&open_nodes_lock);
-	
-	return EOK;
-}
-
-int ext2fs_node_put_core(ext2fs_node_t *enode)
-{
-	node_key_t key = {
-		.service_id = enode->instance->service_id,
-		.index = enode->inode_ref->index
-	};
-
-	hash_table_remove(&open_nodes, &key);
-	
-	assert(enode->instance->open_nodes_count > 0);
-	enode->instance->open_nodes_count--;
-
-	int rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
-	if (rc != EOK) {
-		EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
-		return rc;
-	}
-
-	free(enode->fs_node);
-	free(enode);
-	return EOK;
-}
-
-int ext2fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
-{
-	EXT2FS_DBG("");
-	// TODO
-	return ENOTSUP;
-}
-
-int ext2fs_destroy_node(fs_node_t *fn)
-{
-	EXT2FS_DBG("");
-	// TODO
-	return ENOTSUP;
-}
-
-int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
-{
-	EXT2FS_DBG("");
-	// TODO
-	return ENOTSUP;
-}
-
-int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
-{
-	EXT2FS_DBG("");
-	// TODO
-	return ENOTSUP;
-}
-
-int ext2fs_has_children(bool *has_children, fs_node_t *fn)
-{
-	EXT2FS_DBG("");
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	ext2_directory_iterator_t it;
-	ext2_filesystem_t *fs;
-	int rc;
-	bool found = false;
-	size_t name_size;
-
-	fs = enode->instance->filesystem;
-
-	if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
-	    EXT2_INODE_MODE_DIRECTORY)) {
-		*has_children = false;
-		EXT2FS_DBG("EOK - false");
-		return EOK;
-	}
-	
-	rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0);
-	if (rc != EOK) {
-		EXT2FS_DBG("error %u", rc);
-		return rc;
-	}
-	
-	/* Find a non-empty directory entry */
-	while (it.current != NULL) {
-		if (it.current->inode != 0) {
-			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
-				it.current);
-			if (!ext2fs_is_dots(&it.current->name, name_size)) {
-				found = true;
-				break;
-			}
-		}
-		
-		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			ext2_directory_iterator_fini(&it);
-			EXT2FS_DBG("error %u", rc);
-			return rc;
-		}
-	}
-	
-	rc = ext2_directory_iterator_fini(&it);
-	if (rc != EOK) {
-		EXT2FS_DBG("error %u", rc);
-		return rc;
-	}
-
-	*has_children = found;
-	EXT2FS_DBG("EOK");
-	
-	return EOK;
-}
-
-
-fs_index_t ext2fs_index_get(fs_node_t *fn)
-{
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	EXT2FS_DBG("%u", enode->inode_ref->index);
-	return enode->inode_ref->index;
-}
-
-aoff64_t ext2fs_size_get(fs_node_t *fn)
-{
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
-	    enode->inode_ref->inode);
-	EXT2FS_DBG("%" PRIu64, size);
-	return size;
-}
-
-unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
-{
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
-	EXT2FS_DBG("%u", count);
-	return count;
-}
-
-bool ext2fs_is_directory(fs_node_t *fn)
-{
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
-	    enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
-	EXT2FS_DBG("%s", is_dir ? "true" : "false");
-	EXT2FS_DBG("%u", enode->inode_ref->index);
-	return is_dir;
-}
-
-bool ext2fs_is_file(fs_node_t *fn)
-{
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
-	    enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
-	EXT2FS_DBG("%s", is_file ? "true" : "false");
-	return is_file;
-}
-
-service_id_t ext2fs_service_get(fs_node_t *fn)
-{
-	EXT2FS_DBG("");
-	ext2fs_node_t *enode = EXT2FS_NODE(fn);
-	return enode->instance->service_id;
-}
-
-/** libfs operations */
-libfs_ops_t ext2fs_libfs_ops = {
-	.root_get = ext2fs_root_get,
-	.match = ext2fs_match,
-	.node_get = ext2fs_node_get,
-	.node_open = ext2fs_node_open,
-	.node_put = ext2fs_node_put,
-	.create = ext2fs_create_node,
-	.destroy = ext2fs_destroy_node,
-	.link = ext2fs_link,
-	.unlink = ext2fs_unlink,
-	.has_children = ext2fs_has_children,
-	.index_get = ext2fs_index_get,
-	.size_get = ext2fs_size_get,
-	.lnkcnt_get = ext2fs_lnkcnt_get,
-	.is_directory = ext2fs_is_directory,
-	.is_file = ext2fs_is_file,
-	.service_get = ext2fs_service_get
-};
-
-/*
- * VFS operations.
- */
-
-static int ext2fs_mounted(service_id_t service_id, const char *opts,
-   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
-{
-	EXT2FS_DBG("");
-	int rc;
-	ext2_filesystem_t *fs;
-	ext2fs_instance_t *inst;
-	bool read_only;
-	
-	/* Allocate libext2 filesystem structure */
-	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
-	if (fs == NULL)
-		return ENOMEM;
-	
-	/* Allocate instance structure */
-	inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
-	if (inst == NULL) {
-		free(fs);
-		return ENOMEM;
-	}
-	
-	/* Initialize the filesystem  */
-	rc = ext2_filesystem_init(fs, service_id);
-	if (rc != EOK) {
-		free(fs);
-		free(inst);
-		return rc;
-	}
-	
-	/* Do some sanity checking */
-	rc = ext2_filesystem_check_sanity(fs);
-	if (rc != EOK) {
-		ext2_filesystem_fini(fs);
-		free(fs);
-		free(inst);
-		return rc;
-	}
-	
-	/* Check flags */
-	rc = ext2_filesystem_check_flags(fs, &read_only);
-	if (rc != EOK) {
-		ext2_filesystem_fini(fs);
-		free(fs);
-		free(inst);
-		return rc;
-	}
-	
-	/* Initialize instance */
-	link_initialize(&inst->link);
-	inst->service_id = service_id;
-	inst->filesystem = fs;
-	inst->open_nodes_count = 0;
-	
-	/* Read root node */
-	fs_node_t *root_node;
-	rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX);
-	if (rc != EOK) {
-		ext2_filesystem_fini(fs);
-		free(fs);
-		free(inst);
-		return rc;
-	}
-	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
-		
-	/* Add instance to the list */
-	fibril_mutex_lock(&instance_list_mutex);
-	list_append(&inst->link, &instance_list);
-	fibril_mutex_unlock(&instance_list_mutex);
-	
-	*index = EXT2_INODE_ROOT_INDEX;
-	*size = 0;
-	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
-	
-	ext2fs_node_put(root_node);
-
-	return EOK;
-}
-
-static int ext2fs_unmounted(service_id_t service_id)
-{
-	EXT2FS_DBG("");
-	ext2fs_instance_t *inst;
-	int rc;
-	
-	rc = ext2fs_instance_get(service_id, &inst);
-	
-	if (rc != EOK)
-		return rc;
-	
-	fibril_mutex_lock(&open_nodes_lock);
-
-	EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count)
-	if (inst->open_nodes_count != 0) {
-		fibril_mutex_unlock(&open_nodes_lock);
-		return EBUSY;
-	}
-	
-	/* Remove the instance from the list */
-	fibril_mutex_lock(&instance_list_mutex);
-	list_remove(&inst->link);
-	fibril_mutex_unlock(&instance_list_mutex);
-
-	fibril_mutex_unlock(&open_nodes_lock);
-	
-	ext2_filesystem_fini(inst->filesystem);
-	
-	return EOK;
-}
-
-static int
-ext2fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
-    size_t *rbytes)
-{
-	EXT2FS_DBG("");
-	
-	ext2fs_instance_t *inst;
-	ext2_inode_ref_t *inode_ref;
-	int rc;
-	
-	/*
-	 * Receive the read request.
-	 */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		return EINVAL;
-	}
-	
-	rc = ext2fs_instance_get(service_id, &inst);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return rc;
-	}
-	
-	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return rc;
-	}
-	
-	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-	    EXT2_INODE_MODE_FILE)) {
-		rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
-		    rbytes);
-	} else if (ext2_inode_is_type(inst->filesystem->superblock,
-	    inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
-		rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
-		    rbytes);
-	} else {
-		/* Other inode types not supported */
-		async_answer_0(callid, ENOTSUP);
-		rc = ENOTSUP;
-	}
-	
-	ext2_filesystem_put_inode_ref(inode_ref);
-	
-	return rc;
-}
-
-/**
- * Determine whether given directory entry name is . or ..
- */
-bool ext2fs_is_dots(const uint8_t *name, size_t name_size) {
-	if (name_size == 1 && name[0] == '.') {
-		return true;
-	}
-	
-	if (name_size == 2 && name[0] == '.' && name[1] == '.') {
-		return true;
-	}
-	
-	return false;
-}
-
-int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
-    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
-{
-	ext2_directory_iterator_t it;
-	aoff64_t next;
-	uint8_t *buf;
-	size_t name_size;
-	int rc;
-	bool found = false;
-	
-	rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return rc;
-	}
-	
-	/* Find next interesting directory entry.
-	 * We want to skip . and .. entries
-	 * as these are not used in HelenOS
-	 */
-	while (it.current != NULL) {
-		if (it.current->inode == 0) {
-			goto skip;
-		}
-		
-		name_size = ext2_directory_entry_ll_get_name_length(
-		    inst->filesystem->superblock, it.current);
-		
-		/* skip . and .. */
-		if (ext2fs_is_dots(&it.current->name, name_size)) {
-			goto skip;
-		}
-		
-		/* The on-disk entry does not contain \0 at the end
-		 * end of entry name, so we copy it to new buffer
-		 * and add the \0 at the end
-		 */
-		buf = malloc(name_size+1);
-		if (buf == NULL) {
-			ext2_directory_iterator_fini(&it);
-			async_answer_0(callid, ENOMEM);
-			return ENOMEM;
-		}
-		memcpy(buf, &it.current->name, name_size);
-		*(buf + name_size) = 0;
-		found = true;
-		(void) async_data_read_finalize(callid, buf, name_size + 1);
-		free(buf);
-		break;
-		
-skip:
-		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK) {
-			ext2_directory_iterator_fini(&it);
-			async_answer_0(callid, rc);
-			return rc;
-		}
-	}
-	
-	if (found) {
-		rc = ext2_directory_iterator_next(&it);
-		if (rc != EOK)
-			return rc;
-		next = it.current_offset;
-	}
-	
-	rc = ext2_directory_iterator_fini(&it);
-	if (rc != EOK)
-		return rc;
-	
-	if (found) {
-		*rbytes = next - pos;
-		return EOK;
-	} else {
-		async_answer_0(callid, ENOENT);
-		return ENOENT;
-	}
-}
-
-int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
-    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
-{
-	int rc;
-	uint32_t block_size;
-	aoff64_t file_block;
-	uint64_t file_size;
-	uint32_t fs_block;
-	size_t offset_in_block;
-	size_t bytes;
-	block_t *block;
-	uint8_t *buffer;
-	
-	file_size = ext2_inode_get_size(inst->filesystem->superblock,
-		inode_ref->inode);
-	
-	if (pos >= file_size) {
-		/* Read 0 bytes successfully */
-		async_data_read_finalize(callid, NULL, 0);
-		*rbytes = 0;
-		return EOK;
-	}
-	
-	/* For now, we only read data from one block at a time */
-	block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
-	file_block = pos / block_size;
-	offset_in_block = pos % block_size;
-	bytes = min(block_size - offset_in_block, size);
-	
-	/* Handle end of file */
-	if (pos + bytes > file_size) {
-		bytes = file_size - pos;
-	}
-	
-	/* Get the real block number */
-	rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
-		inode_ref->inode, file_block, &fs_block);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return rc;
-	}
-	
-	/* Check for sparse file
-	 * If ext2_filesystem_get_inode_data_block_index returned
-	 * fs_block == 0, it means that the given block is not allocated for the 
-	 * file and we need to return a buffer of zeros
-	 */
-	if (fs_block == 0) {
-		buffer = malloc(bytes);
-		if (buffer == NULL) {
-			async_answer_0(callid, ENOMEM);
-			return ENOMEM;
-		}
-		
-		memset(buffer, 0, bytes);
-		
-		async_data_read_finalize(callid, buffer, bytes);
-		*rbytes = bytes;
-		
-		free(buffer);
-		
-		return EOK;
-	}
-	
-	/* Usual case - we need to read a block from device */
-	rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return rc;
-	}
-	
-	assert(offset_in_block + bytes <= block_size);
-	async_data_read_finalize(callid, block->data + offset_in_block, bytes);
-	
-	rc = block_put(block);
-	if (rc != EOK)
-		return rc;
-	
-	*rbytes = bytes;
-	return EOK;
-}
-
-static int
-ext2fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
-    size_t *wbytes, aoff64_t *nsize)
-{
-	EXT2FS_DBG("");
-	return ENOTSUP;
-}
-
-static int
-ext2fs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
-{
-	EXT2FS_DBG("");
-	return ENOTSUP;
-}
-
-static int ext2fs_close(service_id_t service_id, fs_index_t index)
-{
-	EXT2FS_DBG("");
-	return EOK;
-}
-
-static int ext2fs_destroy(service_id_t service_id, fs_index_t index)
-{
-	EXT2FS_DBG("");
-	return ENOTSUP;
-}
-
-static int ext2fs_sync(service_id_t service_id, fs_index_t index)
-{
-	EXT2FS_DBG("");
-	return ENOTSUP;
-}
-
-vfs_out_ops_t ext2fs_ops = {
-	.mounted = ext2fs_mounted,
-	.unmounted = ext2fs_unmounted,
-	.read = ext2fs_read,
-	.write = ext2fs_write,
-	.truncate = ext2fs_truncate,
-	.close = ext2fs_close,
-	.destroy = ext2fs_destroy,
-	.sync = ext2fs_sync,
-};
-
-/**
- * @}
- */
-
Index: uspace/srv/fs/ext4fs/ext4fs_ops.c
===================================================================
--- uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/srv/fs/ext4fs/ext4fs_ops.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -1,3 +1,4 @@
 /*
+ * Copyright (c) 2011 Martin Sucha
  * Copyright (c) 2012 Frantisek Princ
  * All rights reserved.
Index: uspace/srv/logger/initlvl.c
===================================================================
--- uspace/srv/logger/initlvl.c	(revision bebf97d3755a1ed2e30dabc28d9f3070933d5cee)
+++ uspace/srv/logger/initlvl.c	(revision c73910287a21883954d2c3d3c7fcbc1668ecc81f)
@@ -38,4 +38,5 @@
 #include <sysinfo.h>
 #include <str.h>
+#include <stdlib.h>
 #include "logger.h"
 
@@ -91,4 +92,5 @@
 	char level_str[200];
 	str_cpy(level_str, 200, (const char *) argument);
+	free(argument);
 
 	parse_level_settings(level_str);
