Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision e1e3b26433bc8d04cf494f90cd529aa1943c1364)
+++ uspace/srv/fs/fat/fat_ops.c	(revision e22632a95acad144901b77c884e2d72ced3dcd4e)
@@ -48,4 +48,9 @@
 #include <assert.h>
 
+#define BS_BLOCK		0
+
+#define FIN_KEY_DEV_HANDLE	0
+#define FIN_KEY_INDEX		1
+
 /** Hash table of FAT in-core nodes. */
 hash_table_t fin_hash;
@@ -126,4 +131,17 @@
 }
 
+static uint16_t fat_bps_get(dev_handle_t dev_handle)
+{
+	block_t *bb;
+	uint16_t bps;
+	
+	bb = block_get(dev_handle, BS_BLOCK);
+	assert(bb != NULL);
+	bps = uint16_t_le2host(((fat_bs_t *)bb->data)->bps);
+	block_put(bb);
+
+	return bps;
+}
+
 static void fat_sync_node(fat_node_t *node)
 {
@@ -131,4 +149,10 @@
 }
 
+/** Instantiate a FAT in-core node.
+ *
+ * FAT stores the info necessary for instantiation of a node in the parent of
+ * that node.  This design necessitated the addition of the parent node index
+ * parameter to this otherwise generic libfs API.
+ */
 static void *
 fat_node_get(dev_handle_t dev_handle, fs_index_t index, fs_index_t pindex)
@@ -136,13 +160,13 @@
 	link_t *lnk;
 	fat_node_t *node = NULL;
-	block_t *bb;
 	block_t *b;
+	unsigned bps;
+	unsigned dps;
 	fat_dentry_t *d;
-	unsigned bps;		/* bytes per sector */
-	unsigned dps;		/* dentries per sector */
+	unsigned i, j;
 
 	unsigned long key[] = {
-		dev_handle,
-		index
+		[FIN_KEY_DEV_HANDLE] = dev_handle,
+		[FIN_KEY_INDEX] = index
 	};
 
@@ -158,4 +182,7 @@
 	}
 
+	bps = fat_bps_get(dev_handle);
+	dps = bps / sizeof(fat_dentry_t);
+	
 	if (!list_empty(&ffn_head)) {
 		/*
@@ -168,4 +195,7 @@
 		if (node->dirty)
 			fat_sync_node(node);
+		key[FIN_KEY_DEV_HANDLE] = node->dev_handle;
+		key[FIN_KEY_INDEX] = node->index;
+		hash_table_remove(&fin_hash, key, sizeof(key)/sizeof(*key));
 	} else {
 		/*
@@ -177,13 +207,48 @@
 	}
 	fat_node_initialize(node);
-
-	if (!pindex) {
-		
-	} else {
-	}
-
-}
-
-#define BS_BLOCK	0
+	node->refcnt++;
+	node->lnkcnt++;
+	node->dev_handle = dev_handle;
+	node->index = index;
+	node->pindex = pindex;
+
+	/*
+	 * Because of the design of the FAT file system, we have no clue about
+	 * how big (i.e. how many directory entries it contains) is the parent
+	 * of the node we are trying to instantiate.  However, we know that it
+	 * must contain a directory entry for our node of interest.  We simply
+	 * scan the parent until we find it.
+	 */
+	for (i = 0; ; i++) {
+		b = fat_block_get(node->dev_handle, node->pindex, i);
+		if (!b) {
+			node->refcnt--;
+			list_append(&node->ffn_link, &ffn_head);
+			return NULL;
+		}
+		for (j = 0; j < dps; j++) {
+			d = ((fat_dentry_t *)b->data) + j;
+			if (d->firstc == node->index)
+				goto found;
+		}
+		block_put(b);
+	}
+	
+found:
+	if (!(d->attr & (FAT_ATTR_SUBDIR | FAT_ATTR_VOLLABEL)))
+		node->type = FAT_FILE;
+	if ((d->attr & FAT_ATTR_SUBDIR) || !pindex)
+		node->type = FAT_DIRECTORY;
+	assert((node->type == FAT_FILE) || (node->type == FAT_DIRECTORY));
+	
+	node->size = uint32_t_le2host(d->size);
+	block_put(b);
+	
+	key[FIN_KEY_DEV_HANDLE] = node->dev_handle;
+	key[FIN_KEY_INDEX] = node->index;
+	hash_table_insert(&fin_hash, key, &node->fin_link);
+
+	return node;
+}
 
 static void *fat_match(void *prnt, const char *component)
@@ -196,12 +261,7 @@
 	unsigned blocks;
 	fat_dentry_t *d;
-	block_t *bb;
 	block_t *b;
 
-	bb = block_get(parentp->dev_handle, BS_BLOCK);
-	if (!bb)
-		return NULL;
-	bps = uint16_t_le2host(((fat_bs_t *)bb->data)->bps);
-	block_put(bb);
+	bps = fat_bps_get(parentp->dev_handle);
 	dps = bps / sizeof(fat_dentry_t);
 	blocks = parentp->size / bps + (parentp->size % bps != 0);
