From 1c01b8eab9e65d1e8856b9589413915e4cca8cac Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 8 Oct 2009 15:04:28 -0700 Subject: [PATCH 1/1] Add case-insensitive lookup support to BlueSky core. --- bluesky/bluesky.h | 3 +++ bluesky/dir.c | 22 +++++++++++++++++++++- bluesky/inode.c | 1 + nfs3/nfs3.c | 2 +- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index 5524c44..f37a537 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -149,6 +149,7 @@ typedef struct { /* Directory-specific fields */ GSequence *dirents; /* List of entries for READDIR */ GHashTable *dirhash; /* Hash table by name for LOOKUP */ + GHashTable *dirhash_folded; /* As above, but case-folded */ uint64_t parent_inum; /* inode for ".."; 0 if the root directory */ } BlueSkyInode; @@ -159,6 +160,7 @@ typedef struct { * is used to provide a stable key for restarting a READDIR call. */ typedef struct { gchar *name; + gchar *name_folded; /* Name, folded for case-insensitive lookup */ uint32_t cookie; uint64_t inum; } BlueSkyDirent; @@ -194,6 +196,7 @@ void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode); void bluesky_dirent_destroy(gpointer dirent); uint64_t bluesky_directory_hash(gchar *name); uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name); +uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name); gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum); void bluesky_directory_dump(BlueSkyInode *dir); diff --git a/bluesky/dir.c b/bluesky/dir.c index 14eb6eb..82f3baa 100644 --- a/bluesky/dir.c +++ b/bluesky/dir.c @@ -18,6 +18,7 @@ void bluesky_dirent_destroy(gpointer data) { BlueSkyDirent *dirent = (BlueSkyDirent *)data; g_free(dirent->name); + g_free(dirent->name_folded); g_free(dirent); } @@ -50,6 +51,22 @@ uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name) return d->inum; } +/* Case-insensitive lookup. */ +uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name) +{ + g_return_val_if_fail(inode->type == BLUESKY_DIRECTORY, 0); + g_return_val_if_fail(inode->dirhash_folded != NULL, 0); + + name = bluesky_lowercase(name); + BlueSkyDirent *d = g_hash_table_lookup(inode->dirhash_folded, name); + g_free(name); + + if (d == NULL) + return 0; + else + return d->inum; +} + /* Insert a new entry into a directory. Should be called with the inode lock * already held. */ gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum) @@ -62,6 +79,7 @@ gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum) BlueSkyDirent *d = g_new(BlueSkyDirent, 1); d->name = g_strdup(name); + d->name_folded = bluesky_lowercase(name); d->inum = inum; GSequence *dirents = dir->dirents; @@ -94,6 +112,7 @@ gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum) /* Add the directory entry to both indices. */ g_sequence_insert_sorted(dirents, d, bluesky_dirent_compare, NULL); g_hash_table_insert(dir->dirhash, d->name, d); + g_hash_table_insert(dir->dirhash_folded, d->name_folded, d); bluesky_inode_update_ctime(dir, 1); bluesky_inode_flush(dir->fs, dir); @@ -112,7 +131,8 @@ gboolean bluesky_directory_remove(BlueSkyInode *dir, gchar *name) return FALSE; } - g_hash_table_remove(dir->dirhash, name); + g_hash_table_remove(dir->dirhash, d->name); + g_hash_table_remove(dir->dirhash_folded, d->name_folded); GSequenceIter *i = g_sequence_search(dir->dirents, d, bluesky_dirent_compare, NULL); diff --git a/bluesky/inode.c b/bluesky/inode.c index f3f3198..b62870d 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -117,6 +117,7 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, case BLUESKY_DIRECTORY: i->dirents = g_sequence_new(bluesky_dirent_destroy); i->dirhash = g_hash_table_new(g_str_hash, g_str_equal); + i->dirhash_folded = g_hash_table_new(g_str_hash, g_str_equal); break; case BLUESKY_BLOCK: case BLUESKY_CHARACTER: diff --git a/nfs3/nfs3.c b/nfs3/nfs3.c index 593d660..cffad52 100644 --- a/nfs3/nfs3.c +++ b/nfs3/nfs3.c @@ -572,7 +572,7 @@ nfsproc3_readdir_3_svc(readdir3args *argp, struct svc_req *rqstp) static entry3 dirents[MAX_READDIR_DIRENTS]; int count = 0; - BlueSkyDirent start = {NULL, argp->cookie, 0}; + BlueSkyDirent start = {NULL, NULL, argp->cookie, 0}; GSequenceIter *i = g_sequence_search(dir->dirents, &start, bluesky_dirent_compare, NULL); -- 2.20.1