Index: uspace/srv/fs/fat/fat_dentry.c
===================================================================
--- uspace/srv/fs/fat/fat_dentry.c	(revision ed194977ac205ef0e7b7c2b213636b59b1bf4f3f)
+++ uspace/srv/fs/fat/fat_dentry.c	(revision 34fdb75ba0263b25284ff0ccd04c66ad9b827897)
@@ -39,4 +39,5 @@
 #include <ctype.h>
 #include <str.h>
+#include <errno.h>
 
 static bool is_d_char(const char ch)
@@ -218,4 +219,11 @@
 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
 {
+/*	if (d->attr == FAT_ATTR_LFN) { */
+		/* long name entry */
+/*		if (d->attr & FAT_LFN_ERASED)
+			return FAT_DENTRY_FREE;
+		else
+			return FAT_DENTRY_LFN;
+	}*/
 	if (d->attr & FAT_ATTR_VOLLABEL) {
 		/* volume label entry */
@@ -259,4 +267,87 @@
 }
 
+/** Get number of bytes in a string with size limit.
+ *
+ * @param str  NULL-terminated (or not) string.
+ * @param size Maximum number of bytes to consider.
+ *
+ * @return Number of bytes in string (without 0 and ff).
+ *
+ */
+size_t fat_lfn_str_nlength(const uint8_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;
+	}
+	return offset;
+}
+
+/** Get number of bytes in a FAT long entry occuped by characters.
+ *
+ * @param d FAT long entry.
+ *
+ * @return Number of bytes.
+ *
+ */
+size_t fat_lfn_size(const fat_dentry_t *d)
+{
+	size_t size = 0;
+	
+	size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
+	size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
+	size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);	
+	
+	return size;
+}
+
+void 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))
+			continue;
+		dst[(*offset)-1] = src[i];
+		dst[(*offset)-2] = src[i-1];
+		(*offset)-=2;
+	}
+}
+
+void fat_lfn_copy_entry(const fat_dentry_t *d, uint8_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);
+}
+
+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;
+	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 = (src[i] << 8) | src[i+1];
+			rc = chr_encode(c, (char*)dst, &offset, dst_size);
+			if (rc!=EOK) {
+				return rc;
+			}
+		}
+	}
+	dst[offset] = 0;	
+	return EOK;
+}
+
 
 /**
Index: uspace/srv/fs/fat/fat_dentry.h
===================================================================
--- uspace/srv/fs/fat/fat_dentry.h	(revision ed194977ac205ef0e7b7c2b213636b59b1bf4f3f)
+++ uspace/srv/fs/fat/fat_dentry.h	(revision 34fdb75ba0263b25284ff0ccd04c66ad9b827897)
@@ -50,5 +50,5 @@
 #define FAT_ATTR_SUBDIR   0x10
 #define FAT_ATTR_ARCHIVE  0x20
-#define FAT_ATTR_LNAME \
+#define FAT_ATTR_LFN \
     (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
     
@@ -62,5 +62,25 @@
 #define FAT_DENTRY_DOT		0x2e
 #define FAT_DENTRY_ERASED	0xe5
-#define FAT_LAST_LONG_ENTRY 0x40
+#define FAT_LFN_LAST		0x40
+#define FAT_LFN_ERASED		0x80
+
+#define FAT_LFN_ORDER(d) (d->lfn.order)
+#define FAT_IS_LFN(d) \
+    ((FAT_LFN_ORDER(d) & FAT_LFN_LAST) == FAT_LFN_LAST)
+#define FAT_LFN_COUNT(d) \
+    (FAT_LFN_ORDER(d) ^ FAT_LFN_LAST)
+#define FAT_LFN_PART1(d) (d->lfn.part1)
+#define FAT_LFN_PART2(d) (d->lfn.part2)
+#define FAT_LFN_PART3(d) (d->lfn.part3)
+#define FAT_LFN_ATTR(d) (d->lfn.attr)
+#define FAT_LFN_CHKSUM(d) (d->lfn.check_sum)
+
+#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_ENTRY_SIZE \
+    (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
 
 typedef enum {
@@ -69,4 +89,5 @@
 	FAT_DENTRY_FREE,
 	FAT_DENTRY_VALID
+	/* FAT_DENTRY_LFN */
 } fat_dentry_clsf_t;
 
@@ -96,14 +117,15 @@
 		struct {
 			uint8_t		order;
-			uint8_t		name1[10];
+			uint8_t		part1[FAT_LFN_PART1_SIZE];
 			uint8_t		attr;
 			uint8_t		type;
 			uint8_t		check_sum;
-			uint8_t		name2[12];
+			uint8_t		part2[FAT_LFN_PART2_SIZE];
 			uint16_t	firstc_lo; /* MUST be 0 */
-			uint8_t		name3[4];
-		} long_entry __attribute__ ((packed));
+			uint8_t		part3[FAT_LFN_PART3_SIZE];
+		} lfn __attribute__ ((packed));
 	};
 } __attribute__ ((packed)) fat_dentry_t;
+
 
 extern int fat_dentry_namecmp(char *, const char *);
@@ -114,4 +136,11 @@
 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_size(const fat_dentry_t *);
+extern void fat_lfn_copy_part(const uint8_t *, size_t, uint8_t *, size_t *);
+extern void 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);
+
+
 #endif
 
