mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Compare commits
279 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3c69c4569 | |||
| 45f523adb8 | |||
| f7cc4fb4b1 | |||
| ddec13be29 | |||
| 74ac023cb0 | |||
| 7f75d42ec8 | |||
| e53acf42ec | |||
| 18233a27c5 | |||
| 9857f48bb9 | |||
| 289976372f | |||
| 72d2ce4b43 | |||
| eb0faec74a | |||
| 767f99cffa | |||
| 7caa8d4618 | |||
| 88c12486bf | |||
| 8b357c27b4 | |||
| a7a8f2f461 | |||
| 5e5c0b4a58 | |||
| 154657b455 | |||
| 3866f27448 | |||
| b4f29918ed | |||
| b29b78b321 | |||
| 917b049030 | |||
| 4843dedb4d | |||
| 69373906ca | |||
| 24a6efa227 | |||
| 9004d9e05c | |||
| fa4fccd426 | |||
| 57bd741d96 | |||
| 50c8809d51 | |||
| e4c1ec916b | |||
| a4bc07cba5 | |||
| 40e542852f | |||
| bde2d67f25 | |||
| 6d1bde17c8 | |||
| ad0c2aa2e9 | |||
| ddbd198864 | |||
| 3e768ddfd4 | |||
| 6ccf8856b9 | |||
| 1caaa69deb | |||
| 5aa2798e42 | |||
| 597daddf2a | |||
| ff1c3d9888 | |||
| cc6cdb96fb | |||
| db5619541a | |||
| d94fc32f45 | |||
| 34723bba89 | |||
| a0efbd20a1 | |||
| 4d86c53e81 | |||
| 560c2acb88 | |||
| 592de4c8f2 | |||
| 8cbe3f6453 | |||
| ec8ee1a509 | |||
| 30ae8a2f96 | |||
| 5337e5cead | |||
| 576fcd7d3d | |||
| 64615e635f | |||
| 38c22bf771 | |||
| 064f624eab | |||
| 26e5790a78 | |||
| 48cecd0ad1 | |||
| 69e57e52ab | |||
| dbd6e45aba | |||
| 3714dfdca7 | |||
| 06b1051a7e | |||
| 8edb7d3833 | |||
| 8a14cbae0c | |||
| 7f727086af | |||
| 7cd79d34bb | |||
| 939165d4cf | |||
| b4f063e1da | |||
| bdc79a2995 | |||
| 2bb78af1a7 | |||
| d8e4575157 | |||
| b54e182c0f | |||
| fe89e71200 | |||
| fb69d56297 | |||
| 6c1b39ae60 | |||
| 2082e01555 | |||
| 24a9231ad0 | |||
| 3c7903cc14 | |||
| b721f9020e | |||
| bd02e5c632 | |||
| 0d5cf52f08 | |||
| f97cddf2da | |||
| 49f42cd003 | |||
| 0d7dc2d692 | |||
| 2039bed70d | |||
| 9535b6a8bf | |||
| df945e824b | |||
| 237c6f1c9e | |||
| 61131073f2 | |||
| 013abe2b3e | |||
| 63c29b10fe | |||
| f5ad07a87b | |||
| 28d40d9037 | |||
| b3bdf494ab | |||
| 8d914ace33 | |||
| 58f234638b | |||
| 7dfc0d8e60 | |||
| 2963e3bd93 | |||
| 3dfa99c232 | |||
| 804463a470 | |||
| 77466ba6f5 | |||
| 3a8819d42b | |||
| 9765885fe6 | |||
| 16b01a06e0 | |||
| c400261a11 | |||
| 9b72971dc9 | |||
| 4449173b3d | |||
| 10a249d3a8 | |||
| e91d011c8c | |||
| 4124c12bac | |||
| a927f4a04d | |||
| f3ec60a061 | |||
| 2251086c0f | |||
| 9447f1ca80 | |||
| f13b771317 | |||
| 257439477e | |||
| c702865332 | |||
| e2abe31fc1 | |||
| 82c300f7f6 | |||
| 94eb3b89e8 | |||
| f662cc0aa2 | |||
| 1526930e54 | |||
| 1cdc99f327 | |||
| d97b16950c | |||
| aff4a57092 | |||
| 826aa2e46d | |||
| 2c59a05dff | |||
| aafd773fe7 | |||
| 4356974c5b | |||
| 7f1e2d2f03 | |||
| cde2ba2c18 | |||
| a093ca2001 | |||
| fe9fcd603b | |||
| d8b2151143 | |||
| 904c9eb3c4 | |||
| 598dfd2b02 | |||
| 77d388ce1d | |||
| 9eb35d3967 | |||
| 34902db21c | |||
| cdaf5e9281 | |||
| 98833b4d74 | |||
| f995d8d806 | |||
| eb4636b947 | |||
| a7c6e1165c | |||
| 8bb88d1806 | |||
| 849ff95116 | |||
| dc29271987 | |||
| 623c5d8eb9 | |||
| e0ce520e0a | |||
| f9cd032a5f | |||
| 39b21f95b7 | |||
| dfbfb88a45 | |||
| 971a69ad1b | |||
| fddf6ddf1e | |||
| 81c625e7c9 | |||
| 97293ddee1 | |||
| 21f36b564f | |||
| 34e2b0f89c | |||
| d5ca6aa462 | |||
| 639ad436a0 | |||
| 76fce2c5a9 | |||
| 632718e1d0 | |||
| a4fababb71 | |||
| ac8741d57d | |||
| 28e412b79d | |||
| 01aa9b9516 | |||
| acd353b8b3 | |||
| c5d8d976f6 | |||
| 3d44514b24 | |||
| fb3fb1bf99 | |||
| 757e5f8174 | |||
| 3669f2aee4 | |||
| 14f26879de | |||
| 2f46a77ff2 | |||
| 10853fdf35 | |||
| 591fd558e1 | |||
| b863e65ea3 | |||
| fc61f64630 | |||
| 3483673ef7 | |||
| 9e839d3b8b | |||
| 33f121d7fb | |||
| 9500ca8f83 | |||
| 4dfbc0f909 | |||
| effb685fba | |||
| 3692e49e9b | |||
| 04d56d9b6a | |||
| 34417ae692 | |||
| 67d04a746e | |||
| 552e0f84aa | |||
| 3e880fedf7 | |||
| e5c4a6ed2c | |||
| 0bda7d80c2 | |||
| 7cb86df48d | |||
| 21e5df2826 | |||
| a5ee51e156 | |||
| bddcb4772c | |||
| a3f13bdca9 | |||
| 55444b9c4e | |||
| 2f14d7742e | |||
| 0534882f4e | |||
| ce2f2f4416 | |||
| 5259aeb039 | |||
| e51999edd1 | |||
| 2f96c847b9 | |||
| 32d6436027 | |||
| 7358326a13 | |||
| 434a879538 | |||
| 745a8dda65 | |||
| c40086615f | |||
| fe3d38e542 | |||
| f19a3b5549 | |||
| eb308e1861 | |||
| 9a4e7874d6 | |||
| d78e528527 | |||
| 81f0e4d583 | |||
| 1d9f462071 | |||
| 047dca3849 | |||
| 1f7c6ab70c | |||
| 1c49ae5324 | |||
| 2e82f8294f | |||
| b2ead8735b | |||
| 5e9166847d | |||
| 28c01599d5 | |||
| ce47a82fb5 | |||
| f1b047c32b | |||
| bc6ed4f4a2 | |||
| b1ac31f590 | |||
| 326d83f25b | |||
| 7218164088 | |||
| 6f970c36e3 | |||
| eea4150dbd | |||
| afa736c37d | |||
| 643e632368 | |||
| ffe354ab07 | |||
| f77090070c | |||
| fd5d2c84e8 | |||
| ef6af84ea1 | |||
| f64bf73279 | |||
| 157be8443d | |||
| 154e15e88f | |||
| 159122eb98 | |||
| 7b6e157a4d | |||
| c6eff111cc | |||
| f23384725f | |||
| 970863e7df | |||
| 0b473e3bff | |||
| 5a43adb62b | |||
| 1a4a949dfe | |||
| 069c20be40 | |||
| c7f0172b25 | |||
| 125759dc75 | |||
| f0a10fcc6d | |||
| c70b9cb84e | |||
| 5ebdd9a989 | |||
| 77e0d9dba1 | |||
| 55b9e274b6 | |||
| 67fe1e66b5 | |||
| ea2a26bd57 | |||
| 55b279ab09 | |||
| e5e4c8bf88 | |||
| c888254f70 | |||
| 75323d64f8 | |||
| a0c4f2febd | |||
| 4b714c7057 | |||
| 559bca4223 | |||
| 8ed28673a9 | |||
| ed9639c66b | |||
| 98b9ef74cf | |||
| e6be90614a | |||
| 20c2cdf7ba | |||
| c70787bde9 | |||
| 8835f66b8c | |||
| 2b2ebe0823 | |||
| 3ff3feb0e1 | |||
| ee4bc2302a | |||
| cd4a512291 |
@@ -19,11 +19,6 @@ assignees: ''
|
||||
|
||||
# Often helpful information:
|
||||
|
||||
Output of `fastfetch --version`:
|
||||
```
|
||||
//paste here
|
||||
```
|
||||
|
||||
The content of the configuration file you use (if any)
|
||||
```
|
||||
//paste here
|
||||
@@ -34,7 +29,7 @@ Output of `env NO_CONFIG=1 fastfetch --load-config all --show-errors --stat --mu
|
||||
Note that this output will contain you public IP. If it is not relevant for the issue, feel free to remove it before uploading.
|
||||
|
||||
If you get the following error: `Error: couldn't find config: [...]`, copy the files in [presets](../../presets/) to `/usr/share/fastfetch/presets/` or `~/.local/share/fastfetch/presets/`.
|
||||
If this isn't possible (or too much work) for you, post the output of `env NO_CONFIG=1 fastfetch --show-errors --stat --multithreading false --disable-linewrap false --hide-cursor false`.
|
||||
If this isn't possible (or too much work) for you, post the output of `env NO_CONFIG=1 fastfetch --show-errors --stat --multithreading false --disable-linewrap false --hide-cursor false && fastfetch --version`.
|
||||
-->
|
||||
|
||||
```
|
||||
|
||||
+48
-24
@@ -13,24 +13,29 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
compiler: [gcc, clang, "musl-gcc"]
|
||||
compiler: [
|
||||
{ cc: gcc, cxx: "g++" },
|
||||
{ cc: clang, cxx: "clang++" },
|
||||
{ cc: "musl-gcc", cxx: "musl-g++" }
|
||||
]
|
||||
enableFeatures: [ON, OFF]
|
||||
exclude:
|
||||
# The feature libraries are all build against glibc, so they can't be used with musl
|
||||
- compiler: "musl-gcc"
|
||||
- compiler: { cc: "musl-gcc", cxx: "musl-g++" }
|
||||
enableFeatures: ON
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
|
||||
|
||||
- name: configure project
|
||||
env:
|
||||
CC: ${{ matrix.compiler }}
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} .
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
@@ -39,7 +44,7 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: run fastfetch
|
||||
run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: ./fastfetch --stat --show-errors --no-buffer --load-config presets/all
|
||||
|
||||
- name: run flashfetch
|
||||
run: ./flashfetch
|
||||
@@ -54,10 +59,10 @@ jobs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
@@ -77,11 +82,14 @@ jobs:
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
@@ -103,7 +111,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install required packages
|
||||
run: brew install vulkan-loader molten-vk imagemagick chafa
|
||||
@@ -126,11 +134,14 @@ jobs:
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
@@ -148,7 +159,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
@@ -159,8 +170,9 @@ jobs:
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
time ./fastfetch -c presets/ci
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -180,14 +192,14 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: git zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
@@ -213,22 +225,28 @@ jobs:
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: zip fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fastfetch-win64
|
||||
path: ./fastfetch-*-Win64.zip
|
||||
path: ./fastfetch-*-Win64.*
|
||||
|
||||
win32:
|
||||
name: Win32
|
||||
@@ -241,14 +259,14 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
@@ -271,22 +289,28 @@ jobs:
|
||||
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: zip fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fastfetch-win32
|
||||
path: ./fastfetch-*-Win32.zip
|
||||
path: ./fastfetch-*-Win32.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
|
||||
+119
-2
@@ -1,4 +1,121 @@
|
||||
# 2.0.0 (beta)
|
||||
# 2.1.0
|
||||
|
||||
This release introduces a new output format: JSON result
|
||||
|
||||
Changes:
|
||||
* Users module detects and prints user login time by default. Specifying `--users-compact` to disable it
|
||||
* Fastfetch now requires yyjson 0.8.0 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package
|
||||
* Reduced information supported by `--terminal-format`, `--shell-format`
|
||||
* Some config presets (`devinfo` and `verbose`) are obseleted and removed. They are barely maintained and can be replaced with `--format json` now.
|
||||
* Custom strings in `--module-key` and `--module-format` are no longer trimmed.
|
||||
* `/boot` is hidden by default (FreeBSD, Disk)
|
||||
|
||||
Features:
|
||||
* Add `--format json`, which prints system information as JSON format
|
||||
* Add fast path for xfce4 version detection (DE, FreeBSD)
|
||||
* Support contour terminal version and font detection (Terminal / TerminalFont)
|
||||
* Support `kitty-direct` / `iterm` without specifying logo width / height. Note: in this case, the entre screen will be cleared.
|
||||
* Support new flag `--logo-separate`. If true, print modules at bottom of the logo
|
||||
* Support Apple Silicon CPU frequency detection (CPU, macOS)
|
||||
* Support user login time detection (Users)
|
||||
* Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows)
|
||||
* Print monitor type (built-in or external) (Display)
|
||||
* Support full GPU detection in WSL (Linux, GPU)
|
||||
* Add `--module-key " "` as a special case for hiding keys
|
||||
* Support `--title-format`. See `fastfetch --help title-format` for detail
|
||||
* Support `--colors-key` (Colors)
|
||||
* Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5
|
||||
* Support Windows Service Pack version detection (Kernel, Windows)
|
||||
* Support Debian point releases detection (OS, Linux)
|
||||
* Add new module `NetIO` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish.
|
||||
* Use `lscpu` to detect CPU name for ARM CPUs (CPU, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fix fastfetch hanging in specific environment (#561)
|
||||
* Fix short read when reading from stdin (Logo)
|
||||
* Fix `poll() timeout or failed` error when image is very large (Logo)
|
||||
* Fix Termux Monet terminal version detection (Terminal)
|
||||
* Fix zpool volumes detection (Disk, Linux)
|
||||
* Fix external volumes detection (Disk, Linux)
|
||||
* Fix snap package number detection on systems other than Ubuntu (Packages, Linux)
|
||||
* Fix dpkg / apt package number detection (Packages, Linux)
|
||||
* Fix bluetooth mac address detection (Bluetooth, Windows)
|
||||
|
||||
Logo:
|
||||
* Add Afterglow
|
||||
* Add Elbrus
|
||||
* Update EvolutionOS
|
||||
* Update AOSC OS
|
||||
* Update Ubuntu_old
|
||||
* Update Windows 11_small
|
||||
* Add Amazon Linux
|
||||
* Add LainOS
|
||||
* Fix colors of Slackware
|
||||
|
||||
# 2.0.5
|
||||
|
||||
Bugfixes:
|
||||
* Fix segfault when using libxrandr (#544, Display, Linux)
|
||||
* Don't print 0px (#544, Cursor)
|
||||
|
||||
Features:
|
||||
* Add option `--disk-use-available` (#543)
|
||||
* Add option `--disk-show-readonly`
|
||||
|
||||
# 2.0.4
|
||||
|
||||
Bugfixes:
|
||||
* Fix building on 32-bit FreeBSD (Memory, FreeBSD)
|
||||
* Fix `--file-raw` doesn't work (Logo)
|
||||
|
||||
Features:
|
||||
* Trait `-` as an alias for `/dev/stdin`. Available for `--file`, `--file-raw` and `--raw` (Logo)
|
||||
|
||||
# 2.0.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix typo in config parsing for --color-title (#534)
|
||||
* Fix percent formatting for `--*-format` (#535)
|
||||
* Fix loading presets for homebrew (macOS)
|
||||
|
||||
Features:
|
||||
* Add option `--percent-ndigits`
|
||||
* Add command flag `--config` as an alias of `--load-config`
|
||||
* Windows packages now include presets (Windows)
|
||||
|
||||
# 2.0.2
|
||||
|
||||
Bugfixes:
|
||||
* Workarund [a compiler bug of GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282) (Windows)
|
||||
* Fix presets not detected by file name (#529)
|
||||
|
||||
Logo:
|
||||
* Add Tuxedo OS
|
||||
|
||||
# 2.0.1
|
||||
|
||||
First stable release of Fastfetch V2
|
||||
|
||||
Changes:
|
||||
* Unescape strings only when parsing `.conf` files
|
||||
* Previously: `$ NO_CONFIG=1 fastfetch --os-key \\\\ -s os -l none` prints `\: *`. Note the backslashs are unescaped twice (once by shell and once by fastfetch).
|
||||
* Now: `$ NO_CONFIG=1 fastfetch --os-key \\\\ -s os -l none` prints `\\: *`
|
||||
* Remove option shortcut `-c` (alias of `--color`), which is more commonly used as alias of `--config`
|
||||
* Rename `--recache` to `--logo-recache` (which is used for regenerate image logo cache). Remove option shortcut `-r` (alias of `--recache`).
|
||||
* Detecting brightness of external displays with DDC/CI is no longer guarded behind `--allow-slow-operations` (Brightness)
|
||||
|
||||
Features:
|
||||
* Add `--key-width` for aligning the left edge of values, supported both for global `--key-width` and specific module `--module-key-width`
|
||||
* Add `--bar-char-elapsed`, `--bar-char-total`, `--bar-width` and `--bar-border` options
|
||||
* Add CMake option `ENABLE_SYSTEM_YYJSON`, which allow building fastfetch with system-provided yyjson (for package managers)
|
||||
* Add new module `Version`, which prints fastfetch version (like `fastfetch --version`)
|
||||
|
||||
Bugfixes:
|
||||
* Fix label detection. Use `--disk-key 'Disk ({2})'` to display it (Disk, Linux)
|
||||
* Fix some module options were not inited
|
||||
* Fix terminal version and font detection on NixOS (Terminal, Linux)
|
||||
|
||||
# 2.0.0-beta
|
||||
|
||||
Fastfetch v2 introduces a new configuration file format: JSON config. Please refer to <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for details.
|
||||
|
||||
@@ -32,7 +149,7 @@ Features:
|
||||
* Support iTerm non-ascii font detection (Terminal, macOS)
|
||||
* Add option `--title-color-user`, `--title-color-at` and `--title-color-host` (Title)
|
||||
* Add Exherbo logo and package manager count (Packages, Linux, #503)
|
||||
* Add module `Terminal Size` which prints the number of terminal width and height in charactors and pixels
|
||||
* Add module `Terminal Size` which prints the number of terminal width and height in characters and pixels
|
||||
* Add new option `--temperature-unit`
|
||||
* Better CPU and Host detection for Android (Android)
|
||||
* Support yakuake terminal version & font detection (Terminal, Linux)
|
||||
|
||||
+68
-32
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url & FetchContent
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.0.0
|
||||
VERSION 2.1.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -36,24 +36,6 @@ endif()
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
include(FetchContent)
|
||||
function(ff_fetch_dep package repo tag)
|
||||
FetchContent_Declare(
|
||||
"${package}"
|
||||
GIT_REPOSITORY "${repo}"
|
||||
GIT_TAG "${tag}"
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_GetProperties("${package}")
|
||||
if(NOT ${package}_POPULATED)
|
||||
message("-- Fetching dependency ${package}@${tag} from ${repo}")
|
||||
FetchContent_Populate(${package})
|
||||
add_subdirectory(${${package}_SOURCE_DIR} ${${package}_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
ff_fetch_dep(yyjson "https://github.com/ibireme/yyjson" "0.7.0")
|
||||
|
||||
#####################
|
||||
# Configure options #
|
||||
#####################
|
||||
@@ -85,8 +67,10 @@ cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
|
||||
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_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
|
||||
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
@@ -115,10 +99,13 @@ set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=retu
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration")
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
|
||||
enable_language(CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -fno-exceptions -fno-rtti")
|
||||
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")
|
||||
endif()
|
||||
|
||||
@@ -129,8 +116,8 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
endif()
|
||||
|
||||
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
|
||||
if(NOT WIN32)
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
|
||||
@@ -138,8 +125,8 @@ if(NOT WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(STATUS "Enabling LTO")
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT IPO_SUPPORTED)
|
||||
if(IPO_SUPPORTED)
|
||||
@@ -228,7 +215,6 @@ fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||
fastfetch_load_text(src/data/config_system.txt DATATEXT_CONFIG_SYSTEM)
|
||||
fastfetch_load_text(src/data/config_user.txt DATATEXT_CONFIG_USER)
|
||||
fastfetch_load_text(src/data/config_user.jsonc DATATEXT_CONFIG_USER_JSONC)
|
||||
fastfetch_load_text(src/data/modules.txt DATATEXT_MODULES)
|
||||
fastfetch_load_text(src/data/help.txt DATATEXT_HELP)
|
||||
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
|
||||
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
|
||||
@@ -270,11 +256,14 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
|
||||
|
||||
set(LIBFASTFETCH_SRC
|
||||
src/common/bar.c
|
||||
src/common/commandoption.c
|
||||
src/common/font.c
|
||||
src/common/format.c
|
||||
src/common/init.c
|
||||
src/common/jsonconfig.c
|
||||
src/common/library.c
|
||||
src/common/modules.c
|
||||
src/common/netif/netif.c
|
||||
src/common/option.c
|
||||
src/common/parsing.c
|
||||
src/common/printing.c
|
||||
@@ -283,19 +272,22 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/chassis/chassis.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
src/detection/datetime/datetime.c
|
||||
src/detection/disk/disk.c
|
||||
src/detection/displayserver/displayserver.c
|
||||
src/detection/font/font.c
|
||||
src/detection/gpu/gpu.c
|
||||
src/detection/locale/locale.c
|
||||
src/detection/media/media.c
|
||||
src/detection/netio/netio.c
|
||||
src/detection/opencl/opencl.c
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/publicip/publicip.c
|
||||
src/detection/terminalfont/terminalfont.c
|
||||
src/detection/terminalshell/terminalshell.c
|
||||
src/detection/version/version.c
|
||||
src/detection/vulkan/vulkan.c
|
||||
src/detection/weather/weather.c
|
||||
src/logo/builtin.c
|
||||
src/logo/image/im6.c
|
||||
src/logo/image/im7.c
|
||||
@@ -329,6 +321,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/localip/localip.c
|
||||
src/modules/memory/memory.c
|
||||
src/modules/monitor/monitor.c
|
||||
src/modules/netio/netio.c
|
||||
src/modules/opencl/opencl.c
|
||||
src/modules/opengl/opengl.c
|
||||
src/modules/os/os.c
|
||||
@@ -350,6 +343,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/title/title.c
|
||||
src/modules/uptime/uptime.c
|
||||
src/modules/users/users.c
|
||||
src/modules/version/version.c
|
||||
src/modules/vulkan/vulkan.c
|
||||
src/modules/wallpaper/wallpaper.c
|
||||
src/modules/weather/weather.c
|
||||
@@ -368,6 +362,7 @@ 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_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
@@ -396,6 +391,7 @@ if(LINUX)
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/monitor/monitor_linux.c
|
||||
src/detection/netio/netio_linux.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/packages/packages_linux.c
|
||||
@@ -419,6 +415,7 @@ if(LINUX)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_android.c
|
||||
@@ -442,6 +439,7 @@ elseif(ANDROID)
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/memory/memory_linux.c
|
||||
src/detection/monitor/monitor_nosupport.c
|
||||
src/detection/netio/netio_linux.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_android.c
|
||||
src/detection/packages/packages_linux.c
|
||||
@@ -465,6 +463,7 @@ elseif(BSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
@@ -494,6 +493,7 @@ elseif(BSD)
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_bsd.c
|
||||
src/detection/monitor/monitor_nosupport.c
|
||||
src/detection/netio/netio_bsd.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/packages/packages_linux.c
|
||||
@@ -517,6 +517,7 @@ elseif(BSD)
|
||||
elseif(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
@@ -529,7 +530,6 @@ elseif(APPLE)
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/cpuusage/cpuusage_apple.c
|
||||
src/detection/cursor/cursor_apple.m
|
||||
src/detection/disk/disk_apple.m
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/displayserver/displayserver_apple.c
|
||||
src/detection/font/font_apple.m
|
||||
@@ -542,6 +542,7 @@ elseif(APPLE)
|
||||
src/detection/media/media_apple.m
|
||||
src/detection/memory/memory_apple.c
|
||||
src/detection/monitor/monitor_apple.m
|
||||
src/detection/netio/netio_bsd.c
|
||||
src/detection/opengl/opengl_apple.c
|
||||
src/detection/os/os_apple.m
|
||||
src/detection/packages/packages_apple.c
|
||||
@@ -566,6 +567,7 @@ elseif(APPLE)
|
||||
elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_windows.c
|
||||
src/common/netif/netif_windows.c
|
||||
src/common/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/detection/battery/battery_windows.c
|
||||
@@ -589,6 +591,7 @@ elseif(WIN32)
|
||||
src/detection/media/media_nosupport.c
|
||||
src/detection/memory/memory_windows.c
|
||||
src/detection/monitor/monitor_windows.c
|
||||
src/detection/netio/netio_windows.c
|
||||
src/detection/opengl/opengl_windows.c
|
||||
src/detection/os/os_windows.cpp
|
||||
src/detection/packages/packages_windows.c
|
||||
@@ -615,19 +618,44 @@ elseif(WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DIRECTX_HEADERS)
|
||||
message(STATUS "Enabling DirectX headers for WSL")
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp)
|
||||
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/3rdparty/mk_wcwidch/wcwidth.c)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SYSTEM_YYJSON)
|
||||
find_package(yyjson)
|
||||
if(yyjson_FOUND)
|
||||
message(STATUS "System provided yyjson is used")
|
||||
else()
|
||||
message(FATAL_ERROR "ENABLE_SYSTEM_YYJSON is set but system provided yyjson is not found")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/3rdparty/yyjson/yyjson.c
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(libfastfetch OBJECT
|
||||
${LIBFASTFETCH_SRC}
|
||||
)
|
||||
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE)
|
||||
if(yyjson_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
|
||||
target_link_libraries(libfastfetch PRIVATE yyjson)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1)
|
||||
if(WIN32)
|
||||
target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE)
|
||||
endif()
|
||||
|
||||
if(HAVE_WCWIDTH)
|
||||
@@ -770,6 +798,10 @@ ff_lib_enable(DDCUTIL
|
||||
"ddcutil"
|
||||
"Ddcutil"
|
||||
)
|
||||
ff_lib_enable(DIRECTX_HEADERS
|
||||
"DirectX-Headers"
|
||||
"DirectX-Headers"
|
||||
)
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
|
||||
@@ -822,6 +854,7 @@ elseif(WIN32)
|
||||
)
|
||||
elseif(BSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "usbhid"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
@@ -847,7 +880,6 @@ target_include_directories(libfastfetch
|
||||
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE ${CMAKE_DL_LIBS}
|
||||
PRIVATE yyjson
|
||||
)
|
||||
|
||||
######################
|
||||
@@ -862,7 +894,6 @@ target_compile_definitions(fastfetch
|
||||
)
|
||||
target_link_libraries(fastfetch
|
||||
PRIVATE libfastfetch
|
||||
PRIVATE yyjson
|
||||
)
|
||||
|
||||
add_executable(flashfetch
|
||||
@@ -873,9 +904,14 @@ target_compile_definitions(flashfetch
|
||||
)
|
||||
target_link_libraries(flashfetch
|
||||
PRIVATE libfastfetch
|
||||
PRIVATE yyjson
|
||||
)
|
||||
|
||||
# Prevent fastfetch from linking to libstdc++
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(WIN32)
|
||||
set(TARGET_NAME fastfetch)
|
||||
target_sources(fastfetch
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
# Fastfetch
|
||||
|
||||
[](https://github.com/fastfetch-cli/fastfetch/actions/workflows/ci.yml)
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
|
||||
|
||||
@@ -62,6 +71,7 @@ The following libraries are used if present at runtime:
|
||||
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
|
||||
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
|
||||
* [`libddcutil`](https://github.com/rockowitz/ddcutil): Used for brightness detection of external displays
|
||||
* [`DirectX-Headers`](https://github.com/microsoft/DirectX-Headers): Used for GPU detection in WSL
|
||||
|
||||
### macOS
|
||||
|
||||
@@ -82,7 +92,7 @@ For the image logo, iTerm with iterm image protocol should work. Apple Terminal
|
||||
|
||||
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
|
||||
|
||||
For the image logo, only chafa is supported due to [a design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not included by default due to the massive dependencies of imagemagick. You must built it yourself.
|
||||
For the image logo, WezTerm with iterm image protocol is known to work, surprisingly.
|
||||
|
||||
### Android
|
||||
|
||||
@@ -91,19 +101,21 @@ For the image logo, only chafa is supported due to [a design flaw of ConPTY](htt
|
||||
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api)
|
||||
* [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android.
|
||||
|
||||
For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol.
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
|
||||
##### Available Modules
|
||||
```
|
||||
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, OpenCL, OpenGL, Packages, Player, Power Adapter, Processes, PublicIP, Separator, OS, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Vulkan, Wallpaper, Wifi, WM, WMTheme
|
||||
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme
|
||||
```
|
||||
|
||||
##### Builtin logos
|
||||
|
||||
<!-- `Content of src/logo/builtin.c`.split('\n').map(x => x.trim()).filter(x => x.startsWith('// ')).map(x => x.slice(3)).sort((a,b)=>a.toUpperCase().localeCompare(b.toUpperCase())).join(', ') -->
|
||||
<!-- `Content of src/logo/builtin.c`.split('\n').map(x => x.trim()).filter(x => x.startsWith('// ')).map(x => x.slice(3)).filter(x => x != 'LAST').sort((a, b)=>a.toUpperCase().localeCompare(b.toUpperCase())).join(', ') -->
|
||||
```
|
||||
AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, LAST, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin
|
||||
AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin
|
||||
```
|
||||
|
||||
Run `fastfetch --print-logos` to print them
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ __fastfetch_complete_help()
|
||||
"terminal-format"
|
||||
"terminalfont-format"
|
||||
"cpu-format"
|
||||
"cpu-usage-format"
|
||||
"cpuusage-format"
|
||||
"gpu-format"
|
||||
"memory-format"
|
||||
"swap-format"
|
||||
|
||||
+158
-2
@@ -17,6 +17,12 @@
|
||||
"title": "Color of the module key. Left empty to use `display.color.keys`",
|
||||
"$ref": "#/$defs/colors"
|
||||
},
|
||||
"keyWidth": {
|
||||
"title": "Width of the module key. Use 0 to use `display.keyWidth`",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
},
|
||||
"format": {
|
||||
"title": "Output format of the module",
|
||||
"type": "string"
|
||||
@@ -155,6 +161,16 @@
|
||||
"title": "Whether to preserve the aspect ratio of the logo. Supported by iTerm image protocol",
|
||||
"default": false
|
||||
},
|
||||
"recache": {
|
||||
"type": "boolean",
|
||||
"title": "If true, regenerate image logo cache",
|
||||
"default": false
|
||||
},
|
||||
"separate": {
|
||||
"type": "boolean",
|
||||
"title": "If true, print modules at bottom of the logo",
|
||||
"default": false
|
||||
},
|
||||
"chafa": {
|
||||
"type": "object",
|
||||
"title": "Chafa configuration. See chafa document for details",
|
||||
@@ -221,6 +237,11 @@
|
||||
"title": "Use multiple threads to detect values",
|
||||
"default": true
|
||||
},
|
||||
"thread": {
|
||||
"type": "boolean",
|
||||
"title": "Alias of multithreading",
|
||||
"default": true
|
||||
},
|
||||
"stat": {
|
||||
"type": "boolean",
|
||||
"title": "Show time usage (in ms) for individual modules",
|
||||
@@ -253,6 +274,11 @@
|
||||
"type": "integer",
|
||||
"title": "Set the timeout (ms) for WMI queries, `-1` for no timeout. Windows only",
|
||||
"default": 5000
|
||||
},
|
||||
"processingTimeout": {
|
||||
"type": "integer",
|
||||
"title": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout",
|
||||
"default": 1000
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -309,6 +335,12 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"keyWidth": {
|
||||
"title": "Align the width of keys to number of characters, 0 to disable",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
},
|
||||
"binaryPrefix": {
|
||||
"type": "string",
|
||||
"title": "Set the binary prefix to used when printing bytes",
|
||||
@@ -321,6 +353,8 @@
|
||||
"sizeNdigits": {
|
||||
"type": "integer",
|
||||
"title": "Set the number of digits to keep after the decimal point when formatting sizes",
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"default": 2
|
||||
},
|
||||
"sizeMaxPrefix": {
|
||||
@@ -335,13 +369,47 @@
|
||||
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
|
||||
"default": "C"
|
||||
},
|
||||
"bar": {
|
||||
"type": "object",
|
||||
"title": "Set the bar configuration",
|
||||
"properties": {
|
||||
"charElapsed": {
|
||||
"type": "string",
|
||||
"title": "Set the character to use in elapsed part",
|
||||
"default": "■"
|
||||
},
|
||||
"charTotal": {
|
||||
"type": "string",
|
||||
"title": "Set the character to use in total part",
|
||||
"default": "-"
|
||||
},
|
||||
"border": {
|
||||
"type": "boolean",
|
||||
"title": "Whether to show a border around the bar",
|
||||
"default": true
|
||||
},
|
||||
"width": {
|
||||
"type": "integer",
|
||||
"title": "Set the width of the bar, in number of characters",
|
||||
"minimum": 1,
|
||||
"default": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"percentType": {
|
||||
"type": "number",
|
||||
"title": "Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number",
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"maximum": 255,
|
||||
"default": 1
|
||||
},
|
||||
"percentNdigits": {
|
||||
"type": "number",
|
||||
"title": "Set the number of digits to keep after the decimal point when formatting percentage numbers",
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"default": 0
|
||||
},
|
||||
"noBuffer": {
|
||||
"type": "boolean",
|
||||
"title": "Whether to disable the stdout application buffer",
|
||||
@@ -490,6 +558,7 @@
|
||||
"media",
|
||||
"memory",
|
||||
"monitor",
|
||||
"netio",
|
||||
"opencl",
|
||||
"opengl",
|
||||
"os",
|
||||
@@ -509,6 +578,7 @@
|
||||
"theme",
|
||||
"uptime",
|
||||
"users",
|
||||
"version",
|
||||
"vulkan",
|
||||
"wallpaper",
|
||||
"weather",
|
||||
@@ -577,6 +647,7 @@
|
||||
"theme",
|
||||
"uptime",
|
||||
"users",
|
||||
"version",
|
||||
"vulkan",
|
||||
"wallpaper",
|
||||
"wm",
|
||||
@@ -590,6 +661,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -617,6 +691,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -640,6 +717,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -663,6 +743,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -716,6 +799,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -736,6 +822,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"title": "Text to print",
|
||||
"type": "string"
|
||||
@@ -772,6 +861,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -803,17 +895,30 @@
|
||||
"title": "Set if subvolumes should be printed",
|
||||
"default": false
|
||||
},
|
||||
"showReadOnly": {
|
||||
"type": "boolean",
|
||||
"title": "Set if read only volumes should be printed",
|
||||
"default": false
|
||||
},
|
||||
"showUnknown": {
|
||||
"type": "boolean",
|
||||
"title": "Set if unknown (unable to detect sizes) volumes should be printed",
|
||||
"default": false
|
||||
},
|
||||
"useAvailable": {
|
||||
"type": "boolean",
|
||||
"title": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -851,6 +956,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -892,7 +1000,7 @@
|
||||
"title": "Show IPs with given name prefix only",
|
||||
"type": "string"
|
||||
},
|
||||
"showDefaultRouteOnly": {
|
||||
"defaultRouteOnly": {
|
||||
"title": "Show ips that are used for default routing only",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
@@ -903,6 +1011,39 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "Network throughput (usage)",
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "netio"
|
||||
},
|
||||
"namePrefix": {
|
||||
"title": "Show IPs with given name prefix only",
|
||||
"type": "string"
|
||||
},
|
||||
"defaultRouteOnly": {
|
||||
"title": "Show ips that are used for default routing only",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -931,6 +1072,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -961,6 +1105,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -1003,6 +1150,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -1044,6 +1194,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
@@ -1077,6 +1230,9 @@
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors
|
||||
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:Version:Break:Colors
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
"sound",
|
||||
"gamepad",
|
||||
"weather",
|
||||
"netio",
|
||||
"version",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
-c all
|
||||
--pipe
|
||||
--show-errors
|
||||
--no-buffer
|
||||
--publicip-timeout 1000
|
||||
--weather-timeout 1000
|
||||
--stat
|
||||
@@ -1,3 +0,0 @@
|
||||
--disable-linewrap false
|
||||
--multithreading false
|
||||
--show-errors
|
||||
@@ -1,3 +0,0 @@
|
||||
--load-config devinfo
|
||||
--load-config all
|
||||
--load-config verbose
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "builtin",
|
||||
"source": "arch"
|
||||
},
|
||||
"display": {
|
||||
"disableLinewrap": false,
|
||||
"showErrors": true
|
||||
},
|
||||
"general": {
|
||||
"multithreading": false
|
||||
},
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
{
|
||||
"type": "os",
|
||||
"format": "Arch Linux ({12})"
|
||||
},
|
||||
"host",
|
||||
"kernel",
|
||||
"uptime",
|
||||
{
|
||||
"type": "packages",
|
||||
"format": "{} (pacman)"
|
||||
},
|
||||
"shell",
|
||||
"display",
|
||||
"de",
|
||||
"wm",
|
||||
"wmtheme",
|
||||
"theme",
|
||||
"icons",
|
||||
"font",
|
||||
"cursor",
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"cpu",
|
||||
"gpu",
|
||||
"memory",
|
||||
"disk",
|
||||
"battery",
|
||||
"poweradapter",
|
||||
"locale",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Load with --load-config examples/2.jsonc
|
||||
// Note that you must replace the image path to an existing image to display it.
|
||||
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"padding": {
|
||||
"top": 2
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": " -> "
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "\u001b[90m┌────────────────────────────────────────────────────────────┐"
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"keyWidth": 10
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "\u001b[90m└────────────────────────────────────────────────────────────┘"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "\u001b[90m┌────────────────────────────────────────────────────────────┐"
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": " OS",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "│ ├",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│ ├",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "│ └",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": " DE/WM",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "lm",
|
||||
"key": "│ ├",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "wmtheme",
|
||||
"key": "│ ├",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "icons",
|
||||
"key": "│ ├",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│ ├",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "wallpaper",
|
||||
"key": "│ └",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": " PC",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│ ├",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "display",
|
||||
"key": "│ └",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "sound",
|
||||
"key": " SND",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "player",
|
||||
"key": "│ ├",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "media",
|
||||
"key": "│ └",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "\u001b[90m└────────────────────────────────────────────────────────────┘"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percentType": 9,
|
||||
"separator": "\u001b[31m-> "
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"key": "Distro ",
|
||||
"type": "os"
|
||||
},
|
||||
{
|
||||
"key": "Shell ",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"key": "Terminal ",
|
||||
"type": "terminal"
|
||||
},
|
||||
{
|
||||
"key": "Display ",
|
||||
"type": "display"
|
||||
},
|
||||
{
|
||||
"key": "Backlight ",
|
||||
"type": "brightness"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 6,
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percentType": 6,
|
||||
"keyWidth": 11,
|
||||
"bar": {
|
||||
"charElapsed": "=",
|
||||
"charTotal": "-",
|
||||
"width": 13
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"memory",
|
||||
"swap",
|
||||
"disk",
|
||||
"battery",
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 11,
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
|
||||
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {}
|
||||
--kernel-format Sysname: {}; Release: {}; Version: {}
|
||||
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
|
||||
--processes-format Count: {}
|
||||
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak-system: {}; flatpak-user: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}; pkgtool: {}; paludis {}
|
||||
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
|
||||
--display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {}
|
||||
--de-format Process name: {}; Pretty name: {}; Version: {}
|
||||
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
|
||||
--wmtheme-format Name: {}
|
||||
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
|
||||
--font-format Font1: {}; Font2: {}; Font3: {}; Font4: {}
|
||||
--cursor-format Theme: {}; Size: {}
|
||||
--terminal-format Process: {}; Path: {}; Exe: {}
|
||||
--terminalfont-format Pretty: {}; Name: {}; Size: {}; Styles: {}
|
||||
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
|
||||
--cpu-usage-format Percentage: {}
|
||||
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {}
|
||||
--memory-format Used: {}; Total: {}; Percentage: {}
|
||||
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; External: {}; Hidden: {}; Filesystem: {}; Name: {}
|
||||
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
|
||||
--poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {}
|
||||
--player-format Pretty: {}; Name: {}; Bus: {}; Url: {}
|
||||
--media-format Pretty: {}; Name: {}; Artist: {}; Album: {}
|
||||
--datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}
|
||||
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
|
||||
--opengl-format version: {}; renderer: {}; vendor: {}
|
||||
--opencl-format version: {}; device: {}; vendor: {}
|
||||
--bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"home": "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c",
|
||||
"license": "Embed in source",
|
||||
"version": "2007-05-26 (Unicode 5.0)",
|
||||
"author": "Markus Kuhn",
|
||||
"modified": "CarterLi"
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ibireme/yyjson",
|
||||
"license": "MIT ( embed in source )",
|
||||
"version": "0.8.0",
|
||||
"author": "ibireme"
|
||||
}
|
||||
Vendored
+9447
File diff suppressed because it is too large
Load Diff
Vendored
+7910
File diff suppressed because it is too large
Load Diff
+45
-39
@@ -1,51 +1,57 @@
|
||||
#include "common/bar.h"
|
||||
#include "common/color.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "bar.h"
|
||||
|
||||
// green, yellow, red: print the color on nth (0~9) block
|
||||
// set its value == 10 means the color will not be printed
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red)
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red)
|
||||
{
|
||||
assert(green <= 10 && yellow <= 10 && red <= 10);
|
||||
assert(green <= 100 && yellow <= 100 && red <= 100);
|
||||
|
||||
// [ 0%, 5%) prints 0 blocks
|
||||
// [ 5%, 15%) prints 1 block;
|
||||
// ...
|
||||
// [85%, 95%) prints 9 blocks;
|
||||
// [95%,100%] prints 10 blocks
|
||||
percent = (uint8_t)(percent + 5) / 10;
|
||||
assert(percent <= 10);
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksGreen = (uint32_t) (green / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * instance.config.barWidth + 0.5);
|
||||
uint32_t blocksRed = (uint32_t) (red / 100.0 * instance.config.barWidth + 0.5);
|
||||
assert(blocksPercent <= instance.config.barWidth);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
ffStrbufAppendS(buffer, "\033[97m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
if(instance.config.barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < percent; ++i)
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
{
|
||||
if (i == green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
else if (i == yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
else if (i == red)
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
if (i == blocksGreen)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (i == blocksYellow)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else if (i == blocksRed)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
ffStrbufAppendS(buffer, "■");
|
||||
ffStrbufAppend(buffer, &instance.config.barCharElapsed);
|
||||
}
|
||||
|
||||
if (percent < 10)
|
||||
if (blocksPercent < instance.config.barWidth)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
ffStrbufAppendS(buffer, "\033[97m");
|
||||
for (uint8_t i = percent; i < 10; ++i)
|
||||
ffStrbufAppendS(buffer, "-");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
|
||||
for (uint32_t i = blocksPercent; i < instance.config.barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &instance.config.barCharTotal);
|
||||
}
|
||||
|
||||
if(instance.config.barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
ffStrbufAppendS(buffer, "\033[97m ]" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
// if (green < yellow)
|
||||
@@ -57,7 +63,7 @@ void ffAppendPercentBar(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_
|
||||
// [green, 100]: print green
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): PRINT RED
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses)
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses)
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
@@ -71,23 +77,23 @@ void ffAppendPercentNum(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_
|
||||
if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (percent <= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percent >= green)
|
||||
ffStrbufAppendS(buffer, "\033[32m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (percent >= yellow)
|
||||
ffStrbufAppendS(buffer, "\033[93m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\033[91m");
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%u%%", (unsigned) percent);
|
||||
ffStrbufAppendF(buffer, "%.*f%%", instance.config.percentNdigits, percent);
|
||||
|
||||
if (colored && !instance.config.pipe)
|
||||
{
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ enum
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, uint8_t percent, uint8_t green, uint8_t yellow, bool parentheses);
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "commandoption.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/time.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
|
||||
{
|
||||
yyjson_mut_doc* doc = instance.state.resultDoc;
|
||||
if (__builtin_expect(!doc, true)) return NULL;
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJson)
|
||||
baseInfo->generateJson(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
return module;
|
||||
}
|
||||
|
||||
bool ffParseModuleCommand(const char* type)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(type, baseInfo->name))
|
||||
{
|
||||
if (!genJson(baseInfo))
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
if (!ffStrStartsWith(key, "--") || !isalpha(key[2])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (baseInfo->parseCommandOptions(baseInfo, key, value)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffPrepareCommandOption(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);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
ffPrepareNetIO(&instance.config.netIo);
|
||||
|
||||
if(instance.config.multithreading)
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
ffPreparePublicIp(&instance.config.publicIP);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
|
||||
ffPrepareWeather(&instance.config.weather);
|
||||
}
|
||||
}
|
||||
|
||||
static void parseStructureCommand(const char* line, FFlist* customValues)
|
||||
{
|
||||
// handle `--set` and `--set-keyless`
|
||||
FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues)
|
||||
{
|
||||
if (ffStrbufEqualS(&customValue->key, line))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyCustomOptions))) FFCustomOptions options;
|
||||
ffInitCustomOptions(&options);
|
||||
if (customValue->printKey)
|
||||
ffStrbufAppend(&options.moduleArgs.key, &customValue->key);
|
||||
ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value);
|
||||
ffPrintCustom(&options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ffParseModuleCommand(line))
|
||||
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data)
|
||||
{
|
||||
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
|
||||
|
||||
//Parse the structure and call the modules
|
||||
uint32_t startIndex = 0;
|
||||
while (startIndex < data->structure.length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
|
||||
data->structure.chars[colonIndex] = '\0';
|
||||
|
||||
uint64_t ms = 0;
|
||||
if(instance.config.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues);
|
||||
|
||||
if(instance.config.stat)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (resultDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
|
||||
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!instance.config.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_common_commandoption
|
||||
#define FF_INCLUDED_common_commandoption
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFCustomValue
|
||||
{
|
||||
bool printKey;
|
||||
FFstrbuf key;
|
||||
FFstrbuf value;
|
||||
} FFCustomValue;
|
||||
|
||||
// Things only needed by fastfetch
|
||||
typedef struct FFdata
|
||||
{
|
||||
FFstrbuf structure;
|
||||
FFlist customValues; // List of FFCustomValue
|
||||
bool loadUserConfig;
|
||||
} FFdata;
|
||||
|
||||
bool ffParseModuleCommand(const char* type);
|
||||
bool ffParseModuleOptions(const char* key, const char* value);
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data);
|
||||
|
||||
#endif
|
||||
+2
-2
@@ -12,6 +12,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
|
||||
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT64)
|
||||
ffStrbufAppendF(buffer, "%" PRIu64, *(uint64_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
|
||||
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
|
||||
@@ -254,7 +256,5 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
|
||||
}
|
||||
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ typedef enum FFformatargtype
|
||||
{
|
||||
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||
FF_FORMAT_ARG_TYPE_UINT,
|
||||
FF_FORMAT_ARG_TYPE_UINT64,
|
||||
FF_FORMAT_ARG_TYPE_UINT16,
|
||||
FF_FORMAT_ARG_TYPE_UINT8,
|
||||
FF_FORMAT_ARG_TYPE_INT,
|
||||
|
||||
+105
-86
@@ -27,6 +27,7 @@ static void initState(FFstate* state)
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
}
|
||||
|
||||
static void defaultConfig(void)
|
||||
@@ -48,7 +49,6 @@ static void defaultConfig(void)
|
||||
#endif
|
||||
|
||||
instance.config.showErrors = false;
|
||||
instance.config.recache = false;
|
||||
instance.config.allowSlowOperations = false;
|
||||
instance.config.pipe = !isatty(STDOUT_FILENO);
|
||||
|
||||
@@ -68,58 +68,71 @@ static void defaultConfig(void)
|
||||
instance.config.multithreading = true;
|
||||
instance.config.stat = false;
|
||||
instance.config.noBuffer = false;
|
||||
instance.config.keyWidth = 0;
|
||||
|
||||
ffInitTitleOptions(&instance.config.title);
|
||||
ffInitOSOptions(&instance.config.os);
|
||||
ffInitHostOptions(&instance.config.host);
|
||||
ffStrbufInitStatic(&instance.config.barCharElapsed, "■");
|
||||
ffStrbufInitStatic(&instance.config.barCharTotal, "-");
|
||||
instance.config.barWidth = 10;
|
||||
instance.config.barBorder = true;
|
||||
instance.config.percentType = 1;
|
||||
instance.config.percentNdigits = 0;
|
||||
|
||||
ffInitBatteryOptions(&instance.config.battery);
|
||||
ffInitBiosOptions(&instance.config.bios);
|
||||
ffInitBluetoothOptions(&instance.config.bluetooth);
|
||||
ffInitBoardOptions(&instance.config.board);
|
||||
ffInitBreakOptions(&instance.config.break_);
|
||||
ffInitBrightnessOptions(&instance.config.brightness);
|
||||
ffInitChassisOptions(&instance.config.chassis);
|
||||
ffInitCommandOptions(&instance.config.command);
|
||||
ffInitCustomOptions(&instance.config.custom);
|
||||
ffInitKernelOptions(&instance.config.kernel);
|
||||
ffInitUptimeOptions(&instance.config.uptime);
|
||||
ffInitProcessesOptions(&instance.config.processes);
|
||||
ffInitPackagesOptions(&instance.config.packages);
|
||||
ffInitShellOptions(&instance.config.shell);
|
||||
ffInitDisplayOptions(&instance.config.display);
|
||||
ffInitDEOptions(&instance.config.de);
|
||||
ffInitWMOptions(&instance.config.wm);
|
||||
ffInitWMThemeOptions(&instance.config.wmTheme);
|
||||
ffInitThemeOptions(&instance.config.theme);
|
||||
ffInitIconsOptions(&instance.config.icons);
|
||||
ffInitFontOptions(&instance.config.font);
|
||||
ffInitCursorOptions(&instance.config.cursor);
|
||||
ffInitTerminalOptions(&instance.config.terminal);
|
||||
ffInitTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffInitCPUOptions(&instance.config.cpu);
|
||||
ffInitCPUUsageOptions(&instance.config.cpuUsage);
|
||||
ffInitGPUOptions(&instance.config.gpu);
|
||||
ffInitMemoryOptions(&instance.config.memory);
|
||||
ffInitSwapOptions(&instance.config.swap);
|
||||
ffInitChassisOptions(&instance.config.chassis);
|
||||
ffInitColorsOptions(&instance.config.colors);
|
||||
ffInitCommandOptions(&instance.config.command);
|
||||
ffInitCursorOptions(&instance.config.cursor);
|
||||
ffInitCustomOptions(&instance.config.custom);
|
||||
ffInitDEOptions(&instance.config.de);
|
||||
ffInitDateTimeOptions(&instance.config.dateTime);
|
||||
ffInitDiskOptions(&instance.config.disk);
|
||||
ffInitBatteryOptions(&instance.config.battery);
|
||||
ffInitPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffInitDisplayOptions(&instance.config.display);
|
||||
ffInitFontOptions(&instance.config.font);
|
||||
ffInitGPUOptions(&instance.config.gpu);
|
||||
ffInitGamepadOptions(&instance.config.gamepad);
|
||||
ffInitHostOptions(&instance.config.host);
|
||||
ffInitIconsOptions(&instance.config.icons);
|
||||
ffInitKernelOptions(&instance.config.kernel);
|
||||
ffInitLMOptions(&instance.config.lm);
|
||||
ffInitLocaleOptions(&instance.config.locale);
|
||||
ffInitLocalIpOptions(&instance.config.localIP);
|
||||
ffInitLocaleOptions(&instance.config.locale);
|
||||
ffInitMediaOptions(&instance.config.media);
|
||||
ffInitMemoryOptions(&instance.config.memory);
|
||||
ffInitMonitorOptions(&instance.config.monitor);
|
||||
ffInitNetIOOptions(&instance.config.netIo);
|
||||
ffInitOSOptions(&instance.config.os);
|
||||
ffInitOpenCLOptions(&instance.config.openCL);
|
||||
ffInitOpenGLOptions(&instance.config.openGL);
|
||||
ffInitPackagesOptions(&instance.config.packages);
|
||||
ffInitPlayerOptions(&instance.config.player);
|
||||
ffInitPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffInitProcessesOptions(&instance.config.processes);
|
||||
ffInitPublicIpOptions(&instance.config.publicIP);
|
||||
ffInitSeparatorOptions(&instance.config.separator);
|
||||
ffInitShellOptions(&instance.config.shell);
|
||||
ffInitSoundOptions(&instance.config.sound);
|
||||
ffInitSwapOptions(&instance.config.swap);
|
||||
ffInitTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffInitTerminalOptions(&instance.config.terminal);
|
||||
ffInitTerminalSizeOptions(&instance.config.terminalSize);
|
||||
ffInitThemeOptions(&instance.config.theme);
|
||||
ffInitTitleOptions(&instance.config.title);
|
||||
ffInitUptimeOptions(&instance.config.uptime);
|
||||
ffInitUsersOptions(&instance.config.users);
|
||||
ffInitVersionOptions(&instance.config.version);
|
||||
ffInitVulkanOptions(&instance.config.vulkan);
|
||||
ffInitWMOptions(&instance.config.wm);
|
||||
ffInitWMThemeOptions(&instance.config.wmTheme);
|
||||
ffInitWallpaperOptions(&instance.config.wallpaper);
|
||||
ffInitWeatherOptions(&instance.config.weather);
|
||||
ffInitWifiOptions(&instance.config.wifi);
|
||||
ffInitPlayerOptions(&instance.config.player);
|
||||
ffInitMediaOptions(&instance.config.media);
|
||||
ffInitDateTimeOptions(&instance.config.dateTime);
|
||||
ffInitVulkanOptions(&instance.config.vulkan);
|
||||
ffInitWallpaperOptions(&instance.config.wallpaper);
|
||||
ffInitOpenGLOptions(&instance.config.openGL);
|
||||
ffInitOpenCLOptions(&instance.config.openCL);
|
||||
ffInitUsersOptions(&instance.config.users);
|
||||
ffInitBluetoothOptions(&instance.config.bluetooth);
|
||||
ffInitSoundOptions(&instance.config.sound);
|
||||
ffInitSeparatorOptions(&instance.config.separator);
|
||||
ffInitGamepadOptions(&instance.config.gamepad);
|
||||
ffInitColorsOptions(&instance.config.colors);
|
||||
|
||||
ffStrbufInit(&instance.config.libPCI);
|
||||
ffStrbufInit(&instance.config.libVulkan);
|
||||
@@ -145,8 +158,6 @@ static void defaultConfig(void)
|
||||
ffStrbufInit(&instance.config.libPulse);
|
||||
ffStrbufInit(&instance.config.libnm);
|
||||
ffStrbufInit(&instance.config.libDdcutil);
|
||||
|
||||
instance.config.percentType = 1;
|
||||
}
|
||||
|
||||
void ffInitInstance(void)
|
||||
@@ -225,11 +236,11 @@ void ffStart(void)
|
||||
startDetectionThreads();
|
||||
#endif
|
||||
|
||||
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe;
|
||||
ffHideCursor = instance.config.hideCursor && !instance.config.pipe;
|
||||
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!instance.config.noBuffer) setvbuf(stdout, NULL, _IOFBF, 4096);
|
||||
setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096);
|
||||
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
@@ -245,7 +256,7 @@ void ffStart(void)
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.pipe && !instance.state.resultDoc)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
@@ -272,63 +283,70 @@ static void destroyConfig(void)
|
||||
ffStrbufDestroy(&instance.config.colorKeys);
|
||||
ffStrbufDestroy(&instance.config.colorTitle);
|
||||
ffStrbufDestroy(&instance.config.keyValueSeparator);
|
||||
ffStrbufDestroy(&instance.config.barCharElapsed);
|
||||
ffStrbufDestroy(&instance.config.barCharTotal);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufDestroy(&instance.config.playerName);
|
||||
ffStrbufDestroy(&instance.config.osFile);
|
||||
#endif
|
||||
|
||||
ffDestroyTitleOptions(&instance.config.title);
|
||||
ffDestroyOSOptions(&instance.config.os);
|
||||
ffDestroyHostOptions(&instance.config.host);
|
||||
ffDestroyBatteryOptions(&instance.config.battery);
|
||||
ffDestroyBiosOptions(&instance.config.bios);
|
||||
ffDestroyBluetoothOptions(&instance.config.bluetooth);
|
||||
ffDestroyBoardOptions(&instance.config.board);
|
||||
ffDestroyBreakOptions(&instance.config.break_);
|
||||
ffDestroyBrightnessOptions(&instance.config.brightness);
|
||||
ffDestroyChassisOptions(&instance.config.chassis);
|
||||
ffDestroyCommandOptions(&instance.config.command);
|
||||
ffDestroyCustomOptions(&instance.config.custom);
|
||||
ffDestroyKernelOptions(&instance.config.kernel);
|
||||
ffDestroyUptimeOptions(&instance.config.uptime);
|
||||
ffDestroyProcessesOptions(&instance.config.processes);
|
||||
ffDestroyPackagesOptions(&instance.config.packages);
|
||||
ffDestroyShellOptions(&instance.config.shell);
|
||||
ffDestroyDisplayOptions(&instance.config.display);
|
||||
ffDestroyDEOptions(&instance.config.de);
|
||||
ffDestroyWMOptions(&instance.config.wm);
|
||||
ffDestroyWMThemeOptions(&instance.config.wmTheme);
|
||||
ffDestroyThemeOptions(&instance.config.theme);
|
||||
ffDestroyIconsOptions(&instance.config.icons);
|
||||
ffDestroyFontOptions(&instance.config.font);
|
||||
ffDestroyCursorOptions(&instance.config.cursor);
|
||||
ffDestroyTerminalOptions(&instance.config.terminal);
|
||||
ffDestroyTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffDestroyCPUOptions(&instance.config.cpu);
|
||||
ffDestroyCPUUsageOptions(&instance.config.cpuUsage);
|
||||
ffDestroyGPUOptions(&instance.config.gpu);
|
||||
ffDestroyMemoryOptions(&instance.config.memory);
|
||||
ffDestroySwapOptions(&instance.config.swap);
|
||||
ffDestroyChassisOptions(&instance.config.chassis);
|
||||
ffDestroyColorsOptions(&instance.config.colors);
|
||||
ffDestroyCommandOptions(&instance.config.command);
|
||||
ffDestroyCursorOptions(&instance.config.cursor);
|
||||
ffDestroyCustomOptions(&instance.config.custom);
|
||||
ffDestroyDEOptions(&instance.config.de);
|
||||
ffDestroyDateTimeOptions(&instance.config.dateTime);
|
||||
ffDestroyDiskOptions(&instance.config.disk);
|
||||
ffDestroyBatteryOptions(&instance.config.battery);
|
||||
ffDestroyPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffDestroyDisplayOptions(&instance.config.display);
|
||||
ffDestroyFontOptions(&instance.config.font);
|
||||
ffDestroyGPUOptions(&instance.config.gpu);
|
||||
ffDestroyGamepadOptions(&instance.config.gamepad);
|
||||
ffDestroyHostOptions(&instance.config.host);
|
||||
ffDestroyIconsOptions(&instance.config.icons);
|
||||
ffDestroyKernelOptions(&instance.config.kernel);
|
||||
ffDestroyLMOptions(&instance.config.lm);
|
||||
ffDestroyLocaleOptions(&instance.config.locale);
|
||||
ffDestroyLocalIpOptions(&instance.config.localIP);
|
||||
ffDestroyLocaleOptions(&instance.config.locale);
|
||||
ffDestroyMediaOptions(&instance.config.media);
|
||||
ffDestroyMemoryOptions(&instance.config.memory);
|
||||
ffDestroyMonitorOptions(&instance.config.monitor);
|
||||
ffDestroyNetIOOptions(&instance.config.netIo);
|
||||
ffDestroyOSOptions(&instance.config.os);
|
||||
ffDestroyOpenCLOptions(&instance.config.openCL);
|
||||
ffDestroyOpenGLOptions(&instance.config.openGL);
|
||||
ffDestroyPackagesOptions(&instance.config.packages);
|
||||
ffDestroyPlayerOptions(&instance.config.player);
|
||||
ffDestroyPowerAdapterOptions(&instance.config.powerAdapter);
|
||||
ffDestroyProcessesOptions(&instance.config.processes);
|
||||
ffDestroyPublicIpOptions(&instance.config.publicIP);
|
||||
ffDestroySeparatorOptions(&instance.config.separator);
|
||||
ffDestroyShellOptions(&instance.config.shell);
|
||||
ffDestroySoundOptions(&instance.config.sound);
|
||||
ffDestroySwapOptions(&instance.config.swap);
|
||||
ffDestroyTerminalFontOptions(&instance.config.terminalFont);
|
||||
ffDestroyTerminalOptions(&instance.config.terminal);
|
||||
ffDestroyTerminalSizeOptions(&instance.config.terminalSize);
|
||||
ffDestroyThemeOptions(&instance.config.theme);
|
||||
ffDestroyTitleOptions(&instance.config.title);
|
||||
ffDestroyUptimeOptions(&instance.config.uptime);
|
||||
ffDestroyUsersOptions(&instance.config.users);
|
||||
ffDestroyVersionOptions(&instance.config.version);
|
||||
ffDestroyVulkanOptions(&instance.config.vulkan);
|
||||
ffDestroyWMOptions(&instance.config.wm);
|
||||
ffDestroyWMThemeOptions(&instance.config.wmTheme);
|
||||
ffDestroyWallpaperOptions(&instance.config.wallpaper);
|
||||
ffDestroyWeatherOptions(&instance.config.weather);
|
||||
ffDestroyWifiOptions(&instance.config.wifi);
|
||||
ffDestroyPlayerOptions(&instance.config.player);
|
||||
ffDestroyMediaOptions(&instance.config.media);
|
||||
ffDestroyDateTimeOptions(&instance.config.dateTime);
|
||||
ffDestroyVulkanOptions(&instance.config.vulkan);
|
||||
ffDestroyOpenGLOptions(&instance.config.openGL);
|
||||
ffDestroyOpenCLOptions(&instance.config.openCL);
|
||||
ffDestroyUsersOptions(&instance.config.users);
|
||||
ffDestroyBluetoothOptions(&instance.config.bluetooth);
|
||||
ffDestroySeparatorOptions(&instance.config.separator);
|
||||
ffDestroySoundOptions(&instance.config.sound);
|
||||
ffDestroyGamepadOptions(&instance.config.gamepad);
|
||||
ffDestroyColorsOptions(&instance.config.colors);
|
||||
|
||||
ffStrbufDestroy(&instance.config.libPCI);
|
||||
ffStrbufDestroy(&instance.config.libVulkan);
|
||||
@@ -360,6 +378,7 @@ static void destroyState(void)
|
||||
{
|
||||
ffPlatformDestroy(&instance.state.platform);
|
||||
yyjson_doc_free(instance.state.configDoc);
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
}
|
||||
|
||||
void ffDestroyInstance(void)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
typedef HANDLE FFNativeFD;
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
typedef int FFNativeFD;
|
||||
#endif
|
||||
|
||||
@@ -84,6 +85,8 @@ typedef enum FFPathType
|
||||
bool ffPathExists(const char* path, FFPathType pathType);
|
||||
bool ffPathExpandEnv(const char* in, FFstrbuf* out);
|
||||
|
||||
#define FF_IO_TERM_RESP_WAIT_MS 100 // #554
|
||||
|
||||
FF_C_SCANF(2, 3)
|
||||
const char* ffGetTerminalResponse(const char* request, const char* format, ...);
|
||||
|
||||
@@ -130,4 +133,25 @@ static inline bool wrapFclose(FILE** pfile)
|
||||
}
|
||||
#define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose)))
|
||||
|
||||
#ifndef _WIN32
|
||||
static inline bool wrapClosedir(DIR** pdir)
|
||||
{
|
||||
assert(pdir);
|
||||
if (!*pdir)
|
||||
return false;
|
||||
closedir(*pdir);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool wrapClosedir(HANDLE* pdir)
|
||||
{
|
||||
assert(pdir);
|
||||
if (!*pdir)
|
||||
return false;
|
||||
FindClose(*pdir);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#define FF_AUTO_CLOSE_DIR __attribute__((__cleanup__(wrapClosedir)))
|
||||
|
||||
#endif // FF_INCLUDED_common_io_io
|
||||
|
||||
@@ -54,24 +54,20 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
|
||||
uint32_t free = ffStrbufGetFree(buffer);
|
||||
|
||||
while(
|
||||
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
|
||||
(uint32_t) readed == free
|
||||
(readed = read(fd, buffer->chars + buffer->length, free)) > 0
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
if((uint32_t) readed == free)
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
ffStrbufTrimRight(buffer, ' ');
|
||||
|
||||
return readed >= 0;
|
||||
return buffer->length > 0;
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||
@@ -150,7 +146,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
fflush(stdout);
|
||||
|
||||
//Give the terminal 35ms to respond
|
||||
if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, 35) <= 0)
|
||||
if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
|
||||
return "poll() timeout or failed";
|
||||
|
||||
@@ -44,16 +44,14 @@ bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer)
|
||||
bool success;
|
||||
while(
|
||||
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
|
||||
(uint32_t) readed == free
|
||||
readed > 0
|
||||
) {
|
||||
buffer->length += (uint32_t) readed;
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
if((uint32_t) readed == free)
|
||||
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
|
||||
free = ffStrbufGetFree(buffer);
|
||||
}
|
||||
|
||||
if(readed > 0)
|
||||
buffer->length += (uint32_t) readed;
|
||||
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
ffStrbufTrimRight(buffer, '\n');
|
||||
@@ -173,7 +171,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (WaitForSingleObjectEx(hInput, 35, TRUE) != WAIT_OBJECT_0)
|
||||
if (WaitForSingleObjectEx(hInput, FF_IO_TERM_RESP_WAIT_MS, TRUE) != WAIT_OBJECT_0)
|
||||
{
|
||||
SetConsoleMode(hInput, prev_mode);
|
||||
return "WaitForSingleObject() failed or timeout";
|
||||
|
||||
+115
-159
@@ -17,14 +17,19 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
|
||||
ffStrbufSetNS(&moduleArgs->key, (uint32_t) yyjson_get_len(val), yyjson_get_str(val));
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "format"))
|
||||
{
|
||||
ffStrbufSetNS(&moduleArgs->outputFormat, (uint32_t) yyjson_get_len(val), yyjson_get_str(val));
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "keyColor"))
|
||||
{
|
||||
ffOptionParseColor(yyjson_get_str(val), &moduleArgs->keyColor);
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(key, "format"))
|
||||
else if(ffStrEqualsIgnCase(key, "keyWidth"))
|
||||
{
|
||||
ffStrbufSetNS(&moduleArgs->outputFormat, (uint32_t) yyjson_get_len(val), yyjson_get_str(val));
|
||||
moduleArgs->keyWidth = (uint32_t) yyjson_get_uint(val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -65,165 +70,76 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p
|
||||
return "Invalid enum value type; must be a string or integer";
|
||||
}
|
||||
|
||||
static inline bool tryModule(const char* type, yyjson_val* module, const char* moduleName, void (*const f)(yyjson_val *module))
|
||||
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
|
||||
{
|
||||
if (ffStrEqualsIgnCase(type, moduleName))
|
||||
yyjson_mut_doc* doc = instance.state.resultDoc;
|
||||
if (__builtin_expect(!doc, true)) return NULL;
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJson)
|
||||
baseInfo->generateJson(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
return module;
|
||||
}
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(type[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
f(module);
|
||||
return true;
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(type, baseInfo->name))
|
||||
{
|
||||
if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal);
|
||||
if (!genJson(baseInfo))
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* module)
|
||||
static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
{
|
||||
switch (toupper(type[0]))
|
||||
FFconfig* cfg = &instance.config;
|
||||
switch (type[0])
|
||||
{
|
||||
case 'B': {
|
||||
return
|
||||
tryModule(type, module, FF_BATTERY_MODULE_NAME, ffParseBatteryJsonObject) ||
|
||||
tryModule(type, module, FF_BIOS_MODULE_NAME, ffParseBiosJsonObject) ||
|
||||
tryModule(type, module, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothJsonObject) ||
|
||||
tryModule(type, module, FF_BOARD_MODULE_NAME, ffParseBoardJsonObject) ||
|
||||
tryModule(type, module, FF_BREAK_MODULE_NAME, ffParseBreakJsonObject) ||
|
||||
tryModule(type, module, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessJsonObject) ||
|
||||
false;
|
||||
case 'b': case 'B': {
|
||||
if (ffStrEqualsIgnCase(type, FF_CPUUSAGE_MODULE_NAME))
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C': {
|
||||
return
|
||||
tryModule(type, module, FF_CHASSIS_MODULE_NAME, ffParseChassisJsonObject) ||
|
||||
tryModule(type, module, FF_COMMAND_MODULE_NAME, ffParseCommandJsonObject) ||
|
||||
tryModule(type, module, FF_COLORS_MODULE_NAME, ffParseColorsJsonObject) ||
|
||||
tryModule(type, module, FF_CPU_MODULE_NAME, ffParseCPUJsonObject) ||
|
||||
tryModule(type, module, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageJsonObject) ||
|
||||
tryModule(type, module, FF_CURSOR_MODULE_NAME, ffParseCursorJsonObject) ||
|
||||
tryModule(type, module, FF_CUSTOM_MODULE_NAME, ffParseCustomJsonObject) ||
|
||||
false;
|
||||
case 'n': case 'N': {
|
||||
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseNetIOJsonObject(&cfg->netIo, module);
|
||||
ffPrepareNetIO(&cfg->netIo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'D': {
|
||||
return
|
||||
tryModule(type, module, FF_DATETIME_MODULE_NAME, ffParseDateTimeJsonObject) ||
|
||||
tryModule(type, module, FF_DE_MODULE_NAME, ffParseDEJsonObject) ||
|
||||
tryModule(type, module, FF_DISPLAY_MODULE_NAME, ffParseDisplayJsonObject) ||
|
||||
tryModule(type, module, FF_DISK_MODULE_NAME, ffParseDiskJsonObject) ||
|
||||
false;
|
||||
case 'p': case 'P': {
|
||||
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParsePublicIpJsonObject(&cfg->publicIP, module);
|
||||
ffPreparePublicIp(&cfg->publicIP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'F': {
|
||||
return
|
||||
tryModule(type, module, FF_FONT_MODULE_NAME, ffParseFontJsonObject) ||
|
||||
false;
|
||||
case 'w': case 'W': {
|
||||
if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseWeatherJsonObject(&cfg->weather, module);
|
||||
ffPrepareWeather(&cfg->weather);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'G': {
|
||||
return
|
||||
tryModule(type, module, FF_GAMEPAD_MODULE_NAME, ffParseGamepadJsonObject) ||
|
||||
tryModule(type, module, FF_GPU_MODULE_NAME, ffParseGPUJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'H': {
|
||||
return
|
||||
tryModule(type, module, FF_HOST_MODULE_NAME, ffParseHostJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'I': {
|
||||
return
|
||||
tryModule(type, module, FF_ICONS_MODULE_NAME, ffParseIconsJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'K': {
|
||||
return
|
||||
tryModule(type, module, FF_KERNEL_MODULE_NAME, ffParseKernelJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'L': {
|
||||
return
|
||||
tryModule(type, module, FF_LM_MODULE_NAME, ffParseLMJsonObject) ||
|
||||
tryModule(type, module, FF_LOCALE_MODULE_NAME, ffParseLocaleJsonObject) ||
|
||||
tryModule(type, module, FF_LOCALIP_MODULE_NAME, ffParseLocalIpJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'M': {
|
||||
return
|
||||
tryModule(type, module, FF_MEDIA_MODULE_NAME, ffParseMediaJsonObject) ||
|
||||
tryModule(type, module, FF_MEMORY_MODULE_NAME, ffParseMemoryJsonObject) ||
|
||||
tryModule(type, module, FF_MONITOR_MODULE_NAME, ffParseMonitorJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'O': {
|
||||
return
|
||||
tryModule(type, module, FF_OPENCL_MODULE_NAME, ffParseOpenCLJsonObject) ||
|
||||
tryModule(type, module, FF_OPENGL_MODULE_NAME, ffParseOpenGLJsonObject) ||
|
||||
tryModule(type, module, FF_OS_MODULE_NAME, ffParseOSJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'P': {
|
||||
return
|
||||
tryModule(type, module, FF_PACKAGES_MODULE_NAME, ffParsePackagesJsonObject) ||
|
||||
tryModule(type, module, FF_PLAYER_MODULE_NAME, ffParsePlayerJsonObject) ||
|
||||
tryModule(type, module, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterJsonObject) ||
|
||||
tryModule(type, module, FF_PROCESSES_MODULE_NAME, ffParseProcessesJsonObject) ||
|
||||
tryModule(type, module, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'S': {
|
||||
return
|
||||
tryModule(type, module, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorJsonObject) ||
|
||||
tryModule(type, module, FF_SHELL_MODULE_NAME, ffParseShellJsonObject) ||
|
||||
tryModule(type, module, FF_SOUND_MODULE_NAME, ffParseSoundJsonObject) ||
|
||||
tryModule(type, module, FF_SWAP_MODULE_NAME, ffParseSwapJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'T': {
|
||||
return
|
||||
tryModule(type, module, FF_TERMINAL_MODULE_NAME, ffParseTerminalJsonObject) ||
|
||||
tryModule(type, module, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontJsonObject) ||
|
||||
tryModule(type, module, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeJsonObject) ||
|
||||
tryModule(type, module, FF_TITLE_MODULE_NAME, ffParseTitleJsonObject) ||
|
||||
tryModule(type, module, FF_THEME_MODULE_NAME, ffParseThemeJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'U': {
|
||||
return
|
||||
tryModule(type, module, FF_UPTIME_MODULE_NAME, ffParseUptimeJsonObject) ||
|
||||
tryModule(type, module, FF_USERS_MODULE_NAME, ffParseUsersJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'V': {
|
||||
return
|
||||
tryModule(type, module, FF_VULKAN_MODULE_NAME, ffParseVulkanJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
case 'W': {
|
||||
return
|
||||
tryModule(type, module, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperJsonObject) ||
|
||||
tryModule(type, module, FF_WEATHER_MODULE_NAME, ffParseWeatherJsonObject) ||
|
||||
tryModule(type, module, FF_WM_MODULE_NAME, ffParseWMJsonObject) ||
|
||||
tryModule(type, module, FF_WIFI_MODULE_NAME, ffParseWifiJsonObject) ||
|
||||
tryModule(type, module, FF_WMTHEME_MODULE_NAME, ffParseWMThemeJsonObject) ||
|
||||
false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(void)
|
||||
static const char* printJsonConfig(bool prepare)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
@@ -235,12 +151,14 @@ static const char* printJsonConfig(void)
|
||||
if (!modules) return NULL;
|
||||
if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects";
|
||||
|
||||
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
|
||||
|
||||
yyjson_val* item;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(modules, idx, max, item)
|
||||
{
|
||||
uint64_t ms = 0;
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
if(!prepare && instance.config.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
yyjson_val* module = item;
|
||||
@@ -257,21 +175,32 @@ static const char* printJsonConfig(void)
|
||||
else
|
||||
return "modules must be an array of strings or objects";
|
||||
|
||||
if(!parseModuleJsonObject(type, module))
|
||||
if(prepare)
|
||||
prepareModuleJsonObject(type, module);
|
||||
else if(!parseModuleJsonObject(type, module))
|
||||
return "Unknown module type";
|
||||
|
||||
if(__builtin_expect(instance.config.stat, false))
|
||||
if(!prepare && instance.config.stat)
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
ms = ffTimeGetTick() - ms;
|
||||
if (resultDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
|
||||
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
else
|
||||
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!instance.config.noBuffer) fflush(stdout);
|
||||
if (!instance.config.noBuffer && !resultDoc) fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -430,9 +359,36 @@ const char* ffParseDisplayJsonConfig(void)
|
||||
config->temperatureUnit = (FFTemperatureUnit) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "percentType"))
|
||||
config->percentType = (uint32_t) yyjson_get_uint(val);
|
||||
config->percentType = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "percentNdigits"))
|
||||
config->percentNdigits = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "bar"))
|
||||
{
|
||||
if (yyjson_is_obj(val))
|
||||
{
|
||||
const char* charElapsed = yyjson_get_str(yyjson_obj_get(val, "charElapsed"));
|
||||
if (charElapsed)
|
||||
ffStrbufSetS(&config->barCharElapsed, charElapsed);
|
||||
|
||||
const char* charTotal = yyjson_get_str(yyjson_obj_get(val, "charTotal"));
|
||||
if (charTotal)
|
||||
ffStrbufSetS(&config->barCharTotal, charTotal);
|
||||
|
||||
yyjson_val* border = yyjson_obj_get(val, "border");
|
||||
if (border)
|
||||
config->barBorder = yyjson_get_bool(border);
|
||||
|
||||
yyjson_val* width = yyjson_obj_get(val, "width");
|
||||
if (width)
|
||||
config->barWidth = (uint8_t) yyjson_get_uint(width);
|
||||
}
|
||||
else
|
||||
return "display.bar must be an object";
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "noBuffer"))
|
||||
config->noBuffer = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "keyWidth"))
|
||||
config->keyWidth = (uint32_t) yyjson_get_uint(val);
|
||||
else
|
||||
return "Unknown display property";
|
||||
}
|
||||
@@ -515,9 +471,9 @@ const char* ffParseLibraryJsonConfig(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(void)
|
||||
void ffPrintJsonConfig(bool prepare)
|
||||
{
|
||||
const char* error = printJsonConfig();
|
||||
const char* error = printJsonConfig(prepare);
|
||||
if (error)
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, NULL, "%s", error);
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
}
|
||||
|
||||
+17
-4
@@ -4,7 +4,20 @@
|
||||
|
||||
bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs);
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
|
||||
void ffPrintJsonConfig();
|
||||
const char* ffParseGeneralJsonConfig();
|
||||
const char* ffParseDisplayJsonConfig();
|
||||
const char* ffParseLibraryJsonConfig();
|
||||
void ffPrintJsonConfig(bool prepare);
|
||||
const char* ffParseGeneralJsonConfig(void);
|
||||
const char* ffParseDisplayJsonConfig(void);
|
||||
const char* ffParseLibraryJsonConfig(void);
|
||||
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *_key,
|
||||
const FFstrbuf* buf) {
|
||||
return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length);
|
||||
}
|
||||
|
||||
yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const FFstrbuf* buf) {
|
||||
return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
static FFModuleBaseInfo* A[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* B[] = {
|
||||
(void*) &instance.config.battery,
|
||||
(void*) &instance.config.bios,
|
||||
(void*) &instance.config.bluetooth,
|
||||
(void*) &instance.config.board,
|
||||
(void*) &instance.config.break_,
|
||||
(void*) &instance.config.brightness,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.chassis,
|
||||
(void*) &instance.config.command,
|
||||
(void*) &instance.config.colors,
|
||||
(void*) &instance.config.cpu,
|
||||
(void*) &instance.config.cpuUsage,
|
||||
(void*) &instance.config.cursor,
|
||||
(void*) &instance.config.custom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* D[] = {
|
||||
(void*) &instance.config.dateTime,
|
||||
(void*) &instance.config.de,
|
||||
(void*) &instance.config.display,
|
||||
(void*) &instance.config.disk,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* E[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* F[] = {
|
||||
(void*) &instance.config.font,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* G[] = {
|
||||
(void*) &instance.config.gamepad,
|
||||
(void*) &instance.config.gpu,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* H[] = {
|
||||
(void*) &instance.config.host,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* I[] = {
|
||||
(void*) &instance.config.icons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* J[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* K[] = {
|
||||
(void*) &instance.config.kernel,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* L[] = {
|
||||
(void*) &instance.config.lm,
|
||||
(void*) &instance.config.locale,
|
||||
(void*) &instance.config.localIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* M[] = {
|
||||
(void*) &instance.config.media,
|
||||
(void*) &instance.config.memory,
|
||||
(void*) &instance.config.monitor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* N[] = {
|
||||
(void*) &instance.config.netIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* O[] = {
|
||||
(void*) &instance.config.openCL,
|
||||
(void*) &instance.config.openGL,
|
||||
(void*) &instance.config.os,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* P[] = {
|
||||
(void*) &instance.config.packages,
|
||||
(void*) &instance.config.player,
|
||||
(void*) &instance.config.powerAdapter,
|
||||
(void*) &instance.config.processes,
|
||||
(void*) &instance.config.publicIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* Q[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* R[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* S[] = {
|
||||
(void*) &instance.config.separator,
|
||||
(void*) &instance.config.shell,
|
||||
(void*) &instance.config.sound,
|
||||
(void*) &instance.config.swap,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.terminal,
|
||||
(void*) &instance.config.terminalFont,
|
||||
(void*) &instance.config.terminalSize,
|
||||
(void*) &instance.config.title,
|
||||
(void*) &instance.config.theme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* U[] = {
|
||||
(void*) &instance.config.uptime,
|
||||
(void*) &instance.config.users,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* V[] = {
|
||||
(void*) &instance.config.version,
|
||||
(void*) &instance.config.vulkan,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* W[] = {
|
||||
(void*) &instance.config.wallpaper,
|
||||
(void*) &instance.config.weather,
|
||||
(void*) &instance.config.wm,
|
||||
(void*) &instance.config.wifi,
|
||||
(void*) &instance.config.wmTheme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* X[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* Y[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* Z[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
FFModuleBaseInfo** ffModuleInfos[] = {
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "netif.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <net/if.h>
|
||||
#else
|
||||
#define IF_NAMESIZE 16
|
||||
#endif
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex);
|
||||
enum { IF_INDEX_UNINITIALIZED = (uint32_t) -1, IF_INDEX_INVALID = (uint32_t) -2 };
|
||||
static uint32_t ifIndex = IF_INDEX_UNINITIALIZED;
|
||||
static char ifName[IF_NAMESIZE + 1];
|
||||
|
||||
static inline void init()
|
||||
{
|
||||
if (ifIndex == (uint32_t) IF_INDEX_UNINITIALIZED && !ffNetifGetDefaultRouteImpl(ifName, &ifIndex))
|
||||
ifIndex = (uint32_t) IF_INDEX_INVALID;
|
||||
}
|
||||
|
||||
const char* ffNetifGetDefaultRouteIfName()
|
||||
{
|
||||
init();
|
||||
return ifName;
|
||||
}
|
||||
|
||||
uint32_t ffNetifGetDefaultRouteIfIndex()
|
||||
{
|
||||
init();
|
||||
return ifIndex;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
const char* ffNetifGetDefaultRouteIfName();
|
||||
#endif
|
||||
|
||||
uint32_t ffNetifGetDefaultRouteIfIndex();
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "netif.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__NetBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
|
||||
#elif defined(__FreeBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__OpenBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#else
|
||||
# error unknown platform
|
||||
#endif
|
||||
|
||||
static struct sockaddr *
|
||||
get_rt_address(struct rt_msghdr *rtm, int desired)
|
||||
{
|
||||
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
|
||||
|
||||
for (int i = 0; i < RTAX_MAX; i++)
|
||||
{
|
||||
if (rtm->rtm_addrs & (1 << i))
|
||||
{
|
||||
if ((1 <<i ) == desired)
|
||||
return sa;
|
||||
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
|
||||
|
||||
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
|
||||
if (pfRoute < 0)
|
||||
return false;
|
||||
|
||||
{
|
||||
struct timeval timeout = {1, 0};
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
int pid = getpid();
|
||||
|
||||
struct {
|
||||
struct rt_msghdr hdr;
|
||||
struct sockaddr_in dst;
|
||||
uint8_t data[512];
|
||||
} rtmsg = {
|
||||
.hdr = {
|
||||
.rtm_type = RTM_GET,
|
||||
.rtm_flags = RTF_UP | RTF_GATEWAY,
|
||||
.rtm_version = RTM_VERSION,
|
||||
.rtm_addrs = RTA_DST | RTA_IFP,
|
||||
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
|
||||
.rtm_pid = pid,
|
||||
.rtm_seq = 1,
|
||||
},
|
||||
.dst = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_len = sizeof(rtmsg.dst),
|
||||
},
|
||||
};
|
||||
|
||||
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
|
||||
return false;
|
||||
|
||||
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
|
||||
{
|
||||
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
|
||||
{
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
|
||||
if (sdl)
|
||||
{
|
||||
assert(sdl->sdl_nlen <= IF_NAMESIZE);
|
||||
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
|
||||
iface[sdl->sdl_nlen] = '\0';
|
||||
*ifIndex = sdl->sdl_index;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
|
||||
if (!netRoute) return false;
|
||||
|
||||
// skip first line
|
||||
flockfile(netRoute);
|
||||
while (getc_unlocked(netRoute) != '\n');
|
||||
funlockfile(netRoute);
|
||||
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
|
||||
|
||||
while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2)
|
||||
{
|
||||
if (destination != 0) continue;
|
||||
*ifIndex = if_nametoindex(iface);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <iphlpapi.h>
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char* iface/* unsupported */, uint32_t* ifIndex)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
|
||||
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
|
||||
{
|
||||
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
|
||||
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
|
||||
{
|
||||
*ifIndex = ipForwardRow->dwForwardIfIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -77,7 +77,8 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
|
||||
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
|
||||
{
|
||||
#ifdef FF_HAVE_THREADS
|
||||
ffThreadJoin(state->thread);
|
||||
if (!ffThreadJoin(state->thread, timeout))
|
||||
return false;
|
||||
#endif
|
||||
if(state->sockfd == -1)
|
||||
return false;
|
||||
@@ -85,8 +86,8 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui
|
||||
if(timeout > 0)
|
||||
{
|
||||
struct timeval timev;
|
||||
timev.tv_sec = 0;
|
||||
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
|
||||
timev.tv_sec = timeout / 1000;
|
||||
timev.tv_usec = (__typeof__(timev.tv_usec)) ((timeout % 1000) * 1000); //milliseconds to microseconds
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -34,6 +34,11 @@ bool ffOptionParseModuleArgs(const char* argumentKey, const char* subKey, const
|
||||
ffOptionParseString(argumentKey, value, &result->key);
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(subKey, "format"))
|
||||
{
|
||||
ffOptionParseString(argumentKey, value, &result->outputFormat);
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(subKey, "key-color"))
|
||||
{
|
||||
if(value == NULL)
|
||||
@@ -44,9 +49,9 @@ bool ffOptionParseModuleArgs(const char* argumentKey, const char* subKey, const
|
||||
ffOptionParseColor(value, &result->keyColor);
|
||||
return true;
|
||||
}
|
||||
else if(ffStrEqualsIgnCase(subKey, "format"))
|
||||
else if(ffStrEqualsIgnCase(subKey, "key-width"))
|
||||
{
|
||||
ffOptionParseString(argumentKey, value, &result->outputFormat);
|
||||
result->keyWidth = ffOptionParseUInt32(argumentKey, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -175,6 +180,7 @@ void ffOptionInitModuleArg(FFModuleArgs* args)
|
||||
ffStrbufInit(&args->key);
|
||||
ffStrbufInit(&args->keyColor);
|
||||
ffStrbufInit(&args->outputFormat);
|
||||
args->keyWidth = 0;
|
||||
}
|
||||
|
||||
void ffOptionDestroyModuleArg(FFModuleArgs* args)
|
||||
|
||||
@@ -2,11 +2,46 @@
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
struct yyjson_val;
|
||||
struct yyjson_mut_doc;
|
||||
struct yyjson_mut_val;
|
||||
|
||||
// Must be the first field of FFModuleOptions
|
||||
typedef struct FFModuleBaseInfo
|
||||
{
|
||||
const char* name;
|
||||
// A dirty polymorphic implementation in C.
|
||||
// This is UB, because `void*` is not compatible with `FF*Options*`.
|
||||
// However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer
|
||||
// https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type
|
||||
bool (*parseCommandOptions)(void* options, const char* key, const char* value);
|
||||
void (*parseJsonObject)(void* options, struct yyjson_val *module);
|
||||
void (*printModule)(void* options);
|
||||
void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
} FFModuleBaseInfo;
|
||||
|
||||
static inline void ffOptionInitModuleBaseInfo(
|
||||
FFModuleBaseInfo* baseInfo,
|
||||
const char* name,
|
||||
void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value)
|
||||
void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module)
|
||||
void* printModule, // void (*const printModule)(void* options)
|
||||
void* generateJson // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
)
|
||||
{
|
||||
baseInfo->name = name;
|
||||
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
|
||||
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
|
||||
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
|
||||
baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson;
|
||||
}
|
||||
|
||||
typedef struct FFModuleArgs
|
||||
{
|
||||
FFstrbuf key;
|
||||
FFstrbuf keyColor;
|
||||
FFstrbuf outputFormat;
|
||||
uint32_t keyWidth;
|
||||
} FFModuleArgs;
|
||||
|
||||
typedef struct FFKeyValuePair
|
||||
|
||||
+32
-56
@@ -2,7 +2,7 @@
|
||||
#include "common/printing.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor)
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType)
|
||||
{
|
||||
ffLogoPrintLine();
|
||||
|
||||
@@ -10,20 +10,24 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFstrb
|
||||
if(moduleName == NULL)
|
||||
return;
|
||||
|
||||
//This is used as a magic value for hiding keys
|
||||
if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " "))
|
||||
return;
|
||||
|
||||
if(!instance.config.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
if (instance.config.brightColor)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
|
||||
if(customKeyColor != NULL && customKeyColor->length > 0)
|
||||
ffPrintColor(customKeyColor);
|
||||
if(moduleArgs && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR) && moduleArgs->keyColor.length > 0)
|
||||
ffPrintColor(&moduleArgs->keyColor);
|
||||
else
|
||||
ffPrintColor(&instance.config.colorKeys);
|
||||
}
|
||||
|
||||
//NULL check is required for modules with custom keys, e.g. disk with the folder path
|
||||
if(customKeyFormat == NULL || customKeyFormat->length == 0)
|
||||
if((printType & FF_PRINT_TYPE_NO_CUSTOM_KEY) || !moduleArgs || moduleArgs->key.length == 0)
|
||||
{
|
||||
fputs(moduleName, stdout);
|
||||
|
||||
@@ -33,10 +37,10 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFstrb
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
ffParseFormatString(&key, customKeyFormat, 1, (FFformatarg[]){
|
||||
ffParseFormatString(&key, &moduleArgs->key, 1, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex}
|
||||
});
|
||||
ffPrintUserString(key.chars);
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
@@ -46,32 +50,37 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFstrb
|
||||
|
||||
if(!instance.config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
}
|
||||
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateA(256);
|
||||
ffParseFormatString(&buffer, format, numArgs, arguments);
|
||||
|
||||
if(buffer.length > 0)
|
||||
if (!instance.config.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
|
||||
{
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, customKeyFormat, customKeyColor);
|
||||
ffPrintUserString(buffer.chars);
|
||||
putchar('\n');
|
||||
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.keyWidth;
|
||||
if (keyWidth > 0)
|
||||
printf("\e[%uG", (unsigned) (keyWidth + instance.state.logoWidth));
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
ffPrintFormatString(moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->keyColor, &moduleArgs->outputFormat, numArgs, arguments);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (moduleArgs)
|
||||
ffParseFormatString(&buffer, &moduleArgs->outputFormat, numArgs, arguments);
|
||||
else
|
||||
ffStrbufAppendS(&buffer, "unknown");
|
||||
|
||||
if(buffer.length > 0)
|
||||
{
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType);
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
}
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor, const char* message, va_list arguments)
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
{
|
||||
if(!instance.config.showErrors)
|
||||
return;
|
||||
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, customKeyFormat, customKeyColor);
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
@@ -84,11 +93,11 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFstrb
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor, const char* message, ...)
|
||||
void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, customKeyFormat, customKeyColor, message, arguments);
|
||||
printError(moduleName, moduleIndex, moduleArgs, printType, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
@@ -96,7 +105,7 @@ void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArg
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, &moduleArgs->key, &moduleArgs->keyColor, message, arguments);
|
||||
printError(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
@@ -107,9 +116,7 @@ void ffPrintColor(const FFstrbuf* colorValue)
|
||||
if(colorValue->length == 0)
|
||||
return;
|
||||
|
||||
fputs("\033[", stdout);
|
||||
ffStrbufWriteTo(colorValue, stdout);
|
||||
fputc('m', stdout);
|
||||
printf("\e[%sm", colorValue->chars);
|
||||
}
|
||||
|
||||
void ffPrintCharTimes(char c, uint32_t times)
|
||||
@@ -125,34 +132,3 @@ void ffPrintCharTimes(char c, uint32_t times)
|
||||
if(remaining > 0)
|
||||
fwrite(str, 1, remaining, stdout);
|
||||
}
|
||||
|
||||
void ffPrintUserString(const char* value)
|
||||
{
|
||||
while(*value != '\0')
|
||||
{
|
||||
if(*value != '\\')
|
||||
{
|
||||
putchar(*value);
|
||||
++value;
|
||||
continue;
|
||||
}
|
||||
|
||||
++value;
|
||||
|
||||
if(*value == 'n')
|
||||
putchar('\n');
|
||||
else if(*value == 't')
|
||||
putchar('\t');
|
||||
else if(*value == 'e')
|
||||
putchar('\e');
|
||||
else if(*value == '\\')
|
||||
putchar('\\');
|
||||
else
|
||||
{
|
||||
putchar('\\');
|
||||
putchar(*value);
|
||||
}
|
||||
|
||||
++value;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -6,13 +6,23 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor);
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor, const FFstrbuf* format, uint32_t numArgs, const FFformatarg* arguments);
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments);
|
||||
FF_C_PRINTF(5, 6) void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFstrbuf* customKeyFormat, const FFstrbuf* customKeyColor, const char* message, ...);
|
||||
typedef enum FFPrintType {
|
||||
FF_PRINT_TYPE_DEFAULT = 0,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR = 1 << 1,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH = 1 << 2,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_OUTPUT_FORMAT = 1 << 3, // reserved
|
||||
} FFPrintType;
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType);
|
||||
void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
|
||||
static inline void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, uint32_t numArgs, const FFformatarg* arguments)
|
||||
{
|
||||
ffPrintFormatString(moduleName, moduleIndex, moduleArgs, FF_PRINT_TYPE_DEFAULT, numArgs, arguments);
|
||||
}
|
||||
FF_C_PRINTF(5, 6) void ffPrintErrorString(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
|
||||
FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, const char* message, ...);
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
void ffPrintCharTimes(char c, uint32_t times);
|
||||
void ffPrintUserString(const char* str);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
close(useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
setenv("LANG", "C", 1);
|
||||
execvp(argv[0], argv);
|
||||
exit(901);
|
||||
}
|
||||
|
||||
+38
-2
@@ -10,6 +10,7 @@
|
||||
#include <handleapi.h>
|
||||
#include <synchapi.h>
|
||||
#include <process.h>
|
||||
#include <processthreadsapi.h>
|
||||
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
|
||||
typedef SRWLOCK FFThreadMutex;
|
||||
typedef HANDLE FFThreadType;
|
||||
@@ -21,9 +22,23 @@
|
||||
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
|
||||
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static __stdcall unsigned fn ## ThreadMain () { fn(); return 0; }
|
||||
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
|
||||
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, 0xffffffff /*INFINITE*/); }
|
||||
static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout)
|
||||
{
|
||||
if (WaitForSingleObject(thread, timeout == 0 ? (DWORD) -1 : timeout) != 0 /*WAIT_OBJECT_0*/)
|
||||
{
|
||||
TerminateThread(thread, (DWORD) -1);
|
||||
CloseHandle(thread);
|
||||
return false;
|
||||
}
|
||||
CloseHandle(thread);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#if __has_include(<pthread_np.h>)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
typedef pthread_mutex_t FFThreadMutex;
|
||||
typedef pthread_t FFThreadType;
|
||||
@@ -37,7 +52,28 @@
|
||||
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; }
|
||||
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static void* fn ## ThreadMain () { fn(); return NULL; }
|
||||
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
|
||||
static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); }
|
||||
static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout)
|
||||
{
|
||||
#if (defined(__linux__) && !defined(__ANDROID__)) || __has_include(<pthread_np.h>)
|
||||
if (timeout > 0)
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
|
||||
{
|
||||
ts.tv_sec += ts.tv_sec / 1000;
|
||||
ts.tv_nsec += (ts.tv_nsec % 1000) * 1000000;
|
||||
if (pthread_timedjoin_np(thread, NULL, &ts) != 0)
|
||||
{
|
||||
pthread_kill(thread, SIGTERM);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pthread_join(thread, NULL);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#else //FF_HAVE_THREADS
|
||||
#define FF_THREAD_MUTEX_INITIALIZER 0
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <synchapi.h>
|
||||
#include <profileapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
@@ -26,6 +27,19 @@ static inline uint64_t ffTimeGetTick() //In msec
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t ffTimeGetNow()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
uint64_t timeNow;
|
||||
GetSystemTimeAsFileTime((FILETIME*) &timeNow);
|
||||
return (timeNow - 116444736000000000ull) / 10000ull;
|
||||
#else
|
||||
struct timespec timeNow;
|
||||
clock_gettime(CLOCK_REALTIME, &timeNow);
|
||||
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void ffTimeSleep(uint32_t msec)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -360,7 +360,7 @@
|
||||
#--terminal-key Terminal
|
||||
#--terminalfont-key Terminal Font
|
||||
#--cpu-key CPU
|
||||
#--cpu-usage-key CPU Usage
|
||||
#--cpuusage-key CPU Usage
|
||||
#--gpu-key GPU {1}
|
||||
#--memory-key Memory
|
||||
#--swap-key Swap
|
||||
@@ -370,12 +370,14 @@
|
||||
#--lm-key LM
|
||||
#--locale-key Locale
|
||||
#--localip-key Local IP ({1})
|
||||
#--netio-key Network IO ({1})
|
||||
#--publicip-key Public IP
|
||||
#--wifi-key Wifi
|
||||
#--weather-key Weather
|
||||
#--player-key Media Player
|
||||
#--media-key Media
|
||||
#--datetime-key Date Time
|
||||
#--version-key Version
|
||||
#--vulkan-key Vulkan
|
||||
#--opengl-key OpenGL
|
||||
#--opencl-key OpenCL
|
||||
@@ -390,6 +392,7 @@
|
||||
# For information on format strings, see "fastfetch --help format".
|
||||
# To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format".
|
||||
# An empty format string (As they are currently below) will behave as if it was not set.
|
||||
#--title-format
|
||||
#--os-format
|
||||
#--host-format
|
||||
#--chassis-format
|
||||
@@ -410,7 +413,7 @@
|
||||
#--terminal-format
|
||||
#--terminalfont-format
|
||||
#--cpu-format
|
||||
#--cpu-usage-format
|
||||
#--cpuusage-format
|
||||
#--gpu-format
|
||||
#--memory-format
|
||||
#--swap-format
|
||||
@@ -420,12 +423,14 @@
|
||||
#--lm-format
|
||||
#--locale-format
|
||||
#--localip-format
|
||||
#--netio-format
|
||||
#--publicip-format
|
||||
#--weather-format
|
||||
#--monitor-format
|
||||
#--player-format
|
||||
#--media-format
|
||||
#--datetime-format
|
||||
#--version-format
|
||||
#--vulkan-format
|
||||
#--opengl-format
|
||||
#--opencl-format
|
||||
@@ -437,6 +442,7 @@
|
||||
|
||||
# Key color options:
|
||||
# Overrides the global `--color-keys` for one specified module
|
||||
#--title-key-color
|
||||
#--os-key-color
|
||||
#--host-key-color
|
||||
#--chassis-key-color
|
||||
@@ -457,7 +463,7 @@
|
||||
#--terminal-key-color
|
||||
#--terminalfont-key-color
|
||||
#--cpu-key-color
|
||||
#--cpu-usage-key-color
|
||||
#--cpuusage-key-color
|
||||
#--gpu-key-color
|
||||
#--memory-key-color
|
||||
#--swap-key-color
|
||||
@@ -467,12 +473,14 @@
|
||||
#--lm-key-color
|
||||
#--locale-key-color
|
||||
#--localip-key-color
|
||||
#--netio-key-color
|
||||
#--publicip-key-color
|
||||
#--weather-key-color
|
||||
#--monitor-key-color
|
||||
#--player-key-color
|
||||
#--media-key-color
|
||||
#--datetime-key-color
|
||||
#--version-key-color
|
||||
#--vulkan-key-color
|
||||
#--opengl-key-color
|
||||
#--opencl-key-color
|
||||
|
||||
+16
-3
@@ -19,6 +19,7 @@ Informative options:
|
||||
|
||||
General options:
|
||||
--load-config <file>: Load a config file or preset (+)
|
||||
--config <file>: Alias of --load-config (+)
|
||||
--multithreading <?value>: Use multiple threads to detect values
|
||||
--stat <?value>: Show time usage (in ms) for individual modules
|
||||
--allow-slow-operations <?value>: Allow operations that are usually very slow for more detailed output
|
||||
@@ -40,6 +41,7 @@ Logo options:
|
||||
--logo-padding-right <padding>: Set the padding on the right of the logo
|
||||
--logo-padding-top <padding>: Set the padding on the top of the logo
|
||||
--logo-print-remaining <?value>: Whether to print the remaining logo, if it has more lines than modules to display
|
||||
--logo-recache <?value>: If true, regenerate image logo cache
|
||||
--file <file>: Short for --logo-type file --logo <file>
|
||||
--file-raw <file>: Short for --logo-type file-raw --logo <file>
|
||||
--data <data>: Short for --logo-type data --logo <data>
|
||||
@@ -58,8 +60,9 @@ Display options:
|
||||
-s,--structure <structure>: Set the structure of the fetch. Must be a colon separated list of keys. Use "fastfetch --list-modules" to see the ones available.
|
||||
--color-keys <color>: Set the color of the keys
|
||||
--color-title <color>: Set the color of the title
|
||||
--color <color>: Set the color of both the keys and title
|
||||
--key-width <num>: Align the width of keys to <num> characters
|
||||
--bright-color <?value>: Set if the keys, title and ASCII logo should be printed in bright color. Default is true
|
||||
-c,--color <color>: Set the color of both the keys and title
|
||||
--separator <str>: Set the separator between key and value. Default is a colon with a space
|
||||
--set <key=value>: Hard set the value of a key
|
||||
--set-keyless <key=value>: Hard set the value of a key, but don't print the key or the separator
|
||||
@@ -68,6 +71,11 @@ Display options:
|
||||
--hide-cursor <?value>: Whether to hide the cursor during the run
|
||||
--binary-prefix <value>: Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC
|
||||
--percent-type <value>: Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1
|
||||
--percent-ndigits <value>: Set the number of digits to keep after the decimal point when formatting percentage numbers. Default is 0
|
||||
--bar-char-elapsed <str>: Set the character to use in elapsed part. Default is '■'
|
||||
--bar-char-total <str>: Set the character to use in total part. Default is '-'
|
||||
--bar-width <?num>: Set the width of the bar, in number of characters. Default is 10
|
||||
--bar-border <?value>: Whether to show a border around the bar. Default is true
|
||||
--no-buffer <?value>: Set if the stdout application buffer should be disabled. Default is false
|
||||
--size-ndigits <value>: Set the number of digits to keep after the decimal point when formatting sizes
|
||||
--size-max-prefix <value>: Set the largest binary prefix to use when formatting sizes. Default is YB
|
||||
@@ -82,6 +90,7 @@ General module options:
|
||||
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
|
||||
|
||||
--<module>-key-color <format>: Override the global `--color-keys` option for each specific module.
|
||||
--<module>-key-width <num>: Override the global `--key-width` option for each specific module.
|
||||
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
@@ -120,7 +129,9 @@ Module specific options:
|
||||
--disk-show-external <?value>: Set if external volume should be printed. Default is true
|
||||
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
|
||||
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
|
||||
--disk-show-readonly <?value>: Set if read only volumes should be printed. Default is false
|
||||
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
|
||||
--disk-use-available <?value>: Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false
|
||||
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
|
||||
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
|
||||
@@ -136,9 +147,11 @@ Module specific options:
|
||||
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
|
||||
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
|
||||
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
|
||||
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
|
||||
--localip-default-route-only <?value>: Show ips that are used for default routing only. Default is false
|
||||
--localip-name-prefix <str>: Show interfaces with given interface name prefix only. Default is empty
|
||||
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is false
|
||||
--localip-compact <?value>: Show all IPs in one line. Default is false
|
||||
--netio-name-prefix <str>: Show interfaces with given name prefix only. Default is empty
|
||||
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is false
|
||||
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--publicip-url: The URL of public IP detection server to be used.
|
||||
--weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
Battery
|
||||
Bios
|
||||
Bluetooth
|
||||
Board
|
||||
Break
|
||||
Chassis
|
||||
Colors
|
||||
CPU
|
||||
CPUUsage
|
||||
Cursor
|
||||
Date
|
||||
Datetime
|
||||
DE
|
||||
Disk
|
||||
Display
|
||||
Font
|
||||
GPU
|
||||
Host
|
||||
Icons
|
||||
Kernel
|
||||
Locale
|
||||
LocalIP
|
||||
Media
|
||||
Memory
|
||||
OpenGL
|
||||
OS
|
||||
Packages
|
||||
Player
|
||||
PowerAdapter
|
||||
Processes
|
||||
PublicIP
|
||||
Separator
|
||||
Shell
|
||||
Swap
|
||||
Terminal
|
||||
TerminalFont
|
||||
Theme
|
||||
Time
|
||||
Title
|
||||
Uptime
|
||||
Vulkan
|
||||
Weather
|
||||
Wifi
|
||||
WM
|
||||
WMTheme
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define FF_BATTERY_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct BatteryResult
|
||||
typedef struct FFBatteryResult
|
||||
{
|
||||
FFstrbuf manufacturer;
|
||||
FFstrbuf modelName;
|
||||
@@ -15,7 +15,7 @@ typedef struct BatteryResult
|
||||
double capacity;
|
||||
FFstrbuf status;
|
||||
double temperature;
|
||||
} BatteryResult;
|
||||
} FFBatteryResult;
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Battery info result is not a JSON object";
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
@@ -68,7 +68,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
|
||||
return NULL;
|
||||
ffStrbufClear(&temp);
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
@@ -78,7 +78,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
|
||||
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
|
||||
ffStrbufAppendS(&battery->status, "AC powered");
|
||||
ffStrbufClear(&temp);
|
||||
|
||||
|
||||
if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
|
||||
{
|
||||
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
|
||||
|
||||
@@ -38,7 +38,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
bool boolValue;
|
||||
const char* error;
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->capacity = 0.0/0.0;
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT))
|
||||
continue;
|
||||
|
||||
BatteryResult* battery = ffListAdd(results);
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
|
||||
@@ -27,7 +27,7 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
|
||||
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
|
||||
return;
|
||||
|
||||
BatteryResult* result = ffListAdd(results);
|
||||
FFBatteryResult* result = ffListAdd(results);
|
||||
|
||||
//capacity must exist and be not empty
|
||||
ffStrbufAppendS(dir, "/capacity");
|
||||
|
||||
@@ -74,7 +74,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
|
||||
continue;
|
||||
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
|
||||
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||
@@ -143,7 +143,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
SYSTEM_BATTERY_STATE info;
|
||||
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
|
||||
{
|
||||
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->technology);
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBluetoothDevice
|
||||
typedef struct FFBluetoothResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf address;
|
||||
FFstrbuf type;
|
||||
uint8_t battery; // 0-100%
|
||||
bool connected;
|
||||
} FFBluetoothDevice;
|
||||
} FFBluetoothResult;
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */);
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
|
||||
if(!ioDevices)
|
||||
@@ -10,7 +10,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
|
||||
|
||||
for(IOBluetoothDevice* ioDevice in ioDevices)
|
||||
{
|
||||
FFBluetoothDevice* device = ffListAdd(devices);
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
|
||||
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
|
||||
ffStrbufInit(&device->type);
|
||||
|
||||
@@ -44,7 +44,7 @@ array [ //root
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
@@ -72,7 +72,7 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
|
||||
ffDBusGetBool(dbus, &dictIter, &device->connected);
|
||||
}
|
||||
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
@@ -130,7 +130,7 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
FFBluetoothDevice* device = ffListAdd(devices);
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
@@ -193,7 +193,7 @@ static const char* detectBluetooth(FFlist* devices)
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */)
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
return detectBluetooth(devices);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */)
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
|
||||
.fReturnConnected = TRUE,
|
||||
@@ -25,7 +25,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
|
||||
return "BluetoothFindFirstDevice() failed or no devices found";
|
||||
|
||||
do {
|
||||
FFBluetoothDevice* device = ffListAdd(devices);
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
@@ -33,9 +33,14 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
|
||||
device->connected = !!btdi.fConnected;
|
||||
|
||||
ffStrbufSetWS(&device->name, btdi.szName);
|
||||
for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i)
|
||||
ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]);
|
||||
ffStrbufTrimRight(&device->name, ':');
|
||||
|
||||
ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
btdi.Address.rgBytes[0],
|
||||
btdi.Address.rgBytes[1],
|
||||
btdi.Address.rgBytes[2],
|
||||
btdi.Address.rgBytes[3],
|
||||
btdi.Address.rgBytes[4],
|
||||
btdi.Address.rgBytes[5]);
|
||||
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
|
||||
|
||||
if(BitTest(&btdi.ulClassofDevice, 13))
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
typedef struct FFBrightnessResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
float value;
|
||||
double min, max, current;
|
||||
} FFBrightnessResult;
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
|
||||
|
||||
@@ -20,7 +20,9 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
|
||||
if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess)
|
||||
{
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
brightness->value = value * 100;
|
||||
brightness->current = value;
|
||||
brightness->max = 1;
|
||||
brightness->min = 0;
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +33,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
|
||||
|
||||
// https://github.com/waydabber/m1ddc
|
||||
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
|
||||
static const char* detectWithDdcci(FFlist* result)
|
||||
FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
|
||||
{
|
||||
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
|
||||
return "IOAVService is not available";
|
||||
@@ -90,7 +92,9 @@ static const char* detectWithDdcci(FFlist* result)
|
||||
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
|
||||
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
brightness->value = (float) current * 100.f / max;
|
||||
brightness->max = max;
|
||||
brightness->min = 0;
|
||||
brightness->current = current;
|
||||
ffStrbufInit(&brightness->name);
|
||||
|
||||
uint8_t edid[128] = {};
|
||||
@@ -108,8 +112,10 @@ const char* ffDetectBrightness(FFlist* result)
|
||||
|
||||
detectWithDisplayServices(displayServer, result);
|
||||
|
||||
if (instance.config.allowSlowOperations && displayServer->displays.length > result->length)
|
||||
#ifdef __aarch64__
|
||||
if (displayServer->displays.length > result->length)
|
||||
detectWithDdcci(result);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -26,13 +26,16 @@ const char* ffDetectBrightness(FFlist* result)
|
||||
if(ioctl(blfd, BACKLIGHTGETSTATUS, &status) < 0)
|
||||
continue;
|
||||
|
||||
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInit(&display->name);
|
||||
display->value = (float) status.brightness / BACKLIGHTMAXLEVELS;
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInit(&brightness->name);
|
||||
|
||||
brightness->max = BACKLIGHTMAXLEVELS;
|
||||
brightness->min = 0;
|
||||
brightness->current = status.brightness;
|
||||
|
||||
struct backlight_info info;
|
||||
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
|
||||
ffStrbufAppendS(&display->name, info.name);
|
||||
ffStrbufAppendS(&brightness->name, info.name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -44,4 +47,4 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
return "Backlight is supported only on FreeBSD 13 and newer";
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -72,8 +72,9 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
}
|
||||
else
|
||||
ffStrbufInitS(&brightness->name, entry->d_name);
|
||||
double maxBrightness = ffStrbufToDouble(&buffer);
|
||||
brightness->value = (float) (actualBrightness * 100 / maxBrightness);
|
||||
brightness->max = ffStrbufToDouble(&buffer);
|
||||
brightness->min = 0;
|
||||
brightness->current = actualBrightness;
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
|
||||
@@ -123,7 +124,9 @@ static const char* detectWithDdcci(FFlist* result)
|
||||
ffddca_free_any_vcp_value(vcpValue);
|
||||
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
brightness->value = (float) current * 100.f / (float) max;
|
||||
brightness->max = max;
|
||||
brightness->min = 0;
|
||||
brightness->current = current;
|
||||
ffStrbufInitS(&brightness->name, display->model_name);
|
||||
}
|
||||
ffddca_close_display(handle);
|
||||
@@ -139,12 +142,9 @@ const char* ffDetectBrightness(FFlist* result)
|
||||
detectWithBacklight(result);
|
||||
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
if (instance.config.allowSlowOperations)
|
||||
{
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
if (result->length < displayServer->displays.length)
|
||||
detectWithDdcci(result);
|
||||
}
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
if (result->length < displayServer->displays.length)
|
||||
detectWithDdcci(result);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -20,7 +20,9 @@ static const char* detectWithWmi(FFlist* result)
|
||||
if(FFWmiVariant vtValue = record.get(L"CurrentBrightness"))
|
||||
{
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
brightness->value = vtValue.get<uint8_t>();
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = vtValue.get<uint8_t>();
|
||||
|
||||
ffStrbufInit(&brightness->name);
|
||||
if (FFWmiVariant vtName = record.get(L"InstanceName"))
|
||||
@@ -51,7 +53,9 @@ static char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist*
|
||||
else
|
||||
ffStrbufInitWS(&brightness->name, physicalMonitor.szPhysicalMonitorDescription);
|
||||
|
||||
brightness->value = (float) (curr - min) * 100.f / (float) (max - min);
|
||||
brightness->max = max;
|
||||
brightness->min = min;
|
||||
brightness->current = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +80,7 @@ const char* ffDetectBrightness(FFlist* result)
|
||||
if (hasBuiltinDisplay(displayServer))
|
||||
detectWithWmi(result);
|
||||
|
||||
if (instance.config.allowSlowOperations && result->length < displayServer->displays.length)
|
||||
if (result->length < displayServer->displays.length)
|
||||
detectWithDdcci(displayServer, result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ const char* ffDetectChassis(FFChassisResult* result)
|
||||
|
||||
if(result->type.length)
|
||||
{
|
||||
const char* typeStr = ffChassisTypeToString(ffStrbufToUInt16(&result->type, 9999));
|
||||
const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999));
|
||||
if(typeStr)
|
||||
ffStrbufSetS(&result->type, typeStr);
|
||||
}
|
||||
|
||||
@@ -2,17 +2,6 @@
|
||||
#include "common/sysctl.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
|
||||
static double getFrequency(const char* propName)
|
||||
{
|
||||
double herz = (double) ffSysctlGetInt64(propName, 0);
|
||||
if(herz <= 0.0)
|
||||
return herz;
|
||||
|
||||
herz /= 1000.0; //to KHz
|
||||
herz /= 1000.0; //to MHz
|
||||
return herz / 1000.0; //to GHz
|
||||
}
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
{
|
||||
double result = 0;
|
||||
@@ -31,11 +20,85 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
// https://github.com/giampaolo/psutil/pull/2222/files
|
||||
|
||||
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice");
|
||||
if (matchDict == NULL)
|
||||
return "IOServiceMatching(\"AppleARMIODevice\") failed";
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
|
||||
continue;
|
||||
if (strcmp(name, "pmgr") != 0)
|
||||
continue;
|
||||
|
||||
uint32_t pMin, eMin, aMax, pCoreLength;
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
|
||||
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
|
||||
|
||||
if (pCoreLength >= 8)
|
||||
{
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
|
||||
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
|
||||
}
|
||||
else
|
||||
cpu->frequencyMax = 0.0;
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
IOObjectRelease(iterator);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0;
|
||||
else
|
||||
{
|
||||
unsigned current = 0;
|
||||
size_t size = sizeof(current);
|
||||
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0)
|
||||
cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
|
||||
return "sysctlbyname(machdep.cpu.brand_string) failed";
|
||||
|
||||
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
|
||||
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple "))
|
||||
ffStrbufAppendS(&cpu->vendor, "Apple");
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
|
||||
if(cpu->coresPhysical == 1)
|
||||
@@ -49,10 +112,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if(cpu->coresOnline == 1)
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||
|
||||
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
|
||||
if(cpu->frequencyMax == 0.0)
|
||||
cpu->frequencyMax = getFrequency("hw.cpufrequency");
|
||||
detectFrequency(cpu);
|
||||
|
||||
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "cpu.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/mallocHelper.h"
|
||||
@@ -128,7 +129,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
const char* error = parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch);
|
||||
if (error) return error;
|
||||
|
||||
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 1);
|
||||
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
@@ -163,5 +164,17 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectAndroid(cpu);
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL }))
|
||||
{
|
||||
ffParsePropLines(buffer.chars, "Model name:", &cpu->name);
|
||||
if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
||||
}
|
||||
|
||||
FF_HKEY_AUTO_DESTROY hKey;
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ const char* ffGetCpuUsageResult(double* result)
|
||||
if(inUseAll2 != inUseAll1)
|
||||
{
|
||||
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
inUseAll1 = inUseAll2;
|
||||
totalAll1 = totalAll2;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/datetime/datetime.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
const FFDateTimeResult* ffDetectDateTime(void)
|
||||
{
|
||||
static FFDateTimeResult result;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
if (init)
|
||||
{
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
const time_t t = time(NULL);
|
||||
struct tm* tm = localtime(&t);
|
||||
|
||||
result.year = (uint16_t) (tm->tm_year + 1900);
|
||||
result.yearShort = (uint8_t) (result.year % 100);
|
||||
result.month = (uint8_t) (tm->tm_mon + 1);
|
||||
|
||||
ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm);
|
||||
|
||||
ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm);
|
||||
|
||||
ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm);
|
||||
|
||||
result.week = (uint8_t) (tm->tm_yday / 7 + 1);
|
||||
|
||||
ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm);
|
||||
|
||||
ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm);
|
||||
|
||||
result.dayInYear = (uint8_t) (tm->tm_yday + 1);
|
||||
result.dayInMonth = (uint8_t) tm->tm_mday;
|
||||
result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday;
|
||||
|
||||
result.hour = (uint8_t) tm->tm_hour;
|
||||
|
||||
ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
|
||||
|
||||
result.hour12 = (uint8_t) (result.hour % 12);
|
||||
|
||||
ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
|
||||
|
||||
result.minute = (uint8_t) tm->tm_min;
|
||||
|
||||
ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
|
||||
|
||||
result.second = (uint8_t) tm->tm_sec;
|
||||
|
||||
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
|
||||
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FF_INCLUDED_detection_datetime_datetime
|
||||
#define FF_INCLUDED_detection_datetime_datetime
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFDateTimeResult
|
||||
{
|
||||
//Examples for 21.02.2022 - 15:18:37
|
||||
uint16_t year; //2022
|
||||
uint8_t yearShort; //22
|
||||
uint8_t month; //2
|
||||
FFstrbuf monthPretty; //02
|
||||
FFstrbuf monthName; //February
|
||||
FFstrbuf monthNameShort; //Feb
|
||||
uint8_t week; //8
|
||||
FFstrbuf weekday; //Monday
|
||||
FFstrbuf weekdayShort; //Mon
|
||||
uint16_t dayInYear; //52
|
||||
uint8_t dayInMonth; //21
|
||||
uint8_t dayInWeek; //1
|
||||
uint8_t hour; //15
|
||||
FFstrbuf hourPretty; //15
|
||||
uint8_t hour12; //3
|
||||
FFstrbuf hour12Pretty; //03
|
||||
uint8_t minute; //18
|
||||
FFstrbuf minutePretty; //18
|
||||
uint8_t second; //37
|
||||
FFstrbuf secondPretty; //37
|
||||
} FFDateTimeResult;
|
||||
|
||||
const FFDateTimeResult* ffDetectDateTime();
|
||||
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@ static int compareDisks(const void* disk1, const void* disk2)
|
||||
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
|
||||
}
|
||||
|
||||
const char* ffDetectDisks(FFlist* disks)
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
const char* error = ffDetectDisksImpl(disks);
|
||||
|
||||
@@ -22,7 +22,13 @@ const char* ffDetectDisks(FFlist* disks)
|
||||
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
|
||||
{
|
||||
if(disk->bytesTotal == 0)
|
||||
disk->type |= FF_DISK_TYPE_UNKNOWN_BIT;
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_UNKNOWN_BIT;
|
||||
else
|
||||
{
|
||||
disk->bytesUsed = disk->bytesTotal - (
|
||||
options->calcType == FF_DISK_CALC_TYPE_FREE ? disk->bytesFree : disk->bytesAvailable
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -5,14 +5,25 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef enum FFDiskPhysicalType
|
||||
{
|
||||
FF_DISK_PHYSICAL_TYPE_UNKNOWN,
|
||||
FF_DISK_PHYSICAL_TYPE_HDD,
|
||||
FF_DISK_PHYSICAL_TYPE_SSD,
|
||||
} FFDiskPhysicalType;
|
||||
|
||||
typedef struct FFDisk
|
||||
{
|
||||
FFstrbuf mountFrom;
|
||||
FFstrbuf mountpoint;
|
||||
FFstrbuf filesystem;
|
||||
FFstrbuf name;
|
||||
FFDiskType type;
|
||||
FFDiskVolumeType type;
|
||||
FFDiskPhysicalType physicalType;
|
||||
|
||||
uint64_t bytesUsed;
|
||||
uint64_t bytesFree;
|
||||
uint64_t bytesAvailable;
|
||||
uint64_t bytesTotal;
|
||||
|
||||
uint32_t filesUsed;
|
||||
@@ -23,6 +34,6 @@ typedef struct FFDisk
|
||||
* Returns a List of FFDisk, sorted alphabetically by mountpoint.
|
||||
* If error is not set, disks contains at least one disk.
|
||||
*/
|
||||
const char* ffDetectDisks(FFlist* result /* list of FFDisk */);
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* result /* list of FFDisk */);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "disk.h"
|
||||
|
||||
#include <sys/mount.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
{
|
||||
// FreeBSD doesn't support these flags
|
||||
if(fs->f_flags & MNT_DONTBROWSE)
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
else if(fs->f_flags & MNT_REMOVABLE)
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
|
||||
ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String);
|
||||
}
|
||||
@@ -1,42 +1,68 @@
|
||||
#include "disk.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
{
|
||||
if(
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/boot") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/dev") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/var") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/tmp") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/proc") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/zroot") ||
|
||||
ffStrbufStartsWithS(&disk->mountpoint, "/compat/linux/")
|
||||
)
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
else if((fs->f_flags & MNT_NOSUID) || !(fs->f_flags & MNT_LOCAL))
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
if(ffStrbufEqualS(&disk->filesystem, "zfs"))
|
||||
{
|
||||
disk->type = !ffStrbufStartsWithS(&disk->mountFrom, "zroot/") || ffStrbufStartsWithS(&disk->mountFrom, "zroot/ROOT/")
|
||||
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
|
||||
: FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
|
||||
}
|
||||
else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi"))
|
||||
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
else if(!(fs->f_flags & MNT_LOCAL))
|
||||
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
|
||||
ffStrbufInit(&disk->name);
|
||||
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
}
|
||||
#elif __APPLE__
|
||||
#include <sys/attr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct VolAttrBuf {
|
||||
uint32_t length;
|
||||
attrreference_t volNameRef;
|
||||
char volNameSpace[MAXPATHLEN];
|
||||
} __attribute__((aligned(4), packed));
|
||||
|
||||
void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
{
|
||||
if(fs->f_flags & MNT_DONTBROWSE)
|
||||
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
else if(fs->f_flags & MNT_REMOVABLE || !(fs->f_flags & MNT_LOCAL))
|
||||
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
|
||||
struct VolAttrBuf attrBuf;
|
||||
if (getattrlist(disk->mountpoint.chars, &(struct attrlist) {
|
||||
.bitmapcount = ATTR_BIT_MAP_COUNT,
|
||||
.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME,
|
||||
}, &attrBuf, sizeof(attrBuf), 0) == 0)
|
||||
ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace);
|
||||
}
|
||||
#else
|
||||
void detectFsInfo(struct statfs* fs, FFDisk* disk);
|
||||
#endif
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
{
|
||||
struct statfs* buf;
|
||||
int size = getfsstat(NULL, 0, MNT_WAIT);
|
||||
|
||||
int size = getmntinfo(&buf, MNT_WAIT);
|
||||
if(size <= 0)
|
||||
return "getmntinfo(&buf, MNT_WAIT) failed";
|
||||
return "getfsstat(NULL, 0, MNT_WAIT) failed";
|
||||
|
||||
FF_AUTO_FREE struct statfs* buf = malloc(sizeof(*buf) * (unsigned) size);
|
||||
if(getfsstat(buf, (int) (sizeof(*buf) * (unsigned) size), MNT_NOWAIT) <= 0)
|
||||
return "getfsstat(buf, size, MNT_NOWAIT) failed";
|
||||
|
||||
for(struct statfs* fs = buf; fs < buf + size; ++fs)
|
||||
{
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
continue;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
// f_bavail and f_ffree are signed on FreeBSD...
|
||||
@@ -44,15 +70,26 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
if(fs->f_ffree < 0) fs->f_ffree = 0;
|
||||
#endif
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
|
||||
|
||||
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
|
||||
disk->bytesUsed = disk->bytesTotal - ((uint64_t)fs->f_bfree * fs->f_bsize);
|
||||
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
|
||||
disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
|
||||
disk->filesTotal = (uint32_t) fs->f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree);
|
||||
|
||||
ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname);
|
||||
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
|
||||
ffStrbufInitS(&disk->filesystem, fs->f_fstypename);
|
||||
ffStrbufInit(&disk->name);
|
||||
disk->type = 0;
|
||||
detectFsInfo(fs, disk);
|
||||
|
||||
if(fs->f_flags & MNT_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
+163
-111
@@ -1,5 +1,6 @@
|
||||
#include "disk.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <limits.h>
|
||||
@@ -7,6 +8,8 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifdef __USE_LARGEFILE64
|
||||
#define stat stat64
|
||||
@@ -15,77 +18,60 @@
|
||||
#define readdir readdir64
|
||||
#endif
|
||||
|
||||
static bool isPhysicalDevice(FFstrbuf* device)
|
||||
static bool isPhysicalDevice(const struct mntent* device)
|
||||
{
|
||||
#ifndef __ANDROID__ //On Android, `/dev` is not accessable, so that the following checks always fail
|
||||
|
||||
//https://askubuntu.com/a/1289123
|
||||
if(ffStrbufEqualS(device, "/cow"))
|
||||
//Always show the root path
|
||||
if(ffStrEquals(device->mnt_dir, "/"))
|
||||
return true;
|
||||
|
||||
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
|
||||
if(ffStrbufEqualS(device, "drvfs"))
|
||||
if(ffStrEquals(device->mnt_fsname, "drvfs"))
|
||||
return true;
|
||||
|
||||
//ZFS root pool. The format is rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>
|
||||
if(ffStrbufStartsWithS(device, "rpool/"))
|
||||
//ZFS pool
|
||||
if(ffStrEquals(device->mnt_type, "zfs"))
|
||||
return true;
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
|
||||
return false;
|
||||
|
||||
if(
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices
|
||||
) return false;
|
||||
|
||||
struct stat deviceStat;
|
||||
if(stat(device->chars, &deviceStat) != 0)
|
||||
if(stat(device->mnt_fsname, &deviceStat) != 0)
|
||||
return false;
|
||||
|
||||
//Ignore all devices that are not block devices
|
||||
if(!S_ISBLK(deviceStat.st_mode))
|
||||
return false;
|
||||
|
||||
#else
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
if(!ffStrbufStartsWithS(device, "/dev/"))
|
||||
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
|
||||
return false;
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
if(
|
||||
ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices
|
||||
ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices
|
||||
ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
|
||||
ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices
|
||||
) return false;
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void appendNextEntry(FFstrbuf* buffer, char** source)
|
||||
{
|
||||
//Read the current entry into the buffer
|
||||
while(**source != '\0' && !isspace(**source))
|
||||
{
|
||||
//After a backslash the next 3 characters are octal ascii codes
|
||||
if(**source == '\\' && strnlen(*source, 4) == 4)
|
||||
{
|
||||
char octal[4] = {0};
|
||||
strncpy(octal, *source + 1, 3);
|
||||
|
||||
long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr
|
||||
if(value > 0 && value < CHAR_MAX)
|
||||
{
|
||||
ffStrbufAppendC(buffer, (char) value);
|
||||
*source += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendC(buffer, **source);
|
||||
++*source;
|
||||
}
|
||||
|
||||
//Skip whitespace
|
||||
while(isspace(**source))
|
||||
++*source;
|
||||
}
|
||||
|
||||
static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath)
|
||||
{
|
||||
DIR* dir = opendir(basePath->chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath->chars);
|
||||
if(dir == NULL)
|
||||
return;
|
||||
|
||||
@@ -110,82 +96,161 @@ static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFst
|
||||
ffStrbufAppendS(&disk->name, entry->d_name);
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
static void detectName(FFDisk* disk)
|
||||
{
|
||||
struct stat deviceStat;
|
||||
if(stat(device->chars, &deviceStat) != 0)
|
||||
if(stat(disk->mountFrom.chars, &deviceStat) != 0)
|
||||
return;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate();
|
||||
|
||||
//Try partlabel first
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-partlabel/");
|
||||
//Detect USB devices. Code is put here to reuse deviceStat
|
||||
//https://stackoverflow.com/a/73302717
|
||||
ffStrbufAppendS(&basePath, "/dev/disk/by-id/");
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
if (ffStrbufStartsWithS(&disk->name, "usb-"))
|
||||
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
ffStrbufClear(&disk->name);
|
||||
|
||||
//Try label first
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-label/");
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
|
||||
//Try label second
|
||||
if(disk->name.length == 0)
|
||||
{
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-label/");
|
||||
//Try partlabel second
|
||||
ffStrbufSetS(&basePath, "/dev/disk/by-partlabel/");
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
}
|
||||
|
||||
//Use the mountpoint as a last resort
|
||||
if(disk->name.length == 0)
|
||||
ffStrbufAppend(&disk->name, &disk->mountpoint);
|
||||
if (disk->name.length == 0) return;
|
||||
|
||||
// Basic\x20data\x20partition
|
||||
for (uint32_t i = ffStrbufFirstIndexS(&disk->name, "\\x");
|
||||
i != disk->name.length;
|
||||
i = ffStrbufNextIndexS(&disk->name, i + 1, "\\x"))
|
||||
{
|
||||
uint32_t len = (uint32_t) strlen("\\x20");
|
||||
if (disk->name.length >= len)
|
||||
{
|
||||
char bak = disk->name.chars[i + len];
|
||||
disk->name.chars[i + len] = '\0';
|
||||
disk->name.chars[i] = (char) strtoul(&disk->name.chars[i + 2], NULL, 16);
|
||||
ffStrbufRemoveSubstr(&disk->name, i + 1, i + len);
|
||||
disk->name.chars[i + 1] = bak;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options)
|
||||
static void detectType(FF_MAYBE_UNUSED const FFlist* disks, FFDisk* currentDisk)
|
||||
{
|
||||
if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated"))
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/mnt/media_rw/"))
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool isSubvolume(const FFlist* devices)
|
||||
static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk)
|
||||
{
|
||||
const FFstrbuf* current = ffListGet(devices, devices->length - 1);
|
||||
|
||||
if(ffStrbufEqualS(current, "drvfs")) // WSL Windows drives
|
||||
if(ffStrbufEqualS(¤tDisk->mountFrom, "drvfs")) // WSL Windows drives
|
||||
return false;
|
||||
|
||||
//Filter all disks which device was already found. This catches BTRFS subvolumes.
|
||||
for(uint32_t i = 0; i < devices->length - 1; i++)
|
||||
if(ffStrbufEqualS(¤tDisk->filesystem, "zfs"))
|
||||
{
|
||||
const FFstrbuf* otherDevice = ffListGet(devices, i);
|
||||
//ZFS subvolumes
|
||||
uint32_t index = ffStrbufFirstIndexC(¤tDisk->mountFrom, '/');
|
||||
if (index == currentDisk->mountFrom.length)
|
||||
return false;
|
||||
|
||||
if(ffStrbufEqual(current, otherDevice))
|
||||
return true;
|
||||
FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->mountFrom.chars);
|
||||
for(uint32_t i = 0; i < disks->length - 1; i++)
|
||||
{
|
||||
const FFDisk* otherDevice = ffListGet(disks, i);
|
||||
if(ffStrbufEqualS(&otherDevice->filesystem, "zfs") && ffStrbufStartsWith(&otherDevice->mountFrom, &zpoolName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Filter all disks which device was already found. This catches BTRFS subvolumes.
|
||||
for(uint32_t i = 0; i < disks->length - 1; i++)
|
||||
{
|
||||
const FFDisk* otherDevice = ffListGet(disks, i);
|
||||
|
||||
//ZFS subvolumes: rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>.
|
||||
//Test if the third slash is present.
|
||||
if(ffStrbufStartsWithS(current, "rpool/") && ffStrHasNChars(current->chars, '/', 3))
|
||||
return true;
|
||||
if(ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options)
|
||||
static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk)
|
||||
{
|
||||
if(isSubvolume(devices))
|
||||
currentDisk->type = FF_DISK_TYPE_SUBVOLUME_BIT;
|
||||
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
|
||||
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
// https://stackoverflow.com/a/73302025
|
||||
// Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does.
|
||||
// USB devices should be handled in detectName
|
||||
FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/sys/block/");
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath.chars);
|
||||
if(dir == NULL)
|
||||
return false;
|
||||
|
||||
uint32_t index = ffStrbufLastIndexC(¤tDisk->mountFrom, '/');
|
||||
const char* partitionName = index == currentDisk->mountFrom.length ? NULL : currentDisk->mountFrom.chars + index + 1;
|
||||
if (!partitionName || !*partitionName) return false;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (!ffStrStartsWith(partitionName, entry->d_name)) continue;
|
||||
|
||||
ffStrbufAppendS(&basePath, entry->d_name);
|
||||
index = basePath.length;
|
||||
// /sys/block/sdx/queue/rotational
|
||||
ffStrbufAppendS(&basePath, "/queue/rotational");
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (ffReadFileBuffer(basePath.chars, &buffer))
|
||||
currentDisk->physicalType = ffStrbufEqualS(&buffer, "1") ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD;
|
||||
else
|
||||
currentDisk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
|
||||
ffStrbufSubstrBefore(&basePath, index);
|
||||
|
||||
// /sys/block/sdx/removable
|
||||
ffStrbufAppendS(&basePath, "/removable");
|
||||
|
||||
return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectType(const FFlist* disks, FFDisk* currentDisk)
|
||||
{
|
||||
bool isRemovable = detectPhysicalTypeAndReturnRemovable(currentDisk);
|
||||
|
||||
if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return;
|
||||
if(isRemovable)
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else if(isSubvolume(disks, currentDisk))
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
|
||||
else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi"))
|
||||
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
else
|
||||
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -197,69 +262,56 @@ static void detectStats(FFDisk* disk)
|
||||
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
|
||||
|
||||
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
|
||||
disk->bytesUsed = disk->bytesTotal - (fs.f_bfree * fs.f_frsize);
|
||||
disk->bytesFree = fs.f_bfree * fs.f_frsize;
|
||||
disk->bytesAvailable = fs.f_bavail * fs.f_frsize;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
|
||||
disk->filesTotal = (uint32_t) fs.f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
|
||||
|
||||
if(fs.f_flag & ST_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
}
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
{
|
||||
FILE* mountsFile = fopen("/proc/mounts", "r");
|
||||
FILE* mountsFile = setmntent("/proc/mounts", "r");
|
||||
if(mountsFile == NULL)
|
||||
return "fopen(\"/proc/mounts\", \"r\") == NULL";
|
||||
return "setmntent(\"/proc/mounts\", \"r\") == NULL";
|
||||
|
||||
FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof(FFstrbuf));
|
||||
struct mntent* device;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
while(getline(&line, &len, mountsFile) != EOF)
|
||||
while((device = getmntent(mountsFile)))
|
||||
{
|
||||
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
|
||||
char* currentPos = line;
|
||||
|
||||
//detect device
|
||||
FFstrbuf* device = ffListAdd(&devices);
|
||||
ffStrbufInit(device);
|
||||
appendNextEntry(device, ¤tPos);
|
||||
|
||||
if(!isPhysicalDevice(device))
|
||||
{
|
||||
ffStrbufDestroy(device);
|
||||
devices.length--;
|
||||
continue;
|
||||
}
|
||||
|
||||
//We have a valid device, add it to the list
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
disk->type = FF_DISK_VOLUME_TYPE_NONE;
|
||||
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
|
||||
|
||||
//detect mountFrom
|
||||
ffStrbufInitS(&disk->mountFrom, device->mnt_fsname);
|
||||
|
||||
//detect mountpoint
|
||||
ffStrbufInit(&disk->mountpoint);
|
||||
appendNextEntry(&disk->mountpoint, ¤tPos);
|
||||
ffStrbufInitS(&disk->mountpoint, device->mnt_dir);
|
||||
|
||||
//detect filesystem
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
appendNextEntry(&disk->filesystem, ¤tPos);
|
||||
ffStrbufInitS(&disk->filesystem, device->mnt_type);
|
||||
|
||||
//detect name
|
||||
ffStrbufInit(&disk->name);
|
||||
detectName(disk, device);
|
||||
detectName(disk); // Also detects external devices
|
||||
|
||||
//detect type
|
||||
detectType(&devices, disk, currentPos);
|
||||
detectType(disks, disk);
|
||||
|
||||
//Detects stats
|
||||
detectStats(disk);
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, device, devices)
|
||||
ffStrbufDestroy(device);
|
||||
|
||||
fclose(mountsFile);
|
||||
endmntent(mountsFile);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "disk.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char* ffDetectDisksImpl(FFlist* disks)
|
||||
@@ -25,20 +27,60 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
ffStrbufInitWS(&disk->mountpoint, mountpoint);
|
||||
|
||||
uint64_t bytesFree;
|
||||
if(!GetDiskFreeSpaceExW(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
|
||||
wchar_t volumeName[64];
|
||||
|
||||
disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN;
|
||||
if(mountpoint[1] == ':')
|
||||
{
|
||||
memcpy(volumeName, L"\\\\.\\ :", sizeof(L"\\\\.\\ :"));
|
||||
volumeName[4] = mountpoint[0];
|
||||
FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(volumeName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {};
|
||||
if(DeviceIoControl(
|
||||
handle,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
&(STORAGE_PROPERTY_QUERY) {
|
||||
.PropertyId = StorageDeviceSeekPenaltyProperty,
|
||||
.QueryType = PropertyStandardQuery,
|
||||
},
|
||||
sizeof(STORAGE_PROPERTY_QUERY),
|
||||
&dspd,
|
||||
sizeof(dspd),
|
||||
NULL,
|
||||
NULL
|
||||
))
|
||||
disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD;
|
||||
}
|
||||
}
|
||||
|
||||
if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
|
||||
{
|
||||
ffStrbufInitWS(&disk->mountFrom, volumeName);
|
||||
}
|
||||
else
|
||||
ffStrbufInit(&disk->mountFrom);
|
||||
|
||||
if(!GetDiskFreeSpaceExW(
|
||||
mountpoint,
|
||||
(PULARGE_INTEGER)&disk->bytesAvailable,
|
||||
(PULARGE_INTEGER)&disk->bytesTotal,
|
||||
(PULARGE_INTEGER)&disk->bytesFree
|
||||
))
|
||||
{
|
||||
disk->bytesTotal = 0;
|
||||
bytesFree = 0;
|
||||
disk->bytesFree = 0;
|
||||
disk->bytesAvailable = 0;
|
||||
}
|
||||
disk->bytesUsed = disk->bytesTotal - bytesFree;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
|
||||
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
|
||||
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
|
||||
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
|
||||
else if(driveType == DRIVE_FIXED)
|
||||
disk->type = FF_DISK_TYPE_REGULAR_BIT;
|
||||
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
else
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
|
||||
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
|
||||
|
||||
ffStrbufInit(&disk->filesystem);
|
||||
ffStrbufInit(&disk->name);
|
||||
@@ -47,11 +89,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
|
||||
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
DWORD diskFlags;
|
||||
BOOL result = GetVolumeInformationW(mountpoint,
|
||||
diskName, sizeof(diskName) / sizeof(*diskName), //Volume name
|
||||
NULL, //Serial number
|
||||
NULL, //Max component length
|
||||
NULL, //File system flags
|
||||
&diskFlags, //File system flags
|
||||
diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem)
|
||||
);
|
||||
SetErrorMode(errorMode);
|
||||
@@ -60,6 +103,8 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
{
|
||||
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
|
||||
ffStrbufSetWS(&disk->name, diskName);
|
||||
if(diskFlags & FILE_READ_ONLY_VOLUME)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
}
|
||||
|
||||
//Unsupported
|
||||
|
||||
@@ -80,9 +80,9 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
ffStrbufContainC(&buffer, ','))
|
||||
{
|
||||
// 1440,3200,560 => width,height,ppi
|
||||
uint32_t width = ffStrbufToUInt16(&buffer, 0);
|
||||
uint32_t width = (uint32_t) ffStrbufToUInt(&buffer, 0);
|
||||
ffStrbufSubstrAfterFirstC(&buffer, ',');
|
||||
uint32_t height = ffStrbufToUInt16(&buffer, 0);
|
||||
uint32_t height = (uint32_t) ffStrbufToUInt(&buffer, 0);
|
||||
return ffdsAppendDisplay(ds,
|
||||
width,
|
||||
height,
|
||||
|
||||
@@ -233,6 +233,23 @@ static void getXFCE4(FFDisplayServerResult* result)
|
||||
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
|
||||
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if(result->deVersion.length == 0)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
|
||||
continue;
|
||||
ffStrbufAppendS(&result->deVersion, &entry->d_name[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
|
||||
{
|
||||
//This is somewhat slow
|
||||
|
||||
@@ -116,6 +116,7 @@ typedef struct XrandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(XInternAtom)
|
||||
FF_LIBRARY_SYMBOL(XGetAtomName);
|
||||
FF_LIBRARY_SYMBOL(XFree);
|
||||
FF_LIBRARY_SYMBOL(XRRGetScreenInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentConfiguration)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentRate)
|
||||
@@ -207,9 +208,11 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
|
||||
Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true);
|
||||
if (atomEdid != None)
|
||||
{
|
||||
unsigned long nitems = 0;
|
||||
int actual_format = 0;
|
||||
unsigned long nitems = 0, bytes_after = 0;
|
||||
Atom actual_type = None;
|
||||
uint8_t* edidData = NULL;
|
||||
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, 0, 0, AnyPropertyType, NULL, NULL, &nitems, NULL, &edidData) == Success)
|
||||
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success)
|
||||
{
|
||||
if (nitems >= 128)
|
||||
{
|
||||
@@ -217,6 +220,8 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
|
||||
ffEdidGetName(edidData, name);
|
||||
}
|
||||
}
|
||||
if (edidData)
|
||||
data->ffXFree(edidData);
|
||||
}
|
||||
bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary);
|
||||
|
||||
@@ -228,8 +233,9 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
bool foundOutput = false;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(data->ffXGetAtomName(data->display, monitorInfo->name));
|
||||
char* xname = data->ffXGetAtomName(data->display, monitorInfo->name);
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(xname);
|
||||
data->ffXFree(xname);
|
||||
for(int i = 0; i < monitorInfo->noutput; i++)
|
||||
{
|
||||
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary))
|
||||
@@ -341,6 +347,7 @@ void ffdsConnectXrandr(FFDisplayServerResult* result)
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XInternAtom,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XGetAtomName,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XFree,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetScreenInfo,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentRate,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentConfiguration,);
|
||||
|
||||
@@ -130,7 +130,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
|
||||
ffStrbufSetWS(&device->name, displayName);
|
||||
else
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,6 +311,12 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
||||
if (!ffGPUDetectByDirectX(options, gpus))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
return pciDetectGPUs(options, gpus);
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
|
||||
#define INITGUID
|
||||
extern "C" {
|
||||
#include "common/library.h"
|
||||
#include "detection/gpu/gpu.h"
|
||||
}
|
||||
|
||||
#include <wsl/winadapter.h>
|
||||
#include <directx/dxcore.h>
|
||||
#include <directx/d3d12.h>
|
||||
#include <dxguids/dxguids.h>
|
||||
#include <utility>
|
||||
#include <cinttypes>
|
||||
|
||||
template <typename Fn>
|
||||
struct on_scope_exit {
|
||||
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
|
||||
~on_scope_exit() { this->_fn(); }
|
||||
|
||||
private:
|
||||
Fn _fn;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libdxcore, nullptr, "dlopen libdxcore.so failed. Make sure WSLg is enabled", "/usr/lib/wsl/lib/libdxcore" FF_LIBRARY_EXTENSION, 4)
|
||||
// DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here
|
||||
typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory);
|
||||
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(libdxcore, "DXCoreCreateAdapterFactory");
|
||||
if(ffDXCoreCreateAdapterFactory == nullptr) return "dlsym DXCoreCreateAdapterFactory failed";
|
||||
|
||||
IDXCoreAdapterFactory *factory = nullptr;
|
||||
|
||||
if (FAILED(ffDXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory))))
|
||||
return "DXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory)) failed";
|
||||
on_scope_exit destroyFactory([&] { factory->Release(); });
|
||||
|
||||
IDXCoreAdapterList *list = NULL;
|
||||
if (FAILED(factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list)))
|
||||
return "factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list) failed";
|
||||
on_scope_exit destroyList([&] { list->Release(); });
|
||||
|
||||
for (uint32_t i = 0, count = list->GetAdapterCount(); i < count; i++)
|
||||
{
|
||||
IDXCoreAdapter *adapter = nullptr;
|
||||
if (FAILED(list->GetAdapter(i, &adapter)))
|
||||
continue;
|
||||
on_scope_exit destroyAdapter([&] { adapter->Release(); });
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/dxcore_interface/ne-dxcore_interface-dxcoreadapterproperty
|
||||
{
|
||||
bool value = 0;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsHardware, sizeof(value), &value)) && !value)
|
||||
continue;
|
||||
}
|
||||
|
||||
char desc[256];
|
||||
if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, sizeof(desc), desc)))
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
|
||||
ffStrbufInitS(&gpu->name, desc);
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
uint64_t value = 0;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverVersion, sizeof(value), &value)))
|
||||
{
|
||||
ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64 ".%" PRIu64 ".%" PRIu64,
|
||||
(value >> 48) & 0xFFFF,
|
||||
(value >> 32) & 0xFFFF,
|
||||
(value >> 16) & 0xFFFF,
|
||||
(value >> 0) & 0xFFFF);
|
||||
}
|
||||
|
||||
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DedicatedAdapterMemory, sizeof(value), &value)))
|
||||
gpu->dedicated.total = value;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::SharedSystemMemory, sizeof(value), &value)))
|
||||
gpu->shared.total = value;
|
||||
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
bool integrated;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, sizeof(integrated), &integrated)))
|
||||
gpu->type = integrated ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
DXCoreHardwareID hardwareId;
|
||||
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
|
||||
{
|
||||
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
|
||||
ffStrbufAppendS(&gpu->vendor, vendorStr);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -59,7 +59,7 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffStrbufAppendF(&host->productName, " - %s", wslDistroName);
|
||||
ffStrbufAppendS(&host->productFamily, "WSL");
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY wslVer = ffStrbufCreate(); //Wide charactors
|
||||
FF_STRBUF_AUTO_DESTROY wslVer = ffStrbufCreate(); //Wide characters
|
||||
if(!ffProcessAppendStdOut(&wslVer, (char* const[]){
|
||||
"wsl.exe",
|
||||
"--version",
|
||||
|
||||
@@ -12,10 +12,6 @@ typedef struct FFLocalIpResult
|
||||
FFstrbuf ipv6;
|
||||
FFstrbuf mac;
|
||||
bool defaultRoute;
|
||||
|
||||
#ifdef _WIN32
|
||||
uint32_t ifIndex;
|
||||
#endif
|
||||
} FFLocalIpResult;
|
||||
|
||||
const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "localip.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
@@ -11,124 +13,11 @@
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <net/if_dl.h>
|
||||
#include <net/route.h>
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <netpacket/packet.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
|
||||
{
|
||||
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
|
||||
if (!netRoute) return false;
|
||||
|
||||
// skip first line
|
||||
flockfile(netRoute);
|
||||
while (getc_unlocked(netRoute) != '\n');
|
||||
funlockfile(netRoute);
|
||||
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
|
||||
|
||||
static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small");
|
||||
while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2)
|
||||
{
|
||||
if (destination == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#elif defined(__FreeBSD__) || defined(__APPLE__)
|
||||
|
||||
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__NetBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
|
||||
#elif defined(__FreeBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__OpenBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#else
|
||||
# error unknown platform
|
||||
#endif
|
||||
|
||||
static struct sockaddr *
|
||||
get_rt_address(struct rt_msghdr *rtm, int desired)
|
||||
{
|
||||
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
|
||||
|
||||
for (int i = 0; i < RTAX_MAX; i++)
|
||||
{
|
||||
if (rtm->rtm_addrs & (1 << i))
|
||||
{
|
||||
if ((1 <<i ) == desired)
|
||||
return sa;
|
||||
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
|
||||
{
|
||||
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
|
||||
|
||||
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
|
||||
if (pfRoute < 0)
|
||||
return false;
|
||||
|
||||
{
|
||||
struct timeval timeout = {1, 0};
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
int pid = getpid();
|
||||
|
||||
struct {
|
||||
struct rt_msghdr hdr;
|
||||
struct sockaddr_in dst;
|
||||
uint8_t data[512];
|
||||
} rtmsg = {
|
||||
.hdr = {
|
||||
.rtm_type = RTM_GET,
|
||||
.rtm_flags = RTF_UP | RTF_GATEWAY,
|
||||
.rtm_version = RTM_VERSION,
|
||||
.rtm_addrs = RTA_DST | RTA_IFP,
|
||||
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
|
||||
.rtm_pid = pid,
|
||||
.rtm_seq = 1,
|
||||
},
|
||||
.dst = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_len = sizeof(rtmsg.dst),
|
||||
},
|
||||
};
|
||||
|
||||
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
|
||||
return false;
|
||||
|
||||
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
|
||||
{
|
||||
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
|
||||
{
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
|
||||
if (sdl)
|
||||
{
|
||||
assert(sdl->sdl_nlen <= IF_NAMESIZE);
|
||||
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
|
||||
iface[sdl->sdl_nlen] = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute)
|
||||
{
|
||||
FFLocalIpResult* ip = NULL;
|
||||
|
||||
@@ -145,7 +34,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
|
||||
ffStrbufInit(&ip->ipv4);
|
||||
ffStrbufInit(&ip->ipv6);
|
||||
ffStrbufInit(&ip->mac);
|
||||
ip->defaultRoute = false;
|
||||
ip->defaultRoute = defaultRoute;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
@@ -168,11 +57,17 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
if(getifaddrs(&ifAddrStruct) < 0)
|
||||
return "getifaddrs(&ifAddrStruct) failed";
|
||||
|
||||
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
|
||||
|
||||
for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name);
|
||||
if (options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
if ((ifa->ifa_flags & IFF_LOOPBACK) && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT))
|
||||
continue;
|
||||
|
||||
@@ -187,7 +82,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute);
|
||||
}
|
||||
else if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
@@ -197,7 +92,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute);
|
||||
}
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
else if (ifa->ifa_addr->sa_family == AF_LINK)
|
||||
@@ -209,7 +104,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr);
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute);
|
||||
}
|
||||
#else
|
||||
else if (ifa->ifa_addr->sa_family == AF_PACKET)
|
||||
@@ -221,18 +116,12 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr;
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
|
||||
|
||||
char iface[16 /*IF_NAMESIZE*/ + 1];
|
||||
if (getDefaultRoute(iface))
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results)
|
||||
ip->defaultRoute = ffStrbufEqualS(&ip->name, iface);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,12 @@
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "localip.h"
|
||||
|
||||
static void setDefaultRoute(FFlist* ips)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
return;
|
||||
|
||||
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
|
||||
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
|
||||
{
|
||||
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
|
||||
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
|
||||
{
|
||||
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *ips)
|
||||
{
|
||||
if (ip->ifIndex == ipForwardRow->dwForwardIfIndex)
|
||||
{
|
||||
ip->defaultRoute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, uint32_t ifIndex)
|
||||
static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, bool defaultRoute)
|
||||
{
|
||||
FFLocalIpResult* ip = NULL;
|
||||
|
||||
@@ -44,8 +17,7 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type
|
||||
ffStrbufInit(&ip->ipv4);
|
||||
ffStrbufInit(&ip->ipv6);
|
||||
ffStrbufInit(&ip->mac);
|
||||
ip->defaultRoute = false;
|
||||
ip->ifIndex = ifIndex;
|
||||
ip->defaultRoute = defaultRoute;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -70,14 +42,16 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL;
|
||||
|
||||
// Start with a 16 KB buffer and resize if needed -
|
||||
// multiple attempts in case interfaces change while
|
||||
// Multiple attempts in case interfaces change while
|
||||
// we are in the middle of querying them.
|
||||
DWORD adapter_addresses_buffer_size = 16 * 1024;
|
||||
for (int attempts = 0; attempts != 3; ++attempts)
|
||||
DWORD adapter_addresses_buffer_size = 0;
|
||||
for (int attempts = 0;; ++attempts)
|
||||
{
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size);
|
||||
assert(adapter_addresses);
|
||||
if (adapter_addresses_buffer_size)
|
||||
{
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size);
|
||||
assert(adapter_addresses);
|
||||
}
|
||||
|
||||
DWORD error = GetAdaptersAddresses(
|
||||
options->showType & FF_LOCALIP_TYPE_IPV4_BIT
|
||||
@@ -90,15 +64,21 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
|
||||
if (error == ERROR_SUCCESS)
|
||||
break;
|
||||
else if (ERROR_BUFFER_OVERFLOW == error)
|
||||
else if (ERROR_BUFFER_OVERFLOW == error && attempts < 4)
|
||||
continue;
|
||||
else
|
||||
return "GetAdaptersAddresses() failed";
|
||||
}
|
||||
|
||||
uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex();
|
||||
|
||||
// Iterate through all of the adapters
|
||||
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex;
|
||||
if (options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
bool isLoop = adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK;
|
||||
if (isLoop && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT))
|
||||
continue;
|
||||
@@ -116,7 +96,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
uint8_t* ptr = adapter->PhysicalAddress;
|
||||
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
|
||||
addNewIp(results, name, addressBuffer, -1, newIp, adapter->IfIndex);
|
||||
addNewIp(results, name, addressBuffer, -1, newIp, isDefaultRoute);
|
||||
newIp = false;
|
||||
}
|
||||
|
||||
@@ -127,7 +107,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
|
||||
addNewIp(results, name, addressBuffer, AF_INET, newIp, adapter->IfIndex);
|
||||
addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute);
|
||||
newIp = false;
|
||||
}
|
||||
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
|
||||
@@ -135,13 +115,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
addNewIp(results, name, addressBuffer, AF_INET6, newIp, adapter->IfIndex);
|
||||
addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute);
|
||||
newIp = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDefaultRoute(results);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
{
|
||||
uint64_t length = sizeof(ram->bytesTotal);
|
||||
size_t length = sizeof(ram->bytesTotal);
|
||||
if (sysctl((int[]){ CTL_HW, HW_PHYSMEM }, 2, &ram->bytesTotal, &length, NULL, 0))
|
||||
return "Failed to read hw.physmem";
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "common/io/io.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -30,15 +29,9 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/edid");
|
||||
|
||||
struct stat fileStat;
|
||||
if (stat(drmDir.chars, &fileStat) < 0 || fileStat.st_size == 0 || fileStat.st_size % 128 != 0)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_AUTO_FREE uint8_t* edidData = malloc((size_t) fileStat.st_size);
|
||||
if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) != sizeof(edidData))
|
||||
uint8_t edidData[512];
|
||||
ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData);
|
||||
if(edidLength <= 0 || edidLength % 128 != 0)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
@@ -54,7 +47,7 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
ffStrbufInit(&display->name);
|
||||
ffEdidGetName(edidData, &display->name);
|
||||
ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight);
|
||||
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) fileStat.st_size);
|
||||
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "netio.h"
|
||||
|
||||
#include "common/time.h"
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options);
|
||||
|
||||
static FFlist ioCounters1;
|
||||
static uint64_t time1;
|
||||
|
||||
void ffPrepareNetIO(FFNetIOOptions* options)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
ffNetIOGetIoCounters(&ioCounters1, options);
|
||||
time1 = ffTimeGetNow();
|
||||
}
|
||||
|
||||
const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
const char* error = NULL;
|
||||
if (time1 == 0)
|
||||
{
|
||||
ffListInit(&ioCounters1, sizeof(FFNetIOResult));
|
||||
error = ffNetIOGetIoCounters(&ioCounters1, options);
|
||||
if (error)
|
||||
return error;
|
||||
time1 = ffTimeGetNow();
|
||||
}
|
||||
|
||||
if (ioCounters1.length == 0)
|
||||
return "No network interfaces found";
|
||||
|
||||
uint64_t time2 = ffTimeGetNow();
|
||||
while (time2 - time1 < 1000)
|
||||
{
|
||||
ffTimeSleep((uint32_t) (1000 - (time2 - time1)));
|
||||
time2 = ffTimeGetNow();
|
||||
}
|
||||
|
||||
error = ffNetIOGetIoCounters(result, options);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (result->length != ioCounters1.length)
|
||||
return "Different number of network interfaces. Network change?";
|
||||
|
||||
for (uint32_t i = 0; i < result->length; ++i)
|
||||
{
|
||||
FFNetIOResult* icPrev = (FFNetIOResult*)ffListGet(&ioCounters1, i);
|
||||
FFNetIOResult* icCurr = (FFNetIOResult*)ffListGet(result, i);
|
||||
if (!ffStrbufEqual(&icPrev->name, &icCurr->name))
|
||||
return "Network interface name changed";
|
||||
|
||||
static_assert(sizeof(FFNetIOResult) - offsetof(FFNetIOResult, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetIOResult layout");
|
||||
for (size_t off = offsetof(FFNetIOResult, txBytes); off < sizeof(FFNetIOResult); off += sizeof(uint64_t))
|
||||
{
|
||||
uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
|
||||
uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
|
||||
uint64_t temp = *currValue;
|
||||
*currValue -= *prevValue;
|
||||
*currValue /= (time2 - time1) / 1000 /* seconds */;
|
||||
*prevValue = temp;
|
||||
}
|
||||
}
|
||||
time1 = time2;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFNetIOResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
bool defaultRoute;
|
||||
uint64_t txBytes;
|
||||
uint64_t rxBytes;
|
||||
uint64_t txPackets;
|
||||
uint64_t rxPackets;
|
||||
uint64_t rxErrors;
|
||||
uint64_t txErrors;
|
||||
uint64_t rxDrops;
|
||||
uint64_t txDrops;
|
||||
} FFNetIOResult;
|
||||
|
||||
const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options);
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "netio.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex();
|
||||
|
||||
size_t bufSize = 0;
|
||||
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, NULL, &bufSize, 0, 0) < 0)
|
||||
return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, ifIndex }, 6, NULL, &bufSize, 0, 0) failed";
|
||||
|
||||
FF_AUTO_FREE struct if_msghdr* buf = (struct if_msghdr*) malloc(bufSize);
|
||||
if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, buf, &bufSize, 0, 0) < 0)
|
||||
return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, ifIndex }, 6, buf, &bufSize, 0, 0) failed";
|
||||
|
||||
for (struct if_msghdr* ifm = buf;
|
||||
ifm < (struct if_msghdr*) ((uint8_t*) buf + bufSize);
|
||||
ifm = (struct if_msghdr*) ((uint8_t*) ifm + ifm->ifm_msglen))
|
||||
{
|
||||
if (ifm->ifm_type != RTM_IFINFO || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue;
|
||||
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1);
|
||||
assert(sdl->sdl_family == AF_LINK);
|
||||
if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue;
|
||||
|
||||
sdl->sdl_data[sdl->sdl_nlen] = 0;
|
||||
|
||||
if (options->namePrefix.length && strncmp(sdl->sdl_data, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
|
||||
*counters = (FFNetIOResult) {
|
||||
.name = ffStrbufCreateNS(sdl->sdl_nlen, sdl->sdl_data),
|
||||
.txBytes = ifm->ifm_data.ifi_obytes,
|
||||
.rxBytes = ifm->ifm_data.ifi_ibytes,
|
||||
.txPackets = ifm->ifm_data.ifi_opackets,
|
||||
.rxPackets = ifm->ifm_data.ifi_ipackets,
|
||||
.txErrors = ifm->ifm_data.ifi_oerrors,
|
||||
.rxErrors = ifm->ifm_data.ifi_ierrors,
|
||||
.txDrops = 0, // unsupported
|
||||
.rxDrops = ifm->ifm_data.ifi_iqdrops,
|
||||
.defaultRoute = sdl->sdl_index == defaultRouteIfIndex,
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "netio.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, FFstrbuf* path, FFlist* result)
|
||||
{
|
||||
ffStrbufSetF(path, "/sys/class/net/%s/operstate", ifName);
|
||||
if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up"))
|
||||
return;
|
||||
|
||||
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&counters->name, ifName);
|
||||
counters->defaultRoute = isDefaultRoute;
|
||||
|
||||
ffStrbufSetF(path, "/sys/class/net/%s/statistics/", ifName);
|
||||
uint32_t statLen = path->length;
|
||||
|
||||
ffStrbufAppendS(path, "rx_bytes");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->rxBytes = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_bytes");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->txBytes = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_packets");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->rxPackets = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_packets");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->txPackets = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_errors");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->rxErrors = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_errors");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->txErrors = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_dropped");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->rxDrops = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_dropped");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
counters->txDrops = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
}
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net");
|
||||
if (!dirp) return "opendir(\"/sys/class/net\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
|
||||
|
||||
if (options->defaultRouteOnly)
|
||||
{
|
||||
if (options->namePrefix.length && strncmp(defaultRouteIfName, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
return NULL;
|
||||
|
||||
getData(&buffer, defaultRouteIfName, true, &path, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
const char* ifName = entry->d_name;
|
||||
if(ifName[0] == '.')
|
||||
continue;
|
||||
|
||||
if (options->namePrefix.length && strncmp(ifName, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), &path, result);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "netio.h"
|
||||
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL;
|
||||
|
||||
// Multiple attempts in case interfaces change while
|
||||
// we are in the middle of querying them.
|
||||
DWORD adapter_addresses_buffer_size = 0;
|
||||
for (int attempts = 0;; ++attempts)
|
||||
{
|
||||
if (adapter_addresses_buffer_size)
|
||||
{
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size);
|
||||
assert(adapter_addresses);
|
||||
}
|
||||
|
||||
DWORD error = GetAdaptersAddresses(
|
||||
AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
|
||||
NULL,
|
||||
adapter_addresses,
|
||||
&adapter_addresses_buffer_size);
|
||||
|
||||
if (error == ERROR_SUCCESS)
|
||||
break;
|
||||
else if (ERROR_BUFFER_OVERFLOW == error && attempts < 4)
|
||||
continue;
|
||||
else
|
||||
return "GetAdaptersAddresses() failed";
|
||||
}
|
||||
|
||||
uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex();
|
||||
|
||||
// Iterate through all of the adapters
|
||||
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
|
||||
{
|
||||
bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex;
|
||||
if (options->defaultRouteOnly && !isDefaultRoute)
|
||||
continue;
|
||||
|
||||
char name[128];
|
||||
WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL);
|
||||
if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex };
|
||||
if (GetIfEntry2(&ifRow) == NO_ERROR)
|
||||
{
|
||||
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
|
||||
*counters = (FFNetIOResult) {
|
||||
.name = ffStrbufCreateS(name),
|
||||
.txBytes = ifRow.OutOctets,
|
||||
.rxBytes = ifRow.InOctets,
|
||||
.txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts),
|
||||
.rxPackets = (ifRow.InUcastPkts + ifRow.InNUcastPkts),
|
||||
.rxErrors = ifRow.InErrors,
|
||||
.txErrors = ifRow.OutErrors,
|
||||
.rxDrops = ifRow.InDiscards,
|
||||
.txDrops = ifRow.OutDiscards,
|
||||
.defaultRoute = isDefaultRoute,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -49,14 +49,17 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
if(ffStrStartsWithIgnCase(version, "OpenCL "))
|
||||
versionPretty = version + strlen("OpenCL ");
|
||||
ffStrbufSetS(&result->version, versionPretty);
|
||||
ffStrbufTrim(&result->version, ' ');
|
||||
|
||||
ffStrbufEnsureFree(&result->device, 128);
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, result->device.allocated, result->device.chars, NULL);
|
||||
ffStrbufRecalculateLength(&result->device);
|
||||
ffStrbufTrim(&result->device, ' ');
|
||||
|
||||
ffStrbufEnsureFree(&result->vendor, 32);
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, result->vendor.allocated, result->vendor.chars, NULL);
|
||||
ffStrbufRecalculateLength(&result->vendor);
|
||||
ffStrbufTrim(&result->vendor, ' ');
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ typedef struct FFOpenGLResult
|
||||
FFstrbuf slv;
|
||||
} FFOpenGLResult;
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLResult* result);
|
||||
const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,7 +35,7 @@ static const char* cglHandlePixelFormat(FFOpenGLResult* result, CGLPixelFormatOb
|
||||
return error;
|
||||
}
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLResult* result)
|
||||
const char* ffDetectOpenGL(FF_MAYBE_UNUSED FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
{
|
||||
CGLPixelFormatObj pixelFormat;
|
||||
CGLPixelFormatAttribute attrs[] = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user