Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 74ea3c63c02b58dba8c9fea17974b3da66f74190)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 32fb10edc2232e2616b6f6bbc068569cffca59f1)
@@ -144,4 +144,34 @@
 }
 
+typedef enum {
+	FAT_DENTRY_SKIP,
+	FAT_DENTRY_LAST,
+	FAT_DENTRY_VALID
+} fat_dentry_clsf_t;
+
+static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d)
+{
+	if (d->attr & FAT_ATTR_VOLLABEL) {
+		/* volume label entry */
+		return FAT_DENTRY_SKIP;
+	}
+	if (d->name[0] == FAT_DENTRY_ERASED) {
+		/* not-currently-used entry */
+		return FAT_DENTRY_SKIP;
+	}
+	if (d->name[0] == FAT_DENTRY_UNUSED) {
+		/* never used entry */
+		return FAT_DENTRY_LAST;
+	}
+	if (d->name[0] == FAT_DENTRY_DOT) {
+		/*
+		 * Most likely '.' or '..'.
+		 * It cannot occur in a regular file name.
+		 */
+		return FAT_DENTRY_SKIP;
+	}
+	return FAT_DENTRY_VALID;
+}
+
 static void fat_sync_node(fat_node_t *node)
 {
@@ -222,9 +252,4 @@
 	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;
@@ -270,7 +295,4 @@
 		
 		b = fat_block_get(parentp->dev_handle, parentp->index, i);
-		if (!b) 
-			return NULL;
-
 		dentries = (i == blocks - 1) ?
 		    parentp->size % sizeof(fat_dentry_t) :
@@ -278,26 +300,15 @@
 		for (j = 0; j < dentries; j++) { 
 			d = ((fat_dentry_t *)b->data) + j;
-			if (d->attr & FAT_ATTR_VOLLABEL) {
-				/* volume label entry */
+			switch (fat_classify_dentry(d)) {
+			case FAT_DENTRY_SKIP:
 				continue;
-			}
-			if (d->name[0] == FAT_DENTRY_ERASED) {
-				/* not-currently-used entry */
-				continue;
-			}
-			if (d->name[0] == FAT_DENTRY_UNUSED) {
-				/* never used entry */
+			case FAT_DENTRY_LAST:
 				block_put(b);
 				return NULL;
+			default:
+			case FAT_DENTRY_VALID:
+				dentry_name_canonify(d, name);
+				break;
 			}
-			if (d->name[0] == FAT_DENTRY_DOT) {
-				/*
-				 * Most likely '.' or '..'.
-				 * It cannot occur in a regular file name.
-				 */
-				continue;
-			}
-		
-			dentry_name_canonify(d, name);
 			if (strcmp(name, component) == 0) {
 				/* hit */
@@ -331,4 +342,51 @@
 {
 	return ((fat_node_t *)node)->lnkcnt;
+}
+
+static bool fat_has_children(void *node)
+{
+	fat_node_t *nodep = (fat_node_t *)node;
+	unsigned bps;
+	unsigned dps;
+	unsigned blocks;
+	block_t *b;
+	unsigned i, j;
+
+	if (nodep->type != FAT_DIRECTORY)
+		return false;
+
+	bps = fat_bps_get(nodep->dev_handle);
+	dps = bps / sizeof(fat_dentry_t);
+
+	blocks = nodep->size / bps + (nodep->size % bps != 0);
+
+	for (i = 0; i < blocks; i++) {
+		unsigned dentries;
+		fat_dentry_t *d;
+	
+		b = fat_block_get(nodep->dev_handle, nodep->index, i);
+		dentries = (i == blocks - 1) ?
+		    nodep->size % sizeof(fat_dentry_t) :
+		    dps;
+		for (j = 0; j < dentries; j++) {
+			d = ((fat_dentry_t *)b->data) + j;
+			switch (fat_classify_dentry(d)) {
+			case FAT_DENTRY_SKIP:
+				continue;
+			case FAT_DENTRY_LAST:
+				block_put(b);
+				return false;
+			default:
+			case FAT_DENTRY_VALID:
+				block_put(b);
+				return true;
+			}
+			block_put(b);
+			return true;
+		}
+		block_put(b);
+	}
+
+	return false;
 }
 
@@ -364,5 +422,5 @@
 	.size_get = fat_size_get,
 	.lnkcnt_get = fat_lnkcnt_get,
-	.has_children = NULL,
+	.has_children = fat_has_children,
 	.root_get = fat_root_get,
 	.plb_get_char =	fat_plb_get_char,
