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.
This commit is contained in:
Scott Prager 2014-09-20 22:39:31 -04:00 committed by Thiago de Arruda
parent 24da0d49d0
commit 0f4976687d
6 changed files with 60 additions and 63 deletions

View File

@ -2253,7 +2253,7 @@ setfname (
} }
sfname = vim_strsave(sfname); sfname = vim_strsave(sfname);
#ifdef USE_FNAME_CASE #ifdef USE_FNAME_CASE
fname_case(sfname, 0); /* set correct case for short file name */ path_fix_case(sfname); /* set correct case for short file name */
#endif #endif
free(buf->b_ffname); free(buf->b_ffname);
free(buf->b_sfname); free(buf->b_sfname);

View File

@ -9895,9 +9895,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#if defined(WIN64) || defined(_WIN64) #if defined(WIN64) || defined(_WIN64)
"win64", "win64",
#endif #endif
#ifndef CASE_INSENSITIVE_FILENAME
"fname_case", "fname_case",
#endif
#ifdef HAVE_ACL #ifdef HAVE_ACL
"acl", "acl",
#endif #endif

View File

@ -2563,7 +2563,7 @@ do_ecmd (
sfname = ffname; sfname = ffname;
#ifdef USE_FNAME_CASE #ifdef USE_FNAME_CASE
if (sfname != NULL) if (sfname != NULL)
fname_case(sfname, 0); /* set correct case for sfname */ path_fix_case(sfname); // set correct case for sfname
#endif #endif
if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL)) if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))

View File

@ -1290,8 +1290,8 @@ scripterror:
} }
#ifdef USE_FNAME_CASE #ifdef USE_FNAME_CASE
/* Make the case of the file name match the actual file. */ // Make the case of the file name match the actual file.
fname_case(p, 0); path_fix_case(p);
#endif #endif
alist_add(&global_alist, p, alist_add(&global_alist, p,

View File

@ -69,62 +69,6 @@ static int selinux_enabled = -1;
# include "os_unix.c.generated.h" # include "os_unix.c.generated.h"
#endif #endif
#if defined(USE_FNAME_CASE)
/*
* 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.
*/
void fname_case(
char_u *name,
int len /* buffer size, only used when name gets longer */
)
{
char_u *slash, *tail;
DIR *dirp;
struct dirent *dp;
FileInfo file_info;
if (os_fileinfo_link((char *)name, &file_info)) {
/* Open the directory where the file is located. */
slash = vim_strrchr(name, '/');
if (slash == NULL) {
dirp = opendir(".");
tail = name;
} else {
*slash = NUL;
dirp = opendir((char *)name);
*slash = '/';
tail = slash + 1;
}
if (dirp != NULL) {
while ((dp = readdir(dirp)) != NULL) {
/* Only accept names that differ in case and are the same byte
* length. TODO: accept different length name. */
if (STRICMP(tail, dp->d_name) == 0
&& STRLEN(tail) == STRLEN(dp->d_name)) {
char_u newname[MAXPATHL + 1];
/* Verify the inode is equal. */
STRLCPY(newname, name, MAXPATHL + 1);
STRLCPY(newname + (tail - name), dp->d_name,
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, dp->d_name);
break;
}
}
}
closedir(dirp);
}
}
}
#endif
#if defined(HAVE_ACL) #if defined(HAVE_ACL)
# ifdef HAVE_SYS_ACL_H # ifdef HAVE_SYS_ACL_H
# include <sys/acl.h> # include <sys/acl.h>

View File

@ -1617,13 +1617,68 @@ char_u *fix_fname(char_u *fname)
fname = vim_strsave(fname); fname = vim_strsave(fname);
# ifdef USE_FNAME_CASE # 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 # endif
return fname; return fname;
#endif #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. * Return TRUE if "p" points to just after a path separator.
* Takes care of multi-byte characters. * Takes care of multi-byte characters.