Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 94b0b63011903c506f059fe7fcc4594838f3ac99)
+++ uspace/srv/fs/fat/fat.h	(revision a2aa1decbd0c4b48001b868e4220b226dd3a1e10)
@@ -114,4 +114,8 @@
 } __attribute__ ((packed)) fat_bs_t;
 
+#define FAT_ATTR_RDONLY		(1 << 0)
+#define FAT_ATTR_VOLLABEL	(1 << 3)
+#define FAT_ATTR_SUBDIR		(1 << 4)
+
 typedef struct {
 	uint8_t		name[8];
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 94b0b63011903c506f059fe7fcc4594838f3ac99)
+++ uspace/srv/fs/fat/fat_ops.c	(revision a2aa1decbd0c4b48001b868e4220b226dd3a1e10)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2007 Jakub Jermar
+ * Copyright (c) 2008 Jakub Jermar
  * All rights reserved.
  *
@@ -38,9 +38,9 @@
 #include "fat.h"
 #include "../../vfs/vfs.h"
+#include <libfs.h>
 #include <ipc/ipc.h>
 #include <async.h>
 #include <errno.h>
-
-#define PLB_GET_CHAR(i)		(fat_reg.plb_ro[(i) % PLB_SIZE])
+#include <string.h>
 
 #define FAT_NAME_LEN		8
@@ -54,86 +54,120 @@
 #define FAT_DENTRY_ERASED	0xe5
 
-/** Compare one component of path to a directory entry.
- *
- * @param dentry	Directory entry to compare the path component with.
- * @param start		Index into PLB where the path component starts.
- * @param last		Index of the last character of the path in PLB.
- *
- * @return		Zero on failure or delta such that (index + delta) %
- *			PLB_SIZE points	to a new path component in PLB.
- */
-static unsigned match_path_component(fat_dentry_t *dentry, unsigned start,
-    unsigned last)
+static void dentry_name_canonify(fat_dentry_t *d, char *buf)
 {
-	unsigned cur;	/* current position in PLB */
-	int pos;	/* current position in dentry->name or dentry->ext */
-	bool name_processed = false;
-	bool dot_processed = false;
-	bool ext_processed = false;
+	int i;
 
-	if (last < start)
-		last += PLB_SIZE;
-	for (pos = 0, cur = start; (cur <= last) && (PLB_GET_CHAR(cur) != '/');
-	    pos++, cur++) {
-		if (!name_processed) {
-			if ((pos == FAT_NAME_LEN - 1) ||
-			    (dentry->name[pos + 1] == FAT_PAD)) {
-			    	/* this is the last character in name */
-				name_processed = true;
-			}
-			if (dentry->name[0] == FAT_PAD) {
-				/* name is empty */
-				name_processed = true;
-			} else if ((pos == 0) && (dentry->name[pos] ==
-			    FAT_DENTRY_E5_ESC)) {
-				if (PLB_GET_CHAR(cur) == 0xe5)
-					continue;
-				else
-					return 0;	/* character mismatch */
-			} else {
-				if (PLB_GET_CHAR(cur) == dentry->name[pos])
-					continue;
-				else
-					return 0;	/* character mismatch */
-			}
+	for (i = 0; i < FAT_NAME_LEN; i++) {
+		if (d->name[i] == FAT_PAD) {
+			buf++;
+			break;
 		}
-		if (!dot_processed) {
-			dot_processed = true;
-			pos = -1;
-			if (PLB_GET_CHAR(cur) != '.')
-				return 0;
+		if (d->name[i] == FAT_DENTRY_E5_ESC)
+			*buf++ = 0xe5;
+		else
+			*buf++ = d->name[i];
+	}
+	if (d->ext[0] != FAT_PAD)
+		*buf++ = '.';
+	for (i = 0; i < FAT_EXT_LEN; i++) {
+		if (d->ext[i] == FAT_PAD) {
+			*buf = '\0';
+			return;
+		}
+		if (d->ext[i] == FAT_DENTRY_E5_ESC)
+			*buf++ = 0xe5;
+		else
+			*buf++ = d->ext[i];
+	}
+}
+
+static fat_dentry_t *fat_dentry_get(fat_node_t *dirnode, unsigned idx)
+{
+	return NULL;	/* TODO */
+}
+
+static void fat_dentry_put(fat_dentry_t *dentry)
+{
+	/* TODO */
+}
+
+static void *fat_node_get(dev_handle_t dev_handle, fs_index_t index)
+{
+	return NULL;	/* TODO */
+}
+
+static void *fat_match(void *prnt, const char *component)
+{
+	fat_node_t *parentp = (fat_node_t *)prnt;
+	char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
+	unsigned i;
+	unsigned dentries; 
+	fat_dentry_t *d;
+
+	dentries = parentp->size / sizeof(fat_dentry_t);
+	for (i = 0; i < dentries; i++) {
+		d = fat_dentry_get(parentp, i);
+		if (d->attr & FAT_ATTR_VOLLABEL) {
+			/* volume label entry */
+			fat_dentry_put(d);
 			continue;
 		}
-		if (!ext_processed) {
-			if ((pos == FAT_EXT_LEN - 1) ||
-			    (dentry->ext[pos + 1] == FAT_PAD)) {
-				/* this is the last character in ext */
-				ext_processed = true;
-			}
-			if (dentry->ext[0] == FAT_PAD) {
-				/* ext is empty; the match will fail */
-				ext_processed = true;
-			} else if (PLB_GET_CHAR(cur) == dentry->ext[pos]) {
-				continue;
-			} else {
-				/* character mismatch */
-				return 0;
-			}
+		if (d->name[0] == FAT_DENTRY_ERASED) {
+			/* not-currently-used entry */
+			fat_dentry_put(d);
+			continue;
 		}
-		return 0;	/* extra characters in the component */
+		if (d->name[0] == FAT_DENTRY_UNUSED) {
+			/* never used entry */
+			fat_dentry_put(d);
+			break;
+		}
+		if (d->name[0] == FAT_DENTRY_DOT) {
+			/*
+			 * Most likely '.' or '..'.
+			 * It cannot occur in a regular file name.
+			 */
+			fat_dentry_put(d);
+			continue;
+		}
+		
+		dentry_name_canonify(d, name);
+		if (strcmp(name, component) == 0) {
+			/* hit */
+			void *node = fat_node_get(parentp->dev_handle,
+			    (fs_index_t)d->firstc);
+			fat_dentry_put(d);
+			return node;
+
+		} else {
+			/* miss */
+			fat_dentry_put(d);
+		}
 	}
-	if (ext_processed || (name_processed && dentry->ext[0] == FAT_PAD))
-		return cur - start;
-	else
-		return 0;
+
+	return NULL;
 }
+
+/** libfs operations */
+libfs_ops_t fat_libfs_ops = {
+	.match = fat_match,
+	.node_get = fat_node_get,
+	.create = NULL,
+	.destroy = NULL,
+	.link = NULL,
+	.unlink = NULL,
+	.index_get = NULL,
+	.size_get = NULL,
+	.lnkcnt_get = NULL,
+	.has_children = NULL,
+	.root_get = NULL,
+	.plb_get_char =	NULL,
+	.is_directory = NULL,
+	.is_file = NULL
+};
 
 void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
 {
-	int first = IPC_GET_ARG1(*request);
-	int second = IPC_GET_ARG2(*request);
-	int dev_handle = IPC_GET_ARG3(*request);
-
-	
+	libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
 }
 
