Index: trunk/src/emx/ChangeLog.LIBC
===================================================================
--- trunk/src/emx/ChangeLog.LIBC	(revision 2047)
+++ trunk/src/emx/ChangeLog.LIBC	(revision 2048)
@@ -1,3 +1,15 @@
 /* $Id$ */
+
+2005-06-19: knut st. osmundsen <bird-gccos2-spam@anduin.net>
+    - libc:
+        o File resize optimization: The JFS, HPFS and probably NET
+          will never return space which isn't zeroed when expanding
+          a file. Associate a file system information object with the
+          filehandles to keep track of such features. This also fixes
+          the fsStatFH() implementation trouble.
+          This attribute doesn't apply to CDFS. While RAMFS fails
+          the test, it zeros at open but not at setfilesize.
+        o Fixed invalid inode and dev numbers for new files, was passing
+          the wrong path around.
 
 2005-06-13: knut st. osmundsen <bird-gccos2-spam@anduin.net>
Index: trunk/src/emx/include/386/builtin.h
===================================================================
--- trunk/src/emx/include/386/builtin.h	(revision 2047)
+++ trunk/src/emx/include/386/builtin.h	(revision 2048)
@@ -148,5 +148,4 @@
 }
 
-
 /**
  * Atomically increments a 32-bit unsigned value.
@@ -164,11 +163,35 @@
  * Atomically increments a 32-bit unsigned value.
  *
+ * @returns The new value.
  * @param   pu32    Pointer to the value to increment.
  */
-static __inline__ void __atomic_increment_u32(uint32_t __volatile__ *pu32)
-{
-    __asm__ __volatile__("lock; incl %0"
-                         : "=m" (*pu32)
-                         : "m"  (*pu32));
+static __inline__ uint32_t __atomic_increment_u32(uint32_t __volatile__ *pu32)
+{
+    uint32_t u32;
+    __asm__ __volatile__("lock; xadd %0, %1\n\t"
+                         "incl %0\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (1)
+                         : "memory");
+    return u32;
+}
+
+/**
+ * Atomically increments a 32-bit signed value.
+ *
+ * @returns The new value.
+ * @param   pi32    Pointer to the value to increment.
+ */
+static __inline__ uint32_t __atomic_increment_s32(int32_t __volatile__ *pi32)
+{
+    int32_t i32;
+    __asm__ __volatile__("lock; xadd %0, %1\n\t"
+                         "incl %0\n\t"
+                         : "=r" (i32),
+                           "=m" (*pi32)
+                         : "0" (1)
+                         : "memory");
+    return i32;
 }
 
@@ -200,11 +223,35 @@
  * Atomically decrements a 32-bit unsigned value.
  *
- * @param   pu      Pointer to the value to decrement.
- */
-static __inline__ void __atomic_decrement_u32(__volatile__ uint32_t *pu32)
-{
-    __asm__ __volatile__("lock; decl %0"
-                         : "=m" (*pu32)
-                         : "m"  (*pu32));
+ * @returns The new value.
+ * @param   pu32      Pointer to the value to decrement.
+ */
+static __inline__ uint32_t __atomic_decrement_u32(__volatile__ uint32_t *pu32)
+{
+    uint32_t u32;
+    __asm__ __volatile__("lock; xadd %0, %1\n\t"
+                         "decl %0\n\t"
+                         : "=r" (u32),
+                           "=m" (*pu32)
+                         : "0" (-1)
+                         : "memory");
+    return u32;
+}
+
+/**
+ * Atomically decrements a 32-bit signed value.
+ *
+ * @returns The new value.
+ * @param   pi32    Pointer to the value to decrement.
+ */
+static __inline__ uint32_t __atomic_decrement_s32(__volatile__ int32_t *pi32)
+{
+    int32_t i32;
+    __asm__ __volatile__("lock; xadd %0, %1\n\t"
+                         "decl %0\n\t"
+                         : "=r" (i32),
+                           "=m" (*pi32)
+                         : "0" (-1)
+                         : "memory");
+    return i32;
 }
 
@@ -212,4 +259,5 @@
  * Atomically decrements a 16-bit unsigned value.
  *
+ * @returns The new value.
  * @param   pu16    Pointer to the value to decrement.
  */
Index: trunk/src/emx/include/InnoTekLIBC/sharedpm.h
===================================================================
--- trunk/src/emx/include/InnoTekLIBC/sharedpm.h	(revision 2047)
+++ trunk/src/emx/include/InnoTekLIBC/sharedpm.h	(revision 2048)
@@ -163,5 +163,7 @@
 #define __LIBC_SPM_INH_FHB_TYPE_END         (0)
 /** Standard bundle. */
-#define __LIBC_SPM_INH_FHB_TYPE_STANDARD    (0x10 | sizeof(unsigned))
+#define __LIBC_SPM_INH_FHB_TYPE_STANDARD    (0x10 | (sizeof(unsigned) + sizeof(ino_t) + sizeof(dev_t)))
+/** The old standard bundle. */
+#define __LIBC_SPM_INH_FHB_TYPE_STANDARD_OLD (0x10 | sizeof(unsigned))
 /** Socket bundle, using the BSD 4.4 backend. */
 #define __LIBC_SPM_INH_FHB_TYPE_SOCKET_44   (0x20 | (sizeof(unsigned) + sizeof(unsigned short)))
@@ -199,10 +201,35 @@
     /** The common bundle header. */
     __LIBC_SPMINHFHBHDR Hdr;
-    /** Array of flags of Hdr.cHandles entries. */
-    unsigned            afFlags[1];
+    /** Array Hdr.cHandles entries. */
+    struct
+    {
+        /** The flags */
+        unsigned            fFlags;
+        /** The inode number. */
+        ino_t               Inode;
+        /** The device number. */
+        dev_t               Dev;
+    } aHandles[1];
 } __LIBC_SPMINHFHBSTD;
 #pragma pack()
 /** Pointer to SPM standard filehandle inherit bundle. */
 typedef __LIBC_SPMINHFHBSTD *__LIBC_PSPMINHFHBSTD;
+
+/**
+ * SPM standard filehandle inherit bundle
+ * This is used for OS/2 filehandles which only needs flags
+ * transfered.
+ */
+#pragma pack(1)
+typedef struct __libc_SPMInhFHOld
+{
+    /** The common bundle header. */
+    __LIBC_SPMINHFHBHDR Hdr;
+    /** Array of flags of Hdr.cHandles entries. */
+    unsigned            afFlags[1];
+} __LIBC_SPMINHFHBSTDOLD;
+#pragma pack()
+/** Pointer to SPM standard filehandle inherit bundle. */
+typedef __LIBC_SPMINHFHBSTDOLD *__LIBC_PSPMINHFHBSTDOLD;
 
 /**
Index: trunk/src/emx/include/emx/io.h
===================================================================
--- trunk/src/emx/include/emx/io.h	(revision 2047)
+++ trunk/src/emx/include/emx/io.h	(revision 2048)
@@ -225,4 +225,29 @@
 
 /**
+ * Information struct about a mounted file system.
+ *
+ * Used to track down the filesystem of an open file handle and
+ * so we can optimize certain operations like expanding a file.
+ */
+typedef struct __libc_FileSystemInfo
+{
+    /** Number of references to this file system info object.
+     * The structure can be shared by many handles. */
+    volatile int32_t    cRefs;
+    /** Does the file system automatically zero the new space when a file is extended? */
+    unsigned            fZeroNewBytes : 1;
+    /** Device number of the device the filesystem resides on.
+     * On OS/2 the device number is derived from the driveletter. */
+    dev_t               Dev;
+    /** The filesystem driver name. */
+    char                szName[16];
+    /** The mount point - may extend beyond the 4 bytes on some OSes. */
+    char                szMountpoint[4];
+} __LIBC_FSINFO;
+/** Pointer to information about an open filesystem. */
+typedef __LIBC_FSINFO *__LIBC_PFSINFO;
+
+
+/**
  * Filehandle type.
  */
@@ -381,4 +406,7 @@
      * determin this at handle creation time. */
     ino_t                   Inode;
+    /** Pointer to the filesystem information object for the filesystem which
+     * this file resides on. This might be NULL... */
+    __LIBC_PFSINFO          pFsInfo;
 } __LIBC_FH;
 /** Pointer to filehandle. */
Index: trunk/src/emx/src/lib/sys/__dup.c
===================================================================
--- trunk/src/emx/src/lib/sys/__dup.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/__dup.c	(revision 2048)
@@ -10,4 +10,5 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include "b_fs.h"
 
 int __dup(int fh)
@@ -59,4 +60,5 @@
                 pFHNew->Inode       = pFH->Inode;
                 pFHNew->Dev         = pFH->Dev;
+                pFHNew->pFsInfo     = __libc_back_fsInfoObjAddRef(pFH->pFsInfo);
             }
             else
Index: trunk/src/emx/src/lib/sys/__dup2.c
===================================================================
--- trunk/src/emx/src/lib/sys/__dup2.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/__dup2.c	(revision 2048)
@@ -9,4 +9,5 @@
 #include <emx/io.h>
 #include "syscalls.h"
+#include "b_fs.h"
 
 int __dup2(int fh, int fhNew)
@@ -92,4 +93,5 @@
                 pFHNew->Inode       = pFH->Inode;
                 pFHNew->Dev         = pFH->Dev;
+                pFHNew->pFsInfo     = __libc_back_fsInfoObjAddRef(pFH->pFsInfo);
             }
             else
Index: trunk/src/emx/src/lib/sys/b_fs.h
===================================================================
--- trunk/src/emx/src/lib/sys/b_fs.h	(revision 2047)
+++ trunk/src/emx/src/lib/sys/b_fs.h	(revision 2048)
@@ -235,4 +235,29 @@
 dev_t __libc_back_fsPathCalcInodeAndDev(const char *pszNativePath, ino_t *pInode);
 
+/**
+ * Gets the fs info object for the specfied path.
+ *
+ * @returns Pointer to info object for the path, if it got one.
+ * @param   Dev     The device we want the file system object for.
+ */
+__LIBC_PFSINFO __libc_back_fsInfoObjByDev(dev_t Dev);
+
+/**
+ * Adds a reference to an existing FS info object.
+ *
+ * The caller is responsible for making sure that the object cannot
+ * reach 0 references while inside this function.
+ *
+ * @returns pFsInfo.
+ * @param   pFsInfo     Pointer to the fs info object to reference.
+ */
+__LIBC_PFSINFO __libc_back_fsInfoObjAddRef(__LIBC_PFSINFO pFsInfo);
+
+/**
+ * Releases the fs info object for the specfied path.
+ *
+ * @param   pFsInfo     Pointer to the fs info object to release a reference to.
+ */
+void __libc_back_fsInfoObjRelease(__LIBC_PFSINFO pFsInfo);
 
 __END_DECLS
Index: trunk/src/emx/src/lib/sys/b_fsStat.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_fsStat.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/b_fsStat.c	(revision 2048)
@@ -112,6 +112,11 @@
      * pass it to the statfs() backend.
      */
+    int     rc = 0;
     char    szFilename[PATH_MAX];
-    int rc = __libc_Back_ioFHToPath(fh, szFilename, sizeof(szFilename));
+    __LIBC_PFH pFH = __libc_FH(fh);
+    if (pFH && pFH->pFsInfo)
+        strcpy(szFilename, pFH->pFsInfo->szMountpoint);
+    else
+        rc = __libc_Back_ioFHToPath(fh, szFilename, sizeof(szFilename));
     if (!rc)
     {
Index: trunk/src/emx/src/lib/sys/b_ioFileOpen.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/b_ioFileOpen.c	(revision 2048)
@@ -182,5 +182,5 @@
         if (   (ulAction == FILE_CREATED)
             && !__libc_gfNoUnix)
-            __libc_back_fsUnixAttribsSet(hFile, pszFile, Mode, &Dev, &Inode);
+            __libc_back_fsUnixAttribsSet(hFile, szNativePath, Mode, &Dev, &Inode);
         else
             Dev = __libc_back_fsPathCalcInodeAndDev(szNativePath, &Inode);
@@ -216,6 +216,7 @@
                 if (ppFH)
                 {
+                    (*ppFH)->Inode = Inode;
                     (*ppFH)->Dev = Dev;
-                    (*ppFH)->Inode = Inode;
+                    (*ppFH)->pFsInfo = __libc_back_fsInfoObjByDev(Dev);
                 }
                 LIBCLOG_MSG("hFile=%#lx fLibc=%#x fulType=%#lx ulAction=%lu Dev=%#x Inode=%#llx\n",
Index: trunk/src/emx/src/lib/sys/b_ioFileSizeSet.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_ioFileSizeSet.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/b_ioFileSizeSet.c	(revision 2048)
@@ -43,7 +43,7 @@
 *   Global Variables                                                           *
 *******************************************************************************/
-/** A page of zeros. 
+/** A page of zeros.
  * @todo Make this a separate segment for optimal thunking effiency! */
-static const char __libc_gachZeros[65536 - 4096]; 
+static const char __libc_gachZeros[65536 - 4096];
 
 
@@ -193,5 +193,7 @@
                      */
                     off_t   cbLeft = cbFile - cbCur;
-                    if (cbLeft <= 0 || !fZero)
+                    if (    cbLeft <= 0
+                        ||  !fZero
+                        || (pFH->pFsInfo && pFH->pFsInfo->fZeroNewBytes))
                     {
                         FS_RESTORE();
Index: trunk/src/emx/src/lib/sys/filehandles.c
===================================================================
--- trunk/src/emx/src/lib/sys/filehandles.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/filehandles.c	(revision 2048)
@@ -52,4 +52,5 @@
 #include <emx/umalloc.h>
 #include "syscalls.h"
+#include "b_fs.h"
 
 #define __LIBC_LOG_GROUP    __LIBC_LOG_GRP_INITTERM
@@ -169,4 +170,5 @@
             __LIBC_PSPMINHFHBHDR    pHdr;
             __LIBC_PSPMINHFHBSTD    pStds;
+            __LIBC_PSPMINHFHBSTDOLD pStdsOld;
             __LIBC_PSPMINHFHBSOCK   pSockets;
             uintptr_t               u;
@@ -184,5 +186,22 @@
                     for (i = 0; i < c; i++)
                     {
-                        if (fhAllocate(iFH, u.pStds->afFlags[i], sizeof(__LIBC_FH), NULL, NULL, NULL, 0))
+                        __LIBC_PFH pFH;
+                        if (fhAllocate(iFH, u.pStds->aHandles[i].fFlags, sizeof(__LIBC_FH), NULL, &pFH, NULL, 0))
+                        {
+                            LIBC_ASSERTM_FAILED("Failed to allocated inherited file handle! iFH=%d\n", iFH);
+                            __libc_spmInheritRelease();
+                            return -1;
+                        }
+                        pFH->Dev = u.pStds->aHandles[i].Inode;
+                        pFH->Inode = u.pStds->aHandles[i].Dev;
+                        pFH->pFsInfo = __libc_back_fsInfoObjByDev(pFH->Dev);
+                    }
+                    u.pv = &u.pStds->aHandles[c];
+                    break;
+
+                case __LIBC_SPM_INH_FHB_TYPE_STANDARD_OLD:
+                    for (i = 0; i < c; i++)
+                    {
+                        if (fhAllocate(iFH, u.pStdsOld->afFlags[i], sizeof(__LIBC_FH), NULL, NULL, NULL, 0))
                         {
                             LIBC_ASSERTM_FAILED("Failed to allocated inherited file handle! iFH=%d\n", iFH);
@@ -191,5 +210,5 @@
                         }
                     }
-                    u.pv = &u.pStds->afFlags[c];
+                    u.pv = &u.pStdsOld->afFlags[c];
                     break;
 
@@ -365,5 +384,7 @@
                 for (i = 0; ; )
                 {
-                    u.pStds->afFlags[i] = gpapFHs[iFH]->fFlags;
+                    u.pStds->aHandles[i].fFlags = gpapFHs[iFH]->fFlags;
+                    u.pStds->aHandles[i].Inode  = gpapFHs[iFH]->Inode;
+                    u.pStds->aHandles[i].Dev    = gpapFHs[iFH]->Dev;
                     /* next */
                     i++; iFH++;
@@ -377,5 +398,5 @@
                 /* commit the bundle. */
                 u.pStds->Hdr.cHandles = i;
-                u.pv = &u.pStds->afFlags[i];
+                u.pv = &u.pStds->aHandles[i];
                 break;
             }
@@ -741,4 +762,5 @@
             pFH->Inode  = ++_sys_ino;
         pFH->Dev        = 0;
+        pFH->pFsInfo    = NULL;
 
         /*
Index: trunk/src/emx/src/lib/sys/fs.c
===================================================================
--- trunk/src/emx/src/lib/sys/fs.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/fs.c	(revision 2048)
@@ -182,4 +182,10 @@
 
 
+/** Array of pointers to fs info objects for all
+ * possible OS/2 volumes.
+ */
+static __LIBC_FSINFO  g_aFSInfoVolumes['Z' - 'A' + 1];
+/** Mutex semaphore protecting the g_aFSInfoVolumes array. */
+static _fmutex        g_mtxFSInfoVolumes = _FMUTEX_INITIALIZER_EX(_FMC_MUST_COMPLETE, "mtxFSInfoVolumes");
 
 /*******************************************************************************
@@ -1328,7 +1334,5 @@
     else
     {
-        /* ASSUMES that pszNativePath contains a driveletter! If not fix the resolver!!! */
-        if (chDrv >= 'a' && chDrv <= 'z')
-            chDrv -= 'a' - 'A';
+        LIBC_ASSERT(chDrv >= 'A' && chDrv <= 'Z');
         Dev = makedev('V', chDrv);      /* V as in Volume */
     }
@@ -1465,5 +1469,5 @@
     else
     {
-        /* ASSUMES that pszNativePath contains a driveletter! If not fix the resolver!!! */
+        LIBC_ASSERT(chDrv >= 'A' && chDrv <= 'Z');
         if (chDrv >= 'a' && chDrv <= 'z')
             chDrv -= 'a' - 'A';
@@ -1479,4 +1483,130 @@
     *pInode = ((uint64_t)crc32str(psz) << 32) | (uint64_t)sdbm(psz);
     return Dev;
+}
+
+
+/**
+ * Updates the FS info object.
+ */
+static void fsInfoObjUpdate(__LIBC_PFSINFO pFsInfo, dev_t Dev)
+{
+    static char achBuffer[384]; /* we're protected by the mutex, don't assume too much stack! */
+    ULONG       cb = sizeof(achBuffer);
+    PFSQBUFFER2 pfsqb = (PFSQBUFFER2)achBuffer;
+
+    /* init the structure */
+    pFsInfo->fZeroNewBytes = 0;
+    pFsInfo->Dev = Dev;
+    pFsInfo->szName[0] = '\0';
+    pFsInfo->szMountpoint[0] = minor(Dev);
+    pFsInfo->szMountpoint[1] = ':';
+    pFsInfo->szMountpoint[2] = '\0';
+    pFsInfo->szMountpoint[3] = '\0';
+
+    /* query fs info */
+    FS_VAR_SAVE_LOAD();
+    int rc = DosQueryFSAttach((PCSZ)pFsInfo->szMountpoint, 0, FSAIL_QUERYNAME, pfsqb, &cb);
+    LIBC_ASSERTM(!rc, "rc=%d\n", rc);
+    if (!rc)
+        strncat(pFsInfo->szName, (const char *)&pfsqb->szName[pfsqb->cbName + 1], sizeof(pFsInfo->szName) - 1);
+    if (    !strcmp(pFsInfo->szName, "JFS")
+        ||  !strcmp(pFsInfo->szName, "HPFS")
+        ||  !strcmp(pFsInfo->szName, "FAT")
+        ||  !strcmp(pFsInfo->szName, "LAN"))
+        pFsInfo->fZeroNewBytes = 1;   /* RAMFS does not do this. */
+    LIBCLOG_MSG2("fsInfoObjUpdate: dev:%#x mp:%s fsd:%s fZeroNewBytes=%d\n",
+                 pFsInfo->Dev, pFsInfo->szMountpoint, pFsInfo->szName, pFsInfo->fZeroNewBytes);
+    FS_RESTORE();
+}
+
+
+/**
+ * Gets the fs info object for the specfied path.
+ *
+ * @returns Pointer to info object for the path, if it got one.
+ * @param   Dev     The device we want the file system object for.
+ */
+__LIBC_PFSINFO __libc_back_fsInfoObjByDev(dev_t Dev)
+{
+    __LIBC_PFSINFO pFsInfo = NULL;
+    char    chDrv = minor(Dev);
+    if (    major(Dev) == 'V'
+        &&  chDrv >= 'A' && chDrv <= 'Z')
+    {
+        pFsInfo = &g_aFSInfoVolumes[(int)chDrv];
+        _fmutex_request(&g_mtxFSInfoVolumes, 0);
+        int cRefs = __atomic_increment_s32(&pFsInfo->cRefs);
+        LIBC_ASSERT(cRefs > 0);
+        if (cRefs <= 0)
+            pFsInfo->cRefs = cRefs = 1;
+        if (cRefs == 1)
+            fsInfoObjUpdate(pFsInfo, Dev);
+        _fmutex_release(&g_mtxFSInfoVolumes);
+    }
+    else
+        LIBC_ASSERT(chDrv == '/' || chDrv == '\\');
+
+    return pFsInfo;
+}
+
+
+#if 0
+/**
+ * Gets the fs info object for the specfied path.
+ *
+ * @returns Pointer to info object for the path, if it got one.
+ * @param   pszNativePath   The native path as returned by the resolver.
+ */
+__LIBC_PFSINFO __libc_back_fsInfoObjByPath(const char *pszNativePath)
+{
+    /*
+     * Calc device.
+     */
+    dev_t   Dev;
+    char    chDrv = *pszNativePath;
+    if (chDrv == '/' || chDrv == '\\')
+        Dev = makedev('U', 0);          /* U as in UNC */
+    else
+    {
+        LIBC_ASSERT(chDrv >= 'A' && chDrv <= 'Z');
+        Dev = makedev('V', chDrv);      /* V as in Volume */
+    }
+    return __libc_back_fsInfoObjByDev(Dev);
+}
+#endif
+
+
+/**
+ * Adds a reference to an existing FS info object.
+ *
+ * The caller is responsible for making sure that the object cannot
+ * reach 0 references while inside this function.
+ *
+ * @returns pFsInfo.
+ * @param   pFsInfo     Pointer to the fs info object to reference.
+ */
+__LIBC_PFSINFO __libc_back_fsInfoObjAddRef(__LIBC_PFSINFO pFsInfo)
+{
+    if (pFsInfo)
+    {
+        int cRefs = __atomic_increment_s32(&pFsInfo->cRefs);
+        LIBC_ASSERT(cRefs > 1); (void)cRefs;
+    }
+    return pFsInfo;
+}
+
+
+/**
+ * Releases the fs info object for the specfied path.
+ *
+ * @param   pFsInfo     Pointer to the fs info object to release a reference to.
+ */
+void __libc_back_fsInfoObjRelease(__LIBC_PFSINFO pFsInfo)
+{
+    if (pFsInfo)
+    {
+        int cRefs = __atomic_decrement_s32(&pFsInfo->cRefs);
+        LIBC_ASSERT(cRefs > 1); (void)cRefs;
+    }
 }
 
Index: trunk/src/emx/src/lib/sys/tcpipver.c
===================================================================
--- trunk/src/emx/src/lib/sys/tcpipver.c	(revision 2047)
+++ trunk/src/emx/src/lib/sys/tcpipver.c	(revision 2048)
@@ -70,4 +70,5 @@
 #include <InnoTekLIBC/logstrict.h>
 
+#include "b_fs.h"
 
 /*******************************************************************************
@@ -366,4 +367,5 @@
         pFHNew->core.Inode       = pFHSocket->core.Inode;
         pFHNew->core.Dev         = pFHSocket->core.Dev;
+        pFHNew->core.pFsInfo     = pFHSocket->core.pFsInfo;
         LIBCLOG_RETURN_MSG(0, "ret 0 (0x0) *pfhNew=%d\n", *pfhNew);
     }
