* Do not use the valence as a way to determine if we hit EOF, since
         * it can be wrong.  Use the catalog's output only.
         */
-       if ((*(eofflag) == 0) && (lastdescp != NULL) && (lastdescp->cd_nameptr != NULL)) {
+       if ((*(eofflag) == 0) && (lastdescp != NULL)) {
 
                /* Remember last entry */
                if ((dirhint->dh_desc.cd_flags & CD_HASBUF) &&
                        dirhint->dh_desc.cd_flags &= ~CD_HASBUF;
                        vfs_removename((const char *)dirhint->dh_desc.cd_nameptr);
                }
-               dirhint->dh_desc.cd_namelen = lastdescp->cd_namelen;
-               dirhint->dh_desc.cd_nameptr = (const u_int8_t *)
-               vfs_addname((const char *)lastdescp->cd_nameptr, lastdescp->cd_namelen, 0, 0);
-               dirhint->dh_desc.cd_flags |= CD_HASBUF;
+               if (lastdescp->cd_nameptr != NULL) {
+                       dirhint->dh_desc.cd_namelen = lastdescp->cd_namelen;
+                       dirhint->dh_desc.cd_nameptr = (const u_int8_t *)
+                       vfs_addname((const char *)lastdescp->cd_nameptr, lastdescp->cd_namelen, 0, 0);
+                       dirhint->dh_desc.cd_flags |= CD_HASBUF;
+               } else {
+                       dirhint->dh_desc.cd_namelen = 0;
+                       dirhint->dh_desc.cd_nameptr = NULL;
+               }
                dirhint->dh_index = index - 1;
                dirhint->dh_desc.cd_cnid = lastdescp->cd_cnid;
                dirhint->dh_desc.cd_hint = lastdescp->cd_hint;
 
 
 /*
  * cat_create - create a node in the catalog
+ * using MacRoman encoding
  *
  * NOTE: both the catalog file and attribute file locks must
  *       be held before calling this function.
        }
 
        /*
-        * Update the text encoding (on disk and in descriptor).
+        * Update the text encoding (on disk and in descriptor),
+        * using hfs_pickencoding to get the new encoding when available.
         *
         * Note that hardlink inodes don't require a text encoding hint.
         */
        if (!std_hfs &&
            todir_cdp->cd_parentcnid != hfsmp->hfs_private_desc[FILE_HARDLINKS].cd_cnid &&
            todir_cdp->cd_parentcnid != hfsmp->hfs_private_desc[DIR_HARDLINKS].cd_cnid) {
-               recp->hfsPlusFile.textEncoding = kTextEncodingMacUnicode;
+#if !TARGET_OS_EMBEDDED
+               encoding = hfs_pickencoding(to_key->nodeName.unicode, to_key->nodeName.length);
+#else
+               encoding = kTextEncodingMacRoman;
+#endif
+               hfs_setencodingbits(hfsmp, encoding);
+               recp->hfsPlusFile.textEncoding = encoding;
+               if (out_cdp)
+                       out_cdp->cd_encoding = encoding;
        }
 
 #if CONFIG_HFS_STD
 
                namelen = cnp->ustr.length;
                /*
-                * For MacRoman encoded names, assume that its ascii and
-                * convert it directly in an attempt to avoid the more
+                * For MacRoman encoded names (textEncoding == 0), assume that it's ascii
+                * and convert it directly in an attempt to avoid the more
                 * expensive utf8_encodestr conversion.
                 */
                if ((namelen < maxnamelen) && (crp->hfsPlusFile.textEncoding == 0)) {
 
 #include <string.h>
 #include <assert.h>
 #include <Block.h>
+#include <sys/param.h>
 
 #include "fsck_messages.h"
 #include "fsck_keys.h"
        return 0;
 }
 
+static char* escapeCharactersXML(char *input_string)
+{
+    if (input_string == NULL) {
+        return NULL;
+    }
+
+    char *output_string = NULL;
+
+    // In the worst case, each character of the input_string could be a special character,
+    // Each special character can add at most 5 extra characters to the string.
+    char temp[MAXPATHLEN*6 + 1];
+    memset(temp, 0, MAXPATHLEN*6 + 1);
+
+    char *input_ptr = input_string;
+    char *temp_ptr = &temp[0];
+
+    while(*input_ptr != '\0') {
+        char c = *input_ptr;
+
+        switch (c) {
+            case '&': {
+                *temp_ptr = '&';
+                ++temp_ptr;
+                *temp_ptr = 'a';
+                ++temp_ptr;
+                *temp_ptr = 'm';
+                ++temp_ptr;
+                *temp_ptr = 'p';
+                ++temp_ptr;
+                *temp_ptr = ';';
+                ++temp_ptr;
+                break;
+            }
+
+            case '<': {
+                *temp_ptr = '&';
+                ++temp_ptr;
+                *temp_ptr = 'l';
+                ++temp_ptr;
+                *temp_ptr = 't';
+                ++temp_ptr;
+                *temp_ptr = ';';
+                ++temp_ptr;
+                break;
+            }
+
+            case '>': {
+                *temp_ptr = '&';
+                ++temp_ptr;
+                *temp_ptr = 'g';
+                ++temp_ptr;
+                *temp_ptr = 't';
+                ++temp_ptr;
+                *temp_ptr = ';';
+                ++temp_ptr;
+                break;
+            }
+
+            case '"': {
+                *temp_ptr = '&';
+                ++temp_ptr;
+                *temp_ptr = 'q';
+                ++temp_ptr;
+                *temp_ptr = 'u';
+                ++temp_ptr;
+                *temp_ptr = 'o';
+                ++temp_ptr;
+                *temp_ptr = 't';
+                ++temp_ptr;
+                *temp_ptr = ';';
+                ++temp_ptr;
+                break;
+            }
+
+            case '\'': {
+                *temp_ptr = '&';
+                ++temp_ptr;
+                *temp_ptr = 'a';
+                ++temp_ptr;
+                *temp_ptr = 'p';
+                ++temp_ptr;
+                *temp_ptr = 'o';
+                ++temp_ptr;
+                *temp_ptr = 's';
+                ++temp_ptr;
+                *temp_ptr = ';';
+                ++temp_ptr;
+                break;
+            }
+            default: {
+                *temp_ptr = c;
+                ++temp_ptr;
+            }
+        }
+        ++input_ptr;
+    }
+
+    output_string = strdup((const char *)(&temp));
+    return output_string;
+}
+
 /*
  * fsckPrintXML(context, message, va_list)
  * Print out a message in XML (well, plist) format.
 static int
 fsckPrintXML(struct context *ctx, fsck_message_t *m, va_list ap) 
 {
-       char *newmsg = convertfmt(m->msg);
+    char *newmsg = convertfmt(m->msg);
        /* See convertfmt() for details */
        if (newmsg == NULL) {
                return -1;
                                printargs(ctx, "\t\t\t<integer>%llu</integer>\n", x);
                        } else if (m->argtype[i] == fsckTypeString) {
                                char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<string>%s</string>\n", p);
+                char *escapedP = escapeCharactersXML(p);
+                               printargs(ctx, "\t\t\t<string>%s</string>\n", escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypePath) {
-                               char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamPathKey, p);
+                char *p = va_arg(ap, char*);
+                char *escapedP = escapeCharactersXML(p);
+                printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamPathKey, escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypeFile) {
-                               char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamFileKey, p);
+                char *p = va_arg(ap, char*);
+                char *escapedP = escapeCharactersXML(p);
+                printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamFileKey, escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypeDirectory) {
-                               char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamDirectoryKey, p);
+                char *p = va_arg(ap, char*);
+                char *escapedP = escapeCharactersXML(p);
+                printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamDirectoryKey, escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypeVolume) {
-                               char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamVolumeKey, p);
+                char *p = va_arg(ap, char*);
+                char *escapedP = escapeCharactersXML(p);
+                printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamVolumeKey, escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypeFSType) {
-                               char *p = va_arg(ap, char*);
-                               printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamFSTypeKey, p);
+                char *p = va_arg(ap, char*);
+                char *escapedP = escapeCharactersXML(p);
+                printargs(ctx, "\t\t\t<dict><key>%s</key> <string>%s</string></dict>\n", kfsckParamFSTypeKey, escapedP);
+                free(escapedP);
                        } else if (m->argtype[i] == fsckTypeProgress) {
                                int x = va_arg(ap, int);
                                printargs(ctx, "\t\t\t<integer>%d</integer>\n", x);