mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
Compare commits
249 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 06ecc9c480 | |||
| 50288d91e4 | |||
| 499b4ff445 | |||
| dd0021cd5e | |||
| f5b70dd8b7 | |||
| 8f8ca11203 | |||
| 121d399641 | |||
| 26ae4eb21b | |||
| 52a81dbdc4 | |||
| f924a8bf06 | |||
| c7363f904a | |||
| 53ffe8459f | |||
| 1b702e123e | |||
| 14dccce393 | |||
| d040cc810f | |||
| 224bea2559 | |||
| 777d3e599d | |||
| 7c47bc2656 | |||
| e4d31381d8 | |||
| abf8d75454 | |||
| 2ce152beaf | |||
| 766ed07999 | |||
| ddc2131343 | |||
| b64d8a013d | |||
| e6db59fdde | |||
| 7ea0bbfb21 | |||
| ab041e0ad2 | |||
| 207f742624 | |||
| 68f0b11b6f | |||
| b86c0880b9 | |||
| 75f4a3d92d | |||
| 70fa1341a8 | |||
| 0a55314d37 | |||
| 2198e6123e | |||
| dd37ee0e50 | |||
| 7006ae0420 | |||
| 86458ab32a | |||
| 67ca907e38 | |||
| e15d06bbad | |||
| eb53797174 | |||
| c8c32a78b0 | |||
| 1c032624ac | |||
| 5087ea77b4 | |||
| b6b42e69c3 | |||
| 000a688bb6 | |||
| 3e25b213b1 | |||
| a69cf456ea | |||
| 072b76cb12 | |||
| ca8f54d331 | |||
| 6423feaa94 | |||
| 92ada88ea7 | |||
| 1789ef85d7 | |||
| 42509f115c | |||
| 340a58bda1 | |||
| 08dfd1321c | |||
| 45d324a8c6 | |||
| afa986efd4 | |||
| bc6e8c7813 | |||
| 627fee23d1 | |||
| 27b474f205 | |||
| 418c7eecc7 | |||
| 350250d640 | |||
| 3cc21905af | |||
| c698eb8eb5 | |||
| 463c24beb8 | |||
| a5d1b96ecc | |||
| 63106ebdc1 | |||
| fd36783adb | |||
| 3b5186da53 | |||
| 0140a46090 | |||
| 9c38e1255f | |||
| 663f9d69ff | |||
| d12e5ab801 | |||
| 1d770d85f6 | |||
| 5b00afe45d | |||
| 5b276567ac | |||
| 56566916e3 | |||
| 2c0b4ca3a2 | |||
| 54ffdd32dc | |||
| 64f24bdee9 | |||
| 4706f97bf0 | |||
| 0bdb198d52 | |||
| fc7710821e | |||
| e22a9990ec | |||
| fc7f3a1650 | |||
| 915af9546d | |||
| 54a68640ef | |||
| ec1af7c92b | |||
| a1e20270ad | |||
| 4996986ce6 | |||
| e6de2d4fd9 | |||
| 5347e74a1b | |||
| 0ea5639a22 | |||
| aa3a916d5a | |||
| 6e64b758bf | |||
| 49ef7fc51f | |||
| 0e9a5acdbd | |||
| 4f6e80e940 | |||
| df87cdfa6e | |||
| dee4b36a46 | |||
| d04a26337a | |||
| 2afe8d11d1 | |||
| f31d3b8b21 | |||
| 8a20af9917 | |||
| fc5c2f6213 | |||
| 6c314e148a | |||
| a86d0017a9 | |||
| 4038ed2656 | |||
| 0f4bb47c2f | |||
| 19f7c67ede | |||
| ff7e81ed81 | |||
| 681a102a2b | |||
| ba27f4f2ef | |||
| cbe33a4860 | |||
| 5847e3f269 | |||
| b248dfa01c | |||
| 357aa77e21 | |||
| a44bde6f94 | |||
| 5825bce57d | |||
| 996cdd3155 | |||
| 61cdfcabf8 | |||
| 359a77097c | |||
| 1323d007d3 | |||
| d2215f26ac | |||
| 958e7dbd8f | |||
| 5b10cde59f | |||
| e8f2b9a1c7 | |||
| 0686d1db4a | |||
| 7c284f9ee8 | |||
| dc04273bd7 | |||
| d698be6239 | |||
| e44df27c96 | |||
| b365d4cca1 | |||
| 19d3c948ad | |||
| 4a581039d5 | |||
| 79849fb2b5 | |||
| c116a5abdf | |||
| 8f082730a8 | |||
| b81c4a04db | |||
| e26a05e3ac | |||
| f08a1fb0b4 | |||
| 2a82009ffe | |||
| e851f3a7ed | |||
| 3a865df09e | |||
| bae80e2932 | |||
| 4445e1e78d | |||
| f0e3d3d8e1 | |||
| a313fd1572 | |||
| 927d44d919 | |||
| 3b9a91e8af | |||
| 70b4582bb6 | |||
| 461552b8d0 | |||
| 0f3db37199 | |||
| 67f16b269a | |||
| 25671fa4b4 | |||
| 4eaa04d4a4 | |||
| 7592885b9f | |||
| 508a3fde36 | |||
| f0273224e0 | |||
| 31e833c02e | |||
| a20d915412 | |||
| d3453de73c | |||
| 79a11c4728 | |||
| 24591417ce | |||
| de6d066fc9 | |||
| 6362c896f8 | |||
| 0418e9ca5e | |||
| ba0eeab18c | |||
| 5ef630cbc8 | |||
| 1699d14984 | |||
| 501746a270 | |||
| e6bd1c340f | |||
| 49fc95689d | |||
| 3d84ad19be | |||
| 57aa0cf499 | |||
| 6496dcd7d0 | |||
| 1c066bc69a | |||
| 2f1e37bb7c | |||
| fd3c87abe7 | |||
| af075b8ef8 | |||
| 71d461266e | |||
| 163781557f | |||
| 16e6decebf | |||
| e10c9cc164 | |||
| 7ef994d0cf | |||
| 019c9f0f77 | |||
| 5fec607ebe | |||
| b065b3da51 | |||
| 1337525eb5 | |||
| 30ea52938e | |||
| d43ed33661 | |||
| 03aab33507 | |||
| 420d1cf804 | |||
| 5d901da81b | |||
| 5c783e64c0 | |||
| 2efa5a1869 | |||
| 5bfabe7a52 | |||
| c9c9a58f59 | |||
| 546908fc29 | |||
| 0a17da2da0 | |||
| bc6fd025cb | |||
| 9e49451340 | |||
| 4d185e64ac | |||
| 1fa9a61b3f | |||
| 234552fbf2 | |||
| 8423efb686 | |||
| cd8c15d01e | |||
| 3163cfb1b6 | |||
| 7ae007a1d0 | |||
| 0b52d75415 | |||
| 3a7f4f5848 | |||
| 072f67988f | |||
| c640ddbff7 | |||
| 981ae6bdd1 | |||
| 977e3f317e | |||
| e2ee24598c | |||
| 1be90084ab | |||
| 6ded0f9bb0 | |||
| d60b25e424 | |||
| 874f3918b7 | |||
| 61690a1804 | |||
| 1e43e35857 | |||
| 8c86003220 | |||
| 18c3cd2e66 | |||
| b21f35e914 | |||
| 32e3ed1fda | |||
| 6f87026b0c | |||
| e23edae917 | |||
| bdc867031a | |||
| e96b0f7a73 | |||
| 37fe446a58 | |||
| f03a0bc202 | |||
| bcbc5a4bff | |||
| 0b1e2faba1 | |||
| 4708a5e59c | |||
| 7925469e2f | |||
| 53116d65f1 | |||
| 01917b781b | |||
| d01fc56ea2 | |||
| 9c870a57f0 | |||
| 7e557a06b3 | |||
| fa63038862 | |||
| 8439204cef | |||
| 710df0b87b | |||
| 302f0fc85f | |||
| 241aa3a02c | |||
| a17f3dc3f8 | |||
| 34c0bf58cb | |||
| b64b93fc4a |
@@ -16,6 +16,15 @@ body:
|
||||
options:
|
||||
- label: I have checked the FAQ but the issue is not covered
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Not a known issue
|
||||
description: Please check if the issue is already known and being worked on.
|
||||
options:
|
||||
- label: I have checked the existing issues but the issue is not covered
|
||||
required: true
|
||||
- label: My issue is not about crashing on Fedora and KDE 6.6
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### General description of the bug"
|
||||
|
||||
@@ -6,35 +6,42 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
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.
|
||||
Tip: You can display a logo in fastfetch without adding it to fastfetch's official repo.
|
||||
For highly customized, personal logos, we recommend keeping them locally.
|
||||
Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: OS
|
||||
description: Paste content of `/etc/os-release` and `/etc/lsb-release` here. If none of these files exist, describe a way to identify the distro
|
||||
description: Paste the contents of `/etc/os-release` and `/etc/lsb-release` here. If neither file exists, describe how to identify the distro.
|
||||
placeholder: cat /etc/os-release
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Distro Website
|
||||
description: To help prevent spam and verify the request, a distro website is required, and a downloadable ISO must be available on that site.
|
||||
placeholder: https://example.com
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: ASCII Art
|
||||
description: An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
|
||||
description: The ASCII logo should not take up too much space (smaller than 50x20 characters, W x H). Please also include the color codes if they are not available in `os-release`.
|
||||
placeholder: Paste ASCII art here
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Original Image
|
||||
description: If the ASCII art is based on an image, please provide a link to the original image
|
||||
placeholder: Image URL or distro website URL
|
||||
label: Original Image URL
|
||||
description: If the ASCII art is based on an image, please provide a link to the original image file.
|
||||
placeholder: Image URL from the distro website mentioned above
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: The ASCII art is smaller than 50x20 characters (width x height)
|
||||
- label: The ASCII art is smaller than 50x20 characters (W x H).
|
||||
required: true
|
||||
- label: The ASCII art contains color codes, or the color codes are available in `os-release`
|
||||
- label: The ASCII art includes color codes, or the color codes are available in `os-release`.
|
||||
required: true
|
||||
- label: The ASCII art contains no internal paddings (spaces at the start and the end of lines)
|
||||
- label: The ASCII art has no internal padding (spaces at the start and/or end of lines).
|
||||
required: true
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
## Summary
|
||||
|
||||
<!-- Briefly describe what this PR does. -->
|
||||
|
||||
## Related issue (required for new logos for new distros)
|
||||
|
||||
<!--
|
||||
If this PR adds a new logo, it MUST be linked to an existing "Logo Request" issue and has the requests fulfilled.
|
||||
|
||||
Use one of the following formats so GitHub links it properly:
|
||||
- Closes #1234
|
||||
- Fixes #1234
|
||||
- Resolves #1234
|
||||
|
||||
PRs that add logos without an associated Logo Request issue will not be accepted.
|
||||
-->
|
||||
|
||||
Closes #
|
||||
|
||||
## Changes
|
||||
|
||||
-
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have tested my changes locally.
|
||||
+110
-55
@@ -13,7 +13,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
@@ -93,16 +93,16 @@ jobs:
|
||||
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y gcc-13 g++-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build
|
||||
run: sudo apt-get update && sudo apt-get install -y gcc-13 g++-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
@@ -164,7 +164,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-linux-i686
|
||||
path: ./fastfetch-*.*
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
@@ -257,7 +257,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
@@ -270,7 +270,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
@@ -293,7 +293,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
@@ -312,7 +312,7 @@ jobs:
|
||||
- arch: s390x
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
@@ -336,7 +336,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
@@ -345,7 +345,7 @@ jobs:
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
@@ -374,7 +374,7 @@ jobs:
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -394,7 +394,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
@@ -428,42 +428,80 @@ jobs:
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-macos-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
omnios-amd64:
|
||||
runs-on: ubuntu-latest
|
||||
name: SunOS-amd64
|
||||
name: OmniOS-amd64
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/omnios-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update --accept
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
|
||||
cmake --build . --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
cpack
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-sunos-amd64
|
||||
name: fastfetch-omnios-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
solaris-amd64:
|
||||
runs-on: ubuntu-latest
|
||||
name: Solaris-amd64
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/solaris-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
release: "11.4-gcc-14"
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja dconf mesa
|
||||
|
||||
run: |
|
||||
export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
|
||||
cmake --build . --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-solaris-amd64")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-solaris-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
freebsd-amd64:
|
||||
@@ -474,7 +512,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
@@ -483,7 +521,8 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.3'
|
||||
version: '15.0'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
@@ -498,7 +537,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -511,7 +550,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
@@ -520,12 +559,13 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.7'
|
||||
version: '7.8'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -u
|
||||
sudo pkg_add -r llvm-19.1.7p3 cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
|
||||
CC=clang-19 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
sudo pkg_add -r llvm-21.1.2p0 cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
|
||||
CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
@@ -535,7 +575,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-openbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -548,7 +588,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
@@ -558,6 +598,7 @@ jobs:
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.1'
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
|
||||
@@ -571,7 +612,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -584,12 +625,13 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
usesh: yes
|
||||
envs: 'CMAKE_BUILD_TYPE'
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
@@ -606,7 +648,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -619,7 +661,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
@@ -629,6 +671,7 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
environment_variables: 'CMAKE_BUILD_TYPE'
|
||||
run: |
|
||||
uname -a
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
|
||||
@@ -641,13 +684,13 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-hosts:
|
||||
name: Windows-${{ matrix.arch }}
|
||||
name: Windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -660,17 +703,28 @@ jobs:
|
||||
msystem: CLANG64
|
||||
msystem-lower: clang64
|
||||
msys-arch: x86_64
|
||||
win7-compat-flag: OFF
|
||||
win7-compat-postfix: ""
|
||||
- arch: amd64
|
||||
runs-on: windows-latest
|
||||
msystem: CLANG64
|
||||
msystem-lower: clang64
|
||||
msys-arch: x86_64
|
||||
win7-compat-flag: ON
|
||||
win7-compat-postfix: "-win7"
|
||||
- arch: aarch64
|
||||
runs-on: windows-11-arm
|
||||
msystem: CLANGARM64
|
||||
msystem-lower: clangarm64
|
||||
msys-arch: aarch64
|
||||
win7-compat-flag: OFF
|
||||
win7-compat-postfix: ""
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -683,7 +737,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_WIN7_COMPAT=${{ matrix.win7-compat-flag }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
@@ -712,9 +766,9 @@ jobs:
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
id: upload-unsigned-artifact
|
||||
name: upload artifacts for signing
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-windows-${{ matrix.arch }}
|
||||
name: fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}
|
||||
path: |
|
||||
*.dll
|
||||
fastfetch.exe
|
||||
@@ -733,16 +787,16 @@ jobs:
|
||||
output-artifact-directory: '.'
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload true artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: fastfetch-windows-${{ matrix.arch }}
|
||||
path: ./fastfetch-windows-${{ matrix.arch }}.*
|
||||
name: fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}
|
||||
path: ./fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}.*
|
||||
overwrite: true
|
||||
|
||||
release:
|
||||
@@ -761,7 +815,8 @@ jobs:
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- solaris-amd64
|
||||
- omnios-amd64
|
||||
- haiku-amd64
|
||||
- windows-hosts
|
||||
permissions:
|
||||
@@ -775,7 +830,7 @@ jobs:
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v8
|
||||
|
||||
- name: create release
|
||||
if: needs.linux-hosts.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
|
||||
+129
@@ -1,3 +1,132 @@
|
||||
# 2.60.0
|
||||
|
||||
Changes:
|
||||
* The CMake option `ENABLE_WIN7_COMPAT:BOOLEAN` now defaults to `OFF` and will be removed in v2.61.0, effectively dropping support for Windows 7 in the next release.
|
||||
* This follows the Windows 7 deprecation notice introduced in v2.57.0.
|
||||
* `wm.detectPlugin` now defaults to `true` (WM)
|
||||
|
||||
Features:
|
||||
* Adds `{cwd}` for custom title formatting, which displays the current working directory (Title)
|
||||
* Adds support for detecting the Zed version (#2200, Editor)
|
||||
* Adds support for detecting `moss` packages (Packages, Linux)
|
||||
* Adds support for detecting komorebi, FancyWM, and GlazeWM (WM, Windows)
|
||||
* Adds support for WM plugin version detection on macOS (WM, macOS)
|
||||
* Adds support for retrieving the executable path on OpenBSD (#2195, OpenBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes a potential segmentation fault caused by dereferencing a negative index (#2198)
|
||||
* Fixes `tempSensor` parsing so that it accepts only string values (#2202, CPU)
|
||||
* Fixes an issue that unexpectedly caused fewer devices to be reported (Keyboard, Linux)
|
||||
* Improves WM detection on LXQt by querying WM settings only when no WM has already been detected (#2199, WM, Linux)
|
||||
* Fixes memory leaks in DBus connection handling and in the OpenGL EGL context lifecycle
|
||||
* Fixes niri version detection on Fedora (WM, Linux)
|
||||
* Includes various internal cleanups and optimizations
|
||||
|
||||
Logos:
|
||||
* Adds `RengeOS` (#2170)
|
||||
* Adds `Emmabuntüs` (#2207)
|
||||
* Updates Artix Linux (#2157)
|
||||
* Updates Linux Mint (#2186)
|
||||
* Renames `Refracted Devuan` to `Refracta`
|
||||
* Renames `ExodiaPredator` to `ExodiaOS`
|
||||
|
||||
# 2.59.0
|
||||
|
||||
Changes:
|
||||
* Fastfetch no longer relies on the unreliable environment variables `$USER` or `%USERPROFILE%` to determine the current username (Title)
|
||||
* People who set `$USER` to customize the Fastfetch title should use `{ "type": "title", "format": "your-custom-user-name" }` to achieve the same result.
|
||||
* Fastfetch no longer tries to probe inaccessible remote disk drives on Windows (Disk, Windows)
|
||||
* People who have remote drives may use `{ "type": "disk", "hideFolders": "X:\\" }` to ignore problematic ones.
|
||||
* This change removes some ugly hacks from the codebase and matches the behavior on `*nix`.
|
||||
|
||||
Features:
|
||||
* Adds Oracle Solaris support (#2176, SunOS)
|
||||
* Adds UID / SID detection (Title)
|
||||
* In custom format: `{user-id}`
|
||||
* Switches to native GPU detection on GNU/Hurd and removes the `libpciaccess` dependency (GPU, Hurd)
|
||||
* Improves memory size detection on macOS (Memory, macOS)
|
||||
* Avoids relying on `hw.memsize_usable` by default, which may not be available on older macOS versions
|
||||
* Improves Windows disk detection accuracy and performance (Disk, Windows)
|
||||
* Adds more ARM CPU parts and removes duplicated cases (CPU, ARM)
|
||||
|
||||
Logos:
|
||||
* Adds 6-color support to the NixOS logo (including the small variant) (#2180)
|
||||
|
||||
# 2.58.0
|
||||
|
||||
An early release to fix compatibility issues with KDE Plasma 6.6.
|
||||
|
||||
Breaking changes:
|
||||
* The `de.slowVersionDetection` option has been removed. Slow version detection is now always enabled, as required on non-FHS-compliant distros (e.g., NixOS). (#2149, DE, Linux)
|
||||
|
||||
Features:
|
||||
* Adds the `--structure-disabled <modules...>` command-line flag to temporarily disable module structure printing.
|
||||
* For example: `fastfetch --structure-disabled colors` removes the color blocks from the default output.
|
||||
* Supports chassis type detection on Linux ARM devices when reported via the device tree (Chassis, Linux)
|
||||
* Supports Bedrock Linux version detection (#2155, OS, Linux)
|
||||
* Honors the `DBPath` and `RootDir` settings in `pacman.conf` when detecting Pacman packages (#2154, Packages, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes a crash issue on KDE Plasma 6.6 (Display, Linux)
|
||||
* Fixes the Command module not working with `--dynamic-interval` (#2152, Command)
|
||||
* Fixes Quartz Compositor version detection. It now correctly reports the version of `WindowServer` (`SkyLight`) instead of `WindowManager`. (WM, macOS)
|
||||
|
||||
Logos:
|
||||
* Adds Kiss2
|
||||
|
||||
# 2.57.1
|
||||
|
||||
Features:
|
||||
* Tiny performance improvements (Windows)
|
||||
* Improves the reliability of hostname retrieval (Title, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Fixes potential compilation issues on Linux (#2142, Linux)
|
||||
* Fixes compilation errors on macOS when building with older SDKs (#2140, macOS)
|
||||
* Fixes compilation issues when building with `-DENABLE_SYSTEM_YYJSON=ON` (#2143)
|
||||
|
||||
Logos:
|
||||
* Updates PrismLinux and adds a small variant
|
||||
|
||||
# 2.57.0
|
||||
|
||||
Deprecation notice:
|
||||
* Support for Windows 7 (and 8.x) is deprecated and will be removed in a future release. Extended support for Windows 7 (and 8.1) ended on January 10, 2023. These versions do not officially support ANSI escape codes (running fastfetch on them requires a third-party terminal such as ConEmu). In addition, Windows 7 lacks some APIs used by fastfetch. Fastfetch currently loads these APIs dynamically at runtime to maintain compatibility, but this adds complexity to the codebase and increases the maintenance burden.
|
||||
* A CMake flag `ENABLE_WIN7_COMPAT:BOOLEAN` has been introduced (defaults to `ON` for now). If set to `OFF`, Windows 7 compatibility code is excluded, and the resulting binaries will support only Windows 10 (version 1607 and later) and Windows 11.
|
||||
* The main prebuilt Windows binaries on the Release page (`fastfetch-windows-amd64.*`) are built with `ENABLE_WIN7_COMPAT=OFF`. These are the binaries used by `scoop` and `winget`. Users who need Windows 7 (or 8.x) support can download the `-win7` variant instead.
|
||||
* ~~The `ENABLE_WIN7_COMPAT` CMake option and the `-win7` variant binaries are planned to be removed in 2.60.0~~.
|
||||
|
||||
Features:
|
||||
* Supports COSMIC DE version detection (DE, Linux)
|
||||
* Supports niri version detection (#2121, WM, Linux)
|
||||
* Supports cosmic-term version and terminal font detection (Terminal / TerminalFont, Linux)
|
||||
* Supports urxvt font detection (TerminalFont, Linux) (#2105)
|
||||
* Improves xterm font detection by checking `xterm.vt100.faceName` (TerminalFont, Linux)
|
||||
* Supports Secure Boot detection (Bootmgr, macOS)
|
||||
* Supports DPI scale factor detection on Windows 7 (Display, Windows)
|
||||
* Supports xterm 256-color codes in color configuration
|
||||
* In `display.color`: "`@<color-index>`" (e.g., "`@34`" for color index `34`)
|
||||
* In `*.format` strings: "`#@<color-index>`" (e.g., "`#@34`" for color index `34`)
|
||||
* Improves uptime accuracy on Windows 10+ (Uptime, Windows)
|
||||
* Adds a new module `Logo` to query built-in logo raw data in JSON output (Logo)
|
||||
* Usage: `fastfetch -s logo -l <logo-name> -j # Supported in JSON format only`
|
||||
* Supports shell version detection even if the binary has been deleted (#2136, Shell, Linux)
|
||||
* Overall code refinements and optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Skips local / loopback routes when detecting network interfaces (LocalIP, Linux) (#2127)
|
||||
* Fixes CPU speed detection on s390x (CPU, Linux) (#2129)
|
||||
* Fixes GPU detection error handling and supports case-insensitive PCI ID parsing (GPU, Windows)
|
||||
* Fixes some networking issues and memory leaks (Networking)
|
||||
* Fixes `exePath` reporting relative paths on macOS (Shell, macOS)
|
||||
|
||||
Logos:
|
||||
* Adds openSUSE Tumbleweed braille logo
|
||||
* Adds Xinux
|
||||
* Renames HydraPWK to NetHydra
|
||||
* Fixes colors of deepin and UOS
|
||||
* Fixes colors of macOS and variants
|
||||
|
||||
# 2.56.1
|
||||
|
||||
Features:
|
||||
|
||||
+196
-135
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.56.1
|
||||
VERSION 2.60.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -92,7 +92,6 @@ cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF)
|
||||
|
||||
option(ENABLE_ZLIB "Enable zlib" ON)
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
@@ -107,6 +106,12 @@ option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`"
|
||||
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
|
||||
option(ENABLE_WORDEXP "Enable using of wordexp(3) if available, instead of glob(3)" ON)
|
||||
option(ENABLE_LIBZFS "Enable libzfs" ON)
|
||||
if(WIN32 AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||
option(ENABLE_WIN7_COMPAT "Enable Windows 7 compatibility" OFF)
|
||||
endif()
|
||||
if(APPLE)
|
||||
option(ENABLE_APPLE_MEMSIZE_USABLE "Use usable memory size as total memory size in Memory module, to match other systems" OFF)
|
||||
endif()
|
||||
|
||||
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
|
||||
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
|
||||
@@ -161,7 +166,13 @@ if(WIN32 OR Haiku OR ENABLE_DIRECTX_HEADERS)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id")
|
||||
|
||||
if(ENABLE_WIN7_COMPAT)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,console,--major-os-version,6,--minor-os-version,1")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,console,--major-os-version,10,--minor-os-version,0")
|
||||
endif()
|
||||
elseif(APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
|
||||
endif()
|
||||
@@ -342,7 +353,7 @@ fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
|
||||
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
|
||||
if(APPLE)
|
||||
configure_file(src/util/apple/Info.plist.in Info.plist @ONLY)
|
||||
configure_file(src/common/apple/Info.plist.in Info.plist @ONLY)
|
||||
endif()
|
||||
|
||||
####################
|
||||
@@ -364,26 +375,32 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
|
||||
#######################
|
||||
|
||||
set(LIBFASTFETCH_SRC
|
||||
src/common/commandoption.c
|
||||
src/common/duration.c
|
||||
src/common/font.c
|
||||
src/common/format.c
|
||||
src/common/frequency.c
|
||||
src/common/init.c
|
||||
src/common/jsonconfig.c
|
||||
src/common/library.c
|
||||
src/common/modules.c
|
||||
src/common/netif/netif.c
|
||||
src/common/networking/networking_common.c
|
||||
src/common/option.c
|
||||
src/common/parsing.c
|
||||
src/common/percent.c
|
||||
src/common/printing.c
|
||||
src/common/properties.c
|
||||
src/common/settings.c
|
||||
src/common/size.c
|
||||
src/common/temps.c
|
||||
src/common/time.c
|
||||
src/common/impl/commandoption.c
|
||||
src/common/impl/duration.c
|
||||
src/common/impl/font.c
|
||||
src/common/impl/format.c
|
||||
src/common/impl/frequency.c
|
||||
src/common/impl/init.c
|
||||
src/common/impl/jsonconfig.c
|
||||
src/common/impl/library.c
|
||||
src/common/impl/netif.c
|
||||
src/common/impl/networking_common.c
|
||||
src/common/impl/option.c
|
||||
src/common/impl/parsing.c
|
||||
src/common/impl/percent.c
|
||||
src/common/impl/printing.c
|
||||
src/common/impl/properties.c
|
||||
src/common/impl/settings.c
|
||||
src/common/impl/size.c
|
||||
src/common/impl/temps.c
|
||||
src/common/impl/time.c
|
||||
src/common/impl/edidHelper.c
|
||||
src/common/impl/base64.c
|
||||
src/common/impl/FFlist.c
|
||||
src/common/impl/FFstrbuf.c
|
||||
src/common/impl/path.c
|
||||
src/common/impl/FFPlatform.c
|
||||
src/common/impl/smbiosHelper.c
|
||||
src/detection/bluetoothradio/bluetoothradio.c
|
||||
src/detection/bootmgr/bootmgr.c
|
||||
src/detection/chassis/chassis.c
|
||||
@@ -452,6 +469,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/loadavg/loadavg.c
|
||||
src/modules/locale/locale.c
|
||||
src/modules/localip/localip.c
|
||||
src/modules/logo/logo.c
|
||||
src/modules/memory/memory.c
|
||||
src/modules/monitor/monitor.c
|
||||
src/modules/netio/netio.c
|
||||
@@ -489,26 +507,22 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/wm/wm.c
|
||||
src/modules/wmtheme/wmtheme.c
|
||||
src/modules/zpool/zpool.c
|
||||
src/modules/modules.c
|
||||
src/options/display.c
|
||||
src/options/logo.c
|
||||
src/options/general.c
|
||||
src/util/edidHelper.c
|
||||
src/util/base64.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/kmod.c
|
||||
src/util/path.c
|
||||
src/util/platform/FFPlatform.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
|
||||
if(LINUX)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_linux.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
src/detection/board/board_linux.c
|
||||
@@ -583,16 +597,17 @@ if(LINUX)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_linux.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_linux.c
|
||||
src/detection/battery/battery_android.c
|
||||
src/detection/bios/bios_android.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
@@ -656,17 +671,18 @@ elseif(ANDROID)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(FreeBSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_bsd.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/sysctl.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_bsd.c
|
||||
src/detection/battery/battery_bsd.c
|
||||
src/detection/bios/bios_bsd.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
@@ -738,8 +754,6 @@ elseif(FreeBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
if(DragonFly)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -754,12 +768,15 @@ elseif(FreeBSD)
|
||||
endif()
|
||||
elseif(NetBSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_bsd.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/sysctl.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_nbsd.c
|
||||
src/detection/battery/battery_nbsd.c
|
||||
src/detection/bios/bios_nbsd.c
|
||||
src/detection/bluetooth/bluetooth_bsd.c
|
||||
@@ -831,17 +848,19 @@ elseif(NetBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(OpenBSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_bsd.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/sysctl.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/smbiosHelper.c
|
||||
src/common/impl/kmod_nosupport.c
|
||||
src/detection/battery/battery_obsd.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
@@ -913,17 +932,20 @@ elseif(OpenBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_apple.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_apple.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/sysctl.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_apple.c
|
||||
src/common/impl/kmod_apple.c
|
||||
src/common/apple/cf_helpers.c
|
||||
src/common/apple/osascript.m
|
||||
src/common/apple/smc_temps.c
|
||||
src/detection/battery/battery_apple.c
|
||||
src/detection/bios/bios_apple.c
|
||||
src/detection/bluetooth/bluetooth_apple.m
|
||||
@@ -982,18 +1004,24 @@ elseif(APPLE)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/apple/smc_temps.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_apple.c
|
||||
)
|
||||
elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_windows.c
|
||||
src/common/netif/netif_windows.c
|
||||
src/common/networking/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/common/impl/io_windows.c
|
||||
src/common/impl/netif_windows.c
|
||||
src/common/impl/networking_windows.c
|
||||
src/common/impl/processing_windows.c
|
||||
src/common/impl/FFPlatform_windows.c
|
||||
src/common/impl/binary_windows.c
|
||||
src/common/impl/debug_windows.c
|
||||
src/common/impl/kmod_windows.c
|
||||
src/common/windows/getline.c
|
||||
src/common/windows/com.cpp
|
||||
src/common/windows/registry.c
|
||||
src/common/windows/unicode.c
|
||||
src/common/windows/wmi.cpp
|
||||
src/common/windows/variant.cpp
|
||||
src/common/windows/version.c
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
@@ -1032,7 +1060,7 @@ elseif(WIN32)
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/netio/netio_windows.c
|
||||
src/detection/opengl/opengl_windows.c
|
||||
src/detection/os/os_windows.cpp
|
||||
src/detection/os/os_windows.c
|
||||
src/detection/packages/packages_windows.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_windows.c
|
||||
@@ -1047,27 +1075,21 @@ elseif(WIN32)
|
||||
src/detection/users/users_windows.c
|
||||
src/detection/wallpaper/wallpaper_windows.c
|
||||
src/detection/wifi/wifi_windows.c
|
||||
src/detection/wm/wm_windows.cpp
|
||||
src/detection/wm/wm_windows.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
src/util/windows/unicode.c
|
||||
src/util/windows/wmi.cpp
|
||||
src/util/windows/version.c
|
||||
src/util/platform/FFPlatform_windows.c
|
||||
src/util/binary_windows.c
|
||||
src/util/debug_windows.c
|
||||
)
|
||||
elseif(SunOS)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_apple.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_apple.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_sunos.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
@@ -1139,16 +1161,18 @@ elseif(SunOS)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(Haiku)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_haiku.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_haiku.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_nosupport.c
|
||||
src/common/haiku/version.cpp
|
||||
src/detection/battery/battery_haiku.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
@@ -1207,17 +1231,17 @@ elseif(Haiku)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/haiku/version.cpp
|
||||
)
|
||||
elseif(GNU)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_gnu.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/impl/dbus.c
|
||||
src/common/impl/io_unix.c
|
||||
src/common/impl/netif_gnu.c
|
||||
src/common/impl/networking_linux.c
|
||||
src/common/impl/processing_linux.c
|
||||
src/common/impl/FFPlatform_unix.c
|
||||
src/common/impl/binary_linux.c
|
||||
src/common/impl/kmod_nosupport.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/board/board_nosupport.c
|
||||
@@ -1247,7 +1271,7 @@ elseif(GNU)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_general.c
|
||||
src/detection/gpu/gpu_gnu.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_nosupport.c
|
||||
@@ -1286,8 +1310,6 @@ elseif(GNU)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1308,11 +1330,15 @@ endif()
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(wcwidth HAVE_WCWIDTH)
|
||||
if(NOT HAVE_WCWIDTH)
|
||||
list(APPEND LIBFASTFETCH_SRC src/util/wcwidth.c)
|
||||
list(APPEND LIBFASTFETCH_SRC src/common/impl/wcwidth.c)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
endif()
|
||||
check_function_exists(memrchr HAVE_MEMRCHR)
|
||||
if(NOT HAVE_MEMRCHR)
|
||||
list(APPEND LIBFASTFETCH_SRC src/common/impl/memrchr.c)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SYSTEM_YYJSON)
|
||||
find_package(yyjson)
|
||||
@@ -1331,6 +1357,15 @@ add_library(libfastfetch OBJECT
|
||||
${LIBFASTFETCH_SRC}
|
||||
)
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
check_c_source_compiles("int main(void){int arr[1];return _Countof(arr);}" COMPILER_SUPPORTS_COUNT_OF)
|
||||
if(COMPILER_SUPPORTS_COUNT_OF)
|
||||
message(STATUS "_Countof is supported by the compiler")
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_SUPPORTS_COUNT_OF=1)
|
||||
else()
|
||||
message(STATUS "_Countof is NOT supported by the compiler")
|
||||
endif()
|
||||
|
||||
if(yyjson_FOUND)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON=1)
|
||||
target_link_libraries(libfastfetch PUBLIC yyjson::yyjson)
|
||||
@@ -1402,7 +1437,7 @@ elseif(OpenBSD)
|
||||
elseif(DragonFly)
|
||||
target_compile_definitions(libfastfetch PUBLIC __FreeBSD__)
|
||||
elseif(SunOS)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 __EXTENSIONS__ _POSIX_C_SOURCE)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 __EXTENSIONS__ _POSIX_C_SOURCE)
|
||||
elseif(NetBSD)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-char-subscripts")
|
||||
@@ -1410,9 +1445,39 @@ elseif(NetBSD)
|
||||
elseif(Haiku)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
elseif(GNU)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
# On Hurd PATH_MAX is not defined. Set an arbitrary limit as workaround.
|
||||
target_compile_definitions(libfastfetch PUBLIC PATH_MAX=4096)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE PATH_MAX=4096 O_PATH=0)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(ENABLE_APPLE_MEMSIZE_USABLE)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_APPLE_MEMSIZE_USABLE=1)
|
||||
else()
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_APPLE_MEMSIZE_USABLE=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
check_function_exists(_msize HAVE_MSVC_MSIZE)
|
||||
if(HAVE_MSVC_MSIZE)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MSVC_MSIZE=1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_WIN7_COMPAT)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_WIN7_COMPAT=1)
|
||||
else()
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_WIN7_COMPAT=0)
|
||||
endif()
|
||||
else()
|
||||
check_function_exists(malloc_usable_size HAVE_MALLOC_USABLE_SIZE)
|
||||
if(HAVE_MALLOC_USABLE_SIZE)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MALLOC_USABLE_SIZE=1)
|
||||
else()
|
||||
check_function_exists(malloc_size HAVE_MALLOC_SIZE)
|
||||
if(HAVE_MALLOC_SIZE)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_MALLOC_SIZE=1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FreeBSD OR OpenBSD OR NetBSD)
|
||||
@@ -1598,10 +1663,6 @@ ff_lib_enable(DIRECTX_HEADERS
|
||||
"DirectX-Headers"
|
||||
"DirectX-Headers"
|
||||
)
|
||||
ff_lib_enable(PCIACCESS
|
||||
"pciaccess"
|
||||
"pciaccess"
|
||||
)
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
|
||||
@@ -1625,6 +1686,9 @@ if(ENABLE_LIBZFS)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_MEMRCHR)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CUSTOM_MEMRCHR=1)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1661,7 +1725,6 @@ elseif(APPLE)
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "dwmapi"
|
||||
PRIVATE "gdi32"
|
||||
PRIVATE "iphlpapi"
|
||||
PRIVATE "ole32"
|
||||
@@ -1671,13 +1734,11 @@ elseif(WIN32)
|
||||
PRIVATE "version"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
PRIVATE "cfgmgr32"
|
||||
PRIVATE "propsys"
|
||||
PRIVATE "winbrand"
|
||||
PRIVATE "secur32"
|
||||
)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
|
||||
# WoA only works on Windows 10 or higher
|
||||
if(NOT ENABLE_WIN7_COMPAT)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "mincore"
|
||||
)
|
||||
@@ -1865,7 +1926,7 @@ set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(fastfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
PRIVATE src/common/windows/version.rc
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_options(fastfetch
|
||||
@@ -1893,7 +1954,7 @@ if (BUILD_FLASHFETCH)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(flashfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
PRIVATE src/common/windows/version.rc
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_options(flashfetch
|
||||
@@ -2058,7 +2119,7 @@ if(LINUX)
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
endif()
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
elseif(FreeBSD AND NOT DragonFly)
|
||||
set(CPACK_FREEBSD_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};FREEBSD")
|
||||
endif()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2023 Linus Dierheimer
|
||||
Copyright (c) 2022-2025 Carter Li
|
||||
Copyright (c) 2022-2026 Carter Li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
[](README-cn.md)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and illumos (SunOS).
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku and SunOS (illumos, Solaris).
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
fastfetch (2.58.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.58.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 22 Jan 2026 15:30:58 +0800
|
||||
|
||||
fastfetch (2.57.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.57.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 14 Jan 2026 14:00:17 +0800
|
||||
|
||||
fastfetch (2.57.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.57.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 12 Jan 2026 10:11:21 +0800
|
||||
|
||||
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.1
|
||||
|
||||
+29
-14
@@ -318,7 +318,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"cpuFormat": {
|
||||
"description": "Output format of the module `CPU`. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: X86-64 CPU microarchitecture",
|
||||
"description": "Output format of the module `CPU`. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count",
|
||||
"type": "string"
|
||||
},
|
||||
"cpucacheFormat": {
|
||||
@@ -442,7 +442,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"packagesFormat": {
|
||||
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop-user}: Number of scoop-user packages\n 21. {scoop-global}: Number of scoop-global packages\n 22. {choco}: Number of choco packages\n 23. {pkgtool}: Number of pkgtool packages\n 24. {paludis}: Number of paludis packages\n 25. {winget}: Number of winget packages\n 26. {opkg}: Number of opkg packages\n 27. {am-system}: Number of am-system packages\n 28. {sorcery}: Number of sorcery packages\n 29. {lpkg}: Number of lpkg packages\n 30. {lpkgbuild}: Number of lpkgbuild packages\n 31. {guix-system}: Number of guix-system packages\n 32. {guix-user}: Number of guix-user packages\n 33. {guix-home}: Number of guix-home packages\n 34. {linglong}: Number of linglong packages\n 35. {pacstall}: Number of pacstall packages\n 36. {mport}: Number of mport packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {nix-all}: Total number of all nix packages\n 44. {flatpak-all}: Total number of all flatpak app packages\n 45. {brew-all}: Total number of all brew packages\n 46. {guix-all}: Total number of all guix packages\n 47. {hpkg-all}: Total number of all hpkg packages",
|
||||
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop-user}: Number of scoop-user packages\n 21. {scoop-global}: Number of scoop-global packages\n 22. {choco}: Number of choco packages\n 23. {pkgtool}: Number of pkgtool packages\n 24. {paludis}: Number of paludis packages\n 25. {winget}: Number of winget packages\n 26. {opkg}: Number of opkg packages\n 27. {am-system}: Number of am-system packages\n 28. {sorcery}: Number of sorcery packages\n 29. {lpkg}: Number of lpkg packages\n 30. {lpkgbuild}: Number of lpkgbuild packages\n 31. {guix-system}: Number of guix-system packages\n 32. {guix-user}: Number of guix-user packages\n 33. {guix-home}: Number of guix-home packages\n 34. {linglong}: Number of linglong packages\n 35. {pacstall}: Number of pacstall packages\n 36. {mport}: Number of mport packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {kiss}: Number of kiss packages\n 44. {moss}: Number of moss packages\n 45. {nix-all}: Total number of all nix packages\n 46. {flatpak-all}: Total number of all flatpak app packages\n 47. {brew-all}: Total number of all brew packages\n 48. {guix-all}: Total number of all guix packages\n 49. {hpkg-all}: Total number of all hpkg packages",
|
||||
"type": "string"
|
||||
},
|
||||
"physicaldiskFormat": {
|
||||
@@ -498,7 +498,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"titleFormat": {
|
||||
"description": "Output format of the module `Title`. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)\n 9. {full-user-name}: Full user name",
|
||||
"description": "Output format of the module `Title`. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)\n 9. {full-user-name}: Full user name\n 10. {user-id}: UID (*nix) / SID (Windows)\n 11. {pid}: PID of current process\n 12. {cwd}: CWD with home dir replaced by `~`",
|
||||
"type": "string"
|
||||
},
|
||||
"themeFormat": {
|
||||
@@ -546,7 +546,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"zpoolFormat": {
|
||||
"description": "Output format of the module `Zpool`. See Wiki for formatting syntax\n 1. {name}: Zpool name\n 2. {state}: Zpool state\n 3. {used}: Size used\n 4. {total}: Size total\n 5. {used-percentage}: Size percentage num\n 6. {fragmentation-percentage}: Fragmentation percentage num\n 7. {used-percentage-bar}: Size percentage bar\n 8. {fragmentation-percentage-bar}: Fragmentation percentage bar",
|
||||
"description": "Output format of the module `Zpool`. See Wiki for formatting syntax\n 1. {name}: Zpool name\n 2. {guid}: Zpool guid\n 3. {state}: Zpool state\n 4. {used}: Size used\n 5. {allocated}: Size allocated\n 6. {total}: Size total\n 7. {used-percentage}: Size used percentage num\n 8. {allocated-percentage}: Size allocated percentage num\n 9. {fragmentation-percentage}: Fragmentation percentage num\n 10. {used-percentage-bar}: Size used percentage bar\n 11. {allocated-percentage-bar}: Size allocated percentage bar\n 12. {fragmentation-percentage-bar}: Fragmentation percentage bar\n 13. {is-readonly}: Is read-only",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@@ -1521,7 +1521,7 @@
|
||||
"description": "Print battery capacity, status, etc"
|
||||
},
|
||||
"useSetupApi": {
|
||||
"description": "Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only",
|
||||
"description": "Set if `CM API` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
@@ -1999,7 +1999,7 @@
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print some colored blocks",
|
||||
"description": "Display the terminal's 16-color palette",
|
||||
"const": "colors"
|
||||
},
|
||||
"symbol": {
|
||||
@@ -2518,11 +2518,6 @@
|
||||
"const": "de",
|
||||
"description": "Print desktop environment name"
|
||||
},
|
||||
"slowVersionDetection": {
|
||||
"type": "boolean",
|
||||
"description": "Set if DE version should be detected with slow operations.\nShould be unnecessary for most cases.\nThis is only used as a fallback method. Please file a bug report if you encounter any issues.",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2964,8 +2959,11 @@
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"outputColor": {
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
"$ref": "#/$defs/keyboardFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
@@ -3199,6 +3197,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Logo",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "logo",
|
||||
"description": "Query built-in logo for JSON output"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Media",
|
||||
"type": "object",
|
||||
@@ -3296,8 +3308,11 @@
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"outputColor": {
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
"$ref": "#/$defs/mouseFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
@@ -4467,7 +4482,7 @@
|
||||
"detectPlugin": {
|
||||
"description": "Set if window manager plugin should be detected on supported platforms",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"default": true
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
},
|
||||
"tpm",
|
||||
"version",
|
||||
"logo",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Load with --config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Load with --config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
|
||||
+51
-50
@@ -9,25 +9,26 @@
|
||||
// Constants are reusable strings referenced by {$1}, {$2}, etc.
|
||||
// These contain ANSI escape codes for cursor positioning
|
||||
"constants": [
|
||||
"──────────────────────────────────────────────", // {$1} - horizontal line for borders
|
||||
"──────────────────────────────────────────────", // {$1} - horizontal line for inner borders
|
||||
"\u001b[47D", // {$2} - move cursor left 47 columns
|
||||
"\u001b[47C", // {$3} - move cursor right 47 columns
|
||||
"\u001b[46C" // {$4} - move cursor right 46 columns
|
||||
"\u001b[46C", // {$4} - move cursor right 46 columns
|
||||
"══════════════════════════════════════════════" // {$5} - horizontal line for outer borders
|
||||
],
|
||||
"brightColor": false
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "version",
|
||||
"key": "┌───────────────┬─{$1}┐\u001b[41D",
|
||||
"key": "╔═══════════════╦═{$5}╗\u001b[41D",
|
||||
"format": "\u001b[1m{#keys} {1} - {2} "
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
// Key format breakdown for OS module:
|
||||
// "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
// "║ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}║{$2}"
|
||||
//
|
||||
// │ - Left border of key block
|
||||
// ║ - Left border of key block
|
||||
// {icon} - OS icon (defined internally by fastfetch)
|
||||
// \u001b[s - ANSI escape: save cursor position (ESC[s)
|
||||
// {sysname} - Format variable: system name (e.g., "Linux", "Darwin")
|
||||
@@ -36,28 +37,28 @@
|
||||
// \u001b[10C - ANSI escape: move cursor right 10 columns (ESC[10C)
|
||||
// │ - Right border of key block (always 10 columns from left border)
|
||||
// {$3} - Reference to constants[2]: move cursor right 47 columns
|
||||
// │ - Right border of value block
|
||||
// ║ - Right border of value block
|
||||
// {$2} - Reference to constants[1]: move cursor left 47 columns
|
||||
//
|
||||
// This creates a fixed-width layout where the key block is exactly 10 columns wide,
|
||||
// regardless of the actual content length. The cursor manipulation ensures proper
|
||||
// alignment for the table-like structure.
|
||||
"key": "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
"key": "║ {icon} \u001b[s{sysname}\u001b[u\u001b[10C║{$3}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "│ {icon} Fetched │{$3}│{$2}",
|
||||
"key": "║ {icon} Fetched ║{$3}║{$2}",
|
||||
"format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {timezone-name}"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"key": "│ {icon} Locale │{$3}│{$2}"
|
||||
"key": "║ {icon} Locale ║{$3}║{$2}"
|
||||
},
|
||||
|
||||
// Hardware section with cyan color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#cyan}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_cyan} Hardware "
|
||||
},
|
||||
{
|
||||
@@ -66,113 +67,113 @@
|
||||
// │{#cyan}│ - Left border with cyan color
|
||||
// {icon} - Chassis icon
|
||||
// Chassis - Fixed label text
|
||||
// │{$4}│{#keys}│{$2} - Positioning and borders for value area
|
||||
"key": "│{#cyan}│ {icon} Chassis │{$4}│{#keys}│{$2}"
|
||||
// │{$4}│{#keys}║{$2} - Positioning and borders for value area
|
||||
"key": "║{#cyan}│ {icon} Chassis │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│{#cyan}│ {icon} RAM │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} RAM │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│{#cyan}│ {icon} SWAP │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} SWAP │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│{#cyan}│ {icon} CPU │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#cyan}│ {icon} CPU │{$4}│{#keys}║{$2}",
|
||||
"showPeCoreCount": true
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#cyan}│ {icon} GPU │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} GPU │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│{#cyan}│ {icon} Disk │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#cyan}│ {icon} Disk │{$4}│{#keys}║{$2}",
|
||||
"format": "{size-used} \/ {size-total} ({size-percentage}) - {filesystem}",
|
||||
},
|
||||
{
|
||||
"type": "battery",
|
||||
"key": "│{#cyan}│ {icon} Battery │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#cyan}│ {icon} Battery │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#cyan}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Desktop section with green color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#green}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_green} Desktop "
|
||||
},
|
||||
{
|
||||
"type": "de",
|
||||
"key": "│{#green}│ {icon} Desktop │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#green}│ {icon} Desktop │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "│{#green}│ {icon} Session │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#green}│ {icon} Session │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "display",
|
||||
"key": "│{#green}│ {icon} Display │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#green}│ {icon} Display │{$4}│{#keys}║{$2}",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#green}│ {icon} G-Driver │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#green}│ {icon} G-Driver │{$4}│{#keys}║{$2}",
|
||||
"format": "{driver}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#green}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Terminal section with yellow color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"key": "║{#yellow}┌──────────────┬{$1}┐{#keys}║\u001b[37D",
|
||||
"format": "{#bright_yellow} Terminal "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "│{#yellow}│ {icon} Shell │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Shell │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│{#yellow}│ {icon} Terminal │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Terminal │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "│{#yellow}│ {icon} Term Font │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Term Font │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminaltheme",
|
||||
"key": "│{#yellow}│ {icon} Colors │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Colors │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│{#yellow}│ {icon} Packages │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#yellow}│ {icon} Packages │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#yellow}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Development section with red color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}┌──────────────┬{$1}┐{#keys}│\u001b[39D",
|
||||
"key": "║{#red}┌──────────────┬{$1}┐{#keys}║\u001b[39D",
|
||||
"format": "{#bright_red} Development "
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "", // Custom icon override
|
||||
"key": "│{#red}│ {icon} Rust │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Rust │{$4}│{#keys}║{$2}",
|
||||
"text": "rustc --version",
|
||||
"format": "rustc {~6,13}" // Print 6th to 13th characters (version number)
|
||||
},
|
||||
@@ -182,7 +183,7 @@
|
||||
"!system": "Windows" // Posix version
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Clang │{$4}│{#keys}║{$2}",
|
||||
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
@@ -192,67 +193,67 @@
|
||||
"system": "Windows" // Windows version
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Clang │{$4}│{#keys}║{$2}",
|
||||
"text": "clang --version | findstr version", // Finds the line with "version"
|
||||
"format": "clang {~-6}" // Prints the last 6 characters (version number)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} NodeJS │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} NodeJS │{$4}│{#keys}║{$2}",
|
||||
"text": "node --version",
|
||||
"format": "node {~1}" // {~1} removes first character (v)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Go │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Go │{$4}│{#keys}║{$2}",
|
||||
"text": "go version | cut -d' ' -f3",
|
||||
"format": "go {~2}" // {~2} removes first 2 characters (go)
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Zig │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Zig │{$4}│{#keys}║{$2}",
|
||||
"text": "zig version",
|
||||
"format": "zig {}"
|
||||
},
|
||||
{
|
||||
"type": "editor",
|
||||
"key": "│{#red}│ {icon} Editor │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#red}│ {icon} Editor │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Git │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#red}│ {icon} Git │{$4}│{#keys}║{$2}",
|
||||
"text": "git version",
|
||||
"format": "git {~12}"
|
||||
},
|
||||
{
|
||||
"type": "font",
|
||||
"key": "│{#red}│ {icon} Interface │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#red}│ {icon} Interface │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#red}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Uptime section with magenta color theme
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}┌──────────────┬{$1}┐{#keys}│\u001b[36D",
|
||||
"key": "║{#magenta}┌──────────────┬{$1}┐{#keys}║\u001b[36D",
|
||||
"format": "{#bright_magenta} Uptime "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│{#magenta}│ {icon} Uptime │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#magenta}│ {icon} Uptime │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"myselfOnly": true, // Only show current user
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
|
||||
"key": "║{#magenta}│ {icon} Login │{$4}│{#keys}║{$2}"
|
||||
},
|
||||
{
|
||||
"condition": { // Conditional module: only show on non-macOS
|
||||
@@ -260,7 +261,7 @@
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#magenta}│ {icon} OS Age │{$4}│{#keys}║{$2}",
|
||||
"folders": "/", // Check root filesystem
|
||||
"format": "{create-time:10} [{days} days]" // Show creation time and age in days
|
||||
},
|
||||
@@ -270,18 +271,18 @@
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"key": "║{#magenta}│ {icon} OS Age │{$4}│{#keys}║{$2}",
|
||||
"folders": "/System/Volumes/VM", // Work around for APFS on macOS
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}└──────────────┴{$1}┘{#keys}│",
|
||||
"key": "║{#magenta}└──────────────┴{$1}┘{#keys}║",
|
||||
"format": ""
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "└─────────────────{$1}┘", // Bottom border of the entire layout
|
||||
"key": "╚═════════════════{$5}╝", // Bottom border of the entire layout
|
||||
"format": ""
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/3.jsonc
|
||||
// Load with --config examples/3.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,57 @@
|
||||
// Inspired by microfetch
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
"general": {
|
||||
"detectVersion": false
|
||||
},
|
||||
"display": {
|
||||
"separator": " ",
|
||||
"brightColor": false,
|
||||
"key": {
|
||||
"type": "both-2"
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "title",
|
||||
"format": "{user-name-colored}{#light_red}@{host-name-colored} {#}{cwd}"
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "System "
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "Kernel "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "Shell "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "Uptime "
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "Desktop "
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "Memory "
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "Storage (/) ",
|
||||
"folders": "/"
|
||||
},
|
||||
{
|
||||
"type": "colors",
|
||||
"key": "Colors ",
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/4.jsonc
|
||||
// Load with --config examples/4.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/5.jsonc
|
||||
// Load with --config examples/5.jsonc
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Load with --config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Load with --config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/FFlist.h"
|
||||
|
||||
typedef struct FFPlatformSysinfo
|
||||
{
|
||||
@@ -18,8 +18,15 @@ typedef struct FFPlatform
|
||||
FFstrbuf cacheDir; // Trailing slash included
|
||||
FFlist configDirs; // List of FFstrbuf, trailing slash included
|
||||
FFlist dataDirs; // List of FFstrbuf, trailing slash included
|
||||
FFstrbuf exePath; // The real path of current exe
|
||||
FFstrbuf exePath; // The real path of current exe (empty if unavailable)
|
||||
FFstrbuf cwd; // Trailing slash included
|
||||
|
||||
uint32_t pid;
|
||||
#ifndef _WIN32
|
||||
uint32_t uid;
|
||||
#else
|
||||
FFstrbuf sid;
|
||||
#endif
|
||||
FFstrbuf userName;
|
||||
FFstrbuf fullUserName;
|
||||
FFstrbuf hostName;
|
||||
@@ -126,3 +126,10 @@ static inline void ffListClear(FFlist* list)
|
||||
assert(sizeof(itemType) == (listVar).elementSize); \
|
||||
(itemType*) ffListAdd(&(listVar)); \
|
||||
})
|
||||
|
||||
#define FF_LIST_FIRST(itemType, listVar) FF_LIST_GET(itemType, listVar, 0)
|
||||
#define FF_LIST_LAST(itemType, listVar) \
|
||||
({ \
|
||||
assert((listVar).length > 0); \
|
||||
FF_LIST_GET(itemType, listVar, ((listVar).length - 1)); \
|
||||
})
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#define FASTFETCH_STRBUF_DEFAULT_ALLOC 32
|
||||
|
||||
// static string (allocated == 0), chars points to a string literal
|
||||
// dynamic string (allocated > 0), chars points to a heap allocated buffer
|
||||
typedef struct FFstrbuf
|
||||
{
|
||||
uint32_t allocated;
|
||||
@@ -34,6 +36,7 @@ typedef struct FFstrbuf
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf);
|
||||
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
|
||||
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
|
||||
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
|
||||
|
||||
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
|
||||
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);
|
||||
@@ -54,6 +57,10 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c);
|
||||
|
||||
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
|
||||
|
||||
// Clear the content of strbuf and set new value
|
||||
// NOTE: Unlike ffStrbufAppend*, ffStrbufSet* functions may NOT reserve extra space
|
||||
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
|
||||
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
|
||||
FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
|
||||
|
||||
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
|
||||
@@ -96,6 +103,10 @@ FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultV
|
||||
void ffStrbufUpperCase(FFstrbuf* strbuf);
|
||||
void ffStrbufLowerCase(FFstrbuf* strbuf);
|
||||
|
||||
// Function alters the buffer to extract lines or delimited segments (replaces the delimiter with '\0')
|
||||
// so that buffer MUST be heap allocated (NOT a static string)
|
||||
// `lineptr` must be `NULL` and `n` MUST be `0` for the first call
|
||||
// Caller MUST NOT free `*lineptr`
|
||||
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
|
||||
@@ -104,10 +115,14 @@ void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf
|
||||
*
|
||||
* @details Behaves like getline(3) but reads from a FFstrbuf.
|
||||
*
|
||||
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line.
|
||||
* Can be NULL for the first call.
|
||||
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line
|
||||
(points to buffer's internal memory address to avoid memory allocation and copy).
|
||||
MUST NOT be freed by the caller, unlike `getline(3)`.
|
||||
* MUST be NULL for the first call.
|
||||
* @param[in,out] n The pointer to the size of the buffer of lineptr.
|
||||
* @param[in] buffer The buffer to read from. The buffer must not be a string literal.
|
||||
MUST be 0 for the first call.
|
||||
* @param[in] buffer The buffer to read from.
|
||||
MUST be heap allocated (NOT a static string).
|
||||
*
|
||||
* @return true if a line has been read, false if the end of the buffer has been reached.
|
||||
*/
|
||||
@@ -117,7 +132,7 @@ static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
}
|
||||
/**
|
||||
* @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
* @warning This function should be called before breaking an ffStrbufGetline loop.
|
||||
* @warning This function should be called before breaking an ffStrbufGetline loop if `buffer` will be used later.
|
||||
*/
|
||||
static inline void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
{
|
||||
@@ -147,7 +162,7 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
|
||||
static inline void ffStrbufInitCopy(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict src)
|
||||
{
|
||||
if (src->allocated == 0) // static string
|
||||
memcpy(strbuf, src, sizeof(FFstrbuf));
|
||||
*strbuf = *src;
|
||||
else
|
||||
{
|
||||
ffStrbufInitA(strbuf, src->allocated);
|
||||
@@ -167,9 +182,7 @@ static inline void ffStrbufInitMove(FFstrbuf* strbuf, FFstrbuf* src)
|
||||
{
|
||||
if (src)
|
||||
{
|
||||
strbuf->allocated = src->allocated;
|
||||
strbuf->chars = src->chars;
|
||||
strbuf->length = src->length;
|
||||
*strbuf = *src;
|
||||
ffStrbufInit(src);
|
||||
}
|
||||
else
|
||||
@@ -212,21 +225,17 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateF(const char* format, ...)
|
||||
return strbuf;
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr)
|
||||
{
|
||||
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
|
||||
}
|
||||
|
||||
static inline void ffStrbufDestroy(FFstrbuf* strbuf)
|
||||
{
|
||||
extern char* CHAR_NULL_PTR;
|
||||
if(strbuf->allocated > 0)
|
||||
free(strbuf->chars);
|
||||
|
||||
if(strbuf->allocated == 0)
|
||||
{
|
||||
strbuf->length = 0;
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
return;
|
||||
}
|
||||
|
||||
//Avoid free-after-use. These 3 assignments are cheap so don't remove them
|
||||
strbuf->allocated = strbuf->length = 0;
|
||||
free(strbuf->chars);
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
ffStrbufInit(strbuf);
|
||||
}
|
||||
|
||||
FF_C_NODISCARD static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf)
|
||||
@@ -243,6 +252,30 @@ static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf)
|
||||
strbuf->length = (uint32_t) strlen(strbuf->chars);
|
||||
}
|
||||
|
||||
static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
|
||||
{
|
||||
assert(strbuf != NULL);
|
||||
|
||||
if (value == NULL)
|
||||
ffStrbufClear(strbuf);
|
||||
else
|
||||
ffStrbufSetNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
|
||||
{
|
||||
assert(strbuf != NULL);
|
||||
|
||||
if (yyjson_is_str(jsonVal))
|
||||
{
|
||||
ffStrbufSetNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
|
||||
return true;
|
||||
}
|
||||
|
||||
ffStrbufClear(strbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value)
|
||||
{
|
||||
if(value == NULL)
|
||||
@@ -260,42 +293,10 @@ static inline bool ffStrbufAppendJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value)
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
|
||||
if(value != NULL)
|
||||
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
static inline void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
ffStrbufAppendNS(strbuf, length, value);
|
||||
}
|
||||
|
||||
static inline void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
|
||||
{
|
||||
assert(value && value != strbuf);
|
||||
if (strbuf->allocated == 0 && value->allocated == 0)
|
||||
{
|
||||
memcpy(strbuf, value, sizeof(FFstrbuf));
|
||||
return;
|
||||
}
|
||||
ffStrbufSetNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal)
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
return ffStrbufAppendJsonVal(strbuf, jsonVal);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInit(FFstrbuf* strbuf)
|
||||
{
|
||||
extern char* CHAR_NULL_PTR;
|
||||
strbuf->allocated = 0;
|
||||
strbuf->length = 0;
|
||||
strbuf->allocated = strbuf->length = 0;
|
||||
strbuf->chars = CHAR_NULL_PTR;
|
||||
}
|
||||
|
||||
@@ -326,10 +327,12 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateStatic(const char* str)
|
||||
static inline void ffStrbufSetStatic(FFstrbuf* strbuf, const char* value)
|
||||
{
|
||||
if(strbuf->allocated > 0)
|
||||
ffStrbufDestroy(strbuf);
|
||||
free(strbuf->chars);
|
||||
|
||||
if(value != NULL)
|
||||
ffStrbufInitStatic(strbuf, value);
|
||||
else
|
||||
ffStrbufInit(strbuf);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* str)
|
||||
@@ -386,7 +389,7 @@ static inline void ffStrbufPrependS(FFstrbuf* strbuf, const char* value)
|
||||
ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value);
|
||||
}
|
||||
|
||||
static inline int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp)
|
||||
static inline FF_C_NODISCARD int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp)
|
||||
{
|
||||
uint32_t length = strbuf->length > comp->length ? comp->length : strbuf->length;
|
||||
return memcmp(strbuf->chars, comp->chars, length + 1);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "smc_temps.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
@@ -156,113 +156,108 @@ static const char *smcReadValue(io_connect_t conn, const UInt32Char_t key, doubl
|
||||
if (val.dataSize == 0)
|
||||
return "Empty SMC result";
|
||||
|
||||
if (ffStrEquals(val.dataType, "ui8 ") ||
|
||||
ffStrEquals(val.dataType, "ui16") ||
|
||||
ffStrEquals(val.dataType, "ui32") ||
|
||||
ffStrEquals(val.dataType, "ui64"))
|
||||
switch (val.dataType[0])
|
||||
{
|
||||
uint64_t tmp = 0;
|
||||
for (uint32_t i = 0; i < val.dataSize; i++)
|
||||
tmp += (uint64_t)((uint8_t)(val.bytes[i]) * pow(256, val.dataSize - 1 - i));
|
||||
*value = (double)tmp;
|
||||
case 'u': // unsigned integer types
|
||||
if (val.dataType[1] == 'i')
|
||||
{
|
||||
switch (val.dataSize)
|
||||
{
|
||||
case 1: *value = *(uint8_t *)(val.bytes); break;
|
||||
case 2: *value = ntohs(*(uint16_t *)(val.bytes)); break;
|
||||
case 4: *value = ntohl(*(uint32_t *)(val.bytes)); break;
|
||||
case 8: *value = (double) ntohll(*(uint64_t *)(val.bytes)); break;
|
||||
default:
|
||||
return "Unsupported SMC unsigned integer data size";
|
||||
}
|
||||
}
|
||||
else
|
||||
return "Unsupported SMC unsigned data type";
|
||||
break;
|
||||
|
||||
case 'f': // floating point types
|
||||
if (ffStrEquals(val.dataType, "flt ") && val.dataSize == 4)
|
||||
*value = *(float *)(val.bytes);
|
||||
else if (val.dataType[1] == 'p' && val.dataSize == 2) // fixed point types
|
||||
{
|
||||
if (ffStrEquals(val.dataType, "fp1f"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 32768.0;
|
||||
else if (ffStrEquals(val.dataType, "fp4c"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4096.0;
|
||||
else if (ffStrEquals(val.dataType, "fp5b"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 2048.0;
|
||||
else if (ffStrEquals(val.dataType, "fp6a"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1024.0;
|
||||
else if (ffStrEquals(val.dataType, "fp79"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 512.0;
|
||||
else if (ffStrEquals(val.dataType, "fp88"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 256.0;
|
||||
else if (ffStrEquals(val.dataType, "fpa6"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 64.0;
|
||||
else if (ffStrEquals(val.dataType, "fpc4"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16.0;
|
||||
else if (ffStrEquals(val.dataType, "fpe2"))
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4.0;
|
||||
else
|
||||
return "Unsupported SMC floating point data type";
|
||||
}
|
||||
else
|
||||
return "Unsupported SMC floating point data type";
|
||||
break;
|
||||
|
||||
case 's': // signed integer types
|
||||
if (val.dataType[1] == 'i')
|
||||
{
|
||||
switch (val.dataSize)
|
||||
{
|
||||
case 1: *value = *(int8_t *)(val.bytes); break;
|
||||
case 2: *value = ntohs(*(int16_t *)(val.bytes)); break;
|
||||
case 4: *value = ntohl(*(int32_t *)(val.bytes)); break;
|
||||
case 8: *value = (double)ntohll(*(int64_t *)(val.bytes)); break;
|
||||
default: return "Unsupported SMC signed integer data size";
|
||||
}
|
||||
}
|
||||
else if (val.dataType[1] == 'p' && val.dataSize == 2) // signed fixed point types
|
||||
{
|
||||
if (ffStrEquals(val.dataType, "sp1e"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 16384.0;
|
||||
else if (ffStrEquals(val.dataType, "sp3c"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 4096.0;
|
||||
else if (ffStrEquals(val.dataType, "sp4b"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 2048.0;
|
||||
else if (ffStrEquals(val.dataType, "sp5a"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 1024.0;
|
||||
else if (ffStrEquals(val.dataType, "sp69"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 512.0;
|
||||
else if (ffStrEquals(val.dataType, "sp78"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 256.0;
|
||||
else if (ffStrEquals(val.dataType, "sp87"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 128.0;
|
||||
else if (ffStrEquals(val.dataType, "sp96"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 64.0;
|
||||
else if (ffStrEquals(val.dataType, "spb4"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 16.0;
|
||||
else if (ffStrEquals(val.dataType, "spf0"))
|
||||
*value = (int16_t)ntohs(*(int16_t *)(val.bytes)) / 1.0;
|
||||
else
|
||||
return "Unsupported SMC signed integer data type";
|
||||
}
|
||||
else
|
||||
return "Unsupported SMC signed data type";
|
||||
break;
|
||||
|
||||
case '{': // special types like pwm
|
||||
if (ffStrEquals(val.dataType, "{pwm") && val.dataSize == 2)
|
||||
{
|
||||
*value = (double)ntohs(*(uint16_t *)(val.bytes)) * 100 / 65536.0;
|
||||
}
|
||||
else
|
||||
return "Unsupported SMC special data type";
|
||||
break;
|
||||
|
||||
default:
|
||||
return "Unsupported SMC data type";
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "flt "))
|
||||
{
|
||||
*value = *(float *)(val.bytes);
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp1f") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 32768.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp4c") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4096.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp5b") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 2048.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp6a") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1024.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp79") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 512.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fp88") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 256.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fpa6") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 64.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fpc4") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "fpe2") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp1e") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16384.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp3c") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 4096.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp4b") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 2048.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp5a") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1024.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp69") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 512.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp78") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 256.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp87") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 128.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "sp96") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 64.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "spb4") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 16.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "spf0") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(uint16_t *)(val.bytes)) / 1.0;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "si8 ") && val.dataSize == 1)
|
||||
{
|
||||
signed char *bytes = (signed char *)val.bytes;
|
||||
int16_t temp = 0;
|
||||
temp += (int8_t)(bytes[0]);
|
||||
*value = temp;
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "si16") && val.dataSize == 2)
|
||||
{
|
||||
*value = ntohs(*(int16_t *)(val.bytes));
|
||||
}
|
||||
else if (ffStrEquals(val.dataType, "{pwm") && val.dataSize == 2)
|
||||
{
|
||||
*value = (double)ntohs(*(uint16_t *)(val.bytes)) * 100 / 65536.0;
|
||||
}
|
||||
else
|
||||
return "Unknown SMC data type";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __has_builtin
|
||||
#if __has_builtin(__is_array)
|
||||
#if !__cplusplus && FF_SUPPORTS_COUNT_OF
|
||||
#define ARRAY_SIZE(x) _Countof(x)
|
||||
#elif __has_builtin(__is_array)
|
||||
#define ARRAY_SIZE(x) ({ static_assert(__is_array(__typeof__(x)), "Must be an array"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
|
||||
#elif __has_builtin(__builtin_types_compatible_p)
|
||||
#define ARRAY_SIZE(x) ({ static_assert(!__builtin_types_compatible_p(__typeof__(x), __typeof__(&*(x))), "Must not be a pointer"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
|
||||
@@ -1,15 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
// Things only needed by fastfetch
|
||||
typedef struct FFdata
|
||||
{
|
||||
FFstrbuf structure;
|
||||
bool configLoaded;
|
||||
} FFdata;
|
||||
#include "common/ffdata.h"
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffPrintCommandOption(FFdata* data);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
|
||||
+5
-1
@@ -3,7 +3,7 @@
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
@@ -19,6 +19,7 @@ typedef struct FFDBusLibrary
|
||||
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
|
||||
FF_LIBRARY_SYMBOL(dbus_message_unref)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
|
||||
FF_LIBRARY_SYMBOL(dbus_connection_unref)
|
||||
} FFDBusLibrary;
|
||||
|
||||
typedef struct FFDBusData
|
||||
@@ -36,10 +37,13 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int32_t* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
|
||||
void ffDBusDestroyData(FFDBusData* data);
|
||||
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
|
||||
{
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface, NULL);
|
||||
}
|
||||
|
||||
#define FF_DBUS_AUTO_DESTROY_DATA __attribute__((__cleanup__(ffDBusDestroyData)))
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
@@ -28,4 +28,6 @@ static inline const char* ffFindFileName(const char* file)
|
||||
|
||||
#define FF_DEBUG(format, ...) FF_DEBUG_PRINT(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
|
||||
#if _WIN32
|
||||
const char* ffDebugWin32Error(unsigned long errorCode);
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result);
|
||||
bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFDataResultDocType
|
||||
{
|
||||
FF_RESULT_DOC_TYPE_DEFAULT = 0,
|
||||
FF_RESULT_DOC_TYPE_JSON,
|
||||
FF_RESULT_DOC_TYPE_CONFIG,
|
||||
FF_RESULT_DOC_TYPE_CONFIG_FULL,
|
||||
} FFDataResultDocType;
|
||||
|
||||
// FFdata aggregates configuration, generation parameters, and output state used by fastfetch.
|
||||
// It holds the parsed configuration document, a mutable JSON document for results, and related metadata.
|
||||
typedef struct FFdata
|
||||
{
|
||||
yyjson_doc* configDoc; // Parsed JSON configuration document
|
||||
yyjson_mut_doc* resultDoc; // Mutable JSON document for storing results
|
||||
FFstrbuf structure; // Custom output structure from command line
|
||||
FFstrbuf structureDisabled; // Disabled modules in the output structure from command line
|
||||
FFstrbuf genConfigPath; // Path to generate configuration file
|
||||
FFDataResultDocType docType; // Type of result document
|
||||
bool configLoaded;
|
||||
} FFdata;
|
||||
@@ -1,238 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void ffFontInit(FFfont* font)
|
||||
{
|
||||
// Ensure no memory allocates
|
||||
ffStrbufInit(&font->pretty);
|
||||
ffStrbufInit(&font->name);
|
||||
ffStrbufInit(&font->size);
|
||||
ffListInit(&font->styles, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
static void strbufAppendNSExcludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude)
|
||||
{
|
||||
if(value == NULL || length == 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(strbuf, length);
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
if(value[i] != exclude)
|
||||
strbuf->chars[strbuf->length++] = value[i];
|
||||
}
|
||||
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static void fontInitPretty(FFfont* font)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->name);
|
||||
|
||||
if(font->size.length == 0 && font->styles.length == 0)
|
||||
return;
|
||||
else if(font->pretty.length == 0)
|
||||
ffStrbufAppendS(&font->pretty, "default");
|
||||
|
||||
ffStrbufAppendS(&font->pretty, " (");
|
||||
|
||||
if(font->size.length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->size);
|
||||
ffStrbufAppendS(&font->pretty, "pt");
|
||||
|
||||
if(font->styles.length > 0)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, FF_LIST_GET(FFstrbuf, font->styles, i));
|
||||
|
||||
if(i < font->styles.length - 1)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&font->pretty, ')');
|
||||
}
|
||||
|
||||
void ffFontInitQt(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||
|
||||
//Family
|
||||
data = ffStrbufAppendSUntilC(&font->name, data, ',');
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Size
|
||||
data = ffStrbufAppendSUntilC(&font->size, data, ',');
|
||||
ffStrbufTrim(&font->size, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Style
|
||||
data = strrchr(data, ',');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
if (isalpha(*data))
|
||||
{
|
||||
do
|
||||
{
|
||||
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
} while (data);
|
||||
}
|
||||
|
||||
exit:
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* alternativeBuffer)
|
||||
{
|
||||
while(**data == ' ' || **data == '\t' || **data == ',')
|
||||
++(*data);
|
||||
|
||||
const char* wordStart = *data;
|
||||
|
||||
while(**data != ' ' && **data != '\t' && **data != ',' && **data != '\0' && **data != '`' && **data != '\\')
|
||||
++(*data);
|
||||
|
||||
uint32_t wordLength = (uint32_t) (*data - wordStart);
|
||||
if(wordLength == 0)
|
||||
return;
|
||||
|
||||
if(**data == '\0' || **data == '`' || **data == '\\')
|
||||
{
|
||||
ffStrbufAppendNS(&font->size, wordLength, wordStart);
|
||||
if(ffStrbufEndsWithS(&font->size, "px"))
|
||||
ffStrbufSubstrBefore(&font->size, font->size.length - 2);
|
||||
|
||||
double dummy;
|
||||
if(sscanf(font->size.chars, "%lf", &dummy) == 1)
|
||||
return;
|
||||
|
||||
ffStrbufClear(&font->size);
|
||||
}
|
||||
|
||||
if(
|
||||
strncasecmp(wordStart, "Ultra", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Extra", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Semi", 4) == 0 ||
|
||||
strncasecmp(wordStart, "Demi", 4) == 0 ||
|
||||
strncasecmp(wordStart, "Normal", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Roman", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Oblique", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Italic", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Thin", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Light", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Bold", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Black", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Condensed", wordLength) == 0 ||
|
||||
strncasecmp(wordStart, "Expanded", wordLength) == 0
|
||||
) {
|
||||
if(alternativeBuffer == NULL)
|
||||
{
|
||||
alternativeBuffer = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(alternativeBuffer);
|
||||
}
|
||||
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
|
||||
if(
|
||||
strncasecmp(wordStart, "Ultra ", 6) == 0 ||
|
||||
strncasecmp(wordStart, "Extra ", 6) == 0 ||
|
||||
strncasecmp(wordStart, "Semi ", 5) == 0 ||
|
||||
strncasecmp(wordStart, "Demi ", 5) == 0
|
||||
) {
|
||||
fontPangoParseWord(data, font, alternativeBuffer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(alternativeBuffer != NULL)
|
||||
{
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
return;
|
||||
}
|
||||
|
||||
if(font->name.length > 0)
|
||||
ffStrbufAppendC(&font->name, ' ');
|
||||
ffStrbufAppendNS(&font->name, wordLength, wordStart);
|
||||
}
|
||||
|
||||
void ffFontInitPango(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
while(*data != '\0' && *data != '`' && *data != '\\')
|
||||
fontPangoParseWord(&data, font, NULL);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendS(&font->name, name);
|
||||
ffStrbufTrim(&font->name, '"');
|
||||
ffStrbufAppendS(&font->size, size);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
if (name) ffStrbufInitMove(&font->name, name);
|
||||
if (size) ffStrbufInitMove(&font->size, size);
|
||||
if (style)
|
||||
{
|
||||
FFstrbuf* styleBuf = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInitMove(styleBuf, style);
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||
{
|
||||
const char* pspace = strrchr(rawName, ' ');
|
||||
if(pspace == NULL)
|
||||
{
|
||||
ffFontInitCopy(font, rawName);
|
||||
return;
|
||||
}
|
||||
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName);
|
||||
ffStrbufAppendS(&font->size, pspace + 1);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontDestroy(FFfont* font)
|
||||
{
|
||||
ffStrbufDestroy(&font->pretty);
|
||||
ffStrbufDestroy(&font->name);
|
||||
ffStrbufDestroy(&font->size);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, font->styles)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&font->styles);
|
||||
}
|
||||
+4
-2
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/FFlist.h"
|
||||
|
||||
typedef struct FFfont
|
||||
{
|
||||
@@ -15,6 +15,8 @@ void ffFontInit(FFfont* font);
|
||||
void ffFontInitQt(FFfont* font, const char* data);
|
||||
void ffFontInitPango(FFfont* font, const char* data);
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size);
|
||||
void ffFontInitXlfd(FFfont* font, const char* xlfd);
|
||||
void ffFontInitXft(FFfont* font, const char* xft);
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName);
|
||||
void ffFontDestroy(FFfont* font);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFformatArgType
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
|
||||
bool ffGetFileVersion(const char* filePath, FFstrbuf* version);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "FFPlatform_private.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/io.h"
|
||||
#include "detection/version/version.h"
|
||||
|
||||
void ffPlatformInit(FFPlatform* platform)
|
||||
@@ -10,12 +10,17 @@ void ffPlatformInit(FFPlatform* platform)
|
||||
ffListInit(&platform->configDirs, sizeof(FFstrbuf));
|
||||
ffListInit(&platform->dataDirs, sizeof(FFstrbuf));
|
||||
ffStrbufInit(&platform->exePath);
|
||||
ffStrbufInit(&platform->cwd);
|
||||
|
||||
ffStrbufInit(&platform->userName);
|
||||
ffStrbufInit(&platform->fullUserName);
|
||||
ffStrbufInit(&platform->hostName);
|
||||
ffStrbufInit(&platform->userShell);
|
||||
|
||||
#ifdef _WIN32
|
||||
ffStrbufInit(&platform->sid);
|
||||
#endif
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
|
||||
ffStrbufInit(&info->name);
|
||||
@@ -45,12 +50,17 @@ void ffPlatformDestroy(FFPlatform* platform)
|
||||
ffStrbufDestroy(dir);
|
||||
ffListDestroy(&platform->dataDirs);
|
||||
ffStrbufDestroy(&platform->exePath);
|
||||
ffStrbufDestroy(&platform->cwd);
|
||||
|
||||
ffStrbufDestroy(&platform->userName);
|
||||
ffStrbufDestroy(&platform->hostName);
|
||||
ffStrbufDestroy(&platform->userShell);
|
||||
ffStrbufDestroy(&platform->fullUserName);
|
||||
|
||||
#ifdef _WIN32
|
||||
ffStrbufDestroy(&platform->sid);
|
||||
#endif
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
ffStrbufDestroy(&info->architecture);
|
||||
ffStrbufDestroy(&info->name);
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "FFPlatform.h"
|
||||
#include "common/FFPlatform.h"
|
||||
|
||||
void ffPlatformInitImpl(FFPlatform* platform);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "FFPlatform_private.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/arrayUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/io.h"
|
||||
#include "fastfetch_config.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
@@ -11,10 +12,14 @@
|
||||
#include <paths.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libproc.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined(__OpenBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
#include <kvm.h>
|
||||
#include "common/path.h"
|
||||
#elif defined(__HAIKU__)
|
||||
#include <image.h>
|
||||
#include <OS.h>
|
||||
@@ -28,15 +33,19 @@ static void getExePath(FFPlatform* platform)
|
||||
if (exePathLen >= 0)
|
||||
exePath[exePathLen] = '\0';
|
||||
#elif defined(__APPLE__)
|
||||
int exePathLen = proc_pidpath((int) getpid(), exePath, sizeof(exePath));
|
||||
uint32_t exePathLen = sizeof(exePath);
|
||||
if (_NSGetExecutablePath(exePath, &exePathLen) == 0)
|
||||
exePathLen = (uint32_t) strlen(exePath);
|
||||
else
|
||||
exePathLen = 0;
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
size_t exePathLen = sizeof(exePath);
|
||||
if(sysctl(
|
||||
(int[]){CTL_KERN,
|
||||
#ifdef __FreeBSD__
|
||||
KERN_PROC, KERN_PROC_PATHNAME, (int) getpid()
|
||||
KERN_PROC, KERN_PROC_PATHNAME, (pid_t) platform->pid
|
||||
#else
|
||||
KERN_PROC_ARGS, (int) getpid(), KERN_PROC_PATHNAME
|
||||
KERN_PROC_ARGS, platform->pid, KERN_PROC_PATHNAME
|
||||
#endif
|
||||
}, 4,
|
||||
exePath, &exePathLen,
|
||||
@@ -46,7 +55,81 @@ static void getExePath(FFPlatform* platform)
|
||||
else
|
||||
exePathLen--; // remove terminating NUL
|
||||
#elif defined(__OpenBSD__)
|
||||
// OpenBSD doesn't have a reliable way to get the executable path.
|
||||
// Current implementation uses argv[0], which can be easily spoofed.
|
||||
// See #2195
|
||||
size_t exePathLen = 0;
|
||||
kvm_t* kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
if (kd)
|
||||
{
|
||||
int kpCount;
|
||||
struct kinfo_proc* kp = kvm_getprocs(kd, KERN_PROC_PID, (pid_t) platform->pid, sizeof(*kp), &kpCount);
|
||||
if (kp && kpCount == 1)
|
||||
{
|
||||
char** argv = kvm_getargv(kd, kp, 0);
|
||||
if (argv && argv[0])
|
||||
{
|
||||
char* arg0 = argv[0];
|
||||
if (arg0[0])
|
||||
{
|
||||
if (strchr(arg0, '/') != NULL) // likely a path (absolute or relative)
|
||||
{
|
||||
exePathLen = strlen(arg0);
|
||||
if (exePathLen < ARRAY_SIZE(exePath))
|
||||
{
|
||||
memcpy(exePath, arg0, exePathLen);
|
||||
exePath[exePathLen] = '\0';
|
||||
}
|
||||
else
|
||||
exePathLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY tmpPath = ffStrbufCreate();
|
||||
if (ffFindExecutableInPath(arg0, &tmpPath) == NULL && tmpPath.length < ARRAY_SIZE(exePath))
|
||||
{
|
||||
memcpy(exePath, tmpPath.chars, tmpPath.length + 1);
|
||||
exePathLen = tmpPath.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (exePathLen > 0)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(exePath, &st) == 0 && S_ISREG(st.st_mode))
|
||||
{
|
||||
int cntp;
|
||||
struct kinfo_file* kf = kvm_getfiles(kd, KERN_FILE_BYPID, platform->pid, sizeof(*kf), &cntp);
|
||||
if (kf)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cntp; i++)
|
||||
{
|
||||
if (kf[i].fd_fd == KERN_FILE_TEXT)
|
||||
{
|
||||
// KERN_FILE_TEXT is the executable file, not a shared library, and should be unique in the list.
|
||||
if (st.st_dev != (dev_t)kf[i].va_fsid || st.st_ino != (ino_t)kf[i].va_fileid)
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
exePathLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we can't get the list of open files, we can't verify that the file is actually the executable
|
||||
// Assume it is
|
||||
}
|
||||
}
|
||||
else
|
||||
exePathLen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
kvm_close(kd);
|
||||
}
|
||||
#elif defined(__sun)
|
||||
ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1);
|
||||
if (exePathLen >= 0)
|
||||
@@ -177,17 +260,16 @@ static void getDataDirs(FFPlatform* platform)
|
||||
|
||||
static void getUserName(FFPlatform* platform, const struct passwd* pwd)
|
||||
{
|
||||
const char* user = getenv("USER");
|
||||
if(!ffStrSet(user) && pwd)
|
||||
user = pwd->pw_name;
|
||||
|
||||
ffStrbufAppendS(&platform->userName, user);
|
||||
|
||||
if (pwd)
|
||||
{
|
||||
ffStrbufAppendS(&platform->fullUserName, pwd->pw_gecos);
|
||||
ffStrbufSetS(&platform->userName, pwd->pw_name);
|
||||
ffStrbufSetS(&platform->fullUserName, pwd->pw_gecos);
|
||||
ffStrbufTrimSpace(&platform->fullUserName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSetS(&platform->userName, getenv("USER"));
|
||||
}
|
||||
}
|
||||
|
||||
static void getHostName(FFPlatform* platform, const struct utsname* uts)
|
||||
@@ -225,15 +307,28 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void getCwd(FFPlatform* platform)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
if (getcwd(cwd, sizeof(cwd)) != NULL)
|
||||
{
|
||||
ffStrbufSetS(&platform->cwd, cwd);
|
||||
ffStrbufEnsureEndsWithC(&platform->cwd, '/');
|
||||
}
|
||||
}
|
||||
|
||||
void ffPlatformInitImpl(FFPlatform* platform)
|
||||
{
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
platform->pid = (uint32_t) getpid();
|
||||
platform->uid = getuid();
|
||||
struct passwd* pwd = getpwuid(platform->uid);
|
||||
|
||||
struct utsname uts;
|
||||
if(uname(&uts) < 0)
|
||||
memset(&uts, 0, sizeof(uts));
|
||||
|
||||
getExePath(platform);
|
||||
getCwd(platform);
|
||||
getHomeDir(platform, pwd);
|
||||
getCacheDir(platform);
|
||||
getConfigDirs(platform);
|
||||
@@ -1,13 +1,15 @@
|
||||
#include "FFPlatform_private.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/windows/nt.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/windows/unicode.h"
|
||||
#include "common/windows/registry.h"
|
||||
#include "common/windows/nt.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <sddl.h>
|
||||
|
||||
#define SECURITY_WIN32 1 // For secext.h
|
||||
#include <secext.h>
|
||||
@@ -70,15 +72,15 @@ static void getCacheDir(FFPlatform* platform)
|
||||
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
|
||||
{
|
||||
PWSTR pPath = NULL;
|
||||
if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT, NULL, &pPath)))
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath);
|
||||
CoTaskMemFree(pPath);
|
||||
ffStrbufReplaceAllC(&buffer, '\\', '/');
|
||||
ffStrbufEnsureEndsWithC(&buffer, '/');
|
||||
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
|
||||
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
|
||||
}
|
||||
CoTaskMemFree(pPath);
|
||||
}
|
||||
|
||||
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
|
||||
@@ -136,29 +138,51 @@ static void getDataDirs(FFPlatform* platform)
|
||||
|
||||
static void getUserName(FFPlatform* platform)
|
||||
{
|
||||
const char* userName = getenv("USERNAME");
|
||||
if (ffStrSet(userName))
|
||||
ffStrbufSetS(&platform->userName, userName);
|
||||
else
|
||||
{
|
||||
wchar_t buffer[256];
|
||||
DWORD len = ARRAY_SIZE(buffer);
|
||||
if(GetUserNameW(buffer, &len))
|
||||
ffStrbufSetWS(&platform->userName, buffer);
|
||||
}
|
||||
|
||||
wchar_t buffer[256];
|
||||
DWORD len = ARRAY_SIZE(buffer);
|
||||
if (GetUserNameExW(NameDisplay, buffer, &len))
|
||||
DWORD size = ARRAY_SIZE(buffer);
|
||||
if (GetUserNameExW(NameDisplay, buffer, &size))
|
||||
ffStrbufSetWS(&platform->fullUserName, buffer);
|
||||
|
||||
size = ARRAY_SIZE(buffer);
|
||||
if (GetUserNameW(buffer, &size)) // GetUserNameExW(10002)?
|
||||
{
|
||||
ffStrbufSetWS(&platform->userName, buffer);
|
||||
|
||||
size = 0;
|
||||
DWORD refDomainSize = 0;
|
||||
SID_NAME_USE sidNameUse = SidTypeUnknown;
|
||||
LookupAccountNameW(NULL, buffer, NULL, &size, NULL, &refDomainSize, &sidNameUse);
|
||||
if (size > 0)
|
||||
{
|
||||
FF_AUTO_FREE PSID sid = (PSID) malloc(size);
|
||||
FF_AUTO_FREE LPWSTR refDomain = (LPWSTR) malloc(refDomainSize * sizeof(wchar_t));
|
||||
if (LookupAccountNameW(NULL, buffer, sid, &size, refDomain, &refDomainSize, &sidNameUse))
|
||||
{
|
||||
LPWSTR sidString;
|
||||
if (ConvertSidToStringSidW(sid, &sidString))
|
||||
{
|
||||
ffStrbufSetWS(&platform->sid, sidString);
|
||||
LocalFree(sidString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ffStrbufSetS(&platform->userName, getenv("USERNAME"));
|
||||
}
|
||||
|
||||
static void getHostName(FFPlatform* platform)
|
||||
{
|
||||
wchar_t buffer[128];
|
||||
wchar_t buffer[256];
|
||||
DWORD len = ARRAY_SIZE(buffer);
|
||||
if(GetComputerNameExW(ComputerNameDnsHostname, buffer, &len))
|
||||
ffStrbufSetWS(&platform->hostName, buffer);
|
||||
if (GetComputerNameExW(ComputerNameDnsHostname, buffer, &len) && len > 0)
|
||||
ffStrbufSetNWS(&platform->hostName, len, buffer);
|
||||
else
|
||||
{
|
||||
len = ARRAY_SIZE(buffer);
|
||||
if (GetComputerNameExW(ComputerNameNetBIOS, buffer, &len) && len > 0)
|
||||
ffStrbufSetNWS(&platform->hostName, len, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void getUserShell(FFPlatform* platform)
|
||||
@@ -184,10 +208,6 @@ static const char* detectWine(void)
|
||||
|
||||
static void getSystemReleaseAndVersion(FFPlatformSysinfo* info)
|
||||
{
|
||||
RTL_OSVERSIONINFOW osVersion = { .dwOSVersionInfoSize = sizeof(osVersion) };
|
||||
if (!NT_SUCCESS(RtlGetVersion(&osVersion)))
|
||||
return;
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL))
|
||||
return;
|
||||
@@ -197,40 +217,41 @@ static void getSystemReleaseAndVersion(FFPlatformSysinfo* info)
|
||||
|
||||
ffStrbufAppendF(&info->release,
|
||||
"%u.%u.%u.%u",
|
||||
(unsigned) osVersion.dwMajorVersion,
|
||||
(unsigned) osVersion.dwMinorVersion,
|
||||
(unsigned) osVersion.dwBuildNumber,
|
||||
(unsigned) SharedUserData->NtMajorVersion,
|
||||
(unsigned) SharedUserData->NtMinorVersion,
|
||||
(unsigned) SharedUserData->NtBuildNumber,
|
||||
(unsigned) ubr);
|
||||
|
||||
ffRegReadStrbuf(hKey, L"BuildLabEx", &info->version, NULL);
|
||||
|
||||
const char* wineVersion = detectWine();
|
||||
if (wineVersion)
|
||||
ffStrbufSetF(&info->name, "Wine_%s", wineVersion);
|
||||
else
|
||||
{
|
||||
switch (osVersion.dwPlatformId)
|
||||
{
|
||||
case VER_PLATFORM_WIN32s:
|
||||
ffStrbufSetStatic(&info->name, "WIN32s");
|
||||
break;
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
ffStrbufSetStatic(&info->name, "WIN32_WINDOWS");
|
||||
break;
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
ffStrbufSetStatic(&info->name, "WIN32_NT");
|
||||
break;
|
||||
}
|
||||
if (instance.config.general.detectVersion)
|
||||
ffStrbufSetF(&info->name, "Wine_%s", wineVersion);
|
||||
else
|
||||
ffStrbufSetStatic(&info->name, "Wine");
|
||||
}
|
||||
else
|
||||
ffStrbufSetStatic(&info->name, "WIN32_NT");
|
||||
}
|
||||
|
||||
static void getSystemArchitectureAndPageSize(FFPlatformSysinfo* info)
|
||||
static void getSystemPageSize(FFPlatformSysinfo* info)
|
||||
{
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetNativeSystemInfo(&sysInfo);
|
||||
SYSTEM_BASIC_INFORMATION sbi;
|
||||
if (NT_SUCCESS(NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL)))
|
||||
info->pageSize = sbi.PhysicalPageSize;
|
||||
else
|
||||
info->pageSize = 4096;
|
||||
}
|
||||
|
||||
switch(sysInfo.wProcessorArchitecture)
|
||||
static void getSystemArchitecture(FFPlatformSysinfo* info)
|
||||
{
|
||||
SYSTEM_PROCESSOR_INFORMATION spi;
|
||||
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorInformation, &spi, sizeof(spi), NULL)))
|
||||
{
|
||||
switch (spi.ProcessorArchitecture)
|
||||
{
|
||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||
ffStrbufSetStatic(&info->architecture, "x86_64");
|
||||
break;
|
||||
@@ -238,7 +259,7 @@ static void getSystemArchitectureAndPageSize(FFPlatformSysinfo* info)
|
||||
ffStrbufSetStatic(&info->architecture, "ia64");
|
||||
break;
|
||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||
switch (sysInfo.wProcessorLevel)
|
||||
switch (spi.ProcessorLevel)
|
||||
{
|
||||
case 4:
|
||||
ffStrbufSetStatic(&info->architecture, "i486");
|
||||
@@ -276,14 +297,28 @@ static void getSystemArchitectureAndPageSize(FFPlatformSysinfo* info)
|
||||
default:
|
||||
ffStrbufSetStatic(&info->architecture, "unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info->pageSize = sysInfo.dwPageSize;
|
||||
static void getCwd(FFPlatform* platform)
|
||||
{
|
||||
#if _WIN64
|
||||
static_assert(
|
||||
offsetof(RTL_USER_PROCESS_PARAMETERS, Reserved2[5]) == 0x38,
|
||||
"CurrentDirectory should be at offset 0x38 in RTL_USER_PROCESS_PARAMETERS. Structure layout mismatch detected.");
|
||||
#endif
|
||||
PCURDIR cwd = (PCURDIR) &NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Reserved2[5];
|
||||
ffStrbufSetNWS(&platform->cwd, cwd->DosPath.Length / sizeof(WCHAR), cwd->DosPath.Buffer);
|
||||
ffStrbufReplaceAllC(&platform->cwd, '\\', '/');
|
||||
ffStrbufEnsureEndsWithC(&platform->cwd, '/');
|
||||
}
|
||||
|
||||
void ffPlatformInitImpl(FFPlatform* platform)
|
||||
{
|
||||
platform->pid = (uint32_t) GetCurrentProcessId();
|
||||
getExePath(platform);
|
||||
getCwd(platform);
|
||||
getHomeDir(platform);
|
||||
getCacheDir(platform);
|
||||
getConfigDirs(platform);
|
||||
@@ -294,5 +329,6 @@ void ffPlatformInitImpl(FFPlatform* platform)
|
||||
getUserShell(platform);
|
||||
|
||||
getSystemReleaseAndVersion(&platform->sysinfo);
|
||||
getSystemArchitectureAndPageSize(&platform->sysinfo);
|
||||
getSystemArchitecture(&platform->sysinfo);
|
||||
getSystemPageSize(&platform->sysinfo);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "FFlist.h"
|
||||
#include "common/FFlist.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "FFstrbuf.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
@@ -21,11 +22,27 @@ void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments)
|
||||
{
|
||||
assert(format != NULL);
|
||||
|
||||
int len = vasprintf(&strbuf->chars, format, arguments);
|
||||
char* buffer = NULL;
|
||||
int len = vasprintf(&buffer, format, arguments);
|
||||
assert(len >= 0);
|
||||
|
||||
strbuf->allocated = (uint32_t)(len + 1);
|
||||
strbuf->length = (uint32_t)len;
|
||||
ffStrbufInitMoveNS(strbuf, (uint32_t)len, buffer);
|
||||
}
|
||||
|
||||
// Takes ownership of `heapStr`. The caller must not free `heapStr` after calling this
|
||||
// function; the memory will be managed and freed via the associated FFstrbuf.
|
||||
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr)
|
||||
{
|
||||
assert(heapStr != NULL);
|
||||
|
||||
strbuf->length = length;
|
||||
size_t allocSize = ffMallocUsableSize(heapStr);
|
||||
if (allocSize == 0)
|
||||
allocSize = length + 1;
|
||||
else if (allocSize > UINT32_MAX)
|
||||
allocSize = UINT32_MAX;
|
||||
strbuf->allocated = (uint32_t) allocSize;
|
||||
strbuf->chars = heapStr;
|
||||
}
|
||||
|
||||
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free)
|
||||
@@ -55,6 +72,7 @@ void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free)
|
||||
strbuf->allocated = allocate;
|
||||
}
|
||||
|
||||
// Ensure that at least `free` bytes are available in the buffer besides the current length
|
||||
// for an empty buffer, free + 1 length memory will be allocated(+1 for the NUL)
|
||||
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free)
|
||||
{
|
||||
@@ -148,7 +166,7 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments)
|
||||
uint32_t free = ffStrbufGetFree(strbuf);
|
||||
int written = vsnprintf(strbuf->chars + strbuf->length, strbuf->allocated > 0 ? free + 1 : 0, format, arguments);
|
||||
|
||||
if(written > 0 && strbuf->length + (uint32_t) written > free)
|
||||
if(written > 0 && (uint32_t) written > free)
|
||||
{
|
||||
ffStrbufEnsureFree(strbuf, (uint32_t) written);
|
||||
written = vsnprintf(strbuf->chars + strbuf->length, (uint32_t) written + 1, format, copy);
|
||||
@@ -165,7 +183,7 @@ const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char unti
|
||||
if(value == NULL)
|
||||
return NULL;
|
||||
|
||||
char* end = strchr(value, until);
|
||||
const char* end = strchr(value, until);
|
||||
if(end == NULL)
|
||||
ffStrbufAppendS(strbuf, value);
|
||||
else
|
||||
@@ -220,6 +238,55 @@ void ffStrbufPrependC(FFstrbuf* strbuf, char c)
|
||||
strbuf->length += 1;
|
||||
}
|
||||
|
||||
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value)
|
||||
{
|
||||
assert(strbuf != NULL);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(value != NULL);
|
||||
|
||||
if (strbuf->allocated < length + 1)
|
||||
{
|
||||
if (strbuf->allocated > 0)
|
||||
free(strbuf->chars);
|
||||
strbuf->allocated = length + 1;
|
||||
strbuf->chars = malloc(sizeof(char) * strbuf->allocated);
|
||||
}
|
||||
|
||||
memcpy(strbuf->chars, value, length);
|
||||
strbuf->length = length;
|
||||
strbuf->chars[length] = '\0';
|
||||
}
|
||||
|
||||
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
|
||||
{
|
||||
assert(value && value != strbuf);
|
||||
|
||||
if (value->length == 0)
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value->allocated == 0) // static string
|
||||
{
|
||||
if (strbuf->allocated != 0)
|
||||
{
|
||||
free(strbuf->chars);
|
||||
strbuf->allocated = 0;
|
||||
}
|
||||
strbuf->chars = value->chars;
|
||||
strbuf->length = value->length;
|
||||
return;
|
||||
}
|
||||
ffStrbufSetNS(strbuf, value->length, value->chars);
|
||||
}
|
||||
|
||||
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c)
|
||||
{
|
||||
if(strbuf->length == 0)
|
||||
@@ -381,7 +448,15 @@ void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(strbuf, 0);
|
||||
for (char *current_pos = strchr(strbuf->chars, find); current_pos; current_pos = strchr(current_pos + 1, find))
|
||||
for (
|
||||
char *current_pos = memchr(strbuf->chars, find, strbuf->length);
|
||||
current_pos;
|
||||
current_pos = memchr(
|
||||
current_pos + 1,
|
||||
find,
|
||||
strbuf->length - (uint32_t)(current_pos + 1 - strbuf->chars)
|
||||
)
|
||||
)
|
||||
*current_pos = replace;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "base64.h"
|
||||
#include "common/base64.h"
|
||||
|
||||
// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145
|
||||
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "binary.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/binary.h"
|
||||
#include "common/io.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "binary.h"
|
||||
#include "common/binary.h"
|
||||
|
||||
#if defined(FF_HAVE_ELF) || defined(__sun) || (defined(__FreeBSD__) && !defined(__DragonFly__)) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <libelf.h> // #1254
|
||||
#include <fcntl.h>
|
||||
@@ -42,7 +42,7 @@ const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* s
|
||||
if (!elfData.inited)
|
||||
{
|
||||
elfData.inited = true;
|
||||
FF_LIBRARY_LOAD(libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_MESSAGE(libelf, "libelf" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_version)
|
||||
if (elfData.ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#include "binary.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/binary.h"
|
||||
#include "common/io.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/windows/nt.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <imagehlp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -17,19 +16,33 @@
|
||||
*/
|
||||
const char* ffBinaryExtractStrings(const char *peFile, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata, uint32_t minLength)
|
||||
{
|
||||
// Use MapAndLoad with cleanup attribute to ensure proper unloading
|
||||
__attribute__((__cleanup__(UnMapAndLoad))) LOADED_IMAGE loadedImage = {};
|
||||
if (!MapAndLoad(peFile, NULL, &loadedImage, FALSE, TRUE))
|
||||
return "File could not be loaded";
|
||||
FF_AUTO_CLOSE_FD HANDLE hFile = CreateFileA(peFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return "CreateFileA() failed";
|
||||
|
||||
// Iterate through all sections in the PE file
|
||||
for (ULONG i = 0; i < loadedImage.NumberOfSections; ++i)
|
||||
FF_AUTO_CLOSE_FD HANDLE hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (!hMap)
|
||||
return "CreateFileMappingW() failed";
|
||||
|
||||
void* base = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!base)
|
||||
return "MapViewOfFile() failed";
|
||||
|
||||
PIMAGE_NT_HEADERS ntHeaders = RtlImageNtHeader(base);
|
||||
if (!ntHeaders)
|
||||
{
|
||||
UnmapViewOfFile(base);
|
||||
return "RtlImageNtHeader() failed";
|
||||
}
|
||||
|
||||
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
|
||||
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i, ++section)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER section = &loadedImage.Sections[i];
|
||||
// Look for initialized data sections with the name ".rdata" which typically contains string literals
|
||||
if ((section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) && ffStrEquals((const char*) section->Name, ".rdata"))
|
||||
{
|
||||
uint8_t *data = (uint8_t *) loadedImage.MappedAddress + section->PointerToRawData;
|
||||
uint8_t *data = (uint8_t *) base + section->PointerToRawData;
|
||||
|
||||
// Scan the section for string literals
|
||||
for (size_t off = 0; off < section->SizeOfRawData; ++off)
|
||||
@@ -48,5 +61,6 @@ const char* ffBinaryExtractStrings(const char *peFile, bool (*cb)(const char *st
|
||||
}
|
||||
}
|
||||
|
||||
UnmapViewOfFile(base);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "commandoption.h"
|
||||
#include "common/commandoption.h"
|
||||
#include "common/color.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/time.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
@@ -61,7 +61,7 @@ bool ffParseModuleOptions(const char* key, const char* value)
|
||||
}
|
||||
fprintf(stderr, "Error: Unsupported module option: %s\n", key);
|
||||
fputs(" Support of module options has been removed. Please add the flag to the JSON config instead.\n", stderr);
|
||||
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ? value : "true", value ? "\"" : "");
|
||||
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ?: "true", value ? "\"" : "");
|
||||
fputs(" See <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for more information.\n", stderr);
|
||||
exit(477);
|
||||
}
|
||||
@@ -71,40 +71,66 @@ bool ffParseModuleOptions(const char* key, const char* value)
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
|
||||
char* moduleType = NULL;
|
||||
size_t moduleLen = 0;
|
||||
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
}
|
||||
#define FF_IF_MODULE_MATCH(moduleNameConstant) if (moduleLen == strlen(moduleNameConstant) \
|
||||
&& ffStrEqualsIgnCase(moduleType, moduleNameConstant) \
|
||||
&& !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':'))
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
}
|
||||
switch (moduleType[0])
|
||||
{
|
||||
case 'C': case 'c':
|
||||
FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
case 'D': case 'd':
|
||||
FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
}
|
||||
break;
|
||||
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
case 'N': case 'n':
|
||||
FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P': case 'p':
|
||||
FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'W': case 'w':
|
||||
FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#undef FF_IF_MODULE_MATCH
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
static void genJsonConfig(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
|
||||
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
|
||||
if (!modules)
|
||||
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
|
||||
@@ -112,7 +138,7 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&type);
|
||||
|
||||
if (instance.state.fullConfig)
|
||||
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
|
||||
@@ -131,8 +157,9 @@ static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
|
||||
static void genJsonResult(FFdata* data, FFModuleBaseInfo* baseInfo, void* options)
|
||||
{
|
||||
yyjson_mut_doc* doc = data->resultDoc;
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
@@ -142,9 +169,9 @@ static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_
|
||||
}
|
||||
|
||||
static void parseStructureCommand(
|
||||
FFdata* data,
|
||||
const char* line,
|
||||
void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc),
|
||||
yyjson_mut_doc* jsonDoc
|
||||
void (*fn)(FFdata*, FFModuleBaseInfo* baseInfo, void* options)
|
||||
)
|
||||
{
|
||||
if(ffCharIsEnglishAlphabet(line[0]))
|
||||
@@ -156,8 +183,8 @@ static void parseStructureCommand(
|
||||
{
|
||||
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
|
||||
baseInfo->initOptions(optionBuf);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn(baseInfo, optionBuf, jsonDoc);
|
||||
if (__builtin_expect(data->resultDoc != NULL, false))
|
||||
fn(data, baseInfo, optionBuf);
|
||||
else
|
||||
baseInfo->printModule(optionBuf);
|
||||
baseInfo->destroyOptions(optionBuf);
|
||||
@@ -169,30 +196,32 @@ static void parseStructureCommand(
|
||||
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
void ffPrintCommandOption(FFdata* data)
|
||||
{
|
||||
//Parse the structure and call the modules
|
||||
int32_t thres = instance.config.display.stat;
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
|
||||
char* moduleType = NULL;
|
||||
size_t moduleLen = 0;
|
||||
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':'))
|
||||
continue;
|
||||
|
||||
double ms = 0;
|
||||
if(thres >= 0)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, genJsonResult, jsonDoc);
|
||||
parseStructureCommand(data, moduleType, genJsonResult);
|
||||
|
||||
if(thres >= 0)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (jsonDoc)
|
||||
if (data->resultDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(data->resultDoc->root);
|
||||
yyjson_mut_obj_add_real(data->resultDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -205,28 +234,24 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
|
||||
if (!data->resultDoc && !instance.config.display.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
char* moduleType = NULL;
|
||||
size_t moduleLen = 0;
|
||||
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure))
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':'))
|
||||
continue;
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, genJsonConfig, jsonDoc);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
parseStructureCommand(data, moduleType, genJsonConfig);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "dbus.h"
|
||||
#include "common/dbus.h"
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
|
||||
#include "common/thread.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
static bool loadLibSymbols(FFDBusLibrary* lib)
|
||||
{
|
||||
@@ -19,6 +19,7 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_unref, false)
|
||||
dbus = NULL; // don't auto dlclose
|
||||
return true;
|
||||
}
|
||||
@@ -51,6 +52,15 @@ const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffDBusDestroyData(FFDBusData* data)
|
||||
{
|
||||
if (data->connection != NULL)
|
||||
{
|
||||
data->lib->ffdbus_connection_unref(data->connection);
|
||||
data->connection = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
|
||||
{
|
||||
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "debug.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "duration.h"
|
||||
#include "common/duration.h"
|
||||
|
||||
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result)
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "edidHelper.h"
|
||||
#include "common/edidHelper.h"
|
||||
|
||||
void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height)
|
||||
{
|
||||
@@ -0,0 +1,520 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/FFlist.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void ffFontInit(FFfont* font)
|
||||
{
|
||||
// Ensure no memory allocates
|
||||
ffStrbufInit(&font->pretty);
|
||||
ffStrbufInit(&font->name);
|
||||
ffStrbufInit(&font->size);
|
||||
ffListInit(&font->styles, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
static void strbufAppendNSExcludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude)
|
||||
{
|
||||
if(value == NULL || length == 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(strbuf, length);
|
||||
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
if(value[i] != exclude)
|
||||
strbuf->chars[strbuf->length++] = value[i];
|
||||
}
|
||||
|
||||
strbuf->chars[strbuf->length] = '\0';
|
||||
}
|
||||
|
||||
static void fontInitPretty(FFfont* font)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->name);
|
||||
|
||||
if(font->size.length == 0 && font->styles.length == 0)
|
||||
return;
|
||||
else if(font->pretty.length == 0)
|
||||
ffStrbufAppendS(&font->pretty, "default");
|
||||
|
||||
ffStrbufAppendS(&font->pretty, " (");
|
||||
|
||||
if(font->size.length > 0)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, &font->size);
|
||||
if (!ffStrbufEndsWithS(&font->size, "pt") && !ffStrbufEndsWithS(&font->size, "px"))
|
||||
ffStrbufAppendS(&font->pretty, "pt");
|
||||
|
||||
if(font->styles.length > 0)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, FF_LIST_GET(FFstrbuf, font->styles, i));
|
||||
|
||||
if(i < font->styles.length - 1)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&font->pretty, ')');
|
||||
}
|
||||
|
||||
void ffFontInitQt(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
//See https://doc.qt.io/qt-5/qfont.html#toString
|
||||
|
||||
//Family
|
||||
data = ffStrbufAppendSUntilC(&font->name, data, ',');
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Size
|
||||
data = ffStrbufAppendSUntilC(&font->size, data, ',');
|
||||
ffStrbufTrim(&font->size, ' ');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
|
||||
//Style
|
||||
data = strrchr(data, ',');
|
||||
if (!data) goto exit;
|
||||
data++;
|
||||
if (isalpha(*data))
|
||||
{
|
||||
do
|
||||
{
|
||||
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
} while (data);
|
||||
}
|
||||
|
||||
exit:
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* alternativeBuffer)
|
||||
{
|
||||
while(**data == ' ' || **data == '\t' || **data == ',')
|
||||
++(*data);
|
||||
|
||||
const char* wordStart = *data;
|
||||
|
||||
while(**data != ' ' && **data != '\t' && **data != ',' && **data != '\0' && **data != '`' && **data != '\\')
|
||||
++(*data);
|
||||
|
||||
uint32_t wordLength = (uint32_t) (*data - wordStart);
|
||||
if(wordLength == 0)
|
||||
return;
|
||||
|
||||
if(**data == '\0' || **data == '`' || **data == '\\')
|
||||
{
|
||||
ffStrbufAppendNS(&font->size, wordLength, wordStart);
|
||||
if(ffStrbufEndsWithS(&font->size, "px"))
|
||||
ffStrbufSubstrBefore(&font->size, font->size.length - 2);
|
||||
|
||||
double dummy;
|
||||
if(sscanf(font->size.chars, "%lf", &dummy) == 1)
|
||||
return;
|
||||
|
||||
ffStrbufClear(&font->size);
|
||||
}
|
||||
|
||||
if(
|
||||
ffStrStartsWithIgnCase(wordStart, "Ultra") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Extra") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Semi") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Demi") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Normal") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Roman") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Oblique") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Italic") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Thin") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Light") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Bold") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Black") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Condensed") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Expanded")
|
||||
) {
|
||||
if(alternativeBuffer == NULL)
|
||||
{
|
||||
alternativeBuffer = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(alternativeBuffer);
|
||||
}
|
||||
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
|
||||
if(
|
||||
ffStrStartsWithIgnCase(wordStart, "Ultra ") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Extra ") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Semi ") ||
|
||||
ffStrStartsWithIgnCase(wordStart, "Demi ")
|
||||
) {
|
||||
fontPangoParseWord(data, font, alternativeBuffer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(alternativeBuffer != NULL)
|
||||
{
|
||||
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
|
||||
return;
|
||||
}
|
||||
|
||||
if(font->name.length > 0)
|
||||
ffStrbufAppendC(&font->name, ' ');
|
||||
ffStrbufAppendNS(&font->name, wordLength, wordStart);
|
||||
}
|
||||
|
||||
void ffFontInitPango(FFfont* font, const char* data)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
while(*data != '\0' && *data != '`' && *data != '\\')
|
||||
fontPangoParseWord(&data, font, NULL);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendS(&font->name, name);
|
||||
ffStrbufTrim(&font->name, '"');
|
||||
ffStrbufAppendS(&font->size, size);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitXlfd(FFfont* font, const char* xlfd)
|
||||
{
|
||||
assert(xlfd && *xlfd);
|
||||
|
||||
// https://en.wikipedia.org/wiki/X_logical_font_description
|
||||
ffFontInit(font);
|
||||
|
||||
// XLFD: -foundry-family-weight-slant-setwidth-addstyle-pixelsize-pointsize-xres-yres-spacing-averagewidth-charsetregistry-charsetencoding
|
||||
// It often starts with '-', which would create an empty first field. Skip it to align indexes.
|
||||
if(*xlfd == '-')
|
||||
xlfd++;
|
||||
|
||||
const char* pstart = xlfd;
|
||||
|
||||
for(int field = 0; field < 14; field++)
|
||||
{
|
||||
const char* pend = strchr(pstart, '-');
|
||||
uint32_t length = pend ? (uint32_t)(pend - pstart) : (uint32_t) strlen(pstart);
|
||||
|
||||
if(length > 0)
|
||||
{
|
||||
if(field == 1) // family
|
||||
{
|
||||
ffStrbufAppendNS(&font->name, length, pstart);
|
||||
}
|
||||
else if(field == 7) // pointsize (decipoints, preferred)
|
||||
{
|
||||
// parse positive integer from substring
|
||||
long deciPt = 0;
|
||||
bool ok = true;
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
char c = pstart[i];
|
||||
if(c < '0' || c > '9') { ok = false; break; }
|
||||
deciPt = deciPt * 10 + (c - '0');
|
||||
}
|
||||
|
||||
if(ok && deciPt > 0)
|
||||
{
|
||||
ffStrbufClear(&font->size);
|
||||
|
||||
char tmp[32];
|
||||
if(deciPt % 10 == 0)
|
||||
snprintf(tmp, sizeof(tmp), "%ldpt", deciPt / 10);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "%ld.%ldpt", deciPt / 10, deciPt % 10);
|
||||
|
||||
ffStrbufAppendS(&font->size, tmp);
|
||||
}
|
||||
}
|
||||
else if(field == 6) // pixelsize (fallback if pointsize missing/invalid)
|
||||
{
|
||||
if(font->size.length == 0)
|
||||
{
|
||||
long px = 0;
|
||||
bool ok = true;
|
||||
for(uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
char c = pstart[i];
|
||||
if(c < '0' || c > '9') { ok = false; break; }
|
||||
px = px * 10 + (c - '0');
|
||||
}
|
||||
|
||||
if(ok && px > 0)
|
||||
{
|
||||
ffStrbufAppendNS(&font->size, length, pstart);
|
||||
ffStrbufAppendS(&font->size, "px");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(field >= 2 && field <= 5) // weight/slant/setwidth/addstyle
|
||||
{
|
||||
// ignore "normal" (case-insensitive)
|
||||
if(!(length == 6 && ffStrStartsWithIgnCase(pstart, "normal")))
|
||||
{
|
||||
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInitNS(style, length, pstart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!pend)
|
||||
break;
|
||||
|
||||
pstart = pend + 1;
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitXft(FFfont* font, const char* xft)
|
||||
{
|
||||
assert(xft);
|
||||
|
||||
// https://en.wikipedia.org/wiki/Xft
|
||||
// Xft/Fontconfig pattern examples:
|
||||
// "DejaVu Sans Mono-10"
|
||||
// "monospace:size=10:weight=bold:slant=italic"
|
||||
// "Fira Code-12:style=Regular"
|
||||
// Goal: extract family(name), size, and some common styles.
|
||||
|
||||
ffFontInit(font);
|
||||
|
||||
// 1) Parse "head" part before first ':' => usually "family[-size]" (may include commas)
|
||||
const char* p = xft;
|
||||
|
||||
while(*p == ' ' || *p == '\t')
|
||||
++p;
|
||||
|
||||
const char* headStart = p;
|
||||
while(*p != '\0' && *p != ':')
|
||||
++p;
|
||||
const char* headEnd = p;
|
||||
|
||||
// trim tail spaces
|
||||
while(headEnd > headStart && (headEnd[-1] == ' ' || headEnd[-1] == '\t'))
|
||||
--headEnd;
|
||||
|
||||
// If multiple families are listed, take the first one (up to comma)
|
||||
for(const char* q = headStart; q < headEnd; ++q)
|
||||
{
|
||||
if(*q == ',')
|
||||
{
|
||||
headEnd = q;
|
||||
while(headEnd > headStart && (headEnd[-1] == ' ' || headEnd[-1] == '\t'))
|
||||
--headEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Try parse trailing "-<number>" as size, otherwise entire head is name
|
||||
const char* dashPos = NULL;
|
||||
const char* sizeStart = NULL;
|
||||
|
||||
for(const char* q = headEnd; q > headStart; )
|
||||
{
|
||||
--q;
|
||||
if(*q == '-' && (q + 1) < headEnd && ffCharIsDigit(q[1]))
|
||||
{
|
||||
dashPos = q;
|
||||
sizeStart = q + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dashPos)
|
||||
{
|
||||
bool ok = true;
|
||||
bool seenDigit = false;
|
||||
for(const char* q = sizeStart; q < headEnd; ++q)
|
||||
{
|
||||
if(ffCharIsDigit(*q))
|
||||
seenDigit = true;
|
||||
else if(*q == '.')
|
||||
continue;
|
||||
else
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok && seenDigit)
|
||||
{
|
||||
const char* nameEnd = dashPos;
|
||||
while(nameEnd > headStart && (nameEnd[-1] == ' ' || nameEnd[-1] == '\t'))
|
||||
--nameEnd;
|
||||
|
||||
if(nameEnd > headStart)
|
||||
ffStrbufAppendNS(&font->name, (uint32_t) (nameEnd - headStart), headStart);
|
||||
|
||||
if(headEnd > sizeStart)
|
||||
ffStrbufAppendNS(&font->size, (uint32_t) (headEnd - sizeStart), sizeStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(headEnd > headStart)
|
||||
ffStrbufAppendNS(&font->name, (uint32_t) (headEnd - headStart), headStart);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(headEnd > headStart)
|
||||
ffStrbufAppendNS(&font->name, (uint32_t) (headEnd - headStart), headStart);
|
||||
}
|
||||
|
||||
ffStrbufTrim(&font->name, ' ');
|
||||
ffStrbufTrim(&font->name, '"');
|
||||
|
||||
// 2) Parse key=value fields after ':' (Fontconfig-like). Fields separated by ':'.
|
||||
// Common keys: size, pixelsize, pointsize, style, weight, slant, width
|
||||
while(*p == ':')
|
||||
{
|
||||
++p;
|
||||
|
||||
// key
|
||||
const char* keyStart = p;
|
||||
while(*p != '\0' && *p != '=' && *p != ':')
|
||||
++p;
|
||||
const char* keyEnd = p;
|
||||
|
||||
if(*p != '=')
|
||||
continue; // skip tokens without '='
|
||||
|
||||
++p; // skip '='
|
||||
|
||||
// value (until next ':', allow backslash-escaping)
|
||||
FF_STRBUF_AUTO_DESTROY value = ffStrbufCreate();
|
||||
|
||||
while(*p != '\0' && *p != ':')
|
||||
{
|
||||
if(*p == '\\' && p[1] != '\0')
|
||||
{
|
||||
++p;
|
||||
ffStrbufAppendC(&value, *p);
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&value, *p);
|
||||
++p;
|
||||
}
|
||||
|
||||
ffStrbufTrim(&value, ' ');
|
||||
ffStrbufTrim(&value, '"');
|
||||
|
||||
uint32_t keyLen = (uint32_t) (keyEnd - keyStart);
|
||||
|
||||
// helper: set numeric size if not set yet
|
||||
const bool sizeEmpty = (font->size.length == 0);
|
||||
if(value.length > 0)
|
||||
{
|
||||
if(
|
||||
(keyLen == 4 && ffStrStartsWithIgnCase(keyStart, "size")) ||
|
||||
(keyLen == 9 && ffStrStartsWithIgnCase(keyStart, "pixelsize"))
|
||||
)
|
||||
{
|
||||
if(sizeEmpty && ffCharIsDigit(value.chars[0]))
|
||||
{
|
||||
ffStrbufAppend(&font->size, &value);
|
||||
ffStrbufAppendS(&font->size, keyLen == 4 ? "pt" : "px");
|
||||
}
|
||||
}
|
||||
else if(keyLen == 5 && ffStrStartsWithIgnCase(keyStart, "style"))
|
||||
{
|
||||
// style may contain multiple words: "Bold Italic"
|
||||
const char* s = value.chars;
|
||||
while(*s != '\0')
|
||||
{
|
||||
while(*s == ' ' || *s == '\t' || *s == ',')
|
||||
++s;
|
||||
|
||||
const char* w = s;
|
||||
while(*s != '\0' && *s != ' ' && *s != '\t' && *s != ',')
|
||||
++s;
|
||||
|
||||
if(s > w)
|
||||
{
|
||||
FFstrbuf* style = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInitNS(style, (uint32_t) (s - w), w);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(
|
||||
(keyLen == 6 && ffStrStartsWithIgnCase(keyStart, "weight")) ||
|
||||
(keyLen == 5 && ffStrStartsWithIgnCase(keyStart, "slant")) ||
|
||||
(keyLen == 5 && ffStrStartsWithIgnCase(keyStart, "width"))
|
||||
) {
|
||||
// normalize: remove '-' to align with other parsers ("Semi-Bold" -> "SemiBold")
|
||||
FFstrbuf* style = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInit(style);
|
||||
strbufAppendNSExcludingC(style, value.length, value.chars, '-');
|
||||
ffStrbufTrim(style, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
if (name) ffStrbufInitMove(&font->name, name);
|
||||
if (size) ffStrbufInitMove(&font->size, size);
|
||||
if (style)
|
||||
{
|
||||
FFstrbuf* styleBuf = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInitMove(styleBuf, style);
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||
{
|
||||
const char* pspace = strrchr(rawName, ' ');
|
||||
if(pspace == NULL)
|
||||
{
|
||||
ffFontInitCopy(font, rawName);
|
||||
return;
|
||||
}
|
||||
|
||||
ffFontInit(font);
|
||||
|
||||
ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName);
|
||||
ffStrbufAppendS(&font->size, pspace + 1);
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontDestroy(FFfont* font)
|
||||
{
|
||||
ffStrbufDestroy(&font->pretty);
|
||||
ffStrbufDestroy(&font->name);
|
||||
ffStrbufDestroy(&font->size);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, font->styles)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&font->styles);
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/textModifier.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -87,7 +87,7 @@ static uint32_t getArgumentIndex(const char* placeholderValue, uint32_t numArgs,
|
||||
for (uint32_t i = 0; i < numArgs; ++i)
|
||||
{
|
||||
const FFformatarg* arg = &arguments[i];
|
||||
if (arg->name && strcasecmp(placeholderValue, arg->name) == 0)
|
||||
if (arg->name && ffStrEqualsIgnCase(placeholderValue, arg->name))
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
|
||||
// testing for an invalid index
|
||||
if (index > numArgs)
|
||||
if (index > numArgs || index < 1)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{?", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
@@ -230,7 +230,7 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
|
||||
// testing for an invalid index
|
||||
if (index > numArgs)
|
||||
if (index > numArgs || index < 1)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{/", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "frequency.h"
|
||||
#include "common/frequency.h"
|
||||
|
||||
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result)
|
||||
{
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "common/init.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/textModifier.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "detection/terminaltheme/terminaltheme.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "logo/logo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <locale.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include "util/windows/unicode.h"
|
||||
#include "common/windows/unicode.h"
|
||||
#else
|
||||
#include <signal.h>
|
||||
#endif
|
||||
@@ -28,8 +28,6 @@ static void initState(FFstate* state)
|
||||
state->titleFqdn = false;
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
state->dynamicInterval = 0;
|
||||
|
||||
{
|
||||
@@ -96,8 +94,8 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
|
||||
void ffStart(void)
|
||||
{
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe;
|
||||
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
@@ -124,7 +122,7 @@ void ffStart(void)
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
if(!instance.config.display.pipe && !instance.state.resultDoc)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
@@ -138,8 +136,6 @@ void ffStart(void)
|
||||
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
ffLogoPrint();
|
||||
}
|
||||
|
||||
void ffFinish(void)
|
||||
@@ -157,9 +153,6 @@ static void destroyConfig(void)
|
||||
static void destroyState(void)
|
||||
{
|
||||
ffPlatformDestroy(&instance.state.platform);
|
||||
yyjson_doc_free(instance.state.configDoc);
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
ffStrbufDestroy(&instance.state.genConfigPath);
|
||||
}
|
||||
|
||||
void ffDestroyInstance(void)
|
||||
@@ -232,9 +225,6 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_FREETYPE
|
||||
"freetype\n"
|
||||
#endif
|
||||
#if FF_HAVE_PCIACCESS
|
||||
"libpciaccess\n"
|
||||
#endif
|
||||
#if FF_HAVE_PULSE
|
||||
"libpulse\n"
|
||||
#endif
|
||||
@@ -262,6 +252,12 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_EMBEDDED_PCIIDS
|
||||
"Embedded pciids\n"
|
||||
#endif
|
||||
#if FF_WIN7_COMPAT
|
||||
"Windows 7 Compatibility\n"
|
||||
#endif
|
||||
#if FF_APPLE_MEMSIZE_USABLE
|
||||
"Apple memsize_usable\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "io.h"
|
||||
#include "common/io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
@@ -23,7 +23,7 @@ static void createSubfolders(const char* fileName)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
|
||||
char *token = NULL;
|
||||
const char *token = NULL;
|
||||
while((token = strchr(fileName, '/')) != NULL)
|
||||
{
|
||||
ffStrbufAppendNS(&path, (uint32_t)(token - fileName + 1), fileName);
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "io.h"
|
||||
#include "common/io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "util/windows/nt.h"
|
||||
#include "common/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
@@ -2,11 +2,11 @@
|
||||
#include "common/color.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
#include "common/time.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@@ -230,9 +230,10 @@ static bool matchesJsonArray(const char* str, yyjson_val* val)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
static const char* printJsonConfig(FFdata* data, bool prepare)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
yyjson_mut_doc* jsonDoc = data->resultDoc;
|
||||
yyjson_val* const root = yyjson_doc_get_root(data->configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
@@ -298,6 +299,9 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
else
|
||||
return "modules must be an array of strings or objects";
|
||||
|
||||
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, type, ':'))
|
||||
continue;
|
||||
|
||||
if(prepare)
|
||||
prepareModuleJsonObject(type, module);
|
||||
else
|
||||
@@ -329,9 +333,10 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
void ffPrintJsonConfig(FFdata* data, bool prepare)
|
||||
{
|
||||
const char* error = printJsonConfig(prepare, jsonDoc);
|
||||
yyjson_mut_doc* jsonDoc = data->resultDoc;
|
||||
const char* error = printJsonConfig(data, prepare);
|
||||
if (error)
|
||||
{
|
||||
if (jsonDoc)
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "common/kmod.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
#include <IOKit/kext/KextManager.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, modName, kCFStringEncodingUTF8);
|
||||
FF_CFTYPE_AUTO_RELEASE CFArrayRef identifiers = CFArrayCreate(kCFAllocatorDefault, (const void**) &name, 1, &kCFTypeArrayCallBacks);
|
||||
FF_CFTYPE_AUTO_RELEASE CFArrayRef keys = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL);
|
||||
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef kextInfo = KextManagerCopyLoadedKextInfo(identifiers, keys);
|
||||
return CFDictionaryContainsKey(kextInfo, name);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "common/kmod.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
return modfind(modName) >= 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "common/kmod.h"
|
||||
#include "common/io.h"
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
static FFstrbuf modules;
|
||||
if (modules.chars == NULL)
|
||||
{
|
||||
ffStrbufInitS(&modules, "\n");
|
||||
ffAppendFileBuffer("/proc/modules", &modules);
|
||||
}
|
||||
|
||||
if (modules.length == 0) return false;
|
||||
|
||||
uint32_t len = (uint32_t) strlen(modName);
|
||||
if (len > 250) return false;
|
||||
|
||||
char temp[256];
|
||||
temp[0] = '\n';
|
||||
memcpy(temp + 1, modName, len);
|
||||
temp[1 + len] = ' ';
|
||||
return memmem(modules.chars, modules.length, temp, len + 2) != NULL;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "common/kmod.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
typedef struct __attribute__((__packed__)) FFNbsdModList
|
||||
{
|
||||
int len;
|
||||
modstat_t mods[];
|
||||
} FFNbsdModList;
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
static FFNbsdModList* list = NULL;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
struct iovec iov = {};
|
||||
|
||||
for (size_t len = 8192;; len = iov.iov_len)
|
||||
{
|
||||
iov.iov_len = len;
|
||||
iov.iov_base = realloc(iov.iov_base, len);
|
||||
if (modctl(MODCTL_STAT, &iov) < 0)
|
||||
{
|
||||
free(iov.iov_base);
|
||||
return true; // ignore errors
|
||||
}
|
||||
|
||||
if (len >= iov.iov_len) break;
|
||||
}
|
||||
list = (FFNbsdModList*) iov.iov_base;
|
||||
}
|
||||
|
||||
for (int i = 0; i < list->len; i++)
|
||||
{
|
||||
if (ffStrEquals(list->mods[i].ms_name, modName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "common/kmod.h"
|
||||
|
||||
bool ffKmodLoaded(FF_MAYBE_UNUSED const char* modName)
|
||||
{
|
||||
return true; // Don't generate kernel module related errors
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "common/kmod.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <sys/modctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
struct modinfo modinfo = {
|
||||
.mi_id = -1,
|
||||
.mi_nextid = -1,
|
||||
.mi_info = MI_INFO_ALL,
|
||||
};
|
||||
|
||||
for (int id = -1; modctl(MODINFO, id, &modinfo) == 0; id = modinfo.mi_id)
|
||||
{
|
||||
modinfo.mi_name[MODMAXNAMELEN - 1] = '\0';
|
||||
|
||||
if (ffStrEquals(modinfo.mi_name, modName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return !(errno == EINVAL || errno == ENOENT);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "common/kmod.h"
|
||||
#include "common/windows/nt.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
ULONG bufferSize = 0;
|
||||
NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &bufferSize);
|
||||
if (bufferSize == 0)
|
||||
return true; // ignore errors
|
||||
|
||||
FF_AUTO_FREE RTL_PROCESS_MODULES* buffer = malloc(bufferSize);
|
||||
|
||||
if (!NT_SUCCESS(NtQuerySystemInformation(SystemModuleInformation, buffer, bufferSize, &bufferSize)))
|
||||
return true; // ignore errors
|
||||
|
||||
for (ULONG i = 0; i < buffer->NumberOfModules; i++)
|
||||
{
|
||||
const char* name = (const char*) buffer->Modules[i].FullPathName + buffer->Modules[i].OffsetToFileName;
|
||||
|
||||
if (ffStrEqualsIgnCase(name, modName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "common/memrchr.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void* memrchr(const void* s, int c, size_t n)
|
||||
{
|
||||
if (n == 0) return NULL;
|
||||
|
||||
const uint8_t uc = (uint8_t) c;
|
||||
|
||||
const uint8_t* p = (const uint8_t*) s + n;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (*--p == uc) return (void*) p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "netif.h"
|
||||
#include "common/netif.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <net/if.h>
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "netif.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
@@ -73,7 +72,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
int pid = getpid();
|
||||
uint32_t pid = instance.state.platform.pid;
|
||||
|
||||
struct {
|
||||
struct rt_msghdr hdr;
|
||||
@@ -86,7 +85,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
.rtm_version = RTM_VERSION,
|
||||
.rtm_addrs = RTA_DST | RTA_IFP | RTA_IFA,
|
||||
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
|
||||
.rtm_pid = pid,
|
||||
.rtm_pid = (pid_t) pid,
|
||||
.rtm_seq = 1,
|
||||
},
|
||||
.dst = {
|
||||
@@ -100,7 +99,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
if (send(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen, 0) != rtmsg.hdr.rtm_msglen)
|
||||
return false;
|
||||
|
||||
while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid))
|
||||
while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == (pid_t) pid))
|
||||
;
|
||||
|
||||
#ifndef __sun // On Solaris, the RTF_GATEWAY flag is not set for default routes for some reason
|
||||
@@ -146,7 +145,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
int pid = getpid();
|
||||
uint32_t pid = instance.state.platform.pid;
|
||||
|
||||
struct {
|
||||
struct rt_msghdr hdr;
|
||||
@@ -159,7 +158,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
.rtm_version = RTM_VERSION,
|
||||
.rtm_addrs = RTA_DST | RTA_IFP,
|
||||
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
|
||||
.rtm_pid = pid,
|
||||
.rtm_pid = (pid_t) pid,
|
||||
.rtm_seq = 2,
|
||||
},
|
||||
.dst = {
|
||||
@@ -173,7 +172,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
if (send(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen, 0) != rtmsg.hdr.rtm_msglen)
|
||||
return false;
|
||||
|
||||
while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 2 && rtmsg.hdr.rtm_pid == pid))
|
||||
while (recv(pfRoute, &rtmsg, sizeof(rtmsg), 0) > 0 && !(rtmsg.hdr.rtm_seq == 2 && rtmsg.hdr.rtm_pid == (pid_t) pid))
|
||||
;
|
||||
|
||||
#ifndef __sun // On Solaris, the RTF_GATEWAY flag is not set for default routes for some reason
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "netif.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
@@ -19,7 +19,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
}
|
||||
FF_DEBUG("Created netlink socket: fd=%d", sock_fd);
|
||||
|
||||
unsigned pid = (unsigned) getpid();
|
||||
uint32_t pid = instance.state.platform.pid;
|
||||
FF_DEBUG("Process PID: %u", pid);
|
||||
|
||||
// Bind socket
|
||||
@@ -151,6 +151,12 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip local/loopback routes
|
||||
if (rtm->rtm_scope == RT_SCOPE_HOST || rtm->rtm_type == RTN_LOCAL) {
|
||||
FF_DEBUG("Skipping local route #%d (scope=%d, type=%d)", routeCount, rtm->rtm_scope, rtm->rtm_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_DEBUG("Processing IPv4 default route candidate #%d", routeCount);
|
||||
entry = (__typeof__(entry)) { }; // Default to zero metric (no RTA_PRIORITY found)
|
||||
|
||||
@@ -229,7 +235,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
}
|
||||
FF_DEBUG("Created netlink socket: fd=%d", sock_fd);
|
||||
|
||||
unsigned pid = (unsigned) getpid();
|
||||
uint32_t pid = instance.state.platform.pid;
|
||||
FF_DEBUG("Process PID: %u", pid);
|
||||
|
||||
// Bind socket
|
||||
@@ -360,6 +366,12 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip local/loopback routes
|
||||
if (rtm->rtm_scope == RT_SCOPE_HOST || rtm->rtm_type == RTN_LOCAL) {
|
||||
FF_DEBUG("Skipping local route #%d (scope=%d, type=%d)", routeCount, rtm->rtm_scope, rtm->rtm_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_DEBUG("Processing IPv6 default route candidate #%d", routeCount);
|
||||
entry = (__typeof__(entry)) { }; // Default to zero metric (no RTA_PRIORITY found)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/netif.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <ws2tcpip.h> // AF_INET6, IN6_IS_ADDR_UNSPECIFIED
|
||||
#include <iphlpapi.h>
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/library.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
#include "common/networking.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
@@ -12,7 +12,6 @@ struct FFZlibLibrary
|
||||
FF_LIBRARY_SYMBOL(inflateInit2_)
|
||||
FF_LIBRARY_SYMBOL(inflate)
|
||||
FF_LIBRARY_SYMBOL(inflateEnd)
|
||||
FF_LIBRARY_SYMBOL(inflateGetHeader)
|
||||
|
||||
bool inited;
|
||||
} zlibData;
|
||||
@@ -22,7 +21,7 @@ const char* ffNetworkingLoadZlibLibrary(void)
|
||||
if (!zlibData.inited)
|
||||
{
|
||||
zlibData.inited = true;
|
||||
FF_LIBRARY_LOAD(zlib, "dlopen libz failed",
|
||||
FF_LIBRARY_LOAD_MESSAGE(zlib,
|
||||
#ifdef _WIN32
|
||||
"zlib1"
|
||||
#else
|
||||
@@ -32,7 +31,6 @@ const char* ffNetworkingLoadZlibLibrary(void)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateInit2_)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflate)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateEnd)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateGetHeader)
|
||||
zlib = NULL; // don't auto dlclose
|
||||
}
|
||||
return zlibData.ffinflateEnd == NULL ? "Failed to load libz" : NULL;
|
||||
@@ -69,6 +67,8 @@ static uint32_t guessGzipOutputSize(const void* data, uint32_t dataSize)
|
||||
// Decompress gzip content
|
||||
bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
{
|
||||
assert(headerEnd != NULL && *headerEnd == '\r');
|
||||
|
||||
// Calculate header size
|
||||
uint32_t headerSize = (uint32_t) (headerEnd - buffer->chars);
|
||||
|
||||
@@ -86,15 +86,15 @@ bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
|
||||
const char* bodyStart = headerEnd + 4; // Skip delimiter
|
||||
|
||||
// Calculate compressed content size
|
||||
uint32_t compressedSize = buffer->length - headerSize - 4;
|
||||
|
||||
if (compressedSize <= 0) {
|
||||
if (buffer->length <= headerSize + 4) {
|
||||
// No content to decompress
|
||||
FF_DEBUG("Compressed content size is 0, skipping decompression");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate compressed content size
|
||||
uint32_t compressedSize = buffer->length - headerSize - 4;
|
||||
|
||||
// Check if content is actually in gzip format (gzip header magic is 0x1f 0x8b)
|
||||
if (compressedSize < 2 || (uint8_t)bodyStart[0] != 0x1f || (uint8_t)bodyStart[1] != 0x8b) {
|
||||
FF_DEBUG("Content is not valid gzip format, skipping decompression");
|
||||
@@ -137,7 +137,7 @@ bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
// Save already decompressed data amount
|
||||
uint32_t alreadyDecompressed = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += alreadyDecompressed;
|
||||
decompressedBuffer.chars[decompressedBuffer.length] = '\0'; // Ensure null-terminated string
|
||||
decompressedBuffer.chars[decompressedBuffer.length] = '\0';
|
||||
|
||||
ffStrbufEnsureFree(&decompressedBuffer, decompressedBuffer.length / 2);
|
||||
|
||||
@@ -155,7 +155,7 @@ bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
// Calculate decompressed size
|
||||
uint32_t decompressedSize = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += decompressedSize;
|
||||
decompressedBuffer.chars[decompressedSize] = '\0'; // Ensure null-terminated string
|
||||
decompressedBuffer.chars[decompressedBuffer.length] = '\0';
|
||||
FF_DEBUG("Successfully decompressed %u bytes compressed data to %u bytes", compressedSize, decompressedBuffer.length);
|
||||
|
||||
// Modify Content-Length header and remove Content-Encoding header
|
||||
@@ -171,7 +171,7 @@ bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
}
|
||||
else if (ffStrStartsWithIgnCase(line, "Content-Length:"))
|
||||
{
|
||||
ffStrbufAppendF(&newBuffer, "Content-Length: %u\r\n", decompressedSize);
|
||||
ffStrbufAppendF(&newBuffer, "Content-Length: %u\r\n", decompressedBuffer.length);
|
||||
continue;
|
||||
}
|
||||
else if (line[0] == '\r')
|
||||
@@ -181,7 +181,7 @@ bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
break;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&newBuffer, line);
|
||||
ffStrbufAppendS(&newBuffer, line); // Including the trailing \r
|
||||
ffStrbufAppendC(&newBuffer, '\n');
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "common/networking.h"
|
||||
#include "common/time.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
@@ -34,11 +34,7 @@ static const char* tryNonThreadingFastPath(FFNetworkingState* state)
|
||||
|
||||
#ifndef __APPLE__ // On macOS, TCP_FASTOPEN doesn't seem to be needed
|
||||
// Set TCP Fast Open
|
||||
#if __linux__ || __GNU__
|
||||
int flag = 5; // the queue length of pending packets
|
||||
#else
|
||||
int flag = 1; // enable TCP Fast Open
|
||||
#endif
|
||||
int flag = 1;
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP,
|
||||
#ifdef __APPLE__
|
||||
// https://github.com/rust-lang/libc/pull/3135
|
||||
@@ -186,15 +182,12 @@ static const char* initNetworkingState(FFNetworkingState* state, const char* hos
|
||||
FF_DEBUG("Initializing network connection state: host=%s, path=%s", host, path);
|
||||
|
||||
// Initialize command and host information
|
||||
ffStrbufInitA(&state->command, 64);
|
||||
ffStrbufInitA(&state->command, 128);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.0\r\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
// Add extra optimized HTTP headers
|
||||
ffStrbufAppendS(&state->command, "Connection: close\r\n"); // Explicitly tell the server we don't need to keep the connection
|
||||
ffStrbufAppendS(&state->command, "\r\nConnection: close\r\n"); // Explicitly tell the server we don't need to keep the connection
|
||||
|
||||
// If compression needs to be enabled
|
||||
if (state->compression) {
|
||||
@@ -221,9 +214,10 @@ static const char* initNetworkingState(FFNetworkingState* state, const char* hos
|
||||
FF_DEBUG("Resolving address: %s (%s)", host, state->ipv6 ? "IPv6" : "IPv4");
|
||||
// Use AI_NUMERICSERV flag to indicate the service is a numeric port, reducing parsing time
|
||||
|
||||
if(getaddrinfo(host, "80", &hints, &state->addr) != 0)
|
||||
int gaiRes = getaddrinfo(host, "80", &hints, &state->addr);
|
||||
if(gaiRes != 0)
|
||||
{
|
||||
FF_DEBUG("getaddrinfo() failed: %s", gai_strerror(errno));
|
||||
FF_DEBUG("getaddrinfo() failed: %s (res=%d)", gai_strerror(gaiRes), gaiRes);
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
@@ -360,6 +354,7 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
assert(buffer->allocated > 0);
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
@@ -390,15 +385,25 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
// poll for the socket to be readable.
|
||||
// Because of the non-blocking connectx() call, the connection might not be established yet
|
||||
FF_DEBUG("Using poll() to check if socket is readable");
|
||||
if (poll(&(struct pollfd) {
|
||||
.fd = state->sockfd,
|
||||
.events = POLLIN
|
||||
}, 1, timeout > 0 ? (int) timeout : -1) == -1)
|
||||
{
|
||||
FF_DEBUG("poll() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
return "poll() failed";
|
||||
int pollRes = poll(&(struct pollfd) {
|
||||
.fd = state->sockfd,
|
||||
.events = POLLIN
|
||||
}, 1, timeout > 0 ? (int) timeout : -1);
|
||||
if (pollRes == 0)
|
||||
{
|
||||
FF_DEBUG("poll() timed out after %u ms", timeout);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
return "poll() timeout";
|
||||
}
|
||||
else if (pollRes == -1)
|
||||
{
|
||||
FF_DEBUG("poll() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
return "poll() failed";
|
||||
}
|
||||
}
|
||||
FF_DEBUG("Socket is readable, proceeding to receive data");
|
||||
#else
|
||||
@@ -415,12 +420,14 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
uint32_t headerEnd = 0;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
++recvCount, buffer->length, ffStrbufGetFree(buffer));
|
||||
|
||||
// We set `Connection: close`, so the server will close the connection when done.
|
||||
// Thus we can use MSG_WAITALL to wait until the buffer is full or the connection is closed.
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), MSG_WAITALL);
|
||||
|
||||
if (received <= 0) {
|
||||
@@ -438,10 +445,11 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = memmem(buffer->chars, buffer->length, "\r\n\r\n", 4);
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
if (headerEnd == 0) {
|
||||
char* pHeaderEnd = memmem(buffer->chars, buffer->length, "\r\n\r\n", 4);
|
||||
if (pHeaderEnd) {
|
||||
headerEnd = (uint32_t)(pHeaderEnd - buffer->chars);
|
||||
FF_DEBUG("Found HTTP header end marker, position: %u", headerEnd);
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
@@ -451,7 +459,7 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
FF_DEBUG("Detected Content-Length: %u, pre-allocating buffer", contentLength);
|
||||
// Ensure buffer is large enough, adding header size and some margin
|
||||
ffStrbufEnsureFree(buffer, contentLength + 16);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->length);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->allocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,12 +475,12 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
if (headerEnd == 0) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
if (contentLength > 0 && buffer->length != contentLength + (uint32_t)(headerEnd - buffer->chars) + 4) {
|
||||
FF_DEBUG("Received content length mismatches: %u != %u", buffer->length, contentLength + (uint32_t)(headerEnd - buffer->chars) + 4);
|
||||
if (contentLength > 0 && buffer->length != contentLength + headerEnd + 4) {
|
||||
FF_DEBUG("Received content length mismatches: %u != %u", buffer->length, contentLength + headerEnd + 4);
|
||||
return "Content length mismatch";
|
||||
}
|
||||
|
||||
@@ -487,7 +495,7 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
if (!ffNetworkingDecompressGzip(buffer, buffer->chars + headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
//Must be included after <mswsock.h>
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
#include "common/networking.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
static LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
@@ -19,6 +19,7 @@ static const char* initWsaData(WSADATA* wsaData)
|
||||
|
||||
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2) {
|
||||
FF_DEBUG("Invalid wsaData version found: %d.%d", LOBYTE(wsaData->wVersion), HIBYTE(wsaData->wVersion));
|
||||
WSACleanup();
|
||||
return "Invalid wsaData version found";
|
||||
}
|
||||
|
||||
@@ -26,6 +27,7 @@ static const char* initWsaData(WSADATA* wsaData)
|
||||
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd == INVALID_SOCKET) {
|
||||
FF_DEBUG("socket(AF_INET, SOCK_STREAM) failed");
|
||||
WSACleanup();
|
||||
return "socket(AF_INET, SOCK_STREAM) failed";
|
||||
}
|
||||
|
||||
@@ -36,6 +38,8 @@ static const char* initWsaData(WSADATA* wsaData)
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&dwBytes, NULL, NULL) != 0) {
|
||||
FF_DEBUG("WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed");
|
||||
closesocket(sockfd);
|
||||
WSACleanup();
|
||||
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
|
||||
}
|
||||
|
||||
@@ -144,26 +148,35 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
// Initialize overlapped structure for asynchronous I/O
|
||||
memset(&state->overlapped, 0, sizeof(OVERLAPPED));
|
||||
// Initialize overlapped structure with WSA event for asynchronous I/O
|
||||
state->overlapped = (OVERLAPPED){
|
||||
.hEvent = WSACreateEvent()
|
||||
};
|
||||
|
||||
if (state->overlapped.hEvent == WSA_INVALID_EVENT) {
|
||||
FF_DEBUG("WSACreateEvent() failed");
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "WSACreateEvent() failed";
|
||||
}
|
||||
|
||||
// Build HTTP command
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&command, "Connection: close\r\n"); // Explicitly request connection closure
|
||||
ffStrbufInitA(&state->command, 128);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.0\r\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\nConnection: close\r\n"); // Explicitly request connection closure
|
||||
|
||||
// Add compression support if enabled
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Enabling HTTP content compression");
|
||||
ffStrbufAppendS(&command, "Accept-Encoding: gzip\r\n");
|
||||
ffStrbufAppendS(&state->command, "Accept-Encoding: gzip\r\n");
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&command, headers);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&state->command, headers);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef TCP_FASTOPEN
|
||||
if (state->tfo)
|
||||
@@ -182,10 +195,10 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Using ConnectEx to send %u bytes of data", command.length);
|
||||
FF_DEBUG("Using ConnectEx to send %u bytes of data", state->command.length);
|
||||
DWORD sent = 0;
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen,
|
||||
command.chars, command.length, &sent, &state->overlapped);
|
||||
state->command.chars, state->command.length, &sent, &state->overlapped);
|
||||
|
||||
freeaddrinfo(addr);
|
||||
addr = NULL;
|
||||
@@ -195,8 +208,10 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
if (WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
FF_DEBUG("ConnectEx() failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
WSACloseEvent(state->overlapped.hEvent);
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
ffStrbufDestroy(&state->command);
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
else
|
||||
@@ -215,6 +230,7 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
assert(buffer->allocated > 0);
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
@@ -226,13 +242,20 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject with timeout: %u ms", timeout);
|
||||
if (WaitForSingleObject((HANDLE)state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
FF_DEBUG("WSAWaitForMultipleEvents with timeout: %u ms", timeout);
|
||||
DWORD result = WSAWaitForMultipleEvents(1, &state->overlapped.hEvent, TRUE, timeout, FALSE);
|
||||
if (result != WSA_WAIT_EVENT_0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject failed or timed out");
|
||||
if (result == WSA_WAIT_TIMEOUT) {
|
||||
FF_DEBUG("WSAWaitForMultipleEvents timed out");
|
||||
} else {
|
||||
FF_DEBUG("WSAWaitForMultipleEvents failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
}
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
WSACloseEvent(state->overlapped.hEvent);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
ffStrbufDestroy(&state->command);
|
||||
return "WSAWaitForMultipleEvents() failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,8 +264,20 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
{
|
||||
FF_DEBUG("WSAGetOverlappedResult failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
WSACloseEvent(state->overlapped.hEvent);
|
||||
ffStrbufDestroy(&state->command);
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
FF_DEBUG("WSAGetOverlappedResult succeeded, %u bytes sent", (unsigned) transfer);
|
||||
ffStrbufDestroy(&state->command);
|
||||
WSACloseEvent(state->overlapped.hEvent);
|
||||
state->overlapped.hEvent = NULL;
|
||||
|
||||
if (setsockopt(state->sockfd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) != 0)
|
||||
{
|
||||
FF_DEBUG("Failed to update connect context: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
// Not a critical error, continue anyway
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
@@ -252,12 +287,16 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
|
||||
// Set larger receive buffer for better performance
|
||||
int rcvbuf = 65536; // 64KB
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&rcvbuf, sizeof(rcvbuf));
|
||||
if (setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&rcvbuf, sizeof(rcvbuf)))
|
||||
{
|
||||
FF_DEBUG("Failed to set SO_RCVBUF: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
// Not a critical error, continue anyway
|
||||
}
|
||||
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
uint32_t headerEnd = 0;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
@@ -280,10 +319,11 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = strstr(buffer->chars, "\r\n\r\n");
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
if (headerEnd == 0) {
|
||||
char* pHeaderEnd = strstr(buffer->chars, "\r\n\r\n");
|
||||
if (pHeaderEnd) {
|
||||
headerEnd = (uint32_t)(pHeaderEnd - buffer->chars);
|
||||
FF_DEBUG("Found HTTP header end marker, position: %u", headerEnd);
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
@@ -309,10 +349,14 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
if (headerEnd == 0) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
if (contentLength > 0 && buffer->length != contentLength + headerEnd + 4) {
|
||||
FF_DEBUG("Received content length mismatches: %u != %u", buffer->length, contentLength + headerEnd + 4);
|
||||
return "Content length mismatch";
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
|
||||
FF_DEBUG("Received valid HTTP 200 response, content length: %u bytes, total length: %u bytes",
|
||||
@@ -326,7 +370,7 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
if (!ffNetworkingDecompressGzip(buffer, buffer->chars + headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/option.h"
|
||||
#include "common/color.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
// Return start position of the inner key if the argument key belongs to the module specified, NULL otherwise
|
||||
const char* ffOptionTestPrefix(const char* argumentKey, const char* moduleName)
|
||||
@@ -166,6 +166,22 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
exit(479);
|
||||
}
|
||||
}
|
||||
else if (value[0] == '@')
|
||||
{
|
||||
// Xterm 256 color
|
||||
++value;
|
||||
char* pend = NULL;
|
||||
uint32_t color = (uint32_t) strtoul(value, &pend, 10);
|
||||
if (pend == value || color > 255) {
|
||||
fprintf(stderr, "Error: invalid 256 color code found: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(buffer, FF_COLOR_FG_256);
|
||||
ffStrbufAppendUInt(buffer, color);
|
||||
value = pend;
|
||||
continue;
|
||||
}
|
||||
else if (value[0] == '#')
|
||||
{
|
||||
// RGB color
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "path.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/path.h"
|
||||
#include "common/io.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#if !_WIN32
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "common/color.h"
|
||||
#include "common/option.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/textModifier.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
static void appendOutputColor(FFstrbuf* buffer, const FFModuleArgs* module)
|
||||
{
|
||||
@@ -261,6 +261,8 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha
|
||||
|
||||
bool ffPercentParseJsonObject(yyjson_val* key, yyjson_val* value, FFPercentageModuleConfig* config)
|
||||
{
|
||||
assert(key);
|
||||
|
||||
if (!unsafe_yyjson_equals_str(key, "percent"))
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/textModifier.h"
|
||||
#include "logo/logo.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType)
|
||||
{
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/io.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -222,6 +222,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
{
|
||||
assert(processName->length > 0);
|
||||
ffStrbufClear(exe);
|
||||
if (exePath) ffStrbufClear(exePath);
|
||||
|
||||
#if defined(__linux__) || defined(__GNU__)
|
||||
|
||||
@@ -270,13 +271,14 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (length > 0) // doesn't contain trailing NUL
|
||||
{
|
||||
buf[length] = '\0';
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
// When the process is a deleted executable, the resolved path is like `/usr/bin/app (deleted)`
|
||||
// But we can still access the binary via `/proc/pid/exe`. See #2136
|
||||
if (ffPathExists(buf, FF_PATHTYPE_ANY))
|
||||
ffStrbufSetNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (exePath->length == 0)
|
||||
ffStrbufSetS(exePath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
@@ -318,16 +320,21 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
ffStrbufSetS(exe, arg0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (exePath || exe->length == 0)
|
||||
{
|
||||
char buf[PROC_PIDPATHINFO_MAXSIZE];
|
||||
int length = proc_pidpath(pid, buf, ARRAY_SIZE(buf));
|
||||
if (length > 0)
|
||||
{
|
||||
ffStrbufEnsureFixedLengthFree(exe, (uint32_t) length);
|
||||
ffStrbufAppendNS(exe, (uint32_t) length, buf);
|
||||
if (exe->length == 0)
|
||||
ffStrbufSetNS(exe, (uint32_t) length, buf);
|
||||
if (exePath)
|
||||
ffStrbufSet(exePath, exe);
|
||||
{
|
||||
// We don't use exec_path above as exePath because it's a relative path and can be different
|
||||
// from the actual executable being run (for example, when the original file is moved)
|
||||
ffStrbufSetNS(exePath, (uint32_t) length, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,8 +410,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (length > 0) // doesn't contain trailing NUL
|
||||
{
|
||||
buf[length] = '\0';
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
ffStrbufSetNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
#include "common/windows/unicode.h"
|
||||
#include "common/windows/nt.h"
|
||||
|
||||
#include <stdalign.h>
|
||||
#include <windows.h>
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
@@ -51,7 +53,7 @@ const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle*
|
||||
|
||||
wchar_t pipeName[32];
|
||||
static unsigned pidCounter = 0;
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u-%u", GetCurrentProcessId(), ++pidCounter);
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u-%u", instance.state.platform.pid, ++pidCounter);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
pipeName,
|
||||
@@ -152,7 +154,7 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
#if __aarch64__
|
||||
#if !FF_WIN7_COMPAT
|
||||
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
|
||||
#else
|
||||
// To support Windows 7
|
||||
@@ -172,7 +174,7 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "GetOverlappedResult"
|
||||
#if __aarch64__
|
||||
#if !FF_WIN7_COMPAT
|
||||
"Ex"
|
||||
#endif
|
||||
"(hChildPipeRead) failed";
|
||||
@@ -193,9 +195,16 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
|
||||
exit:
|
||||
{
|
||||
DWORD exitCode = 0;
|
||||
if (GetExitCodeProcess(hProcess, &exitCode) && exitCode != STILL_ACTIVE && exitCode != 0)
|
||||
return "Child process exited with an error";
|
||||
PROCESS_BASIC_INFORMATION info = {};
|
||||
ULONG size;
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessBasicInformation, &info, sizeof(info), &size)))
|
||||
{
|
||||
assert(size == sizeof(info));
|
||||
if (info.ExitStatus != STILL_ACTIVE && info.ExitStatus != 0)
|
||||
return "Child process exited with an error";
|
||||
}
|
||||
else
|
||||
return "NtQueryInformationProcess(ProcessBasicInformation) failed";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -204,15 +213,12 @@ exit:
|
||||
bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe, const char** exeName, FFstrbuf* exePath, bool* gui)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD HANDLE hProcess = pid == 0
|
||||
? GetCurrentProcess()
|
||||
? NtCurrentProcess()
|
||||
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
|
||||
if (hProcess == NULL)
|
||||
return false;
|
||||
|
||||
if (gui)
|
||||
*gui = GetGuiResources(hProcess, GR_GDIOBJECTS) > 0;
|
||||
|
||||
if(ppid)
|
||||
{
|
||||
PROCESS_BASIC_INFORMATION info = {};
|
||||
@@ -225,23 +231,41 @@ bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFst
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if(exe)
|
||||
{
|
||||
DWORD bufSize = exe->allocated;
|
||||
if(QueryFullProcessImageNameA(hProcess, 0, exe->chars, &bufSize))
|
||||
// TODO: It's possible to query the command line with `NtQueryInformationProcess(60/*ProcessCommandLineInformation*/)` since Windows 8.1
|
||||
|
||||
alignas(UNICODE_STRING) uint8_t buffer[4096];
|
||||
ULONG size;
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessImageFileNameWin32, &buffer, sizeof(buffer), &size)))
|
||||
{
|
||||
// We use full path here
|
||||
// Querying command line of remote processes in Windows requires either WMI or ReadProcessMemory
|
||||
exe->length = bufSize;
|
||||
UNICODE_STRING* imagePath = (UNICODE_STRING*)buffer;
|
||||
ffStrbufSetNWS(exe, imagePath->Length / sizeof(wchar_t), imagePath->Buffer);
|
||||
|
||||
if (exePath) ffStrbufSet(exePath, exe);
|
||||
|
||||
if (pname && exeName)
|
||||
{
|
||||
*exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1;
|
||||
ffStrbufSetS(pname, *exeName);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if(pname && exeName)
|
||||
|
||||
if (gui)
|
||||
{
|
||||
*exeName = exe->chars + ffStrbufLastIndexC(exe, '\\') + 1;
|
||||
ffStrbufSetS(pname, *exeName);
|
||||
SECTION_IMAGE_INFORMATION info = {};
|
||||
ULONG size;
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessImageInformation, &info, sizeof(info), &size)))
|
||||
{
|
||||
assert(size == sizeof(info));
|
||||
*gui = info.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/io.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#ifdef _WIN32
|
||||
#include "util/windows/getline.h"
|
||||
#include "common/windows/getline.h"
|
||||
#endif
|
||||
|
||||
bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "common/library.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -201,7 +201,7 @@ FFvariant ffSettingsGetGnome(const char* dconfKey, const char* gsettingsSchemaNa
|
||||
|
||||
FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName, FFvarianttype type)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {};
|
||||
if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
@@ -260,7 +260,7 @@ FFvariant ffSettingsGetXFConf(const char* channelName, const char* propertyName,
|
||||
|
||||
FFvariant ffSettingsGetXFConfFirstMatch(const char* channelName, const char* propertyPrefix, FFvarianttype type, void* data, FFTestXfconfPropCallback* cb)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {};
|
||||
if (ffDBusLoadData(DBUS_BUS_SESSION, &dbus) != NULL)
|
||||
return FF_VARIANT_NULL;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "size.h"
|
||||
#include "common/size.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "smbiosHelper.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/unused.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
#include "common/smbiosHelper.h"
|
||||
#include "common/io.h"
|
||||
#include "common/unused.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
bool ffIsSmbiosValueSet(FFstrbuf* value)
|
||||
{
|
||||
@@ -109,7 +109,7 @@ typedef struct FFSmbios20EntryPoint
|
||||
uint8_t SmbiosBcdRevision;
|
||||
} __attribute__((__packed__)) FFSmbios20EntryPoint;
|
||||
static_assert(offsetof(FFSmbios20EntryPoint, SmbiosBcdRevision) == 0x1E,
|
||||
"FFSmbios30EntryPoint: Wrong struct alignment");
|
||||
"FFSmbios20EntryPoint: Wrong struct alignment");
|
||||
|
||||
typedef struct FFSmbios30EntryPoint
|
||||
{
|
||||
@@ -434,7 +434,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
return &table;
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "common/windows/nt.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||
|
||||
@@ -450,36 +450,52 @@ typedef struct FFRawSmbiosData
|
||||
|
||||
const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
{
|
||||
static FFRawSmbiosData* buffer;
|
||||
static SYSTEM_FIRMWARE_TABLE_INFORMATION* buffer;
|
||||
static FFSmbiosHeaderTable table;
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
FF_DEBUG("Initializing Windows SMBIOS buffer");
|
||||
const DWORD signature = 'RSMB';
|
||||
|
||||
FF_DEBUG("Querying system firmware table size with signature 'RSMB'");
|
||||
uint32_t bufSize = GetSystemFirmwareTable(signature, 0, NULL, 0);
|
||||
if (bufSize <= sizeof(FFRawSmbiosData)) {
|
||||
FF_DEBUG("Invalid firmware table size: %u (must be > %zu)",
|
||||
bufSize, sizeof(FFRawSmbiosData));
|
||||
SYSTEM_FIRMWARE_TABLE_INFORMATION sfti = {
|
||||
.ProviderSignature = 'RSMB',
|
||||
.Action = SystemFirmwareTableGet,
|
||||
};
|
||||
ULONG bufSize = 0;
|
||||
NtQuerySystemInformation(SystemFirmwareTableInformation, &sfti, sizeof(sfti), &bufSize);
|
||||
if (bufSize <= sizeof(FFRawSmbiosData) + sizeof(sfti)) {
|
||||
FF_DEBUG("Invalid firmware table size: %lu (must be > %zu)", bufSize, sizeof(FFRawSmbiosData) + sizeof(sfti));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Firmware table size: %u bytes", bufSize);
|
||||
if (bufSize != sfti.TableBufferLength + (ULONG) sizeof(sfti)) {
|
||||
FF_DEBUG("Firmware table size mismatch: NtQuerySystemInformation returned %lu but expected %lu",
|
||||
bufSize, sfti.TableBufferLength + (ULONG) sizeof(sfti));
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Firmware table size: %lu bytes", bufSize);
|
||||
|
||||
buffer = (FFRawSmbiosData*) malloc(bufSize);
|
||||
assert(buffer);
|
||||
buffer = malloc(bufSize);
|
||||
*buffer = sfti;
|
||||
FF_DEBUG("Allocated buffer for SMBIOS data");
|
||||
|
||||
FF_MAYBE_UNUSED uint32_t resultSize = GetSystemFirmwareTable(signature, 0, buffer, bufSize);
|
||||
assert(resultSize == bufSize);
|
||||
if (!NT_SUCCESS(NtQuerySystemInformation(SystemFirmwareTableInformation, buffer, bufSize, &bufSize)))
|
||||
{
|
||||
FF_DEBUG("NtQuerySystemInformation(SystemFirmwareTableInformation) failed");
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
return NULL;
|
||||
}
|
||||
FFRawSmbiosData* rawData = (FFRawSmbiosData*) buffer->TableBuffer;
|
||||
|
||||
FF_DEBUG("Successfully retrieved SMBIOS data: version %u.%u, length %u bytes",
|
||||
buffer->SMBIOSMajorVersion, buffer->SMBIOSMinorVersion, buffer->Length);
|
||||
rawData->SMBIOSMajorVersion, rawData->SMBIOSMinorVersion, rawData->Length);
|
||||
|
||||
FF_DEBUG("Parsing SMBIOS table structures");
|
||||
FF_MAYBE_UNUSED int structureCount = 0;
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer->SMBIOSTableData;
|
||||
(const uint8_t*) header < buffer->SMBIOSTableData + buffer->Length;
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) rawData->SMBIOSTableData;
|
||||
(const uint8_t*) header < rawData->SMBIOSTableData + rawData->Length;
|
||||
header = ffSmbiosNextEntry(header)
|
||||
)
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "sysctl.h"
|
||||
#include "common/sysctl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user