mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
355 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| a9f43ff466 | |||
| 924d78d3c4 | |||
| fa92bb84ae | |||
| 288d25e17c | |||
| 610fc2ea36 | |||
| 716c0e2b5c | |||
| 945aed7160 | |||
| 1d4d68f6e0 | |||
| 3e1167260d | |||
| 0130f610e9 | |||
| 94941daf4f | |||
| 2bbd723321 | |||
| 608382109c | |||
| bdc5174f68 | |||
| bc869f1be9 | |||
| dc69e44829 | |||
| d236850119 | |||
| 60ec8c9097 | |||
| 42e7a7d2f7 | |||
| e766809e3a | |||
| cb1f0300b9 | |||
| f2a29309f3 | |||
| 6e7b4bab75 | |||
| b4f39e251c | |||
| af6196fe6e | |||
| bca56b2049 | |||
| f4401f172e | |||
| c11b88fee5 | |||
| 88b1b558d7 | |||
| ba6cdc77c9 | |||
| b952772902 | |||
| 7a322154fa | |||
| 0b6ca158ea | |||
| 100cd9a72b | |||
| 98fb810f1f | |||
| c613e558fd | |||
| c324f83826 | |||
| e50421a6ce | |||
| 417b944e1c | |||
| cb8b4b335d | |||
| c0160537b0 | |||
| 4cb7a6424a | |||
| 7d6c79d73e | |||
| 8652737f64 | |||
| d6ac89ea8d | |||
| 2b620cf487 | |||
| f644df481c | |||
| e99ecacb52 | |||
| 3e22dd4b0e | |||
| 19f30ec687 | |||
| 76bee78200 | |||
| ce7455d8f0 | |||
| 5e27ee0f57 | |||
| 84a5c6ebe8 | |||
| ad7e23f64c | |||
| 2738f20eea | |||
| 09362b236c | |||
| 3cfef81877 | |||
| 3a04ae2542 | |||
| dbaf8a319d | |||
| 2fe2a21bfe | |||
| 37639c3582 | |||
| 9a74e6d7bc | |||
| 5d13389827 | |||
| 1c2c6644d5 | |||
| ffcddf30e3 | |||
| 22c92c7b05 | |||
| b569048010 | |||
| f703d9ac89 | |||
| ed6abfd626 | |||
| 50388efc78 | |||
| 7e8fb0fa14 | |||
| 9d70469665 | |||
| a94f0efb5b | |||
| da3a9be7c6 | |||
| cd8ab8e55a | |||
| 1b5b32afad | |||
| 917f784438 | |||
| c2d5d5cca1 | |||
| b435738c34 | |||
| 934905e63a | |||
| d15bb8a232 | |||
| c22bca1f87 | |||
| e04cc9c9d5 | |||
| 7a2bf4e0ac | |||
| 662f5127fa | |||
| fb9117553b | |||
| 9f24e4363f | |||
| 084f9294f2 | |||
| a9f1f9a647 | |||
| 0aed89036b | |||
| df15bbc5f2 | |||
| e6b0bd3817 | |||
| 11cd7153a2 | |||
| f8bc1cb605 | |||
| 8b8eb6f290 | |||
| 056fe21ee2 | |||
| cb0a88df22 | |||
| 298c0431c3 | |||
| 448de9afa5 | |||
| 9401a4b9ad | |||
| ea92ad3785 | |||
| 7aaad5e03e | |||
| 645bf5c839 | |||
| 7638e0e4a1 | |||
| 302b8a7b1b | |||
| dbb9d8a660 | |||
| c51a164042 | |||
| 6b8a62da6e | |||
| 578ca23e75 | |||
| 2e73a90835 | |||
| cc6273fecc | |||
| e63b777916 | |||
| 907567f511 | |||
| e0fd7308be | |||
| b761034aae | |||
| 04d6b1453d | |||
| 11d1754686 | |||
| 25e84decff | |||
| 7d665b203f | |||
| ac62442798 | |||
| 758f96de60 | |||
| db623b9c86 | |||
| c353bf3c96 | |||
| 338b552499 | |||
| 5d73cc1232 | |||
| faddef7a3b | |||
| 2d9bbc8049 | |||
| 64afaa07e7 | |||
| 5cf3ab23b0 | |||
| 3fe926d3a0 | |||
| f71bb682de | |||
| 904f860f3c | |||
| 8f15c9604c | |||
| ff28f5807b | |||
| 6a317366d7 | |||
| dc3e4a2d18 | |||
| 46c4a71ba3 | |||
| f0759acd11 | |||
| 96c7c2966d | |||
| 554e7bce4a | |||
| 70377a8afd | |||
| 51bc6d421a | |||
| be0756f8ba | |||
| 71a2cb4e1b | |||
| 2eba761bed | |||
| 4b5e1a816b | |||
| a92e4b2d67 | |||
| a32404ba98 | |||
| 0a792e4935 | |||
| 05108977e8 | |||
| 25353261d0 | |||
| 4b517263d0 | |||
| 98a65966e7 | |||
| 32dcf9487f | |||
| e3a698f7b1 | |||
| 1631f74700 | |||
| 78c6d71049 | |||
| 0b9ecdeade | |||
| 185a9211f1 | |||
| 24459b2fbf | |||
| 88c8dcb3e8 | |||
| f3a8fedf0a | |||
| 6b8b7c1a62 | |||
| af26828f91 | |||
| f4c43abbf7 | |||
| e84739bff0 | |||
| 66aad0e4f1 | |||
| 77c43c0214 | |||
| 31ae7a642a | |||
| 1bbb21486c | |||
| 316d8ddf9b | |||
| 5d8c21a5ca | |||
| 240ba5c00c | |||
| 554184ec72 | |||
| 7a055a2254 | |||
| 0a807ac1a3 | |||
| 4d831c8c73 | |||
| e6e78a7aae | |||
| 09bef5f41d | |||
| e394efdd85 | |||
| c10b652a2e | |||
| 1594a69d6c | |||
| 9b1e318bd1 | |||
| e292bf1dee | |||
| 55a0c6e97d | |||
| 8b8e4a40a4 | |||
| 8be070998f | |||
| 093f56a03d | |||
| bd9744c27c | |||
| adc25f4420 | |||
| 229fe7c7bf | |||
| 5d571752ae | |||
| 512ddfae6b | |||
| 7b689f94df | |||
| 9eed149b09 | |||
| 0f5d321df8 | |||
| 4e84094fd8 | |||
| 7b9fce0189 |
@@ -0,0 +1,3 @@
|
||||
github: LinusDierheimer
|
||||
ko_fi: carterli
|
||||
custom: https://paypal.me/zhangsongcui
|
||||
@@ -6,33 +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 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.
|
||||
+213
-65
@@ -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
|
||||
@@ -89,8 +89,11 @@ jobs:
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: add gcc-13 repo
|
||||
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 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 libchafa-dev directx-headers-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
@@ -99,19 +102,19 @@ jobs:
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: CC=gcc-13 CXX=g++-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- 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
|
||||
@@ -142,14 +145,83 @@ jobs:
|
||||
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
|
||||
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
|
||||
cpack
|
||||
echo 'set(CPACK_PACKAGE_RELOCATABLE OFF)' >> CPackConfig.cmake
|
||||
echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake
|
||||
echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake
|
||||
cpack -V
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-i686:
|
||||
name: Linux-i686
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: add gcc-13 repo
|
||||
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 gcc-13-multilib 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 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 chafa --ignore-dependencies
|
||||
|
||||
- name: cmake version
|
||||
run: cmake --version
|
||||
|
||||
- name: configure project
|
||||
run: CC=gcc-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DCMAKE_C_FLAGS="-m32 -march=i686 -mtune=i686" -DCMAKE_SYSTEM_PROCESSOR_OVERRIDE=i686 -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=i386 -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_DIRECTX_HEADERS=Off .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: check deb package
|
||||
run: dpkg -I fastfetch-*.deb
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-linux-i686
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7l:
|
||||
name: Linux-armv7l
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -158,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
|
||||
@@ -169,12 +241,13 @@ jobs:
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y ca-certificates gpg curl
|
||||
apt-get update && apt-get install -y software-properties-common ca-certificates gpg curl
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
|
||||
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
|
||||
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
|
||||
apt-get update && apt-get install -y cmake make g++ 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 rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
apt-get update && apt-get install -y cmake make gcc-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 rpm
|
||||
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
@@ -184,7 +257,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
@@ -197,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
|
||||
@@ -209,8 +282,8 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
apt-get install -y cmake make g++ 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 rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
apt-get install -y cmake make gcc 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 rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
@@ -220,7 +293,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
@@ -239,19 +312,21 @@ 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
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ${{ matrix.arch }}
|
||||
distro: ubuntu20.04
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ 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 libchafa-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
apt-get update && apt-get install -y software-properties-common
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
apt-get update && apt-get install -y cmake make gcc-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 libchafa-dev libelf-dev rpm
|
||||
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_DIRECTX_HEADERS=Off -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
@@ -261,7 +336,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
@@ -270,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
|
||||
@@ -299,7 +374,7 @@ jobs:
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -319,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
|
||||
@@ -353,17 +428,17 @@ jobs:
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
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
|
||||
@@ -371,25 +446,60 @@ jobs:
|
||||
usesh: true
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install pkg:/package/pkg
|
||||
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@v6
|
||||
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
|
||||
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@v6
|
||||
with:
|
||||
name: fastfetch-solaris-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
freebsd-amd64:
|
||||
@@ -400,7 +510,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
|
||||
@@ -409,7 +519,7 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.3'
|
||||
version: '15.0'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
@@ -424,7 +534,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -437,7 +547,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
|
||||
@@ -446,11 +556,12 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.7'
|
||||
version: '7.8'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
sudo pkg_add -u
|
||||
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
|
||||
@@ -460,7 +571,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-openbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -473,7 +584,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
|
||||
@@ -485,8 +596,8 @@ jobs:
|
||||
version: '10.1'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
|
||||
CC=clang 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
|
||||
@@ -496,7 +607,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -509,7 +620,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
@@ -518,10 +629,10 @@ jobs:
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf
|
||||
pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
env CC=clang 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
|
||||
@@ -531,7 +642,7 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
@@ -544,7 +655,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
|
||||
@@ -566,13 +677,13 @@ jobs:
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
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
|
||||
@@ -585,17 +696,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
|
||||
@@ -608,7 +730,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
|
||||
@@ -634,17 +756,41 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
id: upload-unsigned-artifact
|
||||
name: upload artifacts for signing
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: fastfetch-windows-${{ matrix.arch }}${{ matrix.win7-compat-postfix }}
|
||||
path: |
|
||||
*.dll
|
||||
fastfetch.exe
|
||||
flashfetch.exe
|
||||
|
||||
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: submit signing request
|
||||
uses: signpath/github-action-submit-signing-request@v1
|
||||
with:
|
||||
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
|
||||
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
|
||||
project-slug: 'fastfetch'
|
||||
signing-policy-slug: ${{ github.ref == 'refs/heads/master' && 'release-signing' || 'test-signing' }}
|
||||
github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
|
||||
wait-for-completion: true
|
||||
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 artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: upload true artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
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:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
@@ -652,6 +798,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux-hosts
|
||||
- linux-i686
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-vms
|
||||
@@ -661,7 +808,8 @@ jobs:
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- solaris-amd64
|
||||
- omnios-amd64
|
||||
- haiku-amd64
|
||||
- windows-hosts
|
||||
permissions:
|
||||
|
||||
+251
@@ -1,3 +1,254 @@
|
||||
# 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 issues 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:
|
||||
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
|
||||
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
|
||||
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
|
||||
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
|
||||
* Minor optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Fixes cache line size detection (CPU, macOS)
|
||||
|
||||
Logos:
|
||||
* Removes Opak
|
||||
* Updates GXDE
|
||||
|
||||
# 2.56.0
|
||||
|
||||
Features:
|
||||
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
|
||||
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
|
||||
* Adds NUMA node count detection (CPU)
|
||||
* Exposed via `{numa-nodes}` in custom format
|
||||
* Supported on Linux, FreeBSD and Windows
|
||||
* Supports the newest Alacritty config format (#2070, TerminalFont)
|
||||
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
|
||||
* Detects Android OEM UI for certain OSes (DE, Android)
|
||||
* Improves users detection on Linux (#2064, Users, Linux)
|
||||
* Adds systemd fallback when utmp is unavailable
|
||||
* Fixes resource leaks
|
||||
* Always reports the newest session info
|
||||
* Adds kiss package manager support (#2072, Packages, Linux)
|
||||
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
|
||||
* Zpool module rewrite (#2051, Zpool)
|
||||
* Adds new Zpool properties: allocated, guid, readOnly
|
||||
* Zpool module now uses runtime lookup for properties to ensure portability
|
||||
* Adds NetBSD (requires `sudo`) and macOS support
|
||||
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
|
||||
```
|
||||
* Command output:
|
||||
Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* Old behavior:
|
||||
Command: Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* With `"splitLines": true`:
|
||||
Command 1: Line 1
|
||||
Command 2: Line 2
|
||||
Command 3: Line 3
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Fixes {m,o}ksh version detection on Linux (Shell)
|
||||
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
|
||||
* Improves builtin logo printing for piping and buffering (#2065, Logo)
|
||||
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
|
||||
|
||||
Logos:
|
||||
* Updates Codex Linux logo (#2071)
|
||||
* Adds OS/2 Warp logo (#2062)
|
||||
* Adds Amiga logo (#2061)
|
||||
|
||||
# 2.55.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
|
||||
* Regression from v2.55.0
|
||||
* Fix `dylib` searching path on macOS (macOS)
|
||||
* Regression from v2.55.0
|
||||
* Fix an uninitialized field (#2057, Display)
|
||||
|
||||
# 2.55.0
|
||||
|
||||
Changes:
|
||||
* Commands are now executed in parallel by default to improve performance (#2045, Command)
|
||||
* This behavior can be disabled in the config file with `"parallel": false` if it causes problems with certain scripts
|
||||
* Folder/filesystem hiding is moved to the detection stage; hidden entries are no longer probed, improving performance (#2043, Disk)
|
||||
|
||||
Features:
|
||||
* Adds `command.parallel` and `command.useStdErr` config options (Command)
|
||||
* `parallel`: set to `false` to disable parallel execution (see Changes above)
|
||||
* `useStdErr`: set to `true` to use stderr output instead of stdout
|
||||
* Adds the command-line flag `--dynamic-interval <interval-in-ms>` to enable dynamic output auto-refresh (#2041)
|
||||
* Due to internal limitations, some modules do not support dynamic updates (notably Display and Media)
|
||||
* Adds support for using the current playing media's cover art as a logo source (Media / Logo)
|
||||
* Usage: `"logo": { "type": "<image-protocol>", "source": "media-cover" }` in JSON config; or `--<image-protocol> media-cover` in command line
|
||||
* Supports local sources only
|
||||
* Adds native GPU detection support on OpenBSD and NetBSD (instead of depending on `libpciaccess`) (GPU)
|
||||
* No functional changes
|
||||
* Root privileges are required to access PCI config space on OpenBSD (as always)
|
||||
* Adds GPU detection support on GNU/Hurd (GPU)
|
||||
* Requires building with `libpciaccess`
|
||||
* Shows Debian point release on Raspberry Pi OS (#2032, OS, Linux)
|
||||
* Adds `Brush` shell version detection (Shell)
|
||||
* Improves Mac family detection via prefix matching (Host)
|
||||
|
||||
Bugfixes:
|
||||
* Ignores `run-parts` during terminal/shell detection (#2048, Terminal / Shell, Linux)
|
||||
* Fixes fish version detection when `LC_ALL` is set (#2014, Shell, Linux)
|
||||
* Hides the module when no desktop icons are found (#2023, Icons, Windows)
|
||||
* Skips auxiliary display controllers to prevent the module from reporting duplicate entries (#2034, GPU, Linux)
|
||||
* Refines Apple rpath handling; fixes building for the Homebrew version on macOS (#1998, CMake)
|
||||
|
||||
Logos:
|
||||
* Adds Vincent OS and MacaroniOS
|
||||
|
||||
# 2.54.0
|
||||
|
||||
Windows binaries in Release page are now signed by SignPath.
|
||||
|
||||
Changes:
|
||||
* Moves macOS and Windows design language detection from the DE module to the Theme module
|
||||
|
||||
Features:
|
||||
* Adds `--json` and `-j` command line flags as a shortcut for `--format json`
|
||||
* Various improvements to the OS module (OS)
|
||||
* Displays point releases for Debian
|
||||
* Displays code names for Ubuntu
|
||||
* Displays build ID for macOS
|
||||
* Displays code names for Windows (previously shown in the Kernel module)
|
||||
* Adds basic support for Wine (Windows)
|
||||
* Adds basic support for hppa and sh architectures (CPU, Linux)
|
||||
* Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux)
|
||||
* Supports glob patterns in `Disk.hideFolders` (Disk)
|
||||
* For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware`
|
||||
* Adds brightness-level detection for external monitor support on Intel macOS (Brightness, macOS)
|
||||
* Adds configurable spacing between icon and text in keys
|
||||
* `display.key.type: "both-N"` where N is `0-4`
|
||||
* Useful for non-monospaced Nerd Fonts
|
||||
* Adds detection support for modern Samsung Exynos SoCs (CPU, Android)
|
||||
* Adds a new CMake option `-DENABLE_WORDEXP=<ON|OFF>` to enable or disable using `wordexp(3)` for acquiring logo file paths (`logo.source`)
|
||||
* Enabled by default for compatibility
|
||||
* Disabling this option reverts to using `glob(3)`, which is less functional but more secure
|
||||
|
||||
Bugfixes:
|
||||
* Avoids integer overflow when calculating swap size (#1988, Swap, Windows)
|
||||
* Trims whitespace from full user name (Title, macOS)
|
||||
* Fixes default font size for Ghostty (#1986, TerminalFont, Linux)
|
||||
* Works around an issue that could report impossibly high memory usage in rare cases (#1988, Memory, Linux)
|
||||
* Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux)
|
||||
* Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux)
|
||||
* Fixes crashes on ancient Android kernels (#1993, Disk, Android)
|
||||
* Fixes incorrect usage of `glob(3)` (OpenBSD)
|
||||
* Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux)
|
||||
* Various code cleanups and minor fixes
|
||||
|
||||
Logos:
|
||||
* Adds secureblue, PrismLinux, EmperorOS and Zraxyl
|
||||
* Updates T2
|
||||
|
||||
# 2.53.0
|
||||
|
||||
Changes:
|
||||
|
||||
+242
-195
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.53.0
|
||||
VERSION 2.59.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -9,6 +9,17 @@ project(fastfetch
|
||||
|
||||
set(PROJECT_LICENSE "MIT license")
|
||||
|
||||
if(DEFINED CMAKE_SYSTEM_PROCESSOR_OVERRIDE) # Used by github actions for i686 build
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR_OVERRIDE} CACHE INTERNAL "")
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" CMAKE_SYSTEM_PROCESSOR)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
||||
endif()
|
||||
message(STATUS "Build for system processor: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
|
||||
###################
|
||||
# Target Platform #
|
||||
###################
|
||||
@@ -81,8 +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_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD" OFF)
|
||||
|
||||
option(ENABLE_ZLIB "Enable zlib" ON)
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
@@ -95,6 +104,14 @@ option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
|
||||
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
|
||||
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
|
||||
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" ON)
|
||||
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")
|
||||
@@ -149,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()
|
||||
@@ -330,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()
|
||||
|
||||
####################
|
||||
@@ -352,31 +375,39 @@ 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/kmod.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
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
src/detection/command/command.c
|
||||
src/detection/disk/disk.c
|
||||
src/detection/diskio/diskio.c
|
||||
src/detection/displayserver/displayserver.c
|
||||
@@ -397,6 +428,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/version/version.c
|
||||
src/detection/vulkan/vulkan.c
|
||||
src/detection/weather/weather.c
|
||||
src/detection/zpool/zpool.c
|
||||
src/logo/builtin.c
|
||||
src/logo/image/im6.c
|
||||
src/logo/image/im7.c
|
||||
@@ -438,6 +470,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
|
||||
@@ -475,26 +508,21 @@ 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/detection/battery/battery_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
src/detection/board/board_linux.c
|
||||
@@ -569,17 +597,16 @@ if(LINUX)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_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/detection/battery/battery_android.c
|
||||
src/detection/bios/bios_android.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
@@ -643,18 +670,17 @@ elseif(ANDROID)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/detection/zpool/zpool_nosupport.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/detection/battery/battery_bsd.c
|
||||
src/detection/bios/bios_bsd.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
@@ -726,9 +752,6 @@ elseif(FreeBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
if(DragonFly)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -743,12 +766,14 @@ 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/detection/battery/battery_nbsd.c
|
||||
src/detection/bios/bios_nbsd.c
|
||||
src/detection/bluetooth/bluetooth_bsd.c
|
||||
@@ -782,7 +807,7 @@ elseif(NetBSD)
|
||||
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_nbsd.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_nbsd.c
|
||||
@@ -820,18 +845,18 @@ elseif(NetBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_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/detection/battery/battery_obsd.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
@@ -866,7 +891,7 @@ elseif(OpenBSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gpu/gpu_general.c
|
||||
src/detection/gpu/gpu_obsd.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_obsd.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
@@ -903,18 +928,19 @@ elseif(OpenBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_nosupport.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/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
|
||||
@@ -963,7 +989,7 @@ elseif(APPLE)
|
||||
src/detection/terminalfont/terminalfont_apple.m
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalsize/terminalsize_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/theme/theme_apple.c
|
||||
src/detection/tpm/tpm_apple.c
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
@@ -973,19 +999,22 @@ elseif(APPLE)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
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/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/version.c
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
@@ -1024,7 +1053,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.c
|
||||
src/detection/os/os_windows.cpp
|
||||
src/detection/packages/packages_windows.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_windows.c
|
||||
@@ -1033,7 +1062,7 @@ elseif(WIN32)
|
||||
src/detection/terminalfont/terminalfont_windows.c
|
||||
src/detection/terminalshell/terminalshell_windows.c
|
||||
src/detection/terminalsize/terminalsize_windows.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/theme/theme_windows.c
|
||||
src/detection/tpm/tpm_windows.c
|
||||
src/detection/uptime/uptime_windows.c
|
||||
src/detection/users/users_windows.c
|
||||
@@ -1043,24 +1072,16 @@ elseif(WIN32)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
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/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
@@ -1132,17 +1153,17 @@ elseif(SunOS)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_linux.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/haiku/version.cpp
|
||||
src/detection/battery/battery_haiku.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
@@ -1201,18 +1222,16 @@ elseif(Haiku)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_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/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/board/board_nosupport.c
|
||||
@@ -1242,7 +1261,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_nosupport.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
|
||||
@@ -1281,9 +1300,6 @@ elseif(GNU)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1304,11 +1320,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)
|
||||
@@ -1327,16 +1347,25 @@ 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)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON=1)
|
||||
target_link_libraries(libfastfetch PUBLIC yyjson::yyjson)
|
||||
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
|
||||
else()
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
@@ -1398,7 +1427,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")
|
||||
@@ -1406,9 +1435,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)
|
||||
@@ -1594,28 +1653,6 @@ ff_lib_enable(DIRECTX_HEADERS
|
||||
"DirectX-Headers"
|
||||
"DirectX-Headers"
|
||||
)
|
||||
ff_lib_enable(PCIACCESS
|
||||
"pciaccess"
|
||||
"pciaccess"
|
||||
)
|
||||
# The system <libzfs.h> is only usable on SunOS. We provide our local copy of it so it's always available.
|
||||
if(ENABLE_LIBZFS)
|
||||
if(BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_LIBRARIES_BACKUP ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} zfs)
|
||||
check_function_exists("libzfs_init" LIBZFS_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_BACKUP})
|
||||
if(NOT LIBZFS_FOUND)
|
||||
message(STATUS "Library: missing: LIBZFS")
|
||||
else()
|
||||
message(STATUS "Library: found LIBZFS")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
target_link_libraries(libfastfetch PRIVATE zfs)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
|
||||
@@ -1630,6 +1667,18 @@ endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
if(ENABLE_LIBZFS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "zfs"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_MEMRCHR)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_CUSTOM_MEMRCHR=1)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1678,12 +1727,10 @@ elseif(WIN32)
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
PRIVATE "cfgmgr32"
|
||||
PRIVATE "winbrand"
|
||||
PRIVATE "propsys"
|
||||
PRIVATE "secur32"
|
||||
)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
# WoA only works on Windows 10 or higher
|
||||
if(NOT ENABLE_WIN7_COMPAT)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "mincore"
|
||||
)
|
||||
@@ -1721,8 +1768,6 @@ elseif(SunOS)
|
||||
PRIVATE "socket"
|
||||
PRIVATE "kstat"
|
||||
PRIVATE "proc"
|
||||
PRIVATE "zfs"
|
||||
PRIVATE "nvpair"
|
||||
PRIVATE "devinfo"
|
||||
)
|
||||
elseif(GNU)
|
||||
@@ -1733,17 +1778,20 @@ elseif(ANDROID)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
)
|
||||
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
if(HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE -l:libandroid-wordexp.a
|
||||
)
|
||||
else()
|
||||
CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP)
|
||||
if(HAVE_LIBANDROID_WORDEXP)
|
||||
if(ENABLE_WORDEXP)
|
||||
# https://github.com/termux/termux-packages/pull/7056
|
||||
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
if(HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE android-wordexp
|
||||
PRIVATE -l:libandroid-wordexp.a
|
||||
)
|
||||
else()
|
||||
CHECK_LIBRARY_EXISTS(android-wordexp wordexp "" HAVE_LIBANDROID_WORDEXP)
|
||||
if(HAVE_LIBANDROID_WORDEXP)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE android-wordexp
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
elseif(Haiku)
|
||||
@@ -1805,13 +1853,17 @@ if(NOT WIN32)
|
||||
if(HAVE_UTMPX)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1)
|
||||
endif()
|
||||
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
|
||||
if(HAVE_WORDEXP)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
|
||||
if(ENABLE_WORDEXP)
|
||||
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
|
||||
if(HAVE_WORDEXP)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
|
||||
message(STATUS "wordexp.h found, wordexp support enabled")
|
||||
else()
|
||||
set(ENABLE_WORDEXP OFF)
|
||||
endif()
|
||||
endif()
|
||||
CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB)
|
||||
if(HAVE_GLOB)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1)
|
||||
if(NOT ENABLE_WORDEXP)
|
||||
message(STATUS "wordexp.h not found or disabled, glob used instead")
|
||||
endif()
|
||||
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
|
||||
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
|
||||
@@ -1866,7 +1918,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
|
||||
@@ -1894,7 +1946,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
|
||||
@@ -2020,11 +2072,6 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
||||
endif()
|
||||
if(APPLE)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
|
||||
elseif(IS_MUSL)
|
||||
@@ -2064,14 +2111,14 @@ 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()
|
||||
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||
set(CPACK_PACKAGE_CONTACT "Carter Li <zhangsongcui@live.cn>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "\
|
||||
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
|
||||
It is written mostly in C to achieve much better performance.\
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Fastfetch
|
||||
|
||||
Fastfetch 是一款类似 neofetch 的系统信息展示工具,主要用 C 编写,强调性能和可定制性。支持 Linux、macOS、Windows 7+、Android、FreeBSD、OpenBSD、NetBSD、DragonFly、Haiku、SunOS。
|
||||
|
||||
示例配置见 presets/examples,更多截图与平台说明见 Wiki。
|
||||
|
||||
## 安装
|
||||
|
||||
Linux(部分):
|
||||
- Debian 13+ / Ubuntu: apt install fastfetch
|
||||
- Arch: pacman -S fastfetch
|
||||
- Fedora: dnf install fastfetch
|
||||
- openSUSE: zypper install fastfetch
|
||||
- Linuxbrew:brew install fastfetch
|
||||
- 各发行版打包状态:https://repology.org/project/fastfetch/versions
|
||||
|
||||
macOS:
|
||||
- Homebrew:brew install fastfetch
|
||||
- MacPorts:sudo port install fastfetch
|
||||
|
||||
Windows:
|
||||
- scoop install fastfetch
|
||||
- choco install fastfetch
|
||||
- winget install fastfetch
|
||||
- MSYS2:pacman -S mingw-w64-<subsystem>-<arch>-fastfetch
|
||||
|
||||
BSD:
|
||||
- FreeBSD:pkg install fastfetch
|
||||
- NetBSD:pkgin in fastfetch
|
||||
- OpenBSD:pkg_add fastfetch
|
||||
|
||||
Android(Termux):
|
||||
- pkg install fastfetch
|
||||
|
||||
Nightly 构建:
|
||||
- https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview
|
||||
|
||||
## 源码构建
|
||||
|
||||
基本上是 `cmake . && make`。详见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
## 使用
|
||||
|
||||
- 默认运行:`fastfetch`
|
||||
- 查看所有可用模块示例:`fastfetch -c all.jsonc`
|
||||
- 以 JSON 输出指定模块:`fastfetch -s <module1>[:<module2>] --format json`
|
||||
- 完整命令行帮助:`fastfetch --help`
|
||||
- 生成最小配置:`fastfetch --gen-config [</path/to/config.jsonc>]`
|
||||
- 生成完整配置:`fastfetch --gen-config-full`
|
||||
- 请使用支持 JSON schema 的编辑器(如 VSCode)编辑配置文件!
|
||||
- 如果你连接 Github 有网络困难(智能提示不生效),可将配置文件中的 `$schema` 的值替换为 `https://gitee.com/carterl/fastfetch/raw/dev/doc/json_schema.json`
|
||||
|
||||
## 定制
|
||||
|
||||
- 配置使用 JSONC,语法与选项见 Wiki:https://github.com/fastfetch-cli/fastfetch/wiki/Configuration
|
||||
- 预设示例位于 presets,可用 `-c <filename>` 加载
|
||||
- Logo 选项与图像显示见文档:https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options
|
||||
- 模块格式化(示例,仅显示 GPU 名称):
|
||||
```jsonc
|
||||
{
|
||||
"modules": [
|
||||
{ "type": "gpu", "format": "{name}" }
|
||||
]
|
||||
}
|
||||
```
|
||||
详见:https://github.com/fastfetch-cli/fastfetch/wiki/Format-String-Guide
|
||||
|
||||
## 反馈与支持
|
||||
|
||||
- 使用问题:Discussions https://github.com/fastfetch-cli/fastfetch/discussions
|
||||
- 疑似缺陷:Issues https://github.com/fastfetch-cli/fastfetch/issues(请填写模版)
|
||||
|
||||
## 赞助
|
||||
|
||||
<img src="https://github.com/user-attachments/assets/a36a6501-e8b0-4a10-9061-b9206d12ffba" width="220">
|
||||
@@ -11,8 +11,9 @@
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](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 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, illumos (SunOS), and 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" />
|
||||
@@ -36,7 +37,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
|
||||
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `pacman -S fastfetch`
|
||||
* Fedora: `dnf install fastfetch`
|
||||
@@ -103,6 +105,10 @@ Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for d
|
||||
|
||||
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
### WARNING
|
||||
|
||||
Fastfetch supports a `Command` module that can run arbitrary shell commands. If you copy-paste a config file from an untrusted source, it may contain malicious commands that can harm your system or compromise your privacy. Please always review the config file before using it.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Neofetch is good enough. Why do I need fastfetch?
|
||||
@@ -317,6 +323,11 @@ If you find Fastfetch useful, please consider donating.
|
||||
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
|
||||
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
|
||||
|
||||
## Code signing
|
||||
|
||||
* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
|
||||
* This program will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it
|
||||
|
||||
## Star History
|
||||
|
||||
Give us a star to show your support!
|
||||
|
||||
+55
-1
@@ -1,3 +1,58 @@
|
||||
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
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
|
||||
|
||||
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
|
||||
|
||||
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
|
||||
|
||||
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
|
||||
|
||||
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Fix building on plucky
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 14:27:02 +0800
|
||||
|
||||
fastfetch (2.54.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.54.0
|
||||
* Test independent changelog entries for different Ubuntu releases
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 10:47:02 +0800
|
||||
|
||||
fastfetch (2.53.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.53.0
|
||||
@@ -435,4 +490,3 @@ fastfetch (2.7.1) jammy; urgency=medium
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libelf-dev, 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, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libelf-dev, 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, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build, python3-setuptools
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
fastfetch_2.53.0_source.buildinfo universe/utils optional
|
||||
Vendored
+74
-2
@@ -1,4 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# WARNING: DO NOT RUN THIS SCRIPT UNLESS YOU KNOW WHAT YOU ARE DOING.
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
set -euo pipefail
|
||||
|
||||
command -v debuild >/dev/null 2>&1 || { echo "debuild not found. Install devscripts." >&2; exit 1; }
|
||||
command -v dput >/dev/null 2>&1 || { echo "dput not found." >&2; exit 1; }
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
|
||||
OUT_DIR="$(dirname "$ROOT_DIR")"
|
||||
PPA="ppa:zhangsongcui3371/fastfetch"
|
||||
CODENAMES=( jammy noble plucky questing resolute )
|
||||
DRY_RUN=0
|
||||
|
||||
if [[ -d "$OUT_DIR/build" ]]; then
|
||||
echo "Output directory exists: $OUT_DIR/build" >&2
|
||||
echo "Please move or delete it before proceeding." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMPLATE="$ROOT_DIR/debian/changelog.tpl"
|
||||
CHANGELOG_DEBIAN="$ROOT_DIR/debian/changelog"
|
||||
|
||||
if [[ ! -f "$TEMPLATE" ]]; then
|
||||
echo "Template not found: $TEMPLATE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q '#UBUNTU_CODENAME#' "$TEMPLATE"; then
|
||||
echo "Template missing placeholder: #UBUNTU_CODENAME#" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "IMPORTANT: Before proceeding, please ensure that 'debian/changelog.tpl' is up-to-date"
|
||||
echo " with the correct version number, release notes, and maintainer information."
|
||||
echo
|
||||
echo " The template must contain a placeholder like '#UBUNTU_CODENAME#' for the codename."
|
||||
echo
|
||||
read -p "Have you reviewed and updated 'debian/changelog.tpl'? (y/N): " -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cleanup() {
|
||||
rm -f "$CHANGELOG_DEBIAN"
|
||||
rm -f "$ROOT_DIR/debian/files"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
for codename in "${CODENAMES[@]}"; do
|
||||
echo "==> Publishing distro: $codename"
|
||||
sed "s/#UBUNTU_CODENAME#/${codename}/g" "$TEMPLATE" > "$CHANGELOG_DEBIAN"
|
||||
|
||||
( cd "$ROOT_DIR" && debuild -S -i -I )
|
||||
|
||||
changes=( "$OUT_DIR"/fastfetch_*~${codename}_source.changes )
|
||||
if [[ ${#changes[@]} -ne 1 ]]; then
|
||||
echo "Unable to uniquely identify .changes for '$codename' in: $OUT_DIR" >&2
|
||||
printf 'Found:\n'; printf ' %s\n' "${changes[@]}" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $DRY_RUN -eq 1 ]]; then
|
||||
echo "[DRY-RUN] dput \"$PPA\" \"${changes[0]}\""
|
||||
else
|
||||
dput "$PPA" "${changes[0]}"
|
||||
fi
|
||||
|
||||
rm -f "$OUT_DIR"/fastfetch_*~${codename}_source.{changes,dsc,tar.*}
|
||||
|
||||
echo "<== Done: $codename"
|
||||
done
|
||||
|
||||
+71
-12
@@ -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. {nix-all}: Total number of all nix packages\n 45. {flatpak-all}: Total number of all flatpak app packages\n 46. {brew-all}: Total number of all brew packages\n 47. {guix-all}: Total number of all guix packages\n 48. {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",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
@@ -1008,7 +1008,7 @@
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "Set whether to show icon before string keys",
|
||||
"description": "Set whether to show builtin icon before string keys",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": "none",
|
||||
@@ -1020,11 +1020,31 @@
|
||||
},
|
||||
{
|
||||
"const": "icon",
|
||||
"description": "Show icon keys (requires newest nerd font)"
|
||||
"description": "Show builtin icon (requires newest nerd font)"
|
||||
},
|
||||
{
|
||||
"const": "both",
|
||||
"description": "Show both icon and string keys"
|
||||
"description": "Show both icon and string keys (alias of `both-1`)"
|
||||
},
|
||||
{
|
||||
"const": "both-0",
|
||||
"description": "Show both icon and string with no spaces between them"
|
||||
},
|
||||
{
|
||||
"const": "both-1",
|
||||
"description": "Show both icon and string with a space between them"
|
||||
},
|
||||
{
|
||||
"const": "both-2",
|
||||
"description": "Show both icon and string with 2 spaces between them"
|
||||
},
|
||||
{
|
||||
"const": "both-3",
|
||||
"description": "Show both icon and string with 3 spaces between them"
|
||||
},
|
||||
{
|
||||
"const": "both-4",
|
||||
"description": "Show both icon and string with 4 spaces between them"
|
||||
}
|
||||
],
|
||||
"default": "string"
|
||||
@@ -1860,6 +1880,10 @@
|
||||
"temp": {
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"tempSensor": {
|
||||
"description": "Set the temperature sensor to use for CPU temperature detection\n* Linux: `hwmon` or `thermal` path name (eg. `hwmon0`, `thermal_zone0)`\n* macOS: SMC sensor key (eg. `Tp01`)\n* Windows: thermal zone key (eg. `\\_TZ.CPUZ`)\n* FreeBSD: sysctl key (eg. `dev.cpu.0.temperature`)\n* NetBSD: sysmon sensor key (eg. `coretemp0`)",
|
||||
"type": "string"
|
||||
},
|
||||
"showPeCoreCount": {
|
||||
"description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
|
||||
"type": "boolean",
|
||||
@@ -1975,7 +1999,7 @@
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"description": "Print some colored blocks",
|
||||
"description": "Display the terminal's 16-color palette",
|
||||
"const": "colors"
|
||||
},
|
||||
"symbol": {
|
||||
@@ -2081,6 +2105,21 @@
|
||||
"description": "Set the command text to be executed",
|
||||
"type": "string"
|
||||
},
|
||||
"useStdErr": {
|
||||
"description": "Set if stderr should be used instead of stdout for command output",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"parallel": {
|
||||
"description": "Set if the command should be executed in parallel with other commands\nImprove performance when using multiple commands, but may cause issues with some commands",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"splitLines": {
|
||||
"description": "Set if the command output should be split into multiple lines",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2326,7 +2365,7 @@
|
||||
]
|
||||
},
|
||||
"hideFolders": {
|
||||
"description": "A list of folder paths to hide from the disk output",
|
||||
"description": "A list of folder paths (or glob patterns) to hide from the disk output",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
@@ -2342,7 +2381,7 @@
|
||||
"uniqueItems": true
|
||||
}
|
||||
],
|
||||
"default": "/efi:/boot:/boot/efi:/boot/firmware"
|
||||
"default": "/efi:/boot:/boot/*"
|
||||
},
|
||||
"hideFS": {
|
||||
"description": "A list of file systems to hide from the disk output",
|
||||
@@ -2925,8 +2964,11 @@
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"outputColor": {
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
"$ref": "#/$defs/keyboardFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
@@ -3160,6 +3202,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",
|
||||
@@ -3257,8 +3313,11 @@
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"outputColor": {
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/memoryFormat"
|
||||
"$ref": "#/$defs/mouseFormat"
|
||||
},
|
||||
"condition": {
|
||||
"$ref": "#/$defs/conditions"
|
||||
|
||||
@@ -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.
|
||||
|
||||
{
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
},
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"text": "clang --version | head -1 | awk '{print $NF}'",
|
||||
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
@@ -9,7 +9,6 @@ typedef struct FFPlatformSysinfo
|
||||
FFstrbuf release;
|
||||
FFstrbuf version;
|
||||
FFstrbuf architecture;
|
||||
FFstrbuf displayVersion;
|
||||
uint32_t pageSize;
|
||||
} FFPlatformSysinfo;
|
||||
|
||||
@@ -19,8 +18,14 @@ 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)
|
||||
|
||||
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,8 +103,41 @@ FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultV
|
||||
void ffStrbufUpperCase(FFstrbuf* strbuf);
|
||||
void ffStrbufLowerCase(FFstrbuf* strbuf);
|
||||
|
||||
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* @brief Read a line from a 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
|
||||
(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.
|
||||
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.
|
||||
*/
|
||||
static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
{
|
||||
return ffStrbufGetdelim(lineptr, n, '\n', buffer);
|
||||
}
|
||||
/**
|
||||
* @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
* @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)
|
||||
{
|
||||
ffStrbufGetdelimRestore(lineptr, n, '\n', buffer);
|
||||
}
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
|
||||
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
@@ -122,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);
|
||||
@@ -142,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
|
||||
@@ -187,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)
|
||||
@@ -218,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)
|
||||
@@ -235,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;
|
||||
}
|
||||
|
||||
@@ -301,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)
|
||||
@@ -361,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);
|
||||
@@ -40,11 +40,9 @@ const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result)
|
||||
|
||||
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result)
|
||||
{
|
||||
ffStrbufClear(result);
|
||||
if (!cf)
|
||||
{
|
||||
ffStrbufClear(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CFGetTypeID(cf) == CFStringGetTypeID())
|
||||
{
|
||||
@@ -56,6 +54,8 @@ const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result)
|
||||
else
|
||||
{
|
||||
uint32_t length = (uint32_t) CFStringGetLength(cfStr);
|
||||
if (length == 0)
|
||||
return NULL;
|
||||
ffStrbufEnsureFixedLengthFree(result, (uint32_t) CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8));
|
||||
if(!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8))
|
||||
return "CFStringGetCString() failed";
|
||||
@@ -68,7 +68,9 @@ const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result)
|
||||
{
|
||||
CFDataRef cfData = (CFDataRef)cf;
|
||||
uint32_t length = (uint32_t)CFDataGetLength(cfData);
|
||||
ffStrbufEnsureFree(result, length + 1);
|
||||
if (length == 0)
|
||||
return NULL;
|
||||
ffStrbufEnsureFixedLengthFree(result, length + 1);
|
||||
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*)result->chars);
|
||||
result->length = (uint32_t)strnlen(result->chars, length);
|
||||
result->chars[result->length] = '\0';
|
||||
@@ -79,6 +81,29 @@ const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result)
|
||||
{
|
||||
ffStrbufClear(result);
|
||||
if (!cf)
|
||||
return NULL;
|
||||
|
||||
if (CFGetTypeID(cf) == CFDataGetTypeID())
|
||||
{
|
||||
CFDataRef cfData = (CFDataRef)cf;
|
||||
uint32_t length = (uint32_t)CFDataGetLength(cfData);
|
||||
if (length == 0)
|
||||
return NULL;
|
||||
ffStrbufEnsureFixedLengthFree(result, length + 1);
|
||||
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*)result->chars);
|
||||
result->length = length;
|
||||
result->chars[result->length] = '\0';
|
||||
}
|
||||
else
|
||||
return "TypeID is not 'CFData'";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result)
|
||||
{
|
||||
CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
|
||||
@@ -88,6 +113,15 @@ const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* r
|
||||
return ffCfStrGetString(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result)
|
||||
{
|
||||
CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
|
||||
if(cf == NULL)
|
||||
return "CFDictionaryGetValue() failed";
|
||||
|
||||
return ffCfDataGetDataAsString(cf, result);
|
||||
}
|
||||
|
||||
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
|
||||
{
|
||||
CFBooleanRef cf = (CFBooleanRef)CFDictionaryGetValue(dict, key);
|
||||
@@ -8,11 +8,13 @@
|
||||
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result);
|
||||
const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result);
|
||||
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result);
|
||||
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result);
|
||||
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
|
||||
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
|
||||
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
|
||||
const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result);
|
||||
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length);
|
||||
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
|
||||
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result);
|
||||
|
||||
static inline CFNumberRef ffCfCreateInt(int value)
|
||||
@@ -22,6 +24,7 @@ static inline CFNumberRef ffCfCreateInt(int value)
|
||||
|
||||
static inline void cfReleaseWrapper(void* type)
|
||||
{
|
||||
assert(type);
|
||||
if (*(CFTypeRef*) type)
|
||||
CFRelease(*(CFTypeRef*) type);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "smc_temps.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
@@ -137,14 +137,11 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV
|
||||
|
||||
static const char *smcOpen(io_connect_t *conn)
|
||||
{
|
||||
io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
|
||||
FF_IOOBJECT_AUTO_RELEASE io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
|
||||
if (!device)
|
||||
return "No SMC device found";
|
||||
|
||||
kern_return_t result = IOServiceOpen(device, mach_task_self(), 0, conn);
|
||||
IOObjectRelease(device);
|
||||
|
||||
if (result != kIOReturnSuccess)
|
||||
if (IOServiceOpen(device, mach_task_self(), 0, conn) != kIOReturnSuccess)
|
||||
return "IOServiceOpen() failed";
|
||||
|
||||
return NULL;
|
||||
@@ -159,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;
|
||||
}
|
||||
|
||||
@@ -280,15 +272,32 @@ static bool detectTemp(io_connect_t conn, const char* sensor, double* sum)
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result)
|
||||
static io_connect_t conn;
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result)
|
||||
{
|
||||
static io_connect_t conn;
|
||||
if (!conn)
|
||||
{
|
||||
if (smcOpen(&conn) != NULL)
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
else if (conn == (io_connect_t) -1)
|
||||
if (conn == (io_connect_t) -1)
|
||||
return "Could not open SMC connection";
|
||||
|
||||
if (!detectTemp(conn, sensor, result))
|
||||
return "Could not read SMC temperature";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result)
|
||||
{
|
||||
if (!conn)
|
||||
{
|
||||
if (smcOpen(&conn) != NULL)
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
if (conn == (io_connect_t) -1)
|
||||
return "Could not open SMC connection";
|
||||
|
||||
uint32_t count = 0;
|
||||
@@ -30,4 +30,5 @@ enum FFTempType
|
||||
FF_TEMP_MEMORY,
|
||||
};
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result);
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result);
|
||||
@@ -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);
|
||||
|
||||
+1
-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
|
||||
|
||||
@@ -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,221 +0,0 @@
|
||||
#include "fastfetch.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 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);
|
||||
}
|
||||
+5
-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,9 @@ 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)
|
||||
@@ -16,6 +16,10 @@ void ffPlatformInit(FFPlatform* platform)
|
||||
ffStrbufInit(&platform->hostName);
|
||||
ffStrbufInit(&platform->userShell);
|
||||
|
||||
#ifdef _WIN32
|
||||
ffStrbufInit(&platform->sid);
|
||||
#endif
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
|
||||
ffStrbufInit(&info->name);
|
||||
@@ -51,12 +55,15 @@ void ffPlatformDestroy(FFPlatform* platform)
|
||||
ffStrbufDestroy(&platform->userShell);
|
||||
ffStrbufDestroy(&platform->fullUserName);
|
||||
|
||||
#ifdef _WIN32
|
||||
ffStrbufDestroy(&platform->sid);
|
||||
#endif
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
ffStrbufDestroy(&info->architecture);
|
||||
ffStrbufDestroy(&info->name);
|
||||
ffStrbufDestroy(&info->release);
|
||||
ffStrbufDestroy(&info->version);
|
||||
ffStrbufDestroy(&info->displayVersion);
|
||||
}
|
||||
|
||||
void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path)
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "FFPlatform.h"
|
||||
#include "common/FFPlatform.h"
|
||||
|
||||
void ffPlatformInitImpl(FFPlatform* platform);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "FFPlatform_private.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/FFstrbuf.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/io.h"
|
||||
#include "fastfetch_config.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
@@ -21,21 +22,21 @@
|
||||
|
||||
static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
char exePath[PATH_MAX + 1];
|
||||
char exePath[PATH_MAX];
|
||||
#if defined(__linux__) || defined (__GNU__)
|
||||
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
|
||||
if (exePathLen >= 0)
|
||||
exePath[exePathLen] = '\0';
|
||||
#elif defined(__APPLE__)
|
||||
int exePathLen = proc_pidpath((int) getpid(), exePath, sizeof(exePath));
|
||||
int exePathLen = proc_pidpath((pid_t) platform->pid, exePath, sizeof(exePath));
|
||||
#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,
|
||||
@@ -57,7 +58,7 @@ static void getExePath(FFPlatform* platform)
|
||||
|
||||
while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
|
||||
if (info.type == B_APP_IMAGE) {
|
||||
exePathLen = strlcpy(exePath, info.name, PATH_MAX);
|
||||
exePathLen = strlcpy(exePath, info.name, sizeof(exePath));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -176,13 +177,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);
|
||||
if (pwd)
|
||||
{
|
||||
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)
|
||||
@@ -211,7 +215,6 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts)
|
||||
else
|
||||
#endif
|
||||
ffStrbufAppendS(&info->architecture, uts->machine);
|
||||
ffStrbufInit(&info->displayVersion);
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
size_t length = sizeof(info->pageSize);
|
||||
@@ -223,7 +226,9 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts)
|
||||
|
||||
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)
|
||||
@@ -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 <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <sddl.h>
|
||||
|
||||
#define SECURITY_WIN32 1 // For secext.h
|
||||
#include <secext.h>
|
||||
@@ -16,7 +18,7 @@ static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH);
|
||||
if (exePathWLen == 0 && exePathWLen >= MAX_PATH) return;
|
||||
if (exePathWLen == 0 || exePathWLen >= MAX_PATH) return;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hPath = CreateFileW(exePathW, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hPath != INVALID_HANDLE_VALUE)
|
||||
@@ -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,47 +138,72 @@ 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)
|
||||
{
|
||||
// Works in MSYS2
|
||||
ffStrbufAppendS(&platform->userShell, getenv("SHELL"));
|
||||
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
|
||||
const char* userShell = getenv("SHELL");
|
||||
if (userShell)
|
||||
{
|
||||
ffStrbufAppendS(&platform->userShell, userShell);
|
||||
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
|
||||
}
|
||||
}
|
||||
|
||||
static void detectWine(FFstrbuf* buf)
|
||||
static const char* detectWine(void)
|
||||
{
|
||||
const char * __cdecl wine_get_version(void);
|
||||
HMODULE hntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (!hntdll) return;
|
||||
if (!hntdll) return NULL;
|
||||
FF_LIBRARY_LOAD_SYMBOL_LAZY(hntdll, wine_get_version);
|
||||
if (!ffwine_get_version) return;
|
||||
ffStrbufAppendS(buf, buf->length ? " - wine " : "wine ");
|
||||
ffStrbufAppendS(buf, ffwine_get_version());
|
||||
if (!ffwine_get_version) return NULL;
|
||||
return ffwine_get_version();
|
||||
}
|
||||
|
||||
static void getSystemReleaseAndVersion(FFPlatformSysinfo* info)
|
||||
@@ -199,29 +226,25 @@ static void getSystemReleaseAndVersion(FFPlatformSysinfo* info)
|
||||
(unsigned) osVersion.dwBuildNumber,
|
||||
(unsigned) ubr);
|
||||
|
||||
ffStrbufInit(&info->displayVersion);
|
||||
if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &info->displayVersion, NULL))
|
||||
{
|
||||
if (osVersion.szCSDVersion[0])
|
||||
ffStrbufSetWS(&info->displayVersion, osVersion.szCSDVersion);
|
||||
else
|
||||
ffRegReadStrbuf(hKey, L"ReleaseId", &info->displayVersion, NULL); // For old Windows 10
|
||||
}
|
||||
detectWine(&info->displayVersion);
|
||||
|
||||
ffRegReadStrbuf(hKey, L"BuildLabEx", &info->version, NULL);
|
||||
|
||||
switch (osVersion.dwPlatformId)
|
||||
const char* wineVersion = detectWine();
|
||||
if (wineVersion)
|
||||
ffStrbufSetF(&info->name, "Wine_%s", wineVersion);
|
||||
else
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +307,7 @@ static void getSystemArchitectureAndPageSize(FFPlatformSysinfo* info)
|
||||
|
||||
void ffPlatformInitImpl(FFPlatform* platform)
|
||||
{
|
||||
platform->pid = (uint32_t) GetCurrentProcessId();
|
||||
getExePath(platform);
|
||||
getHomeDir(platform);
|
||||
getCacheDir(platform);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -648,19 +723,7 @@ void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c)
|
||||
strbuf->length += num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a line from a 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] 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.
|
||||
*
|
||||
* @return true if a line has been read, false if the end of the buffer has been reached.
|
||||
*/
|
||||
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer)
|
||||
{
|
||||
assert(lineptr && n && buffer);
|
||||
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
|
||||
@@ -674,14 +737,14 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
*lineptr += *n;
|
||||
if (*lineptr >= pBufferEnd) // non-empty last line
|
||||
return false;
|
||||
**lineptr = '\n';
|
||||
**lineptr = delimiter;
|
||||
++*lineptr;
|
||||
}
|
||||
if (*lineptr >= pBufferEnd) // empty last line
|
||||
return false;
|
||||
|
||||
size_t remaining = (size_t) (pBufferEnd - *lineptr);
|
||||
char* ending = memchr(*lineptr, '\n', remaining);
|
||||
char* ending = memchr(*lineptr, delimiter, remaining);
|
||||
if (ending)
|
||||
{
|
||||
*n = (size_t) (ending - *lineptr);
|
||||
@@ -692,9 +755,7 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
/// @warning This function should be called before breaking an ffStrbufGetline loop.
|
||||
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer)
|
||||
{
|
||||
assert(buffer && lineptr && n);
|
||||
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
|
||||
@@ -705,7 +766,7 @@ void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
|
||||
*lineptr += *n;
|
||||
if (*lineptr < buffer->chars + buffer->length)
|
||||
**lineptr = '\n';
|
||||
**lineptr = delimiter;
|
||||
}
|
||||
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf)
|
||||
@@ -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,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 <windows.h>
|
||||
#include <imagehlp.h>
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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>
|
||||
|
||||
@@ -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,7 @@ static void initState(FFstate* state)
|
||||
state->titleFqdn = false;
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
state->dynamicInterval = 0;
|
||||
|
||||
{
|
||||
// don't enable bright color if the terminal is in light mode
|
||||
@@ -48,7 +47,7 @@ static void defaultConfig(void)
|
||||
|
||||
void ffInitInstance(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat>
|
||||
setlocale(LC_ALL, ".UTF8");
|
||||
#else
|
||||
@@ -74,6 +73,9 @@ static void resetConsole(void)
|
||||
#if defined(_WIN32)
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if(instance.state.dynamicInterval > 0)
|
||||
fputs("\033[?1049l", stdout); // Disable alternate buffer
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -88,16 +90,12 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
// empty; used to interrupt the poll and read syscalls
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
@@ -117,11 +115,14 @@ void ffStart(void)
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
|
||||
sigset_t newmask;
|
||||
sigemptyset(&newmask);
|
||||
sigaddset(&newmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &newmask, NULL);
|
||||
#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)
|
||||
@@ -130,14 +131,15 @@ void ffStart(void)
|
||||
if(ffDisableLinewrap)
|
||||
fputs("\033[?7l", stdout);
|
||||
|
||||
ffLogoPrint();
|
||||
if(instance.state.dynamicInterval > 0)
|
||||
{
|
||||
fputs("\033[?1049h\033[H", stdout); // Enable alternate buffer
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void ffFinish(void)
|
||||
{
|
||||
if(instance.config.logo.printRemaining)
|
||||
ffLogoPrintRemaining();
|
||||
|
||||
resetConsole();
|
||||
}
|
||||
|
||||
@@ -151,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)
|
||||
@@ -226,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
|
||||
@@ -256,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>
|
||||
@@ -15,18 +15,15 @@
|
||||
|
||||
#if FF_HAVE_WORDEXP
|
||||
#include <wordexp.h>
|
||||
#elif FF_HAVE_GLOB
|
||||
#warning "<wordexp.h> is not available, use <glob.h> instead"
|
||||
#include <glob.h>
|
||||
#else
|
||||
#warning "Neither <wordexp.h> nor <glob.h> is available"
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
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);
|
||||
@@ -136,14 +133,14 @@ bool ffAppendFileBufferRelative(int dfd, const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out)
|
||||
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
#if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056
|
||||
#if FF_HAVE_WORDEXP
|
||||
|
||||
wordexp_t exp;
|
||||
if (wordexp(in, &exp, 0) != 0)
|
||||
if (wordexp(in, &exp, 0) != 0) // WARN: 0 = no safety flags; command substitution allowed
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc >= 1)
|
||||
@@ -154,16 +151,23 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
|
||||
wordfree(&exp);
|
||||
|
||||
#elif FF_HAVE_GLOB
|
||||
#else
|
||||
|
||||
glob_t gb;
|
||||
if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0)
|
||||
if (glob(in, GLOB_NOSORT
|
||||
#ifdef GLOB_TILDE
|
||||
| GLOB_TILDE
|
||||
#endif
|
||||
#ifdef GLOB_BRACE
|
||||
| GLOB_BRACE
|
||||
#endif
|
||||
, NULL, &gb) != 0)
|
||||
return false;
|
||||
|
||||
if (gb.gl_matchc >= 1)
|
||||
if (gb.gl_pathc >= 1)
|
||||
{
|
||||
result = true;
|
||||
ffStrbufSetS(out, gb.gl_pathv[gb.gl_matchc > 1 ? ffTimeGetNow() % gb.gl_matchc : 0]);
|
||||
ffStrbufSetS(out, gb.gl_pathv[gb.gl_pathc > 1 ? ffTimeGetNow() % (unsigned) gb.gl_pathc : 0]);
|
||||
}
|
||||
|
||||
globfree(&gb);
|
||||
@@ -367,3 +371,8 @@ FFNativeFD ffGetNullFD(void)
|
||||
hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
bool ffRemoveFile(const char* fileName)
|
||||
{
|
||||
return unlink(fileName) == 0;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "io.h"
|
||||
#include "common/io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "common/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
@@ -102,31 +102,48 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(handle, buffer);
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
UNICODE_STRING fileNameW;
|
||||
ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) {
|
||||
.Length = (USHORT) strlen(fileName),
|
||||
.Buffer = (PCHAR) fileName
|
||||
}, TRUE);
|
||||
if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE;
|
||||
assert(fileNameLen <= 0x7FFF);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hFile;
|
||||
HANDLE hFile;
|
||||
IO_STATUS_BLOCK iosb = {};
|
||||
ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &fileNameW,
|
||||
}, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE));
|
||||
RtlFreeUnicodeString(&fileNameW);
|
||||
|
||||
if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED)
|
||||
if(!NT_SUCCESS(NtOpenFile(&hFile,
|
||||
(directory ? FILE_LIST_DIRECTORY | FILE_TRAVERSE : FILE_READ_DATA | FILE_READ_EA) | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &(UNICODE_STRING) {
|
||||
.Buffer = (PWSTR) fileName,
|
||||
.Length = fileNameLen * (USHORT) sizeof(wchar_t),
|
||||
.MaximumLength = (fileNameLen + 1) * (USHORT) sizeof(wchar_t),
|
||||
},
|
||||
.Attributes = OBJ_CASE_INSENSITIVE,
|
||||
},
|
||||
&iosb,
|
||||
FILE_SHARE_READ | (directory ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0),
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)
|
||||
)))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
{
|
||||
wchar_t fileNameW[MAX_PATH];
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, fileNameW, ARRAY_SIZE(fileNameW));
|
||||
if (len == 0) return INVALID_HANDLE_VALUE;
|
||||
// Implies `fileNameW[len] = L'\0';` and `len` includes the null terminator
|
||||
|
||||
for (int i = 0; i < len - 1; ++i)
|
||||
{
|
||||
if (fileNameW[i] == L'/')
|
||||
fileNameW[i] = L'\\';
|
||||
}
|
||||
|
||||
return openatW(dfd, fileNameW, (uint16_t)(len - 1), directory);
|
||||
}
|
||||
|
||||
bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
|
||||
@@ -371,3 +388,8 @@ FFNativeFD ffGetNullFD(void)
|
||||
});
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
bool ffRemoveFile(const char* fileName)
|
||||
{
|
||||
return DeleteFileA(fileName) != FALSE;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -158,6 +158,16 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
}
|
||||
case 'c': case 'C': {
|
||||
if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyCommandOptions))) FFCommandOptions options;
|
||||
ffInitCommandOptions(&options);
|
||||
if (module) ffCommandModuleInfo.parseJsonObject(&options, module);
|
||||
ffPrepareCommand(&options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': case 'D': {
|
||||
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
|
||||
{
|
||||
@@ -220,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))
|
||||
@@ -288,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
|
||||
@@ -319,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)
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "kmod.h"
|
||||
#include "common/kmod.h"
|
||||
|
||||
#if __linux__
|
||||
#include "common/io/io.h"
|
||||
#include "common/io.h"
|
||||
|
||||
bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ bool ffKmodLoaded(const char* modName)
|
||||
return modfind(modName) >= 0;
|
||||
}
|
||||
#elif __NetBSD__
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <sys/param.h>
|
||||
@@ -75,7 +75,7 @@ bool ffKmodLoaded(const char* modName)
|
||||
return false;
|
||||
}
|
||||
#elif __APPLE__
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "common/apple/cf_helpers.h"
|
||||
#include <IOKit/kext/KextManager.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
@@ -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
|
||||
@@ -89,7 +89,7 @@ bool ffNetifGetDefaultRouteImplV4(FFNetifDefaultRouteResult* result)
|
||||
|
||||
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
|
||||
uint32_t minMetric = UINT32_MAX;
|
||||
int routeCount = 0;
|
||||
FF_MAYBE_UNUSED int routeCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -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
|
||||
@@ -299,7 +305,7 @@ bool ffNetifGetDefaultRouteImplV6(FFNetifDefaultRouteResult* result)
|
||||
|
||||
uint8_t buffer[1024 * 16]; // 16 KB buffer should be sufficient
|
||||
uint32_t minMetric = UINT32_MAX;
|
||||
int routeCount = 0;
|
||||
FF_MAYBE_UNUSED int routeCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -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)
|
||||
@@ -64,13 +63,3 @@ const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ffIsAbsolutePath(const char* path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (ffCharIsEnglishAlphabet(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) // drive letter path
|
||||
|| (path[0] == '\\' && path[1] == '\\'); // UNC path
|
||||
#else
|
||||
return path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -28,17 +28,12 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
ffPrintColor(&instance.config.display.colorKeys);
|
||||
}
|
||||
|
||||
bool hasIcon = false;
|
||||
if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_ICON && moduleArgs && moduleArgs->keyIcon.length > 0)
|
||||
{
|
||||
ffStrbufWriteTo(&moduleArgs->keyIcon, stdout);
|
||||
hasIcon = true;
|
||||
}
|
||||
|
||||
if (instance.config.display.keyType & FF_MODULE_KEY_TYPE_STRING)
|
||||
{
|
||||
if(hasIcon)
|
||||
putchar(' ');
|
||||
ffPrintCharTimes(' ', instance.config.display.keyType >> FF_MODULE_KEY_TYPE_SPACE_SHIFT);
|
||||
|
||||
//NULL check is required for modules with custom keys, e.g. disk with the folder path
|
||||
if((printType & FF_PRINT_TYPE_NO_CUSTOM_KEY) || !moduleArgs || moduleArgs->key.length == 0)
|
||||
@@ -136,6 +131,12 @@ void ffPrintCharTimes(char c, uint32_t times)
|
||||
if(times == 0)
|
||||
return;
|
||||
|
||||
if(times == 1)
|
||||
{
|
||||
putchar(c);
|
||||
return;
|
||||
}
|
||||
|
||||
char str[32];
|
||||
memset(str, c, sizeof(str)); //2 instructions when compiling with AVX2 enabled
|
||||
for(uint32_t i = sizeof(str); i <= times; i += (uint32_t)sizeof(str))
|
||||
@@ -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>
|
||||
@@ -58,11 +58,9 @@ static inline int ffPipe2(int* fds, int flags)
|
||||
|
||||
|
||||
// Not thread-safe
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
|
||||
{
|
||||
int pipes[2];
|
||||
const int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
||||
return "pipe() failed";
|
||||
|
||||
@@ -146,7 +144,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
if(childPid == 0)
|
||||
{
|
||||
//Child
|
||||
// Child process
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
putenv("LANG=C.UTF-8");
|
||||
@@ -157,11 +155,24 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
#endif
|
||||
|
||||
close(pipes[1]);
|
||||
outHandle->pid = childPid;
|
||||
outHandle->pipeRead = pipes[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
{
|
||||
assert(handle->pipeRead != -1);
|
||||
assert(handle->pid != -1);
|
||||
|
||||
const int32_t timeout = instance.config.general.processingTimeout;
|
||||
FF_AUTO_CLOSE_FD int childPipeFd = handle->pipeRead;
|
||||
pid_t childPid = handle->pid;
|
||||
handle->pipeRead = -1;
|
||||
handle->pid = -1;
|
||||
char str[FF_PIPE_BUFSIZ];
|
||||
|
||||
while(1)
|
||||
for (;;)
|
||||
{
|
||||
if (timeout >= 0)
|
||||
{
|
||||
@@ -173,30 +184,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (pollret < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
else if (pollret < 0 || (pollfd.revents & POLLERR))
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
return pollret < 0
|
||||
? "poll(&pollfd, 1, timeout) error: pollret < 0"
|
||||
: "poll(&pollfd, 1, timeout) error: pollfd.revents & POLLERR";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,20 +205,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (!WIFEXITED(stat_loc))
|
||||
return "child process exited abnormally";
|
||||
if (WEXITSTATUS(stat_loc) == 127)
|
||||
return "command was not found";
|
||||
return "command not found";
|
||||
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else if (nRead < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
return NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
||||
}
|
||||
@@ -233,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__)
|
||||
|
||||
@@ -281,9 +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);
|
||||
}
|
||||
|
||||
if (exePath->length == 0)
|
||||
ffStrbufSetS(exePath, filePath);
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
@@ -325,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,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,8 +1,11 @@
|
||||
#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 <Windows.h>
|
||||
#include <stdalign.h>
|
||||
#include <windows.h>
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
@@ -45,12 +48,13 @@ static void argvToCmdline(char* const argv[], FFstrbuf* result)
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
const char* ffProcessSpawn(char* const argv[], bool useStdErr, FFProcessHandle* outHandle)
|
||||
{
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
const int32_t timeout = instance.config.general.processingTimeout;
|
||||
|
||||
wchar_t pipeName[32];
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u", GetCurrentProcessId());
|
||||
static unsigned pidCounter = 0;
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u-%u", instance.state.platform.pid, ++pidCounter);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
pipeName,
|
||||
@@ -82,52 +86,67 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {};
|
||||
|
||||
BOOL success;
|
||||
|
||||
STARTUPINFOA siStartInfo = {
|
||||
.cb = sizeof(siStartInfo),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
STARTUPINFOA siStartInfo = {
|
||||
.cb = sizeof(siStartInfo),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
BOOL success = CreateProcessA(
|
||||
NULL, // application name
|
||||
cmdline.chars, // command line
|
||||
NULL, // process security attributes
|
||||
NULL, // primary thread security attributes
|
||||
TRUE, // handles are inherited
|
||||
0, // creation flags
|
||||
NULL, // use parent's environment
|
||||
NULL, // use parent's current directory
|
||||
&siStartInfo, // STARTUPINFO pointer
|
||||
&piProcInfo // receives PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
CloseHandle(hChildPipeWrite);
|
||||
if(!success)
|
||||
{
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
return "command not found";
|
||||
return "CreateProcessA() failed";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hProcess = piProcInfo.hProcess;
|
||||
FF_MAYBE_UNUSED FF_AUTO_CLOSE_FD HANDLE hThread = piProcInfo.hThread;
|
||||
CloseHandle(piProcInfo.hThread); // we don't need the thread handle
|
||||
outHandle->pid = piProcInfo.hProcess;
|
||||
outHandle->pipeRead = hChildPipeRead;
|
||||
hChildPipeRead = INVALID_HANDLE_VALUE; // ownership transferred, don't close it
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
{
|
||||
assert(handle->pipeRead != INVALID_HANDLE_VALUE);
|
||||
assert(handle->pid != INVALID_HANDLE_VALUE);
|
||||
|
||||
int32_t timeout = instance.config.general.processingTimeout;
|
||||
FF_AUTO_CLOSE_FD HANDLE hProcess = handle->pid;
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle->pipeRead;
|
||||
handle->pid = INVALID_HANDLE_VALUE;
|
||||
handle->pipeRead = INVALID_HANDLE_VALUE;
|
||||
|
||||
char str[FF_PIPE_BUFSIZ];
|
||||
DWORD nRead = 0;
|
||||
OVERLAPPED overlapped = { };
|
||||
OVERLAPPED overlapped = {};
|
||||
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
|
||||
do
|
||||
{
|
||||
@@ -136,7 +155,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
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
|
||||
@@ -156,7 +175,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "GetOverlappedResult"
|
||||
#if __aarch64__
|
||||
#if !FF_WIN7_COMPAT
|
||||
"Ex"
|
||||
#endif
|
||||
"(hChildPipeRead) failed";
|
||||
@@ -164,7 +183,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
break;
|
||||
|
||||
case ERROR_BROKEN_PIPE:
|
||||
return NULL;
|
||||
goto exit;
|
||||
|
||||
default:
|
||||
CancelIo(hChildPipeRead);
|
||||
@@ -175,13 +194,27 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
ffStrbufAppendNS(buffer, nRead, str);
|
||||
} while (nRead > 0);
|
||||
|
||||
exit:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -204,12 +237,15 @@ bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFst
|
||||
}
|
||||
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(alignof(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* imageName = (UNICODE_STRING*)buffer;
|
||||
ffStrbufSetNWS(exe, imageName->Length / sizeof(wchar_t), imageName->Buffer);
|
||||
|
||||
if (exePath) ffStrbufSet(exePath, exe);
|
||||
}
|
||||
else
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -402,7 +402,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Parsing SMBIOS table structures");
|
||||
int structureCount = 0;
|
||||
FF_MAYBE_UNUSED int structureCount = 0;
|
||||
for (
|
||||
const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer.chars;
|
||||
(const uint8_t*) header < (const uint8_t*) buffer.chars + buffer.length;
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "sysctl.h"
|
||||
#include "common/sysctl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/temps.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/textModifier.h"
|
||||
#include "common/stringUtils.h"
|
||||
|
||||
void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig config, const FFModuleArgs* module)
|
||||
{
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "common/time.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char ffTimeInternalBuffer[64]; // Reduce memory usage and prevent redundant allocations
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat"
|
||||
#endif
|
||||
|
||||
const char* ffTimeToFullStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
const struct tm* tm = localtime(&tsec);
|
||||
|
||||
uint32_t len = 0;
|
||||
len += (uint32_t) strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer) - len, "%FT%T", tm);
|
||||
len += (uint32_t) snprintf(ffTimeInternalBuffer + len, ARRAY_SIZE(ffTimeInternalBuffer) - len, ".%03u", (unsigned) (msec % 1000));
|
||||
len += (uint32_t) strftime(ffTimeInternalBuffer + len, ARRAY_SIZE(ffTimeInternalBuffer) - len, "%z", tm);
|
||||
return ffTimeInternalBuffer;
|
||||
}
|
||||
|
||||
const char* ffTimeToShortStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
|
||||
strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer), "%F %T", localtime(&tsec));
|
||||
return ffTimeInternalBuffer;
|
||||
}
|
||||
|
||||
const char* ffTimeToTimeStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
|
||||
uint32_t len = (uint32_t) strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer), "%T", localtime(&tsec));
|
||||
sprintf(ffTimeInternalBuffer + len, ".%03u", (unsigned) (msec % 1000));
|
||||
return ffTimeInternalBuffer;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
FFTimeGetAgeResult ffTimeGetAge(uint64_t birthMs, uint64_t nowMs)
|
||||
{
|
||||
FFTimeGetAgeResult result = {};
|
||||
if (__builtin_expect(birthMs == 0 || nowMs < birthMs, 0))
|
||||
return result;
|
||||
|
||||
time_t birth_s = (time_t) (birthMs / 1000);
|
||||
struct tm birth_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&birth_tm, &birth_s);
|
||||
#else
|
||||
localtime_r(&birth_s, &birth_tm);
|
||||
#endif
|
||||
|
||||
time_t now_s = (time_t) (nowMs / 1000);
|
||||
struct tm now_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&now_tm, &now_s);
|
||||
#else
|
||||
localtime_r(&now_s, &now_tm);
|
||||
#endif
|
||||
|
||||
result.years = (uint32_t) (now_tm.tm_year - birth_tm.tm_year);
|
||||
if (now_tm.tm_yday < birth_tm.tm_yday)
|
||||
result.years--;
|
||||
|
||||
birth_tm.tm_year += (int) result.years;
|
||||
birth_s = mktime(&birth_tm);
|
||||
uint32_t diff_s = (uint32_t) (now_s - birth_s);
|
||||
result.daysOfYear = diff_s / (24 * 60 * 60);
|
||||
|
||||
birth_tm.tm_year += 1;
|
||||
result.yearsFraction = (double) diff_s / (double) (mktime(&birth_tm) - birth_s) + result.years;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
double ffQpcMultiplier;
|
||||
|
||||
__attribute__((constructor))
|
||||
static void ffTimeInitQpcMultiplier(void)
|
||||
{
|
||||
LARGE_INTEGER frequency;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
ffQpcMultiplier = 1000. / (double) frequency.QuadPart;
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "wcwidth.h"
|
||||
#include "common/wcwidth.h"
|
||||
#include "3rdparty/widecharwidth/widechar_width_c.h"
|
||||
|
||||
int mk_wcwidth(uint32_t wc)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user