Index: sd-reader_config.h
===================================================================
--- sd-reader_config.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ sd-reader_config.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: partition_config.h
===================================================================
--- partition_config.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ partition_config.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: ChangeLog
===================================================================
--- ChangeLog	(.../sd-reader_release_20071213)	(Revision 126)
+++ ChangeLog	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,4 +1,14 @@
 
+2008-06-08 sd-reader
+	* new "init" command to allow reinitialization of memory card
+	* fix searching through multi-cluster directories
+	* fix reading directory entries spanning a cluster border (backport from mega-eth)
+	* do not abort the whole lfn entry when the file name is too long, just drop single characters (backport from mega-eth)
+	* change fat16_get_dir_entry_of_path() to ignore a slash at the end (backport from mega-eth)
+	* make listing a directory's content much faster (backport from mega-eth)
+	* shrink code size by centralizing cluster offset calculation (backport from mega-eth)
+	* some other small fixes and optimizations
+
 2007-12-13 sd-reader
 	* dual-license the major implementation modules under GPL and LGPL
 
Index: sd_raw_config.h
===================================================================
--- sd_raw_config.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ sd_raw_config.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: partition.c
===================================================================
--- partition.c	(.../sd-reader_release_20071213)	(Revision 126)
+++ partition.c	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: uart.c
===================================================================
--- uart.c	(.../sd-reader_release_20071213)	(Revision 126)
+++ uart.c	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: fat16_config.h
===================================================================
--- fat16_config.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ fat16_config.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
@@ -9,7 +9,7 @@
  */
 
 #ifndef FAT16_CONFIG_H
-#define FAT16_CONFIG_G
+#define FAT16_CONFIG_H
 
 /**
  * \addtogroup fat16
Index: partition.h
===================================================================
--- partition.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ partition.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: sd_raw.c
===================================================================
--- sd_raw.c	(.../sd-reader_release_20071213)	(Revision 126)
+++ sd_raw.c	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
@@ -407,11 +407,8 @@
 #endif
         {
 #if SD_RAW_WRITE_BUFFERING
-            if(!raw_block_written)
-            {
-                if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
-                    return 0;
-            }
+            if(!sd_raw_sync())
+                return 0;
 #endif
 
             /* address card */
@@ -630,11 +627,8 @@
         if(block_address != raw_block_address)
         {
 #if SD_RAW_WRITE_BUFFERING
-            if(!raw_block_written)
-            {
-                if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
-                    return 0;
-            }
+            if(!sd_raw_sync())
+                return 0;
 #endif
 
             if(block_offset || write_length < 512)
@@ -657,8 +651,6 @@
 #endif
         }
 
-        buffer += write_length;
-
         /* address card */
         select_card();
 
@@ -688,14 +680,15 @@
         /* deaddress card */
         unselect_card();
 
-        length -= write_length;
+        buffer += write_length;
         offset += write_length;
+        length -= write_length;
 
 #if SD_RAW_WRITE_BUFFERING
         raw_block_written = 1;
 #endif
     }
-    
+
     return 1;
 #else
     return 0;
@@ -777,6 +770,7 @@
         return 1;
     if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block)))
         return 0;
+    raw_block_written = 1;
 #endif
     return 1;
 #else
Index: uart.h
===================================================================
--- uart.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ uart.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: fat16.c
===================================================================
--- fat16.c	(.../sd-reader_release_20071213)	(Revision 126)
+++ fat16.c	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /* 
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
@@ -159,15 +159,15 @@
 {
     struct fat16_fs_struct* fs;
     struct fat16_dir_entry_struct dir_entry;
-    uint16_t entry_next;
+    uint16_t entry_cluster;
+    uint16_t entry_offset;
 };
 
-struct fat16_read_callback_arg
+struct fat16_read_dir_callback_arg
 {
-    uint16_t entry_cur;
-    uint16_t entry_num;
-    uint32_t entry_offset;
-    uint8_t byte_count;
+    struct fat16_dir_entry_struct* dir_entry;
+    uint16_t bytes_read;
+    uint8_t finished;
 };
 
 struct fat16_usage_count_callback_arg
@@ -177,23 +177,21 @@
 };
 
 #if !USE_DYNAMIC_MEMORY
-static struct fat16_fs_struct fat16_fs_handlers[FAT16_FS_COUNT];
-static struct fat16_file_struct fat16_file_handlers[FAT16_FILE_COUNT];
-static struct fat16_dir_struct fat16_dir_handlers[FAT16_DIR_COUNT];
+static struct fat16_fs_struct fat16_fs_handles[FAT16_FS_COUNT];
+static struct fat16_file_struct fat16_file_handles[FAT16_FILE_COUNT];
+static struct fat16_dir_struct fat16_dir_handles[FAT16_DIR_COUNT];
 #endif
 
 static uint8_t fat16_read_header(struct fat16_fs_struct* fs);
-static uint8_t fat16_read_root_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, struct fat16_dir_entry_struct* dir_entry);
-static uint8_t fat16_read_sub_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, const struct fat16_dir_entry_struct* parent, struct fat16_dir_entry_struct* dir_entry);
-static uint8_t fat16_dir_entry_seek_callback(uint8_t* buffer, uint32_t offset, void* p);
-static uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p);
-static uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry);
 static uint16_t fat16_get_next_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint16_t fat16_append_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num, uint16_t count);
 static uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint8_t fat16_terminate_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint8_t fat16_clear_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint16_t fat16_clear_cluster_callback(uint8_t* buffer, uint32_t offset, void* p);
+static uint32_t fat16_cluster_offset(const struct fat16_fs_struct* fs, uint16_t cluster_num);
+static uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p);
+static uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry);
 static uint32_t fat16_find_offset_for_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_struct* parent, const struct fat16_dir_entry_struct* dir_entry);
 static uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry);
 
@@ -227,7 +225,7 @@
     if(!fs)
         return 0;
 #else
-    struct fat16_fs_struct* fs = fat16_fs_handlers;
+    struct fat16_fs_struct* fs = fat16_fs_handles;
     uint8_t i;
     for(i = 0; i < FAT16_FS_COUNT; ++i)
     {
@@ -371,281 +369,6 @@
 }
 
 /**
- * \ingroup fat16_fs
- * Reads a directory entry of the root directory.
- *
- * \param[in] fs Descriptor of file system to use.
- * \param[in] entry_num The index of the directory entry to read.
- * \param[out] dir_entry Directory entry descriptor which will get filled.
- * \returns 0 on failure, 1 on success
- * \see fat16_read_sub_dir_entry, fat16_read_dir_entry_by_path
- */
-uint8_t fat16_read_root_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, struct fat16_dir_entry_struct* dir_entry)
-{
-    if(!fs || !dir_entry)
-        return 0;
-
-    /* we read from the root directory entry */
-    const struct fat16_header_struct* header = &fs->header;
-    device_read_interval_t device_read_interval = fs->partition->device_read_interval;
-    uint8_t buffer[32];
-
-    /* seek to the n-th entry */
-    struct fat16_read_callback_arg arg;
-    memset(&arg, 0, sizeof(arg));
-    arg.entry_num = entry_num;
-    if(!device_read_interval(header->root_dir_offset,
-                             buffer,
-                             sizeof(buffer),
-                             header->cluster_zero_offset - header->root_dir_offset,
-                             fat16_dir_entry_seek_callback,
-                             &arg) ||
-       arg.entry_offset == 0
-      )
-        return 0;
-
-    /* read entry */
-    memset(dir_entry, 0, sizeof(*dir_entry));
-    if(!device_read_interval(arg.entry_offset,
-                             buffer,
-                             sizeof(buffer),
-                             arg.byte_count,
-                             fat16_dir_entry_read_callback,
-                             dir_entry))
-        return 0;
-
-    return dir_entry->long_name[0] != '\0' ? 1 : 0;
-}
-
-/**
- * \ingroup fat16_fs
- * Reads a directory entry of a given parent directory.
- *
- * \param[in] fs Descriptor of file system to use.
- * \param[in] entry_num The index of the directory entry to read.
- * \param[in] parent Directory entry descriptor in which to read directory entry.
- * \param[out] dir_entry Directory entry descriptor which will get filled.
- * \returns 0 on failure, 1 on success
- * \see fat16_read_root_dir_entry, fat16_read_dir_entry_by_path
- */
-uint8_t fat16_read_sub_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, const struct fat16_dir_entry_struct* parent, struct fat16_dir_entry_struct* dir_entry)
-{
-    if(!fs || !parent || !dir_entry)
-        return 0;
-
-    /* we are in a parent directory and want to search within its directory entry table */
-    if(!(parent->attributes & FAT16_ATTRIB_DIR))
-        return 0;
-
-    /* loop through all clusters of the directory */
-    uint8_t buffer[32];
-    uint32_t cluster_offset;
-    uint16_t cluster_size = fs->header.cluster_size;
-    uint16_t cluster_num = parent->cluster;
-    struct fat16_read_callback_arg arg;
-
-    while(1)
-    {
-        /* calculate new cluster offset */
-        cluster_offset = fs->header.cluster_zero_offset + (uint32_t) (cluster_num - 2) * cluster_size;
-
-        /* seek to the n-th entry */
-        memset(&arg, 0, sizeof(arg));
-        arg.entry_num = entry_num;
-        if(!fs->partition->device_read_interval(cluster_offset,
-                                                buffer,
-                                                sizeof(buffer),
-                                                cluster_size,
-                                                fat16_dir_entry_seek_callback,
-                                                &arg)
-          )
-            return 0;
-
-        /* check if we found the entry */
-        if(arg.entry_offset)
-            break;
-
-        /* get number of next cluster */
-        if(!(cluster_num = fat16_get_next_cluster(fs, cluster_num)))
-            return 0; /* directory entry not found */
-    }
-
-    memset(dir_entry, 0, sizeof(*dir_entry));
-
-    /* read entry */
-    if(!fs->partition->device_read_interval(arg.entry_offset,
-                                            buffer,
-                                            sizeof(buffer),
-                                            arg.byte_count,
-                                            fat16_dir_entry_read_callback,
-                                            dir_entry))
-        return 0;
-
-    return dir_entry->long_name[0] != '\0' ? 1 : 0;
-}
-
-/**
- * \ingroup fat16_fs
- * Callback function for seeking through subdirectory entries.
- */
-uint8_t fat16_dir_entry_seek_callback(uint8_t* buffer, uint32_t offset, void* p)
-{
-    struct fat16_read_callback_arg* arg = p;
-
-    /* skip deleted or empty entries */
-    if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
-        return 1;
-
-    if(arg->entry_cur == arg->entry_num)
-    {
-        arg->entry_offset = offset;
-        arg->byte_count = buffer[11] == 0x0f ?
-                          ((buffer[0] & FAT16_DIRENTRY_LFNSEQMASK) + 1) * 32 :
-                          32;
-        return 0;
-    }
-
-    /* if we read a 8.3 entry, we reached a new directory entry */
-    if(buffer[11] != 0x0f)
-        ++arg->entry_cur;
-
-    return 1;
-}
-
-/**
- * \ingroup fat16_fs
- * Callback function for reading a directory entry.
- */
-uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p)
-{
-    struct fat16_dir_entry_struct* dir_entry = p;
-
-    /* there should not be any deleted or empty entries */
-    if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
-        return 0;
-
-    if(!dir_entry->entry_offset)
-        dir_entry->entry_offset = offset;
-    
-    switch(fat16_interpret_dir_entry(dir_entry, buffer))
-    {
-        case 0: /* failure */
-            return 0;
-        case 1: /* buffer successfully parsed, continue */
-            return 1;
-        case 2: /* directory entry complete, finish */
-            return 0;
-    }
-
-    return 0;
-}
-
-/**
- * \ingroup fat16_fs
- * Interprets a raw directory entry and puts the contained
- * information into the directory entry.
- * 
- * For a single file there may exist multiple directory
- * entries. All except the last one are lfn entries, which
- * contain parts of the long filename. The last directory
- * entry is a traditional 8.3 style one. It contains all
- * other information like size, cluster, date and time.
- * 
- * \param[in,out] dir_entry The directory entry to fill.
- * \param[in] raw_entry A pointer to 32 bytes of raw data.
- * \returns 0 on failure, 1 on success and 2 if the
- *          directory entry is complete.
- */
-uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry)
-{
-    if(!dir_entry || !raw_entry || !raw_entry[0])
-        return 0;
-
-    char* long_name = dir_entry->long_name;
-    if(raw_entry[11] == 0x0f)
-    {
-        uint16_t char_offset = ((raw_entry[0] & 0x3f) - 1) * 13;
-
-        if(char_offset + 12 < sizeof(dir_entry->long_name))
-        {
-            /* Lfn supports unicode, but we do not, for now.
-             * So we assume pure ascii and read only every
-             * second byte.
-             */
-            long_name[char_offset + 0] = raw_entry[1];
-            long_name[char_offset + 1] = raw_entry[3];
-            long_name[char_offset + 2] = raw_entry[5];
-            long_name[char_offset + 3] = raw_entry[7];
-            long_name[char_offset + 4] = raw_entry[9];
-            long_name[char_offset + 5] = raw_entry[14];
-            long_name[char_offset + 6] = raw_entry[16];
-            long_name[char_offset + 7] = raw_entry[18];
-            long_name[char_offset + 8] = raw_entry[20];
-            long_name[char_offset + 9] = raw_entry[22];
-            long_name[char_offset + 10] = raw_entry[24];
-            long_name[char_offset + 11] = raw_entry[28];
-            long_name[char_offset + 12] = raw_entry[30];
-        }
-
-        return 1;
-    }
-    else
-    {
-        /* if we do not have a long name, take the short one */
-        if(long_name[0] == '\0')
-        {
-            uint8_t i;
-            for(i = 0; i < 8; ++i)
-            {
-                if(raw_entry[i] == ' ')
-                    break;
-                long_name[i] = raw_entry[i];
-            }
-            if(long_name[0] == 0x05)
-                long_name[0] = (char) FAT16_DIRENTRY_DELETED;
-
-            if(raw_entry[8] != ' ')
-            {
-                long_name[i++] = '.';
-
-                uint8_t j = 8;
-                for(; j < 11; ++j)
-                {
-                    if(raw_entry[j] != ' ')
-                    {
-                        long_name[i++] = raw_entry[j];
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-            } 
-
-            long_name[i] = '\0';
-        }
-        
-        /* extract properties of file and store them within the structure */
-        dir_entry->attributes = raw_entry[11];
-        dir_entry->cluster = ((uint16_t) raw_entry[26]) |
-                             ((uint16_t) raw_entry[27] << 8);
-        dir_entry->file_size = ((uint32_t) raw_entry[28]) |
-                               ((uint32_t) raw_entry[29] << 8) |
-                               ((uint32_t) raw_entry[30] << 16) |
-                               ((uint32_t) raw_entry[31] << 24);
-
-#if FAT16_DATETIME_SUPPORT
-        dir_entry->modification_time = ((uint16_t) raw_entry[22]) |
-                                       ((uint16_t) raw_entry[23] << 8);
-        dir_entry->modification_date = ((uint16_t) raw_entry[24]) |
-                                       ((uint16_t) raw_entry[25] << 8);
-#endif
-
-        return 2;
-    }
-}
-
-/**
  * \ingroup fat16_file
  * Retrieves the directory entry of a path.
  *
@@ -669,20 +392,28 @@
     memset(dir_entry, 0, sizeof(*dir_entry));
     dir_entry->attributes = FAT16_ATTRIB_DIR;
 
-    if(path[0] == '\0')
-        return 1;
-
     while(1)
     {
+        if(path[0] == '\0')
+            return 1;
+
         struct fat16_dir_struct* dd = fat16_open_dir(fs, dir_entry);
         if(!dd)
             break;
 
         /* extract the next hierarchy we will search for */
-        const char* sep_pos = strchr(path, '/');
-        if(!sep_pos)
-            sep_pos = path + strlen(path);
-        uint8_t length_to_sep = sep_pos - path;
+        const char* sub_path = strchr(path, '/');
+        uint8_t length_to_sep;
+        if(sub_path)
+        {
+            length_to_sep = sub_path - path;
+            ++sub_path;
+        }
+        else
+        {
+            length_to_sep = strlen(path);
+            sub_path = path + length_to_sep;
+        }
         
         /* read directory entries */
         while(fat16_read_dir(dd, dir_entry))
@@ -702,7 +433,7 @@
             if(dir_entry->attributes & FAT16_ATTRIB_DIR)
             {
                 /* we found a parent directory of the file we are searching for */
-                path = sep_pos + 1;
+                path = sub_path;
                 break;
             }
 
@@ -954,8 +685,7 @@
     if(cluster_num < 2)
         return 0;
 
-    uint32_t cluster_offset = fs->header.cluster_zero_offset +
-                              (uint32_t) (cluster_num - 2) * fs->header.cluster_size;
+    uint32_t cluster_offset = fat16_cluster_offset(fs, cluster_num);
     uint8_t zero[16];
     return fs->partition->device_write_interval(cluster_offset,
                                                 zero,
@@ -983,6 +713,22 @@
 }
 
 /**
+ * \ingroup fat16_fs
+ * Calculates the offset of the specified cluster.
+ *
+ * \param[in] fs The filesystem on which to operate.
+ * \param[in] cluster_num The cluster whose offset to calculate.
+ * \returns The cluster offset.
+ */
+uint32_t fat16_cluster_offset(const struct fat16_fs_struct* fs, uint16_t cluster_num)
+{
+    if(!fs || cluster_num < 2)
+        return 0;
+
+    return fs->header.cluster_zero_offset + (uint32_t) (cluster_num - 2) * fs->header.cluster_size;
+}
+
+/**
  * \ingroup fat16_file
  * Opens a file on a FAT16 filesystem.
  *
@@ -1001,7 +747,7 @@
     if(!fd)
         return 0;
 #else
-    struct fat16_file_struct* fd = fat16_file_handlers;
+    struct fat16_file_struct* fd = fat16_file_handles;
     uint8_t i;
     for(i = 0; i < FAT16_FILE_COUNT; ++i)
     {
@@ -1098,8 +844,7 @@
     do
     {
         /* calculate data size to copy from cluster */
-        uint32_t cluster_offset = fd->fs->header.cluster_zero_offset +
-                                  (uint32_t) (cluster_num - 2) * cluster_size + first_cluster_offset;
+        uint32_t cluster_offset = fat16_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
         uint16_t copy_length = cluster_size - first_cluster_offset;
         if(copy_length > buffer_left)
             copy_length = buffer_left;
@@ -1203,8 +948,7 @@
     do
     {
         /* calculate data size to write to cluster */
-        uint32_t cluster_offset = fd->fs->header.cluster_zero_offset +
-                                  (uint32_t) (cluster_num - 2) * cluster_size + first_cluster_offset;
+        uint32_t cluster_offset = fat16_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
         uint16_t write_length = cluster_size - first_cluster_offset;
         if(write_length > buffer_left)
             write_length = buffer_left;
@@ -1444,7 +1188,7 @@
     if(!dd)
         return 0;
 #else
-    struct fat16_dir_struct* dd = fat16_dir_handlers;
+    struct fat16_dir_struct* dd = fat16_dir_handles;
     uint8_t i;
     for(i = 0; i < FAT16_DIR_COUNT; ++i)
     {
@@ -1459,7 +1203,8 @@
     
     memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry));
     dd->fs = fs;
-    dd->entry_next = 0;
+    dd->entry_cluster = dir_entry->cluster;
+    dd->entry_offset = 0;
 
     return dd;
 }
@@ -1499,29 +1244,67 @@
     if(!dd || !dir_entry)
         return 0;
 
-    if(dd->dir_entry.cluster == 0)
+    /* get current position of directory handle */
+    const struct fat16_header_struct* header = &dd->fs->header;
+    uint16_t cluster_size = header->cluster_size;
+    uint16_t cluster_num = dd->entry_cluster;
+    uint16_t cluster_offset = dd->entry_offset;
+    struct fat16_read_dir_callback_arg arg;
+
+    /* reset directory entry */
+    memset(dir_entry, 0, sizeof(*dir_entry));
+
+    /* reset callback arguments */
+    memset(&arg, 0, sizeof(arg));
+    arg.dir_entry = dir_entry;
+
+    /* check if we read from the root directory */
+    if(cluster_num == 0)
+        cluster_size = header->cluster_zero_offset - header->root_dir_offset;
+
+    /* read entries */
+    uint8_t buffer[32];
+    while(!arg.finished)
     {
-        /* read entry from root directory */
-        if(fat16_read_root_dir_entry(dd->fs, dd->entry_next, dir_entry))
+        /* read directory entries up to the cluster border */
+        uint16_t cluster_left = cluster_size - cluster_offset;
+        uint32_t pos = cluster_offset;
+        if(cluster_num == 0)
+            pos += header->root_dir_offset;
+        else
+            pos += fat16_cluster_offset(dd->fs, cluster_num);
+
+        arg.bytes_read = 0;
+        if(!dd->fs->partition->device_read_interval(pos,
+                                                    buffer,
+                                                    sizeof(buffer),
+                                                    cluster_left,
+                                                    fat16_dir_entry_read_callback,
+                                                    &arg)
+          )
+            return 0;
+
+        cluster_offset += arg.bytes_read;
+
+        if(cluster_offset >= cluster_size)
         {
-            ++dd->entry_next;
-            return 1;
+            /* we reached the cluster border and switch to the next cluster */
+            cluster_offset = 0;
+
+            /* get number of next cluster */
+            if(!(cluster_num = fat16_get_next_cluster(dd->fs, cluster_num)))
+            {
+                /* directory entry not found, reset directory handle */
+                cluster_num = dd->dir_entry.cluster;
+                break;
+            }
         }
     }
-    else
-    {
-        /* read entry from a subdirectory */
-        if(fat16_read_sub_dir_entry(dd->fs, dd->entry_next, &dd->dir_entry, dir_entry))
-        {
-            ++dd->entry_next;
-            return 1;
-        }
-    }
 
-    /* restart reading */
-    dd->entry_next = 0;
+    dd->entry_cluster = cluster_num;
+    dd->entry_offset = cluster_offset;
 
-    return 0;
+    return dir_entry->long_name[0] != '\0' ? 1 : 0;
 }
 
 /**
@@ -1540,15 +1323,146 @@
     if(!dd)
         return 0;
 
-    dd->entry_next = 0;
+    dd->entry_cluster = dd->dir_entry.cluster;
+    dd->entry_offset = 0;
     return 1;
 }
 
 /**
  * \ingroup fat16_fs
+ * Callback function for reading a directory entry.
+ */
+uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p)
+{
+    struct fat16_read_dir_callback_arg* arg = p;
+    struct fat16_dir_entry_struct* dir_entry = arg->dir_entry;
+
+    arg->bytes_read += 32;
+
+    /* skip deleted or empty entries */
+    if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
+        return 1;
+
+    if(!dir_entry->entry_offset)
+        dir_entry->entry_offset = offset;
+    
+    switch(fat16_interpret_dir_entry(dir_entry, buffer))
+    {
+        case 0: /* failure */
+        {
+            return 0;
+        }
+        case 1: /* buffer successfully parsed, continue */
+        {
+            return 1;
+        }
+        case 2: /* directory entry complete, finish */
+        {
+            arg->finished = 1;
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * \ingroup fat16_fs
+ * Interprets a raw directory entry and puts the contained
+ * information into the directory entry.
+ * 
+ * For a single file there may exist multiple directory
+ * entries. All except the last one are lfn entries, which
+ * contain parts of the long filename. The last directory
+ * entry is a traditional 8.3 style one. It contains all
+ * other information like size, cluster, date and time.
+ * 
+ * \param[in,out] dir_entry The directory entry to fill.
+ * \param[in] raw_entry A pointer to 32 bytes of raw data.
+ * \returns 0 on failure, 1 on success and 2 if the
+ *          directory entry is complete.
+ */
+uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry)
+{
+    if(!dir_entry || !raw_entry || !raw_entry[0])
+        return 0;
+
+    char* long_name = dir_entry->long_name;
+    if(raw_entry[11] == 0x0f)
+    {
+        /* Lfn supports unicode, but we do not, for now.
+         * So we assume pure ascii and read only every
+         * second byte.
+         */
+        uint16_t char_offset = ((raw_entry[0] & 0x3f) - 1) * 13;
+        const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
+        for(uint8_t i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i)
+            long_name[char_offset + i] = raw_entry[char_mapping[i]];
+
+        return 1;
+    }
+    else
+    {
+        /* if we do not have a long name, take the short one */
+        if(long_name[0] == '\0')
+        {
+            uint8_t i;
+            for(i = 0; i < 8; ++i)
+            {
+                if(raw_entry[i] == ' ')
+                    break;
+                long_name[i] = raw_entry[i];
+            }
+            if(long_name[0] == 0x05)
+                long_name[0] = (char) FAT16_DIRENTRY_DELETED;
+
+            if(raw_entry[8] != ' ')
+            {
+                long_name[i++] = '.';
+
+                uint8_t j = 8;
+                for(; j < 11; ++j)
+                {
+                    if(raw_entry[j] != ' ')
+                    {
+                        long_name[i++] = raw_entry[j];
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            } 
+
+            long_name[i] = '\0';
+        }
+        
+        /* extract properties of file and store them within the structure */
+        dir_entry->attributes = raw_entry[11];
+        dir_entry->cluster = ((uint16_t) raw_entry[26]) |
+                             ((uint16_t) raw_entry[27] << 8);
+        dir_entry->file_size = ((uint32_t) raw_entry[28]) |
+                               ((uint32_t) raw_entry[29] << 8) |
+                               ((uint32_t) raw_entry[30] << 16) |
+                               ((uint32_t) raw_entry[31] << 24);
+
+#if FAT16_DATETIME_SUPPORT
+        dir_entry->modification_time = ((uint16_t) raw_entry[22]) |
+                                       ((uint16_t) raw_entry[23] << 8);
+        dir_entry->modification_date = ((uint16_t) raw_entry[24]) |
+                                       ((uint16_t) raw_entry[25] << 8);
+#endif
+
+        return 2;
+    }
+}
+
+/**
+ * \ingroup fat16_fs
  * Searches for space where to store a directory entry.
  *
  * \param[in] fs The filesystem on which to operate.
+ * \param[in] parent The directory in which to search.
  * \param[in] dir_entry The directory entry for which to search space.
  * \returns 0 on failure, a device offset on success.
  */
@@ -1609,8 +1523,7 @@
                 cluster_num = cluster_next;
             }
 
-            offset = fs->header.cluster_zero_offset +
-                     (uint32_t) (cluster_num - 2) * fs->header.cluster_size;
+            offset = fat16_cluster_offset(fs, cluster_num);
             offset_to = offset + fs->header.cluster_size;
             dir_entry_offset = offset;
             free_dir_entries_found = 0;
Index: sd_raw.h
===================================================================
--- sd_raw.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ sd_raw.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: main.c
===================================================================
--- main.c	(.../sd-reader_release_20071213)	(Revision 126)
+++ main.c	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -62,6 +62,8 @@
  *   Changes current working directory to \<directory\>.
  * - <tt>disk</tt>\n
  *   Shows card manufacturer, status, filesystem capacity and free storage space.
+ * - <tt>init</tt>\n
+ *   Reinitializes and reopens the memory card.
  * - <tt>ls</tt>\n
  *   Shows the content of the current directory.
  * - <tt>mkdir \<directory\></tt>\n
@@ -178,7 +180,7 @@
  * I adapted his work for my circuit. Although this is a very simple
  * solution, I had no problems using it.
  * 
- * \section copyright Copyright 2006-2007 by Roland Riegel
+ * \section copyright Copyright 2006-2008 by Roland Riegel
  * This program is free software; you can redistribute it and/or modify it under
  * the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation (http://www.gnu.org/copyleft/gpl.html).
@@ -211,287 +213,294 @@
     /* setup uart */
     uart_init();
 
-    /* setup sd card slot */
-    if(!sd_raw_init())
+    while(1)
     {
+        /* setup sd card slot */
+        if(!sd_raw_init())
+        {
 #if DEBUG
-        uart_puts_p(PSTR("MMC/SD initialization failed\n"));
+            uart_puts_p(PSTR("MMC/SD initialization failed\n"));
 #endif
-        return 1;
-    }
+            continue;
+        }
 
-    /* open first partition */
-    struct partition_struct* partition = partition_open(sd_raw_read,
-                                                        sd_raw_read_interval,
-                                                        sd_raw_write,
-                                                        sd_raw_write_interval,
-                                                        0
-                                                       );
+        /* open first partition */
+        struct partition_struct* partition = partition_open(sd_raw_read,
+                                                            sd_raw_read_interval,
+                                                            sd_raw_write,
+                                                            sd_raw_write_interval,
+                                                            0
+                                                           );
 
-    if(!partition)
-    {
-        /* If the partition did not open, assume the storage device
-         * is a "superfloppy", i.e. has no MBR.
-         */
-        partition = partition_open(sd_raw_read,
-                                   sd_raw_read_interval,
-                                   sd_raw_write,
-                                   sd_raw_write_interval,
-                                   -1
-                                  );
         if(!partition)
         {
+            /* If the partition did not open, assume the storage device
+             * is a "superfloppy", i.e. has no MBR.
+             */
+            partition = partition_open(sd_raw_read,
+                                       sd_raw_read_interval,
+                                       sd_raw_write,
+                                       sd_raw_write_interval,
+                                       -1
+                                      );
+            if(!partition)
+            {
 #if DEBUG
-            uart_puts_p(PSTR("opening partition failed\n"));
+                uart_puts_p(PSTR("opening partition failed\n"));
 #endif
-            return 1;
+                continue;
+            }
         }
-    }
 
-    /* open file system */
-    struct fat16_fs_struct* fs = fat16_open(partition);
-    if(!fs)
-    {
+        /* open file system */
+        struct fat16_fs_struct* fs = fat16_open(partition);
+        if(!fs)
+        {
 #if DEBUG
-        uart_puts_p(PSTR("opening filesystem failed\n"));
+            uart_puts_p(PSTR("opening filesystem failed\n"));
 #endif
-        return 1;
-    }
+            continue;
+        }
 
-    /* open root directory */
-    struct fat16_dir_entry_struct directory;
-    fat16_get_dir_entry_of_path(fs, "/", &directory);
+        /* open root directory */
+        struct fat16_dir_entry_struct directory;
+        fat16_get_dir_entry_of_path(fs, "/", &directory);
 
-    struct fat16_dir_struct* dd = fat16_open_dir(fs, &directory);
-    if(!dd)
-    {
+        struct fat16_dir_struct* dd = fat16_open_dir(fs, &directory);
+        if(!dd)
+        {
 #if DEBUG
-        uart_puts_p(PSTR("opening root directory failed\n"));
+            uart_puts_p(PSTR("opening root directory failed\n"));
 #endif
-        return 1;
-    }
-    
-    /* print some card information as a boot message */
-    print_disk_info(fs);
-
-    /* provide a simple shell */
-    char buffer[24];
-    while(1)
-    {
-        /* print prompt */
-        uart_putc('>');
-        uart_putc(' ');
-
-        /* read command */
-        char* command = buffer;
-        if(read_line(command, sizeof(buffer)) < 1)
             continue;
+        }
+        
+        /* print some card information as a boot message */
+        print_disk_info(fs);
 
-        /* execute command */
-        if(strncmp_P(command, PSTR("cd "), 3) == 0)
+        /* provide a simple shell */
+        char buffer[24];
+        while(1)
         {
-            command += 3;
-            if(command[0] == '\0')
+            /* print prompt */
+            uart_putc('>');
+            uart_putc(' ');
+
+            /* read command */
+            char* command = buffer;
+            if(read_line(command, sizeof(buffer)) < 1)
                 continue;
 
-            /* change directory */
-            struct fat16_dir_entry_struct subdir_entry;
-            if(find_file_in_dir(fs, dd, command, &subdir_entry))
+            /* execute command */
+            if(strcmp_P(command, PSTR("init")) == 0)
             {
-                struct fat16_dir_struct* dd_new = fat16_open_dir(fs, &subdir_entry);
-                if(dd_new)
+                break;
+            }
+            else if(strncmp_P(command, PSTR("cd "), 3) == 0)
+            {
+                command += 3;
+                if(command[0] == '\0')
+                    continue;
+
+                /* change directory */
+                struct fat16_dir_entry_struct subdir_entry;
+                if(find_file_in_dir(fs, dd, command, &subdir_entry))
                 {
-                    fat16_close_dir(dd);
-                    dd = dd_new;
-                    continue;
+                    struct fat16_dir_struct* dd_new = fat16_open_dir(fs, &subdir_entry);
+                    if(dd_new)
+                    {
+                        fat16_close_dir(dd);
+                        dd = dd_new;
+                        continue;
+                    }
                 }
+
+                uart_puts_p(PSTR("directory not found: "));
+                uart_puts(command);
+                uart_putc('\n');
             }
+            else if(strcmp_P(command, PSTR("ls")) == 0)
+            {
+                /* print directory listing */
+                struct fat16_dir_entry_struct dir_entry;
+                while(fat16_read_dir(dd, &dir_entry))
+                {
+                    uint8_t spaces = sizeof(dir_entry.long_name) - strlen(dir_entry.long_name) + 4;
 
-            uart_puts_p(PSTR("directory not found: "));
-            uart_puts(command);
-            uart_putc('\n');
-        }
-        else if(strcmp_P(command, PSTR("ls")) == 0)
-        {
-            /* print directory listing */
-            struct fat16_dir_entry_struct dir_entry;
-            while(fat16_read_dir(dd, &dir_entry))
+                    uart_puts(dir_entry.long_name);
+                    uart_putc(dir_entry.attributes & FAT16_ATTRIB_DIR ? '/' : ' ');
+                    while(spaces--)
+                        uart_putc(' ');
+                    uart_putdw_dec(dir_entry.file_size);
+                    uart_putc('\n');
+                }
+            }
+            else if(strncmp_P(command, PSTR("cat "), 4) == 0)
             {
-                uint8_t spaces = sizeof(dir_entry.long_name) - strlen(dir_entry.long_name) + 4;
+                command += 4;
+                if(command[0] == '\0')
+                    continue;
+                
+                /* search file in current directory and open it */
+                struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
+                if(!fd)
+                {
+                    uart_puts_p(PSTR("error opening "));
+                    uart_puts(command);
+                    uart_putc('\n');
+                    continue;
+                }
 
-                uart_puts(dir_entry.long_name);
-                uart_putc(dir_entry.attributes & FAT16_ATTRIB_DIR ? '/' : ' ');
-                while(spaces--)
-                    uart_putc(' ');
-                uart_putdw_dec(dir_entry.file_size);
-                uart_putc('\n');
+                /* print file contents */
+                uint8_t buffer[8];
+                uint32_t offset = 0;
+                while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0)
+                {
+                    uart_putdw_hex(offset);
+                    uart_putc(':');
+                    for(uint8_t i = 0; i < 8; ++i)
+                    {
+                        uart_putc(' ');
+                        uart_putc_hex(buffer[i]);
+                    }
+                    uart_putc('\n');
+                    offset += 8;
+                }
+
+                fat16_close_file(fd);
             }
-        }
-        else if(strncmp_P(command, PSTR("cat "), 4) == 0)
-        {
-            command += 4;
-            if(command[0] == '\0')
-                continue;
-            
-            /* search file in current directory and open it */
-            struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
-            if(!fd)
+            else if(strcmp_P(command, PSTR("disk")) == 0)
             {
-                uart_puts_p(PSTR("error opening "));
+                if(!print_disk_info(fs))
+                    uart_puts_p(PSTR("error reading disk info\n"));
+            }
+#if FAT16_WRITE_SUPPORT
+            else if(strncmp_P(command, PSTR("rm "), 3) == 0)
+            {
+                command += 3;
+                if(command[0] == '\0')
+                    continue;
+                
+                struct fat16_dir_entry_struct file_entry;
+                if(find_file_in_dir(fs, dd, command, &file_entry))
+                {
+                    if(fat16_delete_file(fs, &file_entry))
+                        continue;
+                }
+
+                uart_puts_p(PSTR("error deleting file: "));
                 uart_puts(command);
                 uart_putc('\n');
-                continue;
             }
+            else if(strncmp_P(command, PSTR("touch "), 6) == 0)
+            {
+                command += 6;
+                if(command[0] == '\0')
+                    continue;
 
-            /* print file contents */
-            uint8_t buffer[8];
-            uint32_t offset = 0;
-            while(fat16_read_file(fd, buffer, sizeof(buffer)) > 0)
-            {
-                uart_putdw_hex(offset);
-                uart_putc(':');
-                for(uint8_t i = 0; i < 8; ++i)
+                struct fat16_dir_entry_struct file_entry;
+                if(!fat16_create_file(dd, command, &file_entry))
                 {
-                    uart_putc(' ');
-                    uart_putc_hex(buffer[i]);
+                    uart_puts_p(PSTR("error creating file: "));
+                    uart_puts(command);
+                    uart_putc('\n');
                 }
-                uart_putc('\n');
-                offset += 8;
             }
-
-            fat16_close_file(fd);
-        }
-        else if(strcmp_P(command, PSTR("disk")) == 0)
-        {
-            if(!print_disk_info(fs))
-                uart_puts_p(PSTR("error reading disk info\n"));
-        }
-#if FAT16_WRITE_SUPPORT
-        else if(strncmp_P(command, PSTR("rm "), 3) == 0)
-        {
-            command += 3;
-            if(command[0] == '\0')
-                continue;
-            
-            struct fat16_dir_entry_struct file_entry;
-            if(find_file_in_dir(fs, dd, command, &file_entry))
+            else if(strncmp_P(command, PSTR("write "), 6) == 0)
             {
-                if(fat16_delete_file(fs, &file_entry))
+                command += 6;
+                if(command[0] == '\0')
                     continue;
-            }
 
-            uart_puts_p(PSTR("error deleting file: "));
-            uart_puts(command);
-            uart_putc('\n');
-        }
-        else if(strncmp_P(command, PSTR("touch "), 6) == 0)
-        {
-            command += 6;
-            if(command[0] == '\0')
-                continue;
+                char* offset_value = command;
+                while(*offset_value != ' ' && *offset_value != '\0')
+                    ++offset_value;
 
-            struct fat16_dir_entry_struct file_entry;
-            if(!fat16_create_file(dd, command, &file_entry))
-            {
-                uart_puts_p(PSTR("error creating file: "));
-                uart_puts(command);
-                uart_putc('\n');
-            }
-        }
-        else if(strncmp_P(command, PSTR("write "), 6) == 0)
-        {
-            command += 6;
-            if(command[0] == '\0')
-                continue;
+                if(*offset_value == ' ')
+                    *offset_value++ = '\0';
+                else
+                    continue;
 
-            char* offset_value = command;
-            while(*offset_value != ' ' && *offset_value != '\0')
-                ++offset_value;
+                /* search file in current directory and open it */
+                struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
+                if(!fd)
+                {
+                    uart_puts_p(PSTR("error opening "));
+                    uart_puts(command);
+                    uart_putc('\n');
+                    continue;
+                }
 
-            if(*offset_value == ' ')
-                *offset_value++ = '\0';
-            else
-                continue;
+                int32_t offset = strtolong(offset_value);
+                if(!fat16_seek_file(fd, &offset, FAT16_SEEK_SET))
+                {
+                    uart_puts_p(PSTR("error seeking on "));
+                    uart_puts(command);
+                    uart_putc('\n');
 
-            /* search file in current directory and open it */
-            struct fat16_file_struct* fd = open_file_in_dir(fs, dd, command);
-            if(!fd)
-            {
-                uart_puts_p(PSTR("error opening "));
-                uart_puts(command);
-                uart_putc('\n');
-                continue;
-            }
+                    fat16_close_file(fd);
+                    continue;
+                }
 
-            int32_t offset = strtolong(offset_value);
-            if(!fat16_seek_file(fd, &offset, FAT16_SEEK_SET))
-            {
-                uart_puts_p(PSTR("error seeking on "));
-                uart_puts(command);
-                uart_putc('\n');
+                /* read text from the shell and write it to the file */
+                uint8_t data_len;
+                while(1)
+                {
+                    /* give a different prompt */
+                    uart_putc('<');
+                    uart_putc(' ');
 
+                    /* read one line of text */
+                    data_len = read_line(buffer, sizeof(buffer));
+                    if(!data_len)
+                        break;
+
+                    /* write text to file */
+                    if(fat16_write_file(fd, (uint8_t*) buffer, data_len) != data_len)
+                    {
+                        uart_puts_p(PSTR("error writing to file\n"));
+                        break;
+                    }
+                }
+
                 fat16_close_file(fd);
-                continue;
             }
-
-            /* read text from the shell and write it to the file */
-            uint8_t data_len;
-            while(1)
+            else if(strncmp_P(command, PSTR("mkdir "), 6) == 0)
             {
-                /* give a different prompt */
-                uart_putc('<');
-                uart_putc(' ');
+                command += 6;
+                if(command[0] == '\0')
+                    continue;
 
-                /* read one line of text */
-                data_len = read_line(buffer, sizeof(buffer));
-                if(!data_len)
-                    break;
-
-                /* write text to file */
-                if(fat16_write_file(fd, (uint8_t*) buffer, data_len) != data_len)
+                struct fat16_dir_entry_struct dir_entry;
+                if(!fat16_create_dir(dd, command, &dir_entry))
                 {
-                    uart_puts_p(PSTR("error writing to file\n"));
-                    break;
+                    uart_puts_p(PSTR("error creating directory: "));
+                    uart_puts(command);
+                    uart_putc('\n');
                 }
             }
-
-            fat16_close_file(fd);
-        }
-        else if(strncmp_P(command, PSTR("mkdir "), 6) == 0)
-        {
-            command += 6;
-            if(command[0] == '\0')
-                continue;
-
-            struct fat16_dir_entry_struct dir_entry;
-            if(!fat16_create_dir(dd, command, &dir_entry))
+#endif
+#if SD_RAW_WRITE_BUFFERING
+            else if(strcmp_P(command, PSTR("sync")) == 0)
             {
-                uart_puts_p(PSTR("error creating directory: "));
+                if(!sd_raw_sync())
+                    uart_puts_p(PSTR("error syncing disk\n"));
+            }
+#endif
+            else
+            {
+                uart_puts_p(PSTR("unknown command: "));
                 uart_puts(command);
                 uart_putc('\n');
             }
         }
-#endif
-#if SD_RAW_WRITE_BUFFERING
-        else if(strcmp_P(command, PSTR("sync")) == 0)
-        {
-            if(!sd_raw_sync())
-                uart_puts_p(PSTR("error syncing disk\n"));
-        }
-#endif
-        else
-        {
-            uart_puts_p(PSTR("unknown command: "));
-            uart_puts(command);
-            uart_putc('\n');
-        }
-    }
 
-    /* close file system */
-    fat16_close(fs);
+        /* close file system */
+        fat16_close(fs);
 
-    /* close partition */
-    partition_close(partition);
+        /* close partition */
+        partition_close(partition);
+    }
     
     return 0;
 }
@@ -598,12 +607,14 @@
 
 void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec)
 {
+#if FAT16_DATETIME_SUPPORT
     *year = 2007;
     *month = 1;
     *day = 1;
     *hour = 0;
     *min = 0;
     *sec = 0;
+#endif
 }
 
 
Index: fat16.h
===================================================================
--- fat16.h	(.../sd-reader_release_20071213)	(Revision 126)
+++ fat16.h	(.../sd-reader_release_20080608)	(Revision 126)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2008 by Roland Riegel <feedback@roland-riegel.de>
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of either the GNU General Public License version 2
Index: Makefile
===================================================================
--- Makefile	(.../sd-reader_release_20071213)	(Revision 126)
+++ Makefile	(.../sd-reader_release_20080608)	(Revision 126)
@@ -25,7 +25,7 @@
 	rm -rf doc/html
 
 flash: $(HEX)
-	avrdude -y -p $(MCU_AVRDUDE) -U flash:w:$(HEX)
+	avrdude -y -c avr910 -p $(MCU_AVRDUDE) -U flash:w:$(HEX)
 
 $(HEX): $(OUT)
 	$(OBJCOPY) -R .eeprom -O ihex $< $@
