Index: uspace/srv/fs/fat/fat_dentry.c
===================================================================
--- uspace/srv/fs/fat/fat_dentry.c	(revision 563686b59ceabda2b51d115478d65cd0c96e25a8)
+++ uspace/srv/fs/fat/fat_dentry.c	(revision 4372b49b76fe110218c2e4d58757d8b1815ecf84)
@@ -41,4 +41,5 @@
 #include <errno.h>
 #include <byteorder.h>
+#include <assert.h>
 
 static bool is_d_char(const char ch)
@@ -276,14 +277,12 @@
  *
  */
-size_t fat_lfn_str_nlength(const uint8_t *str, size_t size)
+size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
 {
 	size_t offset = 0;
 
 	while (offset < size) {
-		if ((str[offset] == 0x00 && str[offset+1] == 0x00) ||
-			(str[offset] == 0xff && str[offset+1] == 0xff)) 
-			break;
-		
-		offset += 2;
+		if (str[offset] == 0 || str[offset] == 0xffff) 
+			break;
+		offset++;
 	}
 	return offset;
@@ -308,50 +307,55 @@
 }
 
-size_t fat_lfn_copy_part(const uint8_t *src, size_t src_size, uint8_t *dst, size_t offset)
-{
-	int i;
-	for (i=src_size-1; i>0 && offset>1; i-=2) {
-		if ((src[i] == 0x00 && src[i-1] == 0x00) ||
-			(src[i] == 0xff && src[i-1] == 0xff))
+size_t fat_lfn_copy_part(const uint16_t *src, size_t src_size, uint16_t *dst, size_t *offset)
+{
+	while (src_size!=0 && (*offset)!=0) {
+		src_size--;
+		if (src[src_size] == 0 || src[src_size] == 0xffff)
 			continue;
-		dst[offset-1] = src[i];
-		dst[offset-2] = src[i-1];
-		offset-=2;
-	}
-	return offset;
-}
-
-size_t fat_lfn_copy_entry(const fat_dentry_t *d, uint8_t *dst, size_t offset)
-{
-	offset = fat_lfn_copy_part(FAT_LFN_PART3(d), 
-	    FAT_LFN_PART3_SIZE, dst, offset);
-	offset = fat_lfn_copy_part(FAT_LFN_PART2(d), 
-	    FAT_LFN_PART2_SIZE, dst, offset);
-	offset = fat_lfn_copy_part(FAT_LFN_PART1(d), 
-	    FAT_LFN_PART1_SIZE, dst, offset);
-
-	return offset;
-}
-
-int fat_lfn_convert_name(const uint8_t *src, size_t src_size, uint8_t *dst, size_t dst_size)
-{
-	size_t i, offset = 0;
-	uint16_t c;
+
+		(*offset)--;
+		dst[(*offset)] = uint16_t_le2host(src[src_size]);
+	}
+	return (*offset);
+}
+
+size_t fat_lfn_copy_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
+{
+	fat_lfn_copy_part(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE, dst, offset);
+	fat_lfn_copy_part(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE, dst, offset);
+	fat_lfn_copy_part(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE, dst, offset);
+
+	return *offset;
+}
+
+/** Convert utf16 string to string.
+ *
+ * Convert wide string @a src to string. The output is written to the buffer
+ * specified by @a dest and @a size. @a size must be non-zero and the string
+ * written will always be well-formed.
+ *
+ * @param dest	Destination buffer.
+ * @param size	Size of the destination buffer.
+ * @param src	Source wide string.
+ */
+int utf16_to_str(char *dest, size_t size, const uint16_t *src)
+{
 	int rc;
-	for (i=0; i<src_size; i+=2) {
-		if (src[i+1] == 0x00) {
-			if (offset+1 < dst_size)
-				dst[offset++] = src[i];
-			else
-				return EOVERFLOW;
-		} else {
-			c = uint16_t_le2host((src[i] << 8) | src[i+1]);
-			rc = chr_encode(c, (char*)dst, &offset, dst_size);
-			if (rc!=EOK) {
-				return rc;
-			}
-		}
-	}
-	dst[offset] = 0;	
+	uint16_t ch;
+	size_t src_idx, dest_off;
+
+	/* There must be space for a null terminator in the buffer. */
+	assert(size > 0);
+	
+	src_idx = 0;
+	dest_off = 0;
+
+	while ((ch = src[src_idx++]) != 0) {
+		rc = chr_encode(ch, dest, &dest_off, size - 1);
+		if (rc != EOK)
+			return rc;
+	}
+
+	dest[dest_off] = '\0';
 	return EOK;
 }
Index: uspace/srv/fs/fat/fat_dentry.h
===================================================================
--- uspace/srv/fs/fat/fat_dentry.h	(revision 563686b59ceabda2b51d115478d65cd0c96e25a8)
+++ uspace/srv/fs/fat/fat_dentry.h	(revision 4372b49b76fe110218c2e4d58757d8b1815ecf84)
@@ -78,7 +78,7 @@
 #define FAT_LFN_NAME_SIZE   255
 #define FAT_LFN_MAX_COUNT   20
-#define FAT_LFN_PART1_SIZE  10
-#define FAT_LFN_PART2_SIZE  12
-#define FAT_LFN_PART3_SIZE  4
+#define FAT_LFN_PART1_SIZE  5
+#define FAT_LFN_PART2_SIZE  6
+#define FAT_LFN_PART3_SIZE  2
 #define FAT_LFN_ENTRY_SIZE \
     (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
@@ -117,12 +117,12 @@
 		struct {
 			uint8_t		order;
-			uint8_t		part1[FAT_LFN_PART1_SIZE];
+			uint16_t	part1[FAT_LFN_PART1_SIZE];
 			uint8_t		attr;
 			uint8_t		type;
 			uint8_t		check_sum;
-			uint8_t		part2[FAT_LFN_PART2_SIZE];
+			uint16_t	part2[FAT_LFN_PART2_SIZE];
 			uint16_t	firstc_lo; /* MUST be 0 */
-			uint8_t		part3[FAT_LFN_PART3_SIZE];
-		} lfn __attribute__ ((packed));
+			uint16_t	part3[FAT_LFN_PART3_SIZE];
+		} __attribute__ ((packed)) lfn;
 	};
 } __attribute__ ((packed)) fat_dentry_t;
@@ -136,9 +136,9 @@
 extern uint8_t fat_dentry_chksum(uint8_t *);
 
-extern size_t fat_lfn_str_nlength(const uint8_t *, size_t);
+extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
 extern size_t fat_lfn_size(const fat_dentry_t *);
-extern size_t fat_lfn_copy_part(const uint8_t *, size_t, uint8_t *, size_t);
-extern size_t fat_lfn_copy_entry(const fat_dentry_t *, uint8_t *, size_t);
-extern int fat_lfn_convert_name(const uint8_t *, size_t, uint8_t *, size_t);
+extern size_t fat_lfn_copy_part(const uint16_t *, size_t, uint16_t *, size_t *);
+extern size_t fat_lfn_copy_entry(const fat_dentry_t *, uint16_t *, size_t *);
+extern int utf16_to_str(char *, size_t, const uint16_t *);
 
 
Index: uspace/srv/fs/fat/fat_directory.c
===================================================================
--- uspace/srv/fs/fat/fat_directory.c	(revision 563686b59ceabda2b51d115478d65cd0c96e25a8)
+++ uspace/srv/fs/fat/fat_directory.c	(revision 4372b49b76fe110218c2e4d58757d8b1815ecf84)
@@ -41,4 +41,5 @@
 #include <byteorder.h>
 #include <mem.h>
+#include <str.h>
 
 int fat_directory_block_load(fat_directory_t *);
@@ -58,5 +59,5 @@
 	di->last = false;
 
-	di->lfn_utf16[0] = '\0';
+	di->wname[0] = '\0';
 	di->lfn_offset = 0;
 	di->lfn_size = 0;
@@ -174,6 +175,5 @@
 						(di->checksum == FAT_LFN_CHKSUM(d))) {
 						/* Right order! */
-						di->lfn_offset = fat_lfn_copy_entry(d, di->lfn_utf16, 
-							di->lfn_offset);
+						fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
 					} else {
 						/* Something wrong with order. Skip this long entries set */
@@ -190,6 +190,5 @@
 								(FAT_LFN_COUNT(d) - 1)) + fat_lfn_size(d);
 							di->lfn_offset = di->lfn_size;
-							di->lfn_offset = fat_lfn_copy_entry(d, di->lfn_utf16, 
-								di->lfn_offset);
+							fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
 							di->checksum = FAT_LFN_CHKSUM(d);
 						}
@@ -200,8 +199,6 @@
 				if (di->long_entry && 
 					(di->checksum == fat_dentry_chksum(d->name))) {
-					int rc;
-					rc = fat_lfn_convert_name(di->lfn_utf16, di->lfn_size, 
-						(uint8_t*)name, FAT_LFN_NAME_SIZE);
-					if (rc!=EOK)
+					di->wname[di->lfn_size] = '\0';
+					if (utf16_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK)
 						fat_dentry_name_get(d, name);
 				}
Index: uspace/srv/fs/fat/fat_directory.h
===================================================================
--- uspace/srv/fs/fat/fat_directory.h	(revision 563686b59ceabda2b51d115478d65cd0c96e25a8)
+++ uspace/srv/fs/fat/fat_directory.h	(revision 4372b49b76fe110218c2e4d58757d8b1815ecf84)
@@ -48,5 +48,5 @@
 	bool last;
 	/* Long entry data */
-	uint8_t lfn_utf16[FAT_LFN_MAX_COUNT * FAT_LFN_ENTRY_SIZE];
+	uint16_t wname[FAT_LFN_MAX_COUNT * FAT_LFN_ENTRY_SIZE];
 	size_t lfn_offset;
 	size_t lfn_size;
