Index: sd-reader_config.h
===================================================================
--- sd-reader_config.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ sd-reader_config.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: byteordering.h
===================================================================
--- byteordering.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ byteordering.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -30,10 +30,27 @@
  * \author Roland Riegel
  */
 
+#define SWAP16(val) ((((uint16_t) (val)) << 8) | \
+                     (((uint16_t) (val)) >> 8)   \
+                    )
+#define SWAP32(val) (((((uint32_t) (val)) & 0x000000ff) << 24) | \
+                     ((((uint32_t) (val)) & 0x0000ff00) <<  8) | \
+                     ((((uint32_t) (val)) & 0x00ff0000) >>  8) | \
+                     ((((uint32_t) (val)) & 0xff000000) >> 24)   \
+                    )
+
+#if LITTLE_ENDIAN || __AVR__
+#define SWAP_NEEDED 0
+#elif BIG_ENDIAN
+#define SWAP_NEEDED 1
+#else
+#error "Endianess undefined! Please define LITTLE_ENDIAN=1 or BIG_ENDIAN=1."
+#endif
+
 /**
  * \def HTOL16(val)
  *
- * Converts a 16-bit integer to little-endian byte order.
+ * Converts a 16-bit integer from host byte order to little-endian byte order.
  *
  * Use this macro for compile time constants only. For variable values
  * use the function htol16() instead. This saves code size.
@@ -44,7 +61,7 @@
 /**
  * \def HTOL32(val)
  *
- * Converts a 32-bit integer to little-endian byte order.
+ * Converts a 32-bit integer from host byte order to little-endian byte order.
  *
  * Use this macro for compile time constants only. For variable values
  * use the function htol32() instead. This saves code size.
@@ -52,65 +69,78 @@
  * \param[in] val A 32-bit integer in host byte order.
  * \returns The given 32-bit integer converted to little-endian byte order.
  */
-
-#if DOXYGEN || LITTLE_ENDIAN || __AVR__
-#define HTOL16(val) (val)
-#define HTOL32(val) (val)
-#elif BIG_ENDIAN
-#define HTOL16(val) ((((uint16_t) (val)) << 8) | \
-                     (((uint16_t) (val)) >> 8)   \
-                    )
-#define HTOL32(val) (((((uint32_t) (val)) & 0x000000ff) << 24) | \
-                     ((((uint32_t) (val)) & 0x0000ff00) <<  8) | \
-                     ((((uint32_t) (val)) & 0x00ff0000) >>  8) | \
-                     ((((uint32_t) (val)) & 0xff000000) >> 24)   \
-                    )
-#else
-#error "Endianess undefined! Please define LITTLE_ENDIAN=1 or BIG_ENDIAN=1."
-#endif
-
-uint16_t htol16(uint16_t h);
-uint32_t htol32(uint32_t h);
-
 /**
- * Converts a 16-bit integer to host byte order.
+ * \def LTOH16(val)
  *
+ * Converts a 16-bit integer from little-endian byte order to host byte order.
+ *
  * Use this macro for compile time constants only. For variable values
  * use the function ltoh16() instead. This saves code size.
  *
  * \param[in] val A 16-bit integer in little-endian byte order.
  * \returns The given 16-bit integer converted to host byte order.
  */
-#define LTOH16(val) HTOL16(val)
-
 /**
- * Converts a 32-bit integer to host byte order.
+ * \def LTOH32(val)
  *
+ * Converts a 32-bit integer from little-endian byte order to host byte order.
+ *
  * Use this macro for compile time constants only. For variable values
  * use the function ltoh32() instead. This saves code size.
  *
  * \param[in] val A 32-bit integer in little-endian byte order.
  * \returns The given 32-bit integer converted to host byte order.
  */
-#define LTOH32(val) HTOL32(val)
 
+#if SWAP_NEEDED
+#define HTOL16(val) SWAP16(val)
+#define HTOL32(val) SWAP32(val)
+#define LTOH16(val) SWAP16(val)
+#define LTOH32(val) SWAP32(val)
+#else
+#define HTOL16(val) (val)
+#define HTOL32(val) (val)
+#define LTOH16(val) (val)
+#define LTOH32(val) (val)
+#endif
+
+#if DOXYGEN
+
 /**
- * Converts a 16-bit integer to host byte order.
+ * Converts a 16-bit integer from host byte order to little-endian byte order.
  *
  * Use this function on variable values instead of the
+ * macro HTOL16(). This saves code size.
+ *
+ * \param[in] h A 16-bit integer in host byte order.
+ * \returns The given 16-bit integer converted to little-endian byte order.
+ */
+uint16_t htol16(uint16_t h);
+
+/**
+ * Converts a 32-bit integer from host byte order to little-endian byte order.
+ *
+ * Use this function on variable values instead of the
+ * macro HTOL32(). This saves code size.
+ *
+ * \param[in] h A 32-bit integer in host byte order.
+ * \returns The given 32-bit integer converted to little-endian byte order.
+ */
+uint32_t htol32(uint32_t h);
+
+/**
+ * Converts a 16-bit integer from little-endian byte order to host byte order.
+ *
+ * Use this function on variable values instead of the
  * macro LTOH16(). This saves code size.
  *
  * \param[in] l A 16-bit integer in little-endian byte order.
  * \returns The given 16-bit integer converted to host byte order.
  */
-#if DOXYGEN
 uint16_t ltoh16(uint16_t l);
-#else
-#define ltoh16(l) htol16(l)
-#endif
 
 /**
- * Converts a 32-bit integer to host byte order.
+ * Converts a 32-bit integer from little-endian byte order to host byte order.
  *
  * Use this function on variable values instead of the
  * macro LTOH32(). This saves code size.
@@ -118,22 +148,53 @@
  * \param[in] l A 32-bit integer in little-endian byte order.
  * \returns The given 32-bit integer converted to host byte order.
  */
-#if DOXYGEN
 uint32_t ltoh32(uint32_t l);
+
+uint16_t read16(const uint8_t* p);
+uint32_t read32(const uint8_t* p);
+void write16(uint8_t* p, uint16_t i);
+void write32(uint8_t* p, uint32_t i);
+
+#elif SWAP_NEEDED
+
+#define htol16(h) swap16(h)
+#define htol32(h) swap32(h)
+#define ltoh16(l) swap16(l)
+#define ltoh32(l) swap32(l)
+
+uint16_t read16(const uint8_t* p);
+uint32_t read32(const uint8_t* p);
+void write16(uint8_t* p, uint16_t i);
+void write32(uint8_t* p, uint32_t i);
+
 #else
-#define ltoh32(l) htol32(l)
+
+#define htol16(h) (h)
+#define htol32(h) (h)
+#define ltoh16(l) (l)
+#define ltoh32(l) (l)
+
+#if __AVR__
+#define read16(p) (*(const uint16_t*) (p))
+#define read32(p) (*(const uint32_t*) (p))
+#define write16(p, i) { *((uint16_t*) (p)) = i; }
+#define write32(p, i) { *((uint32_t*) (p)) = i; }
+#else
+uint16_t read16(const uint8_t* p);
+uint32_t read32(const uint8_t* p);
+void write16(uint8_t* p, uint16_t i);
+void write32(uint8_t* p, uint32_t i);
 #endif
 
+#endif
+
 /**
  * @}
  */
 
-#if LITTLE_ENDIAN || __AVR__
-#define htol16(h) (h)
-#define htol32(h) (h)
-#else
-uint16_t htol16(uint16_t h);
-uint32_t htol32(uint32_t h);
+#if SWAP_NEEDED
+uint16_t swap16(uint16_t i);
+uint32_t swap32(uint32_t i);
 #endif
 
 #ifdef __cplusplus
Index: partition_config.h
===================================================================
--- partition_config.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ partition_config.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: fat_config.h
===================================================================
--- fat_config.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ fat_config.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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_20101010)	(Revision 172)
+++ ChangeLog	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,4 +1,11 @@
 
+2011-02-05 sd-reader
+	* implement renaming a file or directory
+	* rewrite byteorder handling to fix unaligned memory accesses on 32-bit and probably 16-bit architectures
+	* make fat_create_file() not return failure if the file already exists
+	* make the "cat" output respect the count of bytes actually read
+	* document how to use fat_seek_file() for retrieving the file position
+
 2010-10-10 sd-reader
 	* Fix equal file names when reading two successive 8.3 directory entries.
 	* Fix calculation of cluster positions beyond 4GB (32 bit integer overflow).
Index: sd_raw_config.h
===================================================================
--- sd_raw_config.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ sd_raw_config.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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_20101010)	(Revision 172)
+++ partition.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include "byteordering.h"
 #include "partition.h"
 #include "partition_config.h"
 #include "sd-reader_config.h"
@@ -110,14 +111,8 @@
     if(index >= 0)
     {
         new_partition->type = buffer[4];
-        new_partition->offset = ((uint32_t) buffer[8]) |
-                                ((uint32_t) buffer[9] << 8) |
-                                ((uint32_t) buffer[10] << 16) |
-                                ((uint32_t) buffer[11] << 24);
-        new_partition->length = ((uint32_t) buffer[12]) |
-                                ((uint32_t) buffer[13] << 8) |
-                                ((uint32_t) buffer[14] << 16) |
-                                ((uint32_t) buffer[15] << 24);
+        new_partition->offset = read32(&buffer[8]);
+        new_partition->length = read32(&buffer[12]);
     }
     else
     {
Index: fat.c
===================================================================
--- fat.c	(.../sd-reader_release_20101010)	(Revision 172)
+++ fat.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /* 
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -304,7 +304,7 @@
  * \ingroup fat_fs
  * Reads and parses the header of a FAT filesystem.
  *
- * \param[inout] fs The filesystem for which to parse the header.
+ * \param[in,out] fs The filesystem for which to parse the header.
  * \returns 0 on failure, 1 on success.
  */
 uint8_t fat_read_header(struct fat_fs_struct* fs)
@@ -326,17 +326,17 @@
     if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
         return 0;
 
-    uint16_t bytes_per_sector = ltoh16(*((uint16_t*) &buffer[0x00]));
-    uint16_t reserved_sectors = ltoh16(*((uint16_t*) &buffer[0x03]));
+    uint16_t bytes_per_sector = read16(&buffer[0x00]);
+    uint16_t reserved_sectors = read16(&buffer[0x03]);
     uint8_t sectors_per_cluster = buffer[0x02];
     uint8_t fat_copies = buffer[0x05];
-    uint16_t max_root_entries = ltoh16(*((uint16_t*) &buffer[0x06]));
-    uint16_t sector_count_16 = ltoh16(*((uint16_t*) &buffer[0x08]));
-    uint16_t sectors_per_fat = ltoh16(*((uint16_t*) &buffer[0x0b]));
-    uint32_t sector_count = ltoh32(*((uint32_t*) &buffer[0x15]));
+    uint16_t max_root_entries = read16(&buffer[0x06]);
+    uint16_t sector_count_16 = read16(&buffer[0x08]);
+    uint16_t sectors_per_fat = read16(&buffer[0x0b]);
+    uint32_t sector_count = read32(&buffer[0x15]);
 #if FAT_FAT32_SUPPORT
-    uint32_t sectors_per_fat32 = ltoh32(*((uint32_t*) &buffer[0x19]));
-    uint32_t cluster_root_dir = ltoh32(*((uint32_t*) &buffer[0x21]));
+    uint32_t sectors_per_fat32 = read32(&buffer[0x19]);
+    uint32_t cluster_root_dir = read32(&buffer[0x21]);
 #endif
 
     if(sector_count == 0)
@@ -1221,6 +1221,16 @@
  *
  * The resulting absolute offset is written to the location the \c offset
  * parameter points to.
+ *
+ * Calling this function can also be used to retrieve the current file position:
+   \code
+   int32_t file_pos = 0;
+   if(!fat_seek_file(fd, &file_pos, FAT_SEEK_CUR))
+   {
+       // error
+   }
+   // file_pos now contains the absolute file position
+   \endcode
  * 
  * \param[in] fd The file decriptor of the file on which to seek.
  * \param[in,out] offset A pointer to the new offset, as affected by the \c whence
@@ -1678,15 +1688,15 @@
         
         /* extract properties of file and store them within the structure */
         dir_entry->attributes = buffer[11];
-        dir_entry->cluster = ltoh16(*((uint16_t*) &buffer[26]));
+        dir_entry->cluster = read16(&buffer[26]);
 #if FAT_FAT32_SUPPORT
-        dir_entry->cluster |= ((cluster_t) ltoh16(*((uint16_t*) &buffer[20]))) << 16;
+        dir_entry->cluster |= ((cluster_t) read16(&buffer[20])) << 16;
 #endif
-        dir_entry->file_size = ltoh32(*((uint32_t*) &buffer[28]));
+        dir_entry->file_size = read32(&buffer[28]);
 
 #if FAT_DATETIME_SUPPORT
-        dir_entry->modification_time = ltoh16(*((uint16_t*) &buffer[22]));
-        dir_entry->modification_date = ltoh16(*((uint16_t*) &buffer[24]));
+        dir_entry->modification_time = read16(&buffer[22]);
+        dir_entry->modification_date = read16(&buffer[24]);
 #endif
 
         arg->finished = 1;
@@ -1946,14 +1956,14 @@
     memset(&buffer[11], 0, sizeof(buffer) - 11);
     buffer[0x0b] = dir_entry->attributes;
 #if FAT_DATETIME_SUPPORT
-    *((uint16_t*) &buffer[0x16]) = htol16(dir_entry->modification_time);
-    *((uint16_t*) &buffer[0x18]) = htol16(dir_entry->modification_date);
+    write16(&buffer[0x16], dir_entry->modification_time);
+    write16(&buffer[0x18], dir_entry->modification_date);
 #endif
 #if FAT_FAT32_SUPPORT
-    *((uint16_t*) &buffer[0x14]) = htol16((uint16_t) (dir_entry->cluster >> 16));
+    write16(&buffer[0x14], (uint16_t) (dir_entry->cluster >> 16));
 #endif
-    *((uint16_t*) &buffer[0x1a]) = htol16(dir_entry->cluster);
-    *((uint32_t*) &buffer[0x1c]) = htol32(dir_entry->file_size);
+    write16(&buffer[0x1a], dir_entry->cluster);
+    write32(&buffer[0x1c], dir_entry->file_size);
 
     /* write to disk */
 #if FAT_LFN_SUPPORT
@@ -2044,8 +2054,8 @@
  *
  * \param[in] parent The handle of the directory in which to create the file.
  * \param[in] file The name of the file to create.
- * \param[out] dir_entry The directory entry to fill for the new file.
- * \returns 0 on failure, 1 on success.
+ * \param[out] dir_entry The directory entry to fill for the new (or existing) file.
+ * \returns 0 on failure, 1 on success, 2 if the file already existed.
  * \see fat_delete_file
  */
 uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry)
@@ -2062,7 +2072,7 @@
         if(strcmp(file, dir_entry->long_name) == 0)
         {
             fat_reset_dir(parent);
-            return 0;
+            return 2;
         }
     }
 
@@ -2146,6 +2156,73 @@
 
 #if DOXYGEN || FAT_WRITE_SUPPORT
 /**
+ * \ingroup fat_file
+ * Moves or renames a file.
+ *
+ * Changes a file's name, optionally moving it into another
+ * directory as well. Before calling this function, the
+ * target file name must not exist. Moving a file to a
+ * different filesystem (i.e. \a parent_new doesn't lie on
+ * \a fs) is not supported.
+ * 
+ * After successfully renaming (and moving) the file, the
+ * given directory entry is updated such that it points to
+ * the file's new location.
+ *
+ * \note The notes which apply to fat_create_file() also
+ * apply to this function.
+ *
+ * \param[in] fs The filesystem on which to operate.
+ * \param[in,out] dir_entry The directory entry of the file to move.
+ * \param[in] parent_new The handle of the new parent directory of the file.
+ * \param[in] file_new The file's new name.
+ * \returns 0 on failure, 1 on success.
+ * \see fat_create_file, fat_delete_file, fat_move_dir
+ */
+uint8_t fat_move_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry, struct fat_dir_struct* parent_new, const char* file_new)
+{
+    if(!fs || !dir_entry || !parent_new || (file_new && !file_new[0]))
+        return 0;
+    if(fs != parent_new->fs)
+        return 0;
+
+    /* use existing file name if none has been specified */
+    if(!file_new)
+        file_new = dir_entry->long_name;
+
+    /* create file with new file name */
+    struct fat_dir_entry_struct dir_entry_new;
+    if(!fat_create_file(parent_new, file_new, &dir_entry_new))
+        return 0;
+
+    /* copy members of directory entry which do not change with rename */
+    dir_entry_new.attributes = dir_entry->attributes;
+#if FAT_DATETIME_SUPPORT
+    dir_entry_new.modification_time = dir_entry->modification_time;
+    dir_entry_new.modification_date = dir_entry->modification_date;
+#endif
+    dir_entry_new.cluster = dir_entry->cluster;
+    dir_entry_new.file_size = dir_entry->file_size;
+
+    /* make the new file name point to the old file's content */
+    if(!fat_write_dir_entry(fs, &dir_entry_new))
+    {
+        fat_delete_file(fs, &dir_entry_new);
+        return 0;
+    }
+    
+    /* delete the old file, but not its clusters, which have already been remapped above */
+    dir_entry->cluster = 0;
+    if(!fat_delete_file(fs, dir_entry))
+        return 0;
+
+    *dir_entry = dir_entry_new;
+    return 1;
+}
+#endif
+
+#if DOXYGEN || FAT_WRITE_SUPPORT
+/**
  * \ingroup fat_dir
  * Creates a directory.
  *
@@ -2154,7 +2231,7 @@
  * directory entry will be returned within the dir_entry
  * parameter.
  *
- * \note The notes which apply to fat_create_file also
+ * \note The notes which apply to fat_create_file() also
  * apply to this function.
  *
  * \param[in] parent The handle of the parent directory of the new directory.
@@ -2253,6 +2330,23 @@
 uint8_t fat_delete_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry);
 #endif
 
+/**
+ * \ingroup fat_dir
+ * Moves or renames a directory.
+ *
+ * This is just a synonym for fat_move_file().
+ * 
+ * \param[in] fs The filesystem on which to operate.
+ * \param[in,out] dir_entry The directory entry of the directory to move.
+ * \param[in] parent_new The handle of the new parent directory.
+ * \param[in] dir_new The directory's new name.
+ * \returns 0 on failure, 1 on success.
+ * \see fat_create_dir, fat_delete_dir, fat_move_file
+ */
+#ifdef DOXYGEN
+uint8_t fat_move_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry, struct fat_dir_struct* parent_new, const char* dir_new);
+#endif
+
 #if DOXYGEN || FAT_DATETIME_SUPPORT
 /**
  * \ingroup fat_file
Index: uart.c
===================================================================
--- uart.c	(.../sd-reader_release_20101010)	(Revision 172)
+++ uart.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: partition.h
===================================================================
--- partition.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ partition.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: fat.h
===================================================================
--- fat.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ fat.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -106,8 +106,10 @@
 
 uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry);
 uint8_t fat_delete_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry);
+uint8_t fat_move_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry, struct fat_dir_struct* parent_new, const char* file_new);
 uint8_t fat_create_dir(struct fat_dir_struct* parent, const char* dir, struct fat_dir_entry_struct* dir_entry);
 #define fat_delete_dir fat_delete_file
+#define fat_move_dir fat_move_file
 
 void fat_get_file_modification_date(const struct fat_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day);
 void fat_get_file_modification_time(const struct fat_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec);
Index: sd_raw.c
===================================================================
--- sd_raw.c	(.../sd-reader_release_20101010)	(Revision 172)
+++ sd_raw.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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.h
===================================================================
--- uart.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ uart.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: main.c
===================================================================
--- main.c	(.../sd-reader_release_20101010)	(Revision 172)
+++ main.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -77,6 +77,8 @@
  *   Shows the content of the current directory.
  * - <tt>mkdir \<directory\></tt>\n
  *   Creates a directory called \<directory\>.
+ * - <tt>mv \<file\> \<file_new\></tt>\n
+ *   Renames \<file\> to \<file_new\>. 
  * - <tt>rm \<file\></tt>\n
  *   Deletes \<file\>.
  * - <tt>sync</tt>\n
@@ -182,7 +184,7 @@
  * MMC cards to the Atmel microcontroller (http://www.ulrichradig.de/).
  * I adapted his work for my circuit.
  * 
- * \section copyright Copyright 2006-2010 by Roland Riegel
+ * \section copyright Copyright 2006-2011 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).
@@ -368,11 +370,12 @@
                 /* print file contents */
                 uint8_t buffer[8];
                 uint32_t offset = 0;
-                while(fat_read_file(fd, buffer, sizeof(buffer)) > 0)
+                intptr_t count;
+                while((count = fat_read_file(fd, buffer, sizeof(buffer))) > 0)
                 {
                     uart_putdw_hex(offset);
                     uart_putc(':');
-                    for(uint8_t i = 0; i < 8; ++i)
+                    for(intptr_t i = 0; i < count; ++i)
                     {
                         uart_putc(' ');
                         uart_putc_hex(buffer[i]);
@@ -420,6 +423,32 @@
                     uart_putc('\n');
                 }
             }
+            else if(strncmp_P(command, PSTR("mv "), 3) == 0)
+            {
+                command += 3;
+                if(command[0] == '\0')
+                    continue;
+
+                char* target = command;
+                while(*target != ' ' && *target != '\0')
+                    ++target;
+
+                if(*target == ' ')
+                    *target++ = '\0';
+                else
+                    continue;
+
+                struct fat_dir_entry_struct file_entry;
+                if(find_file_in_dir(fs, dd, command, &file_entry))
+                {
+                    if(fat_move_file(fs, &file_entry, dd, target))
+                        continue;
+                }
+
+                uart_puts_p(PSTR("error moving file: "));
+                uart_puts(command);
+                uart_putc('\n');
+            }
             else if(strncmp_P(command, PSTR("write "), 6) == 0)
             {
                 command += 6;
Index: sd_raw.h
===================================================================
--- sd_raw.h	(.../sd-reader_release_20101010)	(Revision 172)
+++ sd_raw.h	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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: FAQ
===================================================================
--- FAQ	(.../sd-reader_release_20101010)	(Revision 0)
+++ FAQ	(.../sd-reader_release_20110205)	(Revision 172)
@@ -0,0 +1,124 @@
+Frequently Asked Questions for sd-reader
+========================================
+
+General
+-------
+
+Q: Which cards are supported?
+A: All MMC/SD/SDHC/miniSD/microSD/microSDHC should work, although not all variants have been tested.
+   Some very old (low capacity) cards might be broken as well. Cards with a capacity of 16 MB or
+   less are usually formatted with FAT12, so these are supported in raw mode only, if at all.
+
+Q: What data rates can I expect?
+A: See the benchmark page on the homepage.
+   http://www.roland-riegel.de/sd-reader/benchmarks/
+
+Q: Are there boards available for purchase?
+A: No.
+
+Hardware
+--------
+
+Q: Where can I find the schematic?
+A: Get it on the homepage.
+   http://www.roland-riegel.de/sd-reader/sd-reader_circuit_latest.zip
+
+Q: What if my card socket has no Card-Detect and/or Card-Lock switches?
+A: Change sd_raw_config.h such that it looks like
+
+   #define configure_pin_available() /* nothing */
+   #define configure_pin_locked() /* nothing */
+
+   #define get_pin_available() 0
+   #define get_pin_locked() 1 
+
+Q: All attempts to write to the card fail, although reading works. What's the problem?
+A: Enable write support within sd_raw_config.h. And probably, your card socket has no Card-lock
+   detection (see question above).
+
+Q: The card initialization fails. What can I do?
+A: Usually this is some kind of hardware problem.
+   *  Check the physical connections.
+   *  Keep the signal lines to the card as short as possible.
+   *  Do not use diodes to derive the card's supply voltage. Use a 3.3V voltage regulator instead.
+   *  Have a stable, buffered power supply and use capacitors for correct voltage regulator
+      operation (see the schematics linked above).
+   *  Use extra capacitors of 50uF and 100nF as close to the card as possible.
+   *  When using an integrated level shifter or no level shifting at all (see the next question),
+      try adding a pullup of 50k from the data-out line of the card to 3.3V.
+   *  Make sure the limiting frequency of the level shifter is not exceeded. Have a look into its
+      datasheet!
+   *  Check the signals with a scope.
+
+Q: What alternatives to resistor level shifting exist?
+A: If you want to use additional devices with SPI or the resistor solution appears too ugly, there
+   are two possibilities. Either operate the whole circuit with a single 3.3V supply and no level
+   shifting at all or use a level shifting IC which interfaces the memory card to the AVR.
+   Depending on your requirements, adequate devices could include MAX3378E, MAX3392E, MAX3395E,
+   74LVC245 and 74HCT4050 (optionally together with 74HCT125). Please check the datasheets for the
+   required DC/AC characteristics!
+
+Software
+--------
+
+Q: What's the software license?
+A: GPLv2 or (for most parts) LGPLv2.1. Before using a file, read its license terms included at the
+   beginning of the file.
+
+Q: What's the programming language used?
+A: It's C, in compliance with the ISO C99 standard.
+
+Q: What are these .patch-files provided?
+A: Those record the source code differences between the old and new release. If you edited your
+   private sd-reader version, it might be easier to apply the patch files using the "patch" utility
+   common on Unix-like systems, rather than manually inserting the changes by hand. For Windows
+   users, the GnuWin32 project provides a port of "patch".
+
+Q: Where can I learn more about the library interface and how to use it?
+A: Look into the HTML documentation provided online or within each source distribution. Also take
+   the provided main.c as an example application and as a starting point.
+
+Q: How do I adapt it to an ATmegaXYZ and my circuit in particular?
+A: Add your MCU-specific pin configuration to sd_raw_config.h. Some commonly used ones are already
+   included.
+
+Q: How do I adapt it to a different MCU clock?
+A: Change the MCU_FREQ variable within the Makefile.
+
+Q: How do I adapt it to some different MCU architecture?
+A: Change sd_raw_init(), sd_raw_send_byte(), sd_raw_rec_byte() within sd_raw.c and the pin
+   definitions within sd_raw_config.h appropriately.
+
+Q: Can the library be used with Arduino?
+A: Yes. I do not have any experience with Arduino myself, but people report that it works with some
+   minor modifications to the library code needed due to some different compiler settings. Please
+   search the web for details.
+
+Q: Can I use software SPI?
+A: Yes, but the code is not prepared for it.
+
+Q: My application crashes somewhere in the lib. Is there some bug hidden?
+A: There might be a bug. Much more likely, however, is that you experience memory problems,
+   especially heap/stack collisions. The crashes can appear everywhere, but typically this is not
+   the place where the real problem is. Try to minimize the size of structures and other memory
+   blocks your application uses. Sum up the amount of memory your application allocates with global
+   and local variables and the memory you allocate dynamically with malloc(). The avr-nm utility
+   also helps a lot here. When called with the "--print-size --size-sort" parameters, it lists all
+   symbols and their code/memory size within the given file. See the avr-libc FAQ and the nm manual
+   for further information.
+   http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_ramoverlap
+   http://sourceware.org/binutils/docs/binutils/nm.html
+
+Q: Opening the FAT filesystem fails. What can I do?
+A: Make sure there is a FAT16 or FAT32 filesystem on the card. This usually isn't possible for old
+   cards with 16 MB or less. For larger ones, format the cards using the OS utilities, like the
+   Windows Explorer, the Unix/Linux mkdosfs command or special SD card format tools.
+   http://panasonic.jp/support/global/cs/sd/download/sd_formatter.html
+   http://www.sdcard.org/consumers/formatter/
+
+Q: Writing to the card returns no failure, but when checking the file's content the data is not
+   there. What happens?
+A: For performance reasons, writing to the card is always buffered. Before pulling the card out of
+   its socket (or issuing a reset of the MCU), make sure sd_raw_sync() gets called such that all
+   buffered data is written out to permanent card storage.
+
Index: byteordering.c
===================================================================
--- byteordering.c	(.../sd-reader_release_20101010)	(Revision 172)
+++ byteordering.c	(.../sd-reader_release_20110205)	(Revision 172)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2006-2010 by Roland Riegel <feedback@roland-riegel.de>
+ * Copyright (c) 2006-2011 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
@@ -24,36 +24,88 @@
  * \author Roland Riegel
  */
 
-#if DOXYGEN || !(LITTLE_ENDIAN || __AVR__)
+#if DOXYGEN || SWAP_NEEDED
+
 /**
- * Converts a 16-bit integer to little-endian byte order.
+ * \internal
+ * Swaps the bytes of a 16-bit integer.
  *
- * Use this function on variable values instead of the
- * macro HTOL16(). This saves code size.
+ * \param[in] i A 16-bit integer which to swap.
+ * \returns The swapped 16-bit integer.
+ */
+uint16_t swap16(uint16_t i)
+{
+    return SWAP16(i);
+}
+
+/**
+ * \internal
+ * Swaps the bytes of a 32-bit integer.
  *
- * \param[in] h A 16-bit integer in host byte order.
- * \returns The given 16-bit integer converted to little-endian byte order.
+ * \param[in] i A 32-bit integer which to swap.
+ * \returns The swapped 32-bit integer.
  */
-uint16_t htol16(uint16_t h)
+uint32_t swap32(uint32_t i)
 {
-    return HTOL16(h);
+    return SWAP32(i);
 }
+
 #endif
 
-#if DOXYGEN || !(LITTLE_ENDIAN || __AVR__)
+#if DOXYGEN || !__AVR__
+
 /**
- * Converts a 32-bit integer to little-endian byte order.
+ * Reads a 16-bit integer from memory in little-endian byte order.
  *
- * Use this function on variable values instead of the
- * macro HTOL32(). This saves code size.
+ * \param[in] p Pointer from where to read the integer.
+ * \returns The 16-bit integer read from memory.
+ */
+uint16_t read16(const uint8_t* p)
+{
+    return (((uint16_t) p[1]) << 8) |
+           (((uint16_t) p[0]) << 0);
+}
+
+/**
+ * Reads a 32-bit integer from memory in little-endian byte order.
  *
- * \param[in] h A 32-bit integer in host byte order.
- * \returns The given 32-bit integer converted to little-endian byte order.
+ * \param[in] p Pointer from where to read the integer.
+ * \returns The 32-bit integer read from memory.
  */
-uint32_t htol32(uint32_t h)
+uint32_t read32(const uint8_t* p)
 {
-    return HTOL32(h);
+    return (((uint32_t) p[3]) << 24) |
+           (((uint32_t) p[2]) << 16) |
+           (((uint32_t) p[1]) <<  8) |
+           (((uint32_t) p[0]) <<  0);
 }
+
+/**
+ * Writes a 16-bit integer into memory in little-endian byte order.
+ *
+ * \param[in] p Pointer where to write the integer to.
+ * \param[in] i The 16-bit integer to write.
+ */
+void write16(uint8_t* p, uint16_t i)
+{
+    p[1] = (uint8_t) ((i & 0xff00) >> 8);
+    p[0] = (uint8_t) ((i & 0x00ff) >> 0);
+}
+
+/**
+ * Writes a 32-bit integer into memory in little-endian byte order.
+ *
+ * \param[in] p Pointer where to write the integer to.
+ * \param[in] i The 32-bit integer to write.
+ */
+void write32(uint8_t* p, uint32_t i)
+{
+    p[3] = (uint8_t) ((i & 0xff000000) >> 24);
+    p[2] = (uint8_t) ((i & 0x00ff0000) >> 16);
+    p[1] = (uint8_t) ((i & 0x0000ff00) >>  8);
+    p[0] = (uint8_t) ((i & 0x000000ff) >>  0);
+}
+
 #endif
 
 /**
