mirror of
https://gitee.com/openharmony/third_party_f2fs-tools
synced 2024-11-23 10:10:00 +00:00
mkfs.f2fs: fix storing volume label correctly in utf16
This patch fixes to store volume label as utf16 correctly. Many conversion codes are copied from exfat-tools. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
0ff98a3679
commit
9e5c021b67
11
fsck/mount.c
11
fsck/mount.c
@ -99,6 +99,14 @@ void print_node_info(struct f2fs_node *node_block)
|
||||
}
|
||||
}
|
||||
|
||||
static void DISP_label(u_int16_t *name)
|
||||
{
|
||||
char buffer[MAX_VOLUME_NAME];
|
||||
|
||||
utf16_to_utf8(buffer, name, MAX_VOLUME_NAME, MAX_VOLUME_NAME);
|
||||
printf("%-30s" "\t\t[%s]\n", "volum_name", buffer);
|
||||
}
|
||||
|
||||
void print_raw_sb_info(struct f2fs_super_block *sb)
|
||||
{
|
||||
if (!config.dbg_lv)
|
||||
@ -111,6 +119,9 @@ void print_raw_sb_info(struct f2fs_super_block *sb)
|
||||
|
||||
DISP_u32(sb, magic);
|
||||
DISP_u32(sb, major_ver);
|
||||
|
||||
DISP_label(sb->volume_name);
|
||||
|
||||
DISP_u32(sb, minor_ver);
|
||||
DISP_u32(sb, log_sectorsize);
|
||||
DISP_u32(sb, log_sectors_per_block);
|
||||
|
@ -398,6 +398,8 @@ enum {
|
||||
|
||||
#define F2FS_FEATURE_ENCRYPT 0x0001
|
||||
|
||||
#define MAX_VOLUME_NAME 512
|
||||
|
||||
/*
|
||||
* For superblock
|
||||
*/
|
||||
@ -430,7 +432,7 @@ struct f2fs_super_block {
|
||||
__le32 node_ino; /* node inode number */
|
||||
__le32 meta_ino; /* meta inode number */
|
||||
__u8 uuid[16]; /* 128-bit uuid for volume */
|
||||
__le16 volume_name[512]; /* volume name */
|
||||
__le16 volume_name[MAX_VOLUME_NAME]; /* volume name */
|
||||
__le32 extension_count; /* # of extensions below */
|
||||
__u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
|
||||
__le32 cp_payload;
|
||||
@ -847,7 +849,8 @@ enum {
|
||||
SSR
|
||||
};
|
||||
|
||||
extern void ASCIIToUNICODE(u_int16_t *, u_int8_t *);
|
||||
extern int utf8_to_utf16(u_int16_t *, const char *, size_t, size_t);
|
||||
extern int utf16_to_utf8(char *, const u_int16_t *, size_t, size_t);
|
||||
extern int log_base_2(u_int32_t);
|
||||
extern unsigned int addrs_per_inode(struct f2fs_inode *);
|
||||
|
||||
|
179
lib/libf2fs.c
179
lib/libf2fs.c
@ -23,18 +23,177 @@
|
||||
|
||||
#include <f2fs_fs.h>
|
||||
|
||||
void ASCIIToUNICODE(u_int16_t *out_buf, u_int8_t *in_buf)
|
||||
/*
|
||||
* UTF conversion codes are Copied from exfat tools.
|
||||
*/
|
||||
static const char *utf8_to_wchar(const char *input, wchar_t *wc,
|
||||
size_t insize)
|
||||
{
|
||||
u_int8_t *pchTempPtr = in_buf;
|
||||
u_int16_t *pwTempPtr = out_buf;
|
||||
|
||||
while (*pchTempPtr != '\0') {
|
||||
*pwTempPtr = (u_int16_t)*pchTempPtr;
|
||||
pchTempPtr++;
|
||||
pwTempPtr++;
|
||||
if ((input[0] & 0x80) == 0 && insize >= 1) {
|
||||
*wc = (wchar_t) input[0];
|
||||
return input + 1;
|
||||
}
|
||||
*pwTempPtr = '\0';
|
||||
return;
|
||||
if ((input[0] & 0xe0) == 0xc0 && insize >= 2) {
|
||||
*wc = (((wchar_t) input[0] & 0x1f) << 6) |
|
||||
((wchar_t) input[1] & 0x3f);
|
||||
return input + 2;
|
||||
}
|
||||
if ((input[0] & 0xf0) == 0xe0 && insize >= 3) {
|
||||
*wc = (((wchar_t) input[0] & 0x0f) << 12) |
|
||||
(((wchar_t) input[1] & 0x3f) << 6) |
|
||||
((wchar_t) input[2] & 0x3f);
|
||||
return input + 3;
|
||||
}
|
||||
if ((input[0] & 0xf8) == 0xf0 && insize >= 4) {
|
||||
*wc = (((wchar_t) input[0] & 0x07) << 18) |
|
||||
(((wchar_t) input[1] & 0x3f) << 12) |
|
||||
(((wchar_t) input[2] & 0x3f) << 6) |
|
||||
((wchar_t) input[3] & 0x3f);
|
||||
return input + 4;
|
||||
}
|
||||
if ((input[0] & 0xfc) == 0xf8 && insize >= 5) {
|
||||
*wc = (((wchar_t) input[0] & 0x03) << 24) |
|
||||
(((wchar_t) input[1] & 0x3f) << 18) |
|
||||
(((wchar_t) input[2] & 0x3f) << 12) |
|
||||
(((wchar_t) input[3] & 0x3f) << 6) |
|
||||
((wchar_t) input[4] & 0x3f);
|
||||
return input + 5;
|
||||
}
|
||||
if ((input[0] & 0xfe) == 0xfc && insize >= 6) {
|
||||
*wc = (((wchar_t) input[0] & 0x01) << 30) |
|
||||
(((wchar_t) input[1] & 0x3f) << 24) |
|
||||
(((wchar_t) input[2] & 0x3f) << 18) |
|
||||
(((wchar_t) input[3] & 0x3f) << 12) |
|
||||
(((wchar_t) input[4] & 0x3f) << 6) |
|
||||
((wchar_t) input[5] & 0x3f);
|
||||
return input + 6;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u_int16_t *wchar_to_utf16(u_int16_t *output, wchar_t wc, size_t outsize)
|
||||
{
|
||||
if (wc <= 0xffff) {
|
||||
if (outsize == 0)
|
||||
return NULL;
|
||||
output[0] = cpu_to_le16(wc);
|
||||
return output + 1;
|
||||
}
|
||||
if (outsize < 2)
|
||||
return NULL;
|
||||
wc -= 0x10000;
|
||||
output[0] = cpu_to_le16(0xd800 | ((wc >> 10) & 0x3ff));
|
||||
output[1] = cpu_to_le16(0xdc00 | (wc & 0x3ff));
|
||||
return output + 2;
|
||||
}
|
||||
|
||||
int utf8_to_utf16(u_int16_t *output, const char *input, size_t outsize,
|
||||
size_t insize)
|
||||
{
|
||||
const char *inp = input;
|
||||
u_int16_t *outp = output;
|
||||
wchar_t wc;
|
||||
|
||||
while (inp - input < insize && *inp) {
|
||||
inp = utf8_to_wchar(inp, &wc, insize - (inp - input));
|
||||
if (inp == NULL) {
|
||||
DBG(0, "illegal UTF-8 sequence\n");
|
||||
return -EILSEQ;
|
||||
}
|
||||
outp = wchar_to_utf16(outp, wc, outsize - (outp - output));
|
||||
if (outp == NULL) {
|
||||
DBG(0, "name is too long\n");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
}
|
||||
*outp = cpu_to_le16(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const u_int16_t *utf16_to_wchar(const u_int16_t *input, wchar_t *wc,
|
||||
size_t insize)
|
||||
{
|
||||
if ((le16_to_cpu(input[0]) & 0xfc00) == 0xd800) {
|
||||
if (insize < 2 || (le16_to_cpu(input[1]) & 0xfc00) != 0xdc00)
|
||||
return NULL;
|
||||
*wc = ((wchar_t) (le16_to_cpu(input[0]) & 0x3ff) << 10);
|
||||
*wc |= (le16_to_cpu(input[1]) & 0x3ff);
|
||||
*wc += 0x10000;
|
||||
return input + 2;
|
||||
} else {
|
||||
*wc = le16_to_cpu(*input);
|
||||
return input + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static char *wchar_to_utf8(char *output, wchar_t wc, size_t outsize)
|
||||
{
|
||||
if (wc <= 0x7f) {
|
||||
if (outsize < 1)
|
||||
return NULL;
|
||||
*output++ = (char) wc;
|
||||
} else if (wc <= 0x7ff) {
|
||||
if (outsize < 2)
|
||||
return NULL;
|
||||
*output++ = 0xc0 | (wc >> 6);
|
||||
*output++ = 0x80 | (wc & 0x3f);
|
||||
} else if (wc <= 0xffff) {
|
||||
if (outsize < 3)
|
||||
return NULL;
|
||||
*output++ = 0xe0 | (wc >> 12);
|
||||
*output++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*output++ = 0x80 | (wc & 0x3f);
|
||||
} else if (wc <= 0x1fffff) {
|
||||
if (outsize < 4)
|
||||
return NULL;
|
||||
*output++ = 0xf0 | (wc >> 18);
|
||||
*output++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*output++ = 0x80 | (wc & 0x3f);
|
||||
} else if (wc <= 0x3ffffff) {
|
||||
if (outsize < 5)
|
||||
return NULL;
|
||||
*output++ = 0xf8 | (wc >> 24);
|
||||
*output++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*output++ = 0x80 | (wc & 0x3f);
|
||||
} else if (wc <= 0x7fffffff) {
|
||||
if (outsize < 6)
|
||||
return NULL;
|
||||
*output++ = 0xfc | (wc >> 30);
|
||||
*output++ = 0x80 | ((wc >> 24) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 18) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 12) & 0x3f);
|
||||
*output++ = 0x80 | ((wc >> 6) & 0x3f);
|
||||
*output++ = 0x80 | (wc & 0x3f);
|
||||
} else
|
||||
return NULL;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
int utf16_to_utf8(char *output, const u_int16_t *input, size_t outsize,
|
||||
size_t insize)
|
||||
{
|
||||
const u_int16_t *inp = input;
|
||||
char *outp = output;
|
||||
wchar_t wc;
|
||||
|
||||
while (inp - input < insize && le16_to_cpu(*inp)) {
|
||||
inp = utf16_to_wchar(inp, &wc, insize - (inp - input));
|
||||
if (inp == NULL) {
|
||||
DBG(0, "illegal UTF-16 sequence\n");
|
||||
return -EILSEQ;
|
||||
}
|
||||
outp = wchar_to_utf8(outp, wc, outsize - (outp - output));
|
||||
if (outp == NULL) {
|
||||
DBG(0, "name is too long\n");
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
}
|
||||
*outp = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_base_2(u_int32_t num)
|
||||
|
@ -291,8 +291,8 @@ static int f2fs_prepare_super_block(void)
|
||||
|
||||
uuid_generate(sb->uuid);
|
||||
|
||||
ASCIIToUNICODE(sb->volume_name, (u_int8_t *)config.vol_label);
|
||||
|
||||
utf8_to_utf16(sb->volume_name, (const char *)config.vol_label,
|
||||
MAX_VOLUME_NAME, strlen(config.vol_label));
|
||||
set_sb(node_ino, 1);
|
||||
set_sb(meta_ino, 2);
|
||||
set_sb(root_ino, 3);
|
||||
|
Loading…
Reference in New Issue
Block a user