Index: c/src/lib/libbsp/ChangeLog
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/ChangeLog,v
retrieving revision 1.63
diff -p -u -u -r1.63 ChangeLog
--- c/src/lib/libbsp/ChangeLog	11 Dec 2008 10:27:20 -0000	1.63
+++ c/src/lib/libbsp/ChangeLog	23 Apr 2009 07:54:36 -0000
@@ -1,3 +1,8 @@
+2009-04-23	Chris Johns <chrisj@rtems.org>
+
+	* Makefile.am: Add bspinit.c, a common Init task that manages
+	command line arguments from a BSP.
+
 2008-12-11	Ralf Corsépius <ralf.corsepius@rtems.org>
 
 	* shared/clockdrv_shell.c: Turn warning into error.
Index: c/src/lib/libbsp/Makefile.am
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/Makefile.am,v
retrieving revision 1.25
diff -p -u -u -r1.25 Makefile.am
--- c/src/lib/libbsp/Makefile.am	26 Sep 2008 05:40:00 -0000	1.25
+++ c/src/lib/libbsp/Makefile.am	23 Apr 2009 07:54:36 -0000
@@ -10,10 +10,10 @@ DIST_SUBDIRS = @libbsp_cpu_subdir@
 EXTRA_DIST = MERGE.PROCEDURE bsp.am
 
 # shared
-EXTRA_DIST += shared/bootcard.c shared/bspclean.c shared/bsplibc.c \
-    shared/bsppost.c shared/console-polled.c shared/console.c \
-    shared/gnatinstallhandler.c shared/sbrk.c shared/tod.c \
-    shared/tod.h
+EXTRA_DIST += shared/bootcard.c shared/bspclean.c shared/bspinit.c \
+    shared/bsplibc.c shared/bsppost.c shared/console-polled.c \
+    shared/console.c shared/gnatinstallhandler.c shared/sbrk.c \
+    shared/tod.c shared/tod.h
 EXTRA_DIST += shared/vmeUniverse/vmeUniverse.c \
     shared/vmeUniverse/vmeUniverse.h \
     shared/vmeUniverse/vmeUniverseDMA.h \
Index: c/src/lib/libbsp/i386/pc386/Makefile.am
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/Makefile.am,v
retrieving revision 1.50
diff -p -u -u -r1.50 Makefile.am
--- c/src/lib/libbsp/i386/pc386/Makefile.am	2 Oct 2008 13:50:44 -0000	1.50
+++ c/src/lib/libbsp/i386/pc386/Makefile.am	23 Apr 2009 07:54:37 -0000
@@ -89,10 +89,10 @@ include_HEADERS += ../../i386/shared/com
 # startup
 libbsp_a_SOURCES += ../../shared/bsplibc.c ../../shared/bsppost.c \
     ../../shared/bsppredriverhook.c startup/bspgetworkarea.c \
-    ../../shared/bsppretaskinghook.c startup/bspstart.c \
+    ../../shared/bsppretaskinghook.c startup/bspstart.c startup/bspcmdline.c \
     ../../shared/bspclean.c startup/bspreset.c ../../i386/shared/irq/idt.c \
     ../../i386/shared/irq/irq.c ../../i386/shared/irq/irq_init.c \
-    ../../shared/bootcard.c ../../shared/sbrk.c \
+    ../../shared/bootcard.c ../../shared/bspinit.c ../../shared/sbrk.c \
     startup/ldsegs.S ../../i386/shared/irq/irq_asm.S
 
 # timer
Index: c/src/lib/libbsp/i386/pc386/console/console.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/console/console.c,v
retrieving revision 1.40
diff -p -u -u -r1.40 console.c
--- c/src/lib/libbsp/i386/pc386/console/console.c	3 Nov 2008 20:57:38 -0000	1.40
+++ c/src/lib/libbsp/i386/pc386/console/console.c	23 Apr 2009 07:54:37 -0000
@@ -149,7 +149,34 @@ console_initialize(rtems_device_major_nu
                    void                      *arg)
 {
   rtems_status_code status;
+  const char* mode;
+  
+  /*
+   * Check the command line for the type of mode
+   * the consol is.
+   */
+  mode = bsp_cmdline_arg ("--console=");
 
+  if (mode)
+  {
+    mode += sizeof ("--console=") - 1;
+    if (strncmp (mode, "console", sizeof ("console") - 1) == 0)
+    {
+      BSPConsolePort = BSP_CONSOLE_PORT_CONSOLE;
+      BSPPrintkPort  = BSP_CONSOLE_PORT_CONSOLE;
+    }
+    else if (strncmp (mode, "com1", sizeof ("com1") - 1) == 0)
+    {
+      BSPConsolePort = BSP_UART_COM1;
+      BSPPrintkPort  = BSP_UART_COM1;
+    }
+    else if (strncmp (mode, "com2", sizeof ("com2") - 1) == 0)
+    {
+      BSPConsolePort = BSP_UART_COM2;
+      BSPPrintkPort  = BSP_UART_COM2;
+    }
+  }
+  
   /* Initialize the KBD interface */
   kbd_init();
 
Index: c/src/lib/libbsp/i386/pc386/ide/ide.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/ide/ide.c,v
retrieving revision 1.10
diff -p -u -u -r1.10 ide.c
--- c/src/lib/libbsp/i386/pc386/ide/ide.c	6 Sep 2008 17:04:47 -0000	1.10
+++ c/src/lib/libbsp/i386/pc386/ide/ide.c	23 Apr 2009 07:54:37 -0000
@@ -3,6 +3,9 @@
 +-----------------------------------------------------------------+
 | File: ide.c                                                     |
 +-----------------------------------------------------------------+
+|                                                                 |
+|       Copyright those who have fixed bugs and made changes.     |
+|                                                                 |
 |                    Copyright (c) 2003 IMD                       |
 |      Ingenieurbuero fuer Microcomputertechnik Th. Doerfler      |
 |               <Thomas.Doerfler@imd-systems.de>                  |
@@ -30,6 +33,51 @@
 #include <libchip/ide_ctrl_io.h>
 
 /* #define DEBUG_OUT */
+
+static bool pc386_ide_status_busy (uint32_t port,
+                                   uint32_t timeout,
+                                   uint8_t* status_val)
+{
+  do
+  {
+    inport_byte (port + IDE_REGISTER_STATUS, *status_val);
+    if ((*status_val & IDE_REGISTER_STATUS_BSY) == 0)
+      return true;
+
+    if (timeout)
+    {
+      timeout--;
+      rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
+    }
+  }
+  while (timeout);
+
+  return false;
+}
+
+static bool pc386_ide_status_data_ready (uint32_t port,
+                                         uint32_t timeout,
+                                         uint8_t* status_val)
+{
+  do
+  {
+    inport_byte (port + IDE_REGISTER_STATUS, *status_val);
+    
+    if (((*status_val & IDE_REGISTER_STATUS_BSY) == 0) &&
+        (*status_val & IDE_REGISTER_STATUS_DRQ))
+      return true;
+
+    if (timeout)
+    {
+      timeout--;
+      rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
+    }
+  }
+  while (timeout);
+
+  return false;
+}
+
 /*
  * support functions for IDE harddisk IF
  */
@@ -174,18 +222,28 @@ void pc386_ide_read_block
   uint32_t    port = IDE_Controller_Table[minor].port1;
   uint16_t    cnt = 0;
   uint32_t    llength = bufs[(*cbuf)].length;
-  uint8_t   status_val;
+  uint8_t     status_val;
   uint16_t   *lbuf = (uint16_t*)
     ((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
 
-  inport_byte(port+IDE_REGISTER_STATUS,status_val);
-  while ((status_val & IDE_REGISTER_STATUS_DRQ) &&
-	 (cnt < block_size)) {
+  while (cnt < block_size)
+  {
+    if (!pc386_ide_status_data_ready (port, 100, &status_val))
+    {
+      printk ("pc386_ide_read_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
+      /* FIXME: add an error here. */
+      return;
+    }
+    
+    if (status_val & IDE_REGISTER_STATUS_ERR)
+      printk("pc386_ide_read_block: error: %02x\n", status_val);
+    
     inport_word(port+IDE_REGISTER_DATA,*lbuf);
 
 #ifdef DEBUG_OUT
     printk("0x%x ",*lbuf);
 #endif
+
     lbuf++;
     cnt    += sizeof(*lbuf);
     (*pos) += sizeof(*lbuf);
@@ -195,11 +253,7 @@ void pc386_ide_read_block
       lbuf = bufs[(*cbuf)].buffer;
       llength = bufs[(*cbuf)].length;
     }
-    inport_byte(port+IDE_REGISTER_STATUS,status_val);
   }
-#ifdef DEBUG_OUT
-  printk("pc386_ide_read_block()\r\n");
-#endif
 }
 
 /*=========================================================================*\
@@ -230,13 +284,23 @@ void pc386_ide_write_block
   uint8_t     status_val;
   uint16_t   *lbuf = (uint16_t*)
     ((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
-
+  
 #ifdef DEBUG_OUT
-  printk("pc386_ide_write_block()\r\n");
+  printk("pc386_ide_write_block()\n");
 #endif
-  inport_byte(port+IDE_REGISTER_STATUS,status_val);
-  while ((status_val & IDE_REGISTER_STATUS_DRQ) &&
-	 (cnt < block_size)) {
+
+  while (cnt < block_size)
+  {
+    if (!pc386_ide_status_data_ready (port, 100, &status_val))
+    {
+      printk ("pc386_ide_write_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
+      /* FIXME: add an error here. */
+      return;
+    }
+    
+    if (status_val & IDE_REGISTER_STATUS_ERR)
+      printk("pc386_ide_write_block: error: %02x\n", status_val);
+    
 #ifdef DEBUG_OUT
     printk("0x%x ",*lbuf);
 #endif
@@ -250,7 +314,6 @@ void pc386_ide_write_block
       lbuf = bufs[(*cbuf)].buffer;
       llength = bufs[(*cbuf)].length;
     }
-    inport_byte(port+IDE_REGISTER_STATUS,status_val);
   }
 }
 
Index: c/src/lib/libbsp/i386/pc386/ide/idecfg.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/ide/idecfg.c,v
retrieving revision 1.6
diff -p -u -u -r1.6 idecfg.c
--- c/src/lib/libbsp/i386/pc386/ide/idecfg.c	29 Sep 2005 08:05:32 -0000	1.6
+++ c/src/lib/libbsp/i386/pc386/ide/idecfg.c	23 Apr 2009 07:54:37 -0000
@@ -35,7 +35,6 @@ extern ide_ctrl_fns_t pc386_ide_ctrl_fns
 
 /* IDE controllers Table */
 ide_controller_bsp_table_t IDE_Controller_Table[] = {
-#if IDE_USE_PRIMARY_INTERFACE
   {"/dev/ide0",
    IDE_STD, /* standard IDE controller */
    &pc386_ide_ctrl_fns,
@@ -45,11 +44,7 @@ ide_controller_bsp_table_t IDE_Controlle
    FALSE,0, /* not (yet) interrupt driven */
    NULL
   }
-#if IDE_USE_SECONDARY_INTERFACE
   , /* colon only needed when both interfaces present */
-#endif
-#endif
-#if IDE_USE_SECONDARY_INTERFACE
   {"/dev/ide1",
    IDE_STD, /* standard IDE controller */
    &pc386_ide_ctrl_fns,
@@ -59,9 +54,74 @@ ide_controller_bsp_table_t IDE_Controlle
    FALSE,0, /* not (yet) interrupt driven */
    NULL
   }
-#endif
 };
 
-/* Number of rows in IDE_Controller_Table */
-unsigned long IDE_Controller_Count =
-   sizeof(IDE_Controller_Table)/sizeof(IDE_Controller_Table[0]);
+/* Number of rows in IDE_Controller_Table. Default is 0. */
+unsigned long IDE_Controller_Count;
+
+#if IDE_USE_PRIMARY_INTERFACE
+#define IDE1_DEFAULT true
+#else
+#define IDE1_DEFAULT false
+#endif
+#if IDE_USE_SECONDARY_INTERFACE
+#define IDE2_DEFAULT true
+#else
+#define IDE2_DEFAULT false
+#endif
+
+void bsp_ide_cmdline_init(void)
+{
+  bool ide1 = IDE1_DEFAULT;
+  bool ide2 = IDE2_DEFAULT;
+  const char* ide;
+  
+  /*
+   * Can have:
+   *  --ide=1,2
+   */
+  ide = bsp_cmdline_arg ("--ide=");
+  
+  if (ide)
+  {
+    int i;
+    /*
+     * If a command line option exists remove the defaults.
+     */
+    ide1 = ide2 = false;
+    
+    ide += sizeof ("--ide=") - 1;
+    
+    for (i = 0; i < 3; i++)
+    {
+      switch (ide[i])
+      {
+        case '1':
+          ide1 = true;
+          break;
+        case '2':
+          ide2 = true;
+          break;
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+        case ',':
+          break;
+        default:
+        break;
+      }
+    }
+  }
+
+  if (ide2 && !ide1)
+    IDE_Controller_Table[0] = IDE_Controller_Table[1];
+
+  if (ide1)
+    IDE_Controller_Count++;
+  if (ide2)
+    IDE_Controller_Count++;
+}
Index: c/src/lib/libbsp/i386/pc386/include/bsp.h
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/include/bsp.h,v
retrieving revision 1.40
diff -p -u -u -r1.40 bsp.h
--- c/src/lib/libbsp/i386/pc386/include/bsp.h	22 Sep 2008 21:49:43 -0000	1.40
+++ c/src/lib/libbsp/i386/pc386/include/bsp.h	23 Apr 2009 07:54:37 -0000
@@ -183,6 +183,17 @@ void Wait_X_ms(unsigned int timeToWait);
 #define BSP_CONSOLE_PORT_COM2    (BSP_UART_COM2)
 
 /*
+ * Command line.
+ */
+const char* bsp_cmdline(void);
+const char* bsp_cmdline_arg(const char* arg);
+
+/*
+ * IDE command line parsing.
+ */
+void bsp_ide_cmdline_init(void);
+
+/*
  * indicate, that BSP has IDE driver
  */
 #define RTEMS_BSP_HAS_IDE_DRIVER
Index: c/src/lib/libbsp/i386/pc386/start/start.S
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/start/start.S,v
retrieving revision 1.11
diff -p -u -u -r1.11 start.S
--- c/src/lib/libbsp/i386/pc386/start/start.S	22 Mar 2008 14:01:49 -0000	1.11
+++ c/src/lib/libbsp/i386/pc386/start/start.S	23 Apr 2009 07:54:38 -0000
@@ -88,21 +88,42 @@ speakl:	jmp	speakl             # and SPI
         cli			# DISABLE INTERRUPTS!!!
 	cld
 
-		/* Save multiboot info */
-		cmp 	$0x2badb002,eax
-		jne		1f
-		/* We have multiboot info; let's hope DS and ES are OK... */
-		movl	ebx, SYM(_boot_multiboot_info_p)
-		/* Check for memory size info and save */
-		movl	ebx, esi
-		movl	$SYM(_boot_multiboot_info), edi
-		movsd
-		/* only save flag 1 since that's the only data we save */
-		and		$1,-4(edi)
-		je		1f
-		movl	$2,ecx
-		rep movsd
-1:
+	/* Save multiboot info if we detect a multiboot loader */
+	cmp 	$0x2badb002,eax
+	jne	2f
+	
+	/* We have multiboot info; let's hope DS and ES are OK... */
+	movl	ebx, SYM(_boot_multiboot_info_p)
+	/* Check for memory size info and save */
+	movl	ebx, esi
+	movl	(esi), eax
+	movl	eax, ebx
+	movl	$SYM(_boot_multiboot_info), edi
+ 	/* save flags, always present */
+	movsd
+	/* flag 1 is memory */
+	and	$1, eax
+	je	1f
+	movl	$2, ecx
+	rep movsd
+	/* flag 2 is the command line */
+1:	movl	ebx, eax
+	and	$4, eax
+	je	3f
+	movl    (_boot_multiboot_info_p), eax
+	movl    16(eax), esi
+	movl	$255, ecx
+2:	movzbl	(esi), eax
+	test	al, al
+	je	3f
+	movb	al, (edi)
+	inc	edi
+	inc	esi
+	dec	ecx
+	je	3f
+	jmp	2b
+3:	xor	al, al
+	movb	al, (edi)
 #ifdef DEBUG_EARLY_START
 	/*
 	 * Must get video attribute to have a working printk.
@@ -178,11 +199,10 @@ SYM (zero_bss):
 | Transfer control to User's Board Support Package
 +---------------------------------------------------------------------*/
 
-	pushl	$0			# environp
-	pushl	$0			# argv
-        pushl	$0			# argc
+	movl	$SYM(_boot_multiboot_cmdline), eax
+	pushl	eax			# cmdline
 	call	SYM (boot_card)
-	addl	$12, esp
+	addl	$4, esp
 
 /*---------------------------------------------------------------------+
 | Clean up - we do not know anything about it, so we will
@@ -199,11 +219,20 @@ SYM(_boot_multiboot_info_p):
 	.long 0
 
 	PUBLIC(_boot_multiboot_info)
+	PUBLIC(_boot_multiboot_flags)
+	PUBLIC(_boot_multiboot_memory)
+	PUBLIC(_boot_multiboot_cmdline)
 SYM(_boot_multiboot_info):
+SYM(_boot_multiboot_flags):
 	.long 0	/* flags */
+SYM(_boot_multiboot_memory):
 	.long 0 /* mem_lower */
 	.long 0 /* mem_upper */
-
+SYM(_boot_multiboot_cmdline):
+	.rept 256 /* cmd line */
+	.byte 0
+	.endr
+	
 	PUBLIC(_stack_size)
 SYM(_stack_size):
 	.long STACK_SIZE
Index: c/src/lib/libbsp/i386/pc386/startup/bspcmdline.c
===================================================================
RCS file: c/src/lib/libbsp/i386/pc386/startup/bspcmdline.c
diff -N c/src/lib/libbsp/i386/pc386/startup/bspcmdline.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ c/src/lib/libbsp/i386/pc386/startup/bspcmdline.c	23 Apr 2009 07:54:38 -0000
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------+
+| This file contains the PC386 BSP startup package. It includes application,
+| board, and monitor specific initialization and configuration. The generic CPU
+| dependent initialization has been performed before this routine is invoked.
++--------------------------------------------------------------------------+
+| (C) Copyright 2009 RTEMS Project
+|     Chris Johns (chrisj@rtems.org)
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on:
+|   common sense
+| With the following copyright notice:
+| **************************************************************************
+| *  COPYRIGHT (c) 1989-2008.
+| *  On-Line Applications Research Corporation (OAR).
+| *
+| *  The license and distribution terms for this file may be
+| *  found in found in the file LICENSE in this distribution or at
+| *  http://www.rtems.com/license/LICENSE.
+| **************************************************************************
+|
+|  $Id: bspstart.c,v 1.47 2008/09/18 20:41:09 joel Exp $
++--------------------------------------------------------------------------*/
+
+#include <bsp.h>
+#include <rtems/pci.h>
+#include <libcpu/cpuModel.h>
+
+/*
+ *  External data
+ */
+extern uint32_t _boot_multiboot_flags;
+extern uint32_t _boot_multiboot_memory[2];
+extern const char _boot_multiboot_cmdline[256];
+
+/*-------------------------------------------------------------------------+
+|         Function: bsp_cmdline
+|      Description: Call when you want the command line.
+| Global Variables: The multiboot values copied from the loader.
+|        Arguments: None.
+|          Returns: The whole command line.
++--------------------------------------------------------------------------*/
+const char* bsp_cmdline( void )
+{
+  return _boot_multiboot_cmdline;
+}
+
+/*-------------------------------------------------------------------------+
+|         Function: bsp_cmdline_arg
+|      Description: Call to search for an argument.
+| Global Variables: The multiboot values copied from the loader.
+|        Arguments: The option start.
+|          Returns: The option if found or nothing.
++--------------------------------------------------------------------------*/
+const char* bsp_cmdline_arg( const char* arg )
+{
+  return strstr (bsp_cmdline (), arg);
+}
Index: c/src/lib/libbsp/i386/pc386/startup/bspstart.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c,v
retrieving revision 1.47
diff -p -u -u -r1.47 bspstart.c
--- c/src/lib/libbsp/i386/pc386/startup/bspstart.c	18 Sep 2008 20:41:09 -0000	1.47
+++ c/src/lib/libbsp/i386/pc386/startup/bspstart.c	23 Apr 2009 07:54:38 -0000
@@ -78,6 +78,9 @@ void bsp_start_default( void )
   if (pci_init_retval != PCIB_ERR_SUCCESS) {
       printk("PCI bus: could not initialize PCI BIOS interface\n");
   }
+
+  bsp_ide_cmdline_init ();
+
 } /* bsp_start */
 
 /*
Index: c/src/lib/libbsp/shared/ChangeLog
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/shared/ChangeLog,v
retrieving revision 1.136
diff -p -u -u -r1.136 ChangeLog
--- c/src/lib/libbsp/shared/ChangeLog	10 Mar 2009 17:40:06 -0000	1.136
+++ c/src/lib/libbsp/shared/ChangeLog	23 Apr 2009 07:54:38 -0000
@@ -1,3 +1,9 @@
+2009-04-23	Chris Johns <chrisj@rtems.org>
+
+	* bootcard.c, include/bootcard.h: Remove argc/argv/envp and
+	replace with a single BSP boot command line a BSP can optionally
+	support.
+
 2009-03-10	Eric Norum <norume@aps.anl.gov>
 
 	* bootcard.c: Swap order of RTEMS Workspace and Malloc Heap. This
Index: c/src/lib/libbsp/shared/bootcard.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/shared/bootcard.c,v
retrieving revision 1.42
diff -p -u -u -r1.42 bootcard.c
--- c/src/lib/libbsp/shared/bootcard.c	10 Mar 2009 17:40:06 -0000	1.42
+++ c/src/lib/libbsp/shared/bootcard.c	23 Apr 2009 07:54:38 -0000
@@ -48,9 +48,10 @@
 #include <bsp/bootcard.h>
 
 /*
- *  Since there is a forward reference
+ *  At most a single pointer to the cmdline for those target
+ *  short on memory and not supporting a command line.
  */
-char *rtems_progname;
+const char *bsp_boot_cmdline;
 
 /*
  * Are we using a single heap for the RTEMS Workspace and C Program Heap?
@@ -114,21 +115,15 @@ static rtems_status_code bootcard_bsp_li
  *  as much as possible.
  */
 int boot_card(
-  int    argc, 
-  char **argv, 
-  char **envp
+  const char *cmdline
 )
 {
-  static char            *argv_pointer = NULL;
-  static char            *envp_pointer = NULL;
-  char                  **argv_p = &argv_pointer;
-  char                  **envp_p = &envp_pointer;
-  rtems_interrupt_level   bsp_isr_level;
-  rtems_status_code       sc = RTEMS_SUCCESSFUL;
-  void                   *work_area_start = NULL;
-  intptr_t                work_area_size = 0;
-  void                   *heap_start = NULL;
-  intptr_t                heap_size = 0;
+  rtems_interrupt_level  bsp_isr_level;
+  rtems_status_code      sc = RTEMS_SUCCESSFUL;
+  void                  *work_area_start = NULL;
+  intptr_t               work_area_size = 0;
+  void                  *heap_start = NULL;
+  intptr_t               heap_size = 0;
 
   /*
    * Special case for PowerPC: The interrupt disable mask is stored in SPRG0.
@@ -143,22 +138,7 @@ int boot_card(
    */
   rtems_interrupt_disable( bsp_isr_level );
 
-  /*
-   *  Set things up so we have real pointers for argv and envp.
-   *  If the BSP has passed us something useful, then pass it on.
-   *  Somehow we need to eventually make this available to
-   *  a real main() in user land. :)
-   */
-  if ( argv ) argv_p = argv;
-  if ( envp ) envp_p = envp;
-
-  /*
-   *  Set the program name in case some application cares.
-   */
-  if ((argc > 0) && argv && argv[0])
-    rtems_progname = argv[0];
-  else
-    rtems_progname = "RTEMS";
+  bsp_boot_cmdline = cmdline;
 
   /*
    * Invoke Board Support Package initialization routine written in C.
@@ -169,7 +149,8 @@ int boot_card(
    *  Find out where the block of memory the BSP will use for
    *  the RTEMS Workspace and the C Program Heap is.
    */
-  bsp_get_work_area(&work_area_start, &work_area_size, &heap_start, &heap_size);
+  bsp_get_work_area(&work_area_start, (ssize_t*) &work_area_size,
+                    &heap_start, (ssize_t*) &heap_size);
 
   if ( work_area_size <= Configuration.work_space_size ) {
     printk( "bootcard: Work space too big for work area!\n");
Index: c/src/lib/libbsp/shared/bspinit.c
===================================================================
RCS file: c/src/lib/libbsp/shared/bspinit.c
diff -N c/src/lib/libbsp/shared/bspinit.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ c/src/lib/libbsp/shared/bspinit.c	23 Apr 2009 07:54:38 -0000
@@ -0,0 +1,93 @@
+/*
+ *  COPYRIGHT (c) 1989-2009.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.com/license/LICENSE.
+ *
+ *  $Id: bspstart.c,v 1.1 2008/09/16 19:10:15 joel Exp $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <bsp.h>
+#include <bsp/bootcard.h>
+
+/*
+ * This routine calls main from a confdefs.h default Init task
+ * set up. The bootcard will provide the task argument as
+ * command line string (ASCIIZ).
+ */
+
+int main (int argc, char* argv[]);
+
+void Init (rtems_task_argument arg)
+{
+  const char* boot_cmdline = *((const char**) arg);
+  char*       cmdline = 0;
+  char*       command;
+  int         argc = 0;
+  char**      argv = NULL;
+  int         result = -124;
+
+  if (boot_cmdline)
+  {
+    cmdline = malloc (strlen (boot_cmdline) + 1);
+  
+    if (cmdline)
+    {
+      strcpy (cmdline, boot_cmdline);
+
+      command = cmdline;
+
+      /*
+       * Break the line up into arguments with "" being ignored.
+       */
+      while (true)
+      {
+        command = strtok (command, " \t\r\n");
+        if (command == NULL)
+          break;
+        argc++;
+        command = '\0';
+      }
+
+      argv = calloc (argc, sizeof (char*));
+
+      if (argv)
+      {
+        int a;
+        
+        command = cmdline;
+        argv[0] = command;
+
+        for (a = 1; a < argc; a++)
+        {
+          command += strlen (command) + 1;
+          argv[a] = command;
+        }
+      }
+      else
+        argc = 0;
+    }
+  }
+  
+#ifdef RTEMS_NETWORKING
+  rtems_bsdnet_initialize_network ();
+#endif
+
+  result = main (argc, argv);
+ 
+  free (argv);
+  free (cmdline);
+
+  exit (result);
+}
+
+/*
+ * By making this a weak alias and a user can provide there own.
+ */
+
+void Init (rtems_task_argument arg) __attribute__ ((weak));
Index: c/src/lib/libbsp/shared/include/bootcard.h
===================================================================
RCS file: /usr1/CVS/rtems/c/src/lib/libbsp/shared/include/bootcard.h,v
retrieving revision 1.5
diff -p -u -u -r1.5 bootcard.h
--- c/src/lib/libbsp/shared/include/bootcard.h	2 Oct 2008 19:13:05 -0000	1.5
+++ c/src/lib/libbsp/shared/include/bootcard.h	23 Apr 2009 07:54:38 -0000
@@ -60,7 +60,7 @@ void bsp_get_work_area(
   ssize_t  *heap_size
 );
 
-int boot_card( int argc, char **argv, char **envp);
+int boot_card( const char *cmdline );
 
 void bsp_libc_init( void *heap_start, size_t heap_size, size_t sbrk_amount);
 
Index: c/src/libchip/ide/ata.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/libchip/ide/ata.c,v
retrieving revision 1.22
diff -p -u -u -r1.22 ata.c
--- c/src/libchip/ide/ata.c	7 Sep 2008 03:35:29 -0000	1.22
+++ c/src/libchip/ide/ata.c	23 Apr 2009 07:54:39 -0000
@@ -608,6 +608,10 @@ ata_non_data_request_done(ata_req_t *are
                           rtems_device_minor_number ctrl_minor,
                           rtems_status_code status, int error)
 {
+#ifdef DEBUG
+    printf("ata_non_data_request_done: entry\n");
+#endif
+    
     areq->status = status;
     areq->error = error;
     rtems_semaphore_release(areq->sema);
@@ -638,7 +642,7 @@ ata_add_to_controller_queue(rtems_device
 
         ata_queue_msg_t msg;
 
-#ifdef DEBUG
+#ifdef DEBUG_DOES_NOT_WORK_WITH_QEMU
 	uint16_t      val;
         /*
          * read IDE_REGISTER_ALTERNATE_STATUS instead IDE_REGISTER_STATUS
@@ -1289,7 +1293,7 @@ rtems_ata_initialize(rtems_device_major_
                                           IDE_REGISTER_DEVICE_CONTROL_OFFSET,
                                           IDE_REGISTER_DEVICE_CONTROL_nIEN);
         }
-
+#if 0
         /*
          * Issue EXECUTE DEVICE DIAGNOSTIC ATA command for explore is
          * there any ATA device on the controller.
@@ -1315,7 +1319,8 @@ rtems_ata_initialize(rtems_device_major_
          */
         if (breq.req.status != RTEMS_SUCCESSFUL)
             continue;
-
+#endif
+        breq.req.error = ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT;
         /* disassemble returned diagnostic codes */
         if (breq.req.error == ATA_DEV0_PASSED_DEV1_PASSED_OR_NOT_PRSNT)
         {
Index: c/src/libchip/ide/ide_controller.c
===================================================================
RCS file: /usr1/CVS/rtems/c/src/libchip/ide/ide_controller.c,v
retrieving revision 1.9
diff -p -u -u -r1.9 ide_controller.c
--- c/src/libchip/ide/ide_controller.c	29 Jul 2008 02:23:48 -0000	1.9
+++ c/src/libchip/ide/ide_controller.c	23 Apr 2009 07:54:39 -0000
@@ -25,7 +25,7 @@
 #include <libchip/ide_ctrl_io.h>
 
 #if IDE_CONTROLLER_TRACE
-int ide_controller_trace;
+int ide_controller_trace = 1;
 #endif
 
 /*
Index: cpukit/ChangeLog
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/ChangeLog,v
retrieving revision 1.1772
diff -p -u -u -r1.1772 ChangeLog
--- cpukit/ChangeLog	15 Apr 2009 08:36:12 -0000	1.1772
+++ cpukit/ChangeLog	23 Apr 2009 07:54:39 -0000
@@ -1,3 +1,9 @@
+2009-04-23	Chris Johns <chrisj@rtems.org>
+
+	* sapi/include/confdefs.h: Add a prototype for Init with C linkage
+	and define Init task command line arguments if confdefs.h provides
+	an Init entry point.
+
 2009-04-15	Ralf Corsepius <ralf.corsepius@rtems.org>
 
 	* configure.ac: Disable LIBSHELL for unix targets.
Index: cpukit/libblock/include/rtems/ide_part_table.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libblock/include/rtems/ide_part_table.h,v
retrieving revision 1.11
diff -p -u -u -r1.11 ide_part_table.h
--- cpukit/libblock/include/rtems/ide_part_table.h	29 Jul 2008 02:21:14 -0000	1.11
+++ cpukit/libblock/include/rtems/ide_part_table.h	23 Apr 2009 07:54:39 -0000
@@ -51,6 +51,7 @@
 #define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA2         0xaa
 #define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET        0x1fe
 #define RTEMS_IDE_PARTITION_TABLE_OFFSET                  0x1be
+#define RTEMS_IDE_PARTITION_TABLE_SIZE                    (4 * 16)
 #define RTEMS_IDE_PARTITION_BOOTABLE_OFFSET               0
 #define RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET               4
 #define RTEMS_IDE_PARTITION_START_OFFSET                  8
Index: cpukit/libblock/src/bdbuf.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libblock/src/bdbuf.c,v
retrieving revision 1.28
diff -p -u -u -r1.28 bdbuf.c
--- cpukit/libblock/src/bdbuf.c	16 Dec 2008 20:53:33 -0000	1.28
+++ cpukit/libblock/src/bdbuf.c	23 Apr 2009 07:54:39 -0000
@@ -1639,9 +1639,17 @@ rtems_bdbuf_read (dev_t                d
      * enabled and the pool unlocked. This is a change to the previous version
      * of the bdbuf code.
      */
-    int      result;
-    uint32_t b;
-    
+    rtems_event_set out;
+    int             result;
+    uint32_t        b;
+
+    /*
+     * Flush any events.
+     */
+    rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
+                         RTEMS_EVENT_ALL | RTEMS_NO_WAIT,
+                         0, &out);
+                         
     rtems_bdbuf_unlock_pool (pool);
 
     req->req = RTEMS_BLKDEV_REQ_READ;
@@ -1665,7 +1673,7 @@ rtems_bdbuf_read (dev_t                d
     else
     {
       rtems_status_code sc;
-      rtems_event_set   out;
+      
       sc = rtems_event_receive (RTEMS_BDBUF_TRANSFER_SYNC,
                                 RTEMS_EVENT_ALL | RTEMS_WAIT,
                                 0, &out);
Index: cpukit/libblock/src/ide_part_table.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libblock/src/ide_part_table.c,v
retrieving revision 1.13
diff -p -u -u -r1.13 ide_part_table.c
--- cpukit/libblock/src/ide_part_table.c	19 Dec 2008 14:59:35 -0000	1.13
+++ cpukit/libblock/src/ide_part_table.c	23 Apr 2009 07:54:39 -0000
@@ -57,7 +57,8 @@ get_sector(dev_t dev, uint32_t sector_nu
         return RTEMS_INTERNAL_ERROR;
     }
 
-    s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
+    s = (rtems_sector_data_t *) malloc(sizeof(rtems_sector_data_t) +
+                                       RTEMS_IDE_SECTOR_SIZE);
     if (s == NULL)
     {
         return RTEMS_NO_MEMORY;
@@ -131,16 +132,17 @@ static bool
 is_fat_partition(uint8_t type)
 {
   static const uint8_t fat_part_types[] = {
-    DOS_FAT12_PARTITION,DOS_FAT16_PARTITION,
+    DOS_FAT12_PARTITION,
+    DOS_FAT16_PARTITION,
     DOS_P32MB_PARTITION,
-    FAT32_PARTITION    ,FAT32_LBA_PARTITION,
+    FAT32_PARTITION,
+    FAT32_LBA_PARTITION,
     FAT16_LBA_PARTITION
   };
 
   return (NULL != memchr(fat_part_types,type,sizeof(fat_part_types)));
 }
 
-
 /*
  * data_to_part_desc --
  *      parses raw partition table sector data
@@ -433,7 +435,9 @@ rtems_ide_part_table_free(rtems_disk_des
 {
     int part_num;
 
-    for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++)
+    for (part_num = 0;
+         part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
+         part_num++)
     {
         partition_free(disk_desc->partitions[part_num]);
     }
Index: cpukit/libcsupport/include/rtems/libio.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libcsupport/include/rtems/libio.h,v
retrieving revision 1.55
diff -p -u -u -r1.55 libio.h
--- cpukit/libcsupport/include/rtems/libio.h	9 Mar 2009 14:11:22 -0000	1.55
+++ cpukit/libcsupport/include/rtems/libio.h	23 Apr 2009 07:54:39 -0000
@@ -40,6 +40,11 @@ extern "C" {
 #endif
 
 /*
+ * A 64bit file offset for internal use by RTEMS. Based on the newlib type.
+ */
+typedef _off64_t rtems_off64_t;
+
+/*
  * Valid RTEMS file types.
  */
 
@@ -83,9 +88,9 @@ typedef int (*rtems_filesystem_ioctl_t)(
   void          *buffer
 );
 
-typedef off_t (*rtems_filesystem_lseek_t)(
+typedef rtems_off64_t (*rtems_filesystem_lseek_t)(
   rtems_libio_t *iop,
-  off_t          length,
+  rtems_off64_t  length,
   int            whence
 );
 
@@ -101,7 +106,7 @@ typedef int (*rtems_filesystem_fchmod_t)
 
 typedef int (*rtems_filesystem_ftruncate_t)(
   rtems_libio_t *iop,
-  off_t          length
+  rtems_off64_t  length
 );
 
 typedef int (*rtems_filesystem_fpathconf_t)(
@@ -347,8 +352,8 @@ typedef enum
 
 struct rtems_libio_tt {
     rtems_driver_name_t                    *driver;
-    off_t                                   size;      /* size of file */
-    off_t                                   offset;    /* current offset into file */
+    rtems_off64_t                           size;      /* size of file */
+    rtems_off64_t                           offset;    /* current offset into file */
     uint32_t                                flags;
     rtems_filesystem_location_info_t        pathinfo;
     rtems_id                                sem;
@@ -366,7 +371,7 @@ struct rtems_libio_tt {
 
 typedef struct {
     rtems_libio_t          *iop;
-    off_t                   offset;
+    rtems_off64_t           offset;
     char                   *buffer;
     uint32_t                count;
     uint32_t                flags;
@@ -441,10 +446,10 @@ typedef int (*rtems_libio_ioctl_t)(
   void       *buffer
 );
 
-typedef int (*rtems_libio_lseek_t)(
-  int    fd,
-  off_t  offset,
-  int    whence
+typedef rtems_off64_t (*rtems_libio_lseek_t)(
+  int           fd,
+  rtems_off64_t offset,
+  int           whence
 );
 
 /*
Index: cpukit/libfs/src/dosfs/dosfs.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/dosfs.h,v
retrieving revision 1.6
diff -p -u -u -r1.6 dosfs.h
--- cpukit/libfs/src/dosfs/dosfs.h	4 Sep 2008 08:33:05 -0000	1.6
+++ cpukit/libfs/src/dosfs/dosfs.h	23 Apr 2009 07:54:40 -0000
@@ -32,6 +32,11 @@ extern rtems_filesystem_operations_table
 #define MSDOS_FMT_FAT16  2
 #define MSDOS_FMT_FAT32  3
 
+#define MSDOS_FMT_INFO_LEVEL_NONE   (0)
+#define MSDOS_FMT_INFO_LEVEL_INFO   (1)
+#define MSDOS_FMT_INFO_LEVEL_DETAIL (2)
+#define MSDOS_FMT_INFO_LEVEL_DEBUG  (3)
+
 /*
  * data to be filled out for formatter: parameters for format call
  * any parameter set to 0 or NULL will be automatically detected/computed
@@ -51,6 +56,7 @@ typedef struct {
                                   /*   value. This can optimize clusters   */
                                   /*   to be located at start of track     */
                                   /*   or start of flash block             */
+  int       info_level;           /* The amount of info to output          */
 } msdos_format_request_param_t;
 
 /*=========================================================================*\
Index: cpukit/libfs/src/dosfs/fat.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/fat.h,v
retrieving revision 1.15
diff -p -u -u -r1.15 fat.h
--- cpukit/libfs/src/dosfs/fat.h	29 Jan 2009 16:12:44 -0000	1.15
+++ cpukit/libfs/src/dosfs/fat.h	23 Apr 2009 07:54:40 -0000
@@ -250,7 +250,7 @@ extern "C" {
 
 #define FAT_GET_FSINFO_TRAIL_SIGNATURE(x)     FAT_GET_VAL32(x,508)
 #define FAT_SET_FSINFO_TRAIL_SIGNATURE(x,val) FAT_SET_VAL32(x,508,val)
-#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE  (0x000055AA)
+#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE  (0xAA550000)
 /* 
  * I read FSInfo sector from offset 484 to access the information, so offsets 
  * of these fields a relative
@@ -351,15 +351,31 @@ typedef struct fat_fs_info_s
 } fat_fs_info_t;
 
 /*
- * if the name we looking for is file we store not only first data cluster
- * number, but and cluster number and offset for directory entry for this
- * name
+ * FAT position is a the cluster and the offset into the
+ * cluster.
  */
-typedef struct fat_auxiliary_s
+typedef struct fat_pos_s
 {
     uint32_t   cln;
     uint32_t   ofs;
-} fat_auxiliary_t;
+} fat_pos_t;
+
+/*
+ * If the name we looking for is file we store not only first data cluster
+ * number, but and cluster number and offset for directory entry for this
+ * name. We also add the LFN start offset so we can delete it the whole
+ * file name. We can then use this to delete the file.
+ */
+typedef struct fat_dir_pos_s
+{
+    fat_pos_t  sname;
+    fat_pos_t  lname;
+} fat_dir_pos_t;
+
+/*
+ * Set the long name entries to this value for a short file name.
+ */
+#define FAT_FILE_SHORT_NAME (0xffffffff)
 
 #define FAT_FAT_OFFSET(fat_type, cln)                  \
     ((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
@@ -380,6 +396,17 @@ typedef struct fat_auxiliary_s
 #define FAT_OP_TYPE_READ  0x1
 #define FAT_OP_TYPE_GET   0x2
 
+static inline void
+fat_dir_pos_init(
+    fat_dir_pos_t *dir_pos
+    )
+{
+  dir_pos->sname.cln = 0;
+  dir_pos->sname.ofs = 0;
+  dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
+  dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
+}
+
 static inline uint32_t
 fat_cluster_num_to_sector_num(
     rtems_filesystem_mount_table_entry_t *mt_entry,
Index: cpukit/libfs/src/dosfs/fat_file.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/fat_file.c,v
retrieving revision 1.13
diff -p -u -u -r1.13 fat_file.c
--- cpukit/libfs/src/dosfs/fat_file.c	9 Mar 2009 14:11:23 -0000	1.13
+++ cpukit/libfs/src/dosfs/fat_file.c	23 Apr 2009 07:54:40 -0000
@@ -33,20 +33,20 @@
 #include "fat_file.h"
 
 static inline void
-_hash_insert(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
+_hash_insert(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
              fat_file_fd_t *el);
 
 static inline void
-_hash_delete(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
+_hash_delete(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
              fat_file_fd_t *el);
 
 static inline int
 _hash_search(
     rtems_filesystem_mount_table_entry_t  *mt_entry,
-    Chain_Control                         *hash,
+    rtems_chain_control                   *hash,
     uint32_t                               key1,
     uint32_t                               key2,
-    fat_file_fd_t			   **ret
+    fat_file_fd_t			                   **ret
 );
 
 static off_t
@@ -75,8 +75,7 @@ fat_file_lseek(
  *
  * PARAMETERS:
  *     mt_entry - mount table entry
- *     cln      - cluster num of the node
- *     ofs      - offset of the node
+ *     pos      - cluster and offset of the node
  *     fat_fd   - placeholder for returned fat-file descriptor
  *
  * RETURNS:
@@ -86,8 +85,7 @@ fat_file_lseek(
 int
 fat_file_open(
     rtems_filesystem_mount_table_entry_t  *mt_entry,
-    uint32_t                               cln,
-    uint32_t                               ofs,
+    fat_dir_pos_t                         *dir_pos,
     fat_file_fd_t                        **fat_fd
     )
 {
@@ -97,7 +95,7 @@ fat_file_open(
     uint32_t       key = 0;
 
     /* construct key */
-    key = fat_construct_key(mt_entry, cln, ofs);
+    key = fat_construct_key(mt_entry, &dir_pos->sname);
 
     /* access "valid" hash table */
     rc = _hash_search(mt_entry, fs_info->vhash, key, 0, &lfat_fd);
@@ -116,10 +114,14 @@ fat_file_open(
     if ( lfat_fd == NULL )
         rtems_set_errno_and_return_minus_one( ENOMEM );
 
+    memset(lfat_fd, 0, sizeof(fat_file_fd_t));
+    
     lfat_fd->links_num = 1;
     lfat_fd->flags &= ~FAT_FILE_REMOVED;
     lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
 
+    lfat_fd->dir_pos = *dir_pos;
+
     if ( rc != RC_OK )
         lfat_fd->ino = key;
     else
@@ -138,7 +140,6 @@ fat_file_open(
     }
     _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
 
-
     /*
      * other fields of fat-file descriptor will be initialized on upper
      * level
@@ -203,7 +204,7 @@ fat_file_close(
         return rc;
     }
 
-    key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+    key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
 
     if (fat_fd->flags & FAT_FILE_REMOVED)
     {
@@ -582,6 +583,8 @@ fat_file_extend(
         }
     }
 
+    fat_fd->fat_file_size = new_length;
+    
     return RC_OK;
 }
 
@@ -736,7 +739,7 @@ fat_file_mark_removed(
     fat_fs_info_t *fs_info = mt_entry->fs_info;
     uint32_t       key = 0;
 
-    key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+    key = fat_construct_key(mt_entry, &fat_fd->dir_pos.sname);
 
     _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
 
@@ -869,10 +872,10 @@ fat_file_size(
  *     None
  */
 static inline void
-_hash_insert(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
+_hash_insert(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
              fat_file_fd_t *el)
 {
-    _Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
+    rtems_chain_append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
 }
 
 
@@ -889,10 +892,10 @@ _hash_insert(Chain_Control *hash, uint32
  *     None
  */
 static inline void
-_hash_delete(Chain_Control *hash, uint32_t   key1, uint32_t   key2,
+_hash_delete(rtems_chain_control *hash, uint32_t   key1, uint32_t   key2,
              fat_file_fd_t *el)
 {
-    _Chain_Extract(&(el)->link);
+    rtems_chain_extract(&(el)->link);
 }
 
 /* _hash_search --
@@ -912,20 +915,19 @@ _hash_delete(Chain_Control *hash, uint32
 static inline int
 _hash_search(
     rtems_filesystem_mount_table_entry_t  *mt_entry,
-    Chain_Control                         *hash,
+    rtems_chain_control                   *hash,
     uint32_t                               key1,
     uint32_t                               key2,
     fat_file_fd_t                          **ret
     )
 {
-    uint32_t   mod = (key1) % FAT_HASH_MODULE;
-    Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
+    uint32_t          mod = (key1) % FAT_HASH_MODULE;
+    rtems_chain_node *the_node = ((rtems_chain_control *)((hash) + mod))->first;
 
-    for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
+    for ( ; !rtems_chain_is_tail((hash) + mod, the_node) ; )
     {
         fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
-        uint32_t   ck =
-                fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
+        uint32_t       ck =  fat_construct_key(mt_entry, &ffd->dir_pos.sname);
 
         if ( (key1) == ck)
         {
Index: cpukit/libfs/src/dosfs/fat_file.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/fat_file.h,v
retrieving revision 1.8
diff -p -u -u -r1.8 fat_file.h
--- cpukit/libfs/src/dosfs/fat_file.h	4 Feb 2009 12:45:21 -0000	1.8
+++ cpukit/libfs/src/dosfs/fat_file.h	23 Apr 2009 07:54:40 -0000
@@ -20,6 +20,8 @@
 
 #include <time.h>
 
+#include "fat.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -57,30 +59,27 @@ typedef struct fat_file_map_s
  */
 typedef struct fat_file_fd_s
 {
-    Chain_Node      link;          /*
-                                    * fat-file descriptors organized into hash;
-                                    * collision lists are handled via link
-                                    * field
-                                    */
-    uint32_t        links_num;     /*
-                                    * the number of fat_file_open call on
-                                    * this fat-file
-                                    */
-    uint32_t        ino;           /* inode, file serial number :)))) */
-    fat_file_type_t fat_file_type;
-    uint32_t        size_limit;
-    uint32_t        fat_file_size; /* length  */
-    uint32_t        info_cln;
-    uint32_t        cln;
-    uint16_t        info_ofs;
-    unsigned char   first_char;
-    uint8_t         flags;
-    fat_file_map_t  map;
-    time_t          mtime;
+    rtems_chain_node link;          /*
+                                     * fat-file descriptors organized into hash;
+                                     * collision lists are handled via link
+                                     * field
+                                     */
+    uint32_t         links_num;     /*
+                                     * the number of fat_file_open call on
+                                     * this fat-file
+                                     */
+    uint32_t         ino;           /* inode, file serial number :)))) */
+    fat_file_type_t  fat_file_type;
+    uint32_t         size_limit;
+    uint32_t         fat_file_size; /* length  */
+    uint32_t         cln;
+    fat_dir_pos_t    dir_pos;
+    uint8_t          flags;
+    fat_file_map_t   map;
+    time_t           mtime;
 
 } fat_file_fd_t;
 
-
 #define FAT_FILE_REMOVED  0x01
 
 #define FAT_FILE_IS_REMOVED(p)\
@@ -101,8 +100,8 @@ typedef struct fat_file_fd_s
 #define FAT_ROOTDIR_CLUSTER_NUM 0x01
 
 #define FAT_FD_OF_ROOT_DIR(fat_fd)  \
-  ((fat_fd->info_cln == FAT_ROOTDIR_CLUSTER_NUM ) && \
-  (fat_fd->info_ofs == 0))
+  ((fat_fd->dir_pos.sname.cln == FAT_ROOTDIR_CLUSTER_NUM) && \
+  (fat_fd->dir_pos.sname.ofs == 0))
 
 #define FAT_EOF           0x00
 
@@ -122,19 +121,17 @@ typedef struct fat_file_fd_s
 static inline uint32_t
 fat_construct_key(
     rtems_filesystem_mount_table_entry_t *mt_entry,
-    uint32_t                              cl,
-    uint32_t                              ofs)
+    fat_pos_t                            *pos)
 {
-    return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
-              (ofs >> FAT_SECTOR512_BITS)) << 4)              +
-              ((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
+    return ( ((fat_cluster_num_to_sector512_num(mt_entry, pos->cln) +
+              (pos->ofs >> FAT_SECTOR512_BITS)) << 4)              +
+              ((pos->ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
 }
 
 /* Prototypes for "fat-file" operations */
 int
 fat_file_open(rtems_filesystem_mount_table_entry_t  *mt_entry,
-              uint32_t                               cln,
-              uint32_t                               ofs,
+              fat_dir_pos_t                         *dir_pos,
               fat_file_fd_t                        **fat_fd);
 
 int
Index: cpukit/libfs/src/dosfs/msdos.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos.h,v
retrieving revision 1.18
diff -p -u -u -r1.18 msdos.h
--- cpukit/libfs/src/dosfs/msdos.h	9 Mar 2009 14:11:23 -0000	1.18
+++ cpukit/libfs/src/dosfs/msdos.h	23 Apr 2009 07:54:40 -0000
@@ -84,8 +84,10 @@ typedef rtems_filesystem_node_types_t ms
 #define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE    32 /* 32 bytes */
 
 #define MSDOS_DIR_NAME(x)                 (char     *)((x) + 0)
+#define MSDOS_DIR_ENTRY_TYPE(x)           (uint8_t  *)((x) + 0)
 #define MSDOS_DIR_ATTR(x)                 (uint8_t  *)((x) + 11)
 #define MSDOS_DIR_NT_RES(x)               (uint8_t  *)((x) + 12)
+#define MSDOS_DIR_LFN_CHECKSUM(x)         (uint8_t  *)((x) + 13)
 #define MSDOS_DIR_CRT_TIME_TENTH(x)       (uint8_t  *)((x) + 13)
 #define MSDOS_DIR_CRT_TIME(x)             (uint16_t *)((x) + 14)
 #define MSDOS_DIR_CRT_DATE(x)             (uint16_t *)((x) + 16)
@@ -121,6 +123,19 @@ typedef rtems_filesystem_node_types_t ms
 #define MSDOS_ATTR_VOLUME_ID    0x08
 #define MSDOS_ATTR_DIRECTORY    0x10
 #define MSDOS_ATTR_ARCHIVE      0x20
+#define MSDOS_ATTR_LFN          (MSDOS_ATTR_READ_ONLY | \
+                                 MSDOS_ATTR_HIDDEN | \
+                                 MSDOS_ATTR_SYSTEM | \
+                                 MSDOS_ATTR_VOLUME_ID)
+#define MSDOS_ATTR_LFN_MASK     (MSDOS_ATTR_READ_ONLY | \
+                                 MSDOS_ATTR_HIDDEN | \
+                                 MSDOS_ATTR_SYSTEM | \
+                                 MSDOS_ATTR_VOLUME_ID | \
+                                 MSDOS_ATTR_DIRECTORY | \
+                                 MSDOS_ATTR_ARCHIVE)
+
+#define MSDOS_LAST_LONG_ENTRY         0x40
+#define MSDOS_LAST_LONG_ENTRY_MASK    0x3F
 
 #define MSDOS_DT_2SECONDS_MASK        0x1F    /* seconds divided by 2 */
 #define MSDOS_DT_2SECONDS_SHIFT       0
@@ -144,22 +159,35 @@ typedef rtems_filesystem_node_types_t ms
 #define MSDOS_THIS_DIR_ENTRY_EMPTY             0xE5
 #define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY    0x00
 
+/*
+ * Number of characters per directory entry for a long filename.
+ */
+#define MSDOS_LFN_LEN_PER_ENTRY (13)
 
 /*
  *  Macros for names parsing and formatting
  */
-#define msdos_is_valid_name_char(_ch)    (1)
 #define msdos_is_separator(_ch)          rtems_filesystem_is_separator(_ch)
 
 #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_LNF_LEN           (255)
 #define MSDOS_NAME_MAX                   MSDOS_SHORT_NAME_LEN
 #define MSDOS_NAME_MAX_WITH_DOT          (MSDOS_NAME_MAX + 1)
+#define MSDOS_NAME_MAX_LFN_WITH_DOT      (260)
+
 
-#define MSDOS_DOT_NAME     ".          " /* ".", padded to MSDOS_NAME chars */
-#define MSDOS_DOTDOT_NAME  "..         " /* "..", padded to MSDOS_NAME chars */
+extern const char const* MSDOS_DOT_NAME;    /* ".", padded to MSDOS_NAME chars */
+extern const char const* MSDOS_DOTDOT_NAME; /* ".", padded to MSDOS_NAME chars */
+
+typedef enum msdos_name_types_e
+{
+    MSDOS_NAME_INVALID = 0, /* Unknown name type. Has invalid characters. */
+    MSDOS_NAME_SHORT,       /* Name can be short. */
+    MSDOS_NAME_LONG         /* Name is long; cannot be short. */
+} msdos_name_type_t;
 
 typedef enum msdos_token_types_e
 {
@@ -258,9 +286,9 @@ ssize_t msdos_file_write(
   size_t         count            /* IN  */
 );
 
-off_t msdos_file_lseek(
+rtems_off64_t msdos_file_lseek(
   rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
+  rtems_off64_t         offset,           /* IN  */
   int                   whence            /* IN  */
 );
 
@@ -272,7 +300,7 @@ int msdos_file_stat(
 int
 msdos_file_ftruncate(
   rtems_libio_t *iop,               /* IN  */
-  off_t          length             /* IN  */
+  rtems_off64_t  length            /* IN  */
 );
 
 int msdos_file_sync(rtems_libio_t *iop);
@@ -285,6 +313,12 @@ int msdos_file_ioctl(
   void          *buffer           /* IN  */
 );
 
+int
+msdos_dir_chmod(
+  rtems_filesystem_location_info_t *pathloc, /* IN */
+  mode_t                            mode     /* IN */
+);
+
 int msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
 
 int msdos_file_link(
@@ -308,12 +342,18 @@ ssize_t msdos_dir_read(
   size_t         count             /* IN  */
 );
 
-off_t msdos_dir_lseek(
+rtems_off64_t msdos_dir_lseek(
   rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
+  rtems_off64_t         offset,           /* IN  */
   int                   whence            /* IN  */
 );
 
+int
+msdos_file_chmod(
+  rtems_filesystem_location_info_t *pathloc, /* IN */
+  mode_t                            mode     /* IN */
+);
+
 int msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
 
 int msdos_dir_sync(rtems_libio_t *iop);
@@ -324,31 +364,39 @@ int msdos_dir_stat(
 );
 
 int msdos_creat_node(rtems_filesystem_location_info_t  *parent_loc,
-                 msdos_node_type_t                  type,
-                 char                              *name,
-                 mode_t                             mode,
-                 const fat_file_fd_t               *link_fd);
+                     msdos_node_type_t                  type,
+                     const char                        *name,
+                     int                                name_len,
+                     mode_t                             mode,
+                     const fat_file_fd_t               *link_fd);
 
 /* Misc prototypes */
-msdos_token_types_t msdos_get_token(const char *path,
-                                    char       *token,
-                                    int        *token_len);
+msdos_token_types_t msdos_get_token(const char  *path,
+                                    const char **token,
+                                    int         *token_len);
 
 int msdos_find_name(
   rtems_filesystem_location_info_t *parent_loc,
-  char                             *name
+  const char                       *name,
+  int                               name_len
 );
 
 int msdos_get_name_node(
   rtems_filesystem_location_info_t *parent_loc,
-  char                             *name,
-  fat_auxiliary_t                  *paux,
+  bool                              create_node,
+  const char                       *name,
+  int                               name_len,
+  msdos_name_type_t                 name_type,
+  fat_dir_pos_t                    *dir_pos,
   char                             *name_dir_entry
 );
 
 int msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
 
-int msdos_filename_unix2dos(char *un, int unlen, char *dn);
+msdos_name_type_t msdos_long_to_short(const char *lfn, int lfn_len,
+                                      char* sfn, int sfn_len);
+
+int msdos_filename_unix2dos(const char *un, int unlen, char *dn);
 
 void msdos_date_unix2dos(
   unsigned int tsp, unsigned short *ddp,
@@ -368,9 +416,8 @@ int msdos_set_file_size(
 
 int msdos_set_first_char4file_name(
   rtems_filesystem_mount_table_entry_t *mt_entry,
-  uint32_t    cl,
-  uint32_t    ofs,
-  unsigned char first_char
+  fat_dir_pos_t                        *dir_pos,
+  unsigned char                         first_char
 );
 
 int msdos_set_dir_wrt_time_and_date(
@@ -388,8 +435,11 @@ int msdos_dir_is_empty(
 int msdos_find_name_in_fat_file(
     rtems_filesystem_mount_table_entry_t *mt_entry,
     fat_file_fd_t                        *fat_fd,
-    char                                 *name,
-    fat_auxiliary_t                      *paux,
+    bool                                  create_node,
+    const char                           *name,
+    int                                   name_len,
+    msdos_name_type_t                     name_type,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *name_dir_entry
 );
 
@@ -397,14 +447,14 @@ int msdos_find_node_by_cluster_num_in_fa
     rtems_filesystem_mount_table_entry_t *mt_entry,
     fat_file_fd_t                        *fat_fd,
     uint32_t                              cl4find,
-    fat_auxiliary_t                      *paux,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *dir_entry
 );
 
 int msdos_get_dotdot_dir_info_cluster_num_and_offset(
     rtems_filesystem_mount_table_entry_t *mt_entry,
     uint32_t                              cln,
-    fat_auxiliary_t                      *paux,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *dir_entry
 );
 
Index: cpukit/libfs/src/dosfs/msdos_conv.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_conv.c,v
retrieving revision 1.6
diff -p -u -u -r1.6 msdos_conv.c
--- cpukit/libfs/src/dosfs/msdos_conv.c	26 Oct 2004 09:48:53 -0000	1.6
+++ cpukit/libfs/src/dosfs/msdos_conv.c	23 Apr 2009 07:54:40 -0000
@@ -169,6 +169,39 @@ msdos_date_dos2unix(unsigned int dd, uns
 }
 
 static const uint8_t msdos_map[] = {
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 00-07 */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 08-0f */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 10-17 */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 18-1f */
+    0,    '!',  0,    '#',  '$',  '%',  '&',  '\'', /* 20-27 */
+    '(',  ')',  0,    '+',  0,    '-',  0,    0,    /* 28-2f */
+    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  /* 30-37 */
+    '8',  '9',  0,    0,    0,    0,    0,    0,    /* 38-3f */
+    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  /* 40-47 */
+    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  /* 48-4f */
+    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  /* 50-57 */
+    'X',  'Y',  'Z',  0,    0,    0,    '^',  '_',  /* 58-5f */
+    '`',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  /* 60-67 */
+    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  /* 68-6f */
+    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',  /* 70-77 */
+    'X',  'Y',  'Z',  '{',  0,    '}',  '~',  0,    /* 78-7f */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 80-87 */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 88-8f */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 90-97 */
+    0,    0,    0,    0,    0,    0,    0,    0,    /* 98-9f */
+    0,    0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, /* a0-a7 */
+    0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, /* a8-af */
+    0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, /* b0-b7 */
+    0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, /* b8-bf */
+    0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* c0-c7 */
+    0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* c8-cf */
+    0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, /* d0-d7 */
+    0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, /* d8-df */
+    0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, /* e0-e7 */
+    0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, /* e8-ef */
+    0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0xf6, /* f0-f7 */
+    0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0x98, /* f8-ff */
+#if OLD_TABLE
 /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 /* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -201,13 +234,14 @@ static const uint8_t msdos_map[] = {
 /* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 /* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#endif
 };
 /*
  * Convert a unix filename to a DOS filename. Return -1 if wrong name is
  * supplied.
  */
 int
-msdos_filename_unix2dos(char *un, int unlen, char *dn)
+msdos_filename_unix2dos(const char *un, int unlen, char *dn)
 {
 	int i;
 	uint8_t c;
@@ -233,6 +267,14 @@ msdos_filename_unix2dos(char *un, int un
 		return 0;
 	}
 
+  /*
+   * Remove any dots from the start of a file name.
+   */
+	while (unlen && (*un == '.')) {
+		un++;
+		unlen--;
+	}
+  
 	/*
 	 * Copy the unix filename into the dos filename string upto the end
 	 * of string, a '.', or 8 characters. Whichever happens first stops
@@ -240,8 +282,9 @@ msdos_filename_unix2dos(char *un, int un
 	 * upper case.
 	 */
 	for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
-		if ((dn[i] = msdos_map[c]) == 0)
-                        return -1;
+    if (msdos_map[c] == 0)
+      break;
+		dn[i] = msdos_map[c];
 		un++;
 		unlen--;
 	}
@@ -264,8 +307,9 @@ msdos_filename_unix2dos(char *un, int un
 	 * Filenames in this form are probably inaccessable under dos.
 	 */
 	for (i = 8; i <= 10 && unlen && (c = *un); i++) {
-		if ((dn[i] = msdos_map[c]) == 0)
-		        return -1;
+    if (msdos_map[c] == 0)
+      break;
+    dn[i] = msdos_map[c];
 		un++;
 		unlen--;
 	}
Index: cpukit/libfs/src/dosfs/msdos_create.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_create.c,v
retrieving revision 1.13
diff -p -u -u -r1.13 msdos_create.c
--- cpukit/libfs/src/dosfs/msdos_create.c	29 Jul 2008 02:21:14 -0000	1.13
+++ cpukit/libfs/src/dosfs/msdos_create.c	23 Apr 2009 07:54:40 -0000
@@ -17,6 +17,7 @@
 
 #include <errno.h>
 #include <assert.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <rtems/libio_.h>
@@ -29,7 +30,14 @@
 #include "msdos.h"
 
 /* msdos_creat_node --
- *     Create a new node. If a new node is file, FAT 32 Bytes Directory
+ *     Create a new node. Determine if the name is a long name. If long we to
+ *     scan the directory to create a short entry.
+ *
+ *
+
+
+
+ *     If a new node is file, FAT 32 Bytes Directory
  *     Entry Structure is initialized, free space is found in parent
  *     directory and structure is written to the disk. In case of directory,
  *     all above steps present and also new cluster is allocated for a
@@ -48,52 +56,55 @@
  *
  */
 int
-msdos_creat_node(
-    rtems_filesystem_location_info_t  *parent_loc,
-    msdos_node_type_t                  type,
-    char                              *name,
-    mode_t                             mode,
-    const fat_file_fd_t               *link_fd
-    )
+msdos_creat_node(rtems_filesystem_location_info_t  *parent_loc,
+                 msdos_node_type_t                  type,
+                 const char                        *name,
+                 int                                name_len,
+                 mode_t                             mode,
+                 const fat_file_fd_t               *link_fd)
 {
-    int              rc = RC_OK;
-    ssize_t          ret = 0;
-    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
-    fat_file_fd_t   *parent_fat_fd = parent_loc->node_access;
-    fat_file_fd_t   *fat_fd = NULL;
-    time_t           time_ret = 0;
-    uint16_t         time_val = 0;
-    uint16_t         date = 0;
-    fat_auxiliary_t  aux;
-    char             new_node  [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
-    char             dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
-    char             link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
-    uint32_t         sec = 0;
-    uint32_t         byte = 0;
-
-    memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+    int               rc = RC_OK;
+    ssize_t           ret = 0;
+    msdos_fs_info_t  *fs_info = parent_loc->mt_entry->fs_info;
+    fat_file_fd_t    *parent_fat_fd = parent_loc->node_access;
+    fat_file_fd_t    *fat_fd = NULL;
+    time_t            time_ret = 0;
+    uint16_t          time_val = 0;
+    uint16_t          date = 0;
+    fat_dir_pos_t     dir_pos;
+    msdos_name_type_t name_type;
+    char              short_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+    char              dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
+    char              link_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+    uint32_t          sec = 0;
+    uint32_t          byte = 0;
+
+    fat_dir_pos_init(&dir_pos);
+    
+    memset(short_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
     memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
 
-    /* set up name */
-    strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
+    name_type = msdos_long_to_short (name, name_len,
+                                     MSDOS_DIR_NAME(short_node),
+                                     MSDOS_NAME_MAX);
 
     /* fill reserved field */
-    *MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
+    *MSDOS_DIR_NT_RES(short_node) = MSDOS_RES_NT_VALUE;
 
     /* set up last write date and time */
     time_ret = time(NULL);
     if ( time_ret == -1 )
         return -1;
 
-    msdos_date_unix2dos(time_ret, &time_val, &date);
-    *MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
-    *MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
+    msdos_date_unix2dos(time_ret, &date, &time_val);
+    *MSDOS_DIR_WRITE_TIME(short_node) = CT_LE_W(time_val);
+    *MSDOS_DIR_WRITE_DATE(short_node) = CT_LE_W(date);
 
     /* initialize directory/file size */
-    *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
+    *MSDOS_DIR_FILE_SIZE(short_node) = MSDOS_INIT_DIR_SIZE;
 
-    if (type == MSDOS_DIRECTORY){
-        *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
+    if (type == MSDOS_DIRECTORY) {
+      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_DIRECTORY;
     }
     else if (type == MSDOS_HARD_LINK) {
       /*
@@ -105,51 +116,52 @@ msdos_creat_node(
        * read the original directory entry
        */
       sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry,
-					  link_fd->info_cln);
-      sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2);
-      byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+                                          link_fd->dir_pos.sname.cln);
+      sec += (link_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
+      byte = (link_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
 
       ret = _fat_block_read(parent_loc->mt_entry,
-			    sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+                            sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
                             link_node);
       if (ret < 0) {
-	return -1;
+          return -1;
       }
       /*
        * copy various attributes
        */
-      *MSDOS_DIR_ATTR(new_node)          =*MSDOS_DIR_ATTR(link_node);
-      *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
-      *MSDOS_DIR_CRT_TIME(new_node)      =*MSDOS_DIR_CRT_TIME(link_node);
-      *MSDOS_DIR_CRT_DATE(new_node)      =*MSDOS_DIR_CRT_DATE(link_node);
+      *MSDOS_DIR_ATTR(short_node)          =*MSDOS_DIR_ATTR(link_node);
+      *MSDOS_DIR_CRT_TIME_TENTH(short_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
+      *MSDOS_DIR_CRT_TIME(short_node)      =*MSDOS_DIR_CRT_TIME(link_node);
+      *MSDOS_DIR_CRT_DATE(short_node)      =*MSDOS_DIR_CRT_DATE(link_node);
 
       /*
        * copy/set "file size", "first cluster"
        */
-      *MSDOS_DIR_FILE_SIZE(new_node)     =*MSDOS_DIR_FILE_SIZE(link_node);
+      *MSDOS_DIR_FILE_SIZE(short_node)     =*MSDOS_DIR_FILE_SIZE(link_node);
 
-      *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
+      *MSDOS_DIR_FIRST_CLUSTER_LOW(short_node) =
            *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
-      *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
+      *MSDOS_DIR_FIRST_CLUSTER_HI(short_node) =
            *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
       /*
        * set "archive bit" due to changes
        */
-      *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+      *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
       /*
        * set "last access" date to today
        */
-      *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date);
+      *MSDOS_DIR_LAST_ACCESS_DATE(short_node) = CT_LE_W(date);
     }
     else { /* regular file... */
-        *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+        *MSDOS_DIR_ATTR(short_node) |= MSDOS_ATTR_ARCHIVE;
     }
 
     /*
      * find free space in the parent directory and write new initialized
      * FAT 32 Bytes Directory Entry Structure to the disk
      */
-    rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
+    rc = msdos_get_name_node(parent_loc, true, name, name_len,
+                             name_type, &dir_pos, short_node);
     if ( rc != RC_OK )
         return rc;
 
@@ -160,7 +172,7 @@ msdos_creat_node(
     if (type == MSDOS_DIRECTORY)
     {
         /* open new directory as fat-file */
-        rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+        rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
         if (rc != RC_OK)
             goto err;
 
@@ -168,8 +180,6 @@ msdos_creat_node(
          * we opened fat-file for node we just created, so initialize fat-file
          * descritor
          */
-        fat_fd->info_cln = aux.cln;
-        fat_fd->info_ofs = aux.ofs;
         fat_fd->fat_file_size = 0;
         fat_fd->fat_file_type = FAT_DIRECTORY;
         fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
@@ -178,9 +188,9 @@ msdos_creat_node(
          * dot and dotdot entries are identical to new node except the
          * names
          */
-        memcpy(DOT_NODE_P(dot_dotdot), new_node,
+        memcpy(DOT_NODE_P(dot_dotdot), short_node,
                MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
-        memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
+        memcpy(DOTDOT_NODE_P(dot_dotdot), short_node,
                MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
         memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
                MSDOS_NAME_MAX);
@@ -253,9 +263,8 @@ error:
     fat_file_close(parent_loc->mt_entry, fat_fd);
 
 err:
-    /* mark 32bytes structure on the disk as free */
-    msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
-                                   0xE5);
+    /* mark the used 32bytes structure on the disk as free */
+    msdos_set_first_char4file_name(parent_loc->mt_entry, &dir_pos, 0xE5);
     return rc;
 }
 
@@ -287,21 +296,21 @@ err:
  */
 int
 msdos_file_link(rtems_filesystem_location_info_t *to_loc,
-		rtems_filesystem_location_info_t *par_loc,
-		const char                       *token
+                rtems_filesystem_location_info_t *par_loc,
+                const char                       *name
 )
 {
     int                rc = RC_OK;
     rtems_status_code  sc = RTEMS_SUCCESSFUL;
     msdos_fs_info_t   *fs_info     = to_loc->mt_entry->fs_info;
     fat_file_fd_t     *to_fat_fd   = to_loc->node_access;
-    char               new_name[ MSDOS_NAME_MAX + 1 ];
+    const char        *token;
     int                len;
 
     /*
      * check spelling and format new node name
      */
-    if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
+    if (MSDOS_NAME != msdos_get_token(name, &token, &len)) {
       rtems_set_errno_and_return_minus_one(ENAMETOOLONG);
     }
     /*
@@ -324,8 +333,8 @@ msdos_file_link(rtems_filesystem_locatio
      * create new directory entry as "hard link",
      * copying relevant info from existing file
      */
-    rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG,
-			  to_loc->node_access);
+    rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,name,len,S_IFREG,
+                          to_loc->node_access);
     /*
      * set file size and first cluster number of old entry to 0
      */
Index: cpukit/libfs/src/dosfs/msdos_dir.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_dir.c,v
retrieving revision 1.13
diff -p -u -u -r1.13 msdos_dir.c
--- cpukit/libfs/src/dosfs/msdos_dir.c	9 Mar 2009 14:11:23 -0000	1.13
+++ cpukit/libfs/src/dosfs/msdos_dir.c	23 Apr 2009 07:54:40 -0000
@@ -14,6 +14,7 @@
 #include "config.h"
 #endif
 
+#include <ctype.h> 
 #include <stdlib.h>
 #include <unistd.h>
 #include <assert.h>
@@ -145,7 +146,7 @@ msdos_format_dirent_with_dot(char *dst,c
   src_tmp = src;
   len = i;
   while (i-- > 0) {
-    *dst++ = *src_tmp++;
+    *dst++ = tolower(*src_tmp++);
   }
   /*
    * find last non-blank character of extension
@@ -164,7 +165,7 @@ msdos_format_dirent_with_dot(char *dst,c
     len += i + 1; /* extension + dot */
     src_tmp = src + MSDOS_SHORT_BASE_LEN;
     while (i-- > 0) {
-      *dst++ = *src_tmp++;
+      *dst++ = tolower(*src_tmp++);
       len++;
     }
   }
@@ -210,6 +211,9 @@ msdos_dir_read(rtems_libio_t *iop, void 
     uint32_t           j = 0, i = 0;
     uint32_t           bts2rd = 0;
     uint32_t           cur_cln = 0;
+    uint32_t           lfn_start = FAT_FILE_SHORT_NAME;
+    uint8_t            lfn_checksum = 0;
+    int                lfn_entries = 0;
 
     /*
      * cast start and count - protect against using sizes that are not exact
@@ -253,80 +257,211 @@ msdos_dir_read(rtems_libio_t *iop, void 
 
         for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
         {
-            if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+            char* entry = (char*) fs_info->cl_buf + i;
+            
+            /*
+             * Is this directory from here on empty ?
+             */
+            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
                 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
             {
                 rtems_semaphore_release(fs_info->vol_sema);
                 return cmpltd;
             }
 
-            /* have to look at the DIR_NAME as "raw" 8-bit data */
-            if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
-                MSDOS_THIS_DIR_ENTRY_EMPTY)
+            /* Is the directory entry empty */
+            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) == MSDOS_THIS_DIR_ENTRY_EMPTY)
                 continue;
 
-            /*
-             * skip active entries until get the entry to start from
-             */
-            if (start)
-            {
-                start--;
+            /* Is the directory entry empty a volume label */
+            if (((*MSDOS_DIR_ATTR(entry)) & MSDOS_ATTR_VOLUME_ID) &&
+                ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) != MSDOS_ATTR_LFN))
                 continue;
-            }
 
             /*
-             * Move the entry to the return buffer
-             *
-             * unfortunately there is no method to extract ino except to
-             * open fat-file descriptor :( ... so, open it
+             * Check the attribute to see if the entry is for a long file
+             * name.
              */
-
-            /* get number of cluster we are working with */
-            rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
-                                j * bts2rd, &cur_cln);
-            if (rc != RC_OK)
+            if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+                MSDOS_ATTR_LFN)
             {
-                rtems_semaphore_release(fs_info->vol_sema);
-                return rc;
-            }
-
-            rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
-                               &tmp_fat_fd);
-            if (rc != RC_OK)
-            {
-                rtems_semaphore_release(fs_info->vol_sema);
-                return rc;
+                int   o;
+                char* p;
+                int   q;
+                
+                /*
+                 * Is this is the first entry of a LFN ?
+                 */
+                if (lfn_start == FAT_FILE_SHORT_NAME)
+                {
+                    /*
+                     * The first entry must have the last long entry flag set.
+                     */
+                    if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
+                         MSDOS_LAST_LONG_ENTRY) == 0)
+                        continue;
+
+                    /*
+                     * Remember the start location of the long file name.
+                     */
+                    lfn_start =
+                      ((j * bts2rd) + i) / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+                    
+                    /*
+                     * Get the number of entries so we can count down and
+                     * also the checksum of the short entry.
+                     */
+                    lfn_entries = (*MSDOS_DIR_ENTRY_TYPE(entry) &
+                                   MSDOS_LAST_LONG_ENTRY_MASK);
+                    lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
+                    memset (tmp_dirent.d_name, 0, sizeof(tmp_dirent.d_name));
+                }
+
+                /*
+                 * If the entry number or the check sum do not match
+                 * forget this series of long directory entries. These could
+                 * be orphaned entries depending on the history of the
+                 * disk.
+                 */
+                if ((lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+                                     MSDOS_LAST_LONG_ENTRY_MASK)) ||
+                    (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
+                {
+                    lfn_start = FAT_FILE_SHORT_NAME;
+                    continue;
+                }
+             
+                /*
+                 * Extract the file name into the directory entry. The data is
+                 * stored in UNICODE characters (16bit). No translation is
+                 * currently supported.
+                 *
+                 * The DOS maximum length is 255 characters without the
+                 * trailing nul character. We need to range check the length to
+                 * fit in the directory entry name field.
+                 */
+                
+                lfn_entries--;
+                p = entry + 1;
+                o = lfn_entries * MSDOS_LFN_LEN_PER_ENTRY;
+                
+                for (q = 0; q < MSDOS_LFN_LEN_PER_ENTRY; q++)
+                {
+                    if (o >= (sizeof(tmp_dirent.d_name) - 1))
+                        break;
+                        
+                    tmp_dirent.d_name[o++] = *p;
+
+                    if (*p == '\0')
+                        break;
+
+                    switch (q)
+                    {
+                        case 4:
+                            p += 5;
+                            break;
+                        case 10:
+                            p += 4;
+                            break;
+                        default:
+                            p += 2;
+                            break;
+                    }
+                }
             }
-
-            tmp_fat_fd->info_cln = cur_cln;
-            tmp_fat_fd->info_ofs = i;
-
-            /* fill in dirent structure */
-            /* XXX: from what and in what d_off should be computed ?! */
-            tmp_dirent.d_off = start + cmpltd;
-            tmp_dirent.d_reclen = sizeof(struct dirent);
-            tmp_dirent.d_ino = tmp_fat_fd->ino;
-	    /*
-	     * 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,
-	      (char *) fs_info->cl_buf + i); /* src text */
-            memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
-
-            iop->offset = iop->offset + sizeof(struct dirent);
-            cmpltd += (sizeof(struct dirent));
-            count -= (sizeof(struct dirent));
-
-            /* inode number extracted, close fat-file */
-            rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
-            if (rc != RC_OK)
+            else
             {
-                rtems_semaphore_release(fs_info->vol_sema);
-                return rc;
+                fat_dir_pos_t dir_pos;
+              
+                /*
+                 * Skip active entries until get the entry to start from.
+                 */
+                if (start)
+                {
+                    lfn_start = FAT_FILE_SHORT_NAME;
+                    start--;
+                    continue;
+                }
+
+                /*
+                 * Move the entry to the return buffer
+                 *
+                 * unfortunately there is no method to extract ino except to
+                 * open fat-file descriptor :( ... so, open it
+                 */
+
+                /* get number of cluster we are working with */
+                rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
+                                    j * bts2rd, &cur_cln);
+                if (rc != RC_OK)
+                {
+                    rtems_semaphore_release(fs_info->vol_sema);
+                    return rc;
+                }
+
+                fat_dir_pos_init(&dir_pos);
+                dir_pos.sname.cln = cur_cln;
+                dir_pos.sname.ofs = i;
+                rc = fat_file_open(iop->pathinfo.mt_entry, &dir_pos, &tmp_fat_fd);
+                if (rc != RC_OK)
+                {
+                    rtems_semaphore_release(fs_info->vol_sema);
+                    return rc;
+                }
+
+                /* fill in dirent structure */
+                /* XXX: from what and in what d_off should be computed ?! */
+                tmp_dirent.d_off = start + cmpltd;
+                tmp_dirent.d_reclen = sizeof(struct dirent);
+                tmp_dirent.d_ino = tmp_fat_fd->ino;
+
+                /*
+                 * If a long file name check if the correct number of
+                 * entries have been found and if the checksum is correct.
+                 * If not return the short file name.
+                 */
+                if (lfn_start != FAT_FILE_SHORT_NAME)
+                {
+                    uint8_t  cs = 0;
+                    uint8_t* p = (uint8_t*) entry;
+                    int      i;
+
+                    for (i = 0; i < 11; i++, p++)
+                        cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
+
+                    if (lfn_entries || (lfn_checksum != cs))
+                        lfn_start = FAT_FILE_SHORT_NAME;
+                }
+
+                if (lfn_start == FAT_FILE_SHORT_NAME)
+                {
+                    /*
+                     * 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, entry); /* src text */
+                }
+                else
+                {
+                    tmp_dirent.d_namlen = strlen(tmp_dirent.d_name);
+                }
+                
+                memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
+
+                iop->offset = iop->offset + sizeof(struct dirent);
+                cmpltd += (sizeof(struct dirent));
+                count -= (sizeof(struct dirent));
+
+                /* inode number extracted, close fat-file */
+                rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
+                if (rc != RC_OK)
+                {
+                    rtems_semaphore_release(fs_info->vol_sema);
+                    return rc;
+                }
             }
-
+            
             if (count <= 0)
                 break;
         }
@@ -363,8 +498,8 @@ msdos_dir_read(rtems_libio_t *iop, void 
  *     RC_OK on success, or -1 if error occured (errno
  *     set apropriately).
  */
-off_t
-msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
+rtems_off64_t
+msdos_dir_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
 {
     switch (whence)
     {
@@ -471,6 +606,24 @@ msdos_dir_sync(rtems_libio_t *iop)
     return rc;
 }
 
+/* msdos_dir_chmod --
+ *     Change the attributes of the directory. This currently does
+ *     nothing and returns no error.
+ *
+ * PARAMETERS:
+ *     pathloc - node description
+ *     mode - the new mode
+ *
+ * RETURNS:
+ *     RC_OK always
+ */
+int
+msdos_dir_chmod(rtems_filesystem_location_info_t *pathloc,
+                mode_t                            mode)
+{
+  return RC_OK;
+}
+
 /* msdos_dir_rmnod --
  *     Remove directory node.
  *
@@ -498,7 +651,7 @@ msdos_dir_rmnod(rtems_filesystem_locatio
         rtems_set_errno_and_return_minus_one(EIO);
 
     /*
-     * We deny attemp to delete open directory (if directory is current
+     * We deny attempts to delete open directory (if directory is current
      * directory we assume it is open one)
      */
     if (fat_fd->links_num > 1)
@@ -538,8 +691,7 @@ msdos_dir_rmnod(rtems_filesystem_locatio
      */
 
     /* mark file removed */
-    rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
-                                        fat_fd->info_ofs,
+    rc = msdos_set_first_char4file_name(pathloc->mt_entry, &fat_fd->dir_pos,
                                         MSDOS_THIS_DIR_ENTRY_EMPTY);
     if (rc != RC_OK)
     {
Index: cpukit/libfs/src/dosfs/msdos_eval.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_eval.c,v
retrieving revision 1.8
diff -p -u -u -r1.8 msdos_eval.c
--- cpukit/libfs/src/dosfs/msdos_eval.c	4 Sep 2008 08:33:06 -0000	1.8
+++ cpukit/libfs/src/dosfs/msdos_eval.c	23 Apr 2009 07:54:40 -0000
@@ -82,9 +82,9 @@ msdos_eval_path(
     fat_file_fd_t                    *fat_fd = NULL;
     rtems_filesystem_location_info_t  newloc;
     int                               i = 0;
-    int                               len = 0;
+    int                               token_len = 0;
     msdos_token_types_t               type = MSDOS_CURRENT_DIR;
-    char                              token[MSDOS_NAME_MAX + 1];
+    const char                       *token;
 
     sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
                                 MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
@@ -106,8 +106,8 @@ msdos_eval_path(
 
     while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
     {
-        type = msdos_get_token(&pathname[i], token, &len);
-        i += len;
+        type = msdos_get_token(&pathname[i], &token, &token_len);
+        i += token_len;
 
         fat_fd = pathloc->node_access;
 
@@ -149,13 +149,13 @@ msdos_eval_path(
                             goto err;
 
                         rtems_semaphore_release(fs_info->vol_sema);
-                        return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
+                        return (*pathloc->ops->evalpath_h)(&(pathname[i-token_len]),
                                                            flags, pathloc);
                     }
                 }
                 else
                 {
-                    rc = msdos_find_name(pathloc, token);
+                  rc = msdos_find_name(pathloc, token, token_len);
                     if (rc != RC_OK)
                     {
                         if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -183,7 +183,7 @@ msdos_eval_path(
                  *  Otherwise find the token name in the present location and
                  * set the node access to the point we have found.
                  */
-                rc = msdos_find_name(pathloc, token);
+                rc = msdos_find_name(pathloc, token, token_len);
                 if (rc != RC_OK)
                 {
                     if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -264,8 +264,8 @@ msdos_eval4make(
     rtems_filesystem_location_info_t  newloc;
     msdos_token_types_t               type;
     int                               i = 0;
-    int                               len;
-    char                              token[ MSDOS_NAME_MAX + 1 ];
+    int                               token_len;
+    const char                       *token;
     bool                              done = false;
 
     sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
@@ -288,8 +288,8 @@ msdos_eval4make(
 
     while (!done)
     {
-        type = msdos_get_token(&path[i], token, &len);
-        i += len;
+        type = msdos_get_token(&path[i], &token, &token_len);
+        i += token_len;
         fat_fd = pathloc->node_access;
 
         switch (type)
@@ -330,13 +330,13 @@ msdos_eval4make(
                             goto err;
 
                         rtems_semaphore_release(fs_info->vol_sema);
-                        return (*pathloc->ops->evalformake_h)(&path[i-len],
+                        return (*pathloc->ops->evalformake_h)(&path[i-token_len],
                                                               pathloc, name);
                     }
                 }
                 else
                 {
-                    rc = msdos_find_name(pathloc, token);
+                    rc = msdos_find_name(pathloc, token, token_len);
                     if (rc != RC_OK)
                     {
                         if (rc == MSDOS_NAME_NOT_FOUND_ERR)
@@ -361,10 +361,10 @@ msdos_eval4make(
                 }
 
                 /*
-                 *  Otherwise find the token name in the present location and
+                 * Otherwise find the token name in the present location and
                  * set the node access to the point we have found.
                  */
-                rc = msdos_find_name(pathloc, token);
+                rc = msdos_find_name(pathloc, token, token_len);
                 if (rc)
                 {
                     if (rc != MSDOS_NAME_NOT_FOUND_ERR)
@@ -396,7 +396,7 @@ msdos_eval4make(
         }
     }
 
-    *name = &path[i - len];
+    *name = &path[i - token_len];
 
     /*
      * We have evaluated the path as far as we can.
Index: cpukit/libfs/src/dosfs/msdos_file.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_file.c,v
retrieving revision 1.11
diff -p -u -u -r1.11 msdos_file.c
--- cpukit/libfs/src/dosfs/msdos_file.c	9 Mar 2009 14:11:23 -0000	1.11
+++ cpukit/libfs/src/dosfs/msdos_file.c	23 Apr 2009 07:54:40 -0000
@@ -223,8 +223,8 @@ msdos_file_write(rtems_libio_t *iop,cons
  *     new offset on success, or -1 if error occured (errno set
  *     appropriately).
  */
-off_t
-msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
+rtems_off64_t
+msdos_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
 {
     int                rc = RC_OK;
     rtems_status_code  sc = RTEMS_SUCCESSFUL;
@@ -302,7 +302,7 @@ msdos_file_stat(
  *     RC_OK on success, or -1 if error occured (errno set appropriately).
  */
 int
-msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
+msdos_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length)
 {
     int                rc = RC_OK;
     rtems_status_code  sc = RTEMS_SUCCESSFUL;
@@ -444,6 +444,24 @@ msdos_file_ioctl(rtems_libio_t *iop,uint
     return rc;
 }
 
+/* msdos_file_chmod --
+ *     Change the attributes of the file. This currently does
+ *     nothing and returns no error.
+ *
+ * PARAMETERS:
+ *     pathloc - node description
+ *     mode - the new mode
+ *
+ * RETURNS:
+ *     RC_OK always
+ */
+int
+msdos_file_chmod(rtems_filesystem_location_info_t *pathloc,
+                 mode_t                            mode)
+{
+  return RC_OK;
+}
+
 /* msdos_file_rmnod --
  *     Remove node associated with a file - set up first name character to
  *     predefined value(and write it to the disk), and mark fat-file which
@@ -469,8 +487,8 @@ msdos_file_rmnod(rtems_filesystem_locati
         rtems_set_errno_and_return_minus_one(EIO);
 
     /* mark file removed */
-    rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
-                                        fat_fd->info_ofs,
+    rc = msdos_set_first_char4file_name(pathloc->mt_entry,
+                                        &fat_fd->dir_pos,
                                         MSDOS_THIS_DIR_ENTRY_EMPTY);
     if (rc != RC_OK)
     {
Index: cpukit/libfs/src/dosfs/msdos_format.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_format.c,v
retrieving revision 1.6
diff -p -u -u -r1.6 msdos_format.c
--- cpukit/libfs/src/dosfs/msdos_format.c	4 Sep 2008 08:33:06 -0000	1.6
+++ cpukit/libfs/src/dosfs/msdos_format.c	23 Apr 2009 07:54:40 -0000
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <ctype.h>
 #include <assert.h>
 
@@ -65,6 +66,58 @@ typedef struct {
   uint32_t vol_id;
 }  msdos_format_param_t;
 
+/*
+ * Formatted output.
+ */
+static void
+msdos_format_printf (const msdos_format_request_param_t *rqdata,
+                     int                                 info_level,
+                     const char                         *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  if (rqdata->info_level >= info_level)
+  {
+    vfprintf (stdout, format, args);
+    fflush (stdout);
+  }
+}
+
+/*=========================================================================*\
+| Function:                                                                 |
+\*-------------------------------------------------------------------------*/
+static int msdos_format_read_sec
+(
+/*-------------------------------------------------------------------------*\
+| Purpose:                                                                  |
+|     function to read a sector                                             |
++---------------------------------------------------------------------------+
+| Input Parameters:                                                         |
+\*-------------------------------------------------------------------------*/
+ int         fd,                       /* file descriptor index            */
+ uint32_t    start_sector,             /* sector number to write to        */
+ uint32_t    sector_size,              /* size of sector                   */
+ char       *buffer                    /* buffer with read data into       */
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value:                                                             |
+|    0, if success, -1 and errno if failed                                  |
+\*=========================================================================*/
+{
+  int ret_val = 0;
+
+  if (0 > lseek(fd,((off_t)start_sector)*sector_size,SEEK_SET)) {
+    ret_val = -1;
+  }
+  if (ret_val == 0) {
+    if (0 > read(fd,buffer,sector_size)) {
+      ret_val = -1;
+    }
+  }
+
+  return ret_val;
+}
+
 /*=========================================================================*\
 | Function:                                                                 |
 \*-------------------------------------------------------------------------*/
@@ -100,7 +153,7 @@ static int msdos_format_write_sec
   return ret_val;
 }
 
-/*=========================================================================*\
+/*=========================================================================* \
 | Function:                                                                 |
 \*-------------------------------------------------------------------------*/
 static int msdos_format_fill_sectors
@@ -111,6 +164,7 @@ static int msdos_format_fill_sectors
 +---------------------------------------------------------------------------+
 | Input Parameters:                                                         |
 \*-------------------------------------------------------------------------*/
+ const msdos_format_request_param_t *rqdata,
  int         fd,                       /* file descriptor index            */
  uint32_t    start_sector,             /* sector number to fill to         */
  uint32_t    sector_cnt,               /* number of sectors to fill to     */
@@ -124,7 +178,9 @@ static int msdos_format_fill_sectors
 {
   int ret_val = 0;
   char *fill_buffer = NULL;
-
+  uint32_t total_sectors = sector_cnt;
+  int last_percent = -1;
+  
   /*
    * allocate and fill buffer
    */
@@ -138,15 +194,31 @@ static int msdos_format_fill_sectors
       memset(fill_buffer,fill_byte,sector_size);
     }
   }
+
+  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                       "Filling : ");
   /*
    * write to consecutive sectors
    */
   while ((ret_val == 0) && 
 	 (sector_cnt > 0)) {
+    int percent = (sector_cnt * 100) / total_sectors;
+    if (percent != last_percent) {
+      if ((percent & 1) == 0)
+        msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, ".");
+      last_percent = percent;
+    }
     ret_val = msdos_format_write_sec(fd,start_sector,sector_size,fill_buffer);
     start_sector++;
     sector_cnt--;
   }
+  
+  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL, "\n");
+
+  if (ret_val)
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
+                         "filling error on sector: %d\n", start_sector);
+  
   /*
    * cleanup
    */
@@ -311,7 +383,8 @@ static int msdos_format_determine_fmt_pa
   uint32_t fatdata_sect_cnt;
   uint32_t onebit;
   uint32_t sectors_per_cluster_adj = 0;
-
+  uint64_t total_size = 0;
+  
   memset(fmt_params,0,sizeof(*fmt_params));
   /* 
    * this one is fixed in this implementation.
@@ -320,6 +393,10 @@ static int msdos_format_determine_fmt_pa
   if (ret_val == 0) {
     fmt_params->bytes_per_sector = dd->block_size;
     fmt_params->totl_sector_cnt  = dd->size;
+    total_size = dd->block_size * dd->size;
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                         "bytes per sector: %d\ntotal sectors: %d\ntotal size: %lu\n",
+                         dd->block_size, dd->size, total_size);
   }
   /*
    * determine number of FATs
@@ -336,6 +413,11 @@ static int msdos_format_determine_fmt_pa
       ret_val = EINVAL;
     }
   }
+  
+  if (ret_val == 0)
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                         "number of fats: %d\n", fmt_params->fat_num);
+  
   /*
    * Now we get sort of a loop when determining things:
    * The FAT type (FAT12/16/32) is determined ONLY from the 
@@ -396,21 +478,26 @@ static int msdos_format_determine_fmt_pa
        * are a compromise concerning capacity and efficency
        */
       if (fmt_params->totl_sector_cnt 
-	  < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
-	fmt_params->fattype = FAT_FAT12;
-	/* start trying with small clusters */
-	fmt_params->sectors_per_cluster = 2; 
+          < ((uint32_t)FAT_FAT12_MAX_CLN)*8) {
+        fmt_params->fattype = FAT_FAT12;
+        /* start trying with small clusters */
+        fmt_params->sectors_per_cluster = 2; 
       }
       else if (fmt_params->totl_sector_cnt 
-	       < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
-	fmt_params->fattype = FAT_FAT16;
-	/* start trying with small clusters */
-	fmt_params->sectors_per_cluster = 2; 
+               < ((uint32_t)FAT_FAT16_MAX_CLN)*32) {
+        fmt_params->fattype = FAT_FAT16;
+        /* start trying with small clusters */
+        fmt_params->sectors_per_cluster = 2; 
       }
       else {
-	fmt_params->fattype = FAT_FAT32;
-	/* start trying with small clusters... */
-	fmt_params->sectors_per_cluster = 1; 
+        uint32_t gigs = (total_size + (1024 * 1024 * 1024)) / (1024 * 1024 * 1024);
+        int b;
+        fmt_params->fattype = FAT_FAT32;
+        /* scale with the size of disk... */
+        for (b = 31; b > 0; b--)
+          if ((gigs & (1 << b)) != 0)
+            break;
+        fmt_params->sectors_per_cluster = 1 << b;
       }
     }
     /*
@@ -428,7 +515,7 @@ static int msdos_format_determine_fmt_pa
      * sectors_per_cluster*bytes_per_sector must not be bigger than 32K
      */
     for (onebit = 128;onebit >= 1;onebit = onebit>>1) {
-      if (fmt_params->sectors_per_cluster > onebit) {
+      if (fmt_params->sectors_per_cluster >= onebit) {
 	fmt_params->sectors_per_cluster = onebit;
 	if (fmt_params->sectors_per_cluster 
 	    <= 32768L/fmt_params->bytes_per_sector) {
@@ -440,6 +527,9 @@ static int msdos_format_determine_fmt_pa
   }
 
   if (ret_val == 0) {
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                         "sectors per cluster: %d\n", fmt_params->sectors_per_cluster);
+    
     if (fmt_params->fattype == FAT_FAT32) {
       /* recommended: for FAT32, always set reserved sector count to 32 */
       fmt_params->rsvd_sector_cnt = 32;
@@ -649,9 +739,15 @@ static int msdos_format_gen_mbr
     total_sectors_num32 = fmt_params->totl_sector_cnt;
   }
   /*
-   * finally we are there: let's fill in the values into the MBR 
+   * finally we are there: let's fill in the values into the MBR
+   * but first clear the MRB leaving the partition table.
    */
-  memset(mbr,0,FAT_TOTAL_MBR_SIZE);
+#define RTEMS_IDE_PARTITION_TABLE_OFFSET                  0x1be
+#define RTEMS_IDE_PARTITION_TABLE_SIZE                    (4 * 16)
+  memset(mbr,0,RTEMS_IDE_PARTITION_TABLE_OFFSET);
+  memset(mbr + RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE,
+         0,
+         FAT_TOTAL_MBR_SIZE - (RTEMS_IDE_PARTITION_TABLE_OFFSET + RTEMS_IDE_PARTITION_TABLE_SIZE));
   /*
    * FIXME: fill jmpBoot and Boot code...
    * with 0xEB,....
@@ -672,9 +768,9 @@ static int msdos_format_gen_mbr
   FAT_SET_BR_TOTAL_SECTORS_NUM16(mbr , total_sectors_num16);
   FAT_SET_BR_MEDIA(mbr               , fmt_params->media_code);
 
-  FAT_SET_BR_SECTORS_PER_TRACK(mbr   , 0); /* only needed for INT13... */
-  FAT_SET_BR_NUMBER_OF_HEADS(mbr     , 0); /* only needed for INT13... */
-  FAT_SET_BR_HIDDEN_SECTORS(mbr      , 0); /* only needed for INT13... */
+  FAT_SET_BR_SECTORS_PER_TRACK(mbr   , 255); /* only needed for INT13... */
+  FAT_SET_BR_NUMBER_OF_HEADS(mbr     , 6);   /* only needed for INT13... */
+  FAT_SET_BR_HIDDEN_SECTORS(mbr      , 1);   /* only needed for INT13... */
 
   FAT_SET_BR_TOTAL_SECTORS_NUM32(mbr , total_sectors_num32);
   if (fmt_params->fattype != FAT_FAT32) {
@@ -749,7 +845,6 @@ static int msdos_format_gen_fsinfo
 |    0, if success, -1 and errno if failed                                  |
 \*=========================================================================*/
 {
-
   /*
    * clear fsinfo sector data 
    */
@@ -760,9 +855,9 @@ static int msdos_format_gen_fsinfo
   FAT_SET_FSINFO_LEAD_SIGNATURE (fsinfo,FAT_FSINFO_LEAD_SIGNATURE_VALUE );
   FAT_SET_FSINFO_STRUC_SIGNATURE(fsinfo,FAT_FSINFO_STRUC_SIGNATURE_VALUE);
   FAT_SET_FSINFO_TRAIL_SIGNATURE(fsinfo,FAT_FSINFO_TRAIL_SIGNATURE_VALUE);
-/* 
- * write "empty" values for free cluster count and next cluster number 
- */
+  /* 
+   * write "empty" values for free cluster count and next cluster number 
+   */
   FAT_SET_FSINFO_FREE_CLUSTER_COUNT(fsinfo+FAT_FSI_INFO,
 				    0xffffffff);
   FAT_SET_FSINFO_NEXT_FREE_CLUSTER (fsinfo+FAT_FSI_INFO,
@@ -800,9 +895,13 @@ int msdos_format
   int                  i;
   msdos_format_param_t fmt_params;
 
+  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_INFO,
+                       "formating: %s\n", devname);
   /*
    * sanity check on device
    */
+  msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                       "stat check: %s\n", devname);
   if (ret_val == 0) {
     rc = stat(devname, &stat_buf);
     ret_val = rc;
@@ -828,7 +927,9 @@ int msdos_format
    * open device for writing
    */
   if (ret_val == 0) {
-    fd = open(devname, O_WRONLY);
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                         "open device\n");
+    fd = open(devname, O_RDWR);
     if (fd == -1)
     {
       ret_val= -1;
@@ -848,7 +949,8 @@ int msdos_format
       (rqdata != NULL) &&
       !(rqdata->quick_format)) {
     ret_val = msdos_format_fill_sectors
-      (fd,
+      (rqdata,
+       fd,
        0,                            /* start sector */
        fmt_params.totl_sector_cnt,   /* sector count */
        fmt_params.bytes_per_sector,
@@ -858,27 +960,45 @@ int msdos_format
    * create master boot record 
    */
   if (ret_val == 0) {
-    ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
-  }
-  /*
-   * write master boot record to disk
-   * also write copy of MBR to disk
-   */
-  if (ret_val == 0) {
-    ret_val = msdos_format_write_sec(fd, 
-				     0, 
-				     fmt_params.bytes_per_sector,
-				     tmp_sec);
-  }
-  if ((ret_val == 0) && 
-      (fmt_params.mbr_copy_sec != 0)) {
     /*
-     * write copy of MBR
+     * Read the current MBR to obtain the partition table.
      */
-    ret_val = msdos_format_write_sec(fd, 
-				     fmt_params.mbr_copy_sec , 
-				     fmt_params.bytes_per_sector,
-				     tmp_sec);
+    msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                         "read MRB sector\n");
+    ret_val = msdos_format_read_sec(fd,
+                                    0,
+                                    fmt_params.bytes_per_sector,
+                                    tmp_sec);
+    if (ret_val == 0) {
+      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                           "generate MRB sector\n");
+      ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
+    }
+    
+    /*
+     * write master boot record to disk
+     * also write copy of MBR to disk
+     */
+    if (ret_val == 0) {
+      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                           "write MRB sector\n");
+      ret_val = msdos_format_write_sec(fd, 
+                                       0, 
+                                       fmt_params.bytes_per_sector,
+                                       tmp_sec);
+    }
+    if ((ret_val == 0) && 
+        (fmt_params.mbr_copy_sec != 0)) {
+      /*
+       * write copy of MBR
+       */
+      msdos_format_printf (rqdata, MSDOS_FMT_INFO_LEVEL_DETAIL,
+                           "write back up MRB sector\n");
+      ret_val = msdos_format_write_sec(fd, 
+                                       fmt_params.mbr_copy_sec , 
+                                       fmt_params.bytes_per_sector,
+                                       tmp_sec);
+    }
   }
   /*
    * for FAT32: initialize info sector on disk
@@ -903,7 +1023,8 @@ int msdos_format
    */
   if (ret_val == 0) {
     ret_val = msdos_format_fill_sectors
-      (fd,
+      (rqdata,
+       fd,
        fmt_params.rsvd_sector_cnt,                   /* start sector */
        fmt_params.fat_num*fmt_params.sectors_per_fat,/* sector count */
        fmt_params.bytes_per_sector,
@@ -915,7 +1036,8 @@ int msdos_format
    */
   if (ret_val == 0) {
     ret_val = msdos_format_fill_sectors
-      (fd,
+      (rqdata,
+       fd,
        fmt_params.root_dir_start_sec,        /* start sector */
        fmt_params.root_dir_fmt_sec_cnt,      /* sector count */
        fmt_params.bytes_per_sector,
Index: cpukit/libfs/src/dosfs/msdos_handlers_dir.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_handlers_dir.c,v
retrieving revision 1.4
diff -p -u -u -r1.4 msdos_handlers_dir.c
--- cpukit/libfs/src/dosfs/msdos_handlers_dir.c	27 May 2008 10:34:14 -0000	1.4
+++ cpukit/libfs/src/dosfs/msdos_handlers_dir.c	23 Apr 2009 07:54:40 -0000
@@ -26,7 +26,7 @@ const rtems_filesystem_file_handlers_r m
     NULL,             /* msdos_dir_ioctl */
     msdos_dir_lseek,
     msdos_dir_stat,
-    NULL,
+    msdos_dir_chmod,
     NULL,             /* msdos_dir_ftruncate */
     NULL,
     msdos_dir_sync,
Index: cpukit/libfs/src/dosfs/msdos_handlers_file.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_handlers_file.c,v
retrieving revision 1.4
diff -p -u -u -r1.4 msdos_handlers_file.c
--- cpukit/libfs/src/dosfs/msdos_handlers_file.c	27 May 2008 10:34:14 -0000	1.4
+++ cpukit/libfs/src/dosfs/msdos_handlers_file.c	23 Apr 2009 07:54:40 -0000
@@ -26,7 +26,7 @@ const rtems_filesystem_file_handlers_r m
     msdos_file_ioctl,
     msdos_file_lseek,
     msdos_file_stat,
-    NULL,
+    msdos_file_chmod,
     msdos_file_ftruncate,
     NULL,
     msdos_file_sync,
Index: cpukit/libfs/src/dosfs/msdos_init.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_init.c,v
retrieving revision 1.7
diff -p -u -u -r1.7 msdos_init.c
--- cpukit/libfs/src/dosfs/msdos_init.c	27 May 2008 10:34:14 -0000	1.7
+++ cpukit/libfs/src/dosfs/msdos_init.c	23 Apr 2009 07:54:40 -0000
@@ -42,7 +42,8 @@ const rtems_filesystem_operations_table 
 };
 
 /* msdos_initialize --
- *     MSDOS filesystem initialization
+ *     MSDOS filesystem initialization. Called when mounting an
+ *     MSDOS filesystem.
  *
  * PARAMETERS:
  *     temp_mt_entry - mount table entry
Index: cpukit/libfs/src/dosfs/msdos_initsupp.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_initsupp.c,v
retrieving revision 1.8
diff -p -u -u -r1.8 msdos_initsupp.c
--- cpukit/libfs/src/dosfs/msdos_initsupp.c	29 Jul 2008 02:21:14 -0000	1.8
+++ cpukit/libfs/src/dosfs/msdos_initsupp.c	23 Apr 2009 07:54:40 -0000
@@ -57,6 +57,7 @@ msdos_initialize_support(
     rtems_status_code  sc = RTEMS_SUCCESSFUL;
     msdos_fs_info_t   *fs_info = NULL;
     fat_file_fd_t     *fat_fd = NULL;
+    fat_dir_pos_t      root_pos;
     uint32_t           cl_buf_size;
 
     fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
@@ -79,7 +80,9 @@ msdos_initialize_support(
      * open fat-file which correspondes to  root directory
      * (so inode number 0x00000010 is always used for root directory)
      */
-    rc = fat_file_open(temp_mt_entry, FAT_ROOTDIR_CLUSTER_NUM, 0, &fat_fd);
+    fat_dir_pos_init(&root_pos);
+    root_pos.sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
+    rc = fat_file_open(temp_mt_entry, &root_pos, &fat_fd);
     if (rc != RC_OK)
     {
         fat_shutdown_drive(temp_mt_entry);
@@ -90,8 +93,6 @@ msdos_initialize_support(
     /* again: unfortunately "fat-file" is just almost fat file :( */
     fat_fd->fat_file_type = FAT_DIRECTORY;
     fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
-    fat_fd->info_cln = FAT_ROOTDIR_CLUSTER_NUM;
-    fat_fd->info_ofs = 0;
     fat_fd->cln = fs_info->fat.vol.rdir_cl;
 
     fat_fd->map.file_cln = 0;
Index: cpukit/libfs/src/dosfs/msdos_misc.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_misc.c,v
retrieving revision 1.14
diff -p -u -u -r1.14 msdos_misc.c
--- cpukit/libfs/src/dosfs/msdos_misc.c	4 Sep 2008 08:33:06 -0000	1.14
+++ cpukit/libfs/src/dosfs/msdos_misc.c	23 Apr 2009 07:54:40 -0000
@@ -18,6 +18,7 @@
 #endif
 
 #include <stdlib.h>
+#include <ctype.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <string.h>
@@ -30,6 +31,212 @@
 
 #include "msdos.h"
 
+
+#include <stdio.h>
+
+/*
+ * External strings. Saves spave this way.
+ */
+const char const* MSDOS_DOT_NAME    = ".          ";
+const char const* MSDOS_DOTDOT_NAME = "..         ";
+
+/* msdos_is_valid_name_char --
+ *     Routine to check the character in a file or directory name.
+ *     The characters support in the short file name are letters,
+ *     digits, or characters with code points values greater than
+ *     127 (not sure what this last is) plus the following special
+ *     characters "$%'-_@~`!(){}^#&". The must be uppercase.
+ *
+ *     The following 6 characters are allowed in a long names,
+ *     " +,;=[]" including a space and lower case letters.
+ *
+ * PARAMETERS:
+ *     ch        - character to check.
+ *
+ * RETURNS:
+ *     MSDOS_NAME_INVALID - Not valid in a long or short name.
+ *     MSDOS_NAME_SHORT   - Valid in a short name or long name.
+ *     MSDOS_NAME_LONG    - Valid in a long name only.
+ *
+ */
+static msdos_name_type_t
+msdos_is_valid_name_char(const char ch)
+{
+    if (strchr(" +,;=[]", ch) != NULL)
+        return MSDOS_NAME_LONG;
+
+    if ((ch == '.') || isalnum(ch) ||
+        (strchr("$%'-_@~`!(){}^#&", ch) != NULL))
+        return MSDOS_NAME_SHORT;
+    
+    return MSDOS_NAME_INVALID;
+}
+
+/* msdos_short_hex_number --
+ *     Routine to set the hex number in the SFN.
+ *
+ * PARAMETERS:
+ *     name      - name to change
+ *     num       - number to set
+ *
+ * RETURNS:
+ *     nothing
+ *
+ */
+static void
+msdos_short_name_hex(char* sfn, int num)
+{
+    static const char* hex = "0123456789ABCDEF";
+    char* c = MSDOS_DIR_NAME(sfn) + 3;
+    int   i;   
+    *c++ = '~';
+    for (i = 0; i < 4; i++, c++)
+      *c = hex[(num >> ((3 - i) * 4)) & 0xf];
+}
+
+/* msdos_short_random_name --
+ *     Routine to creates a random short name by changing the last 4 characters
+ *     of the name to hex digits based on the number of ticks and the checksum
+ *     short name. The checksum of the short name lets the name be different
+ *     called more than once in a single tick.
+ *
+ * PARAMETERS:
+ *     name      - name to change
+ *
+ * RETURNS:
+ *     nothing
+ *
+ */
+static void
+msdos_short_random_name(char* sfn)
+{
+    uint32_t ticks = rtems_clock_get_ticks_since_boot();
+    uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(sfn);
+    uint16_t cs = 0;
+    int      i;
+    for (i = 0; i < 11; i++, p++)
+        cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
+    ticks += cs << 8;
+    msdos_short_name_hex(sfn, ticks);
+}
+
+/* msdos_name_type --
+ *     Routine the type of file name.
+ *
+ * PARAMETERS:
+ *     name      - name to check
+ *
+ * RETURNS:
+ *     true the name is long, else the name is short.
+ *
+ */
+static msdos_name_type_t
+msdos_name_type(const char *name, int name_len)
+{
+    bool dot = false;
+    bool lowercase = false;
+    bool uppercase = false;
+    int  dot_at = 0;
+    int  count = 0;
+
+    while (*name && (count < name_len))
+    {
+        msdos_name_type_t type = msdos_is_valid_name_char(*name);
+
+        if ((type == MSDOS_NAME_INVALID) || (type == MSDOS_NAME_LONG))
+            return type;
+
+        if (dot)
+        {
+            if ((*name == '.') || ((count - dot_at) > 3))
+                return MSDOS_NAME_LONG;
+        }
+        else
+        {
+            if (count >= 8)
+                return MSDOS_NAME_LONG;
+        }
+
+        if (*name == '.')
+        {
+            dot = true;
+            dot_at = count;
+        }
+        else if ((*name >= 'A') && (*name <= 'Z'))
+            uppercase = true;
+        else if ((*name >= 'a') && (*name <= 'z'))
+            lowercase = true;
+        
+        count++;
+        name++;
+    }
+
+    if (lowercase && uppercase)
+        return MSDOS_NAME_LONG;
+    
+    return MSDOS_NAME_SHORT;
+}
+
+/* msdos_long_to_short --
+ *     Routine to creates a short name from a long. Start the end of the 
+ *
+ * PARAMETERS:
+ *     name      - name to check
+ *
+ * RETURNS:
+ *     true the name is long, else the name is short.
+ *
+ */
+msdos_name_type_t
+msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
+{
+    msdos_name_type_t type;
+    int               i;
+
+    /*
+     * Fill with spaces. This is how a short directory entry is padded.
+     */
+    memset (sfn, ' ', sfn_len);
+
+    /*
+     * Handle '.' and '..' specially.
+     */
+    if ((lfn[0] == '.') && (lfn_len == 1))
+    {
+        sfn[0] = '.';
+        return MSDOS_NAME_SHORT;
+    }
+        
+    if ((lfn[0] == '.') && (lfn[1] == '.') && (lfn_len == 2))
+    {
+        sfn[0] = sfn[1] = '.';
+        return MSDOS_NAME_SHORT;
+    }
+
+    /*
+     * Filenames with only blanks and dots are not allowed!
+     */
+    for (i = 0; i < lfn_len; i++)
+        if ((lfn[i] != ' ') && (lfn[i] == '.'))
+            break;
+
+    if (i > lfn_len)
+        return MSDOS_NAME_INVALID;
+
+    /*
+     * Is this a short name ?
+     */
+    
+    type = msdos_name_type (lfn, lfn_len);
+
+    if (type == MSDOS_NAME_INVALID)
+        return MSDOS_NAME_INVALID;
+    
+    msdos_filename_unix2dos (lfn, lfn_len, sfn);
+    
+    return type;
+}
+
 /* msdos_get_token --
  *     Routine to get a token (name or separator) from the path.
  *
@@ -43,35 +250,34 @@
  *
  */
 msdos_token_types_t
-msdos_get_token(const char *path, char *ret_token, int *token_len)
+msdos_get_token(const char *path, const char **ret_token, int *ret_token_len)
 {
-    int                 rc = RC_OK;
-    register int        i = 0;
     msdos_token_types_t type = MSDOS_NAME;
-    char                token[MSDOS_NAME_MAX_WITH_DOT+1];
-    register char       c;
+    int                 i = 0;
+
+    *ret_token = NULL;
+    *ret_token_len = 0;
 
     /*
-     *  Copy a name into token.  (Remember NULL is a token.)
+     *  Check for a separator.
      */
-    c = path[i];
-    while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )
+    while (!msdos_is_separator(path[i]))
     {
-        token[i] = c;
-        if ( i == MSDOS_NAME_MAX_WITH_DOT )
+        if ( !msdos_is_valid_name_char(path[i]) )
             return MSDOS_INVALID_TOKEN;
-        if ( !msdos_is_valid_name_char(c) )
+        ++i;
+        if ( i == MSDOS_NAME_MAX_LFN_WITH_DOT )
             return MSDOS_INVALID_TOKEN;
-        c = path [++i];
     }
 
+    *ret_token = path;
+    
     /*
-     *  Copy a seperator into token.
+     *  If it is just a separator then it is the current dir.
      */
     if ( i == 0 )
     {
-        token[i] = c;
-        if ( token[i] != '\0' )
+        if ( *path != '\0' )
         {
             i++;
             type = MSDOS_CURRENT_DIR;
@@ -79,13 +285,11 @@ msdos_get_token(const char *path, char *
         else
             type = MSDOS_NO_MORE_PATH;
     }
-    else if (token[ i-1 ] != '\0')
-        token[i] = '\0';
 
     /*
-     *  Set token_len to the number of characters copied.
+     *  Set the token and token_len to the token start and length.
      */
-    *token_len = i;
+    *ret_token_len = i;
 
     /*
      *  If we copied something that was not a seperator see if
@@ -93,25 +297,19 @@ msdos_get_token(const char *path, char *
      */
     if ( type == MSDOS_NAME )
     {
-        if ( strcmp( token, "..") == 0 )
+        if ((i == 2) && ((*ret_token)[0] == '.') && ((*ret_token)[1] == '.'))
         {
-            strcpy(ret_token, MSDOS_DOTDOT_NAME);
             type = MSDOS_UP_DIR;
             return type;
         }
 
-        if ( strcmp( token, "." ) == 0 )
+        if ((i == 1) && ((*ret_token)[0] == '.'))
         {
-            strcpy(ret_token, MSDOS_DOT_NAME);
             type = MSDOS_CURRENT_DIR;
             return type;
         }
-
-        rc = msdos_filename_unix2dos(token, *token_len, ret_token);
-        if ( rc != RC_OK )
-            return MSDOS_INVALID_TOKEN;
     }
-    ret_token[MSDOS_NAME_MAX] = '\0';
+
     return type;
 }
 
@@ -133,50 +331,61 @@ msdos_get_token(const char *path, char *
 int
 msdos_find_name(
     rtems_filesystem_location_info_t *parent_loc,
-    char                             *name
+    const char                       *name,
+    int                               name_len
     )
 {
-    int              rc = RC_OK;
-    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
-    fat_file_fd_t   *fat_fd = NULL;
-    fat_auxiliary_t  aux;
-    unsigned short   time_val = 0;
-    unsigned short   date = 0;
-    char             node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+    int                rc = RC_OK;
+    msdos_fs_info_t   *fs_info = parent_loc->mt_entry->fs_info;
+    fat_file_fd_t     *fat_fd = NULL;
+    msdos_name_type_t  name_type;
+    fat_dir_pos_t      dir_pos;
+    unsigned short     time_val = 0;
+    unsigned short     date = 0;
+    char               node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
 
     memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
 
+    name_type = msdos_long_to_short (name,
+                                     name_len,
+                                     MSDOS_DIR_NAME(node_entry),
+                                     MSDOS_NAME_MAX);
+
     /*
      * find the node which correspondes to the name in the directory pointed by
      * 'parent_loc'
      */
-    rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);
+    rc = msdos_get_name_node(parent_loc, false, name, name_len, name_type,
+                             &dir_pos, node_entry);
     if (rc != RC_OK)
         return rc;
 
+    if (((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_VOLUME_ID) ||
+        ((*MSDOS_DIR_ATTR(node_entry) & MSDOS_ATTR_LFN_MASK) == MSDOS_ATTR_LFN))
+        return MSDOS_NAME_NOT_FOUND_ERR;
+
     /* open fat-file corresponded to the found node */
-    rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+    rc = fat_file_open(parent_loc->mt_entry, &dir_pos, &fat_fd);
     if (rc != RC_OK)
         return rc;
 
+    fat_fd->dir_pos = dir_pos;
+    
     /*
-     * I don't like this if, but: we should do it , or should write new file
+     * I don't like this if, but: we should do it, or should write new file
      * size and first cluster num to the disk after each write operation
-     * (even if one byte is written  - that is TOO non-optimize) because
+     * (even if one byte is written  - that is TOO slow) because
      * otherwise real values of these fields stored in fat-file descriptor
-     * may be accidentely rewritten with wrong values stored on the disk
+     * may be accidentally rewritten with wrong values stored on the disk
      */
     if (fat_fd->links_num == 1)
     {
-        fat_fd->info_cln = aux.cln;
-        fat_fd->info_ofs = aux.ofs;
         fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);
-        fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);
 
         time_val = *MSDOS_DIR_WRITE_TIME(node_entry);
         date = *MSDOS_DIR_WRITE_DATE(node_entry);
 
-        fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));
+        fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(date), CF_LE_W(time_val));
 
         if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
         {
@@ -227,7 +436,7 @@ msdos_find_name(
 }
 
 /* msdos_get_name_node --
- *     This routine is used in two ways: for a new mode creation (a) or for
+ *     This routine is used in two ways: for a new node creation (a) or for
  *     search the node which correspondes to the name parameter (b).
  *     In case (a) 'name' should be set up to NULL and 'name_dir_entry' should
  *     point to initialized 32 bytes structure described a new node.
@@ -247,7 +456,7 @@ msdos_find_name(
  *     name           - NULL or name to find
  *     paux           - identify a node location on the disk -
  *                      cluster num and offset inside the cluster
- *     name_dir_entry - node to create/placeholder for found node (IN/OUT)
+ *     short_dir_entry - node to create/placeholder for found node (IN/OUT)
  *
  * RETURNS:
  *     RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if
@@ -257,90 +466,63 @@ msdos_find_name(
 int
 msdos_get_name_node(
     rtems_filesystem_location_info_t *parent_loc,
-    char                             *name,
-    fat_auxiliary_t                  *paux,
+    bool                              create_node,
+    const char                       *name,
+    int                               name_len,
+    msdos_name_type_t                 name_type,
+    fat_dir_pos_t                    *dir_pos,
     char                             *name_dir_entry
     )
 {
     int              rc = RC_OK;
-    ssize_t          ret = 0;
-    msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
     fat_file_fd_t   *fat_fd = parent_loc->node_access;
     uint32_t         dotdot_cln = 0;
 
-    /* find name in fat-file which correspondes to the directory */
-    rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,
-                                     name_dir_entry);
+    /* find name in fat-file which corresponds to the directory */
+    rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd,
+                                     create_node, name, name_len, name_type,
+                                     dir_pos, name_dir_entry);
     if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
         return rc;
 
-    /* if we search for valid name and name not found -> return */
-    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))
-        return rc;
-
-    /*
-     * if we try to create new entry and the directory is not big enough
-     * currently - try to enlarge directory
-     */
-    if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))
+    if (!create_node)
     {
-        ret = fat_file_write(parent_loc->mt_entry, fat_fd,
-                             fat_fd->fat_file_size,
-                             MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
-                             (uint8_t *)name_dir_entry);
-        if (ret == -1)
-            return -1;
-
-        /* on success directory is enlarged by a new cluster */
-        fat_fd->fat_file_size += fs_info->fat.vol.bpc;
-
-        /* get cluster num where a new node located */
-        rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,
-                            fat_fd->fat_file_size - 1, &paux->cln);
-
-        if (rc != RC_OK)
+        /* if we search for valid name and name not found -> return */
+        if (rc == MSDOS_NAME_NOT_FOUND_ERR)
             return rc;
 
         /*
-         * if new cluster allocated succesfully then new node is at very
-         * beginning of the cluster (offset is computed in bytes)
+         * if we have deal with ".." - it is a special case :(((
+         *
+         * Really, we should return cluster num and offset not of ".." slot, but
+         * slot which correspondes to real directory name.
          */
-        paux->ofs = 0;
-        return RC_OK;
-    }
-
-    /*
-     * if we have deal with ".." - it is a special case :(((
-     *
-     * Really, we should return cluster num and offset not of ".." slot, but
-     * slot which correspondes to real directory name.
-     */
-    if ((rc == RC_OK) && (name != NULL))
-    {
-        if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)
+        if (rc == RC_OK)
         {
-            dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
-
-            /* are we right under root dir ? */
-            if (dotdot_cln == 0)
+            if (strncmp(name, "..", 2) == 0)
             {
-                /*
-                 * we can relax about first_char field - it never should be
-                 * used for root dir
-                 */
-                paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
-                paux->ofs = 0;
-            }
-            else
-            {
-                rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(
-                        parent_loc->mt_entry,
-                        dotdot_cln,
-                        paux,
-                        name_dir_entry
-                        );
-                if (rc != RC_OK)
-                    return rc;
+                dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
+
+                /* are we right under root dir ? */
+                if (dotdot_cln == 0)
+                {
+                    /*
+                     * we can relax about first_char field - it never should be
+                     * used for root dir
+                     */
+                    fat_dir_pos_init(dir_pos);
+                    dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
+                }
+                else
+                {
+                    rc =
+                        msdos_get_dotdot_dir_info_cluster_num_and_offset(parent_loc->mt_entry,
+                                                                         dotdot_cln,
+                                                                         dir_pos,
+                                                                         name_dir_entry);
+                    if (rc != RC_OK)
+                        return rc;
+                }
             }
         }
     }
@@ -380,7 +562,7 @@ int
 msdos_get_dotdot_dir_info_cluster_num_and_offset(
     rtems_filesystem_mount_table_entry_t *mt_entry,
     uint32_t                              cln,
-    fat_auxiliary_t                      *paux,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *dir_entry
     )
 {
@@ -391,18 +573,13 @@ msdos_get_dotdot_dir_info_cluster_num_an
     char             dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
     uint32_t         cl4find = 0;
 
-    memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
-    memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
-
     /*
      * open fat-file corresponded to ".."
      */
-    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+    rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
     if (rc != RC_OK)
         return rc;
 
-    fat_fd->info_cln = paux->cln;
-    fat_fd->info_ofs = paux->ofs;
     fat_fd->cln = cln;
     fat_fd->fat_file_type = FAT_DIRECTORY;
     fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
@@ -418,8 +595,10 @@ msdos_get_dotdot_dir_info_cluster_num_an
     }
 
     /* find "." node in opened directory */
-    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,
-                                     dot_node);
+    memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+    msdos_long_to_short(".", 1, dot_node, MSDOS_SHORT_NAME_LEN);
+    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, ".", 1,
+                                     MSDOS_NAME_SHORT, dir_pos, dot_node);
 
     if (rc != RC_OK)
     {
@@ -428,7 +607,10 @@ msdos_get_dotdot_dir_info_cluster_num_an
     }
 
     /* find ".." node in opened directory */
-    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,
+    memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+    msdos_long_to_short("..", 2, dotdot_node, MSDOS_SHORT_NAME_LEN);
+    rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, "..", 2,
+                                     MSDOS_NAME_SHORT, dir_pos,
                                      dotdot_node);
 
     if (rc != RC_OK)
@@ -450,18 +632,15 @@ msdos_get_dotdot_dir_info_cluster_num_an
          * we handle root dir for all FAT types in the same way with the
          * ordinary directories ( through fat_file_* calls )
          */
-        paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
-        paux->ofs = 0;
+        fat_dir_pos_init(dir_pos);
+        dir_pos->sname.cln = FAT_ROOTDIR_CLUSTER_NUM;
     }
 
     /* open fat-file corresponded to second ".." */
-    rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+    rc = fat_file_open(mt_entry, dir_pos, &fat_fd);
     if (rc != RC_OK)
         return rc;
 
-    fat_fd->info_cln = paux->cln;
-    fat_fd->info_ofs = paux->ofs;
-
     if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
         fat_fd->cln = fs_info->fat.vol.rdir_cl;
     else
@@ -482,7 +661,7 @@ msdos_get_dotdot_dir_info_cluster_num_an
 
     /* in this directory find slot with specified cluster num */
     rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find,
-                                                    paux, dir_entry);
+                                                    dir_pos, dir_entry);
     if (rc != RC_OK)
     {
         fat_file_close(mt_entry, fat_fd);
@@ -518,16 +697,16 @@ msdos_set_dir_wrt_time_and_date(
     uint32_t         sec = 0;
     uint32_t         byte = 0;
 
-    msdos_date_unix2dos(fat_fd->mtime, &time_val, &date);
+    msdos_date_unix2dos(fat_fd->mtime, &date, &time_val);
 
     /*
      * calculate input for _fat_block_write: convert (cluster num, offset) to
      * (sector num, new offset)
      */
-    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
-    sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
     /* byte points to start of 32bytes structure */
-    byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+    byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
 
     time_val = CT_LE_W(time_val);
     ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WTIME_OFFSET,
@@ -572,10 +751,10 @@ msdos_set_first_cluster_num(
      * calculate input for _fat_block_write: convert (cluster num, offset) to
      * (sector num, new offset)
      */
-    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
-    sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
     /* byte from points to start of 32bytes structure */
-    byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+    byte = fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1);
 
     le_cl_low = CT_LE_W((uint16_t  )(new_cln & 0x0000FFFF));
     ret1 = _fat_block_write(mt_entry, sec,
@@ -615,9 +794,9 @@ msdos_set_file_size(
     uint32_t         sec = 0;
     uint32_t         byte = 0;
 
-    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
-    sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
-    byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+    sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->dir_pos.sname.cln);
+    sec += (fat_fd->dir_pos.sname.ofs >> fs_info->fat.vol.sec_log2);
+    byte = (fat_fd->dir_pos.sname.ofs & (fs_info->fat.vol.bps - 1));
 
     le_new_length = CT_LE_L((fat_fd->fat_file_size));
     ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4,
@@ -650,25 +829,58 @@ msdos_set_file_size(
 int
 msdos_set_first_char4file_name(
     rtems_filesystem_mount_table_entry_t *mt_entry,
-    uint32_t                              cl,
-    uint32_t                              ofs,
+    fat_dir_pos_t                        *dir_pos,
     unsigned char                         fchar
     )
 {
-    ssize_t          ret = 0;
+    ssize_t          ret;
     msdos_fs_info_t *fs_info = mt_entry->fs_info;
-    uint32_t         sec = 0;
-    uint32_t         byte = 0;
+    uint32_t         dir_block_size;
+    fat_pos_t        start = dir_pos->lname;
+    fat_pos_t        end = dir_pos->sname;
+
+    if ((end.cln == fs_info->fat.vol.rdir_cl) &&
+        (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+      dir_block_size = fs_info->fat.vol.rdir_size;
+    else
+      dir_block_size = fs_info->fat.vol.bpc;
+    
+    if (dir_pos->lname.cln == FAT_FILE_SHORT_NAME)
+      start = dir_pos->sname;
 
-    sec = fat_cluster_num_to_sector_num(mt_entry, cl);
-    sec += (ofs >> fs_info->fat.vol.sec_log2);
-    byte = (ofs & (fs_info->fat.vol.bps - 1));
-
-    ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
-                           &fchar);
-    if ( ret < 0)
+    /*
+     * We handle the changes directly due the way the short file
+     * name code was written rather than use the fat_file_write
+     * interface.
+     */
+    while (true)
+    {
+      uint32_t sec = (fat_cluster_num_to_sector_num(mt_entry, start.cln) +
+                      (start.ofs >> fs_info->fat.vol.sec_log2));
+      uint32_t byte = (start.ofs & (fs_info->fat.vol.bps - 1));;
+
+      ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
+                             &fchar);
+      if (ret < 0)
         return -1;
 
+      if ((start.cln == end.cln) && (start.ofs == end.ofs))
+        break;
+
+      start.ofs += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+      if (start.ofs >= dir_block_size)
+      {
+        int rc;
+        if ((end.cln == fs_info->fat.vol.rdir_cl) &&
+            (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+          break;
+        rc = fat_get_fat_cluster(mt_entry, start.cln, &start.cln);
+        if ( rc != RC_OK )
+          return rc;
+        start.ofs = 0;
+      }
+    }
+
     return  RC_OK;
 }
 
@@ -713,21 +925,39 @@ msdos_dir_is_empty(
              i < fs_info->fat.vol.bps;
              i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
         {
-            if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+            char* entry = (char*) fs_info->cl_buf + i;
+
+            /*
+             * If the entry is empty, a long file name entry, or '.' or '..'
+             * then consider it as empty.
+             *
+             * Just ignore long file name entries. They must have a short entry to
+             * be valid.
+             */
+            if (((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
                  MSDOS_THIS_DIR_ENTRY_EMPTY) ||
-                (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), MSDOS_DOT_NAME,
+                ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+                 MSDOS_ATTR_LFN) ||
+                (strncmp(MSDOS_DIR_NAME((entry)), MSDOS_DOT_NAME,
                          MSDOS_SHORT_NAME_LEN) == 0) ||
-                (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)),
+                (strncmp(MSDOS_DIR_NAME((entry)),
                          MSDOS_DOTDOT_NAME,
                          MSDOS_SHORT_NAME_LEN) == 0))
                 continue;
 
-            if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+            /*
+             * Nothing more to look at.
+             */
+            if ((*MSDOS_DIR_NAME(entry)) ==
                 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
             {
                 *ret_val = true;
                 return RC_OK;
             }
+
+            /*
+             * Short file name entries mean not empty.
+             */
             return RC_OK;
         }
         j++;
@@ -736,20 +966,15 @@ msdos_dir_is_empty(
     return RC_OK;
 }
 
-
-/* msdos_find_name_in_fat_file --
- *     This routine is used in two ways: for a new mode creation (a) or for
- *     search the node which correspondes to the 'name' parameter (b).
- *     In case (a) name should be set up to NULL and 'name_dir_entry' should
- *     point to initialized 32 bytes structure described a new node.
- *     In case (b) 'name' should contain a valid string.
- *
- *     (a): reading fat-file corresponded to directory we are going to create
- *          node in. If found free slot write contents of name_dir_entry into
- *          it.
- *
- *     (b): reading fat-file corresponded to directory and trying to find slot
- *          with the name field == name parameter
+/* msdos_create_name_in_fat_file --
+ *     This routine creates an entry in the fat file for the file name
+ *     provided by the user. The directory entry passed is the short
+ *     file name and is added as it. If the file name is long a long
+ *     file name set of entries is added.
+ *
+ *     Scan the directory for the file and if not found add the new entry.
+ *     When scanning remember the offset in the file where the directory
+ *     entry can be added.
  *
  * PARAMETERS:
  *     mt_entry       - mount table entry
@@ -764,111 +989,621 @@ msdos_dir_is_empty(
  *     appropriately)
  *
  */
+#define MSDOS_FIND_PRINT 0
 int msdos_find_name_in_fat_file(
     rtems_filesystem_mount_table_entry_t *mt_entry,
     fat_file_fd_t                        *fat_fd,
-    char                                 *name,
-    fat_auxiliary_t                      *paux,
+    bool                                  create_node,
+    const char                           *name,
+    int                                   name_len,
+    msdos_name_type_t                     name_type,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *name_dir_entry
-    )
+                                )
 {
-    int              rc = RC_OK;
     ssize_t          ret = 0;
     msdos_fs_info_t *fs_info = mt_entry->fs_info;
-    uint32_t         i = 0, j = 0;
+    uint32_t         dir_offset = 0;
+    uint32_t         dir_entry = 0;
     uint32_t         bts2rd = 0;
+    fat_pos_t        lfn_start;
+    bool             lfn_matched = false;
+    uint8_t          lfn_checksum = 0;
+    int              lfn_entries = 0;
+    int              lfn_entry = 0;
+    uint32_t         empty_space_offset = 0;
+    uint32_t         empty_space_entry = 0;
+    uint32_t         empty_space_count = 0;
+    bool             empty_space_found = false;
+    uint32_t         entries_per_block;
+    bool             read_cluster = false;
+
+    assert(name_len > 0);
+
+    fat_dir_pos_init(dir_pos);
+    
+    lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+    
+    /*
+     * If the file name is long how many short directory
+     * entries are needed ?
+     */
+    if (name_type == MSDOS_NAME_LONG)
+    {
+        lfn_entries = ((name_len - 1) + MSDOS_LFN_LEN_PER_ENTRY) / MSDOS_LFN_LEN_PER_ENTRY;
 
+        /*
+         * If we are creating a long file name node create a random short
+         * entry for the long file name. Ignore the MSDOS version as that
+         * requires too much processing to find and handle the next number.
+         */
+        if (create_node)
+            msdos_short_random_name(MSDOS_DIR_NAME(name_dir_entry));
+    }
+            
     if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
-       (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+        (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
         bts2rd = fat_fd->fat_file_size;
     else
         bts2rd = fs_info->fat.vol.bpc;
 
-    while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd,
-                                fs_info->cl_buf)) != FAT_EOF)
+    entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+
+#if MSDOS_FIND_PRINT
+    printf ("MSFS:[1] cn:%i ebp:%li bts2rd:%li lfne:%d nl:%i n:%s\n",
+            create_node, entries_per_block, bts2rd, lfn_entries, name_len, name);
+#endif
+    /*
+     * Scan the directory seeing if the file is present. While
+     * doing this see if a suitable location can be found to
+     * create the entry if the name is not found.
+     */
+    while ((ret = fat_file_read(mt_entry, fat_fd, (dir_offset * bts2rd),
+                                bts2rd, fs_info->cl_buf)) != FAT_EOF)
     {
+        bool remainder_empty = false;
+#if MSDOS_FIND_PRINT
+        printf ("MSFS:[2] dir_offset:%li\n", dir_offset);
+#endif
+        
         if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
             rtems_set_errno_and_return_minus_one(EIO);
 
         assert(ret == bts2rd);
 
         /* have to look at the DIR_NAME as "raw" 8-bit data */
-        for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+        for (dir_entry = 0;
+             dir_entry < bts2rd;
+             dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
         {
-            /* is the entry empty ? */
-            if (((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
-                 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) ||
-                 ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
-                 MSDOS_THIS_DIR_ENTRY_EMPTY))
-            {
-                /* whether we are looking for an empty entry */
-                if (name == NULL)
-                {
-                    /* get current cluster number */
-                    rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
-                                        j * bts2rd, &paux->cln);
-                    if (rc != RC_OK)
-                        return rc;
-
-                    /* offset is computed in bytes */
-                    paux->ofs = i;
+            char* entry = (char*) fs_info->cl_buf + dir_entry;
 
-                    /* write new node entry */
-                    ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i,
-                                         MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
-                                         (uint8_t *)name_dir_entry);
-                    if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
-                        return -1;
-
-                    /*
-                     * we don't update fat_file_size here - it should not
-                     * increase
-                     */
-                    return RC_OK;
-                }
+            /*
+             * See if the entry is empty or the remainder of the directory is
+             * empty ? Localise to make the code read better.
+             */
+            bool entry_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
+                                MSDOS_THIS_DIR_ENTRY_EMPTY);
+            remainder_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
+                               MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY);
+#if MSDOS_FIND_PRINT
+            printf ("MSFS:[3] re:%i ee:%i do:%li de:%li(%ld)\n",
+                    remainder_empty, entry_empty, dir_offset,
+                    dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE));
+#endif
+            /*
+             * Remember where the we are, ie the start, so we can come back
+             * to here and write the long file name if this is the start of
+             * a series of empty entries. If empty_space_count is 0 then
+             * we are currently not inside an empty series of entries. It
+             * is a count of empty entries.
+             */
+            if (empty_space_count == 0)
+            {
+                empty_space_entry = dir_entry;
+                empty_space_offset = dir_offset;
+            }
 
+            if (remainder_empty)
+            {
+#if MSDOS_FIND_PRINT
+                printf ("MSFS:[3.1] cn:%i esf:%i\n", create_node, empty_space_found);
+#endif
                 /*
-                 * if name != NULL and there is no more entries in the
+                 * If just looking and there is no more entries in the
                  * directory - return name-not-found
                  */
-                if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
-                     MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY))
+                if (!create_node)
                     return MSDOS_NAME_NOT_FOUND_ERR;
+
+                /*
+                 * Lets go and write the directory entries. If we have not found
+                 * any available space add the remaining number of entries to any that
+                 * we may have already found that are just before this entry. If more
+                 * are needed FAT_EOF is returned by the read and we extend the file.
+                 */
+                if (!empty_space_found)
+                {
+                  empty_space_count +=
+                    entries_per_block - (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+                  empty_space_found = true;
+#if MSDOS_FIND_PRINT
+                  printf ("MSFS:[3.2] esf:%i esc%i\n", empty_space_found, empty_space_count);
+#endif
+                }
+                break;
+            }
+            else if (entry_empty)
+            {
+                if (create_node)
+                {
+                  /*
+                   * Remainder is not empty so is this entry empty ?
+                   */
+                  empty_space_count++;
+                
+                  if (empty_space_count == (lfn_entries + 1))
+                    empty_space_found = true;
+                }
+#if MSDOS_FIND_PRINT
+                printf ("MSFS:[4.1] esc:%li esf:%i\n",
+                        empty_space_count, empty_space_found);
+#endif
             }
             else
             {
-                /* entry not empty and name != NULL -> compare names */
-                if (name != NULL)
+                /*
+                 * A valid entry so handle it.
+                 *
+                 * If empty space has not been found we need to start the
+                 * count again.
+                 */
+                if (create_node && !empty_space_found)
                 {
-                    if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name,
-                                MSDOS_SHORT_NAME_LEN) == 0)
+                    empty_space_entry = 0;
+                    empty_space_count = 0;
+                }
+
+                /*
+                 * Check the attribute to see if the entry is for a long
+                 * file name.
+                 */
+                if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
+                    MSDOS_ATTR_LFN)
+                {
+                    char* p;
+                    int   o;
+                    int   i;
+#if MSDOS_FIND_PRINT
+                    printf ("MSFS:[4.2] lfn:%c entry:%i checksum:%i\n",
+                            lfn_start.cln == FAT_FILE_SHORT_NAME ? 't' : 'f',
+                            *MSDOS_DIR_ENTRY_TYPE(entry) & MSDOS_LAST_LONG_ENTRY_MASK,
+                            *MSDOS_DIR_LFN_CHECKSUM(entry));
+#endif
+                    /*
+                     * If we are not already processing a LFN see if this is
+                     * the first entry of a LFN ?
+                     */
+                    if (lfn_start.cln == FAT_FILE_SHORT_NAME)
                     {
+                        lfn_matched = false;
+
                         /*
-                         * we get the entry we looked for - fill auxiliary
-                         * structure and copy all 32 bytes of the entry
+                         * The first entry must have the last long entry
+                         * flag set.
                          */
-                        rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
-                                            j * bts2rd, &paux->cln);
+                        if ((*MSDOS_DIR_ENTRY_TYPE(entry) &
+                             MSDOS_LAST_LONG_ENTRY) == 0)
+                            continue;
+
+                        /*
+                         * Does the number of entries in the LFN directory
+                         * entry match the number we expect for this
+                         * file name.
+                         */
+                        if (lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+                                            MSDOS_LAST_LONG_ENTRY_MASK))
+                            continue;
+                        
+                        /*
+                         * Get the checksum of the short entry.
+                         */
+                        lfn_start.cln = dir_offset;
+                        lfn_start.ofs = dir_entry;
+                        lfn_entry = lfn_entries;
+                        lfn_checksum = *MSDOS_DIR_LFN_CHECKSUM(entry);
+                        
+#if MSDOS_FIND_PRINT
+                        printf ("MSFS:[4.3] lfn_checksum:%i\n",
+                                *MSDOS_DIR_LFN_CHECKSUM(entry));
+#endif
+                    }
+
+                    /*
+                     * If the entry number or the check sum do not match
+                     * forget this series of long directory entries. These
+                     * could be orphaned entries depending on the history
+                     * of the disk.
+                     */
+                    if ((lfn_entry != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+                                       MSDOS_LAST_LONG_ENTRY_MASK)) ||
+                        (lfn_checksum != *MSDOS_DIR_LFN_CHECKSUM(entry)))
+                    {
+#if MSDOS_FIND_PRINT
+                        printf ("MSFS:[4.4] no match\n");
+#endif
+                        lfn_start.cln = FAT_FILE_SHORT_NAME;
+                        continue;
+                    }
+
+                    lfn_entry--;
+                    o = lfn_entry * MSDOS_LFN_LEN_PER_ENTRY;
+                    p = entry + 1;
+                        
+#if MSDOS_FIND_PRINT
+                    printf ("MSFS:[5] lfne:%i\n", lfn_entry);
+#endif
+                    for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
+                    {
+#if MSDOS_FIND_PRINT > 1
+                        printf ("MSFS:[6] o:%i i:%i *p:%c(%02x) name[o + i]:%c(%02x)\n",
+                                o, i, *p, *p, name[o + i], name[o + i]);
+#endif
+                        if (*p == '\0')
+                            break;
+                        
+                        if (((o + i) >= name_len) || (*p != name[o + i]))
+                        {
+                            lfn_start.cln = FAT_FILE_SHORT_NAME;
+#if MSDOS_FIND_PRINT
+                            printf ("MSFS:[8] lfn:%c\n",
+                                    lfn_start.cln == FAT_FILE_SHORT_NAME ? 't' : 'f');
+#endif
+                            break;
+                        }
+
+                        switch (i)
+                        {
+                            case 4:
+                                p += 5;
+                                break;
+                            case 10:
+                                p += 4;
+                                break;
+                            default:
+                                p += 2;
+                                break;
+                        }
+                    }
+
+                    lfn_matched = ((lfn_entry == 0) &&
+                                   (lfn_start.cln != FAT_FILE_SHORT_NAME));
+                    
+#if MSDOS_FIND_PRINT
+                    printf ("MSFS:[8.1] lfn_matched:%i\n", lfn_matched);
+#endif
+                }
+                else
+                {
+                    /*
+                     * SFN entry found.
+                     *
+                     * If a LFN has been found and it matched check the
+                     * entries have all been found and the checksum is
+                     * correct. If this is the case return the short file
+                     * name entry.
+                     */
+                    if (lfn_matched)
+                    {
+                        uint8_t  cs = 0;
+                        uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(entry);
+                        int      i;
+
+                        for (i = 0; i < MSDOS_SHORT_NAME_LEN; i++, p++)
+                            cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
+
+                        if (lfn_entry || (lfn_checksum != cs))
+                            lfn_matched = false;
+                    }
+#if 0
+                    /*
+                     * If we are creating a node and so have generated a
+                     * random SFN we need to make sure it is not alreay
+                     * present in the directory.
+                     */
+                    if (!lfn_matched &&
+                        create_node &&
+                        (name_type == MSDOS_NAME_LONG) &&
+                        (memcmp(MSDOS_DIR_NAME(entry),
+                                MSDOS_DIR_NAME(name_dir_entry),
+                                MSDOS_SHORT_NAME_LEN) == 0))
+                    {
+                        /*
+                         * FIXME: This should cause a rescan of all entries.
+                         */
+                        msdos_short_random_name(MSDOS_DIR_NAME(name_dir_entry));
+                    }
+#endif
+                    if (lfn_matched ||
+                        (memcmp(MSDOS_DIR_NAME(entry),
+                                MSDOS_DIR_NAME(name_dir_entry),
+                                MSDOS_SHORT_NAME_LEN) == 0))
+                    {
+                        /*
+                         * We get the entry we looked for - fill the position
+                         * structure and the 32 bytes of the short entry
+                         */
+                        int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+                                                dir_offset * bts2rd,
+                                                &dir_pos->sname.cln);
                         if (rc != RC_OK)
                             return rc;
 
-                        /* offset is computed in bytes */
-                        paux->ofs = i;
-                        memcpy(name_dir_entry,(fs_info->cl_buf + i),
+                        dir_pos->sname.ofs = dir_entry;
+                        
+                        if (lfn_start.cln != FAT_FILE_SHORT_NAME)
+                        {
+                          rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+                                              lfn_start.cln * bts2rd,
+                                              &lfn_start.cln);
+                          if (rc != RC_OK)
+                            return rc;
+                        }
+                
+                        dir_pos->lname.cln = lfn_start.cln;
+                        dir_pos->lname.ofs = lfn_start.ofs;
+
+                        memcpy(name_dir_entry, entry,
                                MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
                         return RC_OK;
                     }
+                    
+                    lfn_start.cln = FAT_FILE_SHORT_NAME;
+                    lfn_matched = false;
                 }
             }
         }
-        j++;
+
+        if (remainder_empty)
+            break;
+
+        dir_offset++;
     }
-    return MSDOS_NAME_NOT_FOUND_ERR;
+
+    /*
+     * If we are not to create the entry return a not found error.
+     */
+    if (!create_node)
+      return MSDOS_NAME_NOT_FOUND_ERR;
+
+#if MSDOS_FIND_PRINT
+    printf ("MSFS:[8.1] WRITE do:%ld esc:%ld eso:%ld ese:%ld\n",
+            dir_offset, empty_space_count, empty_space_offset, empty_space_entry);
+#endif
+
+    /*
+     * If a long file name calculate the checksum of the short file name
+     * data to place in each long file name entry. First set the short
+     * file name to the slot of the SFN entry. This will mean no clashes
+     * in this directory.
+     */
+    lfn_checksum = 0;
+    if (name_type == MSDOS_NAME_LONG)
+    {
+        uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(name_dir_entry);
+        int      i;
+        int      slot = (((empty_space_offset * bts2rd) + empty_space_entry) /
+                         MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) + lfn_entries + 1;
+                  
+        msdos_short_name_hex(MSDOS_DIR_NAME(name_dir_entry), slot);
+
+        for (i = 0; i < 11; i++, p++)
+            lfn_checksum =
+                ((lfn_checksum & 1) ? 0x80 : 0) + (lfn_checksum >> 1) + *p;
+    }
+
+    /*
+     * If there is no space available then extend the file. The
+     * empty_space_count is a count of empty entries in the currently
+     * read cluster so if 0 there is no space. Note, dir_offset will
+     * be at the next cluster so we can just make empty_space_offset
+     * that value.
+     */
+    if (empty_space_count == 0)
+    {
+        read_cluster = true;
+        empty_space_offset = dir_offset;
+        empty_space_entry = 0;
+    }
+
+    /*
+     * Have we read past the empty block ? If so go back and read it again.
+     */
+    if (dir_offset != empty_space_offset)
+        read_cluster = true;
+
+    /*
+     * Handle the entry writes.
+     */
+    lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+    lfn_entry = 0;
+
+#if MSDOS_FIND_PRINT
+    printf ("MSFS:[9] read_cluster:%d eso:%ld ese:%ld\n",
+            read_cluster, empty_space_offset, empty_space_entry);
+#endif
+
+    /*
+     * The one more is the short entry.
+     */
+    while (lfn_entry < (lfn_entries + 1))
+    {
+        int length = 0;
+        
+        if (read_cluster)
+        {
+          uint32_t new_length;
+#if MSDOS_FIND_PRINT
+          printf ("MSFS:[9.1] eso:%li\n", empty_space_offset);
+#endif
+          ret = fat_file_read(mt_entry, fat_fd,
+                              (empty_space_offset * bts2rd), bts2rd,
+                              fs_info->cl_buf);
+
+          if (ret != bts2rd)
+          {
+            if (ret != FAT_EOF)
+              rtems_set_errno_and_return_minus_one(EIO);
+
+#if MSDOS_FIND_PRINT
+            printf ("MSFS:[9.2] extending file:%li\n", empty_space_offset);
+#endif
+            ret = fat_file_extend (mt_entry, fat_fd, empty_space_offset * bts2rd,
+                                   &new_length);
+                                           
+            if (ret != RC_OK)
+              return ret;
+
+#if MSDOS_FIND_PRINT
+            printf ("MSFS:[9.3] extended: %d <-> %d\n", new_length, empty_space_offset * bts2rd);
+#endif
+            if (new_length != (empty_space_offset * bts2rd))
+              rtems_set_errno_and_return_minus_one(EIO);
+
+            memset(fs_info->cl_buf, 0, bts2rd);
+
+            ret = fat_file_write(mt_entry, fat_fd,
+                                 empty_space_offset * bts2rd,
+                                 bts2rd, fs_info->cl_buf);
+#if MSDOS_FIND_PRINT
+            printf ("MSFS:[9.4] clear write: %d\n", ret);
+#endif
+            if (ret != bts2rd)
+              rtems_set_errno_and_return_minus_one(EIO);
+          }
+        }
+        
+#if MSDOS_FIND_PRINT
+        printf ("MSFS:[10] eso:%li\n", empty_space_offset);
+#endif
+        
+        for (dir_entry = empty_space_entry;
+             dir_entry < bts2rd;
+             dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+        {
+            char*       entry = (char*) fs_info->cl_buf + dir_entry;
+            char*       p;
+            const char* n;
+            int         i;
+
+            length += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+            lfn_entry++;
+            
+#if MSDOS_FIND_PRINT
+            printf ("MSFS:[10] de:%li(%li) length:%i lfn_entry:%i\n",
+                    dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE),
+                    length, lfn_entry);
+#endif
+            /*
+             * Time to write the short file name entry.
+             */
+            if (lfn_entry == (lfn_entries + 1))
+            {
+                /* get current cluster number */
+                int rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+                                        empty_space_offset * bts2rd,
+                                        &dir_pos->sname.cln);
+                if (rc != RC_OK)
+                  return rc;
+
+                dir_pos->sname.ofs = dir_entry;
+
+                if (lfn_start.cln != FAT_FILE_SHORT_NAME)
+                {
+                  rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+                                      lfn_start.cln * bts2rd,
+                                      &lfn_start.cln);
+                  if (rc != RC_OK)
+                    return rc;
+                }
+                
+                dir_pos->lname.cln = lfn_start.cln;
+                dir_pos->lname.ofs = lfn_start.ofs;
+
+                /* write new node entry */
+                memcpy (entry, (uint8_t *) name_dir_entry,
+                        MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+                break;
+            }
+
+            /*
+             * This is a long file name and we need to write
+             * a long file name entry. See if this is the
+             * first entry written and if so remember the
+             * the location of the long file name.
+             */
+            if (lfn_start.cln == FAT_FILE_SHORT_NAME)
+            {
+              lfn_start.cln = empty_space_offset;
+              lfn_start.ofs = dir_entry;
+            }
+            
+            /*
+             * Clear the entry before loading the data.
+             */
+            memset (entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+
+            *MSDOS_DIR_LFN_CHECKSUM(entry) = lfn_checksum;
+            
+            p = entry + 1;
+            n = name + (lfn_entries - lfn_entry) * MSDOS_LFN_LEN_PER_ENTRY;
+            
+            for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
+            {
+                *p = *n;
+                if (*n != 0)
+                    n++;
+                
+                switch (i)
+                {
+                    case 4:
+                        p += 5;
+                        break;
+                    case 10:
+                        p += 4;
+                        break;
+                    default:
+                        p += 2;
+                        break;
+                }
+            }
+
+            *MSDOS_DIR_ENTRY_TYPE(entry) = (lfn_entries - lfn_entry) + 1;
+            if (lfn_entry == 1)
+                *MSDOS_DIR_ENTRY_TYPE(entry) |= MSDOS_LAST_LONG_ENTRY;
+            *MSDOS_DIR_ATTR(entry) |= MSDOS_ATTR_LFN;
+        }
+
+        ret = fat_file_write(mt_entry, fat_fd,
+                             (empty_space_offset * bts2rd) + empty_space_entry,
+                             length, fs_info->cl_buf + empty_space_entry);
+        if (ret != length)
+            rtems_set_errno_and_return_minus_one(EIO);
+
+        empty_space_offset++;
+        empty_space_entry = 0;
+        read_cluster = true;
+    }
+    
+    return 0;
 }
 
 /* msdos_find_node_by_cluster_num_in_fat_file --
  *     Find node with specified number of cluster in fat-file.
  *
+ * Note, not updated in the LFN change because it is only used
+ *       for . and .. entries and these are always short.
+ *
  * PARAMETERS:
  *     mt_entry  - mount table entry
  *     fat_fd    - fat-file descriptor
@@ -885,7 +1620,7 @@ int msdos_find_node_by_cluster_num_in_fa
     rtems_filesystem_mount_table_entry_t *mt_entry,
     fat_file_fd_t                        *fat_fd,
     uint32_t                              cl4find,
-    fat_auxiliary_t                      *paux,
+    fat_dir_pos_t                        *dir_pos,
     char                                 *dir_entry
     )
 {
@@ -911,28 +1646,32 @@ int msdos_find_node_by_cluster_num_in_fa
 
         for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
         {
+            char* entry = (char*) fs_info->cl_buf + i;
+            
             /* if this and all rest entries are empty - return not-found */
-            if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
                 MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
                 return MSDOS_NAME_NOT_FOUND_ERR;
 
-            /* have to look at the DIR_NAME as "raw" 8-bit data */
             /* if this entry is empty - skip it */
-            if ((*(uint8_t *)MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+            if ((*MSDOS_DIR_ENTRY_TYPE(entry)) ==
                 MSDOS_THIS_DIR_ENTRY_EMPTY)
                 continue;
 
             /* if get a non-empty entry - compare clusters num */
-            if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find)
+            if (MSDOS_EXTRACT_CLUSTER_NUM(entry) == cl4find)
             {
                 /* on success fill aux structure and copy all 32 bytes */
                 rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd,
-                                    &paux->cln);
+                                    &dir_pos->sname.cln);
                 if (rc != RC_OK)
                     return rc;
 
-                paux->ofs = i;
-                memcpy(dir_entry, fs_info->cl_buf + i,
+                dir_pos->sname.ofs = i;
+                dir_pos->lname.cln = FAT_FILE_SHORT_NAME;
+                dir_pos->lname.ofs = FAT_FILE_SHORT_NAME;
+                
+                memcpy(dir_entry, entry,
                        MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
                 return RC_OK;
             }
Index: cpukit/libfs/src/dosfs/msdos_mknod.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/dosfs/msdos_mknod.c,v
retrieving revision 1.7
diff -p -u -u -r1.7 msdos_mknod.c
--- cpukit/libfs/src/dosfs/msdos_mknod.c	29 Jul 2008 02:21:14 -0000	1.7
+++ cpukit/libfs/src/dosfs/msdos_mknod.c	23 Apr 2009 07:54:40 -0000
@@ -36,7 +36,7 @@
  *     determines type of the node to be created and creates it.
  *
  * PARAMETERS:
- *     token   - non-formatted name of a new node
+ *     name    - file name to create
  *     mode    - node type
  *     dev     - dev
  *     pathloc - parent directory description
@@ -46,7 +46,7 @@
  *
  */
 int msdos_mknod(
-    const char                        *token,
+    const char                        *name,
     mode_t                             mode,
     dev_t                              dev,
     rtems_filesystem_location_info_t  *pathloc
@@ -56,12 +56,7 @@ int msdos_mknod(
     rtems_status_code    sc = RTEMS_SUCCESSFUL;
     msdos_fs_info_t     *fs_info = pathloc->mt_entry->fs_info;
     msdos_token_types_t  type = 0;
-    char                 new_name[ MSDOS_NAME_MAX + 1 ];
-    int                  len;
-
-    /* check spelling and format new node name */
-    msdos_get_token(token, new_name, &len);
-
+    
     /*
      *  Figure out what type of msdos node this is.
      */
@@ -82,7 +77,7 @@ int msdos_mknod(
         rtems_set_errno_and_return_minus_one(EIO);
 
     /* Create an MSDOS node */
-    rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
+    rc = msdos_creat_node(pathloc, type, name, strlen(name), mode, NULL);
 
     rtems_semaphore_release(fs_info->vol_sema);
     return rc;
Index: cpukit/libfs/src/imfs/deviceio.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/imfs/deviceio.c,v
retrieving revision 1.20
diff -p -u -u -r1.20 deviceio.c
--- cpukit/libfs/src/imfs/deviceio.c	12 Mar 2009 21:13:15 -0000	1.20
+++ cpukit/libfs/src/imfs/deviceio.c	23 Apr 2009 07:54:40 -0000
@@ -206,12 +206,14 @@ int device_ioctl(
 /*
  *  device_lseek
  *
- *  This handler eats all lseek() operations.
+ *  This handler eats all lseek() operations and does not create
+ *  an error. It assumes all devices can handle the seek. The
+ *  writes fail.
  */
 
-off_t device_lseek(
+rtems_off64_t device_lseek(
   rtems_libio_t *iop,
-  off_t          offset,
+  rtems_off64_t  offset,
   int            whence
 )
 {
@@ -232,7 +234,7 @@ off_t device_lseek(
 
 int device_ftruncate(
   rtems_libio_t *iop,
-  off_t          length
+  rtems_off64_t  length
 )
 {
   return 0;
Index: cpukit/libfs/src/imfs/imfs.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/imfs/imfs.h,v
retrieving revision 1.34
diff -p -u -u -r1.34 imfs.h
--- cpukit/libfs/src/imfs/imfs.h	9 Mar 2009 14:11:23 -0000	1.34
+++ cpukit/libfs/src/imfs/imfs.h	23 Apr 2009 07:54:40 -0000
@@ -98,15 +98,15 @@ typedef uint8_t *block_p;
 typedef block_p *block_ptr;
 
 typedef struct {
-  off_t      size;             /* size of file in bytes */
-  block_ptr  indirect;         /* array of 128 data blocks pointers */
-  block_ptr  doubly_indirect;  /* 128 indirect blocks */
-  block_ptr  triply_indirect;  /* 128 doubly indirect blocks */
+  rtems_off64_t size;             /* size of file in bytes */
+  block_ptr     indirect;         /* array of 128 data blocks pointers */
+  block_ptr     doubly_indirect;  /* 128 indirect blocks */
+  block_ptr     triply_indirect;  /* 128 doubly indirect blocks */
 } IMFS_memfile_t;
 
 typedef struct {
-  off_t      size;             /* size of file in bytes */
-  block_p    direct;           /* pointer to file image */
+  rtems_off64_t size;             /* size of file in bytes */
+  block_p       direct;           /* pointer to file image */
 } IMFS_linearfile_t;
 
 /*
@@ -380,7 +380,7 @@ extern int IMFS_memfile_remove(
 
 extern int memfile_ftruncate(
   rtems_libio_t *iop,               /* IN  */
-  off_t          length             /* IN  */
+  rtems_off64_t  length             /* IN  */
 );
 
 extern int imfs_dir_open(
@@ -400,9 +400,9 @@ extern ssize_t imfs_dir_read(
   size_t         count             /* IN  */
 );
 
-extern off_t imfs_dir_lseek(
+extern rtems_off64_t imfs_dir_lseek(
   rtems_libio_t        *iop,              /* IN  */
-  off_t                 offset,           /* IN  */
+  rtems_off64_t         offset,           /* IN  */
   int                   whence            /* IN  */
 );
 
@@ -444,9 +444,9 @@ extern int memfile_ioctl(
   void          *buffer           /* IN  */
 );
 
-extern off_t memfile_lseek(
+extern rtems_off64_t memfile_lseek(
   rtems_libio_t        *iop,        /* IN  */
-  off_t                 offset,     /* IN  */
+  rtems_off64_t         offset,     /* IN  */
   int                   whence      /* IN  */
 );
 
@@ -483,15 +483,15 @@ extern int device_ioctl(
   void          *buffer             /* IN  */
 );
 
-extern off_t device_lseek(
+extern rtems_off64_t device_lseek(
   rtems_libio_t *iop,               /* IN  */
-  off_t          offset,            /* IN  */
+  rtems_off64_t  offset,            /* IN  */
   int            whence             /* IN  */
 );
 
 extern int device_ftruncate(
   rtems_libio_t *iop,               /* IN  */
-  off_t          length             /* IN  */
+  rtems_off64_t  length             /* IN  */
 );
 
 extern int IMFS_utime(
Index: cpukit/libfs/src/imfs/imfs_directory.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/imfs/imfs_directory.c,v
retrieving revision 1.22
diff -p -u -u -r1.22 imfs_directory.c
--- cpukit/libfs/src/imfs/imfs_directory.c	9 Mar 2009 14:11:23 -0000	1.22
+++ cpukit/libfs/src/imfs/imfs_directory.c	23 Apr 2009 07:54:40 -0000
@@ -182,9 +182,9 @@ int imfs_dir_close(
  *     SEEK_END - N/A --> This will cause an assert.
  */
 
-off_t imfs_dir_lseek(
+rtems_off64_t imfs_dir_lseek(
   rtems_libio_t  *iop,
-  off_t           offset,
+  rtems_off64_t   offset,
   int             whence
 )
 {
Index: cpukit/libfs/src/imfs/imfs_fifo.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/imfs/imfs_fifo.c,v
retrieving revision 1.2
diff -p -u -u -r1.2 imfs_fifo.c
--- cpukit/libfs/src/imfs/imfs_fifo.c	9 Mar 2009 14:11:23 -0000	1.2
+++ cpukit/libfs/src/imfs/imfs_fifo.c	23 Apr 2009 07:54:40 -0000
@@ -119,10 +119,10 @@ int IMFS_fifo_ioctl(
   IMFS_FIFO_RETURN(err);
 }
 
-off_t IMFS_fifo_lseek(
+rtems_off64_t IMFS_fifo_lseek(
   rtems_libio_t *iop,
-  off_t         offset,
-  int           whence
+  rtems_off64_t  offset,
+  int            whence
 )
 {
   off_t err = pipe_lseek(LIBIO2PIPE(iop), offset, whence, iop);
Index: cpukit/libfs/src/imfs/memfile.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/imfs/memfile.c,v
retrieving revision 1.29
diff -p -u -u -r1.29 memfile.c
--- cpukit/libfs/src/imfs/memfile.c	9 Mar 2009 14:11:23 -0000	1.29
+++ cpukit/libfs/src/imfs/memfile.c	23 Apr 2009 07:54:40 -0000
@@ -214,9 +214,9 @@ int memfile_ioctl(
  *  This routine processes the lseek() system call.
  */
 
-off_t memfile_lseek(
+rtems_off64_t memfile_lseek(
   rtems_libio_t   *iop,
-  off_t            offset,
+  rtems_off64_t    offset,
   int              whence
 )
 {
@@ -251,7 +251,7 @@ off_t memfile_lseek(
 
 int memfile_ftruncate(
   rtems_libio_t        *iop,
-  off_t                 length
+  rtems_off64_t         length
 )
 {
   IMFS_jnode_t   *the_jnode;
Index: cpukit/libfs/src/nfsclient/src/nfs.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libfs/src/nfsclient/src/nfs.c,v
retrieving revision 1.10
diff -p -u -u -r1.10 nfs.c
--- cpukit/libfs/src/nfsclient/src/nfs.c	9 Mar 2009 14:11:23 -0000	1.10
+++ cpukit/libfs/src/nfsclient/src/nfs.c	23 Apr 2009 07:54:40 -0000
@@ -2737,9 +2737,9 @@ static int nfs_file_ioctl(
 #define nfs_link_ioctl 0
 #endif
 
-static off_t nfs_file_lseek(
+static rtems_off64_t nfs_file_lseek(
 	rtems_libio_t *iop,
-	off_t          length,
+	rtems_off64_t  length,
 	int            whence
 )
 {
@@ -2770,9 +2770,9 @@ static off_t nfs_file_lseek(
 	return iop->offset;
 }
 
-static off_t nfs_dir_lseek(
+static rtems_off64_t nfs_dir_lseek(
 	rtems_libio_t *iop,
-	off_t          length,
+	rtems_off64_t  length,
 	int            whence
 )
 {
@@ -2818,29 +2818,29 @@ struct fattr {
 
 struct  stat
 {
-		dev_t     st_dev;
-		ino_t     st_ino;
-		mode_t    st_mode;
-		nlink_t   st_nlink;
-		uid_t     st_uid;
-		gid_t     st_gid;
-		dev_t     st_rdev;
-		off_t     st_size;
+		dev_t         st_dev;
+		ino_t         st_ino;
+		mode_t        st_mode;
+		nlink_t       st_nlink;
+		uid_t         st_uid;
+		gid_t         st_gid;
+		dev_t         st_rdev;
+		rtems_off64_t st_size;
 		/* SysV/sco doesn't have the rest... But Solaris, eabi does.  */
 #if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__)
-		time_t    st_atime;
-		time_t    st_mtime;
-		time_t    st_ctime;
+		time_t        st_atime;
+		time_t        st_mtime;
+		time_t        st_ctime;
 #else
-		time_t    st_atime;
-		long      st_spare1;
-		time_t    st_mtime;
-		long      st_spare2;
-		time_t    st_ctime;
-		long      st_spare3;
-		long      st_blksize;
-		long      st_blocks;
-		long  st_spare4[2];
+		time_t        st_atime;
+		long          st_spare1;
+		time_t        st_mtime;
+		long          st_spare2;
+		time_t        st_ctime;
+		long          st_spare3;
+		long          st_blksize;
+		long          st_blocks;
+		long      st_spare4[2];
 #endif
 };
 #endif
@@ -3009,7 +3009,7 @@ sattr	arg;
  */
 static int nfs_file_ftruncate(
 	rtems_libio_t *iop,
-	off_t          length
+	rtems_off64_t  length
 )
 {
 sattr					arg;
Index: cpukit/libmisc/shell/main_msdosfmt.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libmisc/shell/main_msdosfmt.c,v
retrieving revision 1.3
diff -p -u -u -r1.3 main_msdosfmt.c
--- cpukit/libmisc/shell/main_msdosfmt.c	27 Feb 2008 21:52:16 -0000	1.3
+++ cpukit/libmisc/shell/main_msdosfmt.c	23 Apr 2009 07:54:41 -0000
@@ -42,7 +42,8 @@ int rtems_shell_main_msdos_format(
     fattype:             MSDOS_FMT_FATANY,
     media:               0,
     quick_format:        TRUE,
-    cluster_align:       0
+    cluster_align:       0,
+    info_level:          0
   };
   
   const char* driver = NULL;
@@ -51,7 +52,7 @@ int rtems_shell_main_msdos_format(
   for (arg = 1; arg < argc; arg++) {
     if (argv[arg][0] == '-') {
       switch (argv[arg][1]) {
-        case 'v':
+        case 'V':
           arg++;
           if (arg == argc) {
             fprintf (stderr, "error: no volume label.\n");
@@ -59,6 +60,15 @@ int rtems_shell_main_msdos_format(
           }
           rqdata.VolLabel = argv[arg];
           break;
+
+        case 's':
+          arg++;
+          if (arg == argc) {
+            fprintf (stderr, "error: sectors per cluster count.\n");
+            return 1;
+          }
+          rqdata.sectors_per_cluster = rtems_shell_str2int(argv[arg]);
+          break;
           
         case 'r':
           arg++;
@@ -90,6 +100,10 @@ int rtems_shell_main_msdos_format(
           }
           break;
 
+        case 'v':
+          rqdata.info_level++;
+          break;
+          
         default:
           fprintf (stderr, "error: invalid option: %s\n", argv[arg]);
           return 1;
@@ -111,6 +125,19 @@ int rtems_shell_main_msdos_format(
   }
   
   printf ("msdos format: %s\n", driver);
+
+  if (rqdata.info_level)
+  {
+    printf (" %-20s: %s\n", "OEMName", "RTEMS");
+    printf (" %-20s: %s\n", "VolLabel", "RTEMSDisk");
+    printf (" %-20s: %i\n", "sectors per cluster", rqdata.sectors_per_cluster);
+    printf (" %-20s: %i\n", "fats", rqdata.fat_num);
+    printf (" %-20s: %i\n", "files per root dir", rqdata.files_per_root_dir);
+    printf (" %-20s: %i\n", "fat type", rqdata.fattype);
+    printf (" %-20s: %d\n", "media", rqdata.media);
+    printf (" %-20s: %d\n", "quick_format", rqdata.quick_format);
+    printf (" %-20s: %i\n", "cluster align", rqdata.cluster_align);
+  }
   
   if (msdos_format (driver, &rqdata) < 0) {
     fprintf (stderr, "error: format failed: %s\n", strerror (errno));
Index: cpukit/libnetworking/lib/ftpfs.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libnetworking/lib/ftpfs.c,v
retrieving revision 1.18
diff -p -u -u -r1.18 ftpfs.c
--- cpukit/libnetworking/lib/ftpfs.c	14 Apr 2009 08:49:12 -0000	1.18
+++ cpukit/libnetworking/lib/ftpfs.c	23 Apr 2009 07:54:41 -0000
@@ -986,7 +986,7 @@ static int rtems_ftpfs_close( rtems_libi
 }
 
 /* Dummy version to let fopen( *,"w") work properly */
-static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, off_t count)
+static int rtems_ftpfs_ftruncate( rtems_libio_t *iop, rtems_off64_t count)
 {
   return 0;
 }
Index: cpukit/libnetworking/lib/tftpDriver.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libnetworking/lib/tftpDriver.c,v
retrieving revision 1.30
diff -p -u -u -r1.30 tftpDriver.c
--- cpukit/libnetworking/lib/tftpDriver.c	3 Jan 2009 08:31:25 -0000	1.30
+++ cpukit/libnetworking/lib/tftpDriver.c	23 Apr 2009 07:54:41 -0000
@@ -984,7 +984,7 @@ static ssize_t rtems_tftp_write(
  */
 static int rtems_tftp_ftruncate(
     rtems_libio_t   *iop __attribute__((unused)),
-    off_t           count __attribute__((unused))
+    rtems_off64_t    count __attribute__((unused))
 )
 {
     return 0;
Index: cpukit/libnetworking/nfs/bootp_subr.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libnetworking/nfs/bootp_subr.c,v
retrieving revision 1.27
diff -p -u -u -r1.27 bootp_subr.c
--- cpukit/libnetworking/nfs/bootp_subr.c	10 Feb 2009 08:25:06 -0000	1.27
+++ cpukit/libnetworking/nfs/bootp_subr.c	23 Apr 2009 07:54:41 -0000
@@ -464,10 +464,12 @@ bootpc_call(
 
 		} /* while secs */
 	} /* forever send/receive */
-
-        printf("BOOTP timeout for server 0x%x\n",
-               (int)ntohl(sin->sin_addr.s_addr));
-
+	{
+		uint32_t addr = ntohl(sin->sin_addr.s_addr);
+        printf("BOOTP timeout for server %lu.%lu.%lu.%lu\n",
+               (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+               (addr >> 8) & 0xff, addr & 0xff);
+	}
 	error = ETIMEDOUT;
 	goto out;
 
@@ -518,7 +520,12 @@ bootpc_fakeup_interface(struct ifreq *ir
   sin->sin_family = AF_INET;
   sin->sin_addr.s_addr = INADDR_ANY;
   error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
-  if (error) {
+  /*
+   * Ignore a File already exists (EEXIST) error code. This means a
+   * route for the address is already present and is returned on
+   * a second pass to here.
+   */
+  if (error && (error != EEXIST)) {
     printf("bootpc_fakeup_interface: set if addr, error=%s\n", strerror(error));
     return error;
   }
@@ -549,7 +556,6 @@ bootpc_fakeup_interface(struct ifreq *ir
     return error;
   }
   
-  
   /* Add default route to 0.0.0.0 so we can send data */
   
   bzero((caddr_t) &dst, sizeof(dst));
@@ -573,8 +579,10 @@ bootpc_fakeup_interface(struct ifreq *ir
 		    (struct sockaddr *) &mask, 
 		    RTF_UP | RTF_STATIC
 		    , NULL);
-  if (error)
-    printf("bootpc_fakeup_interface: add default route, error=%d\n", error);
+  if (error && error != EEXIST)
+    printf("bootpc_fakeup_interface: add default route, error=%s\n",
+           strerror(error));
+  
   return error;
 }
 
Index: cpukit/libnetworking/rtems/rtems_dhcp.c
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/libnetworking/rtems/rtems_dhcp.c,v
retrieving revision 1.4
diff -p -u -u -r1.4 rtems_dhcp.c
--- cpukit/libnetworking/rtems/rtems_dhcp.c	4 Feb 2009 13:34:34 -0000	1.4
+++ cpukit/libnetworking/rtems/rtems_dhcp.c	23 Apr 2009 07:54:41 -0000
@@ -689,24 +689,31 @@ dhcp_task (rtems_task_argument _sdl)
   int                 error;
   struct proc *procp = NULL;
   int                 disconnected;
+  rtems_status_code   ev_st;
   
   sdl = (struct sockaddr_dl *) _sdl;
   
   count = dhcp_elapsed_time;
   disconnected = 0;
  
-
-  while (TRUE)
+  while (true)
   {
     /*
      * Sleep until the next poll
      */
     timeout = TOD_MILLISECONDS_TO_TICKS (1000);
-    rtems_event_receive (RTEMS_EVENT_0,
-                         RTEMS_WAIT | RTEMS_EVENT_ANY,
-                         timeout, &event_out);
+    ev_st = rtems_event_receive (RTEMS_EVENT_0,
+                                 RTEMS_WAIT | RTEMS_EVENT_ANY,
+                                 timeout, &event_out);
 
-    if(event_out & RTEMS_EVENT_0) break;
+    /*
+     * Check if not a poll timeout. So when ANY event received, exit task.
+     * Actually, only event RTEMS_EVENT_0 sent from rtem_dhcp_failsafe.c
+     * if "failsafe" dhcp enabled when interface down.  Otherwise, no 
+     * event should occur, just timeout.
+     */
+    if(ev_st != RTEMS_TIMEOUT)
+        break;
 
     count++;
 
@@ -714,7 +721,7 @@ dhcp_task (rtems_task_argument _sdl)
     {
       rtems_bsdnet_semaphore_obtain ();
       
-      dhcp_request_req (&call, &dhcp_req, sdl, TRUE);
+      dhcp_request_req (&call, &dhcp_req, sdl, true);
 
       /*
        * Send the Request.
@@ -878,7 +885,7 @@ dhcp_init (int update_files)
   sprintf (ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
 
   if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0) {
-    printf ("dhcpc_init: socreate, error=%d\n", error);
+    printf ("dhcpc_init: socreate, error: %s\n", strerror(error));
     return -1;
   }
 
@@ -896,11 +903,13 @@ dhcp_init (int update_files)
 
   if (!sdl){
     printf ("dhcpc_init: Unable to find HW address\n");
+    soclose (so);
     return -1;
   }
   if (sdl->sdl_alen != EALEN) {
     printf ("dhcpc_init: HW address len is %d, expected value is %d\n",
            sdl->sdl_alen, EALEN);
+    soclose (so);
     return -1;
   }
 
@@ -914,7 +923,8 @@ dhcp_init (int update_files)
    */
   error = bootpc_call (&call, &reply, procp);
   if (error) {
-    printf ("BOOTP call failed -- error %d\n", error);
+    printf ("BOOTP call failed -- %s\n", strerror(error));
+    soclose (so);
     return -1;
   }
 
@@ -923,6 +933,7 @@ dhcp_init (int update_files)
    */
   if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
     printf ("DHCP server did not send Magic Cookie.\n");
+    soclose (so);
     return -1;
   }
 
@@ -930,17 +941,19 @@ dhcp_init (int update_files)
   
   if (dhcp_message_type != DHCP_OFFER) {
     printf ("DHCP server did not send a DHCP Offer.\n");
+    soclose (so);
     return -1;
   }
 
   /*
    * Send a DHCP REQUEST 
    */
-  dhcp_request_req (&call, &reply, sdl, TRUE);
+  dhcp_request_req (&call, &reply, sdl, true);
   
   error = bootpc_call (&call, &reply, procp);
   if (error) {
-    printf ("BOOTP call failed -- error %d\n", error);
+    printf ("BOOTP call failed -- %s\n", strerror(error));
+    soclose (so);
     return -1;
   }
 
@@ -949,6 +962,7 @@ dhcp_init (int update_files)
    */
   if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
     printf ("DHCP server did not send Magic Cookie.\n");
+    soclose (so);
     return -1;
   }
   
@@ -956,6 +970,7 @@ dhcp_init (int update_files)
   
   if (dhcp_message_type != DHCP_ACK) {
     printf ("DHCP server did not accept the DHCP request\n");
+    soclose (so);
     return -1;
   }
 
@@ -1106,8 +1121,10 @@ dhcp_init (int update_files)
  */
 void rtems_bsdnet_do_dhcp (void)
 {
+  bool update = true;
   rtems_bsdnet_semaphore_obtain ();
-  while( dhcp_init (TRUE) < 0 ) {
+  while( dhcp_init (update) < 0 ) {
+    update = false;
     rtems_bsdnet_semaphore_release();
     rtems_task_wake_after(TOD_MILLISECONDS_TO_TICKS(1000));
     rtems_bsdnet_semaphore_obtain ();
@@ -1120,7 +1137,7 @@ int rtems_bsdnet_do_dhcp_timeout( void )
   int return_value;
 
   rtems_bsdnet_semaphore_obtain ();
-  return_value = dhcp_init (FALSE);
+  return_value = dhcp_init (false);
   rtems_bsdnet_semaphore_release ();
 
   return return_value;
Index: cpukit/sapi/include/confdefs.h
===================================================================
RCS file: /usr1/CVS/rtems/cpukit/sapi/include/confdefs.h,v
retrieving revision 1.118
diff -p -u -u -r1.118 confdefs.h
--- cpukit/sapi/include/confdefs.h	5 Jan 2009 20:16:07 -0000	1.118
+++ cpukit/sapi/include/confdefs.h	23 Apr 2009 07:54:41 -0000
@@ -518,7 +518,16 @@ rtems_fs_init_functions_t    rtems_fs_in
 #endif
 
 #ifndef CONFIGURE_INIT_TASK_ENTRY_POINT
+  #ifdef __cplusplus
+  extern "C" {
+  #endif
+    rtems_task Init (rtems_task_argument );
+  #ifdef __cplusplus
+  }
+  #endif
   #define CONFIGURE_INIT_TASK_ENTRY_POINT   Init
+  extern const char* bsp_boot_cmdline;
+  #define CONFIGURE_INIT_TASK_ARGUMENTS     ((rtems_task_argument) &bsp_boot_cmdline)
 #endif
 
 #ifndef CONFIGURE_INIT_TASK_INITIAL_MODES
Index: doc/started/started.texi
===================================================================
RCS file: /usr1/CVS/rtems/doc/started/started.texi,v
retrieving revision 1.20
diff -p -u -u -r1.20 started.texi
--- doc/started/started.texi	21 Jun 2007 18:53:00 -0000	1.20
+++ doc/started/started.texi	23 Apr 2009 07:54:41 -0000
@@ -8,7 +8,7 @@
 @c %**end of header
 
 @c
-@c  COPYRIGHT (c) 1988-2002.
+@c  COPYRIGHT (c) 1988-2007.
 @c  On-Line Applications Research Corporation (OAR).
 @c  All rights reserved.
 @c
Index: make/leaf.cfg
===================================================================
RCS file: /usr1/CVS/rtems/make/leaf.cfg,v
retrieving revision 1.24
diff -p -u -u -r1.24 leaf.cfg
--- make/leaf.cfg	15 Sep 2008 17:43:22 -0000	1.24
+++ make/leaf.cfg	23 Apr 2009 07:54:41 -0000
@@ -118,12 +118,12 @@ DOWNEXT=.ralf
 
 define bsp-link-c
 	$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) \
-	    -o $(basename $@).exe $(LINK_OBJS) $(LINK_LIBS)
+	    -o $(basename $@)$(EXEEXT) $(LINK_OBJS) $(LINK_LIBS)
 endef
 
 define bsp-link-cxx
 	$(LINK.cc) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) \
-	    -o $(basename $@).exe $(LINK_OBJS) $(LINK_LIBS)
+	    -o $(basename $@)$(EXEEXT) $(LINK_OBJS) $(LINK_LIBS)
 endef
 
 define default-bsp-post-link
@@ -134,7 +134,7 @@ endef
 ifndef bsp-post-link
 define bsp-post-link
 	$(default-bsp-post-link)
-	cp $(basename $@).exe $(basename $@)$(DOWNEXT)
+	cp $(basename $@)$(EXEEXT) $(basename $@)$(DOWNEXT)
 endef
 endif
 
Index: make/compilers/gcc-no_bsp.cfg
===================================================================
RCS file: /usr1/CVS/rtems/make/compilers/gcc-no_bsp.cfg,v
retrieving revision 1.14
diff -p -u -u -r1.14 gcc-no_bsp.cfg
--- make/compilers/gcc-no_bsp.cfg	18 Sep 2008 17:33:55 -0000	1.14
+++ make/compilers/gcc-no_bsp.cfg	23 Apr 2009 07:54:41 -0000
@@ -226,9 +226,9 @@ LINK_FILES= \
 # On Solaris at least you need to had /usr/ucblib/libucb.a
 
 define make-exe
-	$(CC) -o $(basename $@).exe $(LINK_FILES) -lc -lm
-	$(NM) -n $(basename $@).exe > $(basename $@).num
-	$(SIZE) $(basename $@).exe
+	$(CC) -o $(basename $@)$(EXEEXT) $(LINK_FILES) -lc -lm
+	$(NM) -n $(basename $@)$(EXEEXT) > $(basename $@).num
+	$(SIZE) $(basename $@)$(EXEEXT)
 endef
 
 define make-rel
Index: make/custom/mcf5235.cfg
===================================================================
RCS file: /usr1/CVS/rtems/make/custom/mcf5235.cfg,v
retrieving revision 1.13
diff -p -u -u -r1.13 mcf5235.cfg
--- make/custom/mcf5235.cfg	11 Jun 2008 08:17:27 -0000	1.13
+++ make/custom/mcf5235.cfg	23 Apr 2009 07:54:41 -0000
@@ -31,6 +31,6 @@ endif
 # is currently required.
 define bsp-post-link
 	$(OBJCOPY) -O binary --strip-all \
-	    $(basename $@).exe $(basename $@)$(DOWNEXT)
-	$(SIZE) $(basename $@).exe
+	    $(basename $@)$(EXEEXT) $(basename $@)$(DOWNEXT)
+	$(SIZE) $(basename $@)$(EXEEXT)
 endef
Index: make/custom/pc386.cfg
===================================================================
RCS file: /usr1/CVS/rtems/make/custom/pc386.cfg,v
retrieving revision 1.46
diff -p -u -u -r1.46 pc386.cfg
--- make/custom/pc386.cfg	20 Nov 2008 15:26:37 -0000	1.46
+++ make/custom/pc386.cfg	23 Apr 2009 07:54:41 -0000
@@ -51,7 +51,7 @@ define bsp-post-link
 	$(OBJCOPY) -O elf32-i386 \
 	    --remove-section=.comment \
 	    --remove-section=.note \
-	    --strip-unneeded $(basename $@).exe $(basename $@).nxe
+	    --strip-unneeded $(basename $@)$(EXEEXT) $(basename $@).nxe
 	$(OBJCOPY) -O binary $(basename $@).nxe $(basename $@).bin
 	$(PROJECT_TOOLS)/bin2boot -v $(basename $@)$(DOWNEXT) $(HEADERADDR)\
 	  $(START16FILE) $(START16ADDR) 0 $(basename $@).bin $(RELOCADDR) 0
Index: testsuites/automake/compile.am
===================================================================
RCS file: /usr1/CVS/rtems/testsuites/automake/compile.am,v
retrieving revision 1.21
diff -p -u -u -r1.21 compile.am
--- testsuites/automake/compile.am	22 Nov 2005 14:13:42 -0000	1.21
+++ testsuites/automake/compile.am	23 Apr 2009 07:54:41 -0000
@@ -18,4 +18,4 @@ AM_CFLAGS =
 AM_CXXFLAGS =
 
 clean-local:
-	$(RM) *.num *.nxe *.elf *.srec* *.bin *.bt
+	$(RM) *$(EXEEXT) *$(DOWNEXT) *.num *.nxe *.elf *.srec* *.bin *.bt
Index: testsuites/samples/iostream/system.h
===================================================================
RCS file: /usr1/CVS/rtems/testsuites/samples/iostream/system.h,v
retrieving revision 1.4
diff -p -u -u -r1.4 system.h
--- testsuites/samples/iostream/system.h	17 Jun 2008 18:50:30 -0000	1.4
+++ testsuites/samples/iostream/system.h	23 Apr 2009 07:54:41 -0000
@@ -15,12 +15,6 @@
 
 #include <rtems.h>
 
-/* functions */
-
-rtems_task Init(
-  rtems_task_argument argument
-);
-
 /* configuration information */
 
 #include <bsp.h> /* for device driver prototypes */
