Compare commits

...

94 Commits

Author SHA1 Message Date
Carter Li 6769410753 Merge pull request #794 from fastfetch-cli/dev
Release: v2.9.2
2024-04-16 10:45:39 +08:00
李通洲 40b9af6c36 Release: v2.9.2 2024-04-16 10:16:31 +08:00
李通洲 e63dfdd8b1 Packages: fix parsing of JSON config; fix wording of json_schema 2024-04-16 10:16:31 +08:00
李通洲 a6639d7211 JsonSchema: don't generate error at custom options 2024-04-16 09:55:21 +08:00
李通洲 3e251f602a Packages: fix parsing of option --packages-disabled 2024-04-16 09:50:24 +08:00
李通洲 ec25ca9fc7 Shell: ignore time 2024-04-15 20:01:40 +08:00
李通洲 396d20f2da Presets: fix compatibility of newer nerd fonts
Fix #792
2024-04-14 22:51:49 +08:00
李通洲 49181fd0bf Doc: update changelog 2024-04-14 18:03:34 +08:00
李通洲 5eb1dbe7bf Logo (Builtin): add openSUSE MicroOS
Fix #789
2024-04-14 18:02:59 +08:00
Anjia Wang 690e988cab Logo: fix logo color of AOSC OS (#791)
Resolve issue: https://github.com/fastfetch-cli/fastfetch/issues/790
2024-04-13 16:44:46 +08:00
Ulices fd41770d6e Fix: bad LainOS logo (#788)
- No need to scape '\'
- Replace a tab with spaces
2024-04-13 08:09:51 +08:00
李通洲 fb26cb1394 Disk (Android): fix build
Android does support `statx`, but it requires targeting newer ANDROID_API version to be available
2024-04-11 19:49:57 +08:00
李通洲 4e4efa67e6 Doc: update issue templates 2024-04-11 14:47:00 +08:00
李通洲 0dfb1b6bb1 Doc: add code of conduct 2024-04-11 14:10:25 +08:00
李通洲 bcbca38b1e Terminal: tidy 2024-04-10 10:11:31 +08:00
李通洲 3f0ccf802c Presets: fix #786 [ci skip] 2024-04-09 22:51:16 +08:00
李通洲 691cb4ac24 Global: use time string when generating JSON result 2024-04-09 20:47:06 +08:00
李通洲 282939f548 Disk (Windows): detect create time 2024-04-09 20:47:06 +08:00
李通洲 6f35b2f382 Disk (Linux): detect create time 2024-04-09 20:47:06 +08:00
李通洲 6700f63091 Disk (macOS): detect create time 2024-04-09 15:15:33 +08:00
李通洲 5c37ebec70 Doc: update changelog 2024-04-09 09:05:10 +08:00
李通洲 28a419d252 fastfetch: always provide trailing new line when generating JSON output 2024-04-09 09:01:28 +08:00
李通洲 95128ee95f 3rdparty (yyjson): upgrade to 0.9.0
To make use of `YYJSON_WRITE_NEWLINE_AT_END`
2024-04-09 08:58:04 +08:00
李通洲 c94180b3d2 Terminal (Windows): ignore far.exe
Ref: https://github.com/fastfetch-cli/fastfetch/issues/784#issuecomment-2043052512
2024-04-08 23:37:53 +08:00
李通洲 12ca1a0cf7 TerminalFont (Windows): better portable mode detection of Windows Terminal
`.portable` can be a folder.

Fix #784
2024-04-08 22:29:24 +08:00
apocelipes 67564dfa2c Platform: fix a memory leak (#782) 2024-04-08 09:10:03 +08:00
Carter Li a1e79a9522 Merge pull request #779 from fastfetch-cli/dev
Release v2.9.1
2024-04-07 20:49:37 +08:00
李通洲 e16f8ef349 Release: v2.9.1 2024-04-07 20:47:19 +08:00
李通洲 fd1a2072b3 Cursor: tidy 2024-04-07 20:44:17 +08:00
李通洲 aa45e70910 Revert "fastfetch: add the missing new-line in config files (#772)"
Fix #778

This reverts commit 4430b7145e.
2024-04-07 20:41:01 +08:00
李通洲 5374feb24b Cursor (Linux): support hyprcursor detection
Fix: #776
2024-04-07 20:09:35 +08:00
李通洲 12ac0ac7a9 Cursor: tidy 2024-04-07 20:09:05 +08:00
李通洲 3d78666ed3 Doc: update changelog
weston-terminal font detection was not pushed in v2.9.0
2024-04-06 17:37:31 +08:00
Carter Li dd2cc116bd TerminalFont (Linux): support weston-terminal 2024-04-06 16:56:17 +08:00
Carter Li ba2636dc1a Merge pull request #775 from fastfetch-cli/dev
Release: v2.9.0
2024-04-04 12:24:44 +08:00
李通洲 69589f1ad5 Release: v2.9.0 2024-04-04 12:22:52 +08:00
Carter Li 39da11de8e LocalIP (BSD): fix build 2024-04-04 19:42:33 +08:00
李通洲 8b7a4daeda TerminalFont: use system mono font if no config file is find 2024-04-04 11:09:28 +08:00
李通洲 82af7a5b52 Doc: update changelog 2024-04-04 10:52:42 +08:00
李通洲 a2d99695fd LocalIP: add new option localip-show-prefix-len 2024-04-04 10:42:44 +08:00
李通洲 3a2786a89f LocalIP: support network prefix detection for IPv6 2024-04-04 10:19:01 +08:00
李通洲 a6cb30d6c8 LocalIP: print all IPs if multiple IPs are assigned to the same interface 2024-04-04 10:09:06 +08:00
李通洲 de6b1f9542 LocalIP (Linux): fix network prefix detection when the value is greater than 24 2024-04-04 10:08:26 +08:00
李通洲 77431671bb Packages (Linux): add am support
Fix: #771
2024-04-03 21:08:55 +08:00
apocelipes 4430b7145e fastfetch: add the missing new-line in config files (#772) 2024-04-03 20:02:38 +08:00
kojq 898859cc7a Flashfetch: add the skipped "host" option from "Flashfetch: simplify implementation" (#770) 2024-04-02 22:36:20 +08:00
李通洲 43b96df112 Version: detect apple clang 2024-04-02 14:28:25 +08:00
李通洲 bb97893bd0 Doc: update changelog 2024-03-29 14:36:11 +08:00
李通洲 9b21ec6e1f Terminal (Linux): support weston-terminal version detection 2024-03-28 13:46:11 +08:00
李通洲 ffac354368 Terminal (Linux): support Lxterminal version detection 2024-03-26 19:28:07 +08:00
李通洲 a9aab51764 Doc: update changelog [ci skip] 2024-03-26 09:06:23 +08:00
Carter Li 4d1fc9ceb1 Packaging: update debian stuff 2024-03-25 15:04:24 +08:00
Carter Li e897a98153 Merge pull request #765 from fastfetch-cli/dev
Release v2.8.10
2024-03-25 14:22:43 +08:00
李通洲 0a8056d835 TerminalShell (Windows): adjustments
1. Don't pretty print CMD
2. Print conhost as Windows Console
2024-03-25 14:10:08 +08:00
李通洲 9681e176b3 Terminal (Windows): don't use wininit as terminal 2024-03-25 11:12:30 +08:00
李通洲 1f8be43881 Disk (Windows): use MS-DOS device name as mountFrom result, instead of useless GUID volume name 2024-03-25 10:09:35 +08:00
李通洲 30813551be Release: v2.8.10 2024-03-25 09:17:03 +08:00
李通洲 beb564f374 CI: try fixing Windows build 2024-03-25 09:17:03 +08:00
李通洲 5c97c012a9 Font (Linux): try fixing style detection 2024-03-24 18:32:50 +08:00
Carter Li 50da7cabd6 GPU (Apple): always use metal to detect vmem 2024-03-23 17:34:09 +08:00
李通洲 a6528cdfd6 Chore: simpify gitignore [ci skip]
And make scc happy
2024-03-22 10:09:58 +08:00
李通洲 588201fe46 Windows: update version.rc 2024-03-21 16:26:56 +08:00
李通洲 6184b5ee96 Doc: update changelog 2024-03-21 11:04:53 +08:00
李通洲 5e7baa9d0a PublicIP: error out if non-http protocol is specified 2024-03-21 11:01:23 +08:00
李通洲 79ae650c58 Networking: avoid short recv 2024-03-21 10:42:25 +08:00
李通洲 44107f289e Network (Windows): fix compiling 2024-03-20 16:09:17 +08:00
李通洲 75927a87b2 Networking: add timeout support for TCP connecting 2024-03-20 15:04:29 +08:00
李通洲 85da30ccf5 Networking: report detailed error messages; support --thread false for debugging 2024-03-20 13:54:27 +08:00
李通洲 f73c3b85c2 Doc: update changelog 2024-03-19 21:18:25 +08:00
李通洲 66bef2fc19 Network: trim trailing white spaces 2024-03-19 21:18:25 +08:00
李通洲 7c5eb021ee Terminal (Linux): ignore chezmoi
Fix #762
2024-03-18 09:03:10 +08:00
李通洲 f902e3b3d8 CPU (Android): don't detect manufactor of Qualcomm as ARM 2024-03-17 19:19:33 +08:00
李通洲 553124ab5b Presets: a new example
Ref: #761
2024-03-16 22:25:35 +08:00
李通洲 6c6d93370d Logo: fix colors of arco linux
Fix #759
2024-03-15 20:32:29 +08:00
Carter Li 55ae3a7dbd CPU (FreeBSD): don't display 0.00 GHz 2024-03-15 11:15:23 +08:00
Carter Li 586874080f Packaging: update debian stuff 2024-03-15 10:51:53 +08:00
Carter Li d5b91a8983 Merge pull request #758 from fastfetch-cli/dev
Release: v2.8.9
2024-03-15 09:50:54 +08:00
李通洲 72fee13112 Release: v2.8.9 2024-03-15 09:21:13 +08:00
李通洲 20ae897f39 fastfetch: remove unused #includes 2024-03-15 08:37:58 +08:00
李通洲 6f756d103f Doc: update changelog 2024-03-14 20:43:17 +08:00
李通洲 c9dd858ce3 CPU (Linux): bing cpuMHz back
It's used in WSL
2024-03-14 20:40:40 +08:00
李通洲 2e201eaaf7 CPU: bring min frequency back & code optimizations 2024-03-14 19:24:03 +08:00
李通洲 7c54dcba69 CPU (Linux): fix detection when .../base_frequency doesn't exist 2024-03-14 10:32:34 +08:00
李通洲 a107395707 Logo (Chafa): fix blurry result when specifying both width and height
Who knows why it was coded like that

Fix #757
2024-03-14 10:18:17 +08:00
李通洲 8a9fe22855 Logo: fix proxmox
Fix #756
2024-03-13 23:58:40 +08:00
李通洲 7e04e23528 CPU: rename min frequency to base frequency 2024-03-13 23:42:59 +08:00
李通洲 8d779f68f3 CPU: detect base frequency 2024-03-13 23:41:11 +08:00
李通洲 98ba08c1a0 CI (macOS): fix build 2024-03-13 10:37:45 +08:00
李通洲 a1499b82f8 Doc: update changelog 2024-03-13 08:44:09 +08:00
李通洲 c6c866d78a Host (Apple): add MacBook Air 2024 2024-03-12 18:27:02 +08:00
李通洲 7a6999bd20 Fastfetch: print final new line in --format json 2024-03-09 12:07:07 +08:00
李通洲 1084cf3523 Terminal (Linux): actually ignore SessionLeader 2024-03-09 11:52:31 +08:00
Carter Li ed5f2a3968 Chore: update screenshots 2024-03-08 15:58:47 +08:00
Carter Li 17e1d4b72d Package: update debian stuff 2024-03-08 10:03:31 +08:00
78 changed files with 1288 additions and 462 deletions
+7 -5
View File
@@ -13,6 +13,7 @@ assignees: ''
* What happened:
* What should happen:
* Fastfetch version used: <!-- please use the latest version, if possible -->
* Did it work in an older version: <!-- if yes, which version -->
* Where did you get the binary: <!-- Github Release / Github Actions / Installed with a package manager (What package manager) / Built from source yourself -->
* Does this issue still occurs in [the latest dev build](https://github.com/fastfetch-cli/fastfetch/actions/)?
@@ -41,18 +42,19 @@ Output of `fastfetch --list-features`:
//paste here
```
## If fastfatch crashed
## If fastfatch crashed or freezed
Paste the stacktrace here. You may get it with:
```
$ gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
```shell
# You may need Ctrl+C to stop the process if it freezes
gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
```
If you are able to identify which module crashed, the strace can be helpful too
```
$ strace /path/to/fastfetch --multithreading false --structure {MODULE} --pipe
```shell
strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
```
If you cannot do the instructions above, please upload the core dump file:
+22 -4
View File
@@ -7,10 +7,28 @@ assignees: ''
---
<!-- Before requesting a new feature, please try `fastfetch -c all.jsonc` to see if it has been supported -->
## Before requesting a new feature
# Current state:
* A lot of features are not enabled by default. Please try `fastfetch --list-modules` and `fastfetch -c all.jsonc` to see if it has been supported
* Fastfetch supports `Command` module, which can be used to grab output from a custom shell script. Please check if it fits your needs
# Wanted state:
```jsonc
// ~/.config/fastfetch/fastfetch.jsonc
{
"modules": [
{
"type": "command",
"text": "/path/to/your/script",
"key": "Feature Title"
}
]
}
```
# Why the change is sensible:
## Wanted features:
<!-- Your features here -->
## Motivation:
<!-- Your motivation here -->
+2
View File
@@ -7,6 +7,8 @@ assignees: ''
---
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo. For highly customized logo for personal use, it's recommended to keep it locally. Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
# OS
```
Paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro.
+3 -4
View File
@@ -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
View File
@@ -1,9 +1,9 @@
**/build/
**/.vscode/
**/.cache/
**/.kdev4/
**/.DS_Store
/.vs
build/
.vs/
.vscode/
.cache/
.kdev4/
.DS_Store
cscope.*
tags
fastfetch.kdev4
+77
View File
@@ -1,3 +1,80 @@
# 2.9.2
Changes:
* To make use of the newly introduced `yyjson` flag `YYJSON_WRITE_NEWLINE_AT_END`, fastfetch now requires `yyjson` 0.9.0 or later
Features:
* Always add a final new-line when generating JSON output
* Detect partition create time, which can be used as OS installation time (Disk)
* Print time string when generating JSON result instead of UNIX epoch time number, which is more human-readable
Bugfixes:
* Fix a memory leak
* Better portable mode detection of Windows Terminal (TerminalFont, Windows)
* Fix parsing of option `--packages-disabled` (Packages)
* Don't use command `time` as a shell (Shell)
Logos:
* Add openSUSE MicroOS
* Fix color of AOSC OS
# 2.9.1
Features:
* Support weston-terminal (missed commit in v2.9.0) (TerminalFont, Linux)
* Support hyprcursor detection (#776, Cursor, Linux)
Bugfixes:
* Fix `fastfetch --gen-config` raises SIGSEGV when `~/.config/fastfetch` doesn't exist. Regression of `2.9.0` (#778)
# 2.9.0
Features:
* Support Lxterminal version detection (Terminal, Linux)
* Support weston-terminal version detection (Terminal, Linux)
* Support `am` package manager detection (#771, Packages, Linux)
* Support network prefix length detection for IPv6 (LocalIP)
* Display all IPs when multiple IPs are assigned to the same interface (LocalIP)
* Add option `--localip-show-prefix-len` to show network prefix length for both IPv4 and IPv6. Defaults to `true` (LocalIP)
Bugfixes:
* Fix network prefix length detection when the value is greater than 24 (#773, LocalIP, Linux)
* For xfce4-terminal, use system mono font if no config file is found (TerminalFont, Linux)
# 2.8.10
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)
* 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
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:
+8 -1
View File
@@ -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.9.2
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -699,6 +699,9 @@ check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
list(APPEND LIBFASTFETCH_SRC src/3rdparty/mk_wcwidch/wcwidth.c)
endif()
if(LINUX)
check_function_exists(statx HAVE_STATX)
endif()
if(ENABLE_SYSTEM_YYJSON)
find_package(yyjson)
@@ -762,6 +765,10 @@ elseif(APPLE)
target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE)
endif()
if(HAVE_STATX)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_STATX)
endif()
if(HAVE_WCWIDTH)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WCWIDTH)
endif()
+133
View File
@@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
+18
View File
@@ -1,3 +1,21 @@
fastfetch (2.8.10) jammy; urgency=medium
* Update to 2.8.10
-- Carter Li <zhangsongcui@live.cn> Mon, 25 Mar 2024 15:01:53 +0800
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
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.8.6_source.buildinfo universe/utils optional
fastfetch_2.8.10_source.buildinfo universe/utils optional
+34 -4
View File
@@ -730,7 +730,6 @@
},
{
"type": "object",
"additionalProperties": false,
"description": "Run module with custom configurations",
"required": [
"type"
@@ -1438,6 +1437,11 @@
"type": "boolean",
"default": false
},
"showPrefixLen": {
"description": "Show network prefix length (/N)",
"type": "boolean",
"default": true
},
"compact": {
"description": "Show all IPs in one line",
"type": "boolean",
@@ -1572,9 +1576,35 @@
"description": "List installed package managers and count of installed packages"
},
"disabled": {
"description": "A colon separated list of package managers to be disabled when detecting",
"type": "string",
"default": "winget"
"description": "List of package managers to be disabled when detecting",
"type": "array",
"items": {
"type": "string",
"enum": [
"am",
"apk",
"brew",
"choco",
"dpkg",
"emerge",
"eopkg",
"flatpak",
"macports",
"nix",
"opkg",
"pacman",
"paludis",
"pkg",
"pkgtool",
"rpm",
"scoop",
"snap",
"winget",
"xbps"
],
"uniqueItems": true
},
"default": ["winget"]
},
"key": {
"$ref": "#/$defs/key"
+3 -3
View File
@@ -84,17 +84,17 @@
},
{
"type": "host",
"key": " PC",
"key": "󰌢 PC",
"keyColor": "green"
},
{
"type": "cpu",
"key": "│ ├",
"key": "│ ├󰻠",
"keyColor": "green"
},
{
"type": "gpu",
"key": "│ ├",
"key": "│ ├󰍛",
"keyColor": "green"
},
{
+104
View File
@@ -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"
}
]
}
+3 -3
View File
@@ -19,15 +19,15 @@
},
{
"type": "host",
"key": " "
"key": " 󰌢"
},
{
"type": "cpu",
"key": " "
"key": " 󰻠"
},
{
"type": "gpu",
"key": " "
"key": " 󰍛"
},
{
"type": "disk",
+1 -2
View File
@@ -14,8 +14,7 @@
},
{
"type": "icons",
"key": "I",
"format": "{5}"
"key": "I"
},
{
"type": "font",
+3 -3
View File
@@ -15,17 +15,17 @@
"modules": [
{
"type": "host",
"key": "╭─",
"key": "╭─󰌢",
"keyColor": "green"
},
{
"type": "cpu",
"key": "├─",
"key": "├─󰻠",
"keyColor": "green"
},
{
"type": "gpu",
"key": "├─",
"key": "├─󰍛",
"keyColor": "green"
},
{
+3 -3
View File
@@ -77,17 +77,17 @@
"break",
{
"type": "host",
"key": " PC",
"key": "󰌢 PC",
"keyColor": "green"
},
{
"type": "cpu",
"key": "├",
"key": "├󰻠",
"keyColor": "green"
},
{
"type": "gpu",
"key": "├",
"key": "├󰍛",
"keyColor": "green"
},
{
+1 -1
View File
@@ -33,7 +33,7 @@
},
{
"type": "memory",
"key": ""
"key": "󰻠"
},
{
"type": "packages",
+1 -1
View File
@@ -12,7 +12,7 @@
"uptime",
{
"type": "battery",
"format": "{/4}{-}{/}{4}%{?5} [{5}]{?}"
"format": "{/4}{-}{/}{4}{?5} [{5}]{?}"
},
"break",
"packages",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 341 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{
"home": "https://github.com/ibireme/yyjson",
"license": "MIT ( embed in source )",
"version": "0.8.0",
"version": "0.9.0",
"author": "ibireme"
}
+31 -5
View File
@@ -1407,6 +1407,7 @@ bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) {
void yyjson_mut_doc_free(yyjson_mut_doc *doc) {
if (doc) {
yyjson_alc alc = doc->alc;
memset(&doc->alc, 0, sizeof(alc));
unsafe_yyjson_str_pool_release(&doc->str_pool, &alc);
unsafe_yyjson_val_pool_release(&doc->val_pool, &alc);
alc.free(alc.ctx, doc);
@@ -8309,13 +8310,15 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
bool cpy = (enc_table == enc_table_cpy);
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
const usize end_len = 2; /* '\n' and '\0' */
switch (unsafe_yyjson_get_type(val)) {
case YYJSON_TYPE_RAW:
str_len = unsafe_yyjson_get_len(val);
str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
check_str_len(str_len);
incr_len(str_len + 1);
incr_len(str_len + end_len);
cur = write_raw(cur, str_ptr, str_len);
break;
@@ -8323,7 +8326,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
str_len = unsafe_yyjson_get_len(val);
str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
check_str_len(str_len);
incr_len(str_len * 6 + 4);
incr_len(str_len * 6 + 2 + end_len);
if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
cur = write_string_noesc(cur, str_ptr, str_len);
} else {
@@ -8333,7 +8336,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
break;
case YYJSON_TYPE_NUM:
incr_len(32);
incr_len(32 + end_len);
cur = write_number(cur, val, flg);
if (unlikely(!cur)) goto fail_num;
break;
@@ -8349,13 +8352,13 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
break;
case YYJSON_TYPE_ARR:
incr_len(4);
incr_len(2 + end_len);
byte_copy_2(cur, "[]");
cur += 2;
break;
case YYJSON_TYPE_OBJ:
incr_len(4);
incr_len(2 + end_len);
byte_copy_2(cur, "{}");
cur += 2;
break;
@@ -8364,6 +8367,7 @@ static_inline u8 *yyjson_write_single(yyjson_val *val,
goto fail_type;
}
if (newline) *cur++ = '\n';
*cur = '\0';
*dat_len = (usize)(cur - hdr);
memset(err, 0, sizeof(yyjson_write_err));
@@ -8436,6 +8440,7 @@ static_inline u8 *yyjson_write_minify(const yyjson_val *root,
bool cpy = (enc_table == enc_table_cpy);
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
alc_len = root->uni.ofs / sizeof(yyjson_val);
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
@@ -8542,6 +8547,11 @@ ctn_end:
}
doc_end:
if (newline) {
incr_len(2);
*(cur - 1) = '\n';
cur++;
}
*--cur = '\0';
*dat_len = (usize)(cur - hdr);
memset(err, 0, sizeof(yyjson_write_err));
@@ -8615,6 +8625,7 @@ static_inline u8 *yyjson_write_pretty(const yyjson_val *root,
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
alc_len = root->uni.ofs / sizeof(yyjson_val);
alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
@@ -8745,6 +8756,10 @@ ctn_end:
}
doc_end:
if (newline) {
incr_len(2);
*cur++ = '\n';
}
*cur = '\0';
*dat_len = (usize)(cur - hdr);
memset(err, 0, sizeof(yyjson_write_err));
@@ -8977,6 +8992,7 @@ static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root,
bool cpy = (enc_table == enc_table_cpy);
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
@@ -9087,6 +9103,11 @@ ctn_end:
}
doc_end:
if (newline) {
incr_len(2);
*(cur - 1) = '\n';
cur++;
}
*--cur = '\0';
*dat_len = (usize)(cur - hdr);
err->code = YYJSON_WRITE_SUCCESS;
@@ -9162,6 +9183,7 @@ static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root,
bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
bool newline = has_write_flag(NEWLINE_AT_END) != 0;
alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
@@ -9296,6 +9318,10 @@ ctn_end:
}
doc_end:
if (newline) {
incr_len(2);
*cur++ = '\n';
}
*cur = '\0';
*dat_len = (usize)(cur - hdr);
err->code = YYJSON_WRITE_SUCCESS;
+35 -21
View File
@@ -527,16 +527,16 @@ extern "C" {
#define YYJSON_VERSION_MAJOR 0
/** The minor version of yyjson. */
#define YYJSON_VERSION_MINOR 8
#define YYJSON_VERSION_MINOR 9
/** The patch version of yyjson. */
#define YYJSON_VERSION_PATCH 0
/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
#define YYJSON_VERSION_HEX 0x000800
#define YYJSON_VERSION_HEX 0x000900
/** The version string of yyjson. */
#define YYJSON_VERSION_STRING "0.8.0"
#define YYJSON_VERSION_STRING "0.9.0"
/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
yyjson_api uint32_t yyjson_version(void);
@@ -738,7 +738,7 @@ typedef uint32_t yyjson_read_flag;
- Report error if double number is infinity.
- Report error if string contains invalid UTF-8 character or BOM.
- Report error on trailing commas, comments, inf and nan literals. */
static const yyjson_read_flag YYJSON_READ_NOFLAG = 0 << 0;
static const yyjson_read_flag YYJSON_READ_NOFLAG = 0;
/** Read the input data in-situ.
This option allows the reader to modify and use input data to store string
@@ -1067,7 +1067,7 @@ typedef uint32_t yyjson_write_flag;
- Report error on inf or nan number.
- Report error on invalid UTF-8 string.
- Do not escape unicode or slash. */
static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0 << 0;
static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0;
/** Write JSON pretty with 4 space indent. */
static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0;
@@ -1096,6 +1096,10 @@ static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5;
This flag will override `YYJSON_WRITE_PRETTY` flag. */
static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6;
/** Adds a newline character `\n` at the end of the JSON.
This can be helpful for text editors or NDJSON. */
static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7;
/** Result code for JSON writer */
@@ -3695,7 +3699,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
The `len` should be the length of the `val`, in bytes.
This function allows duplicated key in one object.
@warning The key/value strings are not copied, you should keep these strings
@warning The key strings are not copied, you should keep these strings
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -4829,6 +4833,7 @@ yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) {
yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) {
if (doc) {
yyjson_alc alc = doc->alc;
memset(&doc->alc, 0, sizeof(alc));
if (doc->str_pool) alc.free(alc.ctx, doc->str_pool);
alc.free(alc.ctx, doc);
}
@@ -5668,6 +5673,7 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
if (yyjson_likely(doc)) {
yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
if (yyjson_likely(val)) {
_val = !!_val;
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
return val;
}
@@ -5920,7 +5926,8 @@ yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) {
yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
yyjson_mut_doc *doc, const bool *vals, size_t count) {
yyjson_mut_arr_with_func({
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)vals[i] << 3);
bool _val = !!vals[i];
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
});
}
@@ -6872,6 +6879,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
const char *_key,
bool _val) {
yyjson_mut_obj_add_func({
_val = !!_val;
val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3);
});
}
@@ -7730,33 +7738,39 @@ yyjson_api_inline bool yyjson_ptr_get_bool(
}
/**
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint.
Returns true if value at `ptr` exists and is the correct type, otherwise false.
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
that fits in `uint64_t`. Returns true if successful, otherwise false.
*/
yyjson_api_inline bool yyjson_ptr_get_uint(
yyjson_val *root, const char *ptr, uint64_t *value) {
yyjson_val *val = yyjson_ptr_get(root, ptr);
if (value && yyjson_is_uint(val)) {
*value = unsafe_yyjson_get_uint(val);
return true;
} else {
return false;
if (value && val) {
uint64_t ret = val->uni.u64;
if (unsafe_yyjson_is_uint(val) ||
(unsafe_yyjson_is_sint(val) && !(ret >> 63))) {
*value = ret;
return true;
}
}
return false;
}
/**
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint.
Returns true if value at `ptr` exists and is the correct type, otherwise false.
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
that fits in `int64_t`. Returns true if successful, otherwise false.
*/
yyjson_api_inline bool yyjson_ptr_get_sint(
yyjson_val *root, const char *ptr, int64_t *value) {
yyjson_val *val = yyjson_ptr_get(root, ptr);
if (value && yyjson_is_sint(val)) {
*value = unsafe_yyjson_get_sint(val);
return true;
} else {
return false;
if (value && val) {
int64_t ret = val->uni.i64;
if (unsafe_yyjson_is_sint(val) ||
(unsafe_yyjson_is_uint(val) && ret >= 0)) {
*value = ret;
return true;
}
}
return false;
}
/**
+19 -44
View File
@@ -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
View File
@@ -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);
+53 -21
View File
@@ -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";
}
+42 -25
View File
@@ -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";
}
+5 -5
View File
@@ -100,19 +100,19 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
{
if(gtk2->length > 0 && gtk3->length > 0 && gtk4->length > 0)
{
if((ffStrbufIgnCaseComp(gtk2, gtk3) == 0) && (ffStrbufIgnCaseComp(gtk2, gtk4) == 0))
if((ffStrbufIgnCaseEqual(gtk2, gtk3)) && (ffStrbufIgnCaseEqual(gtk2, gtk4)))
{
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK2/3/4]");
}
else if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
else if(ffStrbufIgnCaseEqual(gtk2, gtk3))
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK2/3], ");
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK4]");
}
else if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
else if(ffStrbufIgnCaseEqual(gtk3, gtk4))
{
ffStrbufAppend(buffer, gtk2);
ffStrbufAppendS(buffer, " [GTK2], ");
@@ -131,7 +131,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
}
else if(gtk2->length > 0 && gtk3->length > 0)
{
if(ffStrbufIgnCaseComp(gtk2, gtk3) == 0)
if(ffStrbufIgnCaseEqual(gtk2, gtk3))
{
ffStrbufAppend(buffer, gtk3);
ffStrbufAppendS(buffer, " [GTK2/3]");
@@ -146,7 +146,7 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
}
else if(gtk3->length > 0 && gtk4->length > 0)
{
if(ffStrbufIgnCaseComp(gtk3, gtk4) == 0)
if(ffStrbufIgnCaseEqual(gtk3, gtk4))
{
ffStrbufAppend(buffer, gtk4);
ffStrbufAppendS(buffer, " [GTK3/4]");
+36 -2
View File
@@ -1,12 +1,12 @@
#pragma once
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#ifdef _WIN32
#include <synchapi.h>
#include <profileapi.h>
#include <sysinfoapi.h>
#else
#include <time.h>
#endif
static inline uint64_t ffTimeGetTick() //In msec
@@ -45,3 +45,37 @@ static inline void ffTimeSleep(uint32_t msec)
nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL);
#endif
}
#ifdef _WIN32
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
#endif
// Not thread-safe
static inline const char* ffTimeToFullStr(uint64_t msec)
{
if (msec == 0) return "";
time_t tsec = (time_t) (msec / 1000);
const struct tm* tm = localtime(&tsec);
static char buf[32];
strftime(buf, __builtin_strlen("0000-00-00T00:00:00") + 1, "%FT%T", tm);
snprintf(buf + __builtin_strlen("0000-00-00T00:00:00"), __builtin_strlen(".000") + 1, ".%03u", (unsigned) (msec % 1000));
strftime(buf + __builtin_strlen("0000-00-00T00:00:00.000"), __builtin_strlen("+0000") + 1, "%z", tm);
return buf;
}
// Not thread-safe
static inline const char* ffTimeToShortStr(uint64_t msec)
{
if (msec == 0) return "";
time_t tsec = (time_t) (msec / 1000);
static char buf[32];
strftime(buf, sizeof(buf), "%F %T", localtime(&tsec));
return buf;
}
#ifdef _WIN32
#pragma GCC diagnostic pop
#endif
+9
View File
@@ -1261,6 +1261,15 @@
"default": false
}
},
{
"long": "localip-show-prefix-len",
"desc": "Show network prefix length (/N) in local ip module",
"arg": {
"type": "bool",
"optional": true,
"default": true
}
},
{
"long": "localip-name-prefix",
"desc": "Show interfaces with given interface name prefix only",
+3 -1
View File
@@ -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);
+1 -2
View File
@@ -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)
+2 -2
View File
@@ -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)
+34 -21
View File
@@ -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)
{
+46 -33
View File
@@ -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;
}
+19 -4
View File
@@ -68,18 +68,33 @@ static bool detectCursorFromEnv(FFCursorResult* result)
return true;
}
static bool detectCursorHyprcursor(FFCursorResult* result)
{
const char* hyprcursor_theme = getenv("HYPRCURSOR_THEME");
if(!ffStrSet(hyprcursor_theme))
return false;
ffStrbufAppendS(&result->theme, hyprcursor_theme);
ffStrbufAppendS(&result->size, getenv("HYPRCURSOR_SIZE"));
return true;
}
void ffDetectCursor(FFCursorResult* result)
{
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
if(ffStrbufCompS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG) == 0)
if(ffStrbufEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG))
ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
else if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
else if(ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY))
ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
detectCursorFromConfigFile("kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
else if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
detectCursorFromConfigFile("lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
else if(ffStrbufIgnCaseEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_HYPRLAND) && detectCursorHyprcursor(result))
return;
else if(
!detectCursorGTK(result) &&
!detectCursorFromEnv(result) &&
+2
View File
@@ -17,6 +17,8 @@ typedef struct FFDisk
uint32_t filesUsed;
uint32_t filesTotal;
uint64_t createTime;
} FFDisk;
/**
+5
View File
@@ -3,6 +3,7 @@
#include "util/stringUtils.h"
#include <sys/mount.h>
#include <sys/stat.h>
#ifdef __FreeBSD__
#include <libgeom.h>
@@ -130,6 +131,10 @@ const char* ffDetectDisksImpl(FFlist* disks)
if(fs->f_flags & MNT_RDONLY)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
struct stat st;
if(stat(fs->f_mntonname, &st) == 0)
disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000));
}
return NULL;
+8 -1
View File
@@ -6,9 +6,9 @@
#include <limits.h>
#include <ctype.h>
#include <dirent.h>
#include <mntent.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <mntent.h>
#include <sys/mount.h>
#ifdef __USE_LARGEFILE64
@@ -241,6 +241,13 @@ static void detectStats(FFDisk* disk)
if(fs.f_flag & ST_RDONLY)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
disk->createTime = 0;
#ifdef FF_HAVE_STATX
struct statx stx;
if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME))
disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000));
#endif
}
const char* ffDetectDisksImpl(FFlist* disks)
+18 -8
View File
@@ -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,23 @@ const char* ffDetectDisksImpl(FFlist* disks)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
WIN32_FILE_ATTRIBUTE_DATA data;
if(GetFileAttributesExW(mountpoint, GetFileExInfoStandard, &data) && data.ftCreationTime.dwHighDateTime > 0)
disk->createTime = (*(uint64_t*) &data.ftCreationTime - 116444736000000000ull) / 10000ull;
else
disk->createTime = 0;
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;
@@ -21,6 +21,7 @@
#define FF_WM_PRETTY_XFWM4 "Xfwm4"
#define FF_WM_PRETTY_OPENBOX "Openbox"
#define FF_WM_PRETTY_I3 "i3"
#define FF_WM_PRETTY_HYPRLAND "Hyprland"
#define FF_WM_PRETTY_WAYFIRE "Wayfire"
#define FF_WM_PRETTY_SWAY "Sway"
#define FF_WM_PRETTY_BSPWM "bspwm"
+5
View File
@@ -52,6 +52,9 @@ static const char* parseEnv(void)
if(getenv("TDE_FULL_SESSION") != NULL)
return "Trinity";
if(getenv("HYPRLAND_CMD") != NULL)
return "Hyprland";
#ifdef __linux__
if(
getenv("WAYLAND_DISPLAY") != NULL &&
@@ -116,6 +119,8 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_ICEWM);
else if(ffStrEqualsIgnCase(name, "dtwm"))
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DTWM);
else if(ffStrEqualsIgnCase(name, "hyprland"))
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HYPRLAND);
}
static void applyNameIfWM(FFDisplayServerResult* result, const char* processName)
-4
View File
@@ -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;
+2 -2
View File
@@ -151,9 +151,9 @@ const FFQtResult* ffDetectQt(void)
const FFDisplayServerResult* wmde = ffConnectDisplayServer();
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA) == 0)
if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA))
detectPlasma(&result);
else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT) == 0)
else if(ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT))
detectLXQt(&result);
return &result;
+2
View File
@@ -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)";
+28 -8
View File
@@ -40,10 +40,12 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
switch (type)
{
case AF_INET:
ffStrbufSetS(&ip->ipv4, addr);
if (ip->ipv4.length) ffStrbufAppendC(&ip->ipv4, ',');
ffStrbufAppendS(&ip->ipv4, addr);
break;
case AF_INET6:
ffStrbufSetS(&ip->ipv6, addr);
if (ip->ipv6.length) ffStrbufAppendC(&ip->ipv6, ',');
ffStrbufAppendS(&ip->ipv6, addr);
break;
case -1:
ffStrbufSetS(&ip->mac, addr);
@@ -83,12 +85,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
char addressBuffer[INET_ADDRSTRLEN + 4];
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
int cidr = __builtin_popcount(inet_netof(netmask->sin_addr));
if (cidr != 0)
if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)
{
size_t len = strlen(addressBuffer);
snprintf(addressBuffer + len, 4, "/%d", cidr);
struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
int cidr = __builtin_popcount(netmask->sin_addr.s_addr);
if (cidr != 0)
{
size_t len = strlen(addressBuffer);
snprintf(addressBuffer + len, 4, "/%d", cidr);
}
}
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute);
@@ -99,8 +104,23 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
continue;
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
char addressBuffer[INET6_ADDRSTRLEN];
char addressBuffer[INET6_ADDRSTRLEN + 4];
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)
{
struct sockaddr_in6* netmask = (struct sockaddr_in6*) ifa->ifa_netmask;
int cidr = 0;
static_assert(sizeof(netmask->sin6_addr) % sizeof(uint64_t) == 0, "");
for (uint32_t i = 0; i < sizeof(netmask->sin6_addr) / sizeof(uint64_t); ++i)
cidr += __builtin_popcountll(((uint64_t*) &netmask->sin6_addr)[i]);
if (cidr != 0)
{
size_t len = strlen(addressBuffer);
snprintf(addressBuffer + len, 4, "/%d", cidr);
}
}
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute);
}
#if defined(__FreeBSD__) || defined(__APPLE__)
+15 -6
View File
@@ -6,7 +6,7 @@
#include "util/windows/unicode.h"
#include "localip.h"
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, bool defaultRoute)
static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool newIp, bool defaultRoute)
{
FFLocalIpResult* ip = NULL;
@@ -27,13 +27,15 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type
switch (type)
{
case AF_INET:
ffStrbufSetS(&ip->ipv4, value);
if (ip->ipv4.length) ffStrbufAppendC(&ip->ipv4, ',');
ffStrbufAppendS(&ip->ipv4, addr);
break;
case AF_INET6:
ffStrbufSetS(&ip->ipv6, value);
if (ip->ipv6.length) ffStrbufAppendC(&ip->ipv6, ',');
ffStrbufAppendS(&ip->ipv6, addr);
break;
case -1:
ffStrbufSetS(&ip->mac, value);
ffStrbufSetS(&ip->mac, addr);
break;
}
}
@@ -108,7 +110,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
char addressBuffer[INET_ADDRSTRLEN + 4];
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
if (ifa->OnLinkPrefixLength)
if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength)
{
size_t len = strlen(addressBuffer);
snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength);
@@ -120,8 +122,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
{
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
char addressBuffer[INET6_ADDRSTRLEN];
char addressBuffer[INET6_ADDRSTRLEN + 4];
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength)
{
size_t len = strlen(addressBuffer);
snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength);
}
addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute);
newIp = false;
}
+1
View File
@@ -4,6 +4,7 @@
typedef struct FFPackagesResult
{
uint32_t am;
uint32_t apk;
uint32_t brew;
uint32_t brewCask;
+38
View File
@@ -253,6 +253,43 @@ static uint32_t getRpmFromLibrpm(void)
#endif //FF_HAVE_RPM
static uint32_t getAM(FFstrbuf* baseDir)
{
// #771
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, "/opt");
uint32_t optDirLength = baseDir->length;
uint32_t result = 0;
ffStrbufAppendS(baseDir, "/am/APP-MANAGER");
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
{
++result; // `am` itself is counted as a package too
ffStrbufSubstrBefore(baseDir, optDirLength);
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars);
if(dirp)
{
struct dirent *entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
if (entry->d_type == DT_DIR)
{
ffStrbufAppendF(baseDir, "/%s/AM-updater", entry->d_name);
if (ffPathExists(baseDir->chars, FF_PATHTYPE_FILE))
++result;
ffStrbufSubstrBefore(baseDir, optDirLength);
}
}
}
}
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
{
if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
@@ -277,6 +314,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
}
if (!(options->disabled & FF_PACKAGES_FLAG_PALUDIS_BIT)) packageCounts->paludis += countFilesRecursive(baseDir, "/var/db/paludis/repositories", "environment.bz2");
if (!(options->disabled & FF_PACKAGES_FLAG_OPKG_BIT)) packageCounts->opkg += getNumStrings(baseDir, "/usr/lib/opkg/status", "Package:"); // openwrt
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT)) packageCounts->am = getAM(baseDir);
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
+26 -10
View File
@@ -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;
}
+3 -3
View File
@@ -160,7 +160,7 @@ static const char* detectFromWTImpl(FFstrbuf* content, FFstrbuf* name, double* s
#include <shlobj.h>
#endif
static void detectFromWindowsTeriminal(const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont)
static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFontResult* terminalFont)
{
//https://learn.microsoft.com/en-us/windows/terminal/install#settings-json-file
FF_STRBUF_AUTO_DESTROY json = ffStrbufCreate();
@@ -174,7 +174,7 @@ static void detectFromWindowsTeriminal(const FFstrbuf* terminalExe, FFTerminalFo
char* pathEnd = jsonPath + strlen(jsonPath);
strncpy(pathEnd, ".portable", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(ffPathExists(jsonPath, FF_PATHTYPE_FILE))
if(ffPathExists(jsonPath, FF_PATHTYPE_ANY))
{
strncpy(pathEnd, "settings\\settings.json", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1);
if(!ffAppendFileBuffer(jsonPath, &json))
@@ -432,7 +432,7 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
//Used by both Linux (WSL) and Windows
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "Windows Terminal") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "WindowsTerminal.exe"))
detectFromWindowsTeriminal(&terminal->exe, terminalFont);
detectFromWindowsTerminal(&terminal->exe, terminalFont);
#endif
else
@@ -145,13 +145,7 @@ static void detectXFCETerminal(FFTerminalFontResult* terminalFont)
});
}
if (!configFound)
{
ffStrbufSetStatic(&terminalFont->error, "Couldn't find xfce4/xfconf/xfce-perchannel-xml/xfce4-terminal.xml or xfce4/terminal/terminalrc");
return;
}
if(useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "false") == 0)
if(configFound && (useSysFont.length == 0 || ffStrbufIgnCaseCompS(&useSysFont, "false") == 0))
{
if(fontName.length == 0)
ffStrbufAppendF(&terminalFont->error, "Couldn't find FontName in %s", path);
@@ -331,6 +325,19 @@ static void detectWarp(FFTerminalFontResult* terminalFont)
}
}
static void detectWestonTerminal(FFTerminalFontResult* terminalFont)
{
FF_STRBUF_AUTO_DESTROY font = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY size = ffStrbufCreate();
ffParsePropFileConfigValues("weston.ini", 2, (FFpropquery[]) {
{"font=", &font},
{"font-size=", &size},
});
if (!font.length) ffStrbufSetStatic(&font, "DejaVu Sans Mono");
if (!size.length) ffStrbufSetStatic(&size, "14");
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
}
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseEqualS(&terminal->processName, "konsole"))
@@ -361,4 +368,6 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
detectSt(terminalFont, terminal->pid);
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "warp"))
detectWarp(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "weston-terminal"))
detectWestonTerminal(terminalFont);
}
+30 -1
View File
@@ -400,6 +400,29 @@ FF_MAYBE_UNUSED static bool getTerminalVersionSt(FF_MAYBE_UNUSED FFstrbuf* exe,
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionLxterminal(FFstrbuf* exe, FFstrbuf* version)
{
if(!getExeVersionRaw(exe, version)) return false;
// lxterminal 0.3.2
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionWeston(FF_MAYBE_UNUSED FFstrbuf* exe, FFstrbuf* version)
{
// weston-terminal doesn't report a version, use weston version instead
if(ffProcessAppendStdOut(version, (char* const[]){
"weston",
"--version",
NULL
})) return false;
//weston 8.0.0
ffStrbufSubstrAfterFirstC(version, ' ');
return version->length > 0;
}
static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version)
{
const char* env = getenv("TERMINAL_VERSION_STRING");
@@ -410,7 +433,7 @@ static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version)
}
if(!getExeVersionRaw(exe, version)) return false;
// Contour Terminal Emulator 0.3.12.262
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrAfterLastC(version, ' ');
return version->length > 0;
}
@@ -525,6 +548,12 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
if(ffStrbufIgnCaseEqualS(processName, "st"))
return getTerminalVersionSt(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "lxterminal"))
return getTerminalVersionLxterminal(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "weston-terminal"))
return getTerminalVersionWeston(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "urxvt") ||
ffStrbufIgnCaseEqualS(processName, "urxvtd") ||
ffStrbufIgnCaseEqualS(processName, "rxvt") ||
@@ -231,7 +231,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrEquals(name, "ltrace") ||
ffStrEquals(name, "perf") ||
ffStrEquals(name, "guake-wrapped") ||
ffStrEquals(name, "SessionLeader") || // #750
ffStrEquals(name, "time") ||
ffStrContainsIgnCase(name, "debug") ||
ffStrContainsIgnCase(name, "not-found") ||
ffStrEndsWith(name, ".sh")
@@ -281,6 +281,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 +343,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")
@@ -98,16 +98,14 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "su") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "doas") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "strace") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "guake-wrapped") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || // scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") ||
ffStrbufContainIgnCaseS(&result->prettyName, "debug") ||
ffStrbufContainIgnCaseS(&result->prettyName, "time") ||
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
) {
ffStrbufClear(&result->processName);
@@ -143,7 +141,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 +154,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");
@@ -262,6 +258,7 @@ static bool detectDefaultTerminal(FFTerminalResult* result)
if(ffPathExists(result->exe.chars, FF_PATHTYPE_FILE))
{
result->exeName = result->exe.chars + ffStrbufLastIndexC(&result->exe, '\\') + 1;
ffStrbufSet(&result->exePath, &result->exe);
}
else
{
@@ -296,7 +293,7 @@ static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName, &result->exePath, &hasGui))
{
if(!hasGui)
if(!hasGui || ffStrbufIgnCaseEqualS(&result->processName, "far.exe")) // Far includes GUI objects...
{
//We are in nested shell
ffStrbufClear(&result->processName);
@@ -313,7 +310,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 +342,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"))
+15 -1
View File
@@ -32,7 +32,21 @@ void ffDetectVersion(FFVersionResult* version)
version->cmakeBuiltType = FASTFETCH_PROJECT_CMAKE_BUILD_TYPE;
version->compileTime = __DATE__ ", " __TIME__;
#ifdef __clang__
version->compiler = "clang " FF_STR(__clang_major__) "." FF_STR(__clang_minor__) "." FF_STR(__clang_patchlevel__);
version->compiler =
#ifdef _MSC_VER
"clang-cl " ;
#elif defined(__APPLE__) && defined(__apple_build_version__)
"Apple clang "
#else
"clang "
#endif
FF_STR(__clang_major__) "." FF_STR(__clang_minor__) "." FF_STR(__clang_patchlevel__)
#if defined(__APPLE__) && defined(__apple_build_version__)
" (" FF_STR(__apple_build_version__) ")"
#endif
;
#elif defined(__GNUC__)
version->compiler = "gcc " FF_STR(__GNUC__) "." FF_STR(__GNUC_MINOR__) "." FF_STR(__GNUC_PATCHLEVEL__);
#elif defined(_MSC_VER)
+18 -9
View File
@@ -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 -8
View File
@@ -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,7 @@ 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);
yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
else
ffFinish();
}
@@ -843,11 +838,11 @@ static void writeConfigFile(FFdata* data, const FFstrbuf* filename)
ffMigrateCommandOptionToJsonc(data, doc);
if (ffStrbufEqualS(filename, "-"))
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL);
yyjson_mut_write_fp(stdout, doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, NULL, NULL);
else
{
size_t len;
FF_AUTO_FREE const char* str = yyjson_mut_write(doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, &len);
FF_AUTO_FREE const char* str = yyjson_mut_write(doc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES | YYJSON_WRITE_NEWLINE_AT_END, &len);
if (!str)
{
printf("Error: failed to generate config file\n");
+1
View File
@@ -21,6 +21,7 @@ int main(void)
&options->title,
&options->separator,
&options->os,
&options->host,
&options->kernel,
&options->uptime,
&options->packages,
+1 -1
View File
@@ -1,4 +1,4 @@
${c1} A
A
ooo
ooooo
ooooooo
+5 -5
View File
@@ -1,8 +1,8 @@
${c2} /==\\
\\==/
${c2} /==\
\==/
${c1} · · · · · · ·
· · · · · · · · · ·
· · · ${c2}.-======-.${c1}· · · ·
· · · ${c2}.-======-.${c1}· · · ·
${c2} .::.${c1} ·${c2}.-============-.${c1}· ${c2}.::.
.:==:${c1}· ${c2}.:===:'${c1}. ·· .${c2}':===:.${c1} ·${c2}:==:.
.:===:${c1} · ${c2}:===.${c1} · ${c3}.--.${c1} · ${c2}.===:${c1} · ${c2}:===:.
@@ -12,8 +12,8 @@ ${c2} .::.${c1} ·${c2}.-============-.${c1}· ${c2}.::.
':===:${c1} · ${c2}:===.${c1} · ${c3}'--'${c1} · ${c2}.===:${c1} · ${c2}:===:'
':==:${c1}· ${c2}':===:.${c1}' ·· '${c2}.:===:'${c1} ·${c2}:==:'
'::'${c1} · ${c2}'===-. .-==='${c1} · ${c2}'::'
${c2}/==\\${c1} · · · ${c2}:=== ===:${c1} · · · ${c2}/==\\
\\==/${c1} · · ·${c2}:===${c1} ·${c2}===:${c1}· · · ${c2}\\==/${c2}
${c2}/==\${c1} · · · ${c2}:=== ===:${c1} · · · ${c2}/==\
\==/${c1} · · ·${c2}:===${c1} ·${c2}===:${c1}· · · ${c2}\==/${c2}
.-. ${c1}· ${c2}:===${c1}· ${c2}===:${c1} ·${c2} ${c2}.-.
.===. .=== ===. .===.
.======== ========.
+10
View File
@@ -0,0 +1,10 @@
⣀⣠⣴⣶⣶⣿⣿⣿⣿⣶⣶⣦⣄⣀
⢀⣴⣾⣿⠿⠛⠉⠉ ⠉⠉⠛⠿⣿⣷⣦⡀
⣴⣿⡿⠋ ⠙⢿⣿⣦
⣾⣿⡟ ⣠⣴⣶⣿⣿⣶⣦⣄ ⢻⣿⣷
⣠⣤⣤⣤⣤⣤⣤⣼⣿⣿ ⣼⣿⡟⠉ ⠉⢻⣿⣧ ⣿⣿⣧⣤⣤⣤⣤⣤⣤⣄
⠙⠛⠛⠛⠛⠛⠛⢻⣿⣿ ⢻⣿⣧⡀ ⢀⣼⣿⡟ ⣿⣿⡟⠛⠛⠛⠛⠛⠛⠋
⢿⣿⣇ ⠙⠿⣿⣿⣿⣿⠿⠋ ⣸⣿⡿
⠈⢻⣿⣧⣀ ⣀⣾⣿⡟⠁
⠙⠻⣿⣷⣦⣄⣀ ⣀⣠⣴⣾⣿⠟⠋
⠉⠛⠿⢿⣿⣿⣿⣿⣿⣿⡿⠿⠛⠉
+22 -14
View File
@@ -224,7 +224,7 @@ static const FFlogo A[] = {
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_BLACK,
FF_COLOR_FG_GREEN,
FF_COLOR_FG_RED,
FF_COLOR_FG_YELLOW,
},
},
@@ -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,
@@ -2932,6 +2932,14 @@ static const FFlogo O[] = {
.colorKeys = FF_COLOR_FG_GREEN,
.colorTitle = FF_COLOR_FG_GREEN,
},
// openSuseMicroOS
{
.names = {"opensuse-microos", "opensuse_microos"},
.lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_MICROOS,
.colors = {
FF_COLOR_FG_GREEN,
},
},
// OpenSuseLeap
{
.names = {"opensuse_leap", "open_suse_leap", "opensuse-leap", "open-suse-leap", "suse_leap", "suse-leap", "opensuseleap"},
@@ -3299,6 +3307,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 +3577,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
{},
};
+2 -4
View File
@@ -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
View File
@@ -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)"
}));
+21 -3
View File
@@ -2,11 +2,12 @@
#include "common/jsonconfig.h"
#include "common/parsing.h"
#include "common/percent.h"
#include "common/time.h"
#include "detection/disk/disk.h"
#include "modules/disk/disk.h"
#include "util/stringUtils.h"
#define FF_DISK_NUM_FORMAT_ARGS 11
#define FF_DISK_NUM_FORMAT_ARGS 12
#pragma GCC diagnostic ignored "-Wsign-conversion"
static void printDisk(FFDiskOptions* options, const FFDisk* disk)
@@ -112,6 +113,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT);
bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT);
bool isReadOnly = !!(disk->type & FF_DISK_VOLUME_TYPE_READONLY_BIT);
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISK_NUM_FORMAT_ARGS, ((FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
@@ -124,6 +126,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk)
{FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem},
{FF_FORMAT_ARG_TYPE_STRBUF, &disk->name},
{FF_FORMAT_ARG_TYPE_BOOL, &isReadOnly},
{FF_FORMAT_ARG_TYPE_STRING, ffTimeToShortStr(disk->createTime)},
}));
}
}
@@ -422,8 +425,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);
@@ -440,6 +451,12 @@ void ffGenerateDiskJsonResult(FFDiskOptions* options, yyjson_mut_doc* doc, yyjso
yyjson_mut_arr_add_str(doc, typeArr, "Hidden");
if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT)
yyjson_mut_arr_add_str(doc, typeArr, "Read-only");
const char* pstr = ffTimeToFullStr(item->createTime);
if (*pstr)
yyjson_mut_obj_add_strcpy(doc, obj, "createTime", pstr);
else
yyjson_mut_obj_add_null(doc, obj, "createTime");
}
FF_LIST_FOR_EACH(FFDisk, item, disks)
@@ -465,6 +482,7 @@ void ffPrintDiskHelpFormat(void)
"Filesystem",
"Label / name",
"True if read-only",
"Create time in local timezone",
}));
}
+22 -1
View File
@@ -174,6 +174,15 @@ bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, co
return true;
}
if (ffStrEqualsIgnCase(subKey, "show-prefix-len"))
{
if (ffOptionParseBoolean(value))
options->showType |= FF_LOCALIP_TYPE_PREFIX_LEN_BIT;
else
options->showType &= ~FF_LOCALIP_TYPE_PREFIX_LEN_BIT;
return true;
}
if(ffStrEqualsIgnCase(subKey, "compact"))
{
if (ffOptionParseBoolean(value))
@@ -247,6 +256,15 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module)
continue;
}
if (ffStrEqualsIgnCase(key, "showPrefixLen"))
{
if (yyjson_get_bool(val))
options->showType |= FF_LOCALIP_TYPE_PREFIX_LEN_BIT;
else
options->showType &= ~FF_LOCALIP_TYPE_PREFIX_LEN_BIT;
continue;
}
if (ffStrEqualsIgnCase(key, "compact"))
{
if (yyjson_get_bool(val))
@@ -293,6 +311,9 @@ void ffGenerateLocalIpJsonConfig(FFLocalIpOptions* options, yyjson_mut_doc* doc,
if (options->showType & FF_LOCALIP_TYPE_LOOP_BIT)
yyjson_mut_obj_add_bool(doc, module, "showLoop", true);
if (options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT)
yyjson_mut_obj_add_bool(doc, module, "showPrefixLen", true);
if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT)
yyjson_mut_obj_add_bool(doc, module, "compact", true);
}
@@ -369,7 +390,7 @@ void ffInitLocalIpOptions(FFLocalIpOptions* options)
);
ffOptionInitModuleArg(&options->moduleArgs);
options->showType = FF_LOCALIP_TYPE_IPV4_BIT;
options->showType = FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_PREFIX_LEN_BIT;
ffStrbufInit(&options->namePrefix);
options->defaultRouteOnly =
#ifdef __ANDROID__
+6 -5
View File
@@ -7,12 +7,13 @@
typedef enum FFLocalIpType
{
FF_LOCALIP_TYPE_NONE,
FF_LOCALIP_TYPE_LOOP_BIT = 1 << 0,
FF_LOCALIP_TYPE_IPV4_BIT = 1 << 1,
FF_LOCALIP_TYPE_IPV6_BIT = 1 << 2,
FF_LOCALIP_TYPE_MAC_BIT = 1 << 3,
FF_LOCALIP_TYPE_LOOP_BIT = 1 << 0,
FF_LOCALIP_TYPE_IPV4_BIT = 1 << 1,
FF_LOCALIP_TYPE_IPV6_BIT = 1 << 2,
FF_LOCALIP_TYPE_MAC_BIT = 1 << 3,
FF_LOCALIP_TYPE_PREFIX_LEN_BIT = 1 << 4,
FF_LOCALIP_TYPE_COMPACT_BIT = 1 << 10,
FF_LOCALIP_TYPE_COMPACT_BIT = 1 << 10,
} FFLocalIpType;
typedef struct FFLocalIpOptions
+1
View File
@@ -26,6 +26,7 @@ typedef enum FFPackagesFlags
FF_PACKAGES_FLAG_SNAP_BIT = 1 << 16,
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
FF_PACKAGES_FLAG_AM_BIT = 1 << 19,
} FFPackagesFlags;
typedef struct FFPackagesOptions
+111 -43
View File
@@ -4,7 +4,7 @@
#include "modules/packages/packages.h"
#include "util/stringUtils.h"
#define FF_PACKAGES_NUM_FORMAT_ARGS 25
#define FF_PACKAGES_NUM_FORMAT_ARGS 26
void ffPrintPackages(FFPackagesOptions* options)
{
@@ -64,6 +64,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE(paludis)
FF_PRINT_PACKAGE(winget)
FF_PRINT_PACKAGE(opkg)
FF_PRINT_PACKAGE(am)
putchar('\n');
}
@@ -95,6 +96,7 @@ void ffPrintPackages(FFPackagesOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &counts.paludis},
{FF_FORMAT_ARG_TYPE_UINT, &counts.winget},
{FF_FORMAT_ARG_TYPE_UINT, &counts.opkg},
{FF_FORMAT_ARG_TYPE_UINT, &counts.am},
}));
}
@@ -121,32 +123,63 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
*end = '\0';
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(start, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
switch (toupper(start[0]))
{
case 'A': if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(AM)
break;
case 'B': if (false);
FF_TEST_PACKAGE_NAME(BREW)
break;
case 'C': if (false);
FF_TEST_PACKAGE_NAME(CHOCO)
break;
case 'D': if (false);
FF_TEST_PACKAGE_NAME(DPKG)
break;
case 'E': if (false);
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
break;
case 'F': if (false);
FF_TEST_PACKAGE_NAME(FLATPAK)
break;
case 'M': if (false);
FF_TEST_PACKAGE_NAME(MACPORTS)
break;
case 'N': if (false);
FF_TEST_PACKAGE_NAME(NIX)
break;
case 'O': if (false);
FF_TEST_PACKAGE_NAME(OPKG)
break;
case 'P': if (false);
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(PALUDIS)
break;
case 'R': if (false);
FF_TEST_PACKAGE_NAME(RPM)
break;
case 'S': if (false);
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
break;
case 'W': if (false);
FF_TEST_PACKAGE_NAME(WINGET)
break;
case 'X': if (false);
FF_TEST_PACKAGE_NAME(XBPS)
break;
}
#undef FF_TEST_PACKAGE_NAME
if (end)
{
start = end + 1;
end = strchr(end, ':');
end = strchr(start, ':');
}
else
break;
@@ -190,28 +223,60 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
const char* flag = yyjson_get_str(flagObj);
#define FF_TEST_PACKAGE_NAME(name) else if (ffStrEqualsIgnCase(flag, #name)) { options->disabled |= FF_PACKAGES_FLAG_ ## name ## _BIT; }
if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(BREW)
FF_TEST_PACKAGE_NAME(CHOCO)
FF_TEST_PACKAGE_NAME(DPKG)
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
FF_TEST_PACKAGE_NAME(FLATPAK)
FF_TEST_PACKAGE_NAME(NIX)
FF_TEST_PACKAGE_NAME(OPKG)
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PALUDIS)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(MACPORTS)
FF_TEST_PACKAGE_NAME(RPM)
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
switch (toupper(flag[0]))
{
case 'A': if (false);
FF_TEST_PACKAGE_NAME(APK)
FF_TEST_PACKAGE_NAME(AM)
break;
case 'B': if (false);
FF_TEST_PACKAGE_NAME(BREW)
break;
case 'C': if (false);
FF_TEST_PACKAGE_NAME(CHOCO)
break;
case 'D': if (false);
FF_TEST_PACKAGE_NAME(DPKG)
break;
case 'E': if (false);
FF_TEST_PACKAGE_NAME(EMERGE)
FF_TEST_PACKAGE_NAME(EOPKG)
break;
case 'F': if (false);
FF_TEST_PACKAGE_NAME(FLATPAK)
break;
case 'M': if (false);
FF_TEST_PACKAGE_NAME(MACPORTS)
break;
case 'N': if (false);
FF_TEST_PACKAGE_NAME(NIX)
break;
case 'O': if (false);
FF_TEST_PACKAGE_NAME(OPKG)
break;
case 'P': if (false);
FF_TEST_PACKAGE_NAME(PACMAN)
FF_TEST_PACKAGE_NAME(PKG)
FF_TEST_PACKAGE_NAME(PKGTOOL)
FF_TEST_PACKAGE_NAME(PALUDIS)
break;
case 'R': if (false);
FF_TEST_PACKAGE_NAME(RPM)
break;
case 'S': if (false);
FF_TEST_PACKAGE_NAME(SCOOP)
FF_TEST_PACKAGE_NAME(SNAP)
break;
case 'W': if (false);
FF_TEST_PACKAGE_NAME(WINGET)
break;
case 'X': if (false);
FF_TEST_PACKAGE_NAME(XBPS)
break;
}
#undef FF_TEST_PACKAGE_NAME
}
continue;
}
}
@@ -250,6 +315,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
FF_TEST_PACKAGE_NAME(SNAP)
FF_TEST_PACKAGE_NAME(WINGET)
FF_TEST_PACKAGE_NAME(XBPS)
FF_TEST_PACKAGE_NAME(AM)
#undef FF_TEST_PACKAGE_NAME
}
}
@@ -295,6 +361,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
FF_APPEND_PACKAGE_COUNT(winget)
FF_APPEND_PACKAGE_COUNT(xbps)
FF_APPEND_PACKAGE_COUNT(opkg)
FF_APPEND_PACKAGE_COUNT(am)
yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch);
}
@@ -325,7 +392,8 @@ void ffPrintPackagesHelpFormat(void)
"Number of pkgtool packages",
"Number of paludis packages",
"Number of winget packages",
"Number of opkg packages"
"Number of opkg packages",
"Number of am packages",
}));
}
+5 -6
View File
@@ -1,10 +1,11 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/time.h"
#include "detection/uptime/uptime.h"
#include "modules/uptime/uptime.h"
#include "util/stringUtils.h"
#define FF_UPTIME_NUM_FORMAT_ARGS 7
#define FF_UPTIME_NUM_FORMAT_ARGS 6
void ffPrintUptime(FFUptimeOptions* options)
{
@@ -83,8 +84,7 @@ void ffPrintUptime(FFUptimeOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &minutes},
{FF_FORMAT_ARG_TYPE_UINT, &seconds},
{FF_FORMAT_ARG_TYPE_UINT, &milliseconds},
{FF_FORMAT_ARG_TYPE_UINT64, &result.uptime},
{FF_FORMAT_ARG_TYPE_UINT64, &result.bootTime},
{FF_FORMAT_ARG_TYPE_STRING, ffTimeToShortStr(result.uptime)},
}));
}
}
@@ -137,7 +137,7 @@ void ffGenerateUptimeJsonResult(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_uint(doc, obj, "uptime", result.uptime);
yyjson_mut_obj_add_uint(doc, obj, "bootTime", result.bootTime);
yyjson_mut_obj_add_strcpy(doc, obj, "bootTime", ffTimeToFullStr(result.bootTime));
}
void ffPrintUptimeHelpFormat(void)
@@ -148,8 +148,7 @@ void ffPrintUptimeHelpFormat(void)
"Minutes",
"Seconds",
"Milliseconds",
"Uptime in unix timestamp (ms)",
"Boot time in unix timestamp (ms)",
"Boot time in local timezone",
}));
}
+9 -11
View File
@@ -1,11 +1,10 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "common/time.h"
#include "detection/users/users.h"
#include "modules/users/users.h"
#include "util/stringUtils.h"
#include <time.h>
#pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format
#define FF_USERS_NUM_FORMAT_ARGS 5
@@ -57,12 +56,7 @@ void ffPrintUsers(FFUsersOptions* options)
ffStrbufAppendF(&result, "@%s", user->hostName.chars);
if(user->loginTime)
{
char buf[64];
time_t time = (time_t) (user->loginTime / 1000);
strftime(buf, sizeof(buf), "%FT%T%z", localtime(&time));
ffStrbufAppendF(&result, " - login time %s", buf);
}
ffStrbufAppendF(&result, " - login time %s", ffTimeToShortStr(user->loginTime));
ffStrbufPutTo(&result, stdout);
}
@@ -79,7 +73,7 @@ void ffPrintUsers(FFUsersOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &user->hostName},
{FF_FORMAT_ARG_TYPE_STRBUF, &user->sessionName},
{FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp},
{FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime},
{FF_FORMAT_ARG_TYPE_STRING, ffTimeToShortStr(user->loginTime)},
}));
}
}
@@ -163,7 +157,11 @@ void ffGenerateUsersJsonResult(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_m
yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &user->hostName);
yyjson_mut_obj_add_strbuf(doc, obj, "sessionName", &user->sessionName);
yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp);
yyjson_mut_obj_add_uint(doc, obj, "loginTime", user->loginTime);
const char* pstr = ffTimeToFullStr(user->loginTime);
if (*pstr)
yyjson_mut_obj_add_strcpy(doc, obj, "loginTime", pstr);
else
yyjson_mut_obj_add_null(doc, obj, "loginTime");
}
exit:
@@ -183,7 +181,7 @@ void ffPrintUsersHelpFormat(void)
"Host name",
"Session name",
"Client IP",
"Login Time"
"Login Time in local timezone"
}));
}
+3 -2
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -52,6 +52,7 @@ void ffPlatformDestroy(FFPlatform* platform)
FF_LIST_FOR_EACH(FFstrbuf, dir, platform->dataDirs)
ffStrbufDestroy(dir);
ffListDestroy(&platform->dataDirs);
ffStrbufDestroy(&platform->exePath);
ffStrbufDestroy(&platform->userName);
ffStrbufDestroy(&platform->hostName);
+14
View File
@@ -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;
}
+1
View File
@@ -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
View File
@@ -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