[PATCH] dosfs: Improved UTF-16 handling

sebastian.huber at embedded-brains.de sebastian.huber at embedded-brains.de
Mon Jun 18 15:11:51 UTC 2012


From: Sebastian Huber <sebastian.huber at embedded-brains.de>

Characters of long file names are encoded in UTF-16.  In order to avoid
UTF-16 to UTF-8 conversions the short file name is returned in case a
UTF-16 character with a code point value greater than 255 is found in a
long file name.
---
 cpukit/libfs/src/dosfs/msdos_conv.c                |   66 +-
 cpukit/libfs/src/dosfs/msdos_dir.c                 |   10 +
 testsuites/fstests/Makefile.am                     |    1 +
 testsuites/fstests/configure.ac                    |    1 +
 testsuites/fstests/fsdosfsimage01/Makefile.am      |   19 +
 .../fstests/fsdosfsimage01/fsdosfsimage01.doc      |   11 +
 .../fstests/fsdosfsimage01/fsdosfsimage01.scn      |   15 +
 testsuites/fstests/fsdosfsimage01/image.h          | 5474 ++++++++++++++++++++
 testsuites/fstests/fsdosfsimage01/init.c           |  195 +
 9 files changed, 5742 insertions(+), 50 deletions(-)
 create mode 100644 testsuites/fstests/fsdosfsimage01/Makefile.am
 create mode 100644 testsuites/fstests/fsdosfsimage01/fsdosfsimage01.doc
 create mode 100644 testsuites/fstests/fsdosfsimage01/fsdosfsimage01.scn
 create mode 100644 testsuites/fstests/fsdosfsimage01/image.h
 create mode 100644 testsuites/fstests/fsdosfsimage01/init.c

diff --git a/cpukit/libfs/src/dosfs/msdos_conv.c b/cpukit/libfs/src/dosfs/msdos_conv.c
index 95b2581..e75d3ec 100644
--- a/cpukit/libfs/src/dosfs/msdos_conv.c
+++ b/cpukit/libfs/src/dosfs/msdos_conv.c
@@ -185,56 +185,22 @@ static const uint8_t msdos_map[] = {
     '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,
-/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 20 */ 0x00, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, /*  !"#$%&' */
-/* 28 */ 0x28, 0x29, 0x00, 0x00, 0x00, 0x2D, 0x2E, 0x00, /* ()*+,-./ */
-/* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
-/* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
-/* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
-/* 48 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* HIJKLMNO */
-/* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
-/* 58 */ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* XYZ[\]^_ */
-/* 60 */ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
-/* 68 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* hijklmno */
-/* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* pqrstuvw */
-/* 78 */ 0x58, 0x59, 0x5A, 0x5B, 0x7C, 0x00, 0x7E, 0x00, /* xyz{|}~  */
-/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* B8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* C8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* D8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/* 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
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 80-87 */
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 88-8f */
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 90-97 */
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 98-9f */
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* a0-a7 */
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* a8-af */
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* b0-b7 */
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* b8-bf */
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* c0-c7 */
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* c8-cf */
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* d0-d7 */
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* d8-df */
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* e0-e7 */
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* e8-ef */
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* f0-f7 */
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff  /* f8-ff */
 };
 /*
  * Convert a unix filename to a DOS filename. Return -1 if wrong name is
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
index 8175614..9d43bf8 100644
--- a/cpukit/libfs/src/dosfs/msdos_dir.c
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -278,6 +278,16 @@ msdos_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
                     if (*p == '\0')
                         break;
 
+                    /*
+                     * If we have a real 16-bit char, then return the short
+                     * name.
+                     */
+                    if (*(p + 1) != 0)
+                    {
+                        lfn_start = FAT_FILE_SHORT_NAME;
+                        break;
+                    }
+
                     switch (q)
                     {
                         case 4:
diff --git a/testsuites/fstests/Makefile.am b/testsuites/fstests/Makefile.am
index 79aef75..6a8f646 100644
--- a/testsuites/fstests/Makefile.am
+++ b/testsuites/fstests/Makefile.am
@@ -1,6 +1,7 @@
 ACLOCAL_AMFLAGS = -I ../aclocal
 
 SUBDIRS = 
+SUBDIRS += fsdosfsimage01
 SUBDIRS += fsdosfssync01
 SUBDIRS += imfs_fserror
 SUBDIRS += imfs_fslink
diff --git a/testsuites/fstests/configure.ac b/testsuites/fstests/configure.ac
index 81967a9..2fb5c1a 100644
--- a/testsuites/fstests/configure.ac
+++ b/testsuites/fstests/configure.ac
@@ -77,6 +77,7 @@ AC_CHECK_SIZEOF([blkcnt_t])
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
+fsdosfsimage01/Makefile
 fsdosfssync01/Makefile
 imfs_fserror/Makefile
 imfs_fslink/Makefile
diff --git a/testsuites/fstests/fsdosfsimage01/Makefile.am b/testsuites/fstests/fsdosfsimage01/Makefile.am
new file mode 100644
index 0000000..8e1892c
--- /dev/null
+++ b/testsuites/fstests/fsdosfsimage01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = fsdosfsimage01
+fsdosfsimage01_SOURCES = init.c
+
+dist_rtems_tests_DATA = fsdosfsimage01.scn fsdosfsimage01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(fsdosfsimage01_OBJECTS)
+LINK_LIBS = $(fsdosfsimage01_LDLIBS)
+
+fsdosfsimage01$(EXEEXT): $(fsdosfsimage01_OBJECTS) $(fsdosfsimage01_DEPENDENCIES)
+	@rm -f fsdosfsimage01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.doc b/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.doc
new file mode 100644
index 0000000..573a343
--- /dev/null
+++ b/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: fsdosfsimage01
+
+directives:
+
+  TBD
+
+concepts:
+
+  - Ensure that dosfs can somehow cope with real UTF-16 file names
diff --git a/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.scn b/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.scn
new file mode 100644
index 0000000..2a493dd
--- /dev/null
+++ b/testsuites/fstests/fsdosfsimage01/fsdosfsimage01.scn
@@ -0,0 +1,15 @@
+*** TEST DOSFS IMAGE 1 ***
+dir: directory
+copying: file
+______~1: directory
+.: directory
+..: directory
+empty file: file
+.: directory
+..: directory
+__~1: directory
+__~2: file
+.: directory
+..: directory
+pr�zdn� soubor: file
+*** END OF TEST DOSFS IMAGE 1 ***
diff --git a/testsuites/fstests/fsdosfsimage01/image.h b/testsuites/fstests/fsdosfsimage01/image.h
new file mode 100644
index 0000000..e10a635
--- /dev/null
+++ b/testsuites/fstests/fsdosfsimage01/image.h
@@ -0,0 +1,5474 @@
+/*
+ *  Declarations for C structure representing binary file image.bin
+ *
+ *  WARNING: Automatically generated -- do not edit!
+ */
+
+#include <sys/types.h>
+
+static unsigned char image_bin[] = {
[... REMOVED ...]
+};
+
+static const size_t image_bin_size = sizeof(image_bin);
diff --git a/testsuites/fstests/fsdosfsimage01/init.c b/testsuites/fstests/fsdosfsimage01/init.c
new file mode 100644
index 0000000..d4e0155
--- /dev/null
+++ b/testsuites/fstests/fsdosfsimage01/init.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <info at embedded-brains.de>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include <rtems/libio.h>
+#include <rtems/blkdev.h>
+#include <rtems/dosfs.h>
+#include <rtems/bdbuf.h>
+#include <rtems/ramdisk.h>
+
+#include "image.h"
+
+#define BLOCK_SIZE 512
+
+#define BLOCK_COUNT (sizeof(image_bin) / BLOCK_SIZE)
+
+typedef struct {
+  const char *name;
+  bool is_dir;
+} dir_entry;
+
+static ramdisk disk_image = {
+  .block_size = BLOCK_SIZE,
+  .block_num = BLOCK_COUNT,
+  .area = &image_bin [0],
+  .initialized = true,
+  .malloced = false,
+  .trace = false,
+  .free_at_delete_request = false
+};
+
+static size_t list_directory(const dir_entry *entries, size_t entry)
+{
+  DIR *dir;
+  struct dirent *de;
+  int rv;
+
+  dir = opendir(".");
+  rtems_test_assert(dir != NULL);
+
+  while ((de = readdir(dir)) != NULL) {
+    const char *name = de->d_name;
+    int fd;
+    struct stat st;
+    bool is_dir;
+
+    fd = open(name, O_RDONLY);
+    rtems_test_assert(fd >= 0);
+
+    rv = fstat(fd, &st);
+    rtems_test_assert(rv == 0);
+
+    is_dir = S_ISDIR(st.st_mode);
+
+    printf("%s: %s\n", name, is_dir ? "directory" : "file");
+
+    rtems_test_assert(S_ISDIR(st.st_mode) || S_ISREG(st.st_mode));
+    rtems_test_assert(is_dir == entries [entry].is_dir);
+    rtems_test_assert(strcmp(name, entries [entry].name) == 0);
+
+    ++entry;
+
+    rv = close(fd);
+    rtems_test_assert(rv == 0);
+  }
+
+  rv = closedir(dir);
+  rtems_test_assert(rv == 0);
+
+  return entry;
+}
+
+static void Init(rtems_task_argument arg)
+{
+  const char *disk = "/dev/rda";
+  const char *mnt = "/mnt";
+  const char *const dirs [] = {
+    "/mnt",
+    "/mnt/dir",
+    "/mnt/______~1",
+    "/mnt/______~1/__~1"
+  };
+  const dir_entry entries [] = {
+    { "dir", true },
+    { "copying", false },
+    { "______~1", true },
+    { ".", true },
+    { "..", true },
+    { "empty file", false },
+    { ".", true },
+    { "..", true },
+    { "__~1", true },
+    { "__~2", false },
+    { ".", true },
+    { "..", true },
+    { "pr\341zdn\375 soubor", false }
+  };
+  rtems_status_code sc;
+  rtems_device_major_number major;
+  dev_t dev;
+  int rv;
+  size_t dir;
+  size_t entry = 0;
+
+  puts("\n\n*** TEST DOSFS IMAGE 1 ***");
+
+  sc = rtems_disk_io_initialize();
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  sc = rtems_io_register_driver(0, &ramdisk_ops, &major);
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  dev = rtems_filesystem_make_dev_t(major, 0);
+
+  sc = rtems_disk_create_phys(
+    dev,
+    BLOCK_SIZE,
+    BLOCK_COUNT,
+    ramdisk_ioctl,
+    &disk_image,
+    disk
+  );
+  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+  rv = mount_and_make_target_path(
+    disk,
+    mnt,
+    RTEMS_FILESYSTEM_TYPE_DOSFS,
+    RTEMS_FILESYSTEM_READ_WRITE,
+    NULL
+  );
+  rtems_test_assert(rv == 0);
+
+  for (dir = 0; dir < sizeof(dirs) / sizeof(dirs [0]); ++dir) {
+    rv = chdir(dirs [dir]);
+    rtems_test_assert(rv == 0);
+
+    entry = list_directory(entries, entry);
+  }
+
+  rv = chdir("/");
+  rtems_test_assert(rv == 0);
+
+  rv = unmount(mnt);
+  rtems_test_assert(rv == 0);
+
+  puts("*** END OF TEST DOSFS IMAGE 1 ***");
+
+  exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 6
+
+#define CONFIGURE_MAXIMUM_DRIVERS 3
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_FILESYSTEM_DOSFS
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
-- 
1.6.4.2




More information about the devel mailing list