Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Dec 2019 02:41:13 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356032 - head/usr.sbin/fstyp
Message-ID:  <201912230241.xBN2fDte091985@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Mon Dec 23 02:41:13 2019
New Revision: 356032
URL: https://svnweb.freebsd.org/changeset/base/356032

Log:
  fstyp(8): Use iconv(3) to convert NTFS vol labels correctly
  
  Rather than hackily extracting only the ASCII subset of UTF-16LE, go ahead
  and convert the label to the user's locale correctly.

Modified:
  head/usr.sbin/fstyp/fstyp.c
  head/usr.sbin/fstyp/fstyp.h
  head/usr.sbin/fstyp/ntfs.c

Modified: head/usr.sbin/fstyp/fstyp.c
==============================================================================
--- head/usr.sbin/fstyp/fstyp.c	Sun Dec 22 22:33:22 2019	(r356031)
+++ head/usr.sbin/fstyp/fstyp.c	Mon Dec 23 02:41:13 2019	(r356032)
@@ -67,7 +67,7 @@ static struct {
 	{ "ext2fs", &fstyp_ext2fs, false, NULL },
 	{ "geli", &fstyp_geli, true, 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 },

Modified: head/usr.sbin/fstyp/fstyp.h
==============================================================================
--- head/usr.sbin/fstyp/fstyp.h	Sun Dec 22 22:33:22 2019	(r356031)
+++ head/usr.sbin/fstyp/fstyp.h	Mon Dec 23 02:41:13 2019	(r356032)
@@ -38,6 +38,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 */
 

Modified: head/usr.sbin/fstyp/ntfs.c
==============================================================================
--- head/usr.sbin/fstyp/ntfs.c	Sun Dec 22 22:33:22 2019	(r356031)
+++ head/usr.sbin/fstyp/ntfs.c	Mon Dec 23 02:41:13 2019	(r356032)
@@ -31,6 +31,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <err.h>
+#include <iconv.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,6 +94,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, __DECONST(char **, &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)
 {
@@ -101,14 +135,15 @@ fstyp_ntfs(FILE *fp, char *label, size_t size)
 	off_t voloff;
 	char *filerecp, *ap;
 	int8_t mftrecsz;
-	char vnchar;
-	int recsize, j;
+	int recsize;
 
 	filerecp = NULL;
 
 	bf = (struct ntfs_bootfile *)read_buf(fp, 0, 512);
 	if (bf == NULL || strncmp(bf->bf_sysid, "NTFS    ", 8) != 0)
 		goto fail;
+	if (!show_label)
+		goto ok;
 
 	mftrecsz = bf->bf_mftrecsz;
 	recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz);
@@ -127,29 +162,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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912230241.xBN2fDte091985>