mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e897a98153 | |||
| 0a8056d835 | |||
| 9681e176b3 | |||
| 1f8be43881 | |||
| 30813551be | |||
| beb564f374 | |||
| 5c97c012a9 | |||
| 50da7cabd6 | |||
| a6528cdfd6 | |||
| 588201fe46 | |||
| 6184b5ee96 | |||
| 5e7baa9d0a | |||
| 79ae650c58 | |||
| 44107f289e | |||
| 75927a87b2 | |||
| 85da30ccf5 | |||
| f73c3b85c2 | |||
| 66bef2fc19 | |||
| 7c5eb021ee | |||
| f902e3b3d8 | |||
| 553124ab5b | |||
| 6c6d93370d | |||
| 55ae3a7dbd | |||
| 586874080f | |||
| d5b91a8983 | |||
| 72fee13112 | |||
| 20ae897f39 | |||
| 6f756d103f | |||
| c9dd858ce3 | |||
| 2e201eaaf7 | |||
| 7c54dcba69 | |||
| a107395707 | |||
| 8a9fe22855 | |||
| 7e04e23528 | |||
| 8d779f68f3 | |||
| 98ba08c1a0 | |||
| a1499b82f8 | |||
| c6c866d78a | |||
| 7a6999bd20 | |||
| 1084cf3523 | |||
| ed5f2a3968 | |||
| 17e1d4b72d |
@@ -245,8 +245,7 @@ jobs:
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
brew update
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -378,7 +377,7 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
@@ -440,7 +439,7 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
**/build/
|
||||
**/.vscode/
|
||||
**/.cache/
|
||||
**/.kdev4/
|
||||
**/.DS_Store
|
||||
/.vs
|
||||
build/
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache/
|
||||
.kdev4/
|
||||
.DS_Store
|
||||
cscope.*
|
||||
tags
|
||||
fastfetch.kdev4
|
||||
|
||||
@@ -1,3 +1,39 @@
|
||||
# 2.8.10
|
||||
|
||||
Changes:
|
||||
* Use MS-DOS device name as mountFrom result, instead of useless GUID volume name (Windows, Disk)
|
||||
* Some adjustments to Terminal detection (Terminal, Windows)
|
||||
* Don't pretty print CMD
|
||||
* Print conhost as Windows Console
|
||||
* Don't detect `wininit` as Terminal
|
||||
|
||||
Bugfixes:
|
||||
* Don't display 0.00 GHz (CPU, FreeBSD)
|
||||
* Don't detect manufactor of Qualcomm as ARM (CPU, Android)
|
||||
* Ignore `chezmoi` (Terminal, Linux)
|
||||
* Trim trailing possible whitespaces (PublicIP)
|
||||
* Fix detection compatibility for KDE 6 (Font, Linux)
|
||||
* Always use Metal API to detect vmem size (GPU, macOS)
|
||||
|
||||
Features:
|
||||
* Improve stability; print more useful error message; avoid misuse (PublicIP / Weather)
|
||||
|
||||
Logo:
|
||||
* Fix color of Arco Linux
|
||||
|
||||
# 2.8.9
|
||||
|
||||
Bugfixes:
|
||||
* Don't detect `SessionLeader` as terminal, actually (Terminal, Linux)
|
||||
* Fix blurry chafa result when specifying both width and height (#757, Logo)
|
||||
|
||||
Features:
|
||||
* Support new MacBook Air (Host, macOS)
|
||||
* Distinguish min frequency and base frequency (CPU)
|
||||
|
||||
Logo:
|
||||
* Fix proxmox
|
||||
|
||||
# 2.8.8
|
||||
|
||||
Bugfixes:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.8.8
|
||||
VERSION 2.8.10
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
|
||||
Vendored
+12
@@ -1,3 +1,15 @@
|
||||
fastfetch (2.8.9) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.9
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 15 Mar 2024 10:49:42 +0800
|
||||
|
||||
fastfetch (2.8.8) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.8
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 08 Mar 2024 09:59:41 +0800
|
||||
|
||||
fastfetch (2.8.6) jammy; urgency=medium
|
||||
|
||||
* Update to 2.8.6
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.8.6_source.buildinfo universe/utils optional
|
||||
fastfetch_2.8.9_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "none"
|
||||
},
|
||||
"display": {
|
||||
"separator": "-> "
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "title",
|
||||
"format": " {6}{7}{8}"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "┌───────────────────────────── \u001b[1mSystem Information\u001b[0m ─────────────────────────────┐" // `\u001b` is `\033`, or `\e`
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"key": " OS ",
|
||||
"keyColor": "red",
|
||||
"type": "os"
|
||||
},
|
||||
{
|
||||
"key": " Machine ",
|
||||
"keyColor": "green",
|
||||
"type": "host"
|
||||
},
|
||||
{
|
||||
"key": " Kernel ",
|
||||
"keyColor": "magenta",
|
||||
"type": "kernel"
|
||||
},
|
||||
{
|
||||
"key": " Uptime ",
|
||||
"keyColor": "red",
|
||||
"type": "uptime"
|
||||
},
|
||||
{
|
||||
"key": " Resolution ",
|
||||
"keyColor": "yellow",
|
||||
"type": "display",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"key": " WM ",
|
||||
"keyColor": "blue",
|
||||
"type": "wm"
|
||||
},
|
||||
{
|
||||
"key": " DE ",
|
||||
"keyColor": "green",
|
||||
"type": "de"
|
||||
},
|
||||
{
|
||||
"key": " Shell ",
|
||||
"keyColor": "cyan",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"key": " Terminal ",
|
||||
"keyColor": "red",
|
||||
"type": "terminal"
|
||||
},
|
||||
{
|
||||
"key": " CPU ",
|
||||
"keyColor": "yellow",
|
||||
"type": "cpu"
|
||||
},
|
||||
{
|
||||
"key": " GPU ",
|
||||
"keyColor": "blue",
|
||||
"type": "gpu"
|
||||
},
|
||||
{
|
||||
"key": " Memory ",
|
||||
"keyColor": "magenta",
|
||||
"type": "memory"
|
||||
},
|
||||
{
|
||||
"key": " Local IP ",
|
||||
"keyColor": "red",
|
||||
"type": "localip",
|
||||
"compact": true
|
||||
},
|
||||
{
|
||||
"key": " Public IP ",
|
||||
"keyColor": "cyan",
|
||||
"type": "publicip"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "└──────────────────────────────────────────────────────────────────────────────┘" // `\u001b` is `\033`, or `\e`
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 34,
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 341 KiB |
+19
-44
@@ -2,6 +2,7 @@
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void ffFontInit(FFfont* font)
|
||||
{
|
||||
@@ -66,59 +67,33 @@ void ffFontInitQt(FFfont* font, const char* data)
|
||||
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||
|
||||
//Family
|
||||
while(*data != ',' && *data != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&font->name, *data);
|
||||
++data;
|
||||
}
|
||||
if(*data != '\0')
|
||||
++data;
|
||||
data = ffStrbufAppendSUntilC(&font->name, data, ',');
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Size
|
||||
while(*data != ',' && *data != '\0')
|
||||
{
|
||||
ffStrbufAppendC(&font->size, *data);
|
||||
++data;
|
||||
}
|
||||
if(*data != '\0')
|
||||
++data;
|
||||
data = ffStrbufAppendSUntilC(&font->size, data, ',');
|
||||
ffStrbufTrim(&font->size, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
#define FF_FONT_QT_SKIP_VALUE \
|
||||
while(*data != ',' && *data != '\0') \
|
||||
++data; \
|
||||
if(*data != '\0') \
|
||||
++data;
|
||||
|
||||
FF_FONT_QT_SKIP_VALUE //Pixel size
|
||||
FF_FONT_QT_SKIP_VALUE //Style hint
|
||||
FF_FONT_QT_SKIP_VALUE //Font weight
|
||||
FF_FONT_QT_SKIP_VALUE //Font style
|
||||
FF_FONT_QT_SKIP_VALUE //Underline
|
||||
FF_FONT_QT_SKIP_VALUE //Strike out
|
||||
FF_FONT_QT_SKIP_VALUE //Fixed pitch
|
||||
FF_FONT_QT_SKIP_VALUE //Always 0
|
||||
|
||||
#undef FF_FONT_QT_SKIP_VALUE
|
||||
|
||||
while(*data != '\0')
|
||||
//Style
|
||||
data = strrchr(data, ',');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
if (isalpha(*data))
|
||||
{
|
||||
while(*data == ' ')
|
||||
++data;
|
||||
|
||||
if(*data == '\0')
|
||||
break;
|
||||
|
||||
FFstrbuf* style = ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
while(*data != ' ' && *data != '\0')
|
||||
do
|
||||
{
|
||||
ffStrbufAppendC(style, *data);
|
||||
++data;
|
||||
}
|
||||
FFstrbuf* style = ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
} while (data);
|
||||
}
|
||||
|
||||
exit:
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
|
||||
+4
-10
@@ -20,15 +20,9 @@ typedef struct FFNetworkingState {
|
||||
FFThreadType thread;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t timeout;
|
||||
} FFNetworkingState;
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout);
|
||||
|
||||
static inline bool ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, const char* headers, FFstrbuf* buffer)
|
||||
{
|
||||
FFNetworkingState state;
|
||||
if(ffNetworkingSendHttpRequest(&state, host, path, headers))
|
||||
return ffNetworkingRecvHttpResponse(&state, buffer, timeout);
|
||||
return false;
|
||||
}
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer);
|
||||
|
||||
@@ -5,30 +5,50 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
static void connectAndSend(FFNetworkingState* state)
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
|
||||
const char* ret = NULL;
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(state->host.chars, "80", &hints, &addr) != 0)
|
||||
if(getaddrinfo(state->host.chars, "80", &(struct addrinfo) {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
{
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||
{
|
||||
close(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -37,6 +57,7 @@ static void connectAndSend(FFNetworkingState* state)
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
close(state->sockfd);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -48,11 +69,13 @@ error:
|
||||
exit:
|
||||
ffStrbufDestroy(&state->host);
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
ffStrbufInitS(&state->host, host);
|
||||
|
||||
@@ -66,22 +89,30 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
return !!state->thread;
|
||||
#else
|
||||
connectAndSend(state);
|
||||
return state->sockfd != -1;
|
||||
return state->thread ? NULL : "ffThreadCreate(connectAndSend) failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
if (!ffThreadJoin(state->thread, timeout))
|
||||
return false;
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
return false;
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
@@ -91,14 +122,15 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if(received > 0)
|
||||
{
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
close(state->sockfd);
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
@@ -33,21 +33,20 @@ static const char* initWsaData(WSADATA* wsaData)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
if (initWsaData(&wsaData) != NULL)
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
return false;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
return false;
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
return "initWsaData() failed before";
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
@@ -55,26 +54,27 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
return false;
|
||||
return "getaddrinfo() failed";
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
return false;
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
{
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
struct sockaddr_in addr = {
|
||||
if(bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
.sin_port = 0,
|
||||
};
|
||||
if(bind(state->sockfd, (SOCKADDR *)&addr, sizeof(addr)) != 0)
|
||||
}, sizeof(struct sockaddr_in)) != 0)
|
||||
{
|
||||
printf("bind %d\n", WSAGetLastError());
|
||||
return false;
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,35 +93,52 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return false;
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
|
||||
return true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
if (WaitForSingleObject((HANDLE) state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return false;
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if(received > 0)
|
||||
{
|
||||
buffer->length += (uint32_t) received;
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int) ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length = recvStart + (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
closesocket(state->sockfd);
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n");
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@ typedef struct FFCPUResult
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
|
||||
double frequencyMin; // GHz
|
||||
double frequencyBase; // GHz
|
||||
double frequencyMax; // GHz
|
||||
double frequencyMin; // GHz
|
||||
|
||||
double temperature;
|
||||
} FFCPUResult;
|
||||
|
||||
const char* ffCPUDetectByCpuid(FFCPUResult* cpu);
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
|
||||
@@ -60,14 +60,13 @@ static const char* detectFrequency(FFCPUResult* cpu)
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
|
||||
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
|
||||
}
|
||||
else
|
||||
cpu->frequencyMax = 0.0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
|
||||
@@ -11,8 +11,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
cpu->coresOnline = cpu->coresPhysical;
|
||||
|
||||
cpu->frequencyMin = ffSysctlGetInt("hw.clockrate", 0) / 1000.0;
|
||||
cpu->frequencyMax = cpu->frequencyMin;
|
||||
int clockRate = ffSysctlGetInt("hw.clockrate", 0);
|
||||
cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0;
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
static void detectAndroid(FFCPUResult* cpu)
|
||||
{
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
ffSettingsGetAndroidProperty("ro.soc.model", &cpu->name);
|
||||
ffStrbufClear(&cpu->vendor); // We usually detect the vendor of CPU core as ARM, but instead we want the vendor of SOC
|
||||
}
|
||||
if (cpu->vendor.length == 0)
|
||||
{
|
||||
if (!ffSettingsGetAndroidProperty("ro.soc.manufacturer", &cpu->vendor))
|
||||
@@ -94,11 +97,14 @@ static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, cons
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
|
||||
ffStrbufAppendS(basePath, scalingFileName);
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
if (scalingFileName)
|
||||
{
|
||||
ffStrbufAppendS(basePath, scalingFileName);
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
}
|
||||
|
||||
return 0.0/0.0;
|
||||
}
|
||||
@@ -111,7 +117,6 @@ static bool detectFrequency(FFCPUResult* cpu)
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
uint32_t baseLen = path.length;
|
||||
bool flag = false;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
@@ -119,26 +124,34 @@ static bool detectFrequency(FFCPUResult* cpu)
|
||||
if (ffStrStartsWith(entry->d_name, "policy") && isdigit(entry->d_name[strlen("policy")]))
|
||||
{
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
|
||||
if (fmin != fmin) continue;
|
||||
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
if (fmax != fmax) continue;
|
||||
|
||||
if (flag)
|
||||
double fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
|
||||
if (fbase == fbase)
|
||||
{
|
||||
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
|
||||
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
|
||||
if (cpu->frequencyBase == cpu->frequencyBase)
|
||||
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
|
||||
else
|
||||
cpu->frequencyBase = fbase;
|
||||
}
|
||||
else
|
||||
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
if (fmax == fmax)
|
||||
{
|
||||
cpu->frequencyMin = fmin;
|
||||
cpu->frequencyMax = fmax;
|
||||
flag = true;
|
||||
if (cpu->frequencyMax == cpu->frequencyMax)
|
||||
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
|
||||
else
|
||||
cpu->frequencyMax = fmax;
|
||||
}
|
||||
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
|
||||
if (fmin == fmin)
|
||||
{
|
||||
if (cpu->frequencyMin == cpu->frequencyMin)
|
||||
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
|
||||
else
|
||||
cpu->frequencyMin = fmin;
|
||||
}
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
return true;
|
||||
}
|
||||
|
||||
static double detectCPUTemp(void)
|
||||
@@ -234,8 +247,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
|
||||
|
||||
if (!detectFrequency(cpu))
|
||||
cpu->frequencyMin = cpu->frequencyMax = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||
if (!detectFrequency(cpu) || cpu->frequencyBase != cpu->frequencyBase)
|
||||
cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||
|
||||
if(cpuUarch.length > 0)
|
||||
{
|
||||
|
||||
@@ -64,50 +64,53 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
return "No active CPU is found in SMBIOS data";
|
||||
}
|
||||
|
||||
double speed;
|
||||
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
|
||||
speed = data->MaxSpeed / 1000.0;
|
||||
else
|
||||
speed = data->CurrentSpeed / 1000.0;
|
||||
{
|
||||
double speed = data->MaxSpeed / 1000.0;
|
||||
if (cpu->frequencyBase < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
}
|
||||
|
||||
if (cpu->frequencyMax < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByOS(FFCPUResult* cpu)
|
||||
static const char* detectNCores(FFCPUResult* cpu)
|
||||
{
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
||||
if (length == 0)
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
||||
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
|
||||
if (!pProcessorInfo || !GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
|
||||
for(
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
{
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
||||
if (length == 0)
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
||||
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
||||
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
||||
|
||||
if (pProcessorInfo && GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
||||
if(ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if(ptr->Relationship == RelationGroup)
|
||||
{
|
||||
for(
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
||||
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
||||
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
||||
)
|
||||
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
|
||||
{
|
||||
if(ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if(ptr->Relationship == RelationGroup)
|
||||
{
|
||||
cpu->coresOnline += ptr->Group.GroupInfo->ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo->MaximumProcessorCount;
|
||||
}
|
||||
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
|
||||
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
@@ -115,24 +118,34 @@ static const char* detectByOS(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
cpu->frequencyMin = cpu->frequencyMax = mhz / 1000.0;
|
||||
cpu->frequencyBase = mhz / 1000.0;
|
||||
}
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
|
||||
if (cpu->coresLogical == 0)
|
||||
{
|
||||
DWORD cores;
|
||||
if (RegQueryInfoKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", NULL, NULL, &cores, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* error = detectByOS(cpu);
|
||||
detectNCores(cpu);
|
||||
|
||||
const char* error = detectByRegistry(cpu);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
const wchar_t* mountpoint = buf + i;
|
||||
wchar_t* mountpoint = buf + i;
|
||||
|
||||
UINT driveType = GetDriveTypeW(mountpoint);
|
||||
if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
@@ -25,13 +25,6 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
}
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
|
||||
wchar_t volumeName[64];
|
||||
if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
ffStrbufInitWS(&disk->mountFrom, volumeName);
|
||||
else
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
|
||||
if(!GetDiskFreeSpaceExW(
|
||||
mountpoint,
|
||||
@@ -78,6 +71,17 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
}
|
||||
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
if (mountpoint[2] == L'\\' && mountpoint[3] == L'\0')
|
||||
{
|
||||
wchar_t volumeName[MAX_PATH + 1];
|
||||
mountpoint[2] = L'\0';
|
||||
if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
ffStrbufInitWS(&disk->mountFrom, volumeName);
|
||||
else
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
}
|
||||
|
||||
//Unsupported
|
||||
disk->filesUsed = 0;
|
||||
disk->filesTotal = 0;
|
||||
|
||||
@@ -63,10 +63,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel
|
||||
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
|
||||
|
||||
int vram; // Supported on Intel
|
||||
if(!ffCfDictGetInt(properties, CFSTR("VRAM,totalMB"), &vram))
|
||||
gpu->dedicated.total = (uint64_t) vram * 1024 * 1024;
|
||||
|
||||
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
|
||||
|
||||
@@ -111,6 +111,8 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
else if(ffStrbufStartsWithS(hwModel, "Mac"))
|
||||
{
|
||||
const char* version = hwModel->chars + strlen("Mac");
|
||||
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
|
||||
@@ -1,23 +1,35 @@
|
||||
#include "publicip.h"
|
||||
#include "common/networking.h"
|
||||
|
||||
#define FF_UNITIALIZED ((const char*)(uintptr_t) -1)
|
||||
static FFNetworkingState state;
|
||||
static int status = -1;
|
||||
static const char* status = FF_UNITIALIZED;
|
||||
|
||||
void ffPreparePublicIp(FFPublicIpOptions* options)
|
||||
{
|
||||
if (status != -1)
|
||||
if (status != FF_UNITIALIZED)
|
||||
{
|
||||
fputs("Error: this module can only be used once due to internal limitations\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
state.timeout = options->timeout;
|
||||
|
||||
if (options->url.length == 0)
|
||||
status = ffNetworkingSendHttpRequest(&state, "ipinfo.io", "/json", NULL);
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY host = ffStrbufCreateCopy(&options->url);
|
||||
ffStrbufSubstrAfterFirstS(&host, "://");
|
||||
uint32_t hostStartIndex = ffStrbufFirstIndexS(&host, "://");
|
||||
if (hostStartIndex < host.length)
|
||||
{
|
||||
if (hostStartIndex != 4 || !ffStrbufStartsWithIgnCaseS(&host, "http"))
|
||||
{
|
||||
fputs("Error: only http: protocol is supported. Use `Command` module with `curl` if needed\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
ffStrbufSubstrAfter(&host, hostStartIndex + (strlen("://") - 1));
|
||||
}
|
||||
uint32_t pathStartIndex = ffStrbufFirstIndexC(&host, '/');
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
@@ -41,18 +53,21 @@ static inline void wrapYyjsonFree(yyjson_doc** doc)
|
||||
|
||||
const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result)
|
||||
{
|
||||
if (status == -1)
|
||||
if (status == FF_UNITIALIZED)
|
||||
ffPreparePublicIp(options);
|
||||
|
||||
if (status == 0)
|
||||
return "Failed to connect to an IP detection server";
|
||||
if (status != NULL)
|
||||
return status;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096);
|
||||
bool success = ffNetworkingRecvHttpResponse(&state, &response, options->timeout);
|
||||
if (success) ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n");
|
||||
const char* error = ffNetworkingRecvHttpResponse(&state, &response);
|
||||
if (error == NULL)
|
||||
ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n");
|
||||
else
|
||||
return error;
|
||||
|
||||
if (!success || response.length == 0)
|
||||
return "Failed to receive the server response";
|
||||
if (response.length == 0)
|
||||
return "Empty server response received";
|
||||
|
||||
if (options->url.length == 0)
|
||||
{
|
||||
@@ -69,5 +84,6 @@ const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* resul
|
||||
|
||||
ffStrbufDestroy(&result->ip);
|
||||
ffStrbufInitMove(&result->ip, &response);
|
||||
ffStrbufTrimRightSpace(&result->ip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,6 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
|
||||
ffStrEquals(name, "ltrace") ||
|
||||
ffStrEquals(name, "perf") ||
|
||||
ffStrEquals(name, "guake-wrapped") ||
|
||||
ffStrEquals(name, "SessionLeader") || // #750
|
||||
ffStrContainsIgnCase(name, "debug") ||
|
||||
ffStrContainsIgnCase(name, "not-found") ||
|
||||
ffStrEndsWith(name, ".sh")
|
||||
@@ -281,6 +280,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
|
||||
ffStrEquals(name, "login") ||
|
||||
ffStrEquals(name, "sshd") ||
|
||||
ffStrEquals(name, "chezmoi") || // #762
|
||||
#ifdef __linux__
|
||||
ffStrStartsWith(name, "flatpak-") || // #707
|
||||
#endif
|
||||
@@ -342,6 +342,7 @@ static void getTerminalFromEnv(FFTerminalResult* result)
|
||||
!ffStrbufEqualS(&result->processName, "systemd") &&
|
||||
!ffStrbufEqualS(&result->processName, "init") &&
|
||||
!ffStrbufEqualS(&result->processName, "(init)") &&
|
||||
!ffStrbufEqualS(&result->processName, "SessionLeader") && // #750
|
||||
#endif
|
||||
|
||||
!ffStrbufEqualS(&result->processName, "0")
|
||||
|
||||
@@ -143,7 +143,7 @@ static void setShellInfoDetails(FFShellResult* result)
|
||||
ffStrbufSetS(&result->prettyName, "Windows PowerShell ISE");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "cmd"))
|
||||
{
|
||||
ffStrbufClear(&result->prettyName);
|
||||
ffStrbufSetS(&result->prettyName, "CMD");
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE snapshot = NULL;
|
||||
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, result->pid)) && GetLastError() == ERROR_BAD_LENGTH) {}
|
||||
@@ -156,15 +156,13 @@ static void setShellInfoDetails(FFShellResult* result)
|
||||
{
|
||||
if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0)
|
||||
{
|
||||
ffStrbufAppendS(&result->prettyName, "CMD (with Clink ");
|
||||
ffStrbufAppendS(&result->prettyName, " (with Clink ");
|
||||
getProductVersion(module.szExePath, &result->prettyName);
|
||||
ffStrbufAppendC(&result->prettyName, ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result->prettyName.length == 0)
|
||||
ffStrbufAppendS(&result->prettyName, "Command Prompt");
|
||||
}
|
||||
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "nu"))
|
||||
ffStrbufSetS(&result->prettyName, "nushell");
|
||||
@@ -313,7 +311,8 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
|
||||
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(&result->prettyName, "sihost") ||
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "explorer")
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "explorer") ||
|
||||
ffStrbufIgnCaseEqualS(&result->prettyName, "wininit")
|
||||
) {
|
||||
// A CUI program created by Windows Explorer will spawn a conhost as its child.
|
||||
// However the conhost process is just a placeholder;
|
||||
@@ -344,7 +343,7 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
: "Windows Terminal"
|
||||
);
|
||||
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "conhost"))
|
||||
ffStrbufSetStatic(&result->prettyName, "Console Window Host");
|
||||
ffStrbufSetStatic(&result->prettyName, "Windows Console");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "Code"))
|
||||
ffStrbufSetStatic(&result->prettyName, "Visual Studio Code");
|
||||
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer"))
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
#include "weather.h"
|
||||
|
||||
#define FF_UNITIALIZED ((const char*)(uintptr_t) -1)
|
||||
static FFNetworkingState state;
|
||||
static int status = -1;
|
||||
static const char* status = FF_UNITIALIZED;
|
||||
|
||||
void ffPrepareWeather(FFWeatherOptions* options)
|
||||
{
|
||||
if (status != -1)
|
||||
if (status != FF_UNITIALIZED)
|
||||
{
|
||||
fputs("Error: this module can only be used once due to internal limitations\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
state.timeout = options->timeout;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/");
|
||||
if (options->location.length)
|
||||
ffStrbufAppend(&path, &options->location);
|
||||
@@ -21,18 +24,24 @@ void ffPrepareWeather(FFWeatherOptions* options)
|
||||
|
||||
const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result)
|
||||
{
|
||||
if(status == -1)
|
||||
if(status == FF_UNITIALIZED)
|
||||
ffPrepareWeather(options);
|
||||
|
||||
if(status == 0)
|
||||
return "Failed to connect to 'wttr.in'";
|
||||
if(status != NULL)
|
||||
return status;
|
||||
|
||||
ffStrbufEnsureFree(result, 4095);
|
||||
bool success = ffNetworkingRecvHttpResponse(&state, result, options->timeout);
|
||||
if (success) ffStrbufSubstrAfterFirstS(result, "\r\n\r\n");
|
||||
const char* error = ffNetworkingRecvHttpResponse(&state, result);
|
||||
if (error == NULL)
|
||||
{
|
||||
ffStrbufSubstrAfterFirstS(result, "\r\n\r\n");
|
||||
ffStrbufTrimRightSpace(result);
|
||||
}
|
||||
else
|
||||
return error;
|
||||
|
||||
if(!success || result->length == 0)
|
||||
return "Failed to receive the server response";
|
||||
if(result->length == 0)
|
||||
return "Empty server response received";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,20 +1,15 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/commandoption.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/time.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "logo/logo.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "util/windows/getline.h"
|
||||
@@ -824,7 +819,10 @@ static void run(FFdata* data)
|
||||
ffPrintCommandOption(data, instance.state.resultDoc);
|
||||
|
||||
if (instance.state.resultDoc)
|
||||
{
|
||||
yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL);
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
ffFinish();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
${c1} A
|
||||
A
|
||||
ooo
|
||||
ooooo
|
||||
ooooooo
|
||||
|
||||
+13
-13
@@ -413,7 +413,7 @@ static const FFlogo A[] = {
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ARCO,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_GREEN,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
@@ -425,7 +425,7 @@ static const FFlogo A[] = {
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ARCO_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_GREEN,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
@@ -3299,6 +3299,17 @@ static const FFlogo P[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Proxmox
|
||||
{
|
||||
.names = {"proxmox"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_PROXMOX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_256 "202"
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_256 "202",
|
||||
},
|
||||
// PuffOS
|
||||
{
|
||||
.names = {"PuffOS"},
|
||||
@@ -3558,17 +3569,6 @@ static const FFlogo R[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Proxmox
|
||||
{
|
||||
.names = {"proxmox"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_PROXMOX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_256 "202"
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_256 "202",
|
||||
},
|
||||
// LAST
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -768,10 +768,8 @@ static bool printImageIfExistsSlowPath(FFLogoType type, bool printError)
|
||||
requestData.characterPixelWidth = 1;
|
||||
requestData.characterPixelHeight = 1;
|
||||
|
||||
if(
|
||||
(type != FF_LOGO_TYPE_IMAGE_CHAFA || instance.config.logo.width == 0 || instance.config.logo.height == 0) &&
|
||||
!getCharacterPixelDimensions(&requestData)
|
||||
) {
|
||||
if(!getCharacterPixelDimensions(&requestData))
|
||||
{
|
||||
if(printError)
|
||||
fputs("Logo: getCharacterPixelDimensions() failed", stderr);
|
||||
return false;
|
||||
|
||||
+11
-7
@@ -13,7 +13,7 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
FFCPUResult cpu;
|
||||
cpu.temperature = FF_CPU_TEMP_UNSET;
|
||||
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
|
||||
cpu.frequencyMax = cpu.frequencyMin = 0;
|
||||
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
|
||||
ffStrbufInit(&cpu.name);
|
||||
ffStrbufInit(&cpu.vendor);
|
||||
|
||||
@@ -48,8 +48,11 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
if(cpu.coresOnline > 1)
|
||||
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
|
||||
|
||||
if(cpu.frequencyMax > 0.0)
|
||||
ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, cpu.frequencyMax);
|
||||
double freq = cpu.frequencyMax;
|
||||
if(freq != freq)
|
||||
freq = cpu.frequencyBase;
|
||||
if(freq == freq)
|
||||
ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, freq);
|
||||
|
||||
if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET
|
||||
{
|
||||
@@ -69,7 +72,7 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyMin},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyBase},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyMax},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}
|
||||
}));
|
||||
@@ -143,7 +146,7 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
FFCPUResult cpu;
|
||||
cpu.temperature = FF_CPU_TEMP_UNSET;
|
||||
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
|
||||
cpu.frequencyMax = cpu.frequencyMin = 0;
|
||||
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
|
||||
ffStrbufInit(&cpu.name);
|
||||
ffStrbufInit(&cpu.vendor);
|
||||
|
||||
@@ -169,8 +172,9 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
yyjson_mut_obj_add_uint(doc, cores, "online", cpu.coresOnline);
|
||||
|
||||
yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency");
|
||||
yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin);
|
||||
yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase);
|
||||
yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax);
|
||||
yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin);
|
||||
|
||||
yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature);
|
||||
}
|
||||
@@ -187,7 +191,7 @@ void ffPrintCPUHelpFormat(void)
|
||||
"Physical core count",
|
||||
"Logical core count",
|
||||
"Online core count",
|
||||
"Min frequency",
|
||||
"Base frequency",
|
||||
"Max frequency",
|
||||
"Temperature (formatted)"
|
||||
}));
|
||||
|
||||
+10
-2
@@ -422,8 +422,16 @@ void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso
|
||||
yyjson_mut_obj_add_uint(doc, bytes, "used", item->bytesUsed);
|
||||
|
||||
yyjson_mut_val* files = yyjson_mut_obj_add_obj(doc, obj, "files");
|
||||
yyjson_mut_obj_add_uint(doc, files, "total", item->filesTotal);
|
||||
yyjson_mut_obj_add_uint(doc, files, "used", item->filesUsed);
|
||||
if (item->filesTotal == 0 && item->filesUsed == 0)
|
||||
{
|
||||
yyjson_mut_obj_add_null(doc, files, "total");
|
||||
yyjson_mut_obj_add_null(doc, files, "used");
|
||||
}
|
||||
else
|
||||
{
|
||||
yyjson_mut_obj_add_uint(doc, files, "total", item->filesTotal);
|
||||
yyjson_mut_obj_add_uint(doc, files, "used", item->filesUsed);
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "filesystem", &item->filesystem);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "mountpoint", &item->mountpoint);
|
||||
|
||||
+3
-2
@@ -159,16 +159,17 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments)
|
||||
strbuf->length += (uint32_t) written;
|
||||
}
|
||||
|
||||
void ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until)
|
||||
const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until)
|
||||
{
|
||||
if(value == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
char* end = strchr(value, until);
|
||||
if(end == NULL)
|
||||
ffStrbufAppendS(strbuf, value);
|
||||
else
|
||||
ffStrbufAppendNS(strbuf, (uint32_t) (end - value), value);
|
||||
return end;
|
||||
}
|
||||
|
||||
void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...)
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int));
|
||||
FF_C_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
|
||||
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
void ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until);
|
||||
const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until);
|
||||
|
||||
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
|
||||
|
||||
@@ -154,3 +154,17 @@ bool ffRegGetSubKey(HKEY hKey, uint32_t index, FFstrbuf* result, FFstrbuf* error
|
||||
ffStrbufSetWS(result, resultW);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ffRegGetNSubKeys(HKEY hKey, uint32_t* result, FFstrbuf* error)
|
||||
{
|
||||
DWORD buffer;
|
||||
if(RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &buffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
{
|
||||
if (error)
|
||||
ffStrbufAppendS(error, "RegQueryInfoKeyW(hKey) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,5 +21,6 @@ bool ffRegReadData(HKEY hKey, const wchar_t* valueNameW, uint8_t** result, uint3
|
||||
bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error);
|
||||
bool ffRegReadUint64(HKEY hKey, const wchar_t* valueNameW, uint64_t* result, FFstrbuf* error);
|
||||
bool ffRegGetSubKey(HKEY hKey, uint32_t index, FFstrbuf* result, FFstrbuf* error);
|
||||
bool ffRegGetNSubKeys(HKEY hKey, uint32_t* result, FFstrbuf* error);
|
||||
|
||||
#endif
|
||||
|
||||
+24
-42
@@ -1,54 +1,36 @@
|
||||
//
|
||||
// Include the necessary resources
|
||||
//
|
||||
#ifdef RC_INVOKED
|
||||
|
||||
#include <winuser.h>
|
||||
#include <winver.h>
|
||||
#include <ntdef.h>
|
||||
#include "fastfetch_config.h"
|
||||
|
||||
#ifdef RC_INVOKED
|
||||
|
||||
//
|
||||
// Set up debug information
|
||||
//
|
||||
#if DEBUG
|
||||
#define VER_DEBUG VS_FF_DEBUG
|
||||
#else
|
||||
#define VER_DEBUG 0
|
||||
#endif
|
||||
|
||||
#define FF_TO_STR1(str) #str
|
||||
#define FF_TO_STR(str) FF_TO_STR1(str)
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "manifest.xml"
|
||||
|
||||
// ------- version info -------------------------------------------------------
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION FASTFETCH_PROJECT_VERSION_MAJOR,FASTFETCH_PROJECT_VERSION_MINOR,FASTFETCH_PROJECT_VERSION_PATCH,FASTFETCH_PROJECT_VERSION_TWEAK_NUM
|
||||
PRODUCTVERSION FASTFETCH_PROJECT_VERSION_MAJOR,FASTFETCH_PROJECT_VERSION_MINOR,FASTFETCH_PROJECT_VERSION_PATCH,FASTFETCH_PROJECT_VERSION_TWEAK_NUM
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS (VER_DEBUG|VS_FF_PRERELEASE)
|
||||
FILEOS VOS_NT
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", FASTFETCH_PROJECT_HOMEPAGE_URL
|
||||
VALUE "FileDescription", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME) " - " FASTFETCH_PROJECT_DESCRIPTION
|
||||
VALUE "FileVersion", FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK
|
||||
VALUE "InternalName", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME) ".exe"
|
||||
VALUE "LegalCopyright", FASTFETCH_PROJECT_LICENSE
|
||||
VALUE "OriginalFilename", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME) ".exe"
|
||||
VALUE "ProductName", FASTFETCH_PROJECT_NAME
|
||||
VALUE "ProductVersion", FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409,1252
|
||||
END
|
||||
END
|
||||
FILEVERSION FASTFETCH_PROJECT_VERSION_MAJOR,FASTFETCH_PROJECT_VERSION_MINOR,FASTFETCH_PROJECT_VERSION_PATCH,FASTFETCH_PROJECT_VERSION_TWEAK_NUM
|
||||
PRODUCTVERSION FASTFETCH_PROJECT_VERSION_MAJOR,FASTFETCH_PROJECT_VERSION_MINOR,FASTFETCH_PROJECT_VERSION_PATCH,FASTFETCH_PROJECT_VERSION_TWEAK_NUM
|
||||
FILEOS VOS_NT
|
||||
FILETYPE VFT_APP
|
||||
{
|
||||
BLOCK "StringFileInfo" {
|
||||
BLOCK "040904b0" {
|
||||
VALUE "Comments", FASTFETCH_PROJECT_DESCRIPTION
|
||||
VALUE "FileDescription", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME)
|
||||
VALUE "FileVersion", FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK
|
||||
VALUE "InternalName", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME)
|
||||
VALUE "LegalCopyright", FASTFETCH_PROJECT_LICENSE
|
||||
VALUE "OriginalFilename", FF_TO_STR(FASTFETCH_TARGET_BINARY_NAME) ".exe"
|
||||
VALUE "ProductName", FASTFETCH_PROJECT_NAME " - " FASTFETCH_PROJECT_DESCRIPTION
|
||||
VALUE "ProductVersion", FASTFETCH_PROJECT_VERSION FASTFETCH_PROJECT_VERSION_TWEAK
|
||||
VALUE "CompanyName", FASTFETCH_PROJECT_HOMEPAGE_URL
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo" {
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user