Index: uspace/app/fdisk/fdisk.c
===================================================================
--- uspace/app/fdisk/fdisk.c	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/app/fdisk/fdisk.c	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -35,4 +35,5 @@
  */
 
+#include <cap.h>
 #include <errno.h>
 #include <nchoice.h>
@@ -151,5 +152,5 @@
 	nchoice_t *choice = NULL;
 	char *svcname = NULL;
-	fdisk_cap_t cap;
+	cap_spec_t cap;
 	fdisk_dev_info_t *sdev;
 	char *scap = NULL;
@@ -200,7 +201,7 @@
 		}
 
-		fdisk_cap_simplify(&cap);
-
-		rc = fdisk_cap_format(&cap, &scap);
+		cap_simplify(&cap);
+
+		rc = cap_format(&cap, &scap);
 		if (rc != EOK) {
 			assert(rc == ENOMEM);
@@ -445,6 +446,6 @@
 	int rc;
 	fdisk_part_spec_t pspec;
-	fdisk_cap_t cap;
-	fdisk_cap_t mcap;
+	cap_spec_t cap;
+	cap_spec_t mcap;
 	vol_label_supp_t vlsupp;
 	vol_fstype_t fstype = 0;
@@ -466,7 +467,7 @@
 	}
 
-	fdisk_cap_simplify(&mcap);
-
-	rc = fdisk_cap_format(&mcap, &smcap);
+	cap_simplify(&mcap);
+
+	rc = cap_format(&mcap, &smcap);
 	if (rc != EOK) {
 		rc = ENOMEM;
@@ -490,5 +491,5 @@
 			goto error;
 
-		rc = fdisk_cap_parse(scap, &cap);
+		rc = cap_parse(scap, &cap);
 		if (rc == EOK)
 			break;
@@ -586,7 +587,7 @@
 		}
 
-		fdisk_cap_simplify(&pinfo.capacity);
-
-		rc = fdisk_cap_format(&pinfo.capacity, &scap);
+		cap_simplify(&pinfo.capacity);
+
+		rc = cap_format(&pinfo.capacity, &scap);
 		if (rc != EOK) {
 			printf("Out of memory.\n");
@@ -703,6 +704,6 @@
 	fdisk_part_t *part;
 	fdisk_part_info_t pinfo;
-	fdisk_cap_t cap;
-	fdisk_cap_t mcap;
+	cap_spec_t cap;
+	cap_spec_t mcap;
 	fdisk_dev_flags_t dflags;
 	char *sltype = NULL;
@@ -738,7 +739,7 @@
 	}
 
-	fdisk_cap_simplify(&cap);
-
-	rc = fdisk_cap_format(&cap, &sdcap);
+	cap_simplify(&cap);
+
+	rc = cap_format(&cap, &sdcap);
 	if (rc != EOK) {
 		printf("Out of memory.\n");
@@ -792,7 +793,7 @@
 		}
 
-		fdisk_cap_simplify(&pinfo.capacity);
-
-		rc = fdisk_cap_format(&pinfo.capacity, &scap);
+		cap_simplify(&pinfo.capacity);
+
+		rc = cap_format(&pinfo.capacity, &scap);
 		if (rc != EOK) {
 			printf("Out of memory.\n");
@@ -849,7 +850,7 @@
 		}
 
-		fdisk_cap_simplify(&mcap);
-
-		rc = fdisk_cap_format(&mcap, &smcap);
+		cap_simplify(&mcap);
+
+		rc = cap_format(&mcap, &smcap);
 		if (rc != EOK) {
 			rc = ENOMEM;
@@ -871,7 +872,7 @@
 		}
 
-		fdisk_cap_simplify(&mcap);
-
-		rc = fdisk_cap_format(&mcap, &smcap);
+		cap_simplify(&mcap);
+
+		rc = cap_format(&mcap, &smcap);
 		if (rc != EOK) {
 			rc = ENOMEM;
@@ -896,7 +897,7 @@
 		}
 
-		fdisk_cap_simplify(&mcap);
-
-		rc = fdisk_cap_format(&mcap, &smcap);
+		cap_simplify(&mcap);
+
+		rc = cap_format(&mcap, &smcap);
 		if (rc != EOK) {
 			rc = ENOMEM;
@@ -914,7 +915,7 @@
 		}
 
-		fdisk_cap_simplify(&mcap);
-
-		rc = fdisk_cap_format(&mcap, &smcap);
+		cap_simplify(&mcap);
+
+		rc = cap_format(&mcap, &smcap);
 		if (rc != EOK) {
 			rc = ENOMEM;
Index: uspace/app/sysinst/sysinst.c
===================================================================
--- uspace/app/sysinst/sysinst.c	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/app/sysinst/sysinst.c	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -38,4 +38,5 @@
 #include <block.h>
 #include <byteorder.h>
+#include <cap.h>
 #include <errno.h>
 #include <fdisk.h>
@@ -89,5 +90,5 @@
 	fdisk_part_t *part;
 	fdisk_part_spec_t pspec;
-	fdisk_cap_t cap;
+	cap_spec_t cap;
 	service_id_t sid;
 	int rc;
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/lib/c/Makefile	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -64,4 +64,5 @@
 	generic/bd_srv.c \
 	generic/perm.c \
+	generic/cap.c \
 	generic/clipboard.c \
 	generic/config.c \
Index: uspace/lib/c/generic/cap.c
===================================================================
--- uspace/lib/c/generic/cap.c	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
+++ uspace/lib/c/generic/cap.c	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2015 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 libc
+ * @{
+ */
+/**
+ * @file Storage capacity specification.
+ */
+
+#include <cap.h>
+#include <errno.h>
+#include <imath.h>
+#include <stdio.h>
+#include <str.h>
+
+/** Simplified capacity parameters */
+enum {
+	/** Simplified capacity maximum integer digits */
+	scap_max_idig = 3,
+	/** Simplified capacity maximum significant digits */
+	scap_max_sdig = 4
+};
+
+static const char *cu_str[] = {
+	[cu_byte] = "B",
+	[cu_kbyte] = "kB",
+	[cu_mbyte] = "MB",
+	[cu_gbyte] = "GB",
+	[cu_tbyte] = "TB",
+	[cu_pbyte] = "PB",
+	[cu_ebyte] = "EB",
+	[cu_zbyte] = "ZB",
+	[cu_ybyte] = "YB"
+};
+
+void cap_from_blocks(uint64_t nblocks, size_t block_size, cap_spec_t *cap)
+{
+	uint64_t tsize;
+
+	tsize = nblocks * block_size;
+	cap->m = tsize;
+	cap->dp = 0;
+	cap->cunit = cu_byte;
+}
+
+/** Convert capacity to blocks.
+ *
+ * If the value of bytes is not integer, it is properly rounded. If the number
+ * of bytes is not divisible by the number of blocks, it is rounded
+ * up to an integer number of blocks.
+ *
+ * A capacity value entails precision, i.e. it corresponds to a range
+ * of values. @a cvsel selects the value to return. @c cv_nom gives
+ * the nominal (middle) value, @c cv_min gives the minimum value
+ * and @c cv_max gives the maximum value.
+ */
+int cap_spec_to_blocks(cap_spec_t *cap, cap_vsel_t cvsel, size_t block_size,
+    uint64_t *rblocks)
+{
+	int exp;
+	uint64_t bytes;
+	uint64_t f;
+	uint64_t adj;
+	uint64_t blocks;
+	uint64_t rem;
+	int rc;
+
+	exp = cap->cunit * 3 - cap->dp;
+	if (exp < 0) {
+		rc = ipow10_u64(-exp, &f);
+		if (rc != EOK)
+			return ERANGE;
+		bytes = (cap->m + (f / 2)) / f;
+		if (bytes * f - (f / 2) != cap->m)
+			return ERANGE;
+	} else {
+		rc = ipow10_u64(exp, &f);
+		if (rc != EOK)
+			return ERANGE;
+
+		adj = 0;
+		switch (cvsel) {
+		case cv_nom:
+			adj = 0;
+			break;
+		case cv_min:
+			adj = -(f / 2);
+			break;
+		case cv_max:
+			adj = f / 2 - 1;
+			break;
+		}
+
+		bytes = cap->m * f + adj;
+		if ((bytes - adj) / f != cap->m)
+			return ERANGE;
+	}
+
+	rem = bytes % block_size;
+	if ((bytes + rem) < bytes)
+		return ERANGE;
+
+	blocks = (bytes + rem) / block_size;
+
+	*rblocks = blocks;
+	return EOK;
+}
+
+/** Simplify and round capacity to a human-friendly form.
+ *
+ * Change unit and round the number so that we have at most three integer
+ * digits and at most two fractional digits, e.g abc.xy <unit>.
+ */
+void cap_simplify(cap_spec_t *cap)
+{
+	uint64_t div;
+	uint64_t maxv;
+	unsigned sdig;
+	unsigned rdig;
+	int rc;
+
+	/* Change units so that we have at most @c scap_max_idig integer digits */
+	rc = ipow10_u64(scap_max_idig, &maxv);
+	assert(rc == EOK);
+
+	rc = ipow10_u64(cap->dp, &div);
+	assert(rc == EOK);
+
+	while (cap->m / div >= maxv) {
+		++cap->cunit;
+		cap->dp += 3;
+		div = div * 1000;
+	}
+
+	/* Round the number so that we have at most @c scap_max_sdig significant digits */
+	sdig = 1 + ilog10_u64(cap->m); /* number of significant digits */
+	if (sdig > scap_max_sdig) {
+		/* Number of digits to remove */
+		rdig = sdig - scap_max_sdig;
+		if (rdig > cap->dp)
+			rdig = cap->dp;
+
+		rc = ipow10_u64(rdig, &div);
+		assert(rc == EOK);
+
+		cap->m = (cap->m + (div / 2)) / div;
+		cap->dp -= rdig;
+	}
+}
+
+int cap_format(cap_spec_t *cap, char **rstr)
+{
+	int rc;
+	const char *sunit;
+	uint64_t ipart;
+	uint64_t fpart;
+	uint64_t div;
+
+	sunit = NULL;
+
+	if (cap->cunit < 0 || cap->cunit >= CU_LIMIT)
+		assert(false);
+
+	rc = ipow10_u64(cap->dp, &div);
+	if (rc != EOK)
+		return rc;
+
+	ipart = cap->m / div;
+	fpart = cap->m % div;
+
+	sunit = cu_str[cap->cunit];
+	if (cap->dp > 0) {
+		rc = asprintf(rstr, "%" PRIu64 ".%0*" PRIu64 " %s", ipart,
+		    (int)cap->dp, fpart, sunit);
+	} else {
+		rc = asprintf(rstr, "%" PRIu64 " %s", ipart, sunit);
+	}
+	if (rc < 0)
+		return ENOMEM;
+
+	return EOK;
+}
+
+static int cap_digit_val(char c, int *val)
+{
+	switch (c) {
+	case '0': *val = 0; break;
+	case '1': *val = 1; break;
+	case '2': *val = 2; break;
+	case '3': *val = 3; break;
+	case '4': *val = 4; break;
+	case '5': *val = 5; break;
+	case '6': *val = 6; break;
+	case '7': *val = 7; break;
+	case '8': *val = 8; break;
+	case '9': *val = 9; break;
+	default:
+		return EINVAL;
+	}
+
+	return EOK;
+}
+
+int cap_parse(const char *str, cap_spec_t *cap)
+{
+	const char *eptr;
+	const char *p;
+	int d;
+	int dp;
+	unsigned long m;
+	int i;
+
+	m = 0;
+
+	eptr = str;
+	while (cap_digit_val(*eptr, &d) == EOK) {
+		m = m * 10 + d;
+		++eptr;
+	}
+
+	if (*eptr == '.') {
+		++eptr;
+		dp = 0;
+		while (cap_digit_val(*eptr, &d) == EOK) {
+			m = m * 10 + d;
+			++dp;
+			++eptr;
+		}
+	} else {
+		dp = 0;
+	}
+
+	while (*eptr == ' ')
+		++eptr;
+
+	if (*eptr == '\0') {
+		cap->cunit = cu_byte;
+	} else {
+		for (i = 0; i < CU_LIMIT; i++) {
+			if (str_lcasecmp(eptr, cu_str[i],
+			    str_length(cu_str[i])) == 0) {
+				p = eptr + str_size(cu_str[i]);
+				while (*p == ' ')
+					++p;
+				if (*p == '\0')
+					goto found;
+			}
+		}
+
+		return EINVAL;
+found:
+		cap->cunit = i;
+	}
+
+	cap->m = m;
+	cap->dp = dp;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/include/cap.h
===================================================================
--- uspace/lib/c/include/cap.h	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
+++ uspace/lib/c/include/cap.h	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015 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 libc
+ * @{
+ */
+/**
+ * @file Storage capacity specification.
+ */
+
+#ifndef LIBC_CAP_H_
+#define LIBC_CAP_H_
+
+#include <adt/list.h>
+#include <loc.h>
+#include <stdint.h>
+#include <types/label.h>
+#include <types/vol.h>
+#include <vbd.h>
+
+/** Capacity unit */
+typedef enum {
+	cu_byte = 0,
+	cu_kbyte,
+	cu_mbyte,
+	cu_gbyte,
+	cu_tbyte,
+	cu_pbyte,
+	cu_ebyte,
+	cu_zbyte,
+	cu_ybyte
+} cap_unit_t;
+
+/** Which of values within the precision of the capacity */
+typedef enum {
+	/** The nominal (middling) value */
+	cv_nom,
+	/** The minimum value */
+	cv_min,
+	/** The maximum value */
+	cv_max
+} cap_vsel_t;
+
+#define CU_LIMIT (cu_ybyte + 1)
+
+/** Storage capacity.
+ *
+ * Storage capacity represents both value and precision.
+ * It is a decimal floating point value combined with a decimal
+ * capacity unit. There is an integer mantisa @c m which in combination
+ * with the number of decimal positions @c dp gives a decimal floating-point
+ * number. E.g. for m = 1025 and dp = 2 the number is 10.25. If the unit
+ * cunit = cu_kbyte, the capacity is 10.25 kByte, i.e. 10 250 bytes.
+ *
+ * Note that 1.000 kByte is equivalent to 1000 Byte, but 1 kByte is less
+ * precise.
+ */
+typedef struct {
+	/** Mantisa */
+	uint64_t m;
+	/** Decimal positions */
+	unsigned dp;
+	/** Capacity unit */
+	cap_unit_t cunit;
+} cap_spec_t;
+
+extern int cap_format(cap_spec_t *, char **);
+extern int cap_parse(const char *, cap_spec_t *);
+extern void cap_simplify(cap_spec_t *);
+extern void cap_from_blocks(uint64_t, size_t, cap_spec_t *);
+extern int cap_spec_to_blocks(cap_spec_t *, cap_vsel_t, size_t, uint64_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/fdisk/Makefile
===================================================================
--- uspace/lib/fdisk/Makefile	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/lib/fdisk/Makefile	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -33,5 +33,4 @@
 
 SOURCES = \
-	src/cap.c \
 	src/fdisk.c
 
Index: uspace/lib/fdisk/include/fdisk.h
===================================================================
--- uspace/lib/fdisk/include/fdisk.h	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/lib/fdisk/include/fdisk.h	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -49,5 +49,5 @@
 extern int fdisk_dev_info_get_svcname(fdisk_dev_info_t *, char **);
 extern void fdisk_dev_info_get_svcid(fdisk_dev_info_t *, service_id_t *);
-extern int fdisk_dev_info_capacity(fdisk_dev_info_t *, fdisk_cap_t *);
+extern int fdisk_dev_info_capacity(fdisk_dev_info_t *, cap_spec_t *);
 
 extern int fdisk_dev_open(fdisk_t *, service_id_t, fdisk_dev_t **);
@@ -56,5 +56,5 @@
 extern void fdisk_dev_get_flags(fdisk_dev_t *, fdisk_dev_flags_t *);
 extern int fdisk_dev_get_svcname(fdisk_dev_t *, char **);
-extern int fdisk_dev_capacity(fdisk_dev_t *, fdisk_cap_t *);
+extern int fdisk_dev_capacity(fdisk_dev_t *, cap_spec_t *);
 
 extern int fdisk_label_get_info(fdisk_dev_t *, fdisk_label_info_t *);
@@ -65,16 +65,10 @@
 extern fdisk_part_t *fdisk_part_next(fdisk_part_t *);
 extern int fdisk_part_get_info(fdisk_part_t *, fdisk_part_info_t *);
-extern int fdisk_part_get_max_avail(fdisk_dev_t *, fdisk_spc_t, fdisk_cap_t *);
-extern int fdisk_part_get_tot_avail(fdisk_dev_t *, fdisk_spc_t, fdisk_cap_t *);
+extern int fdisk_part_get_max_avail(fdisk_dev_t *, fdisk_spc_t, cap_spec_t *);
+extern int fdisk_part_get_tot_avail(fdisk_dev_t *, fdisk_spc_t, cap_spec_t *);
 extern int fdisk_part_create(fdisk_dev_t *, fdisk_part_spec_t *,
     fdisk_part_t **);
 extern int fdisk_part_destroy(fdisk_part_t *);
 extern void fdisk_pspec_init(fdisk_part_spec_t *);
-
-extern int fdisk_cap_format(fdisk_cap_t *, char **);
-extern int fdisk_cap_parse(const char *, fdisk_cap_t *);
-extern void fdisk_cap_simplify(fdisk_cap_t *);
-extern void fdisk_cap_from_blocks(uint64_t, size_t, fdisk_cap_t *);
-extern int fdisk_cap_to_blocks(fdisk_cap_t *, fdisk_cvsel_t, size_t, uint64_t *);
 
 extern int fdisk_ltype_format(label_type_t, char **);
Index: uspace/lib/fdisk/include/types/fdisk.h
===================================================================
--- uspace/lib/fdisk/include/types/fdisk.h	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/lib/fdisk/include/types/fdisk.h	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -38,4 +38,5 @@
 
 #include <adt/list.h>
+#include <cap.h>
 #include <loc.h>
 #include <stdint.h>
@@ -43,27 +44,4 @@
 #include <types/vol.h>
 #include <vbd.h>
-
-/** Capacity unit */
-typedef enum {
-	cu_byte = 0,
-	cu_kbyte,
-	cu_mbyte,
-	cu_gbyte,
-	cu_tbyte,
-	cu_pbyte,
-	cu_ebyte,
-	cu_zbyte,
-	cu_ybyte
-} fdisk_cunit_t;
-
-/** Which of values within the precision of the capacity */
-typedef enum {
-	/** The nominal (middling) value */
-	fcv_nom,
-	/** The minimum value */
-	fcv_min,
-	/** The maximum value */
-	fcv_max
-} fdisk_cvsel_t;
 
 typedef enum {
@@ -85,25 +63,4 @@
 
 #define CU_LIMIT (cu_ybyte + 1)
-
-/** Partition capacity.
- *
- * Partition capacity represents both value and precision.
- * It is a decimal floating point value combined with a decimal
- * capacity unit. There is an integer mantisa @c m which in combination
- * with the number of decimal positions @c dp gives a decimal floating-point
- * number. E.g. for m = 1025 and dp = 2 the number is 10.25. If the unit
- * cunit = cu_kbyte, the capacity is 10.25 kByte, i.e. 10 250 bytes.
- *
- * Note that 1.000 kByte is equivalent to 1000 Byte, but 1 kByte is less
- * precise.
- */
-typedef struct {
-	/** Mantisa */
-	uint64_t m;
-	/** Decimal positions */
-	unsigned dp;
-	/** Capacity unit */
-	fdisk_cunit_t cunit;
-} fdisk_cap_t;
 
 /** List of devices available for managing by fdisk */
@@ -169,5 +126,5 @@
 	link_t llog_ba;
 	/** Capacity */
-	fdisk_cap_t capacity;
+	cap_spec_t capacity;
 	/** Partition kind */
 	label_pkind_t pkind;
@@ -193,5 +150,5 @@
 typedef struct {
 	/** Desired capacity */
-	fdisk_cap_t capacity;
+	cap_spec_t capacity;
 	/** Partition kind */
 	label_pkind_t pkind;
@@ -205,5 +162,5 @@
 typedef struct {
 	/** Capacity */
-	fdisk_cap_t capacity;
+	cap_spec_t capacity;
 	/** Partition kind */
 	label_pkind_t pkind;
Index: uspace/lib/fdisk/src/cap.c
===================================================================
--- uspace/lib/fdisk/src/cap.c	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ 	(revision )
@@ -1,288 +1,0 @@
-/*
- * Copyright (c) 2015 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 libfdisk
- * @{
- */
-/**
- * @file Disk management library.
- */
-
-#include <errno.h>
-#include <fdisk.h>
-#include <imath.h>
-#include <stdio.h>
-#include <str.h>
-
-/** Simplified capacity parameters */
-enum {
-	/** Simplified capacity maximum integer digits */
-	scap_max_idig = 3,
-	/** Simplified capacity maximum significant digits */
-	scap_max_sdig = 4
-};
-
-static const char *cu_str[] = {
-	[cu_byte] = "B",
-	[cu_kbyte] = "kB",
-	[cu_mbyte] = "MB",
-	[cu_gbyte] = "GB",
-	[cu_tbyte] = "TB",
-	[cu_pbyte] = "PB",
-	[cu_ebyte] = "EB",
-	[cu_zbyte] = "ZB",
-	[cu_ybyte] = "YB"
-};
-
-void fdisk_cap_from_blocks(uint64_t nblocks, size_t block_size,
-    fdisk_cap_t *cap)
-{
-	uint64_t tsize;
-
-	tsize = nblocks * block_size;
-	cap->m = tsize;
-	cap->dp = 0;
-	cap->cunit = cu_byte;
-}
-
-/** Convert capacity to blocks.
- *
- * If the value of bytes is not integer, it is properly rounded. If the number
- * of bytes is not divisible by the number of blocks, it is rounded
- * up to an integer number of blocks.
- *
- * A capacity value entails precision, i.e. it corresponds to a range
- * of values. @a cvsel selects the value to return. @c fcv_nom gives
- * the nominal (middle) value, @c fcv_min gives the minimum value
- * and @c fcv_max gives the maximum value.
- */
-int fdisk_cap_to_blocks(fdisk_cap_t *cap, fdisk_cvsel_t cvsel,
-    size_t block_size, uint64_t *rblocks)
-{
-	int exp;
-	uint64_t bytes;
-	uint64_t f;
-	uint64_t adj;
-	uint64_t blocks;
-	uint64_t rem;
-	int rc;
-
-	exp = cap->cunit * 3 - cap->dp;
-	if (exp < 0) {
-		rc = ipow10_u64(-exp, &f);
-		if (rc != EOK)
-			return ERANGE;
-		bytes = (cap->m + (f / 2)) / f;
-		if (bytes * f - (f / 2) != cap->m)
-			return ERANGE;
-	} else {
-		rc = ipow10_u64(exp, &f);
-		if (rc != EOK)
-			return ERANGE;
-
-		adj = 0;
-		switch (cvsel) {
-		case fcv_nom:
-			adj = 0;
-			break;
-		case fcv_min:
-			adj = -(f / 2);
-			break;
-		case fcv_max:
-			adj = f / 2 - 1;
-			break;
-		}
-
-		bytes = cap->m * f + adj;
-		if ((bytes - adj) / f != cap->m)
-			return ERANGE;
-	}
-
-	rem = bytes % block_size;
-	if ((bytes + rem) < bytes)
-		return ERANGE;
-
-	blocks = (bytes + rem) / block_size;
-
-	*rblocks = blocks;
-	return EOK;
-}
-
-/** Simplify and round capacity to a human-friendly form.
- *
- * Change unit and round the number so that we have at most three integer
- * digits and at most two fractional digits, e.g abc.xy <unit>.
- */
-void fdisk_cap_simplify(fdisk_cap_t *cap)
-{
-	uint64_t div;
-	uint64_t maxv;
-	unsigned sdig;
-	unsigned rdig;
-	int rc;
-
-	/* Change units so that we have at most @c scap_max_idig integer digits */
-	rc = ipow10_u64(scap_max_idig, &maxv);
-	assert(rc == EOK);
-
-	rc = ipow10_u64(cap->dp, &div);
-	assert(rc == EOK);
-
-	while (cap->m / div >= maxv) {
-		++cap->cunit;
-		cap->dp += 3;
-		div = div * 1000;
-	}
-
-	/* Round the number so that we have at most @c scap_max_sdig significant digits */
-	sdig = 1 + ilog10_u64(cap->m); /* number of significant digits */
-	if (sdig > scap_max_sdig) {
-		/* Number of digits to remove */
-		rdig = sdig - scap_max_sdig;
-		if (rdig > cap->dp)
-			rdig = cap->dp;
-
-		rc = ipow10_u64(rdig, &div);
-		assert(rc == EOK);
-
-		cap->m = (cap->m + (div / 2)) / div;
-		cap->dp -= rdig;
-	}
-}
-
-int fdisk_cap_format(fdisk_cap_t *cap, char **rstr)
-{
-	int rc;
-	const char *sunit;
-	uint64_t ipart;
-	uint64_t fpart;
-	uint64_t div;
-
-	sunit = NULL;
-
-	if (cap->cunit < 0 || cap->cunit >= CU_LIMIT)
-		assert(false);
-
-	rc = ipow10_u64(cap->dp, &div);
-	if (rc != EOK)
-		return rc;
-
-	ipart = cap->m / div;
-	fpart = cap->m % div;
-
-	sunit = cu_str[cap->cunit];
-	if (cap->dp > 0) {
-		rc = asprintf(rstr, "%" PRIu64 ".%0*" PRIu64 " %s", ipart,
-		    (int)cap->dp, fpart, sunit);
-	} else {
-		rc = asprintf(rstr, "%" PRIu64 " %s", ipart, sunit);
-	}
-	if (rc < 0)
-		return ENOMEM;
-
-	return EOK;
-}
-
-static int fdisk_digit_val(char c, int *val)
-{
-	switch (c) {
-	case '0': *val = 0; break;
-	case '1': *val = 1; break;
-	case '2': *val = 2; break;
-	case '3': *val = 3; break;
-	case '4': *val = 4; break;
-	case '5': *val = 5; break;
-	case '6': *val = 6; break;
-	case '7': *val = 7; break;
-	case '8': *val = 8; break;
-	case '9': *val = 9; break;
-	default:
-		return EINVAL;
-	}
-
-	return EOK;
-}
-
-int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
-{
-	const char *eptr;
-	const char *p;
-	int d;
-	int dp;
-	unsigned long m;
-	int i;
-
-	m = 0;
-
-	eptr = str;
-	while (fdisk_digit_val(*eptr, &d) == EOK) {
-		m = m * 10 + d;
-		++eptr;
-	}
-
-	if (*eptr == '.') {
-		++eptr;
-		dp = 0;
-		while (fdisk_digit_val(*eptr, &d) == EOK) {
-			m = m * 10 + d;
-			++dp;
-			++eptr;
-		}
-	} else {
-		dp = 0;
-	}
-
-	while (*eptr == ' ')
-		++eptr;
-
-	if (*eptr == '\0') {
-		cap->cunit = cu_byte;
-	} else {
-		for (i = 0; i < CU_LIMIT; i++) {
-			if (str_lcasecmp(eptr, cu_str[i],
-			    str_length(cu_str[i])) == 0) {
-				p = eptr + str_size(cu_str[i]);
-				while (*p == ' ')
-					++p;
-				if (*p == '\0')
-					goto found;
-			}
-		}
-
-		return EINVAL;
-found:
-		cap->cunit = i;
-	}
-
-	cap->m = m;
-	cap->dp = dp;
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/lib/fdisk/src/fdisk.c
===================================================================
--- uspace/lib/fdisk/src/fdisk.c	(revision 9520af7e6dd61442acc104857653aae6a31c1197)
+++ uspace/lib/fdisk/src/fdisk.c	(revision 6c4eedf11368c6c47c86ab45352946ba67b15bdc)
@@ -35,4 +35,5 @@
 
 #include <adt/list.h>
+#include <cap.h>
 #include <errno.h>
 #include <fdisk.h>
@@ -218,5 +219,5 @@
 }
 
-int fdisk_dev_info_capacity(fdisk_dev_info_t *info, fdisk_cap_t *cap)
+int fdisk_dev_info_capacity(fdisk_dev_info_t *info, cap_spec_t *cap)
 {
 	vbd_disk_info_t vinfo;
@@ -227,5 +228,5 @@
 		return EIO;
 
-	fdisk_cap_from_blocks(vinfo.nblocks, vinfo.block_size, cap);
+	cap_from_blocks(vinfo.nblocks, vinfo.block_size, cap);
 	return EOK;
 }
@@ -294,5 +295,5 @@
 		dev->ext_part = part;
 
-	fdisk_cap_from_blocks(part->nblocks, dev->dinfo.block_size,
+	cap_from_blocks(part->nblocks, dev->dinfo.block_size,
 	    &part->capacity);
 	part->part_id = partid;
@@ -535,7 +536,7 @@
 }
 
-int fdisk_dev_capacity(fdisk_dev_t *dev, fdisk_cap_t *cap)
-{
-	fdisk_cap_from_blocks(dev->dinfo.nblocks, dev->dinfo.block_size, cap);
+int fdisk_dev_capacity(fdisk_dev_t *dev, cap_spec_t *cap)
+{
+	cap_from_blocks(dev->dinfo.nblocks, dev->dinfo.block_size, cap);
 	return EOK;
 }
@@ -677,5 +678,5 @@
 
 /** Get size of largest free block. */
-int fdisk_part_get_max_avail(fdisk_dev_t *dev, fdisk_spc_t spc, fdisk_cap_t *cap)
+int fdisk_part_get_max_avail(fdisk_dev_t *dev, fdisk_spc_t spc, cap_spec_t *cap)
 {
 	int rc;
@@ -696,5 +697,5 @@
 	}
 
-	fdisk_cap_from_blocks(nb, dev->dinfo.block_size, cap);
+	cap_from_blocks(nb, dev->dinfo.block_size, cap);
 	return EOK;
 }
@@ -702,5 +703,5 @@
 /** Get total free space capacity. */
 int fdisk_part_get_tot_avail(fdisk_dev_t *dev, fdisk_spc_t spc,
-    fdisk_cap_t *cap)
+    cap_spec_t *cap)
 {
 	fdisk_free_range_t fr;
@@ -724,5 +725,5 @@
 	} while (fdisk_free_range_next(&fr));
 
-	fdisk_cap_from_blocks(totb, dev->dinfo.block_size, cap);
+	cap_from_blocks(totb, dev->dinfo.block_size, cap);
 	return EOK;
 }
@@ -995,15 +996,15 @@
 	int rc;
 
-	rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_nom, dev->dinfo.block_size,
+	rc = cap_spec_to_blocks(&pspec->capacity, cv_nom, dev->dinfo.block_size,
 	    &nom_blocks);
 	if (rc != EOK)
 		return rc;
 
-	rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_min, dev->dinfo.block_size,
+	rc = cap_spec_to_blocks(&pspec->capacity, cv_min, dev->dinfo.block_size,
 	    &min_blocks);
 	if (rc != EOK)
 		return rc;
 
-	rc = fdisk_cap_to_blocks(&pspec->capacity, fcv_max, dev->dinfo.block_size,
+	rc = cap_spec_to_blocks(&pspec->capacity, cv_max, dev->dinfo.block_size,
 	    &max_blocks);
 	if (rc != EOK)
