Index: .bzrignore
===================================================================
--- .bzrignore	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ .bzrignore	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -34,4 +34,5 @@
 uspace/app/dnsres/dnsres
 uspace/app/edit/edit
+uspace/app/fdisk/fdisk
 uspace/app/fontviewer/fontviewer
 uspace/app/getterm/getterm
@@ -91,4 +92,5 @@
 uspace/dist/app/dnsres
 uspace/dist/app/edit
+uspace/dist/app/fdisk
 uspace/dist/app/fontviewer
 uspace/dist/app/getterm
Index: uspace/app/fdisk/fdisk.c
===================================================================
--- uspace/app/fdisk/fdisk.c	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/app/fdisk/fdisk.c	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -66,8 +66,10 @@
 	char *svcname = NULL;
 	fdisk_cap_t cap;
+	fdisk_dev_info_t *sdev;
 	char *scap = NULL;
 	char *dtext = NULL;
 	service_id_t svcid;
 	void *sel;
+	int ndevs;
 	int rc;
 
@@ -93,6 +95,9 @@
 
 	info = fdisk_dev_first(devlist);
+	ndevs = 0;
 	while (info != NULL) {
-		rc = fdisk_dev_get_svcname(info, &svcname);
+		++ndevs;
+
+		rc = fdisk_dev_info_get_svcname(info, &svcname);
 		if (rc != EOK) {
 			printf("Error getting device service name.\n");
@@ -100,5 +105,5 @@
 		}
 
-		rc = fdisk_dev_capacity(info, &cap);
+		rc = fdisk_dev_info_capacity(info, &cap);
 		if (rc != EOK) {
 			printf("Error getting device capacity.\n");
@@ -138,4 +143,17 @@
 	}
 
+	if (ndevs == 0) {
+		printf("No disk devices found.\n");
+		rc = ENOENT;
+		goto error;
+	}
+
+	rc = nchoice_add(choice, "Exit", NULL);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		printf("Out of memory.\n");
+		goto error;
+	}
+
 	rc = nchoice_get(choice, &sel);
 	if (rc != EOK) {
@@ -144,8 +162,12 @@
 	}
 
-	fdisk_dev_get_svcid((fdisk_dev_info_t *)sel, &svcid);
+	sdev = (fdisk_dev_info_t *)sel;
+	if (sdev != NULL) {
+		fdisk_dev_info_get_svcid(sdev, &svcid);
+	} else {
+		svcid = 0;
+	}
+
 	fdisk_dev_list_free(devlist);
-
-	printf("Selected dev with sid=%zu\n", svcid);
 
 	nchoice_destroy(choice);
@@ -167,4 +189,6 @@
 	nchoice_t *choice = NULL;
 	void *sel;
+	char *sltype = NULL;
+	int i;
 	int rc;
 
@@ -183,16 +207,18 @@
 	}
 
-	rc = nchoice_add(choice, "GPT", (void *)fdl_gpt);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		goto error;
-	}
-
-	rc = nchoice_add(choice, "MBR", (void *)fdl_mbr);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		goto error;
+	for (i = FDL_CREATE_LO; i < FDL_CREATE_HI; i++) {
+		rc = fdisk_ltype_format(i, &sltype);
+		if (rc != EOK)
+			goto error;
+
+		rc = nchoice_add(choice, sltype, (void *)(uintptr_t)i);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		free(sltype);
+		sltype = NULL;
 	}
 
@@ -212,4 +238,5 @@
 	return EOK;
 error:
+	free(sltype);
 	if (choice != NULL)
 		nchoice_destroy(choice);
@@ -217,4 +244,216 @@
 }
 
+static int fdsk_delete_label(fdisk_dev_t *dev)
+{
+	int rc;
+
+	rc = fdisk_label_destroy(dev);
+	if (rc != EOK) {
+		printf("Error deleting label.\n");
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int fdsk_select_fstype(fdisk_fstype_t *fstype)
+{
+	nchoice_t *choice = NULL;
+	void *sel;
+	char *sfstype;
+	int i;
+	int rc;
+
+	rc = nchoice_create(&choice);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		printf("Out of memory.\n");
+		goto error;
+	}
+
+	rc = nchoice_set_prompt(choice, "Select file system type");
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		printf("Out of memory.\n");
+		goto error;
+	}
+
+	for (i = FDFS_CREATE_LO; i < FDFS_CREATE_HI; i++) {
+		rc = fdisk_fstype_format(i, &sfstype);
+		if (rc != EOK)
+			goto error;
+
+		rc = nchoice_add(choice, sfstype, (void *)(uintptr_t)i);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		free(sfstype);
+		sfstype = NULL;
+	}
+
+	rc = nchoice_get(choice, &sel);
+	if (rc != EOK) {
+		printf("Error getting user selection.\n");
+		goto error;
+	}
+
+	nchoice_destroy(choice);
+	*fstype = (fdisk_fstype_t)sel;
+	return EOK;
+error:
+	free(sfstype);
+	if (choice != NULL)
+		nchoice_destroy(choice);
+	return rc;
+}
+
+static int fdsk_create_part(fdisk_dev_t *dev)
+{
+	int rc;
+	fdisk_part_spec_t pspec;
+	fdisk_cap_t cap;
+	fdisk_fstype_t fstype;
+	tinput_t *tinput = NULL;
+	char *scap;
+
+	tinput = tinput_new();
+	if (tinput == NULL) {
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = tinput_set_prompt(tinput, "?> ");
+	if (rc != EOK)
+		goto error;
+
+	while (true) {
+		printf("Enter capacity of new partition.\n");
+		rc = tinput_read(tinput, &scap);
+		if (rc != EOK)
+			goto error;
+
+		rc = fdisk_cap_parse(scap, &cap);
+		if (rc == EOK)
+			break;
+	}
+
+	tinput_destroy(tinput);
+
+	rc = fdsk_select_fstype(&fstype);
+	if (rc != EOK)
+		goto error;
+
+	fdisk_pspec_init(&pspec);
+	pspec.capacity = cap;
+	pspec.fstype = fstype;
+
+	rc = fdisk_part_create(dev, &pspec, NULL);
+	if (rc != EOK) {
+		printf("Error creating partition.\n");
+		goto error;
+	}
+
+	return EOK;
+error:
+	if (tinput != NULL)
+		tinput_destroy(tinput);
+	return rc;
+}
+
+static int fdsk_delete_part(fdisk_dev_t *dev)
+{
+	nchoice_t *choice = NULL;
+	fdisk_part_t *part;
+	fdisk_part_info_t pinfo;
+	char *scap = NULL;
+	char *sfstype = NULL;
+	char *sdesc = NULL;
+	void *sel;
+	int rc;
+
+	rc = nchoice_create(&choice);
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		printf("Out of memory.\n");
+		goto error;
+	}
+
+	rc = nchoice_set_prompt(choice, "Select partition to delete");
+	if (rc != EOK) {
+		assert(rc == ENOMEM);
+		printf("Out of memory.\n");
+		goto error;
+	}
+
+	part = fdisk_part_first(dev);
+	while (part != NULL) {
+		rc = fdisk_part_get_info(part, &pinfo);
+		if (rc != EOK) {
+			printf("Error getting partition information.\n");
+			goto error;
+		}
+
+		rc = fdisk_cap_format(&pinfo.capacity, &scap);
+		if (rc != EOK) {
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		rc = fdisk_fstype_format(pinfo.fstype, &sfstype);
+		if (rc != EOK) {
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		rc = asprintf(&sdesc, "%s, %s", scap, sfstype);
+		if (rc < 0) {
+			rc = ENOMEM;
+			goto error;
+		}
+
+		rc = nchoice_add(choice, sdesc, (void *)part);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		free(scap);
+		scap = NULL;
+		free(sfstype);
+		sfstype = NULL;
+		free(sdesc);
+		sdesc = NULL;
+
+		part = fdisk_part_next(part);
+	}
+
+	rc = nchoice_get(choice, &sel);
+	if (rc != EOK) {
+		printf("Error getting user selection.\n");
+		goto error;
+	}
+
+	rc = fdisk_part_destroy((fdisk_part_t *)sel);
+	if (rc != EOK) {
+		printf("Error deleting partition.\n");
+		return rc;
+	}
+
+	nchoice_destroy(choice);
+	return EOK;
+error:
+	free(scap);
+	free(sfstype);
+	free(sdesc);
+
+	if (choice != NULL)
+		nchoice_destroy(choice);
+	return rc;
+}
+
 /** Device menu */
 static int fdsk_dev_menu(fdisk_dev_t *dev)
@@ -222,6 +461,14 @@
 	nchoice_t *choice = NULL;
 	fdisk_label_info_t linfo;
+	fdisk_part_t *part;
+	fdisk_part_info_t pinfo;
+	fdisk_cap_t cap;
 	char *sltype = NULL;
-	int rc;
+	char *sdcap = NULL;
+	char *scap = NULL;
+	char *sfstype = NULL;
+	char *svcname = NULL;
+	int rc;
+	int npart;
 	void *sel;
 
@@ -240,4 +487,22 @@
 	}
 
+	rc = fdisk_dev_capacity(dev, &cap);
+	if (rc != EOK) {
+		printf("Error getting device capacity.\n");
+		goto error;
+	}
+
+	rc = fdisk_cap_format(&cap, &sdcap);
+	if (rc != EOK) {
+		printf("Out of memory.\n");
+		goto error;
+	}
+
+	rc = fdisk_dev_get_svcname(dev, &svcname);
+	if (rc != EOK) {
+		printf("Error getting device service name.\n");
+		goto error;
+	}
+
 	rc = fdisk_label_get_info(dev, &linfo);
 	if (rc != EOK) {
@@ -253,7 +518,41 @@
 	}
 
+	printf("Device: %s, %s\n", sdcap, svcname);
 	printf("Label type: %s\n", sltype);
 	free(sltype);
 	sltype = NULL;
+	free(sdcap);
+	sdcap = NULL;
+
+	part = fdisk_part_first(dev);
+	npart = 0;
+	while (part != NULL) {
+		++npart;
+		rc = fdisk_part_get_info(part, &pinfo);
+		if (rc != EOK) {
+			printf("Error getting partition information.\n");
+			goto error;
+		}
+
+		rc = fdisk_cap_format(&pinfo.capacity, &scap);
+		if (rc != EOK) {
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		rc = fdisk_fstype_format(pinfo.fstype, &sfstype);
+		if (rc != EOK) {
+			printf("Out of memory.\n");
+			goto error;
+		}
+
+		printf("Partition %d: %s, %s\n", npart, scap, sfstype);
+		free(scap);
+		scap = NULL;
+		free(sfstype);
+		sfstype = NULL;
+
+		part = fdisk_part_next(part);
+	}
 
 	rc = nchoice_set_prompt(choice, "Select action");
@@ -262,4 +561,24 @@
 		printf("Out of memory.\n");
 		goto error;
+	}
+
+	if (linfo.ltype != fdl_none) {
+		rc = nchoice_add(choice, "Create partition",
+		    (void *)devac_create_part);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			printf("Out of memory.\n");
+			goto error;
+		}
+	}
+
+	if (npart > 0) {
+		rc = nchoice_add(choice, "Delete partition",
+		    (void *)devac_delete_part);
+		if (rc != EOK) {
+			assert(rc == ENOMEM);
+			printf("Out of memory.\n");
+			goto error;
+		}
 	}
 
@@ -280,20 +599,4 @@
 			goto error;
 		}
-	}
-
-	rc = nchoice_add(choice, "Create partition",
-	    (void *)devac_create_part);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		goto error;
-	}
-
-	rc = nchoice_add(choice, "Delete partition",
-	    (void *)devac_delete_part);
-	if (rc != EOK) {
-		assert(rc == ENOMEM);
-		printf("Out of memory.\n");
-		goto error;
 	}
 
@@ -318,11 +621,17 @@
 		break;
 	case devac_delete_label:
-		rc = fdisk_label_destroy(dev);
+		rc = fdsk_delete_label(dev);
 		if (rc != EOK)
 			goto error;
 		break;
 	case devac_create_part:
+		rc = fdsk_create_part(dev);
+		if (rc != EOK)
+			goto error;
 		break;
 	case devac_delete_part:
+		rc = fdsk_delete_part(dev);
+		if (rc != EOK)
+			goto error;
 		break;
 	case devac_exit:
@@ -334,4 +643,8 @@
 	return EOK;
 error:
+	free(sdcap);
+	free(scap);
+	free(sfstype);
+	free(svcname);
 	if (choice != NULL)
 		nchoice_destroy(choice);
@@ -349,4 +662,7 @@
 		return 1;
 
+	if (svcid == 0)
+		return 0;
+
 	rc = fdisk_dev_open(svcid, &dev);
 	if (rc != EOK) {
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/lib/c/generic/str.c	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -519,5 +519,5 @@
 	wchar_t c1 = 0;
 	wchar_t c2 = 0;
-	
+
 	size_t off1 = 0;
 	size_t off2 = 0;
@@ -529,10 +529,10 @@
 		if (c1 < c2)
 			return -1;
-		
+
 		if (c1 > c2)
 			return 1;
 
 		if (c1 == 0 || c2 == 0)
-			break;		
+			break;
 	}
 
@@ -566,8 +566,8 @@
 	wchar_t c1 = 0;
 	wchar_t c2 = 0;
-	
+
 	size_t off1 = 0;
 	size_t off2 = 0;
-	
+
 	size_t len = 0;
 
@@ -578,4 +578,104 @@
 		c1 = str_decode(s1, &off1, STR_NO_LIMIT);
 		c2 = str_decode(s2, &off2, STR_NO_LIMIT);
+
+		if (c1 < c2)
+			return -1;
+
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;
+
+		++len;
+	}
+
+	return 0;
+
+}
+
+/** Compare two NULL terminated strings in case-insensitive manner.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff their length is equal
+ * and both strings consist of the same sequence of characters
+ * when converted to lower case.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero.
+ *
+ * @param s1 First string to compare.
+ * @param s2 Second string to compare.
+ *
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
+ *
+ */
+int str_casecmp(const char *s1, const char *s2)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+
+	size_t off1 = 0;
+	size_t off2 = 0;
+
+	while (true) {
+		c1 = tolower(str_decode(s1, &off1, STR_NO_LIMIT));
+		c2 = tolower(str_decode(s2, &off2, STR_NO_LIMIT));
+
+		if (c1 < c2)
+			return -1;
+
+		if (c1 > c2)
+			return 1;
+
+		if (c1 == 0 || c2 == 0)
+			break;
+	}
+
+	return 0;
+}
+
+/** Compare two NULL terminated strings with length limit in case-insensitive
+ * manner.
+ *
+ * Do a char-by-char comparison of two NULL-terminated strings.
+ * The strings are considered equal iff
+ * min(str_length(s1), max_len) == min(str_length(s2), max_len)
+ * and both strings consist of the same sequence of characters,
+ * up to max_len characters.
+ *
+ * A string S1 is less than another string S2 if it has a character with
+ * lower value at the first character position where the strings differ.
+ * If the strings differ in length, the shorter one is treated as if
+ * padded by characters with a value of zero. Only the first max_len
+ * characters are considered.
+ *
+ * @param s1      First string to compare.
+ * @param s2      Second string to compare.
+ * @param max_len Maximum number of characters to consider.
+ *
+ * @return 0 if the strings are equal, -1 if the first is less than the second,
+ *         1 if the second is less than the first.
+ *
+ */
+int str_lcasecmp(const char *s1, const char *s2, size_t max_len)
+{
+	wchar_t c1 = 0;
+	wchar_t c2 = 0;
+	
+	size_t off1 = 0;
+	size_t off2 = 0;
+	
+	size_t len = 0;
+
+	while (true) {
+		if (len >= max_len)
+			break;
+
+		c1 = tolower(str_decode(s1, &off1, STR_NO_LIMIT));
+		c2 = tolower(str_decode(s2, &off2, STR_NO_LIMIT));
 
 		if (c1 < c2)
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/lib/c/include/str.h	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -82,4 +82,6 @@
 extern int str_cmp(const char *s1, const char *s2);
 extern int str_lcmp(const char *s1, const char *s2, size_t max_len);
+extern int str_casecmp(const char *s1, const char *s2);
+extern int str_lcasecmp(const char *s1, const char *s2, size_t max_len);
 
 extern bool str_test_prefix(const char *s, const char *p);
Index: uspace/lib/fdisk/include/fdisk.h
===================================================================
--- uspace/lib/fdisk/include/fdisk.h	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/lib/fdisk/include/fdisk.h	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -44,10 +44,12 @@
 extern fdisk_dev_info_t *fdisk_dev_first(fdisk_dev_list_t *);
 extern fdisk_dev_info_t *fdisk_dev_next(fdisk_dev_info_t *);
-extern int fdisk_dev_get_svcname(fdisk_dev_info_t *, char **);
-extern void fdisk_dev_get_svcid(fdisk_dev_info_t *, service_id_t *);
-extern int fdisk_dev_capacity(fdisk_dev_info_t *, fdisk_cap_t *);
+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_open(service_id_t, fdisk_dev_t **);
 extern void fdisk_dev_close(fdisk_dev_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_label_get_info(fdisk_dev_t *, fdisk_label_info_t *);
@@ -57,11 +59,15 @@
 extern fdisk_part_t *fdisk_part_first(fdisk_dev_t *);
 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_cap_t *);
-extern int fdisk_part_create(fdisk_dev_t *, fdisk_partspec_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 int fdisk_ltype_format(fdisk_label_type_t, char **);
+extern int fdisk_fstype_format(fdisk_fstype_t, char **);
 
 #endif
Index: uspace/lib/fdisk/include/types/fdisk.h
===================================================================
--- uspace/lib/fdisk/include/types/fdisk.h	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/lib/fdisk/include/types/fdisk.h	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -41,4 +41,41 @@
 #include <stdint.h>
 
+typedef enum {
+	cu_byte = 0,
+	cu_kbyte,
+	cu_mbyte,
+	cu_gbyte,
+	cu_tbyte,
+	cu_pbyte,
+	cu_ebyte,
+	cu_zbyte,
+	cu_ybyte
+} fdisk_cunit_t;
+
+#define CU_LIMIT (cu_ybyte + 1)
+
+/** File system type */
+typedef enum {
+	fdfs_none = 0,
+	fdfs_unknown,
+	fdfs_exfat,
+	fdfs_fat,
+	fdfs_minix,
+	fdfs_ext4
+} fdisk_fstype_t;
+
+/** Highest fstype value + 1 */
+#define FDFS_LIMIT (fdfs_ext4 + 1)
+/** Lowest fstype allowed for creation */
+#define FDFS_CREATE_LO fdfs_exfat
+/** Highest fstype allowed for creation + 1 */
+#define FDFS_CREATE_HI (fdfs_ext4 + 1)
+
+/** Partition capacity */
+typedef struct {
+	uint64_t value;
+	fdisk_cunit_t cunit;
+} fdisk_cap_t;
+
 /** List of devices available for managing by fdisk */
 typedef struct {
@@ -70,7 +107,19 @@
 } fdisk_label_type_t;
 
+/** Highest label type + 1 */
+#define FDL_LIMIT (fdl_gpt + 1)
+/** Lowest label type allowed for creation */
+#define FDL_CREATE_LO fdl_mbr
+/** Highest label type allowed for creation + 1 */
+#define FDL_CREATE_HI (fdl_gpt + 1)
+
 /** Open fdisk device */
 typedef struct {
+	/** Label type */
 	fdisk_label_type_t ltype;
+	/** Partitions */
+	list_t parts; /* of fdisk_part_t */
+	/** Service ID */
+	service_id_t sid;
 } fdisk_dev_t;
 
@@ -82,27 +131,28 @@
 /** Partition */
 typedef struct {
+	/** Containing device */
+	fdisk_dev_t *dev;
+	/** Link to fdisk_dev_t.parts */
+	link_t ldev;
+	/** Capacity */
+	fdisk_cap_t capacity;
+	/** File system type */
+	fdisk_fstype_t fstype;
 } fdisk_part_t;
-
-typedef enum {
-	cu_byte = 0,
-	cu_kbyte,
-	cu_mbyte,
-	cu_gbyte,
-	cu_tbyte,
-	cu_pbyte,
-	cu_ebyte,
-	cu_zbyte,
-	cu_ybyte
-} fdisk_cunit_t;
-
-/** Partition capacity */
-typedef struct {
-	uint64_t value;
-	fdisk_cunit_t cunit;
-} fdisk_cap_t;
 
 /** Specification of new partition */
 typedef struct {
-} fdisk_partspec_t;
+	/** Desired capacity */
+	fdisk_cap_t capacity;
+	/** File system type */
+	fdisk_fstype_t fstype;
+} fdisk_part_spec_t;
+
+/** Partition info */
+typedef struct {
+	fdisk_cap_t capacity;
+	/** File system type */
+	fdisk_fstype_t fstype;
+} fdisk_part_info_t;
 
 #endif
Index: uspace/lib/fdisk/src/fdisk.c
===================================================================
--- uspace/lib/fdisk/src/fdisk.c	(revision e96047c95e2e340c70836a813474717696c06c3e)
+++ uspace/lib/fdisk/src/fdisk.c	(revision 8227d634855cabb163487dd2efe9a1b301377b9d)
@@ -39,7 +39,20 @@
 #include <fdisk.h>
 #include <loc.h>
+#include <mem.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <str.h>
+
+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"
+};
 
 static void fdisk_dev_info_delete(fdisk_dev_info_t *info)
@@ -144,10 +157,10 @@
 }
 
-void fdisk_dev_get_svcid(fdisk_dev_info_t *info, service_id_t *rsid)
+void fdisk_dev_info_get_svcid(fdisk_dev_info_t *info, service_id_t *rsid)
 {
 	*rsid = info->svcid;
 }
 
-int fdisk_dev_get_svcname(fdisk_dev_info_t *info, char **rname)
+int fdisk_dev_info_get_svcname(fdisk_dev_info_t *info, char **rname)
 {
 	char *name;
@@ -169,5 +182,5 @@
 }
 
-int fdisk_dev_capacity(fdisk_dev_info_t *info, fdisk_cap_t *cap)
+int fdisk_dev_info_capacity(fdisk_dev_info_t *info, fdisk_cap_t *cap)
 {
 	size_t bsize;
@@ -179,4 +192,6 @@
 		if (rc != EOK)
 			return rc;
+
+		info->blk_inited = true;
 	}
 
@@ -204,4 +219,6 @@
 
 	dev->ltype = fdl_none;
+	dev->sid = sid;
+	list_initialize(&dev->parts);
 	*rdev = dev;
 	return EOK;
@@ -211,4 +228,43 @@
 {
 	free(dev);
+}
+
+int fdisk_dev_get_svcname(fdisk_dev_t *dev, char **rname)
+{
+	char *name;
+	int rc;
+
+	rc = loc_service_get_name(dev->sid, &name);
+	if (rc != EOK)
+		return rc;
+
+	*rname = name;
+	return EOK;
+}
+
+int fdisk_dev_capacity(fdisk_dev_t *dev, fdisk_cap_t *cap)
+{
+	size_t bsize;
+	aoff64_t nblocks;
+	int rc;
+
+	rc = block_init(EXCHANGE_SERIALIZE, dev->sid, 2048);
+	if (rc != EOK)
+		return rc;
+
+	rc = block_get_bsize(dev->sid, &bsize);
+	if (rc != EOK)
+		return EIO;
+
+	rc = block_get_nblocks(dev->sid, &nblocks);
+	if (rc != EOK)
+		return EIO;
+
+	block_fini(dev->sid);
+
+	cap->value = bsize * nblocks;
+	cap->cunit = cu_byte;
+
+	return EOK;
 }
 
@@ -230,7 +286,15 @@
 int fdisk_label_destroy(fdisk_dev_t *dev)
 {
+	fdisk_part_t *part;
+
 	if (dev->ltype == fdl_none)
 		return ENOENT;
 
+	part = fdisk_part_first(dev);
+	while (part != NULL) {
+		(void) fdisk_part_destroy(part); /* XXX */
+		part = fdisk_part_first(dev);
+	}
+
 	dev->ltype = fdl_none;
 	return EOK;
@@ -239,10 +303,29 @@
 fdisk_part_t *fdisk_part_first(fdisk_dev_t *dev)
 {
-	return NULL;
+	link_t *link;
+
+	link = list_first(&dev->parts);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, fdisk_part_t, ldev);
 }
 
 fdisk_part_t *fdisk_part_next(fdisk_part_t *part)
 {
-	return NULL;
+	link_t *link;
+
+	link = list_next(&part->ldev, &part->dev->parts);
+	if (link == NULL)
+		return NULL;
+
+	return list_get_instance(link, fdisk_part_t, ldev);
+}
+
+int fdisk_part_get_info(fdisk_part_t *part, fdisk_part_info_t *info)
+{
+	info->capacity = part->capacity;
+	info->fstype = part->fstype;
+	return EOK;
 }
 
@@ -252,7 +335,20 @@
 }
 
-int fdisk_part_create(fdisk_dev_t *dev, fdisk_partspec_t *pspec,
+int fdisk_part_create(fdisk_dev_t *dev, fdisk_part_spec_t *pspec,
     fdisk_part_t **rpart)
 {
+	fdisk_part_t *part;
+
+	part = calloc(1, sizeof(fdisk_part_t));
+	if (part == NULL)
+		return ENOMEM;
+
+	part->dev = dev;
+	list_append(&part->ldev, &dev->parts);
+	part->capacity = pspec->capacity;
+	part->fstype = pspec->fstype;
+
+	if (rpart != NULL)
+		*rpart = part;
 	return EOK;
 }
@@ -260,5 +356,12 @@
 int fdisk_part_destroy(fdisk_part_t *part)
 {
-	return EOK;
+	list_remove(&part->ldev);
+	free(part);
+	return EOK;
+}
+
+void fdisk_pspec_init(fdisk_part_spec_t *pspec)
+{
+	memset(pspec, 0, sizeof(fdisk_part_spec_t));
 }
 
@@ -266,9 +369,51 @@
 {
 	int rc;
-
-	rc = asprintf(rstr, "%" PRIu64 " B", cap->value);
+	const char *sunit;
+
+	sunit = NULL;
+
+	if (cap->cunit < 0 || cap->cunit >= CU_LIMIT)
+		assert(false);
+
+	sunit = cu_str[cap->cunit];
+	rc = asprintf(rstr, "%" PRIu64 " %s", cap->value, sunit);
 	if (rc < 0)
 		return ENOMEM;
 
+	return EOK;
+}
+
+int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
+{
+	char *eptr;
+	char *p;
+	unsigned long val;
+	int i;
+
+	val = strtoul(str, &eptr, 10);
+
+	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->value = val;
 	return EOK;
 }
@@ -303,4 +448,39 @@
 }
 
+int fdisk_fstype_format(fdisk_fstype_t fstype, char **rstr)
+{
+	const char *sfstype;
+	char *s;
+
+	sfstype = NULL;
+	switch (fstype) {
+	case fdfs_none:
+		sfstype = "None";
+		break;
+	case fdfs_unknown:
+		sfstype = "Unknown";
+		break;
+	case fdfs_exfat:
+		sfstype = "ExFAT";
+		break;
+	case fdfs_fat:
+		sfstype = "FAT";
+		break;
+	case fdfs_minix:
+		sfstype = "MINIX";
+		break;
+	case fdfs_ext4:
+		sfstype = "Ext4";
+		break;
+	}
+
+	s = str_dup(sfstype);
+	if (s == NULL)
+		return ENOMEM;
+
+	*rstr = s;
+	return EOK;
+}
+
 /** @}
  */
