Index: fat16.c
===================================================================
--- fat16.c	(.../sd-reader_release_20060316)	(Revision 106)
+++ fat16.c	(.../sd-reader_release_20060319)	(Revision 106)
@@ -139,6 +139,7 @@
     struct fat16_fs_struct* fs;
     struct fat16_dir_entry_struct dir_entry;
     uint32_t pos;
+    uint16_t pos_cluster;
 };
 
 struct fat16_dir_struct
@@ -771,6 +772,7 @@
     memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry));
     fd->fs = fs;
     fd->pos = 0;
+    fd->pos_cluster = dir_entry->cluster;
 
     return fd;
 }
@@ -813,31 +815,38 @@
         return 0;
     
     uint16_t cluster_size = fd->fs->header.cluster_size;
-    uint16_t cluster_num = fd->dir_entry.cluster;
+    uint16_t cluster_num = fd->pos_cluster;
     uint16_t buffer_left = buffer_len;
-    uint16_t first_cluster_offset;
+    uint16_t first_cluster_offset = fd->pos % cluster_size;
 
     /* find cluster in which to start reading */
-    if(cluster_num)
+    if(!cluster_num)
     {
-        uint32_t pos = fd->pos;
-        while(pos >= cluster_size)
+        cluster_num = fd->dir_entry.cluster;
+        
+        if(!cluster_num)
         {
-            pos -= cluster_size;
-            cluster_num = fat16_get_next_cluster(fd->fs, cluster_num);
-            if(!cluster_num)
+            if(!fd->pos)
+                return 0;
+            else
                 return -1;
         }
 
-        first_cluster_offset = pos;
+        if(fd->pos)
+        {
+            uint32_t pos = fd->pos;
+            while(pos >= cluster_size)
+            {
+                pos -= cluster_size;
+                cluster_num = fat16_get_next_cluster(fd->fs, cluster_num);
+                if(!cluster_num)
+                    return -1;
+            }
+        }
     }
-    else
-    {
-        return -1;
-    }
     
     /* read data */
-    while(1)
+    do
     {
         /* calculate data size to copy from cluster */
         uint32_t cluster_offset = fd->fs->header.cluster_zero_offset +
@@ -855,17 +864,24 @@
         buffer_left -= copy_length;
         fd->pos += copy_length;
 
-        /* check if we are done */
-        if(buffer_left == 0)
-            break;
-        
-        /* we are on a cluster boundary, so get the next cluster */
-        if((cluster_num = fat16_get_next_cluster(fd->fs, cluster_num)))
-            first_cluster_offset = 0;
-        else
-            return buffer_len - buffer_left;
-    }
+        if(first_cluster_offset + copy_length >= cluster_size)
+        {
+            /* we are on a cluster boundary, so get the next cluster */
+            if((cluster_num = fat16_get_next_cluster(fd->fs, cluster_num)))
+            {
+                first_cluster_offset = 0;
+            }
+            else
+            {
+                fd->pos_cluster = 0;
+                return buffer_len - buffer_left;
+            }
+        }
 
+        fd->pos_cluster = cluster_num;
+
+    } while(buffer_left > 0); /* check if we are done */
+
     return buffer_len;
 }
 
@@ -891,36 +907,51 @@
         return -1;
 
     uint16_t cluster_size = fd->fs->header.cluster_size;
-    uint16_t cluster_num = fd->dir_entry.cluster;
+    uint16_t cluster_num = fd->pos_cluster;
     uint16_t buffer_left = buffer_len;
-    uint16_t first_cluster_offset = 0;
+    uint16_t first_cluster_offset = fd->pos % cluster_size;
 
     /* find cluster in which to start writing */
-    if(cluster_num)
+    if(!cluster_num)
     {
-        uint32_t pos = fd->pos;
-        while(pos >= cluster_size)
+        cluster_num = fd->dir_entry.cluster;
+        
+        if(!cluster_num)
         {
-            pos -= cluster_size;
-            cluster_num = fat16_get_next_cluster(fd->fs, cluster_num);
-            if(!cluster_num && pos == 0)
-                /* the file exactly ends on a cluster boundary, and we append to it */
-                cluster_num = fat16_append_cluster(fd->fs, cluster_num);
-            if(!cluster_num)
+            if(!fd->pos)
+            {
+                /* empty file */
+                fd->dir_entry.cluster = cluster_num = fat16_append_cluster(fd->fs, 0);
+                if(!cluster_num)
+                    return -1;
+            }
+            else
+            {
                 return -1;
+            }
         }
 
-        first_cluster_offset = pos;
+        if(fd->pos)
+        {
+            uint32_t pos = fd->pos;
+            uint16_t cluster_num_next;
+            while(pos >= cluster_size)
+            {
+                pos -= cluster_size;
+                cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
+                if(!cluster_num_next && pos == 0)
+                    /* the file exactly ends on a cluster boundary, and we append to it */
+                    cluster_num_next = fat16_append_cluster(fd->fs, cluster_num);
+                if(!cluster_num_next)
+                    return -1;
+
+                cluster_num = cluster_num_next;
+            }
+        }
     }
-    else
-    {
-        fd->dir_entry.cluster = cluster_num = fat16_append_cluster(fd->fs, 0);
-        if(!cluster_num)
-            return -1;
-    }
     
     /* write data */
-    while(1)
+    do
     {
         /* calculate data size to write to cluster */
         uint32_t cluster_offset = fd->fs->header.cluster_zero_offset +
@@ -938,23 +969,27 @@
         buffer_left -= write_length;
         fd->pos += write_length;
 
-        /* check if we are done */
-        if(buffer_left == 0)
-            break;
-        
-        /* we are on a cluster boundary, so get the next cluster */
-        uint16_t cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
-        if(!cluster_num_next)
+        if(first_cluster_offset + write_length >= cluster_size)
         {
-            cluster_num_next = fat16_append_cluster(fd->fs, cluster_num);
+            /* we are on a cluster boundary, so get the next cluster */
+            uint16_t cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
+            if(!cluster_num_next && buffer_left > 0)
+                /* we reached the last cluster, append a new one */
+                cluster_num_next = fat16_append_cluster(fd->fs, cluster_num);
             if(!cluster_num_next)
+            {
+                fd->pos_cluster = 0;
                 break;
+            }
+
+            cluster_num = cluster_num_next;
+            first_cluster_offset = 0;
         }
-        cluster_num = cluster_num_next;
-        
-        first_cluster_offset = 0;
-    }
 
+        fd->pos_cluster = cluster_num;
+
+    } while(buffer_left > 0); /* check if we are done */
+
     /* update directory entry */
     if(fd->pos > fd->dir_entry.file_size)
     {
@@ -1032,6 +1067,8 @@
         return 0;
 
     fd->pos = new_pos;
+    fd->pos_cluster = 0;
+
     *offset = new_pos;
     return 1;
 }
@@ -1133,6 +1170,13 @@
                 cluster_num = cluster_num_next;
             }
         }
+
+        /* correct file position */
+        if(size < fd->pos)
+        {
+            fd->pos = size;
+            fd->pos_cluster = 0;
+        }
     }
     
     return 1;
Index: main.c
===================================================================
--- main.c	(.../sd-reader_release_20060316)	(Revision 106)
+++ main.c	(.../sd-reader_release_20060319)	(Revision 106)
@@ -69,17 +69,17 @@
  *     </tr>
  *     <tr>
  *         <td>Partition</td>
- *         <td align="right">394</td>
+ *         <td align="right">382</td>
  *         <td align="right">0</td>
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-only)</td>
- *         <td align="right">3316</td>
+ *         <td align="right">3414</td>
  *         <td align="right">0</td>
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-write)</td>
- *         <td align="right">6158</td>
+ *         <td align="right">6412</td>
  *         <td align="right">0</td>
  *     </tr>
  * </table>
@@ -115,7 +115,7 @@
  *     </tr>
  *     <tr>
  *         <td>file</td>
- *         <td align="right">49</td>
+ *         <td align="right">51</td>
  *     </tr>
  *     <tr>
  *         <td>directory</td>
