aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/path.c
diff options
context:
space:
mode:
authorScott Prager <splinterofchaos@gmail.com>2014-09-20 22:39:31 -0400
committerThiago de Arruda <tpadilha84@gmail.com>2015-03-31 11:20:23 -0300
commit0f4976687d0dfc3a0992195219586be93e49dc9e (patch)
tree7869a4aa3cb88f79cdc75d4282673b230088a6f0 /src/nvim/path.c
parent24da0d49d0a0e576fed6cbd699e40380d5c31322 (diff)
downloadrneovim-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.c57
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.