summaryrefslogtreecommitdiffstats
path: root/cpukit/libfs/src/dosfs/msdos_misc.c
diff options
context:
space:
mode:
authorRalf Kirchner <ralf.kirchner@embedded-brains.de>2013-05-22 12:16:18 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-06-03 17:28:40 +0200
commitd2e0bb36e34f1fe45641f26b8b8d6ef615963854 (patch)
tree3975c03a1f0b0caff9d837ba1d989794f8537639 /cpukit/libfs/src/dosfs/msdos_misc.c
parentbsp/lm3s69xx: Typos (diff)
downloadrtems-d2e0bb36e34f1fe45641f26b8b8d6ef615963854.tar.bz2
dosfs: UTF-8 Support: UI, backwards compatibility
User interface and backwards compatibility for UTF-8 support in the FAT file system. Purpose of UTF-8 support is to permit file names and directory names with characters from all kinds of languages (Czech, Chinese, Arabian, Hebrew, Korean, ...). This commit does not yet support multibyte characters. It only contains the user interface and the backwards compatibility.
Diffstat (limited to 'cpukit/libfs/src/dosfs/msdos_misc.c')
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c1028
1 files changed, 739 insertions, 289 deletions
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
index 88f0b94bbd..56b58c85f7 100644
--- a/cpukit/libfs/src/dosfs/msdos_misc.c
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -9,6 +9,9 @@
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
*
+ * Modifications to support UTF-8 in the file system are
+ * Copyright (c) 2013 embedded brains GmbH.
+ *
* 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.
@@ -26,6 +29,8 @@
#include <unistd.h>
#include <string.h>
#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
#include <rtems/libio_.h>
#include "fat.h"
@@ -69,7 +74,7 @@ msdos_is_valid_name_char(const char ch)
return MSDOS_NAME_LONG;
if ((ch == '.') || isalnum((unsigned char)ch) ||
- (strchr("$%'-_@~`!(){}^#&", ch) != NULL))
+ (strchr("$%'-_@~`!(){}^#&", ch) != NULL) || (unsigned char) ch > 127)
return MSDOS_NAME_SHORT;
return MSDOS_NAME_INVALID;
@@ -192,10 +197,18 @@ msdos_name_type(const char *name, int name_len)
*/
#define MSDOS_L2S_PRINT 0
msdos_name_type_t
-msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
+msdos_long_to_short(rtems_dosfs_convert_control *converter,
+ const char *lfn,
+ int lfn_len,
+ char *sfn,
+ int sfn_len)
{
msdos_name_type_t type;
+ int eno = 0;
int i;
+ ssize_t short_filename_length = sfn_len;
+ void *buffer = converter->buffer.data;
+ size_t codepage_name_len = converter->buffer.size;
/*
* Fill with spaces. This is how a short directory entry is padded.
@@ -242,21 +255,46 @@ msdos_long_to_short(const char *lfn, int lfn_len, char* sfn, int sfn_len)
* Is this a short name ?
*/
- type = msdos_name_type (lfn, lfn_len);
+ eno = (*converter->handler->utf8_to_codepage) (
+ converter,
+ (const uint8_t*)&lfn[0],
+ lfn_len,
+ buffer,
+ &codepage_name_len);
+ if (eno == EINVAL)
+ {
+ eno = 0;
+ type = MSDOS_NAME_LONG;
+ }
+ else
+ {
+ type = msdos_name_type (
+ buffer,
+ codepage_name_len);
+ }
- if (type == MSDOS_NAME_INVALID)
+ if (type != MSDOS_NAME_INVALID)
{
+ short_filename_length = msdos_filename_utf8_to_short_name_for_save (
+ converter,
+ (const uint8_t*)lfn,
+ lfn_len,
+ sfn,
+ short_filename_length);
+ if (short_filename_length < 0 ) {
+ type = MSDOS_NAME_INVALID;
+ }
#if MSDOS_L2S_PRINT
- printf ("MSDOS_L2S: INVALID[2]: lfn:'%s' SFN:'%s'\n", lfn, sfn);
+ printf ("MSDOS_L2S: TYPE:%d lfn:'%s' SFN:'%s'\n", type, lfn, sfn);
#endif
- return MSDOS_NAME_INVALID;
}
-
- msdos_filename_unix2dos (lfn, lfn_len, sfn);
-
+ else
+ {
#if MSDOS_L2S_PRINT
- printf ("MSDOS_L2S: TYPE:%d lfn:'%s' SFN:'%s'\n", type, lfn, sfn);
+ printf ("MSDOS_L2S: INVALID[2]: lfn:'%s' SFN:'%s'\n", lfn, sfn);
#endif
+ }
+
return type;
}
@@ -292,13 +330,15 @@ msdos_find_name(
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);
+ name_type = msdos_long_to_short (
+ fs_info->converter,
+ name,
+ name_len,
+ MSDOS_DIR_NAME(node_entry),
+ MSDOS_NAME_MAX);
/*
- * find the node which correspondes to the name in the directory pointed by
+ * find the node which corresponds to the name in the directory pointed by
* 'parent_loc'
*/
rc = msdos_get_name_node(parent_loc, false, name, name_len, name_type,
@@ -426,7 +466,7 @@ msdos_get_name_node(
/* 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,
+ create_node, (const uint8_t*)name, name_len, name_type,
dir_pos, name_dir_entry);
if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
return rc;
@@ -518,6 +558,7 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
char dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
uint32_t cl4find = 0;
+ rtems_dosfs_convert_control *converter = fs_info->converter;
/*
* open fat-file corresponded to ".."
@@ -542,8 +583,10 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
/* find "." node in opened directory */
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_long_to_short(
+ converter,
+ ".", 1, dot_node, MSDOS_SHORT_NAME_LEN);
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, (const uint8_t*)".", 1,
MSDOS_NAME_SHORT, dir_pos, dot_node);
if (rc != RC_OK)
@@ -554,8 +597,10 @@ msdos_get_dotdot_dir_info_cluster_num_and_offset(
/* find ".." node in opened directory */
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_long_to_short(
+ converter,
+ "..", 2, dotdot_node, MSDOS_SHORT_NAME_LEN);
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, false, (const uint8_t*)"..", 2,
MSDOS_NAME_SHORT, dir_pos,
dotdot_node);
@@ -914,118 +959,348 @@ msdos_dir_is_empty(
return RC_OK;
}
-/* 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.
+#define MSDOS_FIND_PRINT 0
+static int
+msdos_on_entry_found (
+ msdos_fs_info_t *fs_info,
+ fat_file_fd_t *fat_fd,
+ const uint32_t bts2rd,
+ char *name_dir_entry,
+ char *entry,
+ fat_dir_pos_t *dir_pos,
+ uint32_t *dir_offset,
+ const uint32_t dir_entry,
+ const fat_pos_t *lfn_start
+)
+{
+ int rc = RC_OK;
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[9.3] SNF found\n");
+#endif
+ /*
+ * We get the entry we looked for - fill the position
+ * structure and the 32 bytes of the short entry
+ */
+ rc = fat_file_ioctl(&fs_info->fat,
+ fat_fd,
+ F_CLU_NUM,
+ *dir_offset * bts2rd,
+ &dir_pos->sname.cln);
+ if (rc == RC_OK) {
+ dir_pos->sname.ofs = dir_entry;
+
+ if (lfn_start->cln != FAT_FILE_SHORT_NAME)
+ {
+ rc = fat_file_ioctl (&fs_info->fat,
+ fat_fd,
+ F_CLU_NUM,
+ lfn_start->cln * bts2rd,
+ &lfn_start->cln);
+ }
+ if ( rc == RC_OK ) {
+ 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;
+}
+
+ssize_t
+msdos_get_utf16_string_from_long_entry (
+ const char *entry,
+ uint16_t *entry_string_buf,
+ const size_t buf_size,
+ bool is_first_entry
+)
+{
+ ssize_t chars_in_entry;
+
+ if (buf_size >= MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR) {
+ memcpy (&entry_string_buf[0], &entry[1], 10 );
+ memcpy (&entry_string_buf[5], &entry[14], 12 );
+ memcpy (&entry_string_buf[11], &entry[28], 4 );
+
+ if (is_first_entry) {
+ for (chars_in_entry = 0;
+ ( entry_string_buf[chars_in_entry] != 0x0000
+ && chars_in_entry < MSDOS_LFN_LEN_PER_ENTRY );
+ ++chars_in_entry) {
+ ;
+ }
+ }
+ else
+ chars_in_entry = MSDOS_LFN_LEN_PER_ENTRY;
+
+ return chars_in_entry * MSDOS_NAME_LFN_BYTES_PER_CHAR;
+ }
+ else
+ return ENOMEM;
+}
+
+/* msdos_format_dirent_with_dot --
+ * This routine convert a (short) MSDOS filename as present on disk
+ * (fixed 8+3 characters, filled with blanks, without separator dot)
+ * to a "normal" format, with between 0 and 8 name chars,
+ * a separating dot and up to 3 extension characters
+ * Rules to work:
+ * - copy any (0-8) "name" part characters that are non-blank
+ * - if an extension exists, append a dot
+ * - copy any (0-3) non-blank extension characters
+ * - append a '\0' (dont count it for the rturn code
*
* PARAMETERS:
- * mt_entry - mount table entry
- * fat_fd - fat-file descriptor
- * name - NULL or name to find
- * paux - identify a node location on the disk -
- * number of cluster and offset inside the cluster
- * name_dir_entry - node to create/placeholder for found node
+ * dst: pointer to destination char array (must be big enough)
+ * src: pointer to source characters
*
- * RETURNS:
- * RC_OK on success, or error code if error occured (errno set
- * appropriately)
*
+ * RETURNS:
+ * the number of bytes (without trailing '\0'(written to destination
*/
-#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,
- 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
- )
+ssize_t
+msdos_format_dirent_with_dot(char *dst,const char *src)
{
- ssize_t ret = 0;
- msdos_fs_info_t *fs_info = mt_entry->fs_info;
- 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;
- 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);
+ ssize_t len;
+ int i;
+ const char *src_tmp;
+
+ /*
+ * find last non-blank character of base name
+ */
+ for (i = MSDOS_SHORT_BASE_LEN, src_tmp = src + MSDOS_SHORT_BASE_LEN - 1;
+ i > 0 && *src_tmp == ' ';
+ --i,--src_tmp)
+ {};
+ /*
+ * copy base name to destination
+ */
+ src_tmp = src;
+ len = i;
+ while (i-- > 0) {
+ *dst++ = tolower((unsigned char)(*src_tmp++));
+ }
+ /*
+ * find last non-blank character of extension
+ */
+ for (i = MSDOS_SHORT_EXT_LEN,
+ src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1;
+ i > 0 && *src_tmp == ' ';
+ --i, --src_tmp)
+ {};
+ /*
+ * extension is not empty
+ */
+ if (i > 0) {
+ *dst++ = '.'; /* append dot */
+ ++len; /* dot */
+ src_tmp = src + MSDOS_SHORT_BASE_LEN;
+ while (i-- > 0) {
+ *dst++ = tolower((unsigned char)(*src_tmp++));
+ ++len;
+ }
+ }
+ *dst = '\0'; /* terminate string */
- fat_dir_pos_init(dir_pos);
+ return len;
+}
- lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+static ssize_t
+msdos_long_entry_to_utf8_name (
+ rtems_dosfs_convert_control *converter,
+ const char *entry,
+ const bool is_first_entry,
+ uint8_t *entry_utf8_buf,
+ const size_t buf_size)
+{
+ ssize_t retval = 0;
+ int eno = 0;
+ size_t bytes_in_utf8 = buf_size;
+ size_t bytes_in_buf;
+ uint16_t entry_string[MSDOS_LFN_LEN_PER_ENTRY];
+
+ retval = msdos_get_utf16_string_from_long_entry (
+ entry,
+ entry_string,
+ sizeof (entry_string),
+ is_first_entry
+ );
+
+ if (retval >= 0) {
+ bytes_in_buf = retval;
+ eno = (*converter->handler->utf16_to_utf8) (
+ converter,
+ &entry_string[0],
+ bytes_in_buf,
+ &entry_utf8_buf[0],
+ &bytes_in_utf8);
+ if ( eno == 0 ) {
+ retval = bytes_in_utf8;
+ }
+ }
- /*
- * Set the number of short entries needed to store the LFN. If the name
- * is short still check for possible long entries with the short name.
- *
- * In PR1491 we need to have a LFN for a short file name entry. To
- * test this make this test always fail, ie add "0 &&".
- */
- if (create_node && (name_type == MSDOS_NAME_SHORT))
- lfn_entries = 0;
- else
- lfn_entries =
- ((name_len - 1) + MSDOS_LFN_LEN_PER_ENTRY) / MSDOS_LFN_LEN_PER_ENTRY;
+ if (eno != 0) {
+ retval = -1;
+ errno = eno;
+ }
- if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
- (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
- bts2rd = fat_fd->fat_file_size;
- else
- bts2rd = fs_info->fat.vol.bpc;
+ return retval;
+}
- entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+static ssize_t msdos_short_entry_to_utf8_name (
+ rtems_dosfs_convert_control *converter,
+ const char *entry,
+ uint8_t *buf,
+ const size_t buf_size)
+{
+ char char_buf[MSDOS_NAME_MAX_WITH_DOT];
+ int eno = 0;
+ size_t bytes_converted = buf_size;
+ ssize_t bytes_written = msdos_format_dirent_with_dot(char_buf, entry);
+
+ if (bytes_written > 0) {
+ if (char_buf[0] == 0x05)
+ char_buf[0] = 0xE5;
+
+ eno = (*converter->handler->codepage_to_utf8) (
+ converter,
+ char_buf,
+ bytes_written,
+ buf,
+ &bytes_converted);
+ if (eno == 0)
+ bytes_written = bytes_converted;
+ } else {
+ eno = EINVAL;
+ }
+
+ if (eno != 0) {
+ bytes_written = -1;
+ errno = eno;
+ }
+
+ return bytes_written;
+}
-#if MSDOS_FIND_PRINT
- printf ("MSFS:[1] nt:%d, cn:%i ebp:%li bts2rd:%li lfne:%d nl:%i n:%s\n",
- name_type, create_node, entries_per_block, bts2rd,
- lfn_entries, name_len, name);
+static ssize_t
+msdos_compare_entry_against_filename (
+ rtems_dosfs_convert_control *converter,
+ const uint8_t *entry,
+ const size_t entry_size,
+ const uint8_t *filename,
+ const size_t filename_size_remaining,
+ bool *is_matching)
+{
+ ssize_t size_remaining = filename_size_remaining;
+ int eno = 0;
+ uint8_t entry_normalized[( MSDOS_LFN_LEN_PER_ENTRY + 1 ) * MSDOS_NAME_LFN_BYTES_PER_CHAR * MSDOS_NAME_MAX_UTF8_BYTES_PER_CHAR];
+ size_t bytes_in_entry_normalized = sizeof ( entry_normalized );
+
+ eno = (*converter->handler->utf8_normalize_and_fold) (
+ converter,
+ &entry[0],
+ entry_size,
+ &entry_normalized[0],
+ &bytes_in_entry_normalized);
+ if (eno == 0) {
+#if MSDOS_FIND_PRINT > 1
+ printf ( "MSFS:[6] entry_normalized:%s"
+ "name:%s\n",
+ entry,
+ filename );
#endif
+ if (bytes_in_entry_normalized <= size_remaining) {
+ size_remaining = size_remaining - bytes_in_entry_normalized;
+ if (0 == memcmp ( &entry_normalized[0],
+ &filename[size_remaining],
+ bytes_in_entry_normalized)) {
+ *is_matching = true;
+ } else {
+ *is_matching = false;
+ size_remaining = filename_size_remaining;
+ }
+
+ }
+ else {
+ *is_matching = false;
+ }
+ }
+
+ if (eno != 0) {
+ size_remaining = -1;
+ errno = eno;
+ }
+
+ return size_remaining;
+}
+
+static int
+msdos_find_file_in_directory (
+ const uint8_t *filename_converted,
+ const size_t name_len_for_compare,
+ const size_t name_len_for_save,
+ const msdos_name_type_t name_type,
+ msdos_fs_info_t *fs_info,
+ fat_file_fd_t *fat_fd,
+ const uint32_t bts2rd,
+ const bool create_node,
+ const unsigned int fat_entries,
+ char *name_dir_entry,
+ fat_dir_pos_t *dir_pos,
+ uint32_t *dir_offset,
+ uint32_t *empty_space_offset,
+ uint32_t *empty_space_entry,
+ uint32_t *empty_space_count)
+{
+ int rc = RC_OK;
+ ssize_t bytes_read;
+ uint32_t dir_entry;
+ fat_pos_t lfn_start;
+ uint8_t lfn_checksum = 0;
+ bool entry_matched = false;
+ bool empty_space_found = false;
+ uint32_t entries_per_block = bts2rd / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE;
+ int lfn_entry = 0;
+ uint8_t entry_utf8_normalized[(MSDOS_LFN_LEN_PER_ENTRY + 1 ) * MSDOS_NAME_LFN_BYTES_PER_CHAR * MSDOS_NAME_MAX_UTF8_BYTES_PER_CHAR/*MSDOS_ENTRY_LFN_UTF8_BYTES*/];
+ size_t bytes_in_entry;
+ bool filename_matched = false;
+ ssize_t filename_size_remaining = name_len_for_compare;
+ rtems_dosfs_convert_control *converter = fs_info->converter;
+
/*
* 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(&fs_info->fat, fat_fd, (dir_offset * bts2rd),
- bts2rd, fs_info->cl_buf)) != FAT_EOF)
+
+ lfn_start.cln = lfn_start.ofs = FAT_FILE_SHORT_NAME;
+
+ while ( (bytes_read = fat_file_read (&fs_info->fat, fat_fd, (*dir_offset * bts2rd),
+ bts2rd, fs_info->cl_buf)) != FAT_EOF
+ && rc == RC_OK)
{
bool remainder_empty = false;
#if MSDOS_FIND_PRINT
- printf ("MSFS:[2] dir_offset:%li\n", dir_offset);
+ printf ("MSFS:[2] dir_offset:%li\n", *dir_offset);
#endif
- if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ if (bytes_read < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
rtems_set_errno_and_return_minus_one(EIO);
- assert(ret == bts2rd);
+ assert(bytes_read == bts2rd);
/* have to look at the DIR_NAME as "raw" 8-bit data */
for (dir_entry = 0;
- dir_entry < bts2rd;
+ dir_entry < bts2rd && rc == RC_OK && (! filename_matched);
dir_entry += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
{
char* entry = (char*) fs_info->cl_buf + dir_entry;
/*
* See if the entry is empty or the remainder of the directory is
- * empty ? Localise to make the code read better.
+ * empty ? Localize to make the code read better.
*/
bool entry_empty = (*MSDOS_DIR_ENTRY_TYPE(entry) ==
MSDOS_THIS_DIR_ENTRY_EMPTY);
@@ -1033,7 +1308,7 @@ int msdos_find_name_in_fat_file(
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,
+ remainder_empty, entry_empty, *dir_offset,
dir_entry, (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE));
#endif
/*
@@ -1043,10 +1318,10 @@ int msdos_find_name_in_fat_file(
* we are currently not inside an empty series of entries. It
* is a count of empty entries.
*/
- if (empty_space_count == 0)
+ if (*empty_space_count == 0)
{
- empty_space_entry = dir_entry;
- empty_space_offset = dir_offset;
+ *empty_space_entry = dir_entry;
+ *empty_space_offset = *dir_offset;
}
if (remainder_empty)
@@ -1059,7 +1334,7 @@ int msdos_find_name_in_fat_file(
* directory - return name-not-found
*/
if (!create_node)
- return MSDOS_NAME_NOT_FOUND_ERR;
+ rc = MSDOS_NAME_NOT_FOUND_ERR;
/*
* Lets go and write the directory entries. If we have not found
@@ -1067,13 +1342,14 @@ int msdos_find_name_in_fat_file(
* 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)
+ if ( !empty_space_found
+ && rc == RC_OK )
{
- empty_space_count +=
+ *empty_space_count +=
entries_per_block - (dir_entry / MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
- empty_space_found = true;
+ empty_space_found = true;
#if MSDOS_FIND_PRINT
- printf ("MSFS:[3.2] esf:%i esc%i\n", empty_space_found, empty_space_count);
+ printf ( "MSFS:[3.2] esf:%i esc%"PRIu32"\n", empty_space_found, *empty_space_count );
#endif
}
break;
@@ -1082,17 +1358,17 @@ int msdos_find_name_in_fat_file(
{
if (create_node)
{
- /*
- * Remainder is not empty so is this entry empty ?
- */
- empty_space_count++;
+ /*
+ * Remainder is not empty so is this entry empty ?
+ */
+ (*empty_space_count)++;
- if (empty_space_count == (lfn_entries + 1))
- empty_space_found = true;
+ if (*empty_space_count == (fat_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);
+ *empty_space_count, empty_space_found);
#endif
}
else
@@ -1105,8 +1381,8 @@ int msdos_find_name_in_fat_file(
*/
if (create_node && !empty_space_found)
{
- empty_space_entry = 0;
- empty_space_count = 0;
+ *empty_space_entry = 0;
+ *empty_space_count = 0;
}
/*
@@ -1116,9 +1392,7 @@ int msdos_find_name_in_fat_file(
if ((*MSDOS_DIR_ATTR(entry) & MSDOS_ATTR_LFN_MASK) ==
MSDOS_ATTR_LFN)
{
- char* p;
- int o;
- int i;
+/* int o;*/
#if MSDOS_FIND_PRINT
printf ("MSFS:[4.2] lfn:%c entry:%i checksum:%i\n",
lfn_start.cln == FAT_FILE_SHORT_NAME ? 'f' : 't',
@@ -1131,7 +1405,7 @@ int msdos_find_name_in_fat_file(
*/
if (lfn_start.cln == FAT_FILE_SHORT_NAME)
{
- lfn_matched = false;
+ entry_matched = false;
/*
* The first entry must have the last long entry
@@ -1148,21 +1422,21 @@ int msdos_find_name_in_fat_file(
* characters in the entry so this is check further
* on when the characters are checked.
*/
- if (lfn_entries != (*MSDOS_DIR_ENTRY_TYPE(entry) &
+ if (fat_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.cln = *dir_offset;
lfn_start.ofs = dir_entry;
- lfn_entry = lfn_entries;
+ lfn_entry = fat_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));
+ lfn_checksum);
#endif
}
@@ -1182,64 +1456,40 @@ int msdos_find_name_in_fat_file(
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')
- {
- /*
- * If this is the first entry, ie the last part of the
- * long file name and the length does not match then
- * the file names do not match.
- */
- if (((lfn_entry + 1) == lfn_entries) &&
- ((o + i) != name_len))
- lfn_start.cln = FAT_FILE_SHORT_NAME;
- break;
- }
+ lfn_entry--;
- if (((o + i) >= name_len) || (*p != name[o + i]))
- {
+ bytes_in_entry = msdos_long_entry_to_utf8_name (
+ converter,
+ entry,
+ (lfn_entry + 1) == fat_entries,
+ &entry_utf8_normalized[0],
+ sizeof (entry_utf8_normalized));
+ if (bytes_in_entry > 0) {
+ filename_size_remaining = msdos_compare_entry_against_filename (
+ converter,
+ &entry_utf8_normalized[0],
+ bytes_in_entry,
+ &filename_converted[0],
+ filename_size_remaining,
+ &entry_matched);
+
+ if (filename_size_remaining < 0
+ || (! entry_matched)) {
+ filename_size_remaining = name_len_for_compare;
lfn_start.cln = FAT_FILE_SHORT_NAME;
- break;
- }
-
- switch (i)
- {
- case 4:
- p += 5;
- break;
- case 10:
- p += 4;
- break;
- default:
- p += 2;
- break;
}
+ } else {
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ entry_matched = false;
}
-
- 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
{
#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.1] SFN entry, lfn_matched:%i\n", lfn_matched);
+ printf ("MSFS:[9.1] SFN entry, entry_matched:%i\n", entry_matched);
#endif
/*
* SFN entry found.
@@ -1249,7 +1499,7 @@ int msdos_find_name_in_fat_file(
* correct. If this is the case return the short file
* name entry.
*/
- if (lfn_matched)
+ if (entry_matched)
{
uint8_t cs = 0;
uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(entry);
@@ -1259,81 +1509,117 @@ int msdos_find_name_in_fat_file(
cs = ((cs & 1) ? 0x80 : 0) + (cs >> 1) + *p;
if (lfn_entry || (lfn_checksum != cs))
- lfn_matched = false;
-#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.2] checksum, lfn_matched:%i, lfn_entry:%i, lfn_checksum:%02x/%02x\n",
- lfn_matched, lfn_entry, lfn_checksum, cs);
-#endif
- }
+ entry_matched = false;
+ else {
+ filename_matched = true;
+ rc = msdos_on_entry_found (
+ fs_info,
+ fat_fd,
+ bts2rd,
+ name_dir_entry,
+ entry,
+ dir_pos,
+ dir_offset,
+ dir_entry,
+ &lfn_start
+ );
+ }
- /*
- * If the long file names matched or the file name is
- * short and they match then we have the entry. We will not
- * match a long file name against a short file name because
- * a long file name that generates a matching short file
- * name is not a long file name.
- */
- if (lfn_matched ||
- ((name_type == MSDOS_NAME_SHORT) &&
- (lfn_start.cln == FAT_FILE_SHORT_NAME) &&
- (memcmp(MSDOS_DIR_NAME(entry),
- MSDOS_DIR_NAME(name_dir_entry),
- MSDOS_SHORT_NAME_LEN) == 0)))
- {
#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.3] SNF found\n");
+ printf ("MSFS:[9.2] checksum, entry_matched:%i, lfn_entry:%i, lfn_checksum:%02x/%02x\n",
+ entry_matched, lfn_entry, lfn_checksum, cs);
#endif
- /*
- * We get the entry we looked for - fill the position
- * structure and the 32 bytes of the short entry
- */
- int rc = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
- dir_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(&fs_info->fat, fat_fd, F_CLU_NUM,
- lfn_start.cln * bts2rd,
- &lfn_start.cln);
- if (rc != RC_OK)
- return rc;
+ } else {
+ bytes_in_entry = MSDOS_SHORT_NAME_LEN + 1;
+ bytes_in_entry = msdos_short_entry_to_utf8_name (
+ converter,
+ MSDOS_DIR_NAME (entry),
+ &entry_utf8_normalized[0],
+ bytes_in_entry);
+ if (bytes_in_entry > 0) {
+ filename_size_remaining = msdos_compare_entry_against_filename (
+ converter,
+ &entry_utf8_normalized[0],
+ bytes_in_entry,
+ &filename_converted[0],
+ name_len_for_compare,
+ &entry_matched);
+ if (entry_matched && filename_size_remaining == 0) {
+ filename_matched = true;
+ rc = msdos_on_entry_found (
+ fs_info,
+ fat_fd,
+ bts2rd,
+ name_dir_entry,
+ entry,
+ dir_pos,
+ dir_offset,
+ dir_entry,
+ &lfn_start
+ );
+ }
+ if (rc == RC_OK && (! filename_matched)) {
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ entry_matched = false;
+ filename_size_remaining = name_len_for_compare;
+ }
+ } else {
+ lfn_start.cln = FAT_FILE_SHORT_NAME;
+ entry_matched = false;
+ filename_size_remaining = name_len_for_compare;
}
-
- 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;
}
}
}
- if (remainder_empty)
+ if (filename_matched || remainder_empty)
break;
- dir_offset++;
+ (*dir_offset)++;
}
-
- /*
- * If we are not to create the entry return a not found error.
- */
- if (!create_node)
- return MSDOS_NAME_NOT_FOUND_ERR;
+ if ( ! filename_matched ) {
+ /*
+ * If we are not to create the entry return a not found error.
+ */
+ if (!create_node)
+ rc = 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);
+ printf ( "MSFS:[8.1] WRITE do:%"PRIu32" esc:%"PRIu32" eso:%"PRIu32" ese:%"PRIu32"\n",
+ *dir_offset, *empty_space_count, *empty_space_offset, *empty_space_entry );
#endif
+ }
+
+ return rc;
+}
+
+static int
+msdos_add_file (
+ const char *name_converted,
+ const msdos_name_type_t name_type,
+ msdos_fs_info_t *fs_info,
+ fat_file_fd_t *fat_fd,
+ const uint32_t bts2rd,
+ const unsigned int fat_entries,
+ const char *name_dir_entry,
+ fat_dir_pos_t *dir_pos,
+ const uint32_t dir_offset,
+ const uint32_t empty_space_offset_param,
+ const uint32_t empty_space_entry_param,
+ const uint32_t empty_space_count
+
+)
+{
+ int ret = 0;
+ ssize_t bytes_written = 0;
+ uint8_t lfn_checksum = 0;
+ uint32_t empty_space_offset = empty_space_offset_param;
+ uint32_t empty_space_entry = empty_space_entry_param;
+ bool read_cluster = false;
+ int lfn_entry = 0;
+ fat_pos_t lfn_start;
+ uint32_t dir_entry;
/*
* If a long file name calculate the checksum of the short file name
@@ -1341,15 +1627,14 @@ int msdos_find_name_in_fat_file(
* 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)
{
int slot = (((empty_space_offset * bts2rd) + empty_space_entry) /
- MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) + lfn_entries + 1;
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE) + fat_entries + 1;
msdos_short_name_hex(MSDOS_DIR_NAME(name_dir_entry), slot);
}
- if (lfn_entries)
+ if (fat_entries)
{
uint8_t* p = (uint8_t*) MSDOS_DIR_NAME(name_dir_entry);
int i;
@@ -1392,53 +1677,53 @@ int msdos_find_name_in_fat_file(
/*
* The one more is the short entry.
*/
- while (lfn_entry < (lfn_entries + 1))
+ while (lfn_entry < (fat_entries + 1))
{
int length = 0;
if (read_cluster)
{
- uint32_t new_length;
+ uint32_t new_length;
#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.1] eso:%li\n", empty_space_offset);
+ printf ("MSFS:[9.1] eso:%li\n", empty_space_offset);
#endif
- ret = fat_file_read(&fs_info->fat, fat_fd,
- (empty_space_offset * bts2rd), bts2rd,
- fs_info->cl_buf);
+ ret = fat_file_read(&fs_info->fat, 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 (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);
+ printf ("MSFS:[9.2] extending file:%li\n", empty_space_offset);
#endif
- ret = fat_file_extend (&fs_info->fat, fat_fd, false,
- empty_space_offset * bts2rd, &new_length);
+ ret = fat_file_extend (&fs_info->fat, fat_fd, false,
+ empty_space_offset * bts2rd, &new_length);
- if (ret != RC_OK)
- return ret;
+ if (ret != RC_OK)
+ return ret;
#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.3] extended: %d <-> %d\n", new_length, empty_space_offset * bts2rd);
+ printf ("MSFS:[9.3] extended: %"PRIu32" <-> %"PRIu32"\n", new_length, empty_space_offset * bts2rd);
#endif
- if (new_length != (empty_space_offset * bts2rd))
- rtems_set_errno_and_return_minus_one(EIO);
+ if (new_length != (empty_space_offset * bts2rd))
+ rtems_set_errno_and_return_minus_one(EIO);
- memset(fs_info->cl_buf, 0, bts2rd);
+ memset(fs_info->cl_buf, 0, bts2rd);
- ret = fat_file_write(&fs_info->fat, fat_fd,
- empty_space_offset * bts2rd,
- bts2rd, fs_info->cl_buf);
+ bytes_written = fat_file_write(&fs_info->fat, fat_fd,
+ empty_space_offset * bts2rd,
+ bts2rd, fs_info->cl_buf);
#if MSDOS_FIND_PRINT
- printf ("MSFS:[9.4] clear write: %d\n", ret);
+ printf ("MSFS:[9.4] clear write: %d\n", ret);
#endif
- if (ret == -1)
- return ret;
- else if (ret != bts2rd)
- rtems_set_errno_and_return_minus_one(EIO);
- }
+ if (bytes_written == -1)
+ return -1;
+ else if (bytes_written != bts2rd)
+ rtems_set_errno_and_return_minus_one(EIO);
+ }
}
#if MSDOS_FIND_PRINT
@@ -1466,24 +1751,24 @@ int msdos_find_name_in_fat_file(
/*
* Time to write the short file name entry.
*/
- if (lfn_entry == (lfn_entries + 1))
+ if (lfn_entry == (fat_entries + 1))
{
/* get current cluster number */
- int rc = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
- empty_space_offset * bts2rd,
- &dir_pos->sname.cln);
- if (rc != RC_OK)
- return rc;
+ ret = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
+ empty_space_offset * bts2rd,
+ &dir_pos->sname.cln);
+ if (ret != RC_OK)
+ return ret;
dir_pos->sname.ofs = dir_entry;
if (lfn_start.cln != FAT_FILE_SHORT_NAME)
{
- rc = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
- lfn_start.cln * bts2rd,
- &lfn_start.cln);
- if (rc != RC_OK)
- return rc;
+ ret = fat_file_ioctl(&fs_info->fat, fat_fd, F_CLU_NUM,
+ lfn_start.cln * bts2rd,
+ &lfn_start.cln);
+ if (ret != RC_OK)
+ return ret;
}
dir_pos->lname.cln = lfn_start.cln;
@@ -1503,8 +1788,8 @@ int msdos_find_name_in_fat_file(
*/
if (lfn_start.cln == FAT_FILE_SHORT_NAME)
{
- lfn_start.cln = empty_space_offset;
- lfn_start.ofs = dir_entry;
+ lfn_start.cln = empty_space_offset;
+ lfn_start.ofs = dir_entry;
}
/*
@@ -1515,14 +1800,17 @@ int msdos_find_name_in_fat_file(
*MSDOS_DIR_LFN_CHECKSUM(entry) = lfn_checksum;
p = entry + 1;
- n = name + (lfn_entries - lfn_entry) * MSDOS_LFN_LEN_PER_ENTRY;
+ n = name_converted + (fat_entries - lfn_entry) * MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR;
- for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; i++)
+#if MSDOS_FIND_PRINT
+ printf ("MSFS:[11] ");
+#endif
+ for (i = 0; i < MSDOS_LFN_LEN_PER_ENTRY; ++i)
{
- if (*n != 0)
+ if (!(*n == 0 && *(n+1) == 0))
{
*p = *n;
- n++;
+ *(p+1) = *(n+1);
}
else
{
@@ -1530,6 +1818,10 @@ int msdos_find_name_in_fat_file(
p [1] = fill;
fill = 0xff;
}
+ n += MSDOS_NAME_LFN_BYTES_PER_CHAR;
+#if MSDOS_FIND_PRINT
+ printf ( "'%c''%c'", *p, *(p+1) );
+#endif
switch (i)
{
@@ -1544,29 +1836,187 @@ int msdos_find_name_in_fat_file(
break;
}
}
-
- *MSDOS_DIR_ENTRY_TYPE(entry) = (lfn_entries - lfn_entry) + 1;
+#if MSDOS_FIND_PRINT
+ printf ( "\n" );
+#endif
+ *MSDOS_DIR_ENTRY_TYPE(entry) = (fat_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(&fs_info->fat, fat_fd,
- (empty_space_offset * bts2rd) + empty_space_entry,
- length, fs_info->cl_buf + empty_space_entry);
- if (ret == -1)
- return ret;
- else if (ret != length)
+ bytes_written = fat_file_write(&fs_info->fat, fat_fd,
+ (empty_space_offset * bts2rd) + empty_space_entry,
+ length, fs_info->cl_buf + empty_space_entry);
+ if (bytes_written == -1)
+ return -1;
+ else if (bytes_written != length)
rtems_set_errno_and_return_minus_one(EIO);
empty_space_offset++;
empty_space_entry = 0;
read_cluster = true;
}
+ return ret;
+}
+
+int
+msdos_find_name_in_fat_file (
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ bool create_node,
+ const uint8_t *name_utf8,
+ int name_utf8_len,
+ msdos_name_type_t name_type,
+ fat_dir_pos_t *dir_pos,
+ char *name_dir_entry)
+{
+ int retval = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ ssize_t name_len_for_save;
+ ssize_t name_len_for_compare;
+ uint32_t bts2rd = 0;
+ uint32_t empty_space_offset = 0;
+ uint32_t empty_space_entry = 0;
+ uint32_t empty_space_count = 0;
+ uint32_t dir_offset = 0;
+ unsigned int fat_entries;
+ rtems_dosfs_convert_control *converter = fs_info->converter;
+ void *buffer = converter->buffer.data;
+ size_t buffer_size = converter->buffer.size;
+
+ assert(name_utf8_len > 0);
+
+ fat_dir_pos_init(dir_pos);
+
- return 0;
+
+ if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ bts2rd = fat_fd->fat_file_size;
+ else
+ bts2rd = fs_info->fat.vol.bpc;
+
+ switch ( name_type ) {
+ case MSDOS_NAME_SHORT:
+ name_len_for_compare = msdos_filename_utf8_to_short_name_for_compare (
+ converter,
+ name_utf8,
+ name_utf8_len,
+ buffer,
+ MSDOS_SHORT_NAME_LEN);
+ if (name_len_for_compare > 0) {
+ fat_entries = 0;
+ }
+ else
+ retval = -1;
+ break;
+ case MSDOS_NAME_LONG:
+ name_len_for_save = msdos_filename_utf8_to_long_name_for_save (
+ converter,
+ name_utf8,
+ name_utf8_len,
+ buffer,
+ buffer_size);
+ if (name_len_for_save > 0) {
+ fat_entries = (name_len_for_save -1
+ + (MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR)) / (MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR);
+ name_len_for_compare = msdos_filename_utf8_to_long_name_for_compare (
+ converter,
+ name_utf8,
+ name_utf8_len,
+ buffer,
+ buffer_size);
+ if (0 >= name_len_for_compare) {
+ retval = -1;
+ }
+ }
+ else
+ retval = -1;
+ break;
+ case MSDOS_NAME_INVALID:
+ default:
+ errno = EINVAL;
+ retval = -1;
+ break;
+ }
+ if (retval == RC_OK) {
+ /* See if the file/directory does already exist */
+ retval = msdos_find_file_in_directory (
+ buffer,
+ name_len_for_compare,
+ name_len_for_save,
+ name_type,
+ fs_info,
+ fat_fd,
+ bts2rd,
+ create_node,
+ fat_entries,
+ name_dir_entry,
+ dir_pos,
+ &dir_offset,
+ &empty_space_offset,
+ &empty_space_entry,
+ &empty_space_count);
+ }
+ /* Create a non-existing file/directory if requested */
+ if ( retval == RC_OK
+ && create_node) {
+ switch (name_type) {
+ case MSDOS_NAME_SHORT:
+ name_len_for_save = msdos_filename_utf8_to_short_name_for_save (
+ converter,
+ name_utf8,
+ name_utf8_len,
+ buffer,
+ MSDOS_SHORT_NAME_LEN);
+ if (name_len_for_save > 0 ) {
+ fat_entries = 0;
+ }
+ else
+ retval = -1;
+ break;
+ case MSDOS_NAME_LONG:
+ name_len_for_save = msdos_filename_utf8_to_long_name_for_save (
+ converter,
+ name_utf8,
+ name_utf8_len,
+ buffer,
+ buffer_size);
+ if (name_len_for_save > 0) {
+ fat_entries = (name_len_for_save -1
+ + (MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR)) / (MSDOS_LFN_LEN_PER_ENTRY * MSDOS_NAME_LFN_BYTES_PER_CHAR);
+
+ }
+ else
+ retval = -1;
+ break;
+ case MSDOS_NAME_INVALID:
+ default:
+ errno = EINVAL;
+ retval = -1;
+ break;
+ }
+ retval = msdos_add_file (
+ buffer,
+ name_type,
+ fs_info,
+ fat_fd,
+ bts2rd,
+ fat_entries,
+ name_dir_entry,
+ dir_pos,
+ dir_offset,
+ empty_space_offset,
+ empty_space_entry,
+ empty_space_count
+ );
+ }
+
+ return retval;
}
+
/* msdos_find_node_by_cluster_num_in_fat_file --
* Find node with specified number of cluster in fat-file.
*