Module Name: src Committed By: tkusumi Date: Sat Dec 28 08:22:30 UTC 2019
Modified Files: src/usr.sbin/fstyp: fstyp.c fstyp.h ntfs.c Log Message: fstyp: Use iconv(3) to convert NTFS vol labels correctly taken-from: FreeBSD (freebsd/freebsd@23a4b310ffa90719eb9d11506bde1befab3c695f) To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/fstyp/fstyp.c cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/fstyp/fstyp.h cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/fstyp/ntfs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/fstyp/fstyp.c diff -u src/usr.sbin/fstyp/fstyp.c:1.6 src/usr.sbin/fstyp/fstyp.c:1.7 --- src/usr.sbin/fstyp/fstyp.c:1.6 Sat Dec 28 08:00:08 2019 +++ src/usr.sbin/fstyp/fstyp.c Sat Dec 28 08:22:30 2019 @@ -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 }, Index: src/usr.sbin/fstyp/fstyp.h diff -u src/usr.sbin/fstyp/fstyp.h:1.5 src/usr.sbin/fstyp/fstyp.h:1.6 --- src/usr.sbin/fstyp/fstyp.h:1.5 Sat Dec 28 08:00:08 2019 +++ src/usr.sbin/fstyp/fstyp.h Sat Dec 28 08:22:30 2019 @@ -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 */ Index: src/usr.sbin/fstyp/ntfs.c diff -u src/usr.sbin/fstyp/ntfs.c:1.1 src/usr.sbin/fstyp/ntfs.c:1.2 --- src/usr.sbin/fstyp/ntfs.c:1.1 Tue Jan 9 03:31:15 2018 +++ src/usr.sbin/fstyp/ntfs.c Sat Dec 28 08:22:30 2019 @@ -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 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 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);