aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-04-12 10:34:11 -0500
committerEric Sandeen <sandeen@redhat.com>2018-04-12 10:34:11 -0500
commit95c2f78bbc4cb13a96dc10ab112b315158254cab (patch)
tree5cb58229004893d6bb601b4c8533cf8f1ed5f054
parentd2cf5c2868c726b28a4c72dad0140c6735e5574f (diff)
downloadxfsprogs-dev-95c2f78bbc4cb13a96dc10ab112b315158254cab.tar.gz
xfs_scrub: communicate name problems via flagset instead of booleans
Use an unsigned int to pass around name error flags instead of booleans. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--scrub/unicrash.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/scrub/unicrash.c b/scrub/unicrash.c
index 10d7c14245..3538a60647 100644
--- a/scrub/unicrash.c
+++ b/scrub/unicrash.c
@@ -77,6 +77,14 @@ struct unicrash {
#define UNICRASH_SZ(nr) (sizeof(struct unicrash) + \
(nr * sizeof(struct name_entry *)))
+/* Things to complain about in Unicode naming. */
+
+/*
+ * Multiple names resolve to the same normalized string and therefore render
+ * identically.
+ */
+#define UNICRASH_NOT_UNIQUE (1 << 0)
+
/*
* We only care about validating utf8 collisions if the underlying
* system configuration says we're using utf8. If the language
@@ -256,7 +264,7 @@ unicrash_complain(
struct unicrash *uc,
const char *descr,
const char *what,
- bool unique,
+ unsigned int badflags,
const char *name,
uint8_t *uniname)
{
@@ -266,11 +274,20 @@ unicrash_complain(
bad1 = string_escape(name);
bad2 = string_escape((char *)uniname);
- if (!unique)
+ /*
+ * Two names that normalize to the same string will render
+ * identically even though the filesystem considers them unique
+ * names. "cafe\xcc\x81" and "caf\xc3\xa9" have different byte
+ * sequences, but they both appear as "café".
+ */
+ if (badflags & UNICRASH_NOT_UNIQUE) {
str_warn(uc->ctx, descr,
-_("Duplicate normalized Unicode name \"%s\" found in %s."),
- bad1, what);
+_("Unicode name \"%s\" in %s renders identically to \"%s\"."),
+ bad1, what, bad2);
+ goto out;
+ }
+out:
free(bad1);
free(bad2);
}
@@ -291,7 +308,7 @@ unicrash_add(
struct unicrash *uc,
uint8_t *uniname,
xfs_ino_t ino,
- bool *unique)
+ unsigned int *badflags)
{
struct name_entry *ne;
struct name_entry *x;
@@ -304,8 +321,9 @@ unicrash_add(
hash = unicrash_hashname(uniname, uninamelen);
bucket = hash % uc->nr_buckets;
for (nep = &uc->buckets[bucket], ne = *nep; ne != NULL; ne = x) {
- if (u8_strcmp(uniname, ne->uniname) == 0) {
- *unique = uc->compare_ino ? ne->ino == ino : false;
+ if (u8_strcmp(uniname, ne->uniname) == 0 &&
+ (uc->compare_ino ? ino != ne->ino : true)) {
+ *badflags |= UNICRASH_NOT_UNIQUE;
return true;
}
nep = &ne->next;
@@ -321,7 +339,6 @@ unicrash_add(
x->uninamelen = uninamelen;
memcpy(x->uniname, uniname, uninamelen + 1);
*nep = x;
- *unique = true;
return true;
}
@@ -336,19 +353,19 @@ __unicrash_check_name(
xfs_ino_t ino)
{
uint8_t uniname[(NAME_MAX * 2) + 1];
+ unsigned int badflags = 0;
bool moveon;
- bool unique;
memset(uniname, 0, (NAME_MAX * 2) + 1);
unicrash_normalize(name, uniname, NAME_MAX * 2);
- moveon = unicrash_add(uc, uniname, ino, &unique);
+ moveon = unicrash_add(uc, uniname, ino, &badflags);
if (!moveon)
return false;
- if (unique)
- return true;
+ if (badflags)
+ unicrash_complain(uc, descr, namedescr, badflags, name,
+ uniname);
- unicrash_complain(uc, descr, namedescr, unique, name, uniname);
return true;
}