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);
 

Reply via email to