summaryrefslogtreecommitdiff
path: root/include/rtems/dosfs.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/rtems/dosfs.h')
-rw-r--r--include/rtems/dosfs.h433
1 files changed, 433 insertions, 0 deletions
diff --git a/include/rtems/dosfs.h b/include/rtems/dosfs.h
new file mode 100644
index 0000000000..7691ed7e43
--- /dev/null
+++ b/include/rtems/dosfs.h
@@ -0,0 +1,433 @@
+/**
+ * @file
+ *
+ * @brief Application Interface to FAT Filesystem
+ *
+ * @ingroup DOSFS
+ */
+
+/*
+ * 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.org/license/LICENSE.
+ */
+
+#ifndef _RTEMS_DOSFS_H
+#define _RTEMS_DOSFS_H
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct rtems_dosfs_convert_control rtems_dosfs_convert_control;
+
+/**
+ * @brief Converts from UTF-8 into a specific code page.
+ *
+ * @param[in,out] self The convert control.
+ * @param[in] src A well-formed UTF-8 string to be converted.
+ * @param[in] src_size The size of the string in bytes (inludes '\\0' if any).
+ * @param[out] dst The address the converted string will get copied to.
+ * @param[in,out] dst_size The size of the buffer in bytes respectively the
+ * number of bytes written to the buffer.
+ *
+ * @retval 0 Successful operation.
+ * @retval EINVAL Conversion was successful, but is not reversible.
+ * @retval ENOMEM Conversion failed (possibly due to insufficient buffer size).
+ */
+typedef int (*rtems_dosfs_utf8_to_codepage)(
+ rtems_dosfs_convert_control *self,
+ const uint8_t *src,
+ size_t src_size,
+ char *dst,
+ size_t *dst_size
+);
+
+/**
+ * @brief Converts from a specific code page into UTF-8
+ *
+ * @param[in,out] self The convert control.
+ * @param[in] src A well-formed string in code page format.
+ * @param[in] src_size The size of the string in bytes (inludes '\\0' if any).
+ * @param[out] dst The address the converted string will get copied to.
+ * @param[in,out] dst_size The size of the buffer in bytes respectively the
+ * number of bytes written to the buffer.
+ *
+ * @retval 0 Successful operation.
+ * @retval EINVAL Conversion was successful, but is not reversible.
+ * @retval ENOMEM Conversion failed (possibly due to insufficient buffer size).
+ */
+typedef int (*rtems_dosfs_codepage_to_utf8)(
+ rtems_dosfs_convert_control *self,
+ const char *src,
+ size_t src_size,
+ uint8_t *dst,
+ size_t *dst_size
+);
+
+/**
+ * @brief Converts from UTF-8 to UTF-16
+ *
+ * @param[in,out] self The convert control.
+ * @param[in] src A well-formed UTF-8 string to be converted.
+ * @param[in] src_size The size of the string in bytes (inludes '\\0' if any).
+ * @param[out] dst The address the converted string will get copied to
+ * @param[in,out] dst_size The size of the buffer in bytes respectively the
+ * number of bytes written to the buffer.
+ *
+ * @retval 0 Successful operation.
+ * @retval EINVAL Conversion was successful, but is not reversible.
+ * @retval ENOMEM Conversion failed (possibly due to insufficient buffer size).
+ */
+typedef int (*rtems_dosfs_utf8_to_utf16)(
+ rtems_dosfs_convert_control *self,
+ const uint8_t *src,
+ size_t src_size,
+ uint16_t *dst,
+ size_t *dst_size
+);
+
+/**
+ * @brief Converts from UTF-16 to UTF-8.
+ *
+ * @param[in,out] self The convert control.
+ * @param[in] src A well-formed UTF-16 string to be converted.
+ * @param[in] src_size The size of the string in bytes (inludes '\\0' if any).
+ * @param[out] dst The address the converted string will get copied to.
+ * @param[in,out] dst_size The size of the buffer in bytes respectively the
+ * number of bytes written to the buffer
+ *
+ * @retval 0 Successful operation.
+ * @retval EINVAL Conversion was successful, but is not reversible.
+ * @retval ENOMEM Conversion failed (possibly due to insufficient buffer size).
+ */
+typedef int (*rtems_dosfs_utf16_to_utf8)(
+ rtems_dosfs_convert_control *self,
+ const uint16_t *src,
+ size_t src_size,
+ uint8_t *dst,
+ size_t *dst_size
+);
+
+/**
+ * @brief Converts from UTF-8 to Normalized Form Canonical Decomposition.
+ *
+ * Does canonical decomposition of the UTF-8 string and in addition
+ * also converts upper case alphabetic characters to lower case characters
+ *
+ * @param[in,out] self The convert control.
+ * @param[in] src A well-formed UTF-8 string to be normalized and fold.
+ * @param[in] src_size The size of the string in bytes (inludes '\\0' if any).
+ * @param[out] dst The address the normalized and fold string will get
+ * copied to.
+ * @param[in,out] dst_size The size of the buffer in bytes respectively the
+ * number of bytes written to the buffer.
+ *
+ * @retval 0 Successful operation.
+ * @retval EINVAL Conversion failed.
+ * @retval ENOMEM Conversion failed (possibly due to insufficient buffer size).
+ * @retval EOVERFLOW Conversion failed.
+ * @retval ENOENT Conversion failed.
+ */
+typedef int (*rtems_dosfs_utf8_normalize_and_fold)(
+ rtems_dosfs_convert_control *self,
+ const uint8_t *src,
+ size_t src_size,
+ uint8_t *dst,
+ size_t *dst_size
+);
+
+/**
+ * @brief Destroys a convert control structure.
+ *
+ * @param[in,out] self The convert control for destruction.
+ */
+typedef void (*rtems_dosfs_convert_destroy)(
+ rtems_dosfs_convert_control *self
+);
+
+/**
+ * @brief FAT filesystem convert handler.
+ */
+typedef struct {
+ rtems_dosfs_utf8_to_codepage utf8_to_codepage;
+ rtems_dosfs_codepage_to_utf8 codepage_to_utf8;
+ rtems_dosfs_utf8_to_utf16 utf8_to_utf16;
+ rtems_dosfs_utf16_to_utf8 utf16_to_utf8;
+ rtems_dosfs_utf8_normalize_and_fold utf8_normalize_and_fold;
+ rtems_dosfs_convert_destroy destroy;
+} rtems_dosfs_convert_handler;
+
+typedef struct {
+ void *data;
+ size_t size;
+} rtems_dosfs_buffer;
+
+/**
+ * @brief FAT filesystem convert control.
+ *
+ * Short file names are stored in the code page format. Long file names are
+ * stored as little-endian UTF-16. The convert control determines the format
+ * conversions to and from the POSIX file name strings.
+ */
+struct rtems_dosfs_convert_control {
+ const rtems_dosfs_convert_handler *handler;
+ rtems_dosfs_buffer buffer;
+};
+
+/**
+ * @defgroup DOSFS FAT Filesystem Support
+ *
+ * @ingroup FileSystemTypesAndMount
+ *
+ * @brief FAT file system configuration support, format and mount options.
+ *
+ * A block device can be formatted with a FAT file system with the
+ * msdos_format() function.
+ *
+ * The FAT file system mount operation can be controlled with FAT file system
+ * specific mount options, see @ref rtems_dosfs_mount_options.
+ *
+ * @{
+ */
+
+/**
+ * @brief Semaphore count per FAT filesystem instance.
+ *
+ * This can be used for system configuration via <rtems/confdefs.h>.
+ */
+#define RTEMS_DOSFS_SEMAPHORES_PER_INSTANCE 1
+
+/**
+ * @brief FAT filesystem mount options.
+ */
+typedef struct {
+ /**
+ * @brief Converter implementation for new file system instance.
+ *
+ * Before converters have been added to the RTEMS implementation of the FAT
+ * file system, the implementation was:
+ * - Short names were saved in code page format (as is still the case).
+ * - Long names were not saved in UTF-16 format as mandated by the FAT file
+ * system specification. Instead the character in the local encoding was
+ * stored to the low byte directly and the high byte was set to zero.
+ *
+ * There are a few compatibility issues due to a non-standard conform
+ * implementation of the FAT file system before the UTF-8 support was added.
+ * These following issues affect the default converter and the UTF-8
+ * converter:
+ * - Before UTF-8 support was added, it was possible to create files with the
+ * the same short name in single case and mixed case in a directory. It
+ * was for example possible to have files "ABC" and "aBc" in a single
+ * directory. Now this bug is fixed.
+ * - Before UTF-8 support was added, it was possible to create files with a
+ * name length of slightly more than 255 characters. Now the
+ * implementation adheres exactly to the 255 character limit.
+ * - Long file names saved before UTF-8 support was added could contain
+ * non-ASCII characters in the low byte which was saved for a long name
+ * character. With the default converter this means such files can be read
+ * only by their short file name. With the UTF-8 converter file names will
+ * be read correctly as long as the characters written with the old
+ * implementation were Latin-1 characters.
+ *
+ * The following sample code demonstrates how to mount a file
+ * system with UTF-8 support:
+ * @code
+ * #include <errno.h>
+ * #include <assert.h>
+ * #include <rtems/dosfs.h>
+ * #include <rtems/libio.h>
+ *
+ * static int mount_with_utf8(
+ * const char *device_file,
+ * const char *mount_point
+ * )
+ * {
+ * rtems_dosfs_convert_control *convert_ctrl;
+ * int rv;
+ *
+ * convert_ctrl = rtems_dosfs_create_utf8_converter( "CP850" );
+ *
+ * if ( convert_ctrl != NULL ) {
+ * rtems_dosfs_mount_options mount_opts;
+ *
+ * memset( &mount_opts, 0, sizeof( mount_opts ) );
+ * mount_opts.converter = convert_ctrl;
+ *
+ * rv = mount_and_make_target_path(
+ * device_file,
+ * mount_point,
+ * RTEMS_FILESYSTEM_TYPE_DOSFS,
+ * RTEMS_FILESYSTEM_READ_WRITE,
+ * &mount_opts
+ * );
+ * } else {
+ * rv = -1;
+ * errno = ENOMEM;
+ * }
+ *
+ * return rv;
+ * }
+ * @endcode
+ *
+ * In case you do not want UTF-8 support, you can simply pass a NULL pointer
+ * to mount_and_make_target_path() respectively to mount() instead of the
+ * mount_opts address.
+ *
+ * @see rtems_dosfs_create_default_converter() and
+ * rtems_dosfs_create_utf8_converter().
+ */
+ rtems_dosfs_convert_control *converter;
+} rtems_dosfs_mount_options;
+
+/**
+ * @brief Allocates and initializes a default converter.
+ *
+ * This default converter will accept only POSIX file names with pure ASCII
+ * characters. This largely corresponds to the file name handling before the
+ * optional UTF-8 support was added to the RTEMS implementation of the FAT file
+ * system. This handling is mostly backwards compatible to the previous RTEMS
+ * implementation of the FAT file system.
+ *
+ * For backwards compatibility and the previous RTEMS implementation of the FAT
+ * file system please see also @ref rtems_dosfs_mount_options and mount().
+ *
+ * @retval NULL Something failed.
+ * @retval other Pointer to initialized converter.
+ */
+rtems_dosfs_convert_control *rtems_dosfs_create_default_converter(void);
+
+/**
+ * @brief Allocates and initializes a UTF-8 converter.
+ *
+ * This converter will assume that all file names passed to POSIX file handling
+ * methods are UTF-8 strings and will convert them to the selected code page
+ * for short file names and to UTF-16 for long file names. This conversion
+ * will be done during reading and writing. These conversions correspond to
+ * the specification of the FAT file system. This handling is mostly backwards
+ * compatible to the previous RTEMS implementation of the FAT file system.
+ *
+ * For backwards compatibility and the previous RTEMS implementation of the FAT
+ * file system please see also @ref rtems_dosfs_mount_options and mount().
+ *
+ * One possible issue with this converter is: When reading file names which
+ * have been created with other implementations of the FAT file system, it can
+ * happen that during the conversion to UTF-8 a long file name becomes longer
+ * and exceeds the 255 bytes limit. In such a case only the short file name
+ * will get read.
+ *
+ * @param[in] codepage The iconv() identification string for the used code
+ * page.
+ *
+ * @retval NULL Something failed.
+ * @retval other Pointer to initialized converter.
+ */
+rtems_dosfs_convert_control *rtems_dosfs_create_utf8_converter(
+ const char *codepage
+);
+
+#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)
+
+/**
+ * @brief FAT file system format request parameters.
+ */
+typedef struct {
+ /**
+ * @brief OEM name string or NULL.
+ */
+ const char *OEMName;
+
+ /**
+ * @brief Volume label string or NULL.
+ */
+ const char *VolLabel;
+
+ /**
+ * @brief Sectors per cluster hint.
+ *
+ * The format procedure may choose another value. Use 0 as default value.
+ */
+ uint32_t sectors_per_cluster;
+
+ /**
+ * @brief Number of FATs hint.
+ *
+ * Use 0 as default value.
+ */
+ uint32_t fat_num;
+
+ /**
+ * @brief Minimum files in root directory for FAT12 and FAT16.
+ *
+ * The format procedure may choose a greater value. Use 0 as default value.
+ */
+ uint32_t files_per_root_dir;
+
+ /**
+ * @brief Media code.
+ *
+ * Use 0 as default value. The default media code is 0xf8.
+ */
+ uint8_t media;
+
+ /**
+ * @brief Quick format.
+ *
+ * If set to true, then do not clear data sectors to zero.
+ */
+ bool quick_format;
+
+ /**
+ * @brief Do not align FAT, data cluster, and root directory to a cluster
+ * boundary.
+ */
+ bool skip_alignment;
+
+ /**
+ * @brief Synchronize device after write operations.
+ */
+ bool sync_device;
+
+ /**
+ * @brief The amount of info to output.
+ */
+ int info_level;
+} msdos_format_request_param_t;
+
+/**
+ * @brief Formats a block device with a FAT file system.
+ *
+ * @param[in] devname The block device path.
+ * @param[in] rqdata The FAT file system format request data. Use NULL for
+ * default parameters.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occurred. The @c errno indicates the error.
+ */
+int msdos_format (
+ const char *devname,
+ const msdos_format_request_param_t *rqdata
+);
+
+/** @} */
+
+int rtems_dosfs_initialize(rtems_filesystem_mount_table_entry_t *mt_entry,
+ const void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif