mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2025-02-20 11:43:27 +08:00
Editor: improve performance of version detection
This commit is contained in:
parent
8559ab2dcd
commit
4860bc35d6
@ -401,6 +401,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/util/base64.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/path.c
|
||||
src/util/platform/FFPlatform.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
|
@ -1,17 +1,45 @@
|
||||
#include "editor.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
#include "util/linux/elf.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
static inline char* realpath(const char* restrict file_name, char* restrict resolved_name)
|
||||
{
|
||||
return _fullpath(resolved_name, file_name, _MAX_PATH);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __linux__ || __FreeBSD__
|
||||
static bool extractNvimVersion(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("NVIM v0.0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "NVIM v")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("NVIM v"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool extractVimVersion(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("VIM - Vi IMproved 0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "VIM - Vi IMproved ")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("VIM - Vi IMproved "));
|
||||
ffStrbufSubstrBeforeFirstC(userdata, ' ');
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool extractNanoVersion(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("GNU nano 0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "GNU nano ")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("GNU nano "));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectEditor(FFEditorResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->name, getenv("VISUAL"));
|
||||
@ -26,35 +54,15 @@ const char* ffDetectEditor(FFEditorResult* result)
|
||||
return "$VISUAL or $EDITOR not set";
|
||||
}
|
||||
|
||||
if (!instance.config.general.detectVersion) return NULL;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (result->name.chars[0] != '/')
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->path, (char* const[]){
|
||||
FASTFETCH_TARGET_DIR_USR "/bin/which",
|
||||
result->name.chars,
|
||||
NULL,
|
||||
}) != NULL || result->path.length == 0)
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (!(result->name.length > 3 && ffCharIsEnglishAlphabet(result->name.chars[0]) && result->name.chars[1] == ':' && result->name.chars[2] == '\\'))
|
||||
{
|
||||
char buf[32];
|
||||
uint32_t len = GetSystemDirectoryA(buf, sizeof(buf));
|
||||
if (len < strlen("C:\\WINDOWS\\system32")) return NULL;
|
||||
strncpy(buf + len, "\\where.exe", sizeof(buf) - len);
|
||||
if (ffProcessAppendStdOut(&result->path, (char* const[]){
|
||||
buf,
|
||||
result->name.chars,
|
||||
NULL,
|
||||
}) != NULL || result->path.length == 0)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
if (ffIsAbsolutePath(result->name.chars))
|
||||
ffStrbufSet(&result->path, &result->name);
|
||||
else
|
||||
{
|
||||
const char* error = ffFindExecutableInPath(result->name.chars, &result->path);
|
||||
if (error) return error;
|
||||
}
|
||||
|
||||
if (!instance.config.general.detectVersion) return NULL;
|
||||
|
||||
char buf[PATH_MAX + 1];
|
||||
if (!realpath(result->path.chars, buf))
|
||||
@ -82,6 +90,17 @@ const char* ffDetectEditor(FFEditorResult* result)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __linux__ || __FreeBSD__
|
||||
if (ffStrbufEqualS(&result->exe, "nvim"))
|
||||
ffElfExtractStrings(buf, extractNvimVersion, &result->version);
|
||||
else if (ffStrbufEqualS(&result->exe, "vim"))
|
||||
ffElfExtractStrings(buf, extractVimVersion, &result->version);
|
||||
else if (ffStrbufEqualS(&result->exe, "nano"))
|
||||
ffElfExtractStrings(buf, extractNanoVersion, &result->version);
|
||||
|
||||
if (result->version.length > 0) return NULL;
|
||||
#endif
|
||||
|
||||
const char* param = NULL;
|
||||
if (
|
||||
ffStrbufEqualS(&result->exe, "nano") ||
|
||||
|
@ -9,49 +9,72 @@
|
||||
#include <libelf.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
struct FFElfData {
|
||||
FF_LIBRARY_SYMBOL(elf_version)
|
||||
FF_LIBRARY_SYMBOL(elf_begin)
|
||||
FF_LIBRARY_SYMBOL(elf_getshdrstrndx)
|
||||
FF_LIBRARY_SYMBOL(elf_nextscn)
|
||||
FF_LIBRARY_SYMBOL(elf64_getshdr)
|
||||
FF_LIBRARY_SYMBOL(elf32_getshdr)
|
||||
FF_LIBRARY_SYMBOL(elf_getdata)
|
||||
FF_LIBRARY_SYMBOL(elf_strptr)
|
||||
FF_LIBRARY_SYMBOL(elf_end)
|
||||
|
||||
bool inited;
|
||||
} elfData;
|
||||
|
||||
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libelf, &instance.config.library.libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_version)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_begin)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getshdrstrndx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_nextscn)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf64_getshdr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf32_getshdr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getdata)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_strptr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_end)
|
||||
if (!elfData.inited)
|
||||
{
|
||||
elfData.inited = true;
|
||||
FF_LIBRARY_LOAD(libelf, &instance.config.library.libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_version)
|
||||
if (elfData.ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
|
||||
|
||||
if (ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_begin)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_getshdrstrndx)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_nextscn)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf64_getshdr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf32_getshdr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_getdata)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_strptr)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_end)
|
||||
|
||||
libelf = NULL;
|
||||
}
|
||||
|
||||
if (elfData.ffelf_end == NULL)
|
||||
return "load libelf failed";
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
|
||||
if (fd < 0) return "open() failed";
|
||||
|
||||
Elf* elf = ffelf_begin(fd, ELF_C_READ, NULL);
|
||||
Elf* elf = elfData.ffelf_begin(fd, ELF_C_READ, NULL);
|
||||
if (elf == NULL) return "elf_begin() failed";
|
||||
|
||||
size_t shstrndx = 0;
|
||||
if (ffelf_getshdrstrndx(elf, &shstrndx) < 0)
|
||||
if (elfData.ffelf_getshdrstrndx(elf, &shstrndx) < 0)
|
||||
{
|
||||
ffelf_end(elf);
|
||||
elfData.ffelf_end(elf);
|
||||
return "elf_getshdrstrndx() failed";
|
||||
}
|
||||
|
||||
Elf_Scn* scn = NULL;
|
||||
while ((scn = ffelf_nextscn(elf, scn)) != NULL)
|
||||
while ((scn = elfData.ffelf_nextscn(elf, scn)) != NULL)
|
||||
{
|
||||
Elf64_Shdr* shdr64 = ffelf64_getshdr(scn);
|
||||
Elf64_Shdr* shdr64 = elfData.ffelf64_getshdr(scn);
|
||||
Elf32_Shdr* shdr32 = NULL;
|
||||
if (shdr64 == NULL)
|
||||
{
|
||||
shdr32 = ffelf32_getshdr(scn);
|
||||
shdr32 = elfData.ffelf32_getshdr(scn);
|
||||
if (shdr32 == NULL) continue;
|
||||
}
|
||||
|
||||
const char* name = ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
|
||||
const char* name = elfData.ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
|
||||
if (name == NULL || !ffStrEquals(name, ".rodata")) continue;
|
||||
|
||||
Elf_Data* data = ffelf_getdata(scn, NULL);
|
||||
Elf_Data* data = elfData.ffelf_getdata(scn, NULL);
|
||||
if (data == NULL) continue;
|
||||
|
||||
for (size_t off = 0; off < data->d_size; ++off)
|
||||
@ -69,7 +92,7 @@ const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str,
|
||||
break;
|
||||
}
|
||||
|
||||
ffelf_end(elf);
|
||||
elfData.ffelf_end(elf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
56
src/util/path.c
Normal file
56
src/util/path.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include "path.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
{
|
||||
char* path = getenv("PATH");
|
||||
if(!path)
|
||||
return "$PATH not set";
|
||||
|
||||
#ifdef _WIN32
|
||||
const bool appendExe = !ffStrEndsWithIgnCase(name, ".exe");
|
||||
#endif
|
||||
|
||||
for (char* token = NULL; (token = strchr(path,
|
||||
#ifdef _WIN32
|
||||
';'
|
||||
#else
|
||||
':'
|
||||
#endif
|
||||
)) != NULL; path = token + 1)
|
||||
{
|
||||
ffStrbufSetNS(result, (uint32_t)(token - path), path);
|
||||
ffStrbufEnsureEndsWithC(result,
|
||||
#ifdef _WIN32
|
||||
'\\'
|
||||
#else
|
||||
'/'
|
||||
#endif
|
||||
);
|
||||
ffStrbufAppendS(result, name);
|
||||
#ifdef _WIN32
|
||||
if (appendExe) ffStrbufAppendS(result, ".exe");
|
||||
if (!ffPathExists(result->chars, FF_PATHTYPE_FILE))
|
||||
continue;
|
||||
#else
|
||||
struct stat st;
|
||||
if (stat(result->chars, &st) < 0 || !(st.st_mode & S_IXUSR))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
ffStrbufClear(result);
|
||||
return "Executable not found";
|
||||
}
|
||||
|
||||
bool ffIsAbsolutePath(const char* path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ffCharIsEnglishAlphabet(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/');
|
||||
#else
|
||||
return path[0] == '/';
|
||||
#endif
|
||||
}
|
6
src/util/path.h
Normal file
6
src/util/path.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result);
|
||||
bool ffIsAbsolutePath(const char* path);
|
Loading…
x
Reference in New Issue
Block a user