Index: cpukit/libfs/ChangeLog
===================================================================
--- cpukit/libfs/ChangeLog	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/ChangeLog	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -1,2 +1,14 @@
+2003-03-25	Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+	PR 367/filesystem
+	* src/dosfs/Makefile.am, src/dosfs/fat.c, src/dosfs/fat.h,
+	src/dosfs/fat_fat_operations.c, src/dosfs/fat_file.c,
+	src/dosfs/msdos.h, src/dosfs/msdos_dir.c: Some bugs were still
+	present in the DOSFS implementation:
+	    - FAT12 did not work properly on Big-Endian machines
+	    - Some synchronization and error handling problems were present
+	    - Some legal codings for EOC were not recognized
+
+
 2003-03-06	Ralf Corsepius <corsepiu@faw.uni-ulm.de>
 
Index: cpukit/libfs/src/dosfs/Makefile.am
===================================================================
--- cpukit/libfs/src/dosfs/Makefile.am	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/Makefile.am	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -28,4 +28,8 @@
     $(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
 
+PREINSTALL_FILES = $(PROJECT_INCLUDE) \
+    $(include_HEADERS:%=$(PROJECT_INCLUDE)/%)
+
+
 $(PROJECT_INCLUDE):
 	@$(mkinstalldirs) $@
Index: cpukit/libfs/src/dosfs/fat.c
===================================================================
--- cpukit/libfs/src/dosfs/fat.c	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/fat.c	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -261,4 +261,14 @@
 
     vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
+    /*
+     * "sectors per cluster" of zero is invalid
+     * (and would hang the following loop)
+     */
+    if (vol->spc == 0)
+    {
+        rtems_disk_release(vol->dd);
+        set_errno_and_return_minus_one(EINVAL);
+    }    
+
     for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0; 
          i >>= 1, vol->spc_log2++);
@@ -527,5 +537,5 @@
         set_errno_and_return_minus_one( EIO );
 
-    while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
+    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
     {
         ret = fat_cluster_write(mt_entry, cur_cln, buf);
Index: cpukit/libfs/src/dosfs/fat.h
===================================================================
--- cpukit/libfs/src/dosfs/fat.h	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/fat.h	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -84,7 +84,7 @@
 #define FAT_UNDEFINED_VALUE     (unsigned32)0xFFFFFFFF 
 
-#define FAT_FAT12_EOC          0x0FFF
-#define FAT_FAT16_EOC          0xFFFF
-#define FAT_FAT32_EOC          (unsigned32)0x0FFFFFFF
+#define FAT_FAT12_EOC          0x0FF8
+#define FAT_FAT16_EOC          0xFFF8
+#define FAT_FAT32_EOC          (unsigned32)0x0FFFFFF8
 
 #define FAT_FAT12_FREE         0x0000
@@ -307,4 +307,5 @@
             set_errno_and_return_minus_one(EIO);
         fs_info->c.blk_num = blk;    
+	fs_info->c.modified = 0;    
         fs_info->c.state = FAT_CACHE_ACTUAL;    
     }
@@ -322,7 +323,8 @@
             
             sc = rtems_bdbuf_release_modified(fs_info->c.buf);
+	    fs_info->c.state = FAT_CACHE_EMPTY;
+            fs_info->c.modified = 0;    
             if (sc != RTEMS_SUCCESSFUL)
                 set_errno_and_return_minus_one(EIO);
-            fs_info->c.modified = 0;    
             
             if (sec_of_fat && !fs_info->vol.mirror)
@@ -348,4 +350,5 @@
         {
             sc = rtems_bdbuf_release(fs_info->c.buf);
+	    fs_info->c.state = FAT_CACHE_EMPTY;
             if (sc != RTEMS_SUCCESSFUL)
                 set_errno_and_return_minus_one(EIO);
@@ -359,4 +362,5 @@
             set_errno_and_return_minus_one(EIO);
         fs_info->c.blk_num = blk;
+	fs_info->c.state = FAT_CACHE_ACTUAL;
     }
     *buf = fs_info->c.buf;
Index: cpukit/libfs/src/dosfs/fat_fat_operations.c
===================================================================
--- cpukit/libfs/src/dosfs/fat_fat_operations.c	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/fat_fat_operations.c	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -79,5 +79,6 @@
         }    
 
-        if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE) 
+        /*if ((next_cln & fs_info->vol.mask) == FAT_GENFAT_FREE)*/
+        if (next_cln == FAT_GENFAT_FREE)
         {
             /*
@@ -178,5 +179,5 @@
     unsigned32     freed_cls_cnt = 0;
     
-    while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
+    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
     {
         rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
@@ -277,5 +278,4 @@
             else
                 *ret_val = (*ret_val) & FAT_FAT12_MASK;
-
             break;
 
@@ -343,6 +343,14 @@
             if ( FAT_CLUSTER_IS_ODD(cln) )
             {
+#if 0
+	      /* 
+	       * do not perform endian conversion explicitely,
+	       * because following code will enforce little 
+	       * endian format implicitly!
+	       */		 
                 fat16_clv = CT_LE_W((((unsigned16)in_val) << FAT_FAT12_SHIFT));
-
+#else
+                fat16_clv = ((unsigned16)in_val) << FAT_FAT12_SHIFT;
+#endif
                 *((unsigned8 *)(block0->buffer + ofs)) = 
                         (*((unsigned8 *)(block0->buffer + ofs))) & 0x0F;
@@ -380,6 +388,14 @@
             else
             {
+#if 0
+	      /* 
+	       * do not perform endian conversion explicitely,
+	       * because following code will enforce little 
+	       * endian format implicitly!
+	       */		 
                 fat16_clv = CT_LE_W((((unsigned16)in_val) & FAT_FAT12_MASK));
-
+#else
+                fat16_clv = ((unsigned16)in_val) & FAT_FAT12_MASK;
+#endif
                 *((unsigned8 *)(block0->buffer + ofs)) &= 0x00;
 
Index: cpukit/libfs/src/dosfs/fat_file.c
===================================================================
--- cpukit/libfs/src/dosfs/fat_file.c	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/fat_file.c	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -771,5 +771,5 @@
         
     /* for each cluster of the file ... */
-    while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
+    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
     {
         sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
@@ -831,5 +831,5 @@
     fat_fd->fat_file_size = 0;
   
-    while ((cur_cln & fs_info->vol.mask) != fs_info->vol.eoc_val)
+    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
     {
         save_cln = cur_cln;
Index: cpukit/libfs/src/dosfs/msdos.h
===================================================================
--- cpukit/libfs/src/dosfs/msdos.h	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/msdos.h	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -139,5 +139,8 @@
 #define msdos_is_separator(_ch)          rtems_filesystem_is_separator(_ch)
 
-#define MSDOS_SHORT_NAME_LEN             11 /* 11 characters */
+#define MSDOS_SHORT_BASE_LEN             8  /* 8 characters */
+#define MSDOS_SHORT_EXT_LEN              3  /* 3 characters */
+#define MSDOS_SHORT_NAME_LEN             (MSDOS_SHORT_BASE_LEN+\
+                                          MSDOS_SHORT_EXT_LEN) /* 11 chars */
 #define MSDOS_NAME_MAX                   MSDOS_SHORT_NAME_LEN
 #define MSDOS_NAME_MAX_WITH_DOT          (MSDOS_NAME_MAX + 1)
Index: cpukit/libfs/src/dosfs/msdos_dir.c
===================================================================
--- cpukit/libfs/src/dosfs/msdos_dir.c	(revision ec6422eb96778c3a4339f674dc92bdc3edbc1a30)
+++ cpukit/libfs/src/dosfs/msdos_dir.c	(revision c151cfc347d29c7934db74aa4c7aeceaab0de83f)
@@ -103,4 +103,73 @@
     rtems_semaphore_release(fs_info->vol_sema);
     return RC_OK;
+}
+
+/*  msdos_format_dirent_with_dot --
+ *      This routine convert a (short) MSDOS filename as present on disk 
+ *      (fixed 8+3 characters, filled with blanks, without separator dot)
+ *      to a "normal" format, with between 0 and 8 name chars, 
+ *      a separating dot and up to 3 extension characters
+ *   Rules to work:
+ *      - copy any (0-8) "name" part characters that are non-blank
+ *      - if an extension exists, append a dot
+ *      - copy any (0-3) non-blank extension characters
+ *      - append a '\0' (dont count it for the rturn code
+ *
+ * PARAMETERS:
+ *     dst: pointer to destination char array (must be big enough)
+ *     src: pointer to source characters
+ *
+ *
+ * RETURNS:
+ *     the number of bytes (without trailing '\0'(written to destination 
+ */
+static ssize_t 
+msdos_format_dirent_with_dot(char *dst,const char *src)
+{
+  ssize_t len;
+  int i;
+  const char *src_tmp;
+
+  /*
+   * find last non-blank character of base name
+   */
+  for ((i       =       MSDOS_SHORT_BASE_LEN  ,
+	src_tmp = src + MSDOS_SHORT_BASE_LEN-1);
+       ((i > 0) &&
+	(*src_tmp == ' '));
+       i--,src_tmp--)
+    {};
+  /*
+   * copy base name to destination
+   */
+  src_tmp = src;
+  len = i;
+  while (i-- > 0) {
+    *dst++ = *src_tmp++;
+  }
+  /*
+   * find last non-blank character of extension
+   */
+  for ((i       =                            MSDOS_SHORT_EXT_LEN  ,
+	src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1);
+       ((i > 0) && 
+	(*src_tmp == ' '));
+       i--,src_tmp--)
+    {};
+  /*
+   * extension is not empty
+   */
+  if (i > 0) {
+    *dst++ = '.'; /* append dot */
+    len += i + 1; /* extension + dot */
+    src_tmp = src + MSDOS_SHORT_BASE_LEN;
+    while (i-- > 0) {
+      *dst++ = *src_tmp++;
+      len++;
+    }
+  }
+  *dst = '\0'; /* terminate string */
+
+  return len;
 }
 
@@ -237,10 +306,11 @@
             tmp_dirent.d_reclen = sizeof(struct dirent);
             tmp_dirent.d_ino = tmp_fat_fd->ino;
-            tmp_dirent.d_namlen = MSDOS_SHORT_NAME_LEN;
-            memcpy(tmp_dirent.d_name, MSDOS_DIR_NAME((fs_info->cl_buf + i)),
-                   MSDOS_SHORT_NAME_LEN);
-      
-            /* d_name is null-terminated */
-            tmp_dirent.d_name[MSDOS_SHORT_NAME_LEN] = 0;       
+	    /*
+	     * convert dir entry from fixed 8+3 format (without dot)
+	     * to 0..8 + 1dot + 0..3 format
+	     */
+	    tmp_dirent.d_namlen = 
+	      msdos_format_dirent_with_dot(tmp_dirent.d_name,
+					 fs_info->cl_buf + i); /* src text */
             memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
    
