From patchwork Tue Aug 20 19:50:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 2847316 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4245A9F271 for ; Tue, 20 Aug 2013 19:50:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 38A9C20314 for ; Tue, 20 Aug 2013 19:50:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 50063201E4 for ; Tue, 20 Aug 2013 19:50:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751753Ab3HTTu3 (ORCPT ); Tue, 20 Aug 2013 15:50:29 -0400 Received: from mail-ee0-f45.google.com ([74.125.83.45]:53761 "EHLO mail-ee0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751441Ab3HTTu1 (ORCPT ); Tue, 20 Aug 2013 15:50:27 -0400 Received: by mail-ee0-f45.google.com with SMTP id c50so404525eek.18 for ; Tue, 20 Aug 2013 12:50:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=E0X5NbLUmzY606nSMHrpr8wAnY9mhSQhTzpQELJrdjM=; b=VOLjO2e6UIS0tVmMvQZ3gRsxh6xkHzI7hpzO/AaSW/sqKD/JvEHKgxNvP8iy6h5jv9 DX9skCqk40zisRrwGaxGQOuCyNDv2AzZohsNh1TA4nLp6Ocw2HA7La4W6bW9xqTLd7fg C11qtFCwtr+H0il+WhbgF6AqocV7ByxY5D2ZfuN7E/bvEGE4GjHXuGdhhDg2e3koC1q5 mZJ6zf1nOlNLddeM6qCBbI/wByFibzkyiKoifsoAVWw5gXkh93hXesTwg2sBFX7ilosQ 6VkI52AEVVTLFYlkGo6/NFylNJxsIfp7qSvnSy/3msOC6awHaq4REnmfcxdXuq+8uU4Z 1TNQ== X-Gm-Message-State: ALoCoQksls5HZu+VBjB3HokiWMrHcdg7GilzTplk4X7Nb+VgkWA5WTIkXc71AhneDPfjsqnaoBSH X-Received: by 10.15.25.73 with SMTP id k49mr876551eeu.71.1377028226609; Tue, 20 Aug 2013 12:50:26 -0700 (PDT) Received: from salusa.poochiereds.net (cpe-107-015-124-230.nc.res.rr.com. [107.15.124.230]) by mx.google.com with ESMTPSA id x47sm4420573eea.16.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 20 Aug 2013 12:50:25 -0700 (PDT) From: Jeff Layton To: smfrench@gmail.com Cc: linux-cifs@vger.kernel.org, linux-fsdevel@vger.kernel.org, glogow@fbihome.de, bj@sernet.de Subject: [PATCH 2/3] cifs: convert case-insensitive dentry ops to use new case conversion routines Date: Tue, 20 Aug 2013 15:50:10 -0400 Message-Id: <1377028211-17624-3-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1377028211-17624-1-git-send-email-jlayton@redhat.com> References: <1377028211-17624-1-git-send-email-jlayton@redhat.com> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Have the case-insensitive d_compare and d_hash routines convert each character in the filenames to wchar_t's and then use the new cifs_toupper routine to convert those into uppercase. With this scheme we should more closely emulate the case conversion that the servers will do. Reported-and-Tested-by: Jan-Marek Glogowski Signed-off-by: Jeff Layton --- fs/cifs/dir.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d62ce0d..d3e2eaa 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -32,6 +32,7 @@ #include "cifsproto.h" #include "cifs_debug.h" #include "cifs_fs_sb.h" +#include "cifs_unicode.h" static void renew_parental_timestamps(struct dentry *direntry) @@ -834,12 +835,17 @@ static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q) { struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls; unsigned long hash; - int i; + wchar_t c; + int i, charlen; hash = init_name_hash(); - for (i = 0; i < q->len; i++) - hash = partial_name_hash(nls_tolower(codepage, q->name[i]), - hash); + for (i = 0; i < q->len; i += charlen) { + charlen = codepage->char2uni(&q->name[i], q->len - i, &c); + /* error out if we can't convert the character */ + if (unlikely(charlen < 0)) + return charlen; + hash = partial_name_hash(cifs_toupper(c), hash); + } q->hash = end_name_hash(hash); return 0; @@ -849,11 +855,47 @@ static int cifs_ci_compare(const struct dentry *parent, const struct dentry *den unsigned int len, const char *str, const struct qstr *name) { struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls; + wchar_t c1, c2; + int i, l1, l2; - if ((name->len == len) && - (nls_strnicmp(codepage, name->name, str, len) == 0)) - return 0; - return 1; + /* + * We make the assumption here that uppercase characters in the local + * codepage are always the same length as their lowercase counterparts. + * + * If that's ever not the case, then this will fail to match it. + */ + if (name->len != len) + return 1; + + for (i = 0; i < len; i += l1) { + /* Convert characters in both strings to UTF-16. */ + l1 = codepage->char2uni(&str[i], len - i, &c1); + l2 = codepage->char2uni(&name->name[i], name->len - i, &c2); + + /* + * If we can't convert either character, just declare it to + * be 1 byte long and compare the original byte. + */ + if (unlikely(l1 < 0 && l2 < 0)) { + if (str[i] != name->name[i]) + return 1; + l1 = 1; + continue; + } + + /* + * Here, we again ass|u|me that upper/lowercase versions of + * a character are the same length in the local NLS. + */ + if (l1 != l2) + return 1; + + /* Now compare uppercase versions of these characters */ + if (cifs_toupper(c1) != cifs_toupper(c2)) + return 1; + } + + return 0; } const struct dentry_operations cifs_ci_dentry_ops = {