Index: fat16.c
===================================================================
--- fat16.c	(.../sd-reader_release_20060824)	(Revision 106)
+++ fat16.c	(.../sd-reader_release_20060901)	(Revision 106)
@@ -177,6 +177,7 @@
 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_write_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry);
 
 static uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p);
@@ -792,11 +793,12 @@
  *
  * \note If this function is used for freeing just a part of a cluster
  *       chain, the new end of the chain is not correctly terminated
- *       within the FAT. This has to be done manually afterwards.
+ *       within the FAT. Use fat16_terminate_clusters() instead.
  *
  * \param[in] fs The filesystem on which to operate.
  * \param[in] cluster_num The starting cluster of the chain which to free.
  * \returns 0 on failure, 1 on success.
+ * \see fat16_terminate_clusters
  */
 uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num)
 {
@@ -845,6 +847,44 @@
 }
 
 /**
+ * \ingroup fat16_fs
+ * Frees a part of a cluster chain and correctly terminates the rest.
+ *
+ * Marks the specified cluster as the new end of a cluster chain and
+ * frees all following clusters.
+ *
+ * \param[in] fs The filesystem on which to operate.
+ * \param[in] cluster_num The new end of the cluster chain.
+ * \returns 0 on failure, 1 on success.
+ * \see fat16_free_clusters
+ */
+uint8_t fat16_terminate_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num)
+{
+#if FAT16_WRITE_SUPPORT
+    if(!fs || cluster_num < 2)
+        return 0;
+
+    /* fetch next cluster before overwriting the cluster entry */
+    uint16_t cluster_num_next = fat16_get_next_cluster(fs, cluster_num);
+
+    /* mark cluster as the last one */
+    uint8_t buffer[2];
+    buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;
+    buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;
+    if(!fs->partition->device_write(fs->header.fat_offset + 2 * cluster_num, buffer, 2))
+        return 0;
+
+    /* free remaining clusters */
+    if(cluster_num_next)
+        return fat16_free_clusters(fs, cluster_num_next);
+    else
+        return 1;
+#else
+    return 0;
+#endif
+}
+
+/**
  * \ingroup fat16_file
  * Opens a file on a FAT16 filesystem.
  *
@@ -1202,22 +1242,13 @@
             break;
 
         /* seek to the next cluster as long as we need the space */
-        while(size_new > 0)
+        while(size_new > cluster_size)
         {
             /* get next cluster of file */
             uint16_t cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
             if(cluster_num_next)
             {
                 cluster_num = cluster_num_next;
-
-                if(size_new <= cluster_size)
-                {
-                    /* file will shrink; get the first cluster to deallocate */
-                    cluster_num = fat16_get_next_cluster(fd->fs, cluster_num);
-                    size_new = 0;
-                    break;
-                }
-
                 size_new -= cluster_size;
             }
             else
@@ -1226,7 +1257,7 @@
             }
         }
 
-        if(size_new > 0)
+        if(size_new > cluster_size || cluster_num == 0)
         {
             /* Allocate new cluster chain and append
              * it to the existing one, if available.
@@ -1252,11 +1283,16 @@
         if(!fat16_write_dir_entry(fd->fs, &fd->dir_entry))
             return 0;
 
-        if(size_new == 0)
+        if(size == 0)
         {
-            /* free all clusters no longer needed */
+            /* free all clusters of file */
             fat16_free_clusters(fd->fs, cluster_num);
         }
+        else if(size_new <= cluster_size)
+        {
+            /* free all clusters no longer needed */
+            fat16_terminate_clusters(fd->fs, cluster_num);
+        }
 
     } while(0);
 
@@ -1741,21 +1777,33 @@
     if(!fs)
         return 0;
 
-    uint8_t fat[8];
+    uint8_t fat[32];
     struct fat16_usage_count_callback_arg count_arg;
     count_arg.cluster_count = 0;
     count_arg.buffer_size = sizeof(fat);
 
-    if(!fs->partition->device_read_interval(fs->header.fat_offset,
-                                            fat,
-                                            sizeof(fat),
-                                            fs->header.fat_size,
-                                            fat16_get_fs_free_callback,
-                                            &count_arg
-                                           )
-      )
-        return 0;
+    uint32_t fat_offset = fs->header.fat_offset;
+    uint32_t fat_size = fs->header.fat_size;
+    while(fat_size > 0)
+    {
+        uint16_t length = UINT16_MAX - 1;
+        if(fat_size < length)
+            length = fat_size;
 
+        if(!fs->partition->device_read_interval(fat_offset,
+                                                fat,
+                                                sizeof(fat),
+                                                length,
+                                                fat16_get_fs_free_callback,
+                                                &count_arg
+                                               )
+          )
+            return 0;
+
+        fat_offset += length;
+        fat_size -= length;
+    }
+
     return (uint32_t) count_arg.cluster_count * fs->header.cluster_size;
 }
 
@@ -1766,8 +1814,9 @@
 uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p)
 {
     struct fat16_usage_count_callback_arg* count_arg = (struct fat16_usage_count_callback_arg*) p;
+    uint8_t buffer_size = count_arg->buffer_size;
 
-    for(uint8_t i = 0; i < count_arg->buffer_size; i += 2)
+    for(uint8_t i = 0; i < buffer_size; i += 2)
     {
         if((((uint16_t) buffer[1] << 8) | ((uint16_t) buffer[0] << 0)) == FAT16_CLUSTER_FREE)
             ++(count_arg->cluster_count);
Index: main.c
===================================================================
--- main.c	(.../sd-reader_release_20060824)	(Revision 106)
+++ main.c	(.../sd-reader_release_20060901)	(Revision 106)
@@ -101,12 +101,12 @@
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-only)</td>
- *         <td align="right">3722</td>
+ *         <td align="right">3828</td>
  *         <td align="right">0</td>
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-write)</td>
- *         <td align="right">7024</td>
+ *         <td align="right">7298</td>
  *         <td align="right">0</td>
  *     </tr>
  * </table>
Index: ChangeLog
===================================================================
--- ChangeLog	(.../sd-reader_release_20060824)	(Revision 106)
+++ ChangeLog	(.../sd-reader_release_20060901)	(Revision 106)
@@ -1,4 +1,8 @@
 
+2006-09-01 sd-reader
+	* Fix shortening files.
+	* Fix free disk space calculation.
+
 2006-08-24 sd-reader
 	* Improve sleep handling.
 	* Display extended card information on boot and
