diff options
author | Scott Prager <splinterofchaos@gmail.com> | 2014-09-20 22:39:31 -0400 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-03-31 11:20:23 -0300 |
commit | 0f4976687d0dfc3a0992195219586be93e49dc9e (patch) | |
tree | 7869a4aa3cb88f79cdc75d4282673b230088a6f0 /src/nvim/path.c | |
parent | 24da0d49d0a0e576fed6cbd699e40380d5c31322 (diff) | |
download | rneovim-0f4976687d0dfc3a0992195219586be93e49dc9e.tar.gz rneovim-0f4976687d0dfc3a0992195219586be93e49dc9e.tar.bz2 rneovim-0f4976687d0dfc3a0992195219586be93e49dc9e.zip |
os_scandir: fname_case -> path_fix_case
Use os_scandir().
fname_case() only gets used when `defined(USE_FNAME_CASE)` (on operating
systems with case-insensitive file systems), but may be useful in other
contexts, so move it to path.c. (See the TODO.)
Remove the unused parameter, len.
Diffstat (limited to 'src/nvim/path.c')
-rw-r--r-- | src/nvim/path.c | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/src/nvim/path.c b/src/nvim/path.c index 25ed2e3fd8..e83b4e44ed 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1617,13 +1617,68 @@ char_u *fix_fname(char_u *fname) fname = vim_strsave(fname); # ifdef USE_FNAME_CASE - fname_case(fname, 0); // set correct case for file name + path_fix_case(fname); // set correct case for file name # endif return fname; #endif } +/// Set the case of the file name, if it already exists. This will cause the +/// file name to remain exactly the same. +/// Only required for file systems where case is ignored and preserved. +// TODO(SplinterOfChaos): Could also be used when mounting case-insensitive +// file systems. +void path_fix_case(char_u *name) + FUNC_ATTR_NONNULL_ALL +{ + FileInfo file_info; + if (!os_fileinfo_link((char *)name, &file_info)) { + return; + } + + // Open the directory where the file is located. + char_u *slash = vim_strrchr(name, '/'); + char_u *tail; + Directory dir; + bool ok; + if (slash == NULL) { + ok = os_scandir(&dir, "."); + tail = name; + } else { + *slash = NUL; + ok = os_scandir(&dir, (char *) name); + *slash = '/'; + tail = slash + 1; + } + + if (!ok) { + return; + } + + char_u *entry; + while ((entry = (char_u *) os_scandir_next(&dir))) { + // Only accept names that differ in case and are the same byte + // length. TODO: accept different length name. + if (STRICMP(tail, entry) == 0 && STRLEN(tail) == STRLEN(entry)) { + char_u newname[MAXPATHL + 1]; + + // Verify the inode is equal. + STRLCPY(newname, name, MAXPATHL + 1); + STRLCPY(newname + (tail - name), entry, + MAXPATHL - (tail - name) + 1); + FileInfo file_info_new; + if (os_fileinfo_link((char *)newname, &file_info_new) + && os_fileinfo_id_equal(&file_info, &file_info_new)) { + STRCPY(tail, entry); + break; + } + } + } + + os_closedir(&dir); +} + /* * Return TRUE if "p" points to just after a path separator. * Takes care of multi-byte characters. |