fstyp: Use iconv(3) to convert NTFS vol labels correctly
taken-from: FreeBSD (freebsd/freebsd@23a4b310ff)
This commit is contained in:
parent
0cd59d67d5
commit
bdaaf6392d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fstyp.c,v 1.6 2019/12/28 08:00:08 tkusumi Exp $ */
|
||||
/* $NetBSD: fstyp.c,v 1.7 2019/12/28 08:22:30 tkusumi Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 The NetBSD Foundation, Inc.
|
||||
@ -35,7 +35,7 @@
|
||||
*
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: fstyp.c,v 1.6 2019/12/28 08:00:08 tkusumi Exp $");
|
||||
__RCSID("$NetBSD: fstyp.c,v 1.7 2019/12/28 08:22:30 tkusumi Exp $");
|
||||
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/dkio.h>
|
||||
@ -74,7 +74,7 @@ static struct {
|
||||
{ "ext2fs", &fstyp_ext2fs, false, NULL },
|
||||
{ "hfs+", &fstyp_hfsp, false, NULL },
|
||||
{ "msdosfs", &fstyp_msdosfs, false, NULL },
|
||||
{ "ntfs", &fstyp_ntfs, false, NULL },
|
||||
{ "ntfs", &fstyp_ntfs, false, NTFS_ENC },
|
||||
{ "ufs", &fstyp_ufs, false, NULL },
|
||||
#ifdef HAVE_ZFS
|
||||
{ "zfs", &fstyp_zfs, true, NULL },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: fstyp.h,v 1.5 2019/12/28 08:00:08 tkusumi Exp $ */
|
||||
/* $NetBSD: fstyp.h,v 1.6 2019/12/28 08:22:30 tkusumi Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 The NetBSD Foundation, Inc.
|
||||
@ -43,6 +43,11 @@
|
||||
|
||||
/* The spec doesn't seem to permit UTF-16 surrogates; definitely LE. */
|
||||
#define EXFAT_ENC "UCS-2LE"
|
||||
/*
|
||||
* NTFS itself is agnostic to encoding; it just stores 255 u16 wchars. In
|
||||
* practice, UTF-16 seems expected for NTFS. (Maybe also for exFAT.)
|
||||
*/
|
||||
#define NTFS_ENC "UTF-16LE"
|
||||
|
||||
extern bool show_label; /* -l flag */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ntfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $ */
|
||||
/* $NetBSD: ntfs.c,v 1.2 2019/12/28 08:22:30 tkusumi Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 The NetBSD Foundation, Inc.
|
||||
@ -35,8 +35,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: ntfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $");
|
||||
__RCSID("$NetBSD: ntfs.c,v 1.2 2019/12/28 08:22:30 tkusumi Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <iconv.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -98,6 +100,38 @@ struct ntfs_bootfile {
|
||||
uint32_t bf_volsn;
|
||||
} __packed;
|
||||
|
||||
static void
|
||||
convert_label(const void *label /* LE */, size_t labellen, char *label_out,
|
||||
size_t label_sz)
|
||||
{
|
||||
char *label_out_orig;
|
||||
iconv_t cd;
|
||||
size_t rc;
|
||||
|
||||
/* dstname="" means convert to the current locale. */
|
||||
cd = iconv_open("", NTFS_ENC);
|
||||
if (cd == (iconv_t)-1) {
|
||||
warn("ntfs: Could not open iconv");
|
||||
return;
|
||||
}
|
||||
|
||||
label_out_orig = label_out;
|
||||
|
||||
rc = iconv(cd, __UNCONST(&label), &labellen, &label_out,
|
||||
&label_sz);
|
||||
if (rc == (size_t)-1) {
|
||||
warn("ntfs: iconv()");
|
||||
*label_out_orig = '\0';
|
||||
} else {
|
||||
/* NUL-terminate result (iconv advances label_out). */
|
||||
if (label_sz == 0)
|
||||
label_out--;
|
||||
*label_out = '\0';
|
||||
}
|
||||
|
||||
iconv_close(cd);
|
||||
}
|
||||
|
||||
int
|
||||
fstyp_ntfs(FILE *fp, char *label, size_t size)
|
||||
{
|
||||
@ -107,21 +141,22 @@ fstyp_ntfs(FILE *fp, char *label, size_t size)
|
||||
off_t voloff;
|
||||
char *filerecp, *ap;
|
||||
int8_t mftrecsz;
|
||||
char vnchar;
|
||||
size_t recsize, j;
|
||||
size_t recsize;
|
||||
|
||||
filerecp = NULL;
|
||||
|
||||
bf = read_buf(fp, 0, 512);
|
||||
if (bf == NULL || strncmp((char*)bf->bf_sysid, "NTFS ", 8) != 0)
|
||||
goto fail;
|
||||
if (!show_label)
|
||||
goto ok;
|
||||
|
||||
mftrecsz = bf->bf_mftrecsz;
|
||||
recsize = mftrecsz > 0 ? (size_t)(mftrecsz * bf->bf_bps * bf->bf_spc)
|
||||
: (size_t)(1 << -mftrecsz);
|
||||
|
||||
voloff = (off_t)(bf->bf_mftcn * bf->bf_spc * bf->bf_bps +
|
||||
recsize * NTFS_VOLUMEINO);
|
||||
voloff = (off_t)((off_t)bf->bf_mftcn * bf->bf_spc * bf->bf_bps +
|
||||
(off_t)recsize * NTFS_VOLUMEINO);
|
||||
|
||||
filerecp = read_buf(fp, voloff, recsize);
|
||||
if (filerecp == NULL)
|
||||
@ -134,29 +169,15 @@ fstyp_ntfs(FILE *fp, char *label, size_t size)
|
||||
for (ap = filerecp + fr->fr_attroff;
|
||||
atr = (struct ntfs_attr *)ap, (int)atr->a_type != -1;
|
||||
ap += atr->reclen) {
|
||||
if (atr->a_type == NTFS_A_VOLUMENAME) {
|
||||
if(atr->a_datalen >= size *2){
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* UNICODE to ASCII.
|
||||
* Should we need to use iconv(9)?
|
||||
*/
|
||||
for (j = 0; j < atr->a_datalen; j++) {
|
||||
vnchar = *(ap + atr->a_dataoff + j);
|
||||
if (j & 1) {
|
||||
if (vnchar) {
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
label[j / 2] = vnchar;
|
||||
}
|
||||
}
|
||||
label[j / 2] = 0;
|
||||
break;
|
||||
}
|
||||
if (atr->a_type != NTFS_A_VOLUMENAME)
|
||||
continue;
|
||||
|
||||
convert_label(ap + atr->a_dataoff,
|
||||
atr->a_datalen, label, size);
|
||||
break;
|
||||
}
|
||||
|
||||
ok:
|
||||
free(bf);
|
||||
free(filerecp);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user