diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2012-06-16 14:08:58 -0700 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2012-06-16 14:08:58 -0700 |
commit | 6cf42075fcbf4cb75fa00197f227b8a5eceae2bd (patch) | |
tree | eae680b7ee5df2863e46fc60a3ef993d90c48045 /highlight.cpp | |
parent | afd8d2f9bae14cb3c263987a01aedb748b975176 (diff) |
Fix to check for case insensitive filesystems in is_potential_path
Diffstat (limited to 'highlight.cpp')
-rw-r--r-- | highlight.cpp | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/highlight.cpp b/highlight.cpp index b74f5240..a43840a6 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -103,6 +103,28 @@ static wcstring apply_working_directory(const wcstring &path, const wcstring &wo } } +/* Determine if the filesystem containing the given fd is case insensitive. */ +typedef std::map<wcstring, bool> case_sensitivity_cache_t; +bool fs_is_case_insensitive(const wcstring &path, int fd, case_sensitivity_cache_t &case_sensitivity_cache) +{ + /* If _PC_CASE_SENSITIVE is not defined, assume case sensitive */ + bool result = false; +#ifdef _PC_CASE_SENSITIVE + /* Try the cache first */ + case_sensitivity_cache_t::iterator cache = case_sensitivity_cache.find(path); + if (cache != case_sensitivity_cache.end()) { + /* Use the cached value */ + result = cache->second; + } else { + /* Ask the system. A -1 value means error (so assume case sensitive), a 1 value means case sensitive, and a 0 value means case insensitive */ + long ret = fpathconf(fd, _PC_CASE_SENSITIVE); + result = (ret == 0); + case_sensitivity_cache[path] = result; + } +#endif + return result; +} + /* Tests whether the specified string cpath is the prefix of anything we could cd to. directories is a list of possible parent directories (typically either the working directory, or the cdpath). This does I/O! */ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &directories, bool require_dir, wcstring *out_path) @@ -161,6 +183,9 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct /* Don't test the same path multiple times, which can happen if the path is absolute and the CDPATH contains multiple entries */ std::set<wcstring> checked_paths; + /* Keep a cache of which paths / filesystems are case sensitive */ + case_sensitivity_cache_t case_sensitivity_cache; + for (size_t wd_idx = 0; wd_idx < directories.size() && ! result; wd_idx++) { const wcstring &wd = directories.at(wd_idx); @@ -200,12 +225,23 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct // We opened the dir_name; look for a string where the base name prefixes it wcstring ent; + // Check if we're case insensitive + bool case_insensitive = fs_is_case_insensitive(dir_name, dirfd(dir), case_sensitivity_cache); + // Don't ask for the is_dir value unless we care, because it can cause extra filesystem acces */ bool is_dir = false; while (wreaddir_resolving(dir, dir_name, ent, require_dir ? &is_dir : NULL)) - { - // TODO: support doing the right thing on case-insensitive filesystems like HFS+ - if (string_prefixes_string(base_name, ent) && (! require_dir || is_dir)) + { + + /* Determine which function to call to check for prefixes */ + bool (*prefix_func)(const wcstring &, const wcstring &); + if (case_insensitive) { + prefix_func = string_prefixes_string_case_insensitive; + } else { + prefix_func = string_prefixes_string; + } + + if (prefix_func(base_name, ent) && (! require_dir || is_dir)) { result = true; if (out_path) { @@ -213,10 +249,13 @@ bool is_potential_path(const wcstring &const_path, const wcstring_list_t &direct out_path->clear(); const wcstring path_base = wdirname(const_path); - if (string_prefixes_string(path_base, const_path)) { + + + if (prefix_func(path_base, const_path)) { out_path->append(path_base); if (! string_suffixes_string(L"/", *out_path)) out_path->push_back(L'/'); + printf("path: %ls\n", out_path->c_str()); } out_path->append(ent); /* We actually do want a trailing / for directories, since it makes autosuggestion a bit nicer */ |